mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 07:39:08 +01:00
refactoring: move block metadata structures into BlockManager
Separate out the management of chain-agnostic block metadata from any given CChainState instance. This allows us to avoid duplicating data like `mapBlockIndex` unnecessarily for multiple chainstates. This also adds a CChainState constructor that accepts and sets m_blockman. Ultimately this reference will point to a BlockMan instance that is shared across CChainStates. This commit can be decomposed into smaller commits if necessary.
This commit is contained in:
@@ -77,7 +77,11 @@ bool CBlockIndexWorkComparator::operator()(const CBlockIndex *pa, const CBlockIn
|
||||
return false;
|
||||
}
|
||||
|
||||
static CChainState g_chainstate;
|
||||
namespace {
|
||||
BlockManager g_blockman;
|
||||
} // anon namespace
|
||||
|
||||
static CChainState g_chainstate(g_blockman);
|
||||
|
||||
CChainState& ChainstateActive() { return g_chainstate; }
|
||||
|
||||
@@ -95,7 +99,7 @@ CChain& ChainActive() { return g_chainstate.m_chain; }
|
||||
*/
|
||||
RecursiveMutex cs_main;
|
||||
|
||||
BlockMap& mapBlockIndex = ::ChainstateActive().mapBlockIndex;
|
||||
BlockMap& mapBlockIndex = g_blockman.m_block_index;
|
||||
CBlockIndex *pindexBestHeader = nullptr;
|
||||
Mutex g_best_block_mutex;
|
||||
std::condition_variable g_best_block_cv;
|
||||
@@ -127,11 +131,6 @@ CScript COINBASE_FLAGS;
|
||||
namespace {
|
||||
CBlockIndex *&pindexBestInvalid = ::ChainstateActive().pindexBestInvalid;
|
||||
|
||||
/** All pairs A->B, where A (or one of its ancestors) misses transactions, but B has transactions.
|
||||
* Pruned nodes may have entries where B is missing data.
|
||||
*/
|
||||
std::multimap<CBlockIndex*, CBlockIndex*>& mapBlocksUnlinked = ::ChainstateActive().mapBlocksUnlinked;
|
||||
|
||||
CCriticalSection cs_LastBlockFile;
|
||||
std::vector<CBlockFileInfo> vinfoBlockFile;
|
||||
int nLastBlockFile = 0;
|
||||
@@ -1160,7 +1159,7 @@ void static InvalidChainFound(CBlockIndex* pindexNew) EXCLUSIVE_LOCKS_REQUIRED(c
|
||||
void CChainState::InvalidBlockFound(CBlockIndex *pindex, const CValidationState &state) {
|
||||
if (state.GetReason() != ValidationInvalidReason::BLOCK_MUTATED) {
|
||||
pindex->nStatus |= BLOCK_FAILED_VALID;
|
||||
m_failed_blocks.insert(pindex);
|
||||
m_blockman.m_failed_blocks.insert(pindex);
|
||||
setDirtyBlockIndex.insert(pindex);
|
||||
setBlockIndexCandidates.erase(pindex);
|
||||
InvalidChainFound(pindex);
|
||||
@@ -1695,8 +1694,8 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl
|
||||
// relative to a piece of software is an objective fact these defaults can be easily reviewed.
|
||||
// This setting doesn't force the selection of any particular chain but makes validating some faster by
|
||||
// effectively caching the result of part of the verification.
|
||||
BlockMap::const_iterator it = mapBlockIndex.find(hashAssumeValid);
|
||||
if (it != mapBlockIndex.end()) {
|
||||
BlockMap::const_iterator it = m_blockman.m_block_index.find(hashAssumeValid);
|
||||
if (it != m_blockman.m_block_index.end()) {
|
||||
if (it->second->GetAncestor(pindex->nHeight) == pindex &&
|
||||
pindexBestHeader->GetAncestor(pindex->nHeight) == pindex &&
|
||||
pindexBestHeader->nChainWork >= nMinimumChainWork) {
|
||||
@@ -2366,10 +2365,11 @@ CBlockIndex* CChainState::FindMostWorkChain() {
|
||||
if (fFailedChain) {
|
||||
pindexFailed->nStatus |= BLOCK_FAILED_CHILD;
|
||||
} else if (fMissingData) {
|
||||
// If we're missing data, then add back to mapBlocksUnlinked,
|
||||
// If we're missing data, then add back to m_blocks_unlinked,
|
||||
// so that if the block arrives in the future we can try adding
|
||||
// to setBlockIndexCandidates again.
|
||||
mapBlocksUnlinked.insert(std::make_pair(pindexFailed->pprev, pindexFailed));
|
||||
m_blockman.m_blocks_unlinked.insert(
|
||||
std::make_pair(pindexFailed->pprev, pindexFailed));
|
||||
}
|
||||
setBlockIndexCandidates.erase(pindexFailed);
|
||||
pindexFailed = pindexFailed->pprev;
|
||||
@@ -2720,12 +2720,12 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
|
||||
to_mark_failed->nStatus |= BLOCK_FAILED_VALID;
|
||||
setDirtyBlockIndex.insert(to_mark_failed);
|
||||
setBlockIndexCandidates.erase(to_mark_failed);
|
||||
m_failed_blocks.insert(to_mark_failed);
|
||||
m_blockman.m_failed_blocks.insert(to_mark_failed);
|
||||
|
||||
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
|
||||
// add it again.
|
||||
BlockMap::iterator it = mapBlockIndex.begin();
|
||||
while (it != mapBlockIndex.end()) {
|
||||
BlockMap::iterator it = m_blockman.m_block_index.begin();
|
||||
while (it != m_blockman.m_block_index.end()) {
|
||||
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->HaveTxsDownloaded() && !setBlockIndexCandidates.value_comp()(it->second, m_chain.Tip())) {
|
||||
setBlockIndexCandidates.insert(it->second);
|
||||
}
|
||||
@@ -2752,8 +2752,8 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
|
||||
int nHeight = pindex->nHeight;
|
||||
|
||||
// Remove the invalidity flag from this block and all its descendants.
|
||||
BlockMap::iterator it = mapBlockIndex.begin();
|
||||
while (it != mapBlockIndex.end()) {
|
||||
BlockMap::iterator it = m_blockman.m_block_index.begin();
|
||||
while (it != m_blockman.m_block_index.end()) {
|
||||
if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) {
|
||||
it->second->nStatus &= ~BLOCK_FAILED_MASK;
|
||||
setDirtyBlockIndex.insert(it->second);
|
||||
@@ -2764,7 +2764,7 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
|
||||
// Reset invalid block marker if it was pointing to one of those.
|
||||
pindexBestInvalid = nullptr;
|
||||
}
|
||||
m_failed_blocks.erase(it->second);
|
||||
m_blockman.m_failed_blocks.erase(it->second);
|
||||
}
|
||||
it++;
|
||||
}
|
||||
@@ -2774,7 +2774,7 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
|
||||
if (pindex->nStatus & BLOCK_FAILED_MASK) {
|
||||
pindex->nStatus &= ~BLOCK_FAILED_MASK;
|
||||
setDirtyBlockIndex.insert(pindex);
|
||||
m_failed_blocks.erase(pindex);
|
||||
m_blockman.m_failed_blocks.erase(pindex);
|
||||
}
|
||||
pindex = pindex->pprev;
|
||||
}
|
||||
@@ -2784,14 +2784,14 @@ void ResetBlockFailureFlags(CBlockIndex *pindex) {
|
||||
return ::ChainstateActive().ResetBlockFailureFlags(pindex);
|
||||
}
|
||||
|
||||
CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block)
|
||||
CBlockIndex* BlockManager::AddToBlockIndex(const CBlockHeader& block)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
// Check for duplicate
|
||||
uint256 hash = block.GetHash();
|
||||
BlockMap::iterator it = mapBlockIndex.find(hash);
|
||||
if (it != mapBlockIndex.end())
|
||||
BlockMap::iterator it = m_block_index.find(hash);
|
||||
if (it != m_block_index.end())
|
||||
return it->second;
|
||||
|
||||
// Construct new block index object
|
||||
@@ -2800,10 +2800,10 @@ CBlockIndex* CChainState::AddToBlockIndex(const CBlockHeader& block)
|
||||
// to avoid miners withholding blocks but broadcasting headers, to get a
|
||||
// competitive advantage.
|
||||
pindexNew->nSequenceId = 0;
|
||||
BlockMap::iterator mi = mapBlockIndex.insert(std::make_pair(hash, pindexNew)).first;
|
||||
BlockMap::iterator mi = m_block_index.insert(std::make_pair(hash, pindexNew)).first;
|
||||
pindexNew->phashBlock = &((*mi).first);
|
||||
BlockMap::iterator miPrev = mapBlockIndex.find(block.hashPrevBlock);
|
||||
if (miPrev != mapBlockIndex.end())
|
||||
BlockMap::iterator miPrev = m_block_index.find(block.hashPrevBlock);
|
||||
if (miPrev != m_block_index.end())
|
||||
{
|
||||
pindexNew->pprev = (*miPrev).second;
|
||||
pindexNew->nHeight = pindexNew->pprev->nHeight + 1;
|
||||
@@ -2852,17 +2852,17 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi
|
||||
if (m_chain.Tip() == nullptr || !setBlockIndexCandidates.value_comp()(pindex, m_chain.Tip())) {
|
||||
setBlockIndexCandidates.insert(pindex);
|
||||
}
|
||||
std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = mapBlocksUnlinked.equal_range(pindex);
|
||||
std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = m_blockman.m_blocks_unlinked.equal_range(pindex);
|
||||
while (range.first != range.second) {
|
||||
std::multimap<CBlockIndex*, CBlockIndex*>::iterator it = range.first;
|
||||
queue.push_back(it->second);
|
||||
range.first++;
|
||||
mapBlocksUnlinked.erase(it);
|
||||
m_blockman.m_blocks_unlinked.erase(it);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (pindexNew->pprev && pindexNew->pprev->IsValid(BLOCK_VALID_TREE)) {
|
||||
mapBlocksUnlinked.insert(std::make_pair(pindexNew->pprev, pindexNew));
|
||||
m_blockman.m_blocks_unlinked.insert(std::make_pair(pindexNew->pprev, pindexNew));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3230,15 +3230,15 @@ static bool ContextualCheckBlock(const CBlock& block, CValidationState& state, c
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex)
|
||||
bool BlockManager::AcceptBlockHeader(const CBlockHeader& block, CValidationState& state, const CChainParams& chainparams, CBlockIndex** ppindex)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
// Check for duplicate
|
||||
uint256 hash = block.GetHash();
|
||||
BlockMap::iterator miSelf = mapBlockIndex.find(hash);
|
||||
BlockMap::iterator miSelf = m_block_index.find(hash);
|
||||
CBlockIndex *pindex = nullptr;
|
||||
if (hash != chainparams.GetConsensus().hashGenesisBlock) {
|
||||
if (miSelf != mapBlockIndex.end()) {
|
||||
if (miSelf != m_block_index.end()) {
|
||||
// Block header is already known.
|
||||
pindex = miSelf->second;
|
||||
if (ppindex)
|
||||
@@ -3253,8 +3253,8 @@ bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState&
|
||||
|
||||
// Get prev block index
|
||||
CBlockIndex* pindexPrev = nullptr;
|
||||
BlockMap::iterator mi = mapBlockIndex.find(block.hashPrevBlock);
|
||||
if (mi == mapBlockIndex.end())
|
||||
BlockMap::iterator mi = m_block_index.find(block.hashPrevBlock);
|
||||
if (mi == m_block_index.end())
|
||||
return state.Invalid(ValidationInvalidReason::BLOCK_MISSING_PREV, error("%s: prev block not found", __func__), 0, "prev-blk-not-found");
|
||||
pindexPrev = (*mi).second;
|
||||
if (pindexPrev->nStatus & BLOCK_FAILED_MASK)
|
||||
@@ -3306,8 +3306,6 @@ bool CChainState::AcceptBlockHeader(const CBlockHeader& block, CValidationState&
|
||||
if (ppindex)
|
||||
*ppindex = pindex;
|
||||
|
||||
CheckBlockIndex(chainparams.GetConsensus());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3319,7 +3317,10 @@ bool ProcessNewBlockHeaders(const std::vector<CBlockHeader>& headers, CValidatio
|
||||
LOCK(cs_main);
|
||||
for (const CBlockHeader& header : headers) {
|
||||
CBlockIndex *pindex = nullptr; // Use a temp pindex instead of ppindex to avoid a const_cast
|
||||
if (!::ChainstateActive().AcceptBlockHeader(header, state, chainparams, &pindex)) {
|
||||
bool accepted = g_blockman.AcceptBlockHeader(header, state, chainparams, &pindex);
|
||||
::ChainstateActive().CheckBlockIndex(chainparams.GetConsensus());
|
||||
|
||||
if (!accepted) {
|
||||
if (first_invalid) *first_invalid = header;
|
||||
return false;
|
||||
}
|
||||
@@ -3362,7 +3363,10 @@ bool CChainState::AcceptBlock(const std::shared_ptr<const CBlock>& pblock, CVali
|
||||
CBlockIndex *pindexDummy = nullptr;
|
||||
CBlockIndex *&pindex = ppindex ? *ppindex : pindexDummy;
|
||||
|
||||
if (!AcceptBlockHeader(block, state, chainparams, &pindex))
|
||||
bool accepted_header = m_blockman.AcceptBlockHeader(block, state, chainparams, &pindex);
|
||||
CheckBlockIndex(chainparams.GetConsensus());
|
||||
|
||||
if (!accepted_header)
|
||||
return false;
|
||||
|
||||
// Try to process all requested blocks that we don't have, but only
|
||||
@@ -3513,7 +3517,7 @@ void PruneOneBlockFile(const int fileNumber)
|
||||
{
|
||||
LOCK(cs_LastBlockFile);
|
||||
|
||||
for (const auto& entry : mapBlockIndex) {
|
||||
for (const auto& entry : g_blockman.m_block_index) {
|
||||
CBlockIndex* pindex = entry.second;
|
||||
if (pindex->nFile == fileNumber) {
|
||||
pindex->nStatus &= ~BLOCK_HAVE_DATA;
|
||||
@@ -3523,16 +3527,16 @@ void PruneOneBlockFile(const int fileNumber)
|
||||
pindex->nUndoPos = 0;
|
||||
setDirtyBlockIndex.insert(pindex);
|
||||
|
||||
// Prune from mapBlocksUnlinked -- any block we prune would have
|
||||
// Prune from m_blocks_unlinked -- any block we prune would have
|
||||
// to be downloaded again in order to consider its chain, at which
|
||||
// point it would be considered as a candidate for
|
||||
// mapBlocksUnlinked or setBlockIndexCandidates.
|
||||
std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = mapBlocksUnlinked.equal_range(pindex->pprev);
|
||||
// m_blocks_unlinked or setBlockIndexCandidates.
|
||||
auto range = g_blockman.m_blocks_unlinked.equal_range(pindex->pprev);
|
||||
while (range.first != range.second) {
|
||||
std::multimap<CBlockIndex *, CBlockIndex *>::iterator _it = range.first;
|
||||
range.first++;
|
||||
if (_it->second == pindex) {
|
||||
mapBlocksUnlinked.erase(_it);
|
||||
g_blockman.m_blocks_unlinked.erase(_it);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3681,7 +3685,7 @@ fs::path GetBlockPosFilename(const FlatFilePos &pos)
|
||||
return BlockFileSeq().FileName(pos);
|
||||
}
|
||||
|
||||
CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash)
|
||||
CBlockIndex * BlockManager::InsertBlockIndex(const uint256& hash)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
||||
@@ -3689,19 +3693,19 @@ CBlockIndex * CChainState::InsertBlockIndex(const uint256& hash)
|
||||
return nullptr;
|
||||
|
||||
// Return existing
|
||||
BlockMap::iterator mi = mapBlockIndex.find(hash);
|
||||
if (mi != mapBlockIndex.end())
|
||||
BlockMap::iterator mi = m_block_index.find(hash);
|
||||
if (mi != m_block_index.end())
|
||||
return (*mi).second;
|
||||
|
||||
// Create new
|
||||
CBlockIndex* pindexNew = new CBlockIndex();
|
||||
mi = mapBlockIndex.insert(std::make_pair(hash, pindexNew)).first;
|
||||
mi = m_block_index.insert(std::make_pair(hash, pindexNew)).first;
|
||||
pindexNew->phashBlock = &((*mi).first);
|
||||
|
||||
return pindexNew;
|
||||
}
|
||||
|
||||
bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree)
|
||||
bool BlockManager::LoadBlockIndex(const Consensus::Params& consensus_params, CBlockTreeDB& blocktree)
|
||||
{
|
||||
if (!blocktree.LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }))
|
||||
return false;
|
||||
@@ -3729,7 +3733,7 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
|
||||
pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx;
|
||||
} else {
|
||||
pindex->nChainTx = 0;
|
||||
mapBlocksUnlinked.insert(std::make_pair(pindex->pprev, pindex));
|
||||
m_blocks_unlinked.insert(std::make_pair(pindex->pprev, pindex));
|
||||
}
|
||||
} else {
|
||||
pindex->nChainTx = pindex->nTx;
|
||||
@@ -3740,7 +3744,7 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
|
||||
setDirtyBlockIndex.insert(pindex);
|
||||
}
|
||||
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->HaveTxsDownloaded() || pindex->pprev == nullptr))
|
||||
setBlockIndexCandidates.insert(pindex);
|
||||
::ChainstateActive().setBlockIndexCandidates.insert(pindex);
|
||||
if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork))
|
||||
pindexBestInvalid = pindex;
|
||||
if (pindex->pprev)
|
||||
@@ -3752,9 +3756,20 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
|
||||
return true;
|
||||
}
|
||||
|
||||
void BlockManager::Unload() {
|
||||
m_failed_blocks.clear();
|
||||
m_blocks_unlinked.clear();
|
||||
|
||||
for (const BlockMap::value_type& entry : m_block_index) {
|
||||
delete entry.second;
|
||||
}
|
||||
|
||||
m_block_index.clear();
|
||||
}
|
||||
|
||||
bool static LoadBlockIndexDB(const CChainParams& chainparams) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
|
||||
{
|
||||
if (!::ChainstateActive().LoadBlockIndex(chainparams.GetConsensus(), *pblocktree))
|
||||
if (!g_blockman.LoadBlockIndex(chainparams.GetConsensus(), *pblocktree))
|
||||
return false;
|
||||
|
||||
// Load block file info
|
||||
@@ -4051,10 +4066,10 @@ void CChainState::EraseBlockData(CBlockIndex* index)
|
||||
setDirtyBlockIndex.insert(index);
|
||||
// Update indexes
|
||||
setBlockIndexCandidates.erase(index);
|
||||
std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> ret = mapBlocksUnlinked.equal_range(index->pprev);
|
||||
auto ret = m_blockman.m_blocks_unlinked.equal_range(index->pprev);
|
||||
while (ret.first != ret.second) {
|
||||
if (ret.first->second == index) {
|
||||
mapBlocksUnlinked.erase(ret.first++);
|
||||
m_blockman.m_blocks_unlinked.erase(ret.first++);
|
||||
} else {
|
||||
++ret.first;
|
||||
}
|
||||
@@ -4180,7 +4195,6 @@ bool RewindBlockIndex(const CChainParams& params) {
|
||||
|
||||
void CChainState::UnloadBlockIndex() {
|
||||
nBlockSequenceId = 1;
|
||||
m_failed_blocks.clear();
|
||||
setBlockIndexCandidates.clear();
|
||||
}
|
||||
|
||||
@@ -4191,10 +4205,10 @@ void UnloadBlockIndex()
|
||||
{
|
||||
LOCK(cs_main);
|
||||
::ChainActive().SetTip(nullptr);
|
||||
g_blockman.Unload();
|
||||
pindexBestInvalid = nullptr;
|
||||
pindexBestHeader = nullptr;
|
||||
mempool.clear();
|
||||
mapBlocksUnlinked.clear();
|
||||
vinfoBlockFile.clear();
|
||||
nLastBlockFile = 0;
|
||||
setDirtyBlockIndex.clear();
|
||||
@@ -4203,11 +4217,6 @@ void UnloadBlockIndex()
|
||||
for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) {
|
||||
warningcache[b].clear();
|
||||
}
|
||||
|
||||
for (const BlockMap::value_type& entry : mapBlockIndex) {
|
||||
delete entry.second;
|
||||
}
|
||||
mapBlockIndex.clear();
|
||||
fHavePruned = false;
|
||||
|
||||
::ChainstateActive().UnloadBlockIndex();
|
||||
@@ -4251,7 +4260,7 @@ bool CChainState::LoadGenesisBlock(const CChainParams& chainparams)
|
||||
FlatFilePos blockPos = SaveBlockToDisk(block, 0, chainparams, nullptr);
|
||||
if (blockPos.IsNull())
|
||||
return error("%s: writing genesis block to disk failed", __func__);
|
||||
CBlockIndex *pindex = AddToBlockIndex(block);
|
||||
CBlockIndex *pindex = m_blockman.AddToBlockIndex(block);
|
||||
ReceivedBlockTransactions(block, pindex, blockPos, chainparams.GetConsensus());
|
||||
} catch (const std::runtime_error& e) {
|
||||
return error("%s: failed to write genesis block: %s", __func__, e.what());
|
||||
@@ -4482,13 +4491,13 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
|
||||
}
|
||||
// If some parent is missing, then it could be that this block was in
|
||||
// setBlockIndexCandidates but had to be removed because of the missing data.
|
||||
// In this case it must be in mapBlocksUnlinked -- see test below.
|
||||
// In this case it must be in m_blocks_unlinked -- see test below.
|
||||
}
|
||||
} else { // If this block sorts worse than the current tip or some ancestor's block has never been seen, it cannot be in setBlockIndexCandidates.
|
||||
assert(setBlockIndexCandidates.count(pindex) == 0);
|
||||
}
|
||||
// Check whether this block is in mapBlocksUnlinked.
|
||||
std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeUnlinked = mapBlocksUnlinked.equal_range(pindex->pprev);
|
||||
// Check whether this block is in m_blocks_unlinked.
|
||||
std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeUnlinked = m_blockman.m_blocks_unlinked.equal_range(pindex->pprev);
|
||||
bool foundInUnlinked = false;
|
||||
while (rangeUnlinked.first != rangeUnlinked.second) {
|
||||
assert(rangeUnlinked.first->first == pindex->pprev);
|
||||
@@ -4499,22 +4508,22 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
|
||||
rangeUnlinked.first++;
|
||||
}
|
||||
if (pindex->pprev && (pindex->nStatus & BLOCK_HAVE_DATA) && pindexFirstNeverProcessed != nullptr && pindexFirstInvalid == nullptr) {
|
||||
// If this block has block data available, some parent was never received, and has no invalid parents, it must be in mapBlocksUnlinked.
|
||||
// If this block has block data available, some parent was never received, and has no invalid parents, it must be in m_blocks_unlinked.
|
||||
assert(foundInUnlinked);
|
||||
}
|
||||
if (!(pindex->nStatus & BLOCK_HAVE_DATA)) assert(!foundInUnlinked); // Can't be in mapBlocksUnlinked if we don't HAVE_DATA
|
||||
if (pindexFirstMissing == nullptr) assert(!foundInUnlinked); // We aren't missing data for any parent -- cannot be in mapBlocksUnlinked.
|
||||
if (!(pindex->nStatus & BLOCK_HAVE_DATA)) assert(!foundInUnlinked); // Can't be in m_blocks_unlinked if we don't HAVE_DATA
|
||||
if (pindexFirstMissing == nullptr) assert(!foundInUnlinked); // We aren't missing data for any parent -- cannot be in m_blocks_unlinked.
|
||||
if (pindex->pprev && (pindex->nStatus & BLOCK_HAVE_DATA) && pindexFirstNeverProcessed == nullptr && pindexFirstMissing != nullptr) {
|
||||
// We HAVE_DATA for this block, have received data for all parents at some point, but we're currently missing data for some parent.
|
||||
assert(fHavePruned); // We must have pruned.
|
||||
// This block may have entered mapBlocksUnlinked if:
|
||||
// This block may have entered m_blocks_unlinked if:
|
||||
// - it has a descendant that at some point had more work than the
|
||||
// tip, and
|
||||
// - we tried switching to that descendant but were missing
|
||||
// data for some intermediate block between m_chain and the
|
||||
// tip.
|
||||
// So if this block is itself better than m_chain.Tip() and it wasn't in
|
||||
// setBlockIndexCandidates, then it must be in mapBlocksUnlinked.
|
||||
// setBlockIndexCandidates, then it must be in m_blocks_unlinked.
|
||||
if (!CBlockIndexWorkComparator()(pindex, m_chain.Tip()) && setBlockIndexCandidates.count(pindex) == 0) {
|
||||
if (pindexFirstInvalid == nullptr) {
|
||||
assert(foundInUnlinked);
|
||||
|
||||
Reference in New Issue
Block a user