Merge pull request #5403

c5b390b Make comments in main an init doxygen compatible (Michael Ford)
This commit is contained in:
Wladimir J. van der Laan 2014-12-03 10:37:48 +01:00
commit 7eb0667384
No known key found for this signature in database
GPG key ID: 74810B012346C9A6
4 changed files with 189 additions and 160 deletions

View file

@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers // 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. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H) #if defined(HAVE_CONFIG_H)
@ -60,7 +60,7 @@ bool fFeeEstimatesInitialized = false;
#define MIN_CORE_FILEDESCRIPTORS 150 #define MIN_CORE_FILEDESCRIPTORS 150
#endif #endif
// Used to pass flags to the Bind() function /** Used to pass flags to the Bind() function */
enum BindFlags { enum BindFlags {
BF_NONE = 0, BF_NONE = 0,
BF_EXPLICIT = (1U << 0), BF_EXPLICIT = (1U << 0),
@ -175,9 +175,9 @@ void Shutdown()
LogPrintf("%s: done\n", __func__); LogPrintf("%s: done\n", __func__);
} }
// /**
// Signal handlers are very limited in what they are allowed to do, so: * Signal handlers are very limited in what they are allowed to do, so:
// */
void HandleSIGTERM(int) void HandleSIGTERM(int)
{ {
fRequestShutdown = true; fRequestShutdown = true;

View file

@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin developers // 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. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_INIT_H #ifndef BITCOIN_INIT_H
@ -22,7 +22,7 @@ bool ShutdownRequested();
void Shutdown(); void Shutdown();
bool AppInit2(boost::thread_group& threadGroup); bool AppInit2(boost::thread_group& threadGroup);
/* The help message mode determines what help message to show */ /** The help message mode determines what help message to show */
enum HelpMessageMode { enum HelpMessageMode {
HMM_BITCOIND, HMM_BITCOIND,
HMM_BITCOIN_QT HMM_BITCOIN_QT

View file

@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers // 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. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include "main.h" #include "main.h"
@ -33,9 +33,9 @@ using namespace std;
# error "Bitcoin cannot be compiled without assertions." # error "Bitcoin cannot be compiled without assertions."
#endif #endif
// /**
// Global state * Global state
// */
CCriticalSection cs_main; CCriticalSection cs_main;
@ -66,7 +66,7 @@ map<uint256, COrphanTx> mapOrphanTransactions;
map<uint256, set<uint256> > mapOrphanTransactionsByPrev; map<uint256, set<uint256> > mapOrphanTransactionsByPrev;
void EraseOrphansFor(NodeId peer); void EraseOrphansFor(NodeId peer);
// Constant stuff for coinbase transactions we create: /** Constant stuff for coinbase transactions we create: */
CScript COINBASE_FLAGS; CScript COINBASE_FLAGS;
const string strMessageMagic = "Bitcoin Signed Message:\n"; const string strMessageMagic = "Bitcoin Signed Message:\n";
@ -97,44 +97,49 @@ namespace {
CBlockIndex *pindexBestInvalid; CBlockIndex *pindexBestInvalid;
// The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS or better that are at least /**
// as good as our current tip. Entries may be failed, though. * The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS or better that are at least
* as good as our current tip. Entries may be failed, though.
*/
set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates; set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates;
// Number of nodes with fSyncStarted. /** Number of nodes with fSyncStarted. */
int nSyncStarted = 0; int nSyncStarted = 0;
// All pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions. /** All pairs A->B, where A (or one if its ancestors) misses transactions, but B has transactions. */
multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked; multimap<CBlockIndex*, CBlockIndex*> mapBlocksUnlinked;
CCriticalSection cs_LastBlockFile; CCriticalSection cs_LastBlockFile;
std::vector<CBlockFileInfo> vinfoBlockFile; std::vector<CBlockFileInfo> vinfoBlockFile;
int nLastBlockFile = 0; int nLastBlockFile = 0;
// Every received block is assigned a unique and increasing identifier, so we /**
// know which one to give priority in case of a fork. * Every received block is assigned a unique and increasing identifier, so we
* know which one to give priority in case of a fork.
*/
CCriticalSection cs_nBlockSequenceId; CCriticalSection cs_nBlockSequenceId;
// Blocks loaded from disk are assigned id 0, so start the counter at 1. /** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
uint32_t nBlockSequenceId = 1; uint32_t nBlockSequenceId = 1;
// Sources of received blocks, to be able to send them reject messages or ban /**
// them, if processing happens afterwards. Protected by cs_main. * Sources of received blocks, to be able to send them reject messages or ban
* them, if processing happens afterwards. Protected by cs_main.
*/
map<uint256, NodeId> mapBlockSource; map<uint256, NodeId> mapBlockSource;
// Blocks that are in flight, and that are in the queue to be downloaded. /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */
// Protected by cs_main.
struct QueuedBlock { struct QueuedBlock {
uint256 hash; uint256 hash;
CBlockIndex *pindex; // Optional. CBlockIndex *pindex; //! Optional.
int64_t nTime; // Time of "getdata" request in microseconds. int64_t nTime; //! Time of "getdata" request in microseconds.
}; };
map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight; map<uint256, pair<NodeId, list<QueuedBlock>::iterator> > mapBlocksInFlight;
// Number of preferrable block download peers. /** Number of preferable block download peers. */
int nPreferredDownload = 0; int nPreferredDownload = 0;
// Dirty block index entries. /** Dirty block index entries. */
set<CBlockIndex*> setDirtyBlockIndex; set<CBlockIndex*> setDirtyBlockIndex;
// Dirty block file entries. /** Dirty block file entries. */
set<int> setDirtyFileInfo; set<int> setDirtyFileInfo;
} // anon namespace } // anon namespace
@ -148,19 +153,19 @@ namespace {
namespace { namespace {
struct CMainSignals { struct CMainSignals {
// Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. /** Notifies listeners of updated transaction data (transaction, and optionally the block it is found in. */
boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction; boost::signals2::signal<void (const CTransaction &, const CBlock *)> SyncTransaction;
// Notifies listeners of an erased transaction (currently disabled, requires transaction replacement). /** Notifies listeners of an erased transaction (currently disabled, requires transaction replacement). */
boost::signals2::signal<void (const uint256 &)> EraseTransaction; boost::signals2::signal<void (const uint256 &)> EraseTransaction;
// Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). /** Notifies listeners of an updated transaction without new data (for now: a coinbase potentially becoming visible). */
boost::signals2::signal<void (const uint256 &)> UpdatedTransaction; boost::signals2::signal<void (const uint256 &)> UpdatedTransaction;
// Notifies listeners of a new active block chain. /** Notifies listeners of a new active block chain. */
boost::signals2::signal<void (const CBlockLocator &)> SetBestChain; boost::signals2::signal<void (const CBlockLocator &)> SetBestChain;
// Notifies listeners about an inventory item being seen on the network. /** Notifies listeners about an inventory item being seen on the network. */
boost::signals2::signal<void (const uint256 &)> Inventory; boost::signals2::signal<void (const uint256 &)> Inventory;
// Tells listeners to broadcast their data. /** Tells listeners to broadcast their data. */
boost::signals2::signal<void ()> Broadcast; boost::signals2::signal<void ()> Broadcast;
// Notifies listeners of a block validation result /** Notifies listeners of a block validation result */
boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked; boost::signals2::signal<void (const CBlock&, const CValidationState&)> BlockChecked;
} g_signals; } g_signals;
@ -213,32 +218,34 @@ struct CBlockReject {
uint256 hashBlock; uint256 hashBlock;
}; };
// Maintain validation-specific state about nodes, protected by cs_main, instead /**
// by CNode's own locks. This simplifies asynchronous operation, where * Maintain validation-specific state about nodes, protected by cs_main, instead
// processing of incoming data is done after the ProcessMessage call returns, * by CNode's own locks. This simplifies asynchronous operation, where
// and we're no longer holding the node's locks. * processing of incoming data is done after the ProcessMessage call returns,
* and we're no longer holding the node's locks.
*/
struct CNodeState { struct CNodeState {
// Accumulated misbehaviour score for this peer. //! Accumulated misbehaviour score for this peer.
int nMisbehavior; int nMisbehavior;
// Whether this peer should be disconnected and banned (unless whitelisted). //! Whether this peer should be disconnected and banned (unless whitelisted).
bool fShouldBan; bool fShouldBan;
// String name of this peer (debugging/logging purposes). //! String name of this peer (debugging/logging purposes).
std::string name; std::string name;
// List of asynchronously-determined block rejections to notify this peer about. //! List of asynchronously-determined block rejections to notify this peer about.
std::vector<CBlockReject> rejects; std::vector<CBlockReject> rejects;
// The best known block we know this peer has announced. //! The best known block we know this peer has announced.
CBlockIndex *pindexBestKnownBlock; CBlockIndex *pindexBestKnownBlock;
// The hash of the last unknown block this peer has announced. //! The hash of the last unknown block this peer has announced.
uint256 hashLastUnknownBlock; uint256 hashLastUnknownBlock;
// The last full block we both have. //! The last full block we both have.
CBlockIndex *pindexLastCommonBlock; CBlockIndex *pindexLastCommonBlock;
// Whether we've started headers synchronization with this peer. //! Whether we've started headers synchronization with this peer.
bool fSyncStarted; bool fSyncStarted;
// Since when we're stalling block download progress (in microseconds), or 0. //! Since when we're stalling block download progress (in microseconds), or 0.
int64_t nStallingSince; int64_t nStallingSince;
list<QueuedBlock> vBlocksInFlight; list<QueuedBlock> vBlocksInFlight;
int nBlocksInFlight; int nBlocksInFlight;
// Whether we consider this a preferred download peer. //! Whether we consider this a preferred download peer.
bool fPreferredDownload; bool fPreferredDownload;
CNodeState() { CNodeState() {
@ -254,7 +261,7 @@ struct CNodeState {
} }
}; };
// Map maintaining per-node state. Requires cs_main. /** Map maintaining per-node state. Requires cs_main. */
map<NodeId, CNodeState> mapNodeState; map<NodeId, CNodeState> mapNodeState;
// Requires cs_main. // Requires cs_main.
@ -708,15 +715,15 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
return true; return true;
} }
// /**
// Check transaction inputs to mitigate two * Check transaction inputs to mitigate two
// potential denial-of-service attacks: * potential denial-of-service attacks:
// *
// 1. scriptSigs with extra data stuffed into them, * 1. scriptSigs with extra data stuffed into them,
// not consumed by scriptPubKey (or P2SH script) * not consumed by scriptPubKey (or P2SH script)
// 2. P2SH scripts with a crazy number of expensive * 2. P2SH scripts with a crazy number of expensive
// CHECKSIG/CHECKMULTISIG operations * CHECKSIG/CHECKMULTISIG operations
// */
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs) bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
{ {
if (tx.IsCoinBase()) if (tx.IsCoinBase())
@ -1054,7 +1061,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
return true; return true;
} }
// Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock /** Return transaction in tx, and if it was found inside a block, its hash is placed in hashBlock */
bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow) bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock, bool fAllowSlow)
{ {
CBlockIndex *pindexSlow = NULL; CBlockIndex *pindexSlow = NULL;
@ -1818,7 +1825,7 @@ void FlushStateToDisk() {
FlushStateToDisk(state, FLUSH_STATE_ALWAYS); FlushStateToDisk(state, FLUSH_STATE_ALWAYS);
} }
// Update chainActive and related internal data structures. /** Update chainActive and related internal data structures. */
void static UpdateTip(CBlockIndex *pindexNew) { void static UpdateTip(CBlockIndex *pindexNew) {
chainActive.SetTip(pindexNew); chainActive.SetTip(pindexNew);
@ -1857,7 +1864,7 @@ void static UpdateTip(CBlockIndex *pindexNew) {
} }
} }
// Disconnect chainActive's tip. /** Disconnect chainActive's tip. */
bool static DisconnectTip(CValidationState &state) { bool static DisconnectTip(CValidationState &state) {
CBlockIndex *pindexDelete = chainActive.Tip(); CBlockIndex *pindexDelete = chainActive.Tip();
assert(pindexDelete); assert(pindexDelete);
@ -1904,8 +1911,10 @@ static int64_t nTimeFlush = 0;
static int64_t nTimeChainState = 0; static int64_t nTimeChainState = 0;
static int64_t nTimePostConnect = 0; static int64_t nTimePostConnect = 0;
// Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock /**
// corresponding to pindexNew, to bypass loading it again from disk. * Connect a new block to chainActive. pblock is either NULL or a pointer to a CBlock
* corresponding to pindexNew, to bypass loading it again from disk.
*/
bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) { bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *pblock) {
assert(pindexNew->pprev == chainActive.Tip()); assert(pindexNew->pprev == chainActive.Tip());
mempool.check(pcoinsTip); mempool.check(pcoinsTip);
@ -1965,8 +1974,10 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock *
return true; return true;
} }
// Return the tip of the chain with the most work in it, that isn't /**
// known to be invalid (it's however far from certain to be valid). * Return the tip of the chain with the most work in it, that isn't
* known to be invalid (it's however far from certain to be valid).
*/
static CBlockIndex* FindMostWorkChain() { static CBlockIndex* FindMostWorkChain() {
do { do {
CBlockIndex *pindexNew = NULL; CBlockIndex *pindexNew = NULL;
@ -2007,7 +2018,7 @@ static CBlockIndex* FindMostWorkChain() {
} while(true); } while(true);
} }
// Delete all entries in setBlockIndexCandidates that are worse than the current tip. /** Delete all entries in setBlockIndexCandidates that are worse than the current tip. */
static void PruneBlockIndexCandidates() { static void PruneBlockIndexCandidates() {
// Note that we can't delete the current block itself, as we may need to return to it later in case a // Note that we can't delete the current block itself, as we may need to return to it later in case a
// reorganization to a better block fails. // reorganization to a better block fails.
@ -2019,8 +2030,10 @@ static void PruneBlockIndexCandidates() {
assert(!setBlockIndexCandidates.empty()); assert(!setBlockIndexCandidates.empty());
} }
// Try to make some progress towards making pindexMostWork the active block. /**
// pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork. * Try to make some progress towards making pindexMostWork the active block.
* pblock is either NULL or a pointer to a CBlock corresponding to pindexMostWork.
*/
static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) { static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMostWork, CBlock *pblock) {
AssertLockHeld(cs_main); AssertLockHeld(cs_main);
bool fInvalidFound = false; bool fInvalidFound = false;
@ -2085,9 +2098,11 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
return true; return true;
} }
// Make the best chain active, in multiple steps. The result is either failure /**
// or an activated best chain. pblock is either NULL or a pointer to a block * Make the best chain active, in multiple steps. The result is either failure
// that is already loaded (to avoid loading it again from disk). * or an activated best chain. pblock is either NULL or a pointer to a block
* that is already loaded (to avoid loading it again from disk).
*/
bool ActivateBestChain(CValidationState &state, CBlock *pblock) { bool ActivateBestChain(CValidationState &state, CBlock *pblock) {
CBlockIndex *pindexNewTip = NULL; CBlockIndex *pindexNewTip = NULL;
CBlockIndex *pindexMostWork = NULL; CBlockIndex *pindexMostWork = NULL;
@ -2236,7 +2251,7 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
return pindexNew; return pindexNew;
} }
// Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). /** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos) bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos)
{ {
pindexNew->nTx = block.vtx.size(); pindexNew->nTx = block.vtx.size();
@ -2745,7 +2760,7 @@ uint256 CPartialMerkleTree::CalcHash(int height, unsigned int pos, const std::ve
} else { } else {
// calculate left hash // calculate left hash
uint256 left = CalcHash(height-1, pos*2, vTxid), right; uint256 left = CalcHash(height-1, pos*2, vTxid), right;
// calculate right hash if not beyong the end of the array - copy left hash otherwise1 // calculate right hash if not beyond the end of the array - copy left hash otherwise1
if (pos*2+1 < CalcTreeWidth(height-1)) if (pos*2+1 < CalcTreeWidth(height-1))
right = CalcHash(height-1, pos*2+1, vTxid); right = CalcHash(height-1, pos*2+1, vTxid);
else else

View file

@ -1,6 +1,6 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto // Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2014 The Bitcoin developers // 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. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_MAIN_H #ifndef BITCOIN_MAIN_H
@ -60,7 +60,7 @@ static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 50000;
static const unsigned int MAX_STANDARD_TX_SIZE = 100000; static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
/** The maximum allowed number of signature check operations in a block (network rule) */ /** The maximum allowed number of signature check operations in a block (network rule) */
static const unsigned int MAX_BLOCK_SIGOPS = MAX_BLOCK_SIZE/50; 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; static const unsigned int MAX_P2SH_SIGOPS = 15;
/** The maximum number of sigops we're willing to relay/mine in a single tx */ /** 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; static const unsigned int MAX_TX_SIGOPS = MAX_BLOCK_SIGOPS/5;
@ -97,7 +97,7 @@ static const unsigned int BLOCK_DOWNLOAD_WINDOW = 1024;
/** Time to wait (in seconds) between writing blockchain state to disk. */ /** Time to wait (in seconds) between writing blockchain state to disk. */
static const unsigned int DATABASE_WRITE_INTERVAL = 3600; 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_MALFORMED = 0x01;
static const unsigned char REJECT_INVALID = 0x10; static const unsigned char REJECT_INVALID = 0x10;
static const unsigned char REJECT_OBSOLETE = 0x11; static const unsigned char REJECT_OBSOLETE = 0x11;
@ -131,10 +131,10 @@ extern bool fIsBareMultisigStd;
extern unsigned int nCoinCacheSize; extern unsigned int nCoinCacheSize;
extern CFeeRate minRelayTxFee; 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; extern CBlockIndex *pindexBestHeader;
// Minimum disk space required - used in CheckDiskSpace() /** Minimum disk space required - used in CheckDiskSpace() */
static const uint64_t nMinDiskSpace = 52428800; static const uint64_t nMinDiskSpace = 52428800;
/** Register a wallet to receive updates from core */ /** Register a wallet to receive updates from core */
@ -151,15 +151,17 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals);
/** Unregister a network node */ /** Unregister a network node */
void UnregisterNodeSignals(CNodeSignals& nodeSignals); 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 * Process an incoming block. This only returns after the best known valid
specific block passed to it has been checked for validity! * block is made active. Note that it does not, however, guarantee that the
@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. * specific block passed to it has been checked for validity!
@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] 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[out] dbp If pblock is stored to disk (or already there), this will be set to its location. * @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.
@return True if state.IsValid() * @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); bool ProcessNewBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBlockPos *dbp = NULL);
/** Check whether enough disk space is available for an incoming block */ /** Check whether enough disk space is available for an incoming block */
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0); bool CheckDiskSpace(uint64_t nAdditionalBytes = 0);
@ -245,54 +247,59 @@ struct CDiskTxPos : public CDiskBlockPos
CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree);
// /**
// Check transaction inputs, and make sure any * Check transaction inputs, and make sure any
// pay-to-script-hash transactions are evaluating IsStandard scripts * pay-to-script-hash transactions are evaluating IsStandard scripts
// *
// Why bother? To avoid denial-of-service attacks; an attacker * Why bother? To avoid denial-of-service attacks; an attacker
// can submit a standard HASH... OP_EQUAL transaction, * can submit a standard HASH... OP_EQUAL transaction,
// which will get accepted into blocks. The redemption * which will get accepted into blocks. The redemption
// script can be anything; an attacker could use a very * script can be anything; an attacker could use a very
// expensive-to-check-upon-redemption script like: * expensive-to-check-upon-redemption script like:
// DUP CHECKSIG DROP ... repeated 100 times... OP_1 * 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 * Check for standard transaction types
@return True if all inputs (scriptSigs) use only standard transaction forms * @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); 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 * Count ECDSA signature operations the old-fashioned (pre-0.6) way
@see CTransaction::FetchInputs * @return number of sigops this transaction's outputs will produce when spent
*/ * @see CTransaction::FetchInputs
*/
unsigned int GetLegacySigOpCount(const CTransaction& tx); unsigned int GetLegacySigOpCount(const CTransaction& tx);
/** Count ECDSA signature operations in pay-to-script-hash inputs. /**
* 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 * @param[in] mapInputs Map of previous transactions that have outputs we're spending
@see CTransaction::FetchInputs * @return maximum number of sigops required to validate this transaction's inputs
* @see CTransaction::FetchInputs
*/ */
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs); 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 * Check whether all inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
// instead of being performed inline. * 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, bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks,
unsigned int flags, bool cacheStore, std::vector<CScriptCheck> *pvChecks = NULL); 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); 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); bool CheckTransaction(const CTransaction& tx, CValidationState& state);
/** Check for standard transaction types /** 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 IsStandardTx(const CTransaction& tx, std::string& reason);
bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64_t nBlockTime = 0); bool IsFinalTx(const CTransaction &tx, int nBlockHeight = 0, int64_t nBlockTime = 0);
@ -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 class CScriptCheck
{ {
private: private:
@ -345,7 +354,7 @@ public:
/** Data structure that represents a partial merkle tree. /** 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 * allows recovery of the list of txid's and the merkle root, in an
* authenticated way. * authenticated way.
* *
@ -380,36 +389,38 @@ public:
class CPartialMerkleTree class CPartialMerkleTree
{ {
protected: protected:
// the total number of transactions in the block /** the total number of transactions in the block */
unsigned int nTransactions; unsigned int nTransactions;
// node-is-parent-of-matched-txid bits /** node-is-parent-of-matched-txid bits */
std::vector<bool> vBits; std::vector<bool> vBits;
// txids and internal hashes /** txids and internal hashes */
std::vector<uint256> vHash; std::vector<uint256> vHash;
// flag set when encountering invalid data /** flag set when encountering invalid data */
bool fBad; 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) { unsigned int CalcTreeWidth(int height) {
return (nTransactions+(1 << height)-1) >> 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); 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); 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); uint256 TraverseAndExtract(int height, unsigned int pos, unsigned int &nBitsUsed, unsigned int &nHashUsed, std::vector<uint256> &vMatch);
public: public:
// serialization implementation /** serialization implementation */
ADD_SERIALIZE_METHODS; ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation> template <typename Stream, typename Operation>
@ -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(const std::vector<uint256> &vTxid, const std::vector<bool> &vMatch);
CPartialMerkleTree(); 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); uint256 ExtractMatches(std::vector<uint256> &vMatch);
}; };
@ -458,22 +471,21 @@ bool ReadBlockFromDisk(CBlock& block, const CBlockIndex* pindex);
* of problems. Note that in any case, coins may be modified. */ * of problems. Note that in any case, coins may be modified. */
bool DisconnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, CCoinsViewCache& coins, bool* pfClean = NULL); 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); 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 CheckBlockHeader(const CBlockHeader& block, CValidationState& state, bool fCheckPOW = true);
bool CheckBlock(const CBlock& block, CValidationState& state, bool fCheckPOW = true, bool fCheckMerkleRoot = 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 ContextualCheckBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex *pindexPrev);
bool ContextualCheckBlock(const CBlock& 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); bool TestBlockValidity(CValidationState &state, const CBlock& block, CBlockIndex *pindexPrev, bool fCheckPOW = true, bool fCheckMerkleRoot = true);
// Store block on disk /** Store block on disk. If dbp is provided, the file is known to already reside 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 AcceptBlock(CBlock& block, CValidationState& state, CBlockIndex **pindex, CDiskBlockPos* dbp = NULL);
bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL); bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBlockIndex **ppindex= NULL);
@ -482,13 +494,13 @@ bool AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, CBloc
class CBlockFileInfo class CBlockFileInfo
{ {
public: public:
unsigned int nBlocks; // number of blocks stored in file unsigned int nBlocks; //! number of blocks stored in file
unsigned int nSize; // number of used bytes of block file unsigned int nSize; //! number of used bytes of block file
unsigned int nUndoSize; // number of used bytes in the undo file unsigned int nUndoSize; //! number of used bytes in the undo file
unsigned int nHeightFirst; // lowest height of block in file unsigned int nHeightFirst; //! lowest height of block in file
unsigned int nHeightLast; // highest 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 nTimeFirst; //! earliest time of block in file
uint64_t nTimeLast; // latest time of block in file uint64_t nTimeLast; //! latest time of block in file
ADD_SERIALIZE_METHODS; ADD_SERIALIZE_METHODS;
@ -519,7 +531,7 @@ public:
std::string ToString() const; std::string ToString() const;
// update statistics (does not update nSize) /** update statistics (does not update nSize) */
void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) { void AddBlock(unsigned int nHeightIn, uint64_t nTimeIn) {
if (nBlocks==0 || nHeightFirst > nHeightIn) if (nBlocks==0 || nHeightFirst > nHeightIn)
nHeightFirst = nHeightIn; nHeightFirst = nHeightIn;
@ -537,9 +549,9 @@ public:
class CValidationState { class CValidationState {
private: private:
enum mode_state { enum mode_state {
MODE_VALID, // everything ok MODE_VALID, //! everything ok
MODE_INVALID, // network rule violation (DoS value may be set) MODE_INVALID, //! network rule violation (DoS value may be set)
MODE_ERROR, // run-time error MODE_ERROR, //! run-time error
} mode; } mode;
int nDoS; int nDoS;
std::string strRejectReason; std::string strRejectReason;
@ -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. * to filtered nodes.
*/ */
class CMerkleBlock class CMerkleBlock
{ {
public: public:
// Public only for unit testing /** Public only for unit testing */
CBlockHeader header; CBlockHeader header;
CPartialMerkleTree txn; CPartialMerkleTree txn;
public: public:
// Public only for unit testing and relay testing /** Public only for unit testing and relay testing (not relayed) */
// (not relayed)
std::vector<std::pair<unsigned int, uint256> > vMatchedTxn; 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, * Create from a CBlock, filtering transactions according to filter
// thus the filter will likely be modified. * 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); CMerkleBlock(const CBlock& block, CBloomFilter& filter);
ADD_SERIALIZE_METHODS; ADD_SERIALIZE_METHODS;