Skip to content

Commit 0c7785b

Browse files
committed
init, validation: Improve handling if VerifyDB() fails due to insufficient dbcache
The rpc command verifychain now fails if the dbcache was not sufficient to complete the verification at the specified level and depth. In the same situation, the VerifyDB check during Init will now fail (and lead to an early shutdown) if the user has explicitly specified -checkblocks or -checklevel but the check couldn't be executed because of the limited cache. If the user didn't change any of the two and is using the defaults, log a warning but don't prevent the node from starting up.
1 parent d6f781f commit 0c7785b

File tree

7 files changed

+21
-3
lines changed

7 files changed

+21
-3
lines changed

src/init.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
15021502
options.prune = chainman.m_blockman.IsPruneMode();
15031503
options.check_blocks = args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
15041504
options.check_level = args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
1505+
options.require_full_verification = args.IsArgSet("-checkblocks") || args.IsArgSet("-checklevel");
15051506
options.check_interrupt = ShutdownRequested;
15061507
options.coins_error_cb = [] {
15071508
uiInterface.ThreadSafeMessageBox(
@@ -1533,7 +1534,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
15331534
}
15341535
}
15351536

1536-
if (status == node::ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB) {
1537+
if (status == node::ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB || status == node::ChainstateLoadStatus::FAILURE_INSUFFICIENT_DBCACHE) {
15371538
return InitError(error);
15381539
}
15391540

src/node/chainstate.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,11 @@ ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, const C
197197
break;
198198
case VerifyDBResult::CORRUPTED_BLOCK_DB:
199199
return {ChainstateLoadStatus::FAILURE, _("Corrupted block database detected")};
200+
case VerifyDBResult::SKIPPED_L3_CHECKS:
201+
if (options.require_full_verification) {
202+
return {ChainstateLoadStatus::FAILURE_INSUFFICIENT_DBCACHE, _("Insufficient dbcache for block verification")};
203+
}
204+
break;
200205
} // no default case, so the compiler can warn about missing cases
201206
}
202207
}

src/node/chainstate.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ struct ChainstateLoadOptions {
2525
bool reindex{false};
2626
bool reindex_chainstate{false};
2727
bool prune{false};
28+
bool require_full_verification{true};
2829
int64_t check_blocks{DEFAULT_CHECKBLOCKS};
2930
int64_t check_level{DEFAULT_CHECKLEVEL};
3031
std::function<bool()> check_interrupt;
@@ -35,7 +36,13 @@ struct ChainstateLoadOptions {
3536
//! case, and treat other cases as errors. More complex applications may want to
3637
//! try reindexing in the generic failure case, and pass an interrupt callback
3738
//! and exit cleanly in the interrupted case.
38-
enum class ChainstateLoadStatus { SUCCESS, FAILURE, FAILURE_INCOMPATIBLE_DB, INTERRUPTED };
39+
enum class ChainstateLoadStatus {
40+
SUCCESS,
41+
FAILURE,
42+
FAILURE_INCOMPATIBLE_DB,
43+
FAILURE_INSUFFICIENT_DBCACHE,
44+
INTERRUPTED,
45+
};
3946

4047
//! Chainstate load status code and optional error string.
4148
using ChainstateLoadResult = std::tuple<ChainstateLoadStatus, bilingual_str>;

src/rpc/blockchain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,7 @@ static RPCHelpMan verifychain()
11101110
{"nblocks", RPCArg::Type::NUM, RPCArg::DefaultHint{strprintf("%d, 0=all", DEFAULT_CHECKBLOCKS)}, "The number of blocks to check."},
11111111
},
11121112
RPCResult{
1113-
RPCResult::Type::BOOL, "", "Verified or not"},
1113+
RPCResult::Type::BOOL, "", "Verification finished successfully. If false, check debug.log for reason."},
11141114
RPCExamples{
11151115
HelpExampleCli("verifychain", "")
11161116
+ HelpExampleRpc("verifychain", "")

src/test/util/setup_common.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ void TestingSetup::LoadVerifyActivateChainstate()
218218
options.prune = chainman.m_blockman.IsPruneMode();
219219
options.check_blocks = m_args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
220220
options.check_level = m_args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
221+
options.require_full_verification = m_args.IsArgSet("-checkblocks") || m_args.IsArgSet("-checklevel");
221222
auto [status, error] = LoadChainstate(chainman, m_cache_sizes, options);
222223
assert(status == node::ChainstateLoadStatus::SUCCESS);
223224

src/validation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4185,6 +4185,9 @@ VerifyDBResult CVerifyDB::VerifyDB(
41854185

41864186
LogPrintf("Verification: No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions);
41874187

4188+
if (skipped_l3_checks) {
4189+
return VerifyDBResult::SKIPPED_L3_CHECKS;
4190+
}
41884191
return VerifyDBResult::SUCCESS;
41894192
}
41904193

src/validation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ enum class VerifyDBResult {
353353
SUCCESS,
354354
CORRUPTED_BLOCK_DB,
355355
INTERRUPTED,
356+
SKIPPED_L3_CHECKS,
356357
};
357358

358359
/** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */

0 commit comments

Comments
 (0)