rpc, log: add backgroundvalidation to getblockchaininfo
What changed, and why it matters
This commit simply adds a new optional information block called 'backgroundvalidation' to the getblockchaininfo RPC output. It exposes read-only status about an existing background chain-validation process, plus some minor capitalization fixes in help text. There is no security-relevant change.
No security action required; routine review/merge.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch extends getblockchaininfo in src/rpc/blockchain.cpp to include an optional ‘backgroundvalidation’ object when a historical block range exists (e.g., assumeutxo snapshot use). It reports snapshot height, validated block height, best block hash, median time, chain work, and verification progress. It also lowercases a few help-string sentences. A functional test is updated to confirm the field is absent when assumeutxo is not in use. No logic that validates, accepts, or relays blocks/transactions is modified.
Changed components
src/rpc/blockchain.cpptest/functional/rpc_blockchain.pyInspect captured patch +28 / −3
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 5156f658..dc6473b9 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1374,12 +1374,21 @@ RPCHelpMan getblockchaininfo()
{RPCResult::Type::NUM, "headers", "the current number of headers we have validated"},
{RPCResult::Type::STR, "bestblockhash", "the hash of the currently best block"},
{RPCResult::Type::STR_HEX, "bits", "nBits: compact representation of the block difficulty target"},
- {RPCResult::Type::STR_HEX, "target", "The difficulty target"},
+ {RPCResult::Type::STR_HEX, "target", "the difficulty target"},
{RPCResult::Type::NUM, "difficulty", "the current difficulty"},
- {RPCResult::Type::NUM_TIME, "time", "The block time expressed in " + UNIX_EPOCH_TIME},
- {RPCResult::Type::NUM_TIME, "mediantime", "The median block time expressed in " + UNIX_EPOCH_TIME},
+ {RPCResult::Type::NUM_TIME, "time", "the block time expressed in " + UNIX_EPOCH_TIME},
+ {RPCResult::Type::NUM_TIME, "mediantime", "the median block time expressed in " + UNIX_EPOCH_TIME},
{RPCResult::Type::NUM, "verificationprogress", "estimate of verification progress [0..1]"},
{RPCResult::Type::BOOL, "initialblockdownload", "(debug information) estimate of whether this node is in Initial Block Download mode"},
+ {RPCResult::Type::OBJ, "backgroundvalidation", /*optional=*/true, "state info regarding background validation process",
+ {
+ {RPCResult::Type::NUM, "snapshotheight", "the height of the snapshot block. Background validation verifies the chain from genesis up to this height"},
+ {RPCResult::Type::NUM, "blocks", "the height of the most-work background fully-validated chain. The genesis block has height 0"},
+ {RPCResult::Type::STR, "bestblockhash", "the hash of the currently best block validated in the background"},
+ {RPCResult::Type::NUM_TIME, "mediantime", "the median block time expressed in " + UNIX_EPOCH_TIME},
+ {RPCResult::Type::NUM, "verificationprogress", "estimate of background verification progress [0..1]"},
+ {RPCResult::Type::STR_HEX, "chainwork", "total amount of work in background validated chain, in hexadecimal"},
+ }},
{RPCResult::Type::STR_HEX, "chainwork", "total amount of work in active chain, in hexadecimal"},
{RPCResult::Type::NUM, "size_on_disk", "the estimated size of the block and undo files on disk"},
{RPCResult::Type::BOOL, "pruned", "if the blocks are subject to pruning"},
@@ -1420,6 +1429,19 @@ RPCHelpMan getblockchaininfo()
obj.pushKV("mediantime", tip.GetMedianTimePast());
obj.pushKV("verificationprogress", chainman.GuessVerificationProgress(&tip));
obj.pushKV("initialblockdownload", chainman.IsInitialBlockDownload());
+ auto historical_blocks{chainman.GetHistoricalBlockRange()};
+ if (historical_blocks) {
+ UniValue background_validation(UniValue::VOBJ);
+ const CBlockIndex& btip{*CHECK_NONFATAL(historical_blocks->first)};
+ const CBlockIndex& btarget{*CHECK_NONFATAL(historical_blocks->second)};
+ background_validation.pushKV("snapshotheight", btarget.nHeight);
+ background_validation.pushKV("blocks", btip.nHeight);
+ background_validation.pushKV("bestblockhash", btip.GetBlockHash().GetHex());
+ background_validation.pushKV("mediantime", btip.GetMedianTimePast());
+ background_validation.pushKV("chainwork", btip.nChainWork.GetHex());
+ background_validation.pushKV("verificationprogress", chainman.GetBackgroundVerificationProgress(btip));
+ obj.pushKV("backgroundvalidation", std::move(background_validation));
+ }
obj.pushKV("chainwork", tip.nChainWork.GetHex());
obj.pushKV("size_on_disk", chainman.m_blockman.CalculateCurrentUsage());
obj.pushKV("pruned", chainman.m_blockman.IsPruneMode());
diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py
index cecd0c03..18a67ce5 100755
--- a/test/functional/rpc_blockchain.py
+++ b/test/functional/rpc_blockchain.py
@@ -170,6 +170,9 @@ class BlockchainTest(BitcoinTestFramework):
assert res['pruned']
assert not res['automatic_pruning']
+ # check background validation is not present when we are not using assumeutxo
+ assert "backgroundvalidation" not in res.keys()
+
self.restart_node(0, ['-stopatheight=207'])
res = self.nodes[0].getblockchaininfo()
# should have exact keys
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.