Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 3,070 Lines • ▼ Show 20 Lines | bool PreciousBlock(const Config &config, CValidationState &state, | ||||
return g_chainstate.PreciousBlock(config, state, pindex); | return g_chainstate.PreciousBlock(config, state, pindex); | ||||
} | } | ||||
bool CChainState::UnwindBlock(const Config &config, CValidationState &state, | bool CChainState::UnwindBlock(const Config &config, CValidationState &state, | ||||
CBlockIndex *pindex, bool invalidate) { | CBlockIndex *pindex, bool invalidate) { | ||||
CBlockIndex *to_mark_failed = pindex; | CBlockIndex *to_mark_failed = pindex; | ||||
bool pindex_was_in_chain = false; | bool pindex_was_in_chain = false; | ||||
int disconnected = 0; | |||||
// Disconnect (descendants of) pindex, and mark them invalid. | // Disconnect (descendants of) pindex, and mark them invalid. | ||||
while (true) { | while (true) { | ||||
if (ShutdownRequested()) break; | if (ShutdownRequested()) break; | ||||
// Make sure the queue of validation callbacks doesn't grow unboundedly. | // Make sure the queue of validation callbacks doesn't grow unboundedly. | ||||
LimitValidationInterfaceQueue(); | LimitValidationInterfaceQueue(); | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
if (!chainActive.Contains(pindex)) break; | if (!chainActive.Contains(pindex)) break; | ||||
pindex_was_in_chain = true; | pindex_was_in_chain = true; | ||||
CBlockIndex *invalid_walk_tip = chainActive.Tip(); | CBlockIndex *invalid_walk_tip = chainActive.Tip(); | ||||
// ActivateBestChain considers blocks already in chainActive | // ActivateBestChain considers blocks already in chainActive | ||||
// unconditionally valid already, so force disconnect away from it. | // unconditionally valid already, so force disconnect away from it. | ||||
DisconnectedBlockTransactions disconnectpool; | DisconnectedBlockTransactions disconnectpool; | ||||
bool ret = DisconnectTip(config, state, &disconnectpool); | bool ret = DisconnectTip(config, state, &disconnectpool); | ||||
// DisconnectTip will add transactions to disconnectpool. | // DisconnectTip will add transactions to disconnectpool. | ||||
// Adjust the mempool to be consistent with the new tip, adding | // Adjust the mempool to be consistent with the new tip, adding | ||||
// transactions back to the mempool if disconnecting was successful. | // transactions back to the mempool if disconnecting was successful, | ||||
disconnectpool.updateMempoolForReorg(config, /* fAddToMempool = */ ret); | // and we're not doing a very deep invalidation (in which case | ||||
// keeping the mempool up to date is probably futile anyway). | |||||
disconnectpool.updateMempoolForReorg( | |||||
config, /* fAddToMempool = */ (++disconnected <= 10) && ret); | |||||
if (!ret) return false; | if (!ret) return false; | ||||
assert(invalid_walk_tip->pprev == chainActive.Tip()); | assert(invalid_walk_tip->pprev == chainActive.Tip()); | ||||
// 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). | ||||
▲ Show 20 Lines • Show All 2,629 Lines • Show Last 20 Lines |