Changeset View
Changeset View
Standalone View
Standalone View
src/init.cpp
Show First 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | if (fFeeEstimatesInitialized) { | ||||
LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, | LogPrintf("%s: Failed to write fee estimates to %s\n", __func__, | ||||
est_path.string()); | est_path.string()); | ||||
} | } | ||||
fFeeEstimatesInitialized = false; | fFeeEstimatesInitialized = false; | ||||
} | } | ||||
// FlushStateToDisk generates a SetBestChain callback, which we should avoid | // FlushStateToDisk generates a SetBestChain callback, which we should avoid | ||||
// missing | // missing | ||||
if (pcoinsTip != nullptr) { | |||||
FlushStateToDisk(); | FlushStateToDisk(); | ||||
} | |||||
// After there are no more peers/RPC left to give us new data which may | // After there are no more peers/RPC left to give us new data which may | ||||
// generate CValidationInterface callbacks, flush them... | // generate CValidationInterface callbacks, flush them... | ||||
GetMainSignals().FlushBackgroundCallbacks(); | GetMainSignals().FlushBackgroundCallbacks(); | ||||
// Any future callbacks will be dropped. This should absolutely be safe - if | // Any future callbacks will be dropped. This should absolutely be safe - if | ||||
// missing a callback results in an unrecoverable situation, unclean | // missing a callback results in an unrecoverable situation, unclean | ||||
// shutdown would too. The only reason to do the above flushes is to let the | // shutdown would too. The only reason to do the above flushes is to let the | ||||
▲ Show 20 Lines • Show All 802 Lines • ▼ Show 20 Lines | RenameThread("bitcoin-loadblk"); | ||||
LoadExternalBlockFile(config, file, &pos); | LoadExternalBlockFile(config, file, &pos); | ||||
nFile++; | nFile++; | ||||
} | } | ||||
pblocktree->WriteReindexing(false); | pblocktree->WriteReindexing(false); | ||||
fReindex = false; | fReindex = false; | ||||
LogPrintf("Reindexing finished\n"); | LogPrintf("Reindexing finished\n"); | ||||
// To avoid ending up in a situation without genesis block, re-try | // To avoid ending up in a situation without genesis block, re-try | ||||
// initializing (no-op if reindexing worked): | // initializing (no-op if reindexing worked): | ||||
InitBlockIndex(config); | LoadGenesisBlock(config.GetChainParams()); | ||||
} | } | ||||
// hardcoded $DATADIR/bootstrap.dat | // hardcoded $DATADIR/bootstrap.dat | ||||
fs::path pathBootstrap = GetDataDir() / "bootstrap.dat"; | fs::path pathBootstrap = GetDataDir() / "bootstrap.dat"; | ||||
if (fs::exists(pathBootstrap)) { | if (fs::exists(pathBootstrap)) { | ||||
FILE *file = fsbridge::fopen(pathBootstrap, "rb"); | FILE *file = fsbridge::fopen(pathBootstrap, "rb"); | ||||
if (file) { | if (file) { | ||||
fs::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; | fs::path pathBootstrapOld = GetDataDir() / "bootstrap.dat.old"; | ||||
▲ Show 20 Lines • Show All 932 Lines • ▼ Show 20 Lines | while (!fLoaded && !fRequestShutdown) { | ||||
UnloadBlockIndex(); | UnloadBlockIndex(); | ||||
delete pcoinsTip; | delete pcoinsTip; | ||||
delete pcoinsdbview; | delete pcoinsdbview; | ||||
delete pcoinscatcher; | delete pcoinscatcher; | ||||
delete pblocktree; | delete pblocktree; | ||||
pblocktree = | pblocktree = | ||||
new CBlockTreeDB(nBlockTreeDBCache, false, fReindex); | new CBlockTreeDB(nBlockTreeDBCache, false, fReindex); | ||||
pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, | |||||
fReindex || fReindexChainState); | |||||
pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); | |||||
if (fReindex) { | if (fReindex) { | ||||
pblocktree->WriteReindexing(true); | pblocktree->WriteReindexing(true); | ||||
// If we're reindexing in prune mode, wipe away unusable | // If we're reindexing in prune mode, wipe away unusable | ||||
// block files and all undo data files | // block files and all undo data files | ||||
if (fPruneMode) { | if (fPruneMode) { | ||||
CleanupBlockRevFiles(); | CleanupBlockRevFiles(); | ||||
} | } | ||||
} else if (!pcoinsdbview->Upgrade()) { | |||||
strLoadError = _("Error upgrading chainstate database"); | |||||
break; | |||||
} | } | ||||
if (fRequestShutdown) { | if (fRequestShutdown) { | ||||
break; | break; | ||||
} | } | ||||
// LoadBlockIndex will load fTxIndex from the db, or set it if | |||||
// we're reindexing. It will also load fHavePruned if we've | |||||
// ever removed a block file from disk. | |||||
if (!LoadBlockIndex(config)) { | if (!LoadBlockIndex(config)) { | ||||
strLoadError = _("Error loading block database"); | strLoadError = _("Error loading block database"); | ||||
break; | break; | ||||
} | } | ||||
// 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 | // (we're likely using a testnet datadir, or the other way | ||||
// around). | // around). | ||||
if (!mapBlockIndex.empty() && | if (!mapBlockIndex.empty() && | ||||
mapBlockIndex.count( | mapBlockIndex.count( | ||||
chainparams.GetConsensus().hashGenesisBlock) == 0) { | chainparams.GetConsensus().hashGenesisBlock) == 0) { | ||||
return InitError(_("Incorrect or no genesis block found. " | return InitError(_("Incorrect or no genesis block found. " | ||||
"Wrong datadir for network?")); | "Wrong datadir for network?")); | ||||
} | } | ||||
// Initialize the block index (no-op if non-empty database was | |||||
// already loaded) | |||||
if (!InitBlockIndex(config)) { | |||||
strLoadError = _("Error initializing block database"); | |||||
break; | |||||
} | |||||
// Check for changed -txindex state | // Check for changed -txindex state | ||||
if (fTxIndex != gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { | if (fTxIndex != gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)) { | ||||
strLoadError = _("You need to rebuild the database using " | strLoadError = _("You need to rebuild the database using " | ||||
"-reindex-chainstate to change -txindex"); | "-reindex-chainstate to change -txindex"); | ||||
break; | break; | ||||
} | } | ||||
// Check for changed -prune state. What we are concerned about | // Check for changed -prune state. What we are concerned about | ||||
// is a user who has pruned blocks in the past, but is now | // is a user who has pruned blocks in the past, but is now | ||||
// trying to run unpruned. | // trying to run unpruned. | ||||
if (fHavePruned && !fPruneMode) { | if (fHavePruned && !fPruneMode) { | ||||
strLoadError = | strLoadError = | ||||
_("You need to rebuild the database using -reindex to " | _("You need to rebuild the database using -reindex to " | ||||
"go back to unpruned mode. This will redownload the " | "go back to unpruned mode. This will redownload the " | ||||
"entire blockchain"); | "entire blockchain"); | ||||
break; | break; | ||||
} | } | ||||
// At this point blocktree args are consistent with what's on | |||||
// disk. If we're not mid-reindex (based on disk + args), add a | |||||
// genesis block on disk. This is called again in ThreadImport | |||||
// if the reindex completes. | |||||
if (!fReindex && !LoadGenesisBlock(chainparams)) { | |||||
strLoadError = _("Error initializing block database"); | |||||
break; | |||||
} | |||||
// At this point we're either in reindex or we've loaded a | |||||
// useful block tree into mapBlockIndex! | |||||
pcoinsdbview = new CCoinsViewDB(nCoinDBCache, false, | |||||
fReindex || fReindexChainState); | |||||
pcoinscatcher = new CCoinsViewErrorCatcher(pcoinsdbview); | |||||
// If necessary, upgrade from older database format. | |||||
// This is a no-op if we cleared the coinsviewdb with -reindex | |||||
// or -reindex-chainstate | |||||
if (!pcoinsdbview->Upgrade()) { | |||||
strLoadError = _("Error upgrading chainstate database"); | |||||
break; | |||||
} | |||||
// ReplayBlocks is a no-op if we cleared the coinsviewdb with | |||||
// -reindex or -reindex-chainstate | |||||
if (!ReplayBlocks(config, pcoinsdbview)) { | if (!ReplayBlocks(config, pcoinsdbview)) { | ||||
strLoadError = | strLoadError = | ||||
_("Unable to replay blocks. You will need to rebuild " | _("Unable to replay blocks. You will need to rebuild " | ||||
"the database using -reindex-chainstate."); | "the database using -reindex-chainstate."); | ||||
break; | break; | ||||
} | } | ||||
// The on-disk coinsdb is now in a good state, create the cache | |||||
pcoinsTip = new CCoinsViewCache(pcoinscatcher); | pcoinsTip = new CCoinsViewCache(pcoinscatcher); | ||||
LoadChainTip(chainparams); | |||||
if (!fReindex && chainActive.Tip() != nullptr) { | if (!fReindex && !fReindexChainState) { | ||||
// LoadChainTip sets chainActive based on pcoinsTip's best | |||||
// block | |||||
if (!LoadChainTip(config)) { | |||||
strLoadError = _("Error initializing block database"); | |||||
break; | |||||
} | |||||
assert(chainActive.Tip() != nullptr); | |||||
} | |||||
if (!fReindex) { | |||||
// Note that RewindBlockIndex MUST run even if we're about | |||||
// to -reindex-chainstate. It both disconnects blocks based | |||||
// on chainActive, and drops block data in mapBlockIndex | |||||
// based on lack of available witness data. | |||||
uiInterface.InitMessage(_("Rewinding blocks...")); | uiInterface.InitMessage(_("Rewinding blocks...")); | ||||
if (!RewindBlockIndex(config)) { | if (!RewindBlockIndex(config)) { | ||||
strLoadError = _("Unable to rewind the database to a " | strLoadError = _("Unable to rewind the database to a " | ||||
"pre-fork state. You will need to " | "pre-fork state. You will need to " | ||||
"redownload the blockchain"); | "redownload the blockchain"); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (!fReindex && !fReindexChainState) { | |||||
uiInterface.InitMessage(_("Verifying blocks...")); | uiInterface.InitMessage(_("Verifying blocks...")); | ||||
if (fHavePruned && | if (fHavePruned && | ||||
gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > | gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > | ||||
MIN_BLOCKS_TO_KEEP) { | MIN_BLOCKS_TO_KEEP) { | ||||
LogPrintf("Prune: pruned datadir may not have more than %d " | LogPrintf("Prune: pruned datadir may not have more " | ||||
"blocks; only checking available blocks", | "than %d blocks; only checking available " | ||||
"blocks", | |||||
MIN_BLOCKS_TO_KEEP); | MIN_BLOCKS_TO_KEEP); | ||||
} | } | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CBlockIndex *tip = chainActive.Tip(); | CBlockIndex *tip = chainActive.Tip(); | ||||
RPCNotifyBlockChange(true, tip); | RPCNotifyBlockChange(true, tip); | ||||
if (tip && | if (tip && | ||||
tip->nTime > | tip->nTime > | ||||
GetAdjustedTime() + MAX_FUTURE_BLOCK_TIME) { | GetAdjustedTime() + MAX_FUTURE_BLOCK_TIME) { | ||||
strLoadError = | strLoadError = | ||||
_("The block database contains a block which " | _("The block database contains a block which " | ||||
"appears to be from the future. " | "appears to be from the future. This may be " | ||||
"This may be due to your computer's date and " | "due to your computer's date and time being " | ||||
"time being set incorrectly. " | "set incorrectly. Only rebuild the block " | ||||
"Only rebuild the block database if you are sure " | "database if you are sure that your " | ||||
"that your computer's date and time are correct"); | "computer's date and time are correct"); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (!CVerifyDB().VerifyDB( | if (!CVerifyDB().VerifyDB( | ||||
config, pcoinsdbview, | config, pcoinsdbview, | ||||
gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL), | gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL), | ||||
gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) { | gArgs.GetArg("-checkblocks", | ||||
DEFAULT_CHECKBLOCKS))) { | |||||
strLoadError = _("Corrupted block database detected"); | strLoadError = _("Corrupted block database detected"); | ||||
break; | break; | ||||
} | } | ||||
} | |||||
} catch (const std::exception &e) { | } catch (const std::exception &e) { | ||||
LogPrintf("%s\n", e.what()); | LogPrintf("%s\n", e.what()); | ||||
strLoadError = _("Error opening block database"); | strLoadError = _("Error opening block database"); | ||||
break; | break; | ||||
} | } | ||||
fLoaded = true; | fLoaded = true; | ||||
} while (false); | } while (false); | ||||
▲ Show 20 Lines • Show All 198 Lines • Show Last 20 Lines |