Skip to content

Commit

Permalink
validation: Skip VerifyDB checks of level >=3 if dbcache is too small
Browse files Browse the repository at this point in the history
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 bitcoin#25563.
  • Loading branch information
mzumsande committed Jan 19, 2023
1 parent 73b6171 commit 5eaca08
Showing 1 changed file with 19 additions and 12 deletions.
31 changes: 19 additions & 12 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3985,6 +3985,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};
Expand Down Expand Up @@ -4028,30 +4029,36 @@ 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;
}
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) {
Expand Down

0 comments on commit 5eaca08

Please sign in to comment.