diff options
Diffstat (limited to 'src/main.h')
-rw-r--r-- | src/main.h | 299 |
1 files changed, 98 insertions, 201 deletions
diff --git a/src/main.h b/src/main.h index 1bb0919817..8f0378647d 100644 --- a/src/main.h +++ b/src/main.h @@ -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 @@ -14,8 +14,8 @@ #include "chain.h" #include "chainparams.h" #include "coins.h" -#include "core/block.h" -#include "core/transaction.h" +#include "primitives/block.h" +#include "primitives/transaction.h" #include "net.h" #include "pow.h" #include "script/script.h" @@ -49,8 +49,6 @@ class CValidationState; struct CBlockTemplate; struct CNodeStateStats; -/** The maximum allowed size for a serialized block, in bytes (network rule) */ -static const unsigned int MAX_BLOCK_SIZE = 1000000; /** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; static const unsigned int DEFAULT_BLOCK_MIN_SIZE = 0; @@ -60,7 +58,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; @@ -94,8 +92,12 @@ static const unsigned int MAX_HEADERS_RESULTS = 2000; * degree of disordering of blocks on disk (which make reindexing and in the future perhaps pruning * harder). We'll probably want to make this a per-peer adaptive value at some point. */ 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; +/** Maximum length of reject messages. */ +static const unsigned int MAX_REJECT_MESSAGE_LENGTH = 111; -/** "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; @@ -129,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 */ @@ -149,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); @@ -175,8 +179,6 @@ bool InitBlockIndex(); bool LoadBlockIndex(); /** Unload database information */ void UnloadBlockIndex(); -/** Print the loaded block tree */ -void PrintBlockTree(); /** Process protocol messages received from a given node */ bool ProcessMessages(CNode* pfrom); /** Send queued protocol messages to be sent to a give node */ @@ -201,6 +203,8 @@ bool AbortNode(const std::string &msg, const std::string &userMessage=""); bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats); /** Increase a node's misbehavior score. */ void Misbehaving(NodeId nodeid, int howmuch); +/** Flush all state, indexes and buffers to disk. */ +void FlushStateToDisk(); /** (try to) add transaction to memory pool **/ @@ -243,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); @@ -313,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: @@ -323,14 +334,15 @@ private: unsigned int nIn; unsigned int nFlags; bool cacheStore; + ScriptError error; public: - CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false) {} + CScriptCheck(): ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {} CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn) : scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), - ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn) { } + ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR) { } - bool operator()() const; + bool operator()(); void swap(CScriptCheck &check) { scriptPubKey.swap(check.scriptPubKey); @@ -338,110 +350,13 @@ public: std::swap(nIn, check.nIn); std::swap(nFlags, check.nFlags); std::swap(cacheStore, check.cacheStore); + std::swap(error, check.error); } -}; - -/** Data structure that represents a partial merkle tree. - * - * It respresents 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. - * - * The encoding works as follows: we traverse the tree in depth-first order, - * storing a bit for each traversed node, signifying whether the node is the - * parent of at least one matched leaf txid (or a matched txid itself). In - * case we are at the leaf level, or this bit is 0, its merkle node hash is - * stored, and its children are not explorer further. Otherwise, no hash is - * stored, but we recurse into both (or the only) child branch. During - * decoding, the same depth-first traversal is performed, consuming bits and - * hashes as they written during encoding. - * - * The serialization is fixed and provides a hard guarantee about the - * encoded size: - * - * SIZE <= 10 + ceil(32.25*N) - * - * Where N represents the number of leaf nodes of the partial tree. N itself - * is bounded by: - * - * N <= total_transactions - * N <= 1 + matched_transactions*tree_height - * - * The serialization format: - * - uint32 total_transactions (4 bytes) - * - varint number of hashes (1-3 bytes) - * - uint256[] hashes in depth-first order (<= 32*N bytes) - * - varint number of bytes of flag bits (1-3 bytes) - * - byte[] flag bits, packed per 8 in a byte, least significant bit first (<= 2*N-1 bits) - * The size constraints follow from this. - */ -class CPartialMerkleTree -{ -protected: - // the total number of transactions in the block - unsigned int nTransactions; - // node-is-parent-of-matched-txid bits - std::vector<bool> vBits; - - // txids and internal hashes - std::vector<uint256> vHash; - - // flag set when encountering invalid data - bool fBad; - - // 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) - 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 - 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. - uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch); - -public: - - // serialization implementation - ADD_SERIALIZE_METHODS; - - template <typename Stream, typename Operation> - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(nTransactions); - READWRITE(vHash); - std::vector<unsigned char> vBytes; - if (ser_action.ForRead()) { - READWRITE(vBytes); - CPartialMerkleTree &us = *(const_cast<CPartialMerkleTree*>(this)); - us.vBits.resize(vBytes.size() * 8); - for (unsigned int p = 0; p < us.vBits.size(); p++) - us.vBits[p] = (vBytes[p / 8] & (1 << (p % 8))) != 0; - us.fBad = false; - } else { - vBytes.resize((vBits.size()+7)/8); - for (unsigned int p = 0; p < vBits.size(); p++) - vBytes[p / 8] |= vBits[p] << (p % 8); - READWRITE(vBytes); - } - } - - // 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 - uint256 ExtractMatches(std::vector<uint256> &vMatch); + ScriptError GetScriptError() const { return error; } }; - /** Functions for disk access for blocks */ bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos); bool ReadBlockFromDisk(CBlock& block, const CDiskBlockPos& pos); @@ -456,15 +371,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 -bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool fJustCheck = false); +/** 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); -// Store block on disk -// if dbp is provided, the file is known to already reside on disk +/** 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) */ +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 */ bool AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL); bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); @@ -473,13 +394,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; @@ -510,7 +431,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; @@ -528,9 +449,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; @@ -598,6 +519,12 @@ public: /** Find the last common block between the parameter chain and a locator. */ CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator); +/** Mark a block as invalid. */ +bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex); + +/** Remove invalidity status from a block and its descendants. */ +bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex); + /** The currently-connected chain of blocks. */ extern CChain chainActive; @@ -619,36 +546,6 @@ struct CBlockTemplate -/** Used to relay blocks as header + vector<merkle branch> - * to filtered nodes. - */ -class CMerkleBlock -{ -public: - // Public only for unit testing - CBlockHeader header; - CPartialMerkleTree txn; - -public: - // 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. - CMerkleBlock(const CBlock& block, CBloomFilter& filter); - - ADD_SERIALIZE_METHODS; - - template <typename Stream, typename Operation> - inline void SerializationOp(Stream& s, Operation ser_action, int nType, int nVersion) { - READWRITE(header); - READWRITE(txn); - } -}; - - class CValidationInterface { protected: virtual void SyncTransaction(const CTransaction &tx, const CBlock *pblock) {}; |