From 61431e3a57b5613d8715c93c6eae0058e0217eaa Mon Sep 17 00:00:00 2001 From: Martin Zumsande Date: Fri, 8 Jul 2022 15:25:20 -0400 Subject: [PATCH 1/2] 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 62ce1f11624..cbb43c9b2b4 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) { From fe683f352480245add0b27fe7efef5fef4c1e8c3 Mon Sep 17 00:00:00 2001 From: Martin Zumsande Date: Mon, 3 Oct 2022 14:49:13 -0400 Subject: [PATCH 2/2] log: Log VerifyDB Progress over multiple lines This allows to log a timestamp for each entry, and avoids potential interference with other threads that could log concurrently. --- src/validation.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/validation.cpp b/src/validation.cpp index cbb43c9b2b4..f0ffb748dd6 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -4082,7 +4082,7 @@ bool CVerifyDB::VerifyDB( BlockValidationState state; int reportDone = 0; bool skipped_l3_checks{false}; - LogPrintf("[0%%]..."); /* Continued */ + LogPrintf("Verification progress: 0%%\n"); const bool is_snapshot_cs{!chainstate.m_from_snapshot_blockhash}; @@ -4090,7 +4090,7 @@ bool CVerifyDB::VerifyDB( 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) { // report every 10% step - LogPrintf("[%d%%]...", percentageDone); /* Continued */ + LogPrintf("Verification progress: %d%%\n", percentageDone); reportDone = percentageDone / 10; } uiInterface.ShowProgress(_("Verifying blocks…").translated, percentageDone, false); @@ -4159,7 +4159,7 @@ bool CVerifyDB::VerifyDB( 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) { // report every 10% step - LogPrintf("[%d%%]...", percentageDone); /* Continued */ + LogPrintf("Verification progress: %d%%\n", percentageDone); reportDone = percentageDone / 10; } uiInterface.ShowProgress(_("Verifying blocks…").translated, percentageDone, false); @@ -4174,8 +4174,7 @@ bool CVerifyDB::VerifyDB( } } - LogPrintf("[DONE].\n"); - LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions); + LogPrintf("Verification: No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions); return true; }