Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 2,823 Lines • ▼ Show 20 Lines | static void NotifyHeaderTip() LOCKS_EXCLUDED(cs_main) { | ||||
} | } | ||||
// Send block tip changed notifications without cs_main | // Send block tip changed notifications without cs_main | ||||
if (fNotify) { | if (fNotify) { | ||||
uiInterface.NotifyHeaderTip(fInitialBlockDownload, pindexHeader); | uiInterface.NotifyHeaderTip(fInitialBlockDownload, pindexHeader); | ||||
} | } | ||||
} | } | ||||
static void LimitValidationInterfaceQueue() { | |||||
AssertLockNotHeld(cs_main); | |||||
if (GetMainSignals().CallbacksPending() > 10) { | |||||
SyncWithValidationInterfaceQueue(); | |||||
} | |||||
} | |||||
/** | /** | ||||
* Make the best chain active, in multiple steps. The result is either failure | * Make the best chain active, in multiple steps. The result is either failure | ||||
* or an activated best chain. pblock is either nullptr or a pointer to a block | * or an activated best chain. pblock is either nullptr or a pointer to a block | ||||
* that is already loaded (to avoid loading it again from disk). | * that is already loaded (to avoid loading it again from disk). | ||||
* | * | ||||
* ActivateBestChain is split into steps (see ActivateBestChainStep) so that | * ActivateBestChain is split into steps (see ActivateBestChainStep) so that | ||||
* we avoid holding cs_main for an extended period of time; the length of this | * we avoid holding cs_main for an extended period of time; the length of this | ||||
* call may be quite long during reindexing or a substantial reorg. | * call may be quite long during reindexing or a substantial reorg. | ||||
Show All 18 Lines | bool CChainState::ActivateBestChain(const Config &config, | ||||
LOCK(m_cs_chainstate); | LOCK(m_cs_chainstate); | ||||
CBlockIndex *pindexMostWork = nullptr; | CBlockIndex *pindexMostWork = nullptr; | ||||
CBlockIndex *pindexNewTip = nullptr; | CBlockIndex *pindexNewTip = nullptr; | ||||
int nStopAtHeight = gArgs.GetArg("-stopatheight", DEFAULT_STOPATHEIGHT); | int nStopAtHeight = gArgs.GetArg("-stopatheight", DEFAULT_STOPATHEIGHT); | ||||
do { | do { | ||||
boost::this_thread::interruption_point(); | boost::this_thread::interruption_point(); | ||||
if (GetMainSignals().CallbacksPending() > 10) { | |||||
// Block until the validation queue drains. This should largely | // Block until the validation queue drains. This should largely | ||||
// never happen in normal operation, however may happen during | // never happen in normal operation, however may happen during | ||||
// reindex, causing memory blowup if we run too far ahead. | // reindex, causing memory blowup if we run too far ahead. | ||||
// Note that if a validationinterface callback ends up calling | // Note that if a validationinterface callback ends up calling | ||||
// ActivateBestChain this may lead to a deadlock! We should | // ActivateBestChain this may lead to a deadlock! We should | ||||
// probably have a DEBUG_LOCKORDER test for this in the future. | // probably have a DEBUG_LOCKORDER test for this in the future. | ||||
SyncWithValidationInterfaceQueue(); | LimitValidationInterfaceQueue(); | ||||
} | |||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CBlockIndex *starting_tip = chainActive.Tip(); | CBlockIndex *starting_tip = chainActive.Tip(); | ||||
bool blocks_connected = false; | bool blocks_connected = false; | ||||
do { | do { | ||||
// We absolutely may not unlock cs_main until we've made forward | // We absolutely may not unlock cs_main until we've made forward | ||||
// progress (with the exception of shutdown due to hardware | // progress (with the exception of shutdown due to hardware | ||||
▲ Show 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | bool CChainState::UnwindBlock(const Config &config, CValidationState &state, | ||||
bool pindex_was_in_chain = false; | bool pindex_was_in_chain = false; | ||||
// Disconnect (descendants of) pindex, and mark them invalid. | // Disconnect (descendants of) pindex, and mark them invalid. | ||||
while (true) { | while (true) { | ||||
if (ShutdownRequested()) { | if (ShutdownRequested()) { | ||||
break; | break; | ||||
} | } | ||||
// Make sure the queue of validation callbacks doesn't grow unboundedly. | |||||
LimitValidationInterfaceQueue(); | |||||
LOCK(cs_main); | LOCK(cs_main); | ||||
if (!chainActive.Contains(pindex)) { | if (!chainActive.Contains(pindex)) { | ||||
break; | break; | ||||
} | } | ||||
pindex_was_in_chain = true; | pindex_was_in_chain = true; | ||||
CBlockIndex *invalid_walk_tip = chainActive.Tip(); | CBlockIndex *invalid_walk_tip = chainActive.Tip(); | ||||
▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 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); | { | ||||
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 = | CBlockIndex *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,532 Lines • Show Last 20 Lines |