Move erasure of non-active blocks to a separate loop in RewindBlockIndex

This lets us simplify the iteration to just walking back in the chain,
rather than looping over all of mapBlockIndex.
This commit is contained in:
Pieter Wuille 2019-02-24 12:36:07 -08:00
parent 9d6dcc52c6
commit 32b2696ab4

View file

@ -4209,9 +4209,18 @@ void CChainState::EraseBlockData(CBlockIndex* index)
bool CChainState::RewindBlockIndex(const CChainParams& params)
{
LOCK(cs_main);
// Note that during -reindex-chainstate we are called with an empty chainActive!
// First erase all post-segwit blocks without witness not in the main chain,
// as this can we done without costly DisconnectTip calls. Active
// blocks will be dealt with below.
for (const auto& entry : mapBlockIndex) {
if (IsWitnessEnabled(entry.second->pprev, params.GetConsensus()) && !(entry.second->nStatus & BLOCK_OPT_WITNESS) && !chainActive.Contains(entry.second)) {
EraseBlockData(entry.second);
}
}
// Find what height we need to reorganize to.
int nHeight = 1;
while (nHeight <= chainActive.Height()) {
// Although SCRIPT_VERIFY_WITNESS is now generally enforced on all
@ -4226,6 +4235,7 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
// nHeight is now the height of the first insufficiently-validated block, or tipheight + 1
CValidationState state;
CBlockIndex* pindex = chainActive.Tip();
CBlockIndex* tip = pindex;
while (chainActive.Height() >= nHeight) {
if (fPruneMode && !(chainActive.Tip()->nStatus & BLOCK_HAVE_DATA)) {
// If pruning, don't try rewinding past the HAVE_DATA point;
@ -4248,17 +4258,16 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
// Reduce validity flag and have-data flags.
// We do this after actual disconnecting, otherwise we'll end up writing the lack of data
// to disk before writing the chainstate, resulting in a failure to continue if interrupted.
for (const auto& entry : mapBlockIndex) {
CBlockIndex* pindexIter = entry.second;
while (tip->nHeight > chainActive.Height()) {
// Note: If we encounter an insufficiently validated block that
// is on chainActive, it must be because we are a pruning node, and
// this block or some successor doesn't HAVE_DATA, so we were unable to
// rewind all the way. Blocks remaining on chainActive at this point
// must not have their validity reduced.
if (IsWitnessEnabled(pindexIter->pprev, params.GetConsensus()) && !(pindexIter->nStatus & BLOCK_OPT_WITNESS) && !chainActive.Contains(pindexIter)) {
EraseBlockData(pindexIter);
if (IsWitnessEnabled(tip->pprev, params.GetConsensus()) && !(tip->nStatus & BLOCK_OPT_WITNESS)) {
EraseBlockData(tip);
}
tip = tip->pprev;
}
if (chainActive.Tip() != nullptr) {