Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 122 Lines • ▼ Show 20 Lines | |||||
public: | public: | ||||
CChain chainActive; | CChain chainActive; | ||||
BlockMap mapBlockIndex; | BlockMap mapBlockIndex; | ||||
std::multimap<CBlockIndex *, CBlockIndex *> mapBlocksUnlinked; | std::multimap<CBlockIndex *, CBlockIndex *> mapBlocksUnlinked; | ||||
CBlockIndex *pindexBestInvalid = nullptr; | CBlockIndex *pindexBestInvalid = nullptr; | ||||
CBlockIndex *pindexBestParked = nullptr; | CBlockIndex *pindexBestParked = nullptr; | ||||
bool LoadBlockIndex(const Config &config, CBlockTreeDB &blocktree); | bool LoadBlockIndex(const Config &config, CBlockTreeDB &blocktree) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool ActivateBestChain( | bool ActivateBestChain( | ||||
const Config &config, CValidationState &state, | const Config &config, CValidationState &state, | ||||
std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>()); | std::shared_ptr<const CBlock> pblock = std::shared_ptr<const CBlock>()); | ||||
/** | /** | ||||
* If a block header hasn't already been seen, call CheckBlockHeader on it, | * 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 | * ensure that it doesn't descend from an invalid block, and then add it to | ||||
* mapBlockIndex. | * mapBlockIndex. | ||||
*/ | */ | ||||
bool AcceptBlockHeader(const Config &config, const CBlockHeader &block, | bool AcceptBlockHeader(const Config &config, const CBlockHeader &block, | ||||
CValidationState &state, CBlockIndex **ppindex); | CValidationState &state, CBlockIndex **ppindex) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool AcceptBlock(const Config &config, | bool AcceptBlock(const Config &config, | ||||
const std::shared_ptr<const CBlock> &pblock, | const std::shared_ptr<const CBlock> &pblock, | ||||
CValidationState &state, bool fRequested, | CValidationState &state, bool fRequested, | ||||
const FlatFilePos *dbp, bool *fNewBlock); | const FlatFilePos *dbp, bool *fNewBlock) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
// Block (dis)connection on a given view: | // Block (dis)connection on a given view: | ||||
DisconnectResult DisconnectBlock(const CBlock &block, | DisconnectResult DisconnectBlock(const CBlock &block, | ||||
const CBlockIndex *pindex, | const CBlockIndex *pindex, | ||||
CCoinsViewCache &view); | CCoinsViewCache &view); | ||||
bool ConnectBlock(const CBlock &block, CValidationState &state, | bool ConnectBlock(const CBlock &block, CValidationState &state, | ||||
CBlockIndex *pindex, CCoinsViewCache &view, | CBlockIndex *pindex, CCoinsViewCache &view, | ||||
const CChainParams ¶ms, | const CChainParams ¶ms, | ||||
BlockValidationOptions options, bool fJustCheck = false) | BlockValidationOptions options, bool fJustCheck = false) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
// Block disconnection on our pcoinsTip: | // Block disconnection on our pcoinsTip: | ||||
bool DisconnectTip(const Config &config, CValidationState &state, | bool DisconnectTip(const Config &config, CValidationState &state, | ||||
DisconnectedBlockTransactions *disconnectpool) | DisconnectedBlockTransactions *disconnectpool) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
// Manual block validity manipulation: | // Manual block validity manipulation: | ||||
bool PreciousBlock(const Config &config, CValidationState &state, | bool PreciousBlock(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindex); | CBlockIndex *pindex) LOCKS_EXCLUDED(cs_main); | ||||
bool UnwindBlock(const Config &config, CValidationState &state, | bool UnwindBlock(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindex, bool invalidate); | CBlockIndex *pindex, bool invalidate) | ||||
void ResetBlockFailureFlags(CBlockIndex *pindex); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
void ResetBlockFailureFlags(CBlockIndex *pindex) | |||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
template <typename F> | template <typename F> | ||||
void UpdateFlagsForBlock(CBlockIndex *pindexBase, CBlockIndex *pindex, F f); | void UpdateFlagsForBlock(CBlockIndex *pindexBase, CBlockIndex *pindex, F f); | ||||
template <typename F, typename C> | template <typename F, typename C> | ||||
void UpdateFlags(CBlockIndex *pindex, F f, C fchild) | void UpdateFlags(CBlockIndex *pindex, F f, C fchild) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
template <typename F> | template <typename F> | ||||
void UpdateFlags(CBlockIndex *pindex, F f) | void UpdateFlags(CBlockIndex *pindex, F f) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
/** Remove parked status from a block and its descendants. */ | /** Remove parked status from a block and its descendants. */ | ||||
void UnparkBlockImpl(CBlockIndex *pindex, bool fClearChildren); | void UnparkBlockImpl(CBlockIndex *pindex, bool fClearChildren) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
bool ReplayBlocks(const Consensus::Params ¶ms, CCoinsView *view); | bool ReplayBlocks(const Consensus::Params ¶ms, CCoinsView *view); | ||||
bool RewindBlockIndex(const Config &config); | bool RewindBlockIndex(const Config &config); | ||||
bool LoadGenesisBlock(const CChainParams &chainparams); | bool LoadGenesisBlock(const CChainParams &chainparams); | ||||
void PruneBlockIndexCandidates(); | void PruneBlockIndexCandidates(); | ||||
void UnloadBlockIndex(); | void UnloadBlockIndex(); | ||||
Show All 9 Lines | bool ConnectTip(const Config &config, CValidationState &state, | ||||
const std::shared_ptr<const CBlock> &pblock, | const std::shared_ptr<const CBlock> &pblock, | ||||
ConnectTrace &connectTrace, | ConnectTrace &connectTrace, | ||||
DisconnectedBlockTransactions &disconnectpool) | DisconnectedBlockTransactions &disconnectpool) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
CBlockIndex *AddToBlockIndex(const CBlockHeader &block) | CBlockIndex *AddToBlockIndex(const CBlockHeader &block) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
/** Create a new block index entry for a given block hash */ | /** Create a new block index entry for a given block hash */ | ||||
CBlockIndex *InsertBlockIndex(const uint256 &hash); | CBlockIndex *InsertBlockIndex(const uint256 &hash) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
/** | /** | ||||
* Make various assertions about the state of the block index. | * Make various assertions about the state of the block index. | ||||
* | * | ||||
* By default this only executes fully when using the Regtest chain; see: | * By default this only executes fully when using the Regtest chain; see: | ||||
* fCheckBlockIndex. | * fCheckBlockIndex. | ||||
*/ | */ | ||||
void CheckBlockIndex(const Consensus::Params &consensusParams); | void CheckBlockIndex(const Consensus::Params &consensusParams); | ||||
void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) | void InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
CBlockIndex *FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main); | CBlockIndex *FindMostWorkChain() EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
bool ReceivedBlockTransactions(const CBlock &block, CValidationState &state, | bool ReceivedBlockTransactions(const CBlock &block, CValidationState &state, | ||||
CBlockIndex *pindexNew, | CBlockIndex *pindexNew, | ||||
const FlatFilePos &pos) | const FlatFilePos &pos) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
bool RollforwardBlock(const CBlockIndex *pindex, CCoinsViewCache &inputs, | bool RollforwardBlock(const CBlockIndex *pindex, CCoinsViewCache &inputs, | ||||
const Consensus::Params ¶ms); | const Consensus::Params ¶ms) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | |||||
} g_chainstate; | } g_chainstate; | ||||
/** | /** | ||||
* Global state | * Global state | ||||
* | * | ||||
* Mutex to guard access to validation specific variables, such as reading | * Mutex to guard access to validation specific variables, such as reading | ||||
* or changing the chainstate. | * or changing the chainstate. | ||||
* | * | ||||
▲ Show 20 Lines • Show All 2,144 Lines • ▼ Show 20 Lines | void NotifyEntryRemoved(CTransactionRef txRemoved, | ||||
if (reason == MemPoolRemovalReason::CONFLICT) { | if (reason == MemPoolRemovalReason::CONFLICT) { | ||||
blocksConnected.back().conflictedTxs->emplace_back( | blocksConnected.back().conflictedTxs->emplace_back( | ||||
std::move(txRemoved)); | std::move(txRemoved)); | ||||
} | } | ||||
} | } | ||||
}; | }; | ||||
static bool FinalizeBlockInternal(const Config &config, CValidationState &state, | static bool FinalizeBlockInternal(const Config &config, CValidationState &state, | ||||
const CBlockIndex *pindex) { | const CBlockIndex *pindex) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
if (pindex->nStatus.isInvalid()) { | if (pindex->nStatus.isInvalid()) { | ||||
// We try to finalize an invalid block. | // We try to finalize an invalid block. | ||||
return state.DoS(100, | return state.DoS(100, | ||||
error("%s: Trying to finalize invalid block %s", | error("%s: Trying to finalize invalid block %s", | ||||
__func__, pindex->GetBlockHash().ToString()), | __func__, pindex->GetBlockHash().ToString()), | ||||
REJECT_INVALID, "finalize-invalid-block"); | REJECT_INVALID, "finalize-invalid-block"); | ||||
} | } | ||||
Show All 14 Lines | static bool FinalizeBlockInternal(const Config &config, CValidationState &state, | ||||
} | } | ||||
// We have a new block to finalize. | // We have a new block to finalize. | ||||
pindexFinalized = pindex; | pindexFinalized = pindex; | ||||
return true; | return true; | ||||
} | } | ||||
static const CBlockIndex *FindBlockToFinalize(const Config &config, | static const CBlockIndex *FindBlockToFinalize(const Config &config, | ||||
CBlockIndex *pindexNew) { | CBlockIndex *pindexNew) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
const int32_t maxreorgdepth = | const int32_t maxreorgdepth = | ||||
gArgs.GetArg("-maxreorgdepth", DEFAULT_MAX_REORG_DEPTH); | gArgs.GetArg("-maxreorgdepth", DEFAULT_MAX_REORG_DEPTH); | ||||
const int64_t finalizationdelay = | const int64_t finalizationdelay = | ||||
gArgs.GetArg("-finalizationdelay", DEFAULT_MIN_FINALIZATION_DELAY); | gArgs.GetArg("-finalizationdelay", DEFAULT_MIN_FINALIZATION_DELAY); | ||||
▲ Show 20 Lines • Show All 430 Lines • ▼ Show 20 Lines | if (fInvalidFound) { | ||||
CheckForkWarningConditionsOnNewFork(pindexMostWork); | CheckForkWarningConditionsOnNewFork(pindexMostWork); | ||||
} else { | } else { | ||||
CheckForkWarningConditions(); | CheckForkWarningConditions(); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
static void NotifyHeaderTip() { | static void NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) { | ||||
bool fNotify = false; | bool fNotify = false; | ||||
bool fInitialBlockDownload = false; | bool fInitialBlockDownload = false; | ||||
static CBlockIndex *pindexHeaderOld = nullptr; | static CBlockIndex *pindexHeaderOld = nullptr; | ||||
CBlockIndex *pindexHeader = nullptr; | CBlockIndex *pindexHeader = nullptr; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pindexHeader = pindexBestHeader; | pindexHeader = pindexBestHeader; | ||||
▲ Show 20 Lines • Show All 989 Lines • ▼ Show 20 Lines | if (hash != chainparams.GetConsensus().hashGenesisBlock) { | ||||
if (!ContextualCheckBlockHeader(chainparams, block, state, pindexPrev, | if (!ContextualCheckBlockHeader(chainparams, block, state, pindexPrev, | ||||
GetAdjustedTime())) { | GetAdjustedTime())) { | ||||
return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", | return error("%s: Consensus::ContextualCheckBlockHeader: %s, %s", | ||||
__func__, hash.ToString(), FormatStateMessage(state)); | __func__, hash.ToString(), FormatStateMessage(state)); | ||||
} | } | ||||
// If the previous block index isn't valid, determine if it descends | // If the previous block index isn't valid, determine if it descends | ||||
// from any block which has been found invalid (g_failed_blocks), then | // from any block which has been found invalid (m_failed_blocks), then | ||||
// mark pindexPrev and any blocks between them as failed. | // mark pindexPrev and any blocks between them as failed. | ||||
if (!pindexPrev->IsValid(BlockValidity::SCRIPTS)) { | if (!pindexPrev->IsValid(BlockValidity::SCRIPTS)) { | ||||
for (const CBlockIndex *failedit : m_failed_blocks) { | for (const CBlockIndex *failedit : m_failed_blocks) { | ||||
if (pindexPrev->GetAncestor(failedit->nHeight) == failedit) { | if (pindexPrev->GetAncestor(failedit->nHeight) == failedit) { | ||||
assert(failedit->nStatus.hasFailed()); | assert(failedit->nStatus.hasFailed()); | ||||
CBlockIndex *invalid_walk = pindexPrev; | CBlockIndex *invalid_walk = pindexPrev; | ||||
while (invalid_walk != failedit) { | while (invalid_walk != failedit) { | ||||
invalid_walk->nStatus = | invalid_walk->nStatus = | ||||
▲ Show 20 Lines • Show All 566 Lines • ▼ Show 20 Lines | CBlockIndex *CChainState::InsertBlockIndex(const uint256 &hash) { | ||||
mi = mapBlockIndex.insert(std::make_pair(hash, pindexNew)).first; | mi = mapBlockIndex.insert(std::make_pair(hash, pindexNew)).first; | ||||
pindexNew->phashBlock = &((*mi).first); | pindexNew->phashBlock = &((*mi).first); | ||||
return pindexNew; | return pindexNew; | ||||
} | } | ||||
bool CChainState::LoadBlockIndex(const Config &config, | bool CChainState::LoadBlockIndex(const Config &config, | ||||
CBlockTreeDB &blocktree) { | CBlockTreeDB &blocktree) { | ||||
if (!blocktree.LoadBlockIndexGuts(config.GetChainParams().GetConsensus(), | if (!blocktree.LoadBlockIndexGuts( | ||||
[this](const uint256 &hash) { | config.GetChainParams().GetConsensus(), | ||||
[this](const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
return this->InsertBlockIndex(hash); | return this->InsertBlockIndex(hash); | ||||
})) { | })) { | ||||
return false; | return false; | ||||
} | } | ||||
boost::this_thread::interruption_point(); | boost::this_thread::interruption_point(); | ||||
// Calculate nChainWork | // Calculate nChainWork | ||||
std::vector<std::pair<int, CBlockIndex *>> vSortedByHeight; | std::vector<std::pair<int, CBlockIndex *>> vSortedByHeight; | ||||
vSortedByHeight.reserve(mapBlockIndex.size()); | vSortedByHeight.reserve(mapBlockIndex.size()); | ||||
▲ Show 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | for (const std::pair<int, CBlockIndex *> &item : vSortedByHeight) { | ||||
CBlockIndexWorkComparator()(pindexBestHeader, pindex))) { | CBlockIndexWorkComparator()(pindexBestHeader, pindex))) { | ||||
pindexBestHeader = pindex; | pindexBestHeader = pindex; | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool static LoadBlockIndexDB(const Config &config) { | bool static LoadBlockIndexDB(const Config &config) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | |||||
if (!g_chainstate.LoadBlockIndex(config, *pblocktree)) { | if (!g_chainstate.LoadBlockIndex(config, *pblocktree)) { | ||||
return false; | return false; | ||||
} | } | ||||
// Load block file info | // Load block file info | ||||
pblocktree->ReadLastBlockFile(nLastBlockFile); | pblocktree->ReadLastBlockFile(nLastBlockFile); | ||||
vinfoBlockFile.resize(nLastBlockFile + 1); | vinfoBlockFile.resize(nLastBlockFile + 1); | ||||
LogPrintf("%s: last block file = %i\n", __func__, nLastBlockFile); | LogPrintf("%s: last block file = %i\n", __func__, nLastBlockFile); | ||||
▲ Show 20 Lines • Show All 1,239 Lines • Show Last 20 Lines |