diff --git a/src/init.cpp b/src/init.cpp index 0ae823a5fd..81a03cb100 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1892,9 +1892,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) fReindexChainState, nBlockTreeDBCache, nCoinDBCache, - nCoinCacheUsage, - args.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS), - args.GetArg("-checklevel", DEFAULT_CHECKLEVEL)); + nCoinCacheUsage); if (rv.has_value()) { switch (rv.value()) { case ChainstateLoadingError::ERROR_LOADING_BLOCK_DB: @@ -1932,20 +1930,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) case ChainstateLoadingError::ERROR_LOADCHAINTIP_FAILED: strLoadError = _("Error initializing block database"); break; - case ChainstateLoadingError::ERROR_EVO_DB_SANITY_FAILED: - strLoadError = _("Error initializing block database"); - break; case ChainstateLoadingError::ERROR_GENERIC_BLOCKDB_OPEN_FAILED: strLoadError = _("Error opening block database"); break; - case ChainstateLoadingError::ERROR_BLOCK_FROM_FUTURE: - strLoadError = _("The block database contains a block which appears to be from the future. " - "This may be due to your computer's date and time being set incorrectly. " - "Only rebuild the block database if you are sure that your computer's date and time are correct"); - break; - case ChainstateLoadingError::ERROR_CORRUPTED_BLOCK_DB: - strLoadError = _("Corrupted block database detected"); - break; case ChainstateLoadingError::ERROR_COMMITING_EVO_DB: strLoadError = _("Failed to commit Evo database"); break; @@ -1959,8 +1946,34 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) break; } } else { - fLoaded = true; - LogPrintf(" block index %15dms\n", Ticks(SteadyClock::now() - load_block_index_start_time)); + auto rv2 = VerifyLoadedChainstate(chainman, + *Assert(node.evodb.get()), + fReset, + fReindexChainState, + chainparams, + args.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS), + args.GetArg("-checklevel", DEFAULT_CHECKLEVEL)); + if (rv2.has_value()) { + switch (rv2.value()) { + case ChainstateLoadVerifyError::ERROR_BLOCK_FROM_FUTURE: + strLoadError = _("The block database contains a block which appears to be from the future. " + "This may be due to your computer's date and time being set incorrectly. " + "Only rebuild the block database if you are sure that your computer's date and time are correct"); + break; + case ChainstateLoadVerifyError::ERROR_CORRUPTED_BLOCK_DB: + strLoadError = _("Corrupted block database detected"); + break; + case ChainstateLoadVerifyError::ERROR_EVO_DB_SANITY_FAILED: + strLoadError = _("Error initializing block database"); + break; + case ChainstateLoadVerifyError::ERROR_GENERIC_FAILURE: + strLoadError = _("Error opening block database"); + break; + } + } else { + fLoaded = true; + LogPrintf(" block index %15dms\n", Ticks(SteadyClock::now() - load_block_index_start_time)); + } } if (!fLoaded && !ShutdownRequested()) { diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp index 1e3ad84208..350daec44c 100644 --- a/src/node/chainstate.cpp +++ b/src/node/chainstate.cpp @@ -50,9 +50,7 @@ std::optional LoadChainstate(bool fReset, bool fReindexChainState, int64_t nBlockTreeDBCache, int64_t nCoinDBCache, - int64_t nCoinCacheUsage, - unsigned int check_blocks, - unsigned int check_level) + int64_t nCoinCacheUsage) { auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { return fReset || fReindexChainState || chainstate->CoinsTip().GetBestBlock().IsNull(); @@ -232,6 +230,21 @@ std::optional LoadChainstate(bool fReset, return ChainstateLoadingError::ERROR_GENERIC_BLOCKDB_OPEN_FAILED; } + return std::nullopt; +} + +std::optional VerifyLoadedChainstate(ChainstateManager& chainman, + CEvoDB& evodb, + bool fReset, + bool fReindexChainState, + const CChainParams& chainparams, + unsigned int check_blocks, + unsigned int check_level) +{ + auto is_coinsview_empty = [&](CChainState* chainstate) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) { + return fReset || fReindexChainState || chainstate->CoinsTip().GetBestBlock().IsNull(); + }; + try { LOCK(cs_main); @@ -246,7 +259,7 @@ std::optional LoadChainstate(bool fReset, const CBlockIndex* tip = chainstate->m_chain.Tip(); RPCNotifyBlockChange(tip); if (tip && tip->nTime > GetTime() + MAX_FUTURE_BLOCK_TIME) { - return ChainstateLoadingError::ERROR_BLOCK_FROM_FUTURE; + return ChainstateLoadVerifyError::ERROR_BLOCK_FROM_FUTURE; } const bool v19active{DeploymentActiveAfter(tip, chainparams.GetConsensus(), Consensus::DEPLOYMENT_V19)}; if (v19active) { @@ -256,10 +269,10 @@ std::optional LoadChainstate(bool fReset, if (!CVerifyDB().VerifyDB( *chainstate, chainparams, chainstate->CoinsDB(), - *evodb, + evodb, check_level, check_blocks)) { - return ChainstateLoadingError::ERROR_CORRUPTED_BLOCK_DB; + return ChainstateLoadVerifyError::ERROR_CORRUPTED_BLOCK_DB; } // VerifyDB() disconnects blocks which might result in us switching back to legacy. @@ -277,15 +290,15 @@ std::optional LoadChainstate(bool fReset, // TODO: CEvoDB instance should probably be a part of CChainState // (for multiple chainstates to actually work in parallel) // and not a global - if (&chainman.ActiveChainstate() == chainstate && !evodb->IsEmpty()) { + if (&chainman.ActiveChainstate() == chainstate && !evodb.IsEmpty()) { // EvoDB processed some blocks earlier but we have no blocks anymore, something is wrong - return ChainstateLoadingError::ERROR_EVO_DB_SANITY_FAILED; + return ChainstateLoadVerifyError::ERROR_EVO_DB_SANITY_FAILED; } } } } catch (const std::exception& e) { LogPrintf("%s\n", e.what()); - return ChainstateLoadingError::ERROR_GENERIC_BLOCKDB_OPEN_FAILED; + return ChainstateLoadVerifyError::ERROR_GENERIC_FAILURE; } return std::nullopt; diff --git a/src/node/chainstate.h b/src/node/chainstate.h index 0dc31b01c4..ad35f9ecc8 100644 --- a/src/node/chainstate.h +++ b/src/node/chainstate.h @@ -43,10 +43,7 @@ enum class ChainstateLoadingError { ERROR_CHAINSTATE_UPGRADE_FAILED, ERROR_REPLAYBLOCKS_FAILED, ERROR_LOADCHAINTIP_FAILED, - ERROR_EVO_DB_SANITY_FAILED, ERROR_GENERIC_BLOCKDB_OPEN_FAILED, - ERROR_BLOCK_FROM_FUTURE, - ERROR_CORRUPTED_BLOCK_DB, ERROR_COMMITING_EVO_DB, ERROR_UPGRADING_EVO_DB, ERROR_UPGRADING_SIGNALS_DB, @@ -106,8 +103,21 @@ std::optional LoadChainstate(bool fReset, bool fReindexChainState, int64_t nBlockTreeDBCache, int64_t nCoinDBCache, - int64_t nCoinCacheUsage, - unsigned int check_blocks, - unsigned int check_level); + int64_t nCoinCacheUsage); + +enum class ChainstateLoadVerifyError { + ERROR_BLOCK_FROM_FUTURE, + ERROR_CORRUPTED_BLOCK_DB, + ERROR_EVO_DB_SANITY_FAILED, + ERROR_GENERIC_FAILURE, +}; + +std::optional VerifyLoadedChainstate(ChainstateManager& chainman, + CEvoDB& evodb, + bool fReset, + bool fReindexChainState, + const CChainParams& chainparams, + unsigned int check_blocks, + unsigned int check_level); #endif // BITCOIN_NODE_CHAINSTATE_H