Changeset View
Changeset View
Standalone View
Standalone View
src/init.cpp
Show First 20 Lines • Show All 2,389 Lines • ▼ Show 20 Lines | #endif | ||||
LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of " | LogPrintf("* Using %.1f MiB for in-memory UTXO set (plus up to %.1f MiB of " | ||||
"unused mempool space)\n", | "unused mempool space)\n", | ||||
nCoinCacheUsage * (1.0 / 1024 / 1024), | nCoinCacheUsage * (1.0 / 1024 / 1024), | ||||
nMempoolSizeMax * (1.0 / 1024 / 1024)); | nMempoolSizeMax * (1.0 / 1024 / 1024)); | ||||
bool fLoaded = false; | bool fLoaded = false; | ||||
while (!fLoaded && !ShutdownRequested()) { | while (!fLoaded && !ShutdownRequested()) { | ||||
const bool fReset = fReindex; | const bool fReset = fReindex; | ||||
std::string strLoadError; | bilingual_str strLoadError; | ||||
uiInterface.InitMessage(_("Loading block index...").translated); | uiInterface.InitMessage(_("Loading block index...").translated); | ||||
do { | do { | ||||
const int64_t load_block_index_start_time = GetTimeMillis(); | const int64_t load_block_index_start_time = GetTimeMillis(); | ||||
try { | try { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
// This statement makes ::ChainstateActive() usable. | // This statement makes ::ChainstateActive() usable. | ||||
g_chainstate = std::make_unique<CChainState>(); | g_chainstate = std::make_unique<CChainState>(); | ||||
Show All 25 Lines | while (!fLoaded && !ShutdownRequested()) { | ||||
// block file from disk. | // block file from disk. | ||||
// Note that it also sets fReindex based on the disk flag! | // Note that it also sets fReindex based on the disk flag! | ||||
// From here on out fReindex and fReset mean something | // From here on out fReindex and fReset mean something | ||||
// different! | // different! | ||||
if (!LoadBlockIndex(params)) { | if (!LoadBlockIndex(params)) { | ||||
if (ShutdownRequested()) { | if (ShutdownRequested()) { | ||||
break; | break; | ||||
} | } | ||||
strLoadError = _("Error loading block database").translated; | 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 (!::BlockIndex().empty() && | if (!::BlockIndex().empty() && | ||||
!LookupBlockIndex(params.hashGenesisBlock)) { | !LookupBlockIndex(params.hashGenesisBlock)) { | ||||
return InitError(_("Incorrect or no genesis block found. " | return InitError(_("Incorrect or no genesis block found. " | ||||
"Wrong datadir for network?") | "Wrong datadir for network?") | ||||
.translated); | .translated); | ||||
} | } | ||||
// 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"); | ||||
.translated; | |||||
break; | break; | ||||
} | } | ||||
// At this point blocktree args are consistent with what's on | // At this point blocktree args are consistent with what's on | ||||
// disk. If we're not mid-reindex (based on disk + args), add a | // disk. If we're not mid-reindex (based on disk + args), add a | ||||
// genesis block on disk (otherwise we use the one already on | // genesis block on disk (otherwise we use the one already on | ||||
// disk). | // disk). | ||||
// This is called again in ThreadImport after the reindex | // This is called again in ThreadImport after the reindex | ||||
// completes. | // completes. | ||||
if (!fReindex && !LoadGenesisBlock(chainparams)) { | if (!fReindex && !LoadGenesisBlock(chainparams)) { | ||||
strLoadError = | strLoadError = _("Error initializing block database"); | ||||
_("Error initializing block database").translated; | |||||
break; | break; | ||||
} | } | ||||
// At this point we're either in reindex or we've loaded a | // At this point we're either in reindex or we've loaded a | ||||
// useful block tree into BlockIndex()! | // useful block tree into BlockIndex()! | ||||
::ChainstateActive().InitCoinsDB( | ::ChainstateActive().InitCoinsDB( | ||||
/* cache_size_bytes */ nCoinDBCache, | /* cache_size_bytes */ nCoinDBCache, | ||||
/* in_memory */ false, | /* in_memory */ false, | ||||
/* should_wipe */ fReset || fReindexChainState); | /* should_wipe */ fReset || fReindexChainState); | ||||
::ChainstateActive().CoinsErrorCatcher().AddReadErrCallback( | ::ChainstateActive().CoinsErrorCatcher().AddReadErrCallback( | ||||
[]() { | []() { | ||||
uiInterface.ThreadSafeMessageBox( | uiInterface.ThreadSafeMessageBox( | ||||
_("Error reading from database, shutting down.") | _("Error reading from database, shutting down."), | ||||
.translated, | |||||
"", CClientUIInterface::MSG_ERROR); | "", CClientUIInterface::MSG_ERROR); | ||||
}); | }); | ||||
// If necessary, upgrade from older database format. | // If necessary, upgrade from older database format. | ||||
// This is a no-op if we cleared the coinsviewdb with -reindex | // This is a no-op if we cleared the coinsviewdb with -reindex | ||||
// or -reindex-chainstate | // or -reindex-chainstate | ||||
if (!::ChainstateActive().CoinsDB().Upgrade()) { | if (!::ChainstateActive().CoinsDB().Upgrade()) { | ||||
strLoadError = | strLoadError = _("Error upgrading chainstate database"); | ||||
_("Error upgrading chainstate database").translated; | |||||
break; | break; | ||||
} | } | ||||
// ReplayBlocks is a no-op if we cleared the coinsviewdb with | // ReplayBlocks is a no-op if we cleared the coinsviewdb with | ||||
// -reindex or -reindex-chainstate | // -reindex or -reindex-chainstate | ||||
if (!::ChainstateActive().ReplayBlocks(params)) { | if (!::ChainstateActive().ReplayBlocks(params)) { | ||||
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."); | ||||
.translated; | |||||
break; | break; | ||||
} | } | ||||
// The on-disk coinsdb is now in a good state, create the cache | // The on-disk coinsdb is now in a good state, create the cache | ||||
::ChainstateActive().InitCoinsCache(); | ::ChainstateActive().InitCoinsCache(); | ||||
assert(::ChainstateActive().CanFlushToDisk()); | assert(::ChainstateActive().CanFlushToDisk()); | ||||
bool is_coinsview_empty = | bool is_coinsview_empty = | ||||
fReset || fReindexChainState || | fReset || fReindexChainState || | ||||
::ChainstateActive().CoinsTip().GetBestBlock().IsNull(); | ::ChainstateActive().CoinsTip().GetBestBlock().IsNull(); | ||||
if (!is_coinsview_empty) { | if (!is_coinsview_empty) { | ||||
// LoadChainTip initializes the chain based on CoinsTip()'s | // LoadChainTip initializes the chain based on CoinsTip()'s | ||||
// best block | // best block | ||||
if (!::ChainstateActive().LoadChainTip(chainparams)) { | if (!::ChainstateActive().LoadChainTip(chainparams)) { | ||||
strLoadError = | strLoadError = _("Error initializing block database"); | ||||
_("Error initializing block database").translated; | |||||
break; | break; | ||||
} | } | ||||
assert(::ChainActive().Tip() != nullptr); | assert(::ChainActive().Tip() != nullptr); | ||||
uiInterface.InitMessage( | uiInterface.InitMessage( | ||||
_("Verifying blocks...").translated); | _("Verifying blocks...").translated); | ||||
if (fHavePruned && | if (fHavePruned && | ||||
gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > | gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > | ||||
Show All 9 Lines | while (!fLoaded && !ShutdownRequested()) { | ||||
if (tip && tip->nTime > | if (tip && 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. This may be due " | "appears to be from the future. This may be due " | ||||
"to your computer's date and time being set " | "to your computer's date and time being set " | ||||
"incorrectly. Only rebuild the block database if " | "incorrectly. Only rebuild the block database if " | ||||
"you are sure that your computer's date and time " | "you are sure that your computer's date and time " | ||||
"are correct") | "are correct"); | ||||
.translated; | |||||
break; | break; | ||||
} | } | ||||
if (!CVerifyDB().VerifyDB( | if (!CVerifyDB().VerifyDB( | ||||
config, &::ChainstateActive().CoinsDB(), | config, &::ChainstateActive().CoinsDB(), | ||||
gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL), | gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL), | ||||
gArgs.GetArg("-checkblocks", | gArgs.GetArg("-checkblocks", | ||||
DEFAULT_CHECKBLOCKS))) { | DEFAULT_CHECKBLOCKS))) { | ||||
strLoadError = | strLoadError = _("Corrupted block database detected"); | ||||
_("Corrupted block database detected").translated; | |||||
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").translated; | strLoadError = _("Error opening block database"); | ||||
break; | break; | ||||
} | } | ||||
fLoaded = true; | fLoaded = true; | ||||
LogPrintf(" block index %15dms\n", | LogPrintf(" block index %15dms\n", | ||||
GetTimeMillis() - load_block_index_start_time); | GetTimeMillis() - load_block_index_start_time); | ||||
} while (false); | } while (false); | ||||
if (!fLoaded && !ShutdownRequested()) { | if (!fLoaded && !ShutdownRequested()) { | ||||
// first suggest a reindex | // first suggest a reindex | ||||
if (!fReset) { | if (!fReset) { | ||||
bool fRet = uiInterface.ThreadSafeQuestion( | bool fRet = uiInterface.ThreadSafeQuestion( | ||||
strLoadError + ".\n\n" + | strLoadError + Untranslated(".\n\n") + | ||||
_("Do you want to rebuild the block database now?") | _("Do you want to rebuild the block database now?"), | ||||
.translated, | strLoadError.original + | ||||
strLoadError + ".\nPlease restart with -reindex or " | ".\nPlease restart with -reindex or " | ||||
"-reindex-chainstate to recover.", | "-reindex-chainstate to recover.", | ||||
"", | "", | ||||
CClientUIInterface::MSG_ERROR | | CClientUIInterface::MSG_ERROR | | ||||
CClientUIInterface::BTN_ABORT); | CClientUIInterface::BTN_ABORT); | ||||
if (fRet) { | if (fRet) { | ||||
fReindex = true; | fReindex = true; | ||||
AbortShutdown(); | AbortShutdown(); | ||||
} else { | } else { | ||||
LogPrintf("Aborted block database rebuild. Exiting.\n"); | LogPrintf("Aborted block database rebuild. Exiting.\n"); | ||||
return false; | return false; | ||||
} | } | ||||
} else { | } else { | ||||
return InitError(strLoadError); | return InitError(strLoadError.translated); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// As LoadBlockIndex can take several minutes, it's possible the user | // As LoadBlockIndex can take several minutes, it's possible the user | ||||
// requested to kill the GUI during the last operation. If so, exit. | // requested to kill the GUI during the last operation. If so, exit. | ||||
// As the program has not fully started yet, Shutdown() is possibly | // As the program has not fully started yet, Shutdown() is possibly | ||||
// overkill. | // overkill. | ||||
▲ Show 20 Lines • Show All 209 Lines • Show Last 20 Lines |