diff --git a/src/validation.cpp b/src/validation.cpp index df690f2548b..067e9b1695f 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -3690,7 +3690,7 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde // To avoid walking the block index repeatedly in search of candidates, // build a map once so that we can look up candidate blocks by chain // work as we go. - std::multimap candidate_blocks_by_work; + std::multimap highpow_outofchain_headers; { LOCK(cs_main); @@ -3699,13 +3699,12 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde // We don't need to put anything in our active chain into the // multimap, because those candidates will be found and considered // as we disconnect. - // Instead, consider only non-active-chain blocks that have at - // least as much work as where we expect the new tip to end up. + // Instead, consider only non-active-chain blocks that score + // at least as good with CBlockIndexWorkComparator as the new tip. if (!m_chain.Contains(candidate) && - !CBlockIndexWorkComparator()(candidate, pindex->pprev) && - candidate->IsValid(BLOCK_VALID_TRANSACTIONS) && - candidate->HaveNumChainTxs()) { - candidate_blocks_by_work.insert(std::make_pair(candidate->nChainWork, candidate)); + !CBlockIndexWorkComparator()(candidate, pindex->pprev) && + !(candidate->nStatus & BLOCK_FAILED_MASK)) { + highpow_outofchain_headers.insert({candidate->nChainWork, candidate}); } } } @@ -3755,11 +3754,14 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde } // Add any equal or more work headers to setBlockIndexCandidates - auto candidate_it = candidate_blocks_by_work.lower_bound(invalid_walk_tip->pprev->nChainWork); - while (candidate_it != candidate_blocks_by_work.end()) { - if (!CBlockIndexWorkComparator()(candidate_it->second, invalid_walk_tip->pprev)) { - setBlockIndexCandidates.insert(candidate_it->second); - candidate_it = candidate_blocks_by_work.erase(candidate_it); + auto candidate_it = highpow_outofchain_headers.lower_bound(invalid_walk_tip->pprev->nChainWork); + while (candidate_it != highpow_outofchain_headers.end()) { + CBlockIndex* candidate{candidate_it->second}; + if (!CBlockIndexWorkComparator()(candidate, invalid_walk_tip->pprev) && + candidate->IsValid(BLOCK_VALID_TRANSACTIONS) && + candidate->HaveNumChainTxs()) { + setBlockIndexCandidates.insert(candidate); + candidate_it = highpow_outofchain_headers.erase(candidate_it); } else { ++candidate_it; }