Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 3,059 Lines • ▼ Show 20 Lines | while (true) { | ||||
// We immediately mark the disconnected blocks as invalid. | // We immediately mark the disconnected blocks as invalid. | ||||
// This prevents a case where pruned nodes may fail to invalidateblock | // This prevents a case where pruned nodes may fail to invalidateblock | ||||
// and be left unable to start as they have no tip candidates (as there | // 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 | // are no blocks that meet the "have data and are not invalid per | ||||
// nStatus" criteria for inclusion in setBlockIndexCandidates). | // nStatus" criteria for inclusion in setBlockIndexCandidates). | ||||
invalid_walk_tip->nStatus = | invalid_walk_tip->nStatus = | ||||
invalidate ? invalid_walk_tip->nStatus.withFailedParent() | invalidate ? invalid_walk_tip->nStatus.withFailed() | ||||
: invalid_walk_tip->nStatus.withParkedParent(); | : invalid_walk_tip->nStatus.withParked(); | ||||
setDirtyBlockIndex.insert(invalid_walk_tip); | setDirtyBlockIndex.insert(invalid_walk_tip); | ||||
setBlockIndexCandidates.insert(invalid_walk_tip->pprev); | setBlockIndexCandidates.insert(invalid_walk_tip->pprev); | ||||
// If we abort invalidation after this iteration, make sure | if (invalid_walk_tip->pprev == to_mark_failed_or_parked && | ||||
// the last disconnected block gets marked failed (rather than | (invalidate ? to_mark_failed_or_parked->nStatus.hasFailed() | ||||
// just child of failed) | : to_mark_failed_or_parked->nStatus.isParked())) { | ||||
// 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_or_parked->nStatus = | |||||
(invalidate | |||||
? to_mark_failed_or_parked->nStatus.withFailed(false) | |||||
.withFailedParent() | |||||
: to_mark_failed_or_parked->nStatus.withParked(false) | |||||
.withParkedParent()); | |||||
setDirtyBlockIndex.insert(to_mark_failed_or_parked); | |||||
} | |||||
// 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_or_parked = invalid_walk_tip; | to_mark_failed_or_parked = invalid_walk_tip; | ||||
} | } | ||||
{ | { | ||||
// Mark pindex (or the last disconnected block) as invalid or parked, | |||||
// regardless of whether it was in the main chain or not. | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
if (chainActive.Contains(to_mark_failed_or_parked)) { | if (chainActive.Contains(to_mark_failed_or_parked)) { | ||||
// If the to-be-marked invalid block is in the active chain, | // If the to-be-marked invalid block is in the active chain, | ||||
// something is interfering and we can't proceed. | // something is interfering and we can't proceed. | ||||
return false; | return false; | ||||
} | } | ||||
// Mark pindex (or the last disconnected block) as invalid (or parked), | |||||
// even when it never was in the main chain. | |||||
to_mark_failed_or_parked->nStatus = | to_mark_failed_or_parked->nStatus = | ||||
invalidate ? to_mark_failed_or_parked->nStatus.withFailed() | invalidate ? to_mark_failed_or_parked->nStatus.withFailed() | ||||
: to_mark_failed_or_parked->nStatus.withParked(); | : to_mark_failed_or_parked->nStatus.withParked(); | ||||
setDirtyBlockIndex.insert(to_mark_failed_or_parked); | setDirtyBlockIndex.insert(to_mark_failed_or_parked); | ||||
if (invalidate) { | if (invalidate) { | ||||
m_failed_blocks.insert(to_mark_failed_or_parked); | m_failed_blocks.insert(to_mark_failed_or_parked); | ||||
} | } | ||||
Show All 19 Lines | if (pindex_was_in_chain) { | ||||
uiInterface.NotifyBlockTip(IsInitialBlockDownload(), | uiInterface.NotifyBlockTip(IsInitialBlockDownload(), | ||||
to_mark_failed_or_parked->pprev); | to_mark_failed_or_parked->pprev); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool FinalizeBlockAndInvalidate(const Config &config, CValidationState &state, | bool FinalizeBlockAndInvalidate(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindex) { | CBlockIndex *pindex) { | ||||
AssertLockHeld(cs_main); | CBlockIndex *pindexToInvalidate; | ||||
{ | |||||
LOCK(cs_main); | |||||
if (!FinalizeBlockInternal(config, state, pindex)) { | if (!FinalizeBlockInternal(config, state, pindex)) { | ||||
// state is set by FinalizeBlockInternal. | // state is set by FinalizeBlockInternal. | ||||
return false; | return false; | ||||
} | } | ||||
// We have a valid candidate, make sure it is not parked. | // We have a valid candidate, make sure it is not parked. | ||||
if (pindex->nStatus.isOnParkedChain()) { | if (pindex->nStatus.isOnParkedChain()) { | ||||
UnparkBlock(pindex); | UnparkBlock(pindex); | ||||
} | } | ||||
// If the finalized block is not on the active chain, we need to rewind. | // If the finalized block is not on the active chain, we need to rewind. | ||||
if (!AreOnTheSameFork(pindex, chainActive.Tip())) { | if (AreOnTheSameFork(pindex, chainActive.Tip())) { | ||||
return true; | |||||
} | |||||
const CBlockIndex *pindexFork = chainActive.FindFork(pindex); | const CBlockIndex *pindexFork = chainActive.FindFork(pindex); | ||||
CBlockIndex *pindexToInvalidate = | pindexToInvalidate = | ||||
chainActive.Tip()->GetAncestor(pindexFork->nHeight + 1); | chainActive.Tip()->GetAncestor(pindexFork->nHeight + 1); | ||||
return InvalidateBlock(config, state, pindexToInvalidate); | |||||
} | } | ||||
return true; | return InvalidateBlock(config, state, pindexToInvalidate); | ||||
} | } | ||||
bool InvalidateBlock(const Config &config, CValidationState &state, | bool InvalidateBlock(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindex) { | CBlockIndex *pindex) { | ||||
return g_chainstate.UnwindBlock(config, state, pindex, true); | return g_chainstate.UnwindBlock(config, state, pindex, true); | ||||
} | } | ||||
bool ParkBlock(const Config &config, CValidationState &state, | bool ParkBlock(const Config &config, CValidationState &state, | ||||
▲ Show 20 Lines • Show All 2,533 Lines • Show Last 20 Lines |