From afc32c5eeada01b141706e32f0405bdb86c00f04 Mon Sep 17 00:00:00 2001 From: Pieter Wuille Date: Fri, 10 Oct 2014 13:13:47 -0700 Subject: Fix rebuild-chainstate feature and improve its performance Previous refactorings broke the ability to rebuild the chainstate by deleting the chainstate directory, resulting in an incorrect "Incorrect or no genesis block found" error message. Fix that. Also, improve the performance of ActivateBestBlockStep by using the skiplist to only discover a few potential blocks to connect at a time, instead of all blocks forever - as we likely bail out after connecting a single one anyway. --- src/main.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp index 908f4c95b..0612f584a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1968,12 +1968,20 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo // Build list of new blocks to connect. std::vector vpindexToConnect; - vpindexToConnect.reserve(pindexMostWork->nHeight - (pindexFork ? pindexFork->nHeight : -1)); - CBlockIndex *pindexIter = pindexMostWork; - while (pindexIter && pindexIter != pindexFork) { + bool fContinue = true; + int nHeight = pindexFork ? pindexFork->nHeight : -1; + while (fContinue && nHeight != pindexMostWork->nHeight) { + // Don't iterate the entire list of potential improvements toward the best tip, as we likely only need + // a few blocks along the way. + int nTargetHeight = std::min(nHeight + 32, pindexMostWork->nHeight); + vpindexToConnect.clear(); + vpindexToConnect.reserve(nTargetHeight - nHeight); + CBlockIndex *pindexIter = pindexMostWork->GetAncestor(nTargetHeight); + while (pindexIter && pindexIter->nHeight != nHeight) { vpindexToConnect.push_back(pindexIter); pindexIter = pindexIter->pprev; } + nHeight = nTargetHeight; // Connect new blocks. BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { @@ -1984,6 +1992,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo InvalidChainFound(vpindexToConnect.back()); state = CValidationState(); fInvalidFound = true; + fContinue = false; break; } else { // A system error occurred (disk space, database error, ...). @@ -2001,10 +2010,12 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo assert(!setBlockIndexCandidates.empty()); if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) { // We're in a better position than we were. Return temporarily to release the lock. + fContinue = false; break; } } } + } // Callbacks/notifications for a new best chain. if (fInvalidFound) -- cgit v1.2.3