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.
This commit is contained in:
Pieter Wuille 2014-10-10 13:13:47 -07:00
parent 16d5194165
commit afc32c5eea
2 changed files with 15 additions and 4 deletions

View File

@ -974,7 +974,7 @@ bool AppInit2(boost::thread_group& threadGroup)
// If the loaded chain has a wrong genesis, bail out immediately // If the loaded chain has a wrong genesis, bail out immediately
// (we're likely using a testnet datadir, or the other way around). // (we're likely using a testnet datadir, or the other way around).
if (!mapBlockIndex.empty() && chainActive.Genesis() == NULL) if (!mapBlockIndex.empty() && mapBlockIndex.count(Params().HashGenesisBlock()) == 0)
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?")); return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
// Initialize the block index (no-op if non-empty database was already loaded) // Initialize the block index (no-op if non-empty database was already loaded)

View File

@ -1968,12 +1968,20 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
// Build list of new blocks to connect. // Build list of new blocks to connect.
std::vector<CBlockIndex*> vpindexToConnect; std::vector<CBlockIndex*> vpindexToConnect;
vpindexToConnect.reserve(pindexMostWork->nHeight - (pindexFork ? pindexFork->nHeight : -1)); bool fContinue = true;
CBlockIndex *pindexIter = pindexMostWork; int nHeight = pindexFork ? pindexFork->nHeight : -1;
while (pindexIter && pindexIter != pindexFork) { 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); vpindexToConnect.push_back(pindexIter);
pindexIter = pindexIter->pprev; pindexIter = pindexIter->pprev;
} }
nHeight = nTargetHeight;
// Connect new blocks. // Connect new blocks.
BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) { BOOST_REVERSE_FOREACH(CBlockIndex *pindexConnect, vpindexToConnect) {
@ -1984,6 +1992,7 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
InvalidChainFound(vpindexToConnect.back()); InvalidChainFound(vpindexToConnect.back());
state = CValidationState(); state = CValidationState();
fInvalidFound = true; fInvalidFound = true;
fContinue = false;
break; break;
} else { } else {
// A system error occurred (disk space, database error, ...). // A system error occurred (disk space, database error, ...).
@ -2001,10 +2010,12 @@ static bool ActivateBestChainStep(CValidationState &state, CBlockIndex *pindexMo
assert(!setBlockIndexCandidates.empty()); assert(!setBlockIndexCandidates.empty());
if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) { if (!pindexOldTip || chainActive.Tip()->nChainWork > pindexOldTip->nChainWork) {
// We're in a better position than we were. Return temporarily to release the lock. // We're in a better position than we were. Return temporarily to release the lock.
fContinue = false;
break; break;
} }
} }
} }
}
// Callbacks/notifications for a new best chain. // Callbacks/notifications for a new best chain.
if (fInvalidFound) if (fInvalidFound)