<commit_before>// Copyright (c) 2018 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_GRAPHENE_H
#define BITCOIN_GRAPHENE_H

#include "bloom.h"
#include "config.h"
#include "consensus/validation.h"
#include "graphene_set.h"
#include "iblt.h"
#include "primitives/block.h"
#include "protocol.h"
#include "serialize.h"
#include "stat.h"
#include "sync.h"
#include "uint256.h"
#include "unlimited.h"

#include <atomic>
#include <vector>

const unsigned char MIN_MEMPOOL_INFO_BYTES = 8;
const uint64_t EXCESSIVE_BLOCK_TXS = excessiveBlockSize / 100;

class CDataStream;
class CNode;

class CMemPoolInfo
{
public:
    uint64_t nTx;

public:
    CMemPoolInfo(uint64_t nTx);
    CMemPoolInfo();

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream &s, Operation ser_action)
    {
        READWRITE(nTx);
    }
};

class CGrapheneBlock
{
public:
    CBlockHeader header;
    std::vector<uint256> vTxHashes; // List of all transactions id's in the block
    std::vector<CTransactionRef> vAdditionalTxs; // vector of transactions receiver probably does not have
    uint64_t nBlockTxs;
    CGrapheneSet *pGrapheneSet;

public:
    CGrapheneBlock(const CBlockRef pblock, uint64_t nReceiverMemPoolTx);
    CGrapheneBlock() : pGrapheneSet(nullptr) {}
    ~CGrapheneBlock();
    /**
     * Handle an incoming Graphene block
     * Once the block is validated apart from the Merkle root, forward the Xpedited block with a hop count of nHops.
     * @param[in]  vRecv        The raw binary message
     * @param[in]  pFrom        The node the message was from
     * @param[in]  strCommand   The message kind
     * @param[in]  nHops        On the wire, nHops is zero for an incoming Graphene block
     * @return True if handling succeeded
     */
    static bool HandleMessage(CDataStream &vRecv, CNode *pfrom, std::string strCommand, unsigned nHops);

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream &s, Operation ser_action)
    {
        READWRITE(header);
        READWRITE(vAdditionalTxs);
        READWRITE(nBlockTxs);
        if (nBlockTxs > EXCESSIVE_BLOCK_TXS)
            throw std::runtime_error("nBlockTxs exceeds threshold for excessive block txs");
        if (!pGrapheneSet)
            pGrapheneSet = new CGrapheneSet();
        READWRITE(*pGrapheneSet);
    }
    uint64_t GetAdditionalTxSerializationSize()
    {
        return ::GetSerializeSize(vAdditionalTxs, SER_NETWORK, PROTOCOL_VERSION);
    }
    CInv GetInv() { return CInv(MSG_BLOCK, header.GetHash()); }
    bool process(CNode *pfrom, int nSizeGrapheneBlock, std::string strCommand);
    bool CheckBlockHeader(const CBlockHeader &block, CValidationState &state);
};

// This class is used to respond to requests for missing transactions after sending an Graphene block.
// It is filled with the requested transactions in order.
class CGrapheneBlockTx
{
public:
    /** Public only for unit testing */
    uint256 blockhash;
    std::vector<CTransaction> vMissingTx; // map of missing transactions

public:
    CGrapheneBlockTx(uint256 blockHash, std::vector<CTransaction> &vTx);
    CGrapheneBlockTx() {}
    /**
     * Handle receiving a list of missing graphene block transactions from a prior request<commit_msg>graphene: excessiveBlockSize can change during execution<commit_after>// Copyright (c) 2018 The Bitcoin Unlimited developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_GRAPHENE_H
#define BITCOIN_GRAPHENE_H

#include "bloom.h"
#include "config.h"
#include "consensus/validation.h"
#include "graphene_set.h"
#include "iblt.h"
#include "primitives/block.h"
#include "protocol.h"
#include "serialize.h"
#include "stat.h"
#include "sync.h"
#include "uint256.h"
#include "unlimited.h"

#include <atomic>
#include <vector>

const unsigned char MIN_MEMPOOL_INFO_BYTES = 8;

class CDataStream;
class CNode;

class CMemPoolInfo
{
public:
    uint64_t nTx;

public:
    CMemPoolInfo(uint64_t nTx);
    CMemPoolInfo();

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream &s, Operation ser_action)
    {
        READWRITE(nTx);
    }
};

class CGrapheneBlock
{
public:
    CBlockHeader header;
    std::vector<uint256> vTxHashes; // List of all transactions id's in the block
    std::vector<CTransactionRef> vAdditionalTxs; // vector of transactions receiver probably does not have
    uint64_t nBlockTxs;
    CGrapheneSet *pGrapheneSet;

public:
    CGrapheneBlock(const CBlockRef pblock, uint64_t nReceiverMemPoolTx);
    CGrapheneBlock() : pGrapheneSet(nullptr) {}
    ~CGrapheneBlock();
    /**
     * Handle an incoming Graphene block
     * Once the block is validated apart from the Merkle root, forward the Xpedited block with a hop count of nHops.
     * @param[in]  vRecv        The raw binary message
     * @param[in]  pFrom        The node the message was from
     * @param[in]  strCommand   The message kind
     * @param[in]  nHops        On the wire, nHops is zero for an incoming Graphene block
     * @return True if handling succeeded
     */
    static bool HandleMessage(CDataStream &vRecv, CNode *pfrom, std::string strCommand, unsigned nHops);

    ADD_SERIALIZE_METHODS;

    template <typename Stream, typename Operation>
    inline void SerializationOp(Stream &s, Operation ser_action)
    {
        READWRITE(header);
        READWRITE(vAdditionalTxs);
        READWRITE(nBlockTxs);
        // This logic assumes a smallest transaction size of 100 bytes.  This is optimistic for realistic transactions
        // and the downside for pathological blocks is just that graphene won't work so we fall back to xthin
        if (nBlockTxs > excessiveBlockSize / 100)
            throw std::runtime_error("nBlockTxs exceeds threshold for excessive block txs");
        if (!pGrapheneSet)
            pGrapheneSet = new CGrapheneSet();
        READWRITE(*pGrapheneSet);
    }
    uint64_t GetAdditionalTxSerializationSize()
    {
        return ::GetSerializeSize(vAdditionalTxs, SER_NETWORK, PROTOCOL_VERSION);
    }
    CInv GetInv() { return CInv(MSG_BLOCK, header.GetHash()); }
    bool process(CNode *pfrom, int nSizeGrapheneBlock, std::string strCommand);
    bool CheckBlockHeader(const CBlockHeader &block, CValidationState &state);
};

// This class is used to respond to requests for missing transactions after sending an Graphene block.
// It is filled with the requested transactions in order.
class CGrapheneBlockTx
{
public:
    /** Public only for unit testing */
    uint256 blockhash;
    std::vector<CTransaction> vMissingTx; // map of missing transactions

public:
    CGrapheneBlockTx(uint256 blockHash, std::vector<CTransaction> &vTx);
    CGrapheneBlockTx() {}
    /**
     * Handle receiving a list of missing graphene block transactions from a prior request
{'fraction_non_alphanumeric': 0.08602301431378052, 'fraction_numerical': 0.009121526803255684, 'mean_word_length': 3.7608550434201735, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5850517', 'n_tokens_mistral': 2311, 'n_tokens_neox': 2160, 'n_words': 664}