From 61431e3a57b5613d8715c93c6eae0058e0217eaa Mon Sep 17 00:00:00 2001 From: Martin Zumsande Date: Fri, 8 Jul 2022 15:25:20 -0400 Subject: [PATCH] validation: Skip VerifyDB checks of level >=3 if dbcache is too small The previous behavior, skipping some L3 DisconnectBlock calls, but still attempting to reconnect these blocks at L4, makes ConnectBlock assert. The variable skipped_l3_checks is introduced because even with an insufficient cache for the L3 checks, the L1/L2 checks in the same loop should still be completed. Fixes #25563. --- src/validation.cpp | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index 62ce1f1162..cbb43c9b2b 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4081,6 +4081,7 @@ bool CVerifyDB::VerifyDB( int nGoodTransactions = 0; BlockValidationState state; int reportDone = 0; + bool skipped_l3_checks{false}; LogPrintf("[0%%]..."); /* Continued */ const bool is_snapshot_cs{!chainstate.m_from_snapshot_blockhash}; @@ -4124,17 +4125,21 @@ bool CVerifyDB::VerifyDB( // check level 3: check for inconsistencies during memory-only disconnect of tip blocks size_t curr_coins_usage = coins.DynamicMemoryUsage() + chainstate.CoinsTip().DynamicMemoryUsage(); - 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) { - return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); - } - if (res == DISCONNECT_UNCLEAN) { - nGoodTransactions = 0; - pindexFailure = pindex; + if (nCheckLevel >= 3) { + if (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) { + return error("VerifyDB(): *** irrecoverable inconsistency in block data at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString()); + } + if (res == DISCONNECT_UNCLEAN) { + nGoodTransactions = 0; + pindexFailure = pindex; + } else { + nGoodTransactions += block.vtx.size(); + } } else { - nGoodTransactions += block.vtx.size(); + skipped_l3_checks = true; } } if (ShutdownRequested()) return true; @@ -4142,12 +4147,14 @@ bool CVerifyDB::VerifyDB( if (pindexFailure) { return error("VerifyDB(): *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainstate.m_chain.Height() - pindexFailure->nHeight + 1, nGoodTransactions); } - + if (skipped_l3_checks) { + LogPrintf("Skipped verification of level >=3 (insufficient database cache size). Consider increasing -dbcache.\n"); + } // store block count as we move pindex at check level >= 4 int block_count = chainstate.m_chain.Height() - pindex->nHeight; // check level 4: try reconnecting blocks - if (nCheckLevel >= 4) { + if (nCheckLevel >= 4 && !skipped_l3_checks) { while (pindex != chainstate.m_chain.Tip()) { const int percentageDone = std::max(1, std::min(99, 100 - (int)(((double)(chainstate.m_chain.Height() - pindex->nHeight)) / (double)nCheckDepth * 50))); if (reportDone < percentageDone / 10) {