@@ -5050,19 +5050,28 @@ void ChainstateManager::CheckBlockIndex()
50505050 return ;
50515051 }
50525052
5053- // Build forward-pointing map of the entire block tree.
5053+ // Build forward-pointing data structure for the entire block tree.
5054+ // For performance reasons, indexes of the best header chain are stored in a vector (within CChain).
5055+ // All remaining blocks are stored in a multimap.
5056+ // The best header chain can differ from the active chain: E.g. its entries may belong to blocks that
5057+ // are not yet validated.
5058+ CChain best_hdr_chain;
5059+ assert (m_best_header);
5060+ best_hdr_chain.SetTip (*m_best_header);
5061+
50545062 std::multimap<CBlockIndex*,CBlockIndex*> forward;
50555063 for (auto & [_, block_index] : m_blockman.m_block_index ) {
5056- forward.emplace (block_index.pprev , &block_index);
5064+ // Only save indexes in forward that are not part of the best header chain.
5065+ if (!best_hdr_chain.Contains (&block_index)) {
5066+ // Only genesis, which must be part of the best header chain, can have a nullptr parent.
5067+ assert (block_index.pprev );
5068+ forward.emplace (block_index.pprev , &block_index);
5069+ }
50575070 }
5071+ assert (forward.size () + best_hdr_chain.Height () + 1 == m_blockman.m_block_index .size ());
50585072
5059- assert (forward.size () == m_blockman.m_block_index .size ());
5060-
5061- std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> rangeGenesis = forward.equal_range (nullptr );
5062- CBlockIndex *pindex = rangeGenesis.first ->second ;
5063- rangeGenesis.first ++;
5064- assert (rangeGenesis.first == rangeGenesis.second ); // There is only one index entry with parent nullptr.
5065-
5073+ CBlockIndex* pindex = best_hdr_chain[0 ];
5074+ assert (pindex);
50665075 // Iterate over the entire block tree, using depth-first search.
50675076 // Along the way, remember whether there are blocks on the path from genesis
50685077 // block being explored which are the first to have certain properties.
@@ -5274,14 +5283,21 @@ void ChainstateManager::CheckBlockIndex()
52745283 // assert(pindex->GetBlockHash() == pindex->GetBlockHeader().GetHash()); // Perhaps too slow
52755284 // End: actual consistency checks.
52765285
5277- // Try descending into the first subnode.
5286+
5287+ // Try descending into the first subnode. Always process forks first and the best header chain after.
52785288 snap_update_firsts ();
52795289 std::pair<std::multimap<CBlockIndex*,CBlockIndex*>::iterator,std::multimap<CBlockIndex*,CBlockIndex*>::iterator> range = forward.equal_range (pindex);
52805290 if (range.first != range.second ) {
5281- // A subnode was found.
5291+ // A subnode not part of the best header chain was found.
52825292 pindex = range.first ->second ;
52835293 nHeight++;
52845294 continue ;
5295+ } else if (best_hdr_chain.Contains (pindex)) {
5296+ // Descend further into best header chain.
5297+ nHeight++;
5298+ pindex = best_hdr_chain[nHeight];
5299+ if (!pindex) break ; // we are finished, since the best header chain is always processed last
5300+ continue ;
52855301 }
52865302 // This is a leaf node.
52875303 // Move upwards until we reach a node of which we have not yet visited the last child.
@@ -5307,9 +5323,15 @@ void ChainstateManager::CheckBlockIndex()
53075323 // Proceed to the next one.
53085324 rangePar.first ++;
53095325 if (rangePar.first != rangePar.second ) {
5310- // Move to the sibling.
5326+ // Move to a sibling not part of the best header chain .
53115327 pindex = rangePar.first ->second ;
53125328 break ;
5329+ } else if (pindexPar == best_hdr_chain[nHeight - 1 ]) {
5330+ // Move to pindex's sibling on the best-chain, if it has one.
5331+ pindex = best_hdr_chain[nHeight];
5332+ // There will not be a next block if (and only if) parent block is the best header.
5333+ assert ((pindex == nullptr ) == (pindexPar == best_hdr_chain.Tip ()));
5334+ break ;
53135335 } else {
53145336 // Move up further.
53155337 pindex = pindexPar;
@@ -5319,8 +5341,8 @@ void ChainstateManager::CheckBlockIndex()
53195341 }
53205342 }
53215343
5322- // Check that we actually traversed the entire map .
5323- assert (nNodes == forward.size ());
5344+ // Check that we actually traversed the entire block index .
5345+ assert (nNodes == forward.size () + best_hdr_chain. Height () + 1 );
53245346}
53255347
53265348std::string Chainstate::ToString ()
0 commit comments