|
|
|
@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
|
|
|
|
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
|
|
|
|
// Copyright (c) 2009-2014 The Bitcoin developers
|
|
|
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
|
|
|
// Distributed under the MIT software license, see the accompanying
|
|
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
|
|
|
|
|
|
#ifndef BITCOIN_MAIN_H |
|
|
|
@ -60,7 +60,7 @@ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000;
@@ -60,7 +60,7 @@ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000;
|
|
|
|
|
static const unsigned int MAX_STANDARD_TX_SIZE = 100000; |
|
|
|
|
/** The maximum allowed number of signature check operations in a block (network rule) */ |
|
|
|
|
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; |
|
|
|
|
/** Maxiumum number of signature check operations in an IsStandard() P2SH script */ |
|
|
|
|
/** Maximum number of signature check operations in an IsStandard() P2SH script */ |
|
|
|
|
static const unsigned int MAX_P2SH_SIGOPS = 15; |
|
|
|
|
/** The maximum number of sigops we're willing to relay/mine in a single tx */ |
|
|
|
|
static const unsigned int MAX_TX_SIGOPS = MAX_BLOCK_SIGOPS/5; |
|
|
|
@ -97,7 +97,7 @@ static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
@@ -97,7 +97,7 @@ static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
|
|
|
|
|
/** Time to wait (in seconds) between writing blockchain state to disk. */ |
|
|
|
|
static const unsigned int DATABASE_WRITE_INTERVAL = 3600; |
|
|
|
|
|
|
|
|
|
/** "reject" message codes **/ |
|
|
|
|
/** "reject" message codes */ |
|
|
|
|
static const unsigned char REJECT_MALFORMED = 0x01; |
|
|
|
|
static const unsigned char REJECT_INVALID = 0x10; |
|
|
|
|
static const unsigned char REJECT_OBSOLETE = 0x11; |
|
|
|
@ -131,10 +131,10 @@ extern bool fIsBareMultisigStd;
@@ -131,10 +131,10 @@ extern bool fIsBareMultisigStd;
|
|
|
|
|
extern unsigned int nCoinCacheSize; |
|
|
|
|
extern CFeeRate minRelayTxFee; |
|
|
|
|
|
|
|
|
|
// Best header we've seen so far (used for getheaders queries' starting points).
|
|
|
|
|
/** Best header we've seen so far (used for getheaders queries' starting points). */ |
|
|
|
|
extern CBlockIndex *pindexBestHeader; |
|
|
|
|
|
|
|
|
|
// Minimum disk space required - used in CheckDiskSpace()
|
|
|
|
|
/** Minimum disk space required - used in CheckDiskSpace() */ |
|
|
|
|
static const uint64_t nMinDiskSpace = 52428800; |
|
|
|
|
|
|
|
|
|
/** Register a wallet to receive updates from core */ |
|
|
|
@ -151,15 +151,17 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals);
@@ -151,15 +151,17 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals);
|
|
|
|
|
/** Unregister a network node */ |
|
|
|
|
void UnregisterNodeSignals(CNodeSignals& nodeSignals); |
|
|
|
|
|
|
|
|
|
/** Process an incoming block. This only returns after the best known valid
|
|
|
|
|
block is made active. Note that it does not, however, guarantee that the |
|
|
|
|
specific block passed to it has been checked for validity! |
|
|
|
|
@param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state iff pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation. |
|
|
|
|
@param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid. |
|
|
|
|
@param[in] pblock The block we want to process. |
|
|
|
|
@param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. |
|
|
|
|
@return True if state.IsValid() |
|
|
|
|
*/ |
|
|
|
|
/**
|
|
|
|
|
* Process an incoming block. This only returns after the best known valid |
|
|
|
|
* block is made active. Note that it does not, however, guarantee that the |
|
|
|
|
* specific block passed to it has been checked for validity! |
|
|
|
|
* |
|
|
|
|
* @param[out] state This may be set to an Error state if any error occurred processing it, including during validation/connection/etc of otherwise unrelated blocks during reorganisation; or it may be set to an Invalid state if pblock is itself invalid (but this is not guaranteed even when the block is checked). If you want to *possibly* get feedback on whether pblock is valid, you must also install a CValidationInterface - this will have its BlockChecked method called whenever *any* block completes validation. |
|
|
|
|
* @param[in] pfrom The node which we are receiving the block from; it is added to mapBlockSource and may be penalised if the block is invalid. |
|
|
|
|
* @param[in] pblock The block we want to process. |
|
|
|
|
* @param[out] dbp If pblock is stored to disk (or already there), this will be set to its location. |
|
|
|
|
* @return True if state.IsValid() |
|
|
|
|
*/ |
|
|
|
|
bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL); |
|
|
|
|
/** Check whether enough disk space is available for an incoming block */ |
|
|
|
|
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); |
|
|
|
@ -245,54 +247,59 @@ struct CDiskTxPos : public CDiskBlockPos
@@ -245,54 +247,59 @@ struct CDiskTxPos : public CDiskBlockPos
|
|
|
|
|
|
|
|
|
|
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); |
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Check transaction inputs, and make sure any
|
|
|
|
|
// pay-to-script-hash transactions are evaluating IsStandard scripts
|
|
|
|
|
//
|
|
|
|
|
// Why bother? To avoid denial-of-service attacks; an attacker
|
|
|
|
|
// can submit a standard HASH... OP_EQUAL transaction,
|
|
|
|
|
// which will get accepted into blocks. The redemption
|
|
|
|
|
// script can be anything; an attacker could use a very
|
|
|
|
|
// expensive-to-check-upon-redemption script like:
|
|
|
|
|
// DUP CHECKSIG DROP ... repeated 100 times... OP_1
|
|
|
|
|
//
|
|
|
|
|
/**
|
|
|
|
|
* Check transaction inputs, and make sure any |
|
|
|
|
* pay-to-script-hash transactions are evaluating IsStandard scripts |
|
|
|
|
* |
|
|
|
|
* Why bother? To avoid denial-of-service attacks; an attacker |
|
|
|
|
* can submit a standard HASH... OP_EQUAL transaction, |
|
|
|
|
* which will get accepted into blocks. The redemption |
|
|
|
|
* script can be anything; an attacker could use a very |
|
|
|
|
* expensive-to-check-upon-redemption script like: |
|
|
|
|
* DUP CHECKSIG DROP ... repeated 100 times... OP_1 |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
/** Check for standard transaction types
|
|
|
|
|
@param[in] mapInputs Map of previous transactions that have outputs we're spending |
|
|
|
|
@return True if all inputs (scriptSigs) use only standard transaction forms |
|
|
|
|
*/ |
|
|
|
|
/**
|
|
|
|
|
* Check for standard transaction types |
|
|
|
|
* @param[in] mapInputs Map of previous transactions that have outputs we're spending |
|
|
|
|
* @return True if all inputs (scriptSigs) use only standard transaction forms |
|
|
|
|
*/ |
|
|
|
|
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs); |
|
|
|
|
|
|
|
|
|
/** Count ECDSA signature operations the old-fashioned (pre-0.6) way
|
|
|
|
|
@return number of sigops this transaction's outputs will produce when spent |
|
|
|
|
@see CTransaction::FetchInputs |
|
|
|
|
*/ |
|
|
|
|
/**
|
|
|
|
|
* Count ECDSA signature operations the old-fashioned (pre-0.6) way |
|
|
|
|
* @return number of sigops this transaction's outputs will produce when spent |
|
|
|
|
* @see CTransaction::FetchInputs |
|
|
|
|
*/ |
|
|
|
|
unsigned int GetLegacySigOpCount(const CTransaction& tx); |
|
|
|
|
|
|
|
|
|
/** Count ECDSA signature operations in pay-to-script-hash inputs.
|
|
|
|
|
|
|
|
|
|
@param[in] mapInputs Map of previous transactions that have outputs we're spending |
|
|
|
|
@return maximum number of sigops required to validate this transaction's inputs |
|
|
|
|
@see CTransaction::FetchInputs |
|
|
|
|
/**
|
|
|
|
|
* Count ECDSA signature operations in pay-to-script-hash inputs. |
|
|
|
|
* |
|
|
|
|
* @param[in] mapInputs Map of previous transactions that have outputs we're spending |
|
|
|
|
* @return maximum number of sigops required to validate this transaction's inputs |
|
|
|
|
* @see CTransaction::FetchInputs |
|
|
|
|
*/ |
|
|
|
|
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
|
|
|
|
|
// This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it
|
|
|
|
|
// instead of being performed inline.
|
|
|
|
|
/**
|
|
|
|
|
* Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts) |
|
|
|
|
* This does not modify the UTXO set. If pvChecks is not NULL, script checks are pushed onto it |
|
|
|
|
* instead of being performed inline. |
|
|
|
|
*/ |
|
|
|
|
bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks, |
|
|
|
|
unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks = NULL); |
|
|
|
|
|
|
|
|
|
// Apply the effects of this transaction on the UTXO set represented by view
|
|
|
|
|
/** Apply the effects of this transaction on the UTXO set represented by view */ |
|
|
|
|
void UpdateCoins(const CTransaction& tx, CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight); |
|
|
|
|
|
|
|
|
|
// Context-independent validity checks
|
|
|
|
|
/** Context-independent validity checks */ |
|
|
|
|
bool CheckTransaction(const CTransaction& tx, CValidationState& state); |
|
|
|
|
|
|
|
|
|
/** Check for standard transaction types
|
|
|
|
|
@return True if all outputs (scriptPubKeys) use only standard transaction forms |
|
|
|
|
*/ |
|
|
|
|
* @return True if all outputs (scriptPubKeys) use only standard transaction forms |
|
|
|
|
*/ |
|
|
|
|
bool IsStandardTx(const CTransaction& tx, std::string& reason); |
|
|
|
|
|
|
|
|
|
bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64_t nBlockTime = 0); |
|
|
|
@ -315,8 +322,10 @@ public:
@@ -315,8 +322,10 @@ public:
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Closure representing one script verification
|
|
|
|
|
* Note that this stores references to the spending transaction */ |
|
|
|
|
/**
|
|
|
|
|
* Closure representing one script verification |
|
|
|
|
* Note that this stores references to the spending transaction |
|
|
|
|
*/ |
|
|
|
|
class CScriptCheck |
|
|
|
|
{ |
|
|
|
|
private: |
|
|
|
@ -345,7 +354,7 @@ public:
@@ -345,7 +354,7 @@ public:
|
|
|
|
|
|
|
|
|
|
/** Data structure that represents a partial merkle tree.
|
|
|
|
|
* |
|
|
|
|
* It respresents a subset of the txid's of a known block, in a way that |
|
|
|
|
* It represents a subset of the txid's of a known block, in a way that |
|
|
|
|
* allows recovery of the list of txid's and the merkle root, in an |
|
|
|
|
* authenticated way. |
|
|
|
|
* |
|
|
|
@ -380,36 +389,38 @@ public:
@@ -380,36 +389,38 @@ public:
|
|
|
|
|
class CPartialMerkleTree |
|
|
|
|
{ |
|
|
|
|
protected: |
|
|
|
|
// the total number of transactions in the block
|
|
|
|
|
/** the total number of transactions in the block */ |
|
|
|
|
unsigned int nTransactions; |
|
|
|
|
|
|
|
|
|
// node-is-parent-of-matched-txid bits
|
|
|
|
|
/** node-is-parent-of-matched-txid bits */ |
|
|
|
|
std::vector<bool> vBits; |
|
|
|
|
|
|
|
|
|
// txids and internal hashes
|
|
|
|
|
/** txids and internal hashes */ |
|
|
|
|
std::vector<uint256> vHash; |
|
|
|
|
|
|
|
|
|
// flag set when encountering invalid data
|
|
|
|
|
/** flag set when encountering invalid data */ |
|
|
|
|
bool fBad; |
|
|
|
|
|
|
|
|
|
// helper function to efficiently calculate the number of nodes at given height in the merkle tree
|
|
|
|
|
/** helper function to efficiently calculate the number of nodes at given height in the merkle tree */ |
|
|
|
|
unsigned int CalcTreeWidth(int height) { |
|
|
|
|
return (nTransactions+(1 << height)-1) >> height; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// calculate the hash of a node in the merkle tree (at leaf level: the txid's themself)
|
|
|
|
|
/** calculate the hash of a node in the merkle tree (at leaf level: the txid's themselves) */ |
|
|
|
|
uint256 CalcHash(int height, unsigned int pos, const std::vector<uint256> &vTxid); |
|
|
|
|
|
|
|
|
|
// recursive function that traverses tree nodes, storing the data as bits and hashes
|
|
|
|
|
/** recursive function that traverses tree nodes, storing the data as bits and hashes */ |
|
|
|
|
void TraverseAndBuild(int height, unsigned int pos, const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch); |
|
|
|
|
|
|
|
|
|
// recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild.
|
|
|
|
|
// it returns the hash of the respective node.
|
|
|
|
|
/**
|
|
|
|
|
* recursive function that traverses tree nodes, consuming the bits and hashes produced by TraverseAndBuild. |
|
|
|
|
* it returns the hash of the respective node. |
|
|
|
|
*/ |
|
|
|
|
uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch); |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
// serialization implementation
|
|
|
|
|
/** serialization implementation */ |
|
|
|
|
ADD_SERIALIZE_METHODS; |
|
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation> |
|
|
|
@ -432,13 +443,15 @@ public:
@@ -432,13 +443,15 @@ public:
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them
|
|
|
|
|
/** Construct a partial merkle tree from a list of transaction id's, and a mask that selects a subset of them */ |
|
|
|
|
CPartialMerkleTree(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch); |
|
|
|
|
|
|
|
|
|
CPartialMerkleTree(); |
|
|
|
|
|
|
|
|
|
// extract the matching txid's represented by this partial merkle tree.
|
|
|
|
|
// returns the merkle root, or 0 in case of failure
|
|
|
|
|
/**
|
|
|
|
|
* extract the matching txid's represented by this partial merkle tree. |
|
|
|
|
* returns the merkle root, or 0 in case of failure |
|
|
|
|
*/ |
|
|
|
|
uint256 ExtractMatches(std::vector<uint256> &vMatch); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -458,22 +471,21 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
@@ -458,22 +471,21 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
|
|
|
|
|
* of problems. Note that in any case, coins may be modified. */ |
|
|
|
|
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL); |
|
|
|
|
|
|
|
|
|
// Apply the effects of this block (with given index) on the UTXO set represented by coins
|
|
|
|
|
/** Apply the effects of this block (with given index) on the UTXO set represented by coins */ |
|
|
|
|
bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); |
|
|
|
|
|
|
|
|
|
// Context-independent validity checks
|
|
|
|
|
/** Context-independent validity checks */ |
|
|
|
|
bool CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true); |
|
|
|
|
bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = true); |
|
|
|
|
|
|
|
|
|
// Context-dependent validity checks
|
|
|
|
|
/** Context-dependent validity checks */ |
|
|
|
|
bool ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev); |
|
|
|
|
bool ContextualCheckBlock(const CBlock& block, CValidationState& state, CBlockIndex *pindexPrev); |
|
|
|
|
|
|
|
|
|
// Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held)
|
|
|
|
|
/** Check a block is completely valid from start to finish (only works on top of our current best block, with cs_main held) */ |
|
|
|
|
bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex *pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true); |
|
|
|
|
|
|
|
|
|
// Store block on disk
|
|
|
|
|
// if dbp is provided, the file is known to already reside on disk
|
|
|
|
|
/** Store block on disk. If dbp is provided, the file is known to already reside on disk */ |
|
|
|
|
bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL); |
|
|
|
|
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); |
|
|
|
|
|
|
|
|
@ -482,13 +494,13 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
@@ -482,13 +494,13 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
|
|
|
|
|
class CBlockFileInfo |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
unsigned int nBlocks; // number of blocks stored in file
|
|
|
|
|
unsigned int nSize; // number of used bytes of block file
|
|
|
|
|
unsigned int nUndoSize; // number of used bytes in the undo file
|
|
|
|
|
unsigned int nHeightFirst; // lowest height of block in file
|
|
|
|
|
unsigned int nHeightLast; // highest height of block in file
|
|
|
|
|
uint64_t nTimeFirst; // earliest time of block in file
|
|
|
|
|
uint64_t nTimeLast; // latest time of block in file
|
|
|
|
|
unsigned int nBlocks; //! number of blocks stored in file
|
|
|
|
|
unsigned int nSize; //! number of used bytes of block file
|
|
|
|
|
unsigned int nUndoSize; //! number of used bytes in the undo file
|
|
|
|
|
unsigned int nHeightFirst; //! lowest height of block in file
|
|
|
|
|
unsigned int nHeightLast; //! highest height of block in file
|
|
|
|
|
uint64_t nTimeFirst; //! earliest time of block in file
|
|
|
|
|
uint64_t nTimeLast; //! latest time of block in file
|
|
|
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS; |
|
|
|
|
|
|
|
|
@ -519,7 +531,7 @@ public:
@@ -519,7 +531,7 @@ public:
|
|
|
|
|
|
|
|
|
|
std::string ToString() const; |
|
|
|
|
|
|
|
|
|
// update statistics (does not update nSize)
|
|
|
|
|
/** update statistics (does not update nSize) */ |
|
|
|
|
void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { |
|
|
|
|
if (nBlocks==0 || nHeightFirst > nHeightIn) |
|
|
|
|
nHeightFirst = nHeightIn; |
|
|
|
@ -537,9 +549,9 @@ public:
@@ -537,9 +549,9 @@ public:
|
|
|
|
|
class CValidationState { |
|
|
|
|
private: |
|
|
|
|
enum mode_state { |
|
|
|
|
MODE_VALID, // everything ok
|
|
|
|
|
MODE_INVALID, // network rule violation (DoS value may be set)
|
|
|
|
|
MODE_ERROR, // run-time error
|
|
|
|
|
MODE_VALID, //! everything ok
|
|
|
|
|
MODE_INVALID, //! network rule violation (DoS value may be set)
|
|
|
|
|
MODE_ERROR, //! run-time error
|
|
|
|
|
} mode; |
|
|
|
|
int nDoS; |
|
|
|
|
std::string strRejectReason; |
|
|
|
@ -634,24 +646,26 @@ struct CBlockTemplate
@@ -634,24 +646,26 @@ struct CBlockTemplate
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Used to relay blocks as header + vector<merkle branch>
|
|
|
|
|
/**
|
|
|
|
|
* Used to relay blocks as header + vector<merkle branch> |
|
|
|
|
* to filtered nodes. |
|
|
|
|
*/ |
|
|
|
|
class CMerkleBlock |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
// Public only for unit testing
|
|
|
|
|
/** Public only for unit testing */ |
|
|
|
|
CBlockHeader header; |
|
|
|
|
CPartialMerkleTree txn; |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
// Public only for unit testing and relay testing
|
|
|
|
|
// (not relayed)
|
|
|
|
|
/** Public only for unit testing and relay testing (not relayed) */ |
|
|
|
|
std::vector<std::pair<unsigned int, uint256> > vMatchedTxn; |
|
|
|
|
|
|
|
|
|
// Create from a CBlock, filtering transactions according to filter
|
|
|
|
|
// Note that this will call IsRelevantAndUpdate on the filter for each transaction,
|
|
|
|
|
// thus the filter will likely be modified.
|
|
|
|
|
/**
|
|
|
|
|
* Create from a CBlock, filtering transactions according to filter |
|
|
|
|
* Note that this will call IsRelevantAndUpdate on the filter for each transaction, |
|
|
|
|
* thus the filter will likely be modified. |
|
|
|
|
*/ |
|
|
|
|
CMerkleBlock(const CBlock& block, CBloomFilter& filter); |
|
|
|
|
|
|
|
|
|
ADD_SERIALIZE_METHODS; |
|
|
|
|