Browse Source

Merge pull request #5403

c5b390b Make comments in main an init doxygen compatible (Michael Ford)
0.10
Wladimir J. van der Laan 10 years ago
parent
commit
7eb0667384
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 10
      src/init.cpp
  2. 6
      src/init.h
  3. 149
      src/main.cpp
  4. 176
      src/main.h

10
src/init.cpp

@ -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;

6
src/init.h

@ -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

149
src/main.cpp

@ -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

176
src/main.h

@ -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,14 +151,16 @@ 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 */
@ -245,53 +247,58 @@ 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);
@ -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;

Loading…
Cancel
Save