validation: don't update BLOCK_FAILED_VALID to BLOCK_FAILED_CHILD in InvalidateBlock
What changed, and why it matters
This commit simplifies how Bitcoin Core marks blocks as invalid. Previously, the code tried to distinguish between a block that failed validation itself and a child of a failed block, using two different status flags. The commit removes that distinction and uses one flag for both cases, because the two statuses were functionally equivalent. It is a code-cleanup change with no apparent security impact.
No security action required. Treat as routine refactoring. Reviewers may optionally verify that downstream consumers of nStatus treat BLOCK_FAILED_VALID and BLOCK_FAILED_CHILD equivalently, as the commit message asserts.
Security signals we found
No security relevance claimed by vendor
Change is described as non-functional cleanup
No validation logic, consensus rules, or cryptographic checks modified
Only block status flag bookkeeping simplified
Evidence from the diff
In Chainstate::InvalidateBlock, the code previously converted BLOCK_FAILED_VALID to BLOCK_FAILED_CHILD for the last disconnected block and for out-of-chain descendants. This commit removes the conversion logic and marks all such blocks with BLOCK_FAILED_VALID instead. The commit message explicitly states there is no functional difference between BLOCK_FAILED_VALID and BLOCK_FAILED_CHILD and that the change reduces unnecessary complexity. The patch removes 12 lines and adds 3 lines in src/validation.cpp.
Changed components
src/validation.cppChainstate::InvalidateBlockblock status flag managementInspect captured patch +3 / −12
diff --git a/src/validation.cpp b/src/validation.cpp
index c200c3d6..ab55e591 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -3637,15 +3637,8 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde
m_blockman.m_dirty_blockindex.insert(invalid_walk_tip);
setBlockIndexCandidates.erase(invalid_walk_tip);
setBlockIndexCandidates.insert(invalid_walk_tip->pprev);
- if (invalid_walk_tip == to_mark_failed->pprev && (to_mark_failed->nStatus & BLOCK_FAILED_VALID)) {
- // We only want to mark the last disconnected block as BLOCK_FAILED_VALID; its children
- // need to be BLOCK_FAILED_CHILD instead.
- to_mark_failed->nStatus = (to_mark_failed->nStatus ^ BLOCK_FAILED_VALID) | BLOCK_FAILED_CHILD;
- m_blockman.m_dirty_blockindex.insert(to_mark_failed);
- }
// Mark out-of-chain descendants of the invalidated block as invalid
- // (possibly replacing a pre-existing BLOCK_FAILED_VALID with BLOCK_FAILED_CHILD)
// Add any equal or more work headers that are not invalidated to setBlockIndexCandidates
// Recalculate m_best_header if it became invalid.
auto candidate_it = highpow_outofchain_headers.lower_bound(invalid_walk_tip->pprev->nChainWork);
@@ -3659,9 +3652,8 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde
while (candidate_it != highpow_outofchain_headers.end()) {
CBlockIndex* candidate{candidate_it->second};
if (candidate->GetAncestor(invalid_walk_tip->nHeight) == invalid_walk_tip) {
- // Children of failed blocks should be marked as BLOCK_FAILED_CHILD instead.
- candidate->nStatus &= ~BLOCK_FAILED_VALID;
- candidate->nStatus |= BLOCK_FAILED_CHILD;
+ // Children of failed blocks are marked as BLOCK_FAILED_VALID.
+ candidate->nStatus |= BLOCK_FAILED_VALID;
m_blockman.m_dirty_blockindex.insert(candidate);
// If invalidated, the block is irrelevant for setBlockIndexCandidates
// and for m_best_header and can be removed from the cache.
@@ -3682,8 +3674,7 @@ bool Chainstate::InvalidateBlock(BlockValidationState& state, CBlockIndex* pinde
++candidate_it;
}
- // Track the last disconnected block, so we can correct its BLOCK_FAILED_CHILD status in future
- // iterations, or, if it's the last one, call InvalidChainFound on it.
+ // Track the last disconnected block to call InvalidChainFound on it.
to_mark_failed = invalid_walk_tip;
}
Why this scored 18/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.