aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2019-03-03 13:01:26 -0800
committerPieter Wuille <pieter.wuille@gmail.com>2019-03-03 13:01:26 -0800
commit519b0bc5dc5155b6f7e2362c2105552bb7618ad0 (patch)
tree8601e0a0d0816d2ebe6e7cf093d2e3cef0e4ce5d
parent8d220417cd7bc34464e28a4861a885193ec091c2 (diff)
downloadbitcoin-519b0bc5dc5155b6f7e2362c2105552bb7618ad0.tar.xz
Make last disconnected block BLOCK_FAILED_VALID, even when aborted
-rw-r--r--src/validation.cpp15
1 files changed, 10 insertions, 5 deletions
diff --git a/src/validation.cpp b/src/validation.cpp
index c112fbdcc0..55fd8d99a2 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -2829,25 +2829,30 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
// and be left unable to start as they have no tip candidates (as there
// are no blocks that meet the "have data and are not invalid per
// nStatus" criteria for inclusion in setBlockIndexCandidates).
- invalid_walk_tip->nStatus |= BLOCK_FAILED_CHILD;
+ invalid_walk_tip->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(invalid_walk_tip);
setBlockIndexCandidates.erase(invalid_walk_tip);
setBlockIndexCandidates.insert(invalid_walk_tip->pprev);
+ if (invalid_walk_tip->pprev == to_mark_failed && (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;
+ setDirtyBlockIndex.insert(to_mark_failed);
+ }
- // If we abort invalidation after this iteration, make sure
- // the last disconnected block gets marked failed (rather than
- // just child of failed)
+ // 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.
to_mark_failed = invalid_walk_tip;
}
{
- // Mark pindex (or the last disconnected block) as invalid, regardless of whether it was in the main chain or not.
LOCK(cs_main);
if (chainActive.Contains(to_mark_failed)) {
// If the to-be-marked invalid block is in the active chain, something is interfering and we can't proceed.
return false;
}
+ // Mark pindex (or the last disconnected block) as invalid, even when it never was in the main chain
to_mark_failed->nStatus |= BLOCK_FAILED_VALID;
setDirtyBlockIndex.insert(to_mark_failed);
setBlockIndexCandidates.erase(to_mark_failed);