Changeset View
Changeset View
Standalone View
Standalone View
src/validation.h
// Copyright (c) 2009-2010 Satoshi Nakamoto | // Copyright (c) 2009-2010 Satoshi Nakamoto | ||||
// Copyright (c) 2009-2019 The Bitcoin Core developers | // Copyright (c) 2009-2019 The Bitcoin Core developers | ||||
// Copyright (c) 2017-2020 The Bitcoin developers | // Copyright (c) 2017-2020 The Bitcoin developers | ||||
// Distributed under the MIT 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_VALIDATION_H | #ifndef BITCOIN_VALIDATION_H | ||||
#define BITCOIN_VALIDATION_H | #define BITCOIN_VALIDATION_H | ||||
#if defined(HAVE_CONFIG_H) | #if defined(HAVE_CONFIG_H) | ||||
#include <config/bitcoin-config.h> | #include <config/bitcoin-config.h> | ||||
#endif | #endif | ||||
#include <amount.h> | #include <amount.h> | ||||
#include <blockfileinfo.h> | #include <blockfileinfo.h> | ||||
#include <blockindexworkcomparator.h> | |||||
#include <coins.h> | #include <coins.h> | ||||
#include <consensus/consensus.h> | #include <consensus/consensus.h> | ||||
#include <disconnectresult.h> | |||||
#include <flatfile.h> | #include <flatfile.h> | ||||
#include <fs.h> | #include <fs.h> | ||||
#include <protocol.h> // For CMessageHeader::MessageMagic | #include <protocol.h> // For CMessageHeader::MessageMagic | ||||
#include <script/script_error.h> | #include <script/script_error.h> | ||||
#include <script/script_metrics.h> | #include <script/script_metrics.h> | ||||
#include <sync.h> | #include <sync.h> | ||||
#include <versionbits.h> | #include <versionbits.h> | ||||
Show All 17 Lines | |||||
class CCoinsViewDB; | class CCoinsViewDB; | ||||
class CConnman; | class CConnman; | ||||
class CInv; | class CInv; | ||||
class Config; | class Config; | ||||
class CScriptCheck; | class CScriptCheck; | ||||
class CTxMemPool; | class CTxMemPool; | ||||
class CTxUndo; | class CTxUndo; | ||||
class CValidationState; | class CValidationState; | ||||
class DisconnectedBlockTransactions; | |||||
struct FlatFilePos; | |||||
struct ChainTxData; | struct ChainTxData; | ||||
struct FlatFilePos; | |||||
struct PrecomputedTransactionData; | struct PrecomputedTransactionData; | ||||
struct LockPoints; | struct LockPoints; | ||||
namespace Consensus { | namespace Consensus { | ||||
struct Params; | struct Params; | ||||
} | } | ||||
#define MIN_TRANSACTION_SIZE \ | #define MIN_TRANSACTION_SIZE \ | ||||
▲ Show 20 Lines • Show All 408 Lines • ▼ Show 20 Lines | TxSigCheckLimiter(const TxSigCheckLimiter &rhs) | ||||
: CheckInputsLimiter(rhs.remaining.load()) {} | : CheckInputsLimiter(rhs.remaining.load()) {} | ||||
TxSigCheckLimiter &operator=(const TxSigCheckLimiter &rhs) { | TxSigCheckLimiter &operator=(const TxSigCheckLimiter &rhs) { | ||||
remaining = rhs.remaining.load(); | remaining = rhs.remaining.load(); | ||||
return *this; | return *this; | ||||
} | } | ||||
}; | }; | ||||
class ConnectTrace; | |||||
/** | /** | ||||
* Check whether all inputs of this transaction are valid (no double spends, | * Check whether all inputs of this transaction are valid (no double spends, | ||||
* scripts & sigs, amounts). This does not modify the UTXO set. | * scripts & sigs, amounts). This does not modify the UTXO set. | ||||
* | * | ||||
* If pvChecks is not nullptr, script checks are pushed onto it instead of being | * If pvChecks is not nullptr, script checks are pushed onto it instead of being | ||||
* performed inline. Any script checks which are not necessary (eg due to script | * performed inline. Any script checks which are not necessary (eg due to script | ||||
* execution cache hits) are, obviously, not pushed onto pvChecks/run. | * execution cache hits) are, obviously, not pushed onto pvChecks/run. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 216 Lines • ▼ Show 20 Lines | |||||
bool ReplayBlocks(const Consensus::Params ¶ms, CCoinsView *view); | bool ReplayBlocks(const Consensus::Params ¶ms, CCoinsView *view); | ||||
/** Find the last common block between the parameter chain and a locator. */ | /** Find the last common block between the parameter chain and a locator. */ | ||||
CBlockIndex *FindForkInGlobalIndex(const CChain &chain, | CBlockIndex *FindForkInGlobalIndex(const CChain &chain, | ||||
const CBlockLocator &locator) | const CBlockLocator &locator) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
/** | /** | ||||
* CChainState stores and provides an API to update our local knowledge of the | |||||
* current best chain and header tree. | |||||
* | |||||
* It generally provides access to the current block tree, as well as functions | |||||
* to provide new data, which it will appropriately validate and incorporate in | |||||
* its state as necessary. | |||||
* | |||||
* Eventually, the API here is targeted at being exposed externally as a | |||||
* consumable libconsensus library, so any functions added must only call | |||||
* other class member functions, pure functions in other parts of the consensus | |||||
* library, callbacks via the validation interface, or read/write-to-disk | |||||
* functions (eventually this will also be via callbacks). | |||||
*/ | |||||
class CChainState { | |||||
private: | |||||
/** | |||||
* The set of all CBlockIndex entries with BLOCK_VALID_TRANSACTIONS (for | |||||
* itself and all ancestors) and as good as our current tip or better. | |||||
* Entries may be failed or parked though, and pruning nodes may be missing | |||||
* the data for the block; these will get cleaned during FindMostWorkChain. | |||||
*/ | |||||
std::set<CBlockIndex *, CBlockIndexWorkComparator> setBlockIndexCandidates; | |||||
/** | |||||
* the ChainState CriticalSection | |||||
* A lock that must be held when modifying this ChainState - held in | |||||
* ActivateBestChain() | |||||
*/ | |||||
RecursiveMutex m_cs_chainstate; | |||||
/** | |||||
* Every received block is assigned a unique and increasing identifier, so | |||||
* we know which one to give priority in case of a fork. | |||||
* Blocks loaded from disk are assigned id 0, so start the counter at 1. | |||||
*/ | |||||
std::atomic<int32_t> nBlockSequenceId{1}; | |||||
/** Decreasing counter (used by subsequent preciousblock calls). */ | |||||
int32_t nBlockReverseSequenceId = -1; | |||||
/** chainwork for the last block that preciousblock has been applied to. */ | |||||
arith_uint256 nLastPreciousChainwork = 0; | |||||
/** | |||||
* In order to efficiently track invalidity of headers, we keep the set of | |||||
* blocks which we tried to connect and found to be invalid here (ie which | |||||
* were set to BLOCK_FAILED_VALID since the last restart). We can then | |||||
* walk this set and check if a new header is a descendant of something in | |||||
* this set, preventing us from having to walk mapBlockIndex when we try | |||||
* to connect a bad block and fail. | |||||
* | |||||
* While this is more complicated than marking everything which descends | |||||
* from an invalid block as invalid at the time we discover it to be | |||||
* invalid, doing so would require walking all of mapBlockIndex to find all | |||||
* descendants. Since this case should be very rare, keeping track of all | |||||
* BLOCK_FAILED_VALID blocks in a set should be just fine and work just as | |||||
* well. | |||||
* | |||||
* Because we already walk mapBlockIndex in height-order at startup, we go | |||||
* ahead and mark descendants of invalid blocks as FAILED_CHILD at that | |||||
* time, instead of putting things in this set. | |||||
*/ | |||||
std::set<CBlockIndex *> m_failed_blocks; | |||||
public: | |||||
CChain m_chain; | |||||
BlockMap mapBlockIndex GUARDED_BY(cs_main); | |||||
std::multimap<CBlockIndex *, CBlockIndex *> mapBlocksUnlinked; | |||||
CBlockIndex *pindexBestInvalid = nullptr; | |||||
CBlockIndex *pindexBestParked = nullptr; | |||||
CBlockIndex const *pindexFinalized = nullptr; | |||||
bool LoadBlockIndex(const Config &config, CBlockTreeDB &blocktree) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool ActivateBestChain( | |||||
const Config &config, CValidationState &state, | |||||
std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>()); | |||||
/** | |||||
* If a block header hasn't already been seen, call CheckBlockHeader on it, | |||||
* ensure that it doesn't descend from an invalid block, and then add it to | |||||
* mapBlockIndex. | |||||
*/ | |||||
bool AcceptBlockHeader(const Config &config, const CBlockHeader &block, | |||||
CValidationState &state, CBlockIndex **ppindex) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool AcceptBlock(const Config &config, | |||||
const std::shared_ptr<const CBlock> &pblock, | |||||
CValidationState &state, bool fRequested, | |||||
const FlatFilePos *dbp, bool *fNewBlock) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
// Block (dis)connection on a given view: | |||||
DisconnectResult DisconnectBlock(const CBlock &block, | |||||
const CBlockIndex *pindex, | |||||
CCoinsViewCache &view); | |||||
bool ConnectBlock(const CBlock &block, CValidationState &state, | |||||
CBlockIndex *pindex, CCoinsViewCache &view, | |||||
const CChainParams ¶ms, | |||||
BlockValidationOptions options, bool fJustCheck = false) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
// Block disconnection on our pcoinsTip: | |||||
bool DisconnectTip(const CChainParams ¶ms, CValidationState &state, | |||||
DisconnectedBlockTransactions *disconnectpool) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
// Manual block validity manipulation: | |||||
bool PreciousBlock(const Config &config, CValidationState &state, | |||||
CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main); | |||||
bool UnwindBlock(const Config &config, CValidationState &state, | |||||
CBlockIndex *pindex, bool invalidate); | |||||
void ResetBlockFailureFlags(CBlockIndex *pindex) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
template <typename F> | |||||
bool UpdateFlagsForBlock(CBlockIndex *pindexBase, CBlockIndex *pindex, F f) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
template <typename F, typename C, typename AC> | |||||
void UpdateFlags(CBlockIndex *pindex, CBlockIndex *&pindexReset, F f, | |||||
C fChild, AC fAncestorWasChanged) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
/** Remove parked status from a block and its descendants. */ | |||||
void UnparkBlockImpl(CBlockIndex *pindex, bool fClearChildren) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool ReplayBlocks(const Consensus::Params ¶ms, CCoinsView *view); | |||||
bool LoadGenesisBlock(const CChainParams &chainparams); | |||||
void PruneBlockIndexCandidates(); | |||||
void UnloadBlockIndex(); | |||||
private: | |||||
bool ActivateBestChainStep(const Config &config, CValidationState &state, | |||||
CBlockIndex *pindexMostWork, | |||||
const std::shared_ptr<const CBlock> &pblock, | |||||
bool &fInvalidFound, ConnectTrace &connectTrace) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool ConnectTip(const Config &config, CValidationState &state, | |||||
CBlockIndex *pindexNew, | |||||
const std::shared_ptr<const CBlock> &pblock, | |||||
ConnectTrace &connectTrace, | |||||
DisconnectedBlockTransactions &disconnectpool) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
CBlockIndex *AddToBlockIndex(const CBlockHeader &block) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
/** Create a new block index entry for a given block hash */ | |||||
CBlockIndex *InsertBlockIndex(const BlockHash &hash) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
/** | |||||
* Make various assertions about the state of the block index. | |||||
* | |||||
* By default this only executes fully when using the Regtest chain; see: | |||||
* fCheckBlockIndex. | |||||
*/ | |||||
void CheckBlockIndex(const Consensus::Params &consensusParams); | |||||
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
CBlockIndex *FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
void ReceivedBlockTransactions(const CBlock &block, CBlockIndex *pindexNew, | |||||
const FlatFilePos &pos) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool RollforwardBlock(const CBlockIndex *pindex, CCoinsViewCache &inputs, | |||||
const Consensus::Params ¶ms) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
}; | |||||
/** | |||||
* Mark a block as precious and reorganize. | * Mark a block as precious and reorganize. | ||||
* | * | ||||
* May not be called in a validationinterface callback. | * May not be called in a validationinterface callback. | ||||
*/ | */ | ||||
bool PreciousBlock(const Config &config, CValidationState &state, | bool PreciousBlock(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main); | CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main); | ||||
/** | /** | ||||
▲ Show 20 Lines • Show All 93 Lines • Show Last 20 Lines |