Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 3,043 Lines • ▼ Show 20 Lines | while (true) { | ||||
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); | ||||
markblundeberg: Essentially, every time we call DisconnectTip we ought to rescan the entire block index and… | |||||
// 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, | ||||
// and we're not doing a very deep invalidation (in which case | // and we're not doing a very deep invalidation (in which case | ||||
// keeping the mempool up to date is probably futile anyway). | // keeping the mempool up to date is probably futile anyway). | ||||
disconnectpool.updateMempoolForReorg( | disconnectpool.updateMempoolForReorg( | ||||
config, /* fAddToMempool = */ (++disconnected <= 10) && ret); | config, /* fAddToMempool = */ (++disconnected <= 10) && ret); | ||||
Show All 32 Lines | while (true) { | ||||
setDirtyBlockIndex.insert(to_mark_failed_or_parked); | setDirtyBlockIndex.insert(to_mark_failed_or_parked); | ||||
} | } | ||||
// Track the last disconnected block, so we can correct its | // Track the last disconnected block, so we can correct its | ||||
// BLOCK_FAILED_CHILD status in future iterations, or, if it's the last | // BLOCK_FAILED_CHILD status in future iterations, or, if it's the last | ||||
// one, call InvalidChainFound on it. | // one, call InvalidChainFound on it. | ||||
to_mark_failed_or_parked = invalid_walk_tip; | to_mark_failed_or_parked = invalid_walk_tip; | ||||
// Block index must always be in a good state before we unlock cs_main. | |||||
CheckBlockIndex(config.GetChainParams().GetConsensus()); | |||||
} | } | ||||
{ | { | ||||
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; | ||||
Show All 19 Lines | while (true) { | ||||
!setBlockIndexCandidates.value_comp()(i, chainActive.Tip())) { | !setBlockIndexCandidates.value_comp()(i, chainActive.Tip())) { | ||||
setBlockIndexCandidates.insert(i); | setBlockIndexCandidates.insert(i); | ||||
} | } | ||||
} | } | ||||
if (invalidate) { | if (invalidate) { | ||||
InvalidChainFound(to_mark_failed_or_parked); | InvalidChainFound(to_mark_failed_or_parked); | ||||
} | } | ||||
// Block index must always be in a good state before we unlock cs_main. | |||||
CheckBlockIndex(config.GetChainParams().GetConsensus()); | |||||
} | } | ||||
// Only notify about a new block tip if the active chain was modified. | // Only notify about a new block tip if the active chain was modified. | ||||
if (pindex_was_in_chain) { | 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; | ||||
▲ Show 20 Lines • Show All 2,564 Lines • Show Last 20 Lines |
Essentially, every time we call DisconnectTip we ought to rescan the entire block index and find blocks that have enough chainwork and add them to setBlockIndexCandidates, before we unlock cs_main.
This unfortunately seems to be a very time consuming thing if we are rewinding many blocks, but on the other hand, hardly anyone ever calls invalidateblock / parkblock RPCs so it's more important to be correct than to be broken and efficient.