@@ -2792,6 +2792,8 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
27922792 // work as we go.
27932793 std::multimap<const arith_uint256, CBlockIndex *> candidate_blocks_by_work;
27942794
2795+ std::set<CBlockIndex *> failed_valid_descendants;
2796+
27952797 {
27962798 LOCK (cs_main);
27972799 for (const auto & entry : m_blockman.m_block_index ) {
@@ -2801,11 +2803,12 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
28012803 // as we disconnect.
28022804 // Instead, consider only non-active-chain blocks that have at
28032805 // least as much work as where we expect the new tip to end up.
2804- if (!m_chain.Contains (candidate) &&
2805- !CBlockIndexWorkComparator ()(candidate, pindex->pprev ) &&
2806- candidate->IsValid (BLOCK_VALID_TRANSACTIONS) &&
2807- candidate->HaveTxsDownloaded ()) {
2808- candidate_blocks_by_work.insert (std::make_pair (candidate->nChainWork , candidate));
2806+ if (!m_chain.Contains (candidate) && !CBlockIndexWorkComparator ()(candidate, pindex->pprev )) {
2807+ if (candidate->IsValid (BLOCK_VALID_TRANSACTIONS) && candidate->HaveTxsDownloaded ()) {
2808+ candidate_blocks_by_work.insert (std::make_pair (candidate->nChainWork , candidate));
2809+ } else if ((candidate->nStatus & BLOCK_FAILED_VALID) && candidate->GetAncestor (pindex->nHeight ) == pindex) {
2810+ failed_valid_descendants.insert (candidate);
2811+ }
28092812 }
28102813 }
28112814 }
@@ -2863,6 +2866,15 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
28632866 }
28642867 }
28652868
2869+ for (auto candidate_descendant_it = failed_valid_descendants.begin (); candidate_descendant_it != failed_valid_descendants.end (); ) {
2870+ if ((*candidate_descendant_it)->nHeight > invalid_walk_tip->nHeight && (*candidate_descendant_it)->GetAncestor (invalid_walk_tip->nHeight ) == invalid_walk_tip) {
2871+ (*candidate_descendant_it)->nStatus = ((*candidate_descendant_it)->nStatus ^ BLOCK_FAILED_VALID) | BLOCK_FAILED_CHILD;
2872+ candidate_descendant_it = failed_valid_descendants.erase (candidate_descendant_it);
2873+ } else {
2874+ ++candidate_descendant_it;
2875+ }
2876+ }
2877+
28662878 // Track the last disconnected block, so we can correct its BLOCK_FAILED_CHILD status in future
28672879 // iterations, or, if it's the last one, call InvalidChainFound on it.
28682880 to_mark_failed = invalid_walk_tip;
@@ -4652,6 +4664,11 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
46524664 if (pindexFirstInvalid == nullptr ) {
46534665 // Checks for not-invalid blocks.
46544666 assert ((pindex->nStatus & BLOCK_FAILED_MASK) == 0 ); // The failed mask cannot be set for blocks without invalid parents.
4667+ } else if (pindexFirstInvalid != pindex) {
4668+ // If a parent is invalid, we may be BLOCK_FAILED_CHILD (though no guarantee thereof),
4669+ // but we must not be BLOCK_FAILED_VALID (as we shouldn't have attempted to connect
4670+ // this block in the first place).
4671+ assert ((pindex->nStatus & BLOCK_FAILED_VALID) == 0 );
46554672 }
46564673 if (!CBlockIndexWorkComparator ()(pindex, m_chain.Tip ()) && pindexFirstNeverProcessed == nullptr ) {
46574674 if (pindexFirstInvalid == nullptr ) {
0 commit comments