From 9b604c0207b526c008617cdca210f35db5e344db Mon Sep 17 00:00:00 2001 From: James O'Beirne Date: Tue, 13 Apr 2021 10:05:28 -0400 Subject: [PATCH] validation: prepare VerifyDB for assumeutxo Removes assumptions of use only on the active chainstate. --- src/init.cpp | 7 ++----- src/rpc/blockchain.cpp | 3 ++- src/validation.cpp | 16 ++++++++++------ src/validation.h | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index ccf36808173..2b1cd3e2aa9 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1550,11 +1550,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) break; } - // Only verify the DB of the active chainstate. This is fixed in later - // work when we allow VerifyDB to be parameterized by chainstate. - if (&::ChainstateActive() == chainstate && - !CVerifyDB().VerifyDB( - *chainstate, chainparams, &chainstate->CoinsDB(), + if (!CVerifyDB().VerifyDB( + *chainstate, chainparams, chainstate->CoinsDB(), args.GetArg("-checklevel", DEFAULT_CHECKLEVEL), args.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) { strLoadError = _("Corrupted block database detected"); diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 8e029b134bf..d36814716bb 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1239,7 +1239,8 @@ static RPCHelpMan verifychain() LOCK(cs_main); CChainState& active_chainstate = chainman.ActiveChainstate(); - return CVerifyDB().VerifyDB(active_chainstate, Params(), &active_chainstate.CoinsTip(), check_level, check_depth); + return CVerifyDB().VerifyDB( + active_chainstate, Params(), active_chainstate.CoinsTip(), check_level, check_depth); }, }; } diff --git a/src/validation.cpp b/src/validation.cpp index 6fe096465af..332a38119aa 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4104,7 +4104,7 @@ CVerifyDB::~CVerifyDB() bool CVerifyDB::VerifyDB( CChainState& chainstate, const CChainParams& chainparams, - CCoinsView* coinsview, + CCoinsView& coinsview, int nCheckLevel, int nCheckDepth) { AssertLockHeld(cs_main); @@ -4118,13 +4118,16 @@ bool CVerifyDB::VerifyDB( nCheckDepth = chainstate.m_chain.Height(); nCheckLevel = std::max(0, std::min(4, nCheckLevel)); LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel); - CCoinsViewCache coins(coinsview); + CCoinsViewCache coins(&coinsview); CBlockIndex* pindex; CBlockIndex* pindexFailure = nullptr; int nGoodTransactions = 0; BlockValidationState state; int reportDone = 0; LogPrintf("[0%%]..."); /* Continued */ + + bool is_snapshot_cs = !chainstate.m_from_snapshot_blockhash.IsNull(); + for (pindex = chainstate.m_chain.Tip(); pindex && pindex->pprev; pindex = pindex->pprev) { const int percentageDone = std::max(1, std::min(99, (int)(((double)(chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); if (reportDone < percentageDone/10) { @@ -4135,8 +4138,9 @@ bool CVerifyDB::VerifyDB( uiInterface.ShowProgress(_("Verifying blocks...").translated, percentageDone, false); if (pindex->nHeight <= chainstate.m_chain.Height()-nCheckDepth) break; - if (fPruneMode && !(pindex->nStatus & BLOCK_HAVE_DATA)) { - // If pruning, only go back as far as we have data. + if ((fPruneMode || is_snapshot_cs) && !(pindex->nStatus & BLOCK_HAVE_DATA)) { + // If pruning or running under an assumeutxo snapshot, only go + // back as far as we have data. LogPrintf("VerifyDB(): block verification stopping at height %d (pruning, no data)\n", pindex->nHeight); break; } @@ -4158,9 +4162,9 @@ bool CVerifyDB::VerifyDB( } } // check level 3: check for inconsistencies during memory-only disconnect of tip blocks - int64_t curr_coins_usage = coins.DynamicMemoryUsage() + chainstate.CoinsTip().DynamicMemoryUsage(); + size_t curr_coins_usage = coins.DynamicMemoryUsage() + chainstate.CoinsTip().DynamicMemoryUsage(); - if (nCheckLevel >= 3 && static_cast(curr_coins_usage) <= chainstate.m_coinstip_cache_size_bytes) { + if (nCheckLevel >= 3 && curr_coins_usage <= chainstate.m_coinstip_cache_size_bytes) { assert(coins.GetBestBlock() == pindex->GetBlockHash()); DisconnectResult res = chainstate.DisconnectBlock(block, pindex, coins); if (res == DISCONNECT_FAILED) { diff --git a/src/validation.h b/src/validation.h index b4e1c080fe1..d3341f491ec 100644 --- a/src/validation.h +++ b/src/validation.h @@ -332,7 +332,7 @@ public: bool VerifyDB( CChainState& chainstate, const CChainParams& chainparams, - CCoinsView* coinsview, + CCoinsView& coinsview, int nCheckLevel, int nCheckDepth) EXCLUSIVE_LOCKS_REQUIRED(cs_main); };