aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Zumsande <mzumsande@gmail.com>2022-10-06 17:11:02 -0400
committerMartin Zumsande <mzumsande@gmail.com>2023-02-16 17:58:52 -0500
commit0c7785bb2540b69564104767d38342704230cbc2 (patch)
tree722eb5a29c537f221d8041cd954f6b043dfc2f15
parentd6f781f1cfcbc2c2ad5ee289a0642ed00386d013 (diff)
downloadbitcoin-0c7785bb2540b69564104767d38342704230cbc2.tar.xz
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.
-rw-r--r--src/init.cpp3
-rw-r--r--src/node/chainstate.cpp5
-rw-r--r--src/node/chainstate.h9
-rw-r--r--src/rpc/blockchain.cpp2
-rw-r--r--src/test/util/setup_common.cpp1
-rw-r--r--src/validation.cpp3
-rw-r--r--src/validation.h1
7 files changed, 21 insertions, 3 deletions
diff --git a/src/init.cpp b/src/init.cpp
index 5b486854e0..b24ae8606a 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -1502,6 +1502,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
options.prune = chainman.m_blockman.IsPruneMode();
options.check_blocks = args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
options.check_level = args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
+ options.require_full_verification = args.IsArgSet("-checkblocks") || args.IsArgSet("-checklevel");
options.check_interrupt = ShutdownRequested;
options.coins_error_cb = [] {
uiInterface.ThreadSafeMessageBox(
@@ -1533,7 +1534,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
}
}
- if (status == node::ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB) {
+ if (status == node::ChainstateLoadStatus::FAILURE_INCOMPATIBLE_DB || status == node::ChainstateLoadStatus::FAILURE_INSUFFICIENT_DBCACHE) {
return InitError(error);
}
diff --git a/src/node/chainstate.cpp b/src/node/chainstate.cpp
index 7d6e0f3bb0..c521b20b2a 100644
--- a/src/node/chainstate.cpp
+++ b/src/node/chainstate.cpp
@@ -197,6 +197,11 @@ ChainstateLoadResult VerifyLoadedChainstate(ChainstateManager& chainman, const C
break;
case VerifyDBResult::CORRUPTED_BLOCK_DB:
return {ChainstateLoadStatus::FAILURE, _("Corrupted block database detected")};
+ case VerifyDBResult::SKIPPED_L3_CHECKS:
+ if (options.require_full_verification) {
+ return {ChainstateLoadStatus::FAILURE_INSUFFICIENT_DBCACHE, _("Insufficient dbcache for block verification")};
+ }
+ break;
} // no default case, so the compiler can warn about missing cases
}
}
diff --git a/src/node/chainstate.h b/src/node/chainstate.h
index d3c7656bf2..7838a62d0c 100644
--- a/src/node/chainstate.h
+++ b/src/node/chainstate.h
@@ -25,6 +25,7 @@ struct ChainstateLoadOptions {
bool reindex{false};
bool reindex_chainstate{false};
bool prune{false};
+ bool require_full_verification{true};
int64_t check_blocks{DEFAULT_CHECKBLOCKS};
int64_t check_level{DEFAULT_CHECKLEVEL};
std::function<bool()> check_interrupt;
@@ -35,7 +36,13 @@ struct ChainstateLoadOptions {
//! case, and treat other cases as errors. More complex applications may want to
//! try reindexing in the generic failure case, and pass an interrupt callback
//! and exit cleanly in the interrupted case.
-enum class ChainstateLoadStatus { SUCCESS, FAILURE, FAILURE_INCOMPATIBLE_DB, INTERRUPTED };
+enum class ChainstateLoadStatus {
+ SUCCESS,
+ FAILURE,
+ FAILURE_INCOMPATIBLE_DB,
+ FAILURE_INSUFFICIENT_DBCACHE,
+ INTERRUPTED,
+};
//! Chainstate load status code and optional error string.
using ChainstateLoadResult = std::tuple<ChainstateLoadStatus, bilingual_str>;
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index e2a1efea55..28a619fe54 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1110,7 +1110,7 @@ static RPCHelpMan verifychain()
{"nblocks", RPCArg::Type::NUM, RPCArg::DefaultHint{strprintf("%d, 0=all", DEFAULT_CHECKBLOCKS)}, "The number of blocks to check."},
},
RPCResult{
- RPCResult::Type::BOOL, "", "Verified or not"},
+ RPCResult::Type::BOOL, "", "Verification finished successfully. If false, check debug.log for reason."},
RPCExamples{
HelpExampleCli("verifychain", "")
+ HelpExampleRpc("verifychain", "")
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index 6e72f69968..0b347d3141 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -218,6 +218,7 @@ void TestingSetup::LoadVerifyActivateChainstate()
options.prune = chainman.m_blockman.IsPruneMode();
options.check_blocks = m_args.GetIntArg("-checkblocks", DEFAULT_CHECKBLOCKS);
options.check_level = m_args.GetIntArg("-checklevel", DEFAULT_CHECKLEVEL);
+ options.require_full_verification = m_args.IsArgSet("-checkblocks") || m_args.IsArgSet("-checklevel");
auto [status, error] = LoadChainstate(chainman, m_cache_sizes, options);
assert(status == node::ChainstateLoadStatus::SUCCESS);
diff --git a/src/validation.cpp b/src/validation.cpp
index 5a6db2674d..4da52b7d8b 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -4185,6 +4185,9 @@ VerifyDBResult CVerifyDB::VerifyDB(
LogPrintf("Verification: No coin database inconsistencies in last %i blocks (%i transactions)\n", block_count, nGoodTransactions);
+ if (skipped_l3_checks) {
+ return VerifyDBResult::SKIPPED_L3_CHECKS;
+ }
return VerifyDBResult::SUCCESS;
}
diff --git a/src/validation.h b/src/validation.h
index a9977e76e3..044b4ef823 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -353,6 +353,7 @@ enum class VerifyDBResult {
SUCCESS,
CORRUPTED_BLOCK_DB,
INTERRUPTED,
+ SKIPPED_L3_CHECKS,
};
/** RAII wrapper for VerifyDB: Verify consistency of the block and coin databases */