Merge bitcoin/bitcoin#36081: rpc: add bestblockhash to getmininginfo
What changed, and why it matters
This commit adds a new 'bestblockhash' field to the getmininginfo RPC response in Bitcoin Core. It is a feature enhancement, not a security fix. The change lets mining software read the current chain tip hash and the next block's difficulty bits in a single API call, avoiding a harmless race where the chain tip might change between two separate calls. There is no vulnerability being patched.
No security action required. Treat as a normal feature/API improvement.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch extends the getmininginfo RPC to return the active chain tip’s block hash alongside the existing nBits/difficulty fields. It updates the RPC result schema, adds one pushKV call using tip.GetBlockHash().GetHex(), and adds functional tests verifying the new field matches getbestblockhash. No locks, validation, consensus, or cryptography code is modified.
Changed components
src/rpc/mining.cpptest/functional/mining_basic.pytest/functional/mining_mainnet.pydoc/release-notes-36081.mdInspect captured patch +12 / −0
### doc/release-notes-36081.md
@@ -0,0 +1,8 @@
+Updated RPCs
+------------
+
+- The `getmininginfo` RPC now returns a `bestblockhash` field. Together with
+ the existing `next` object this lets mining software obtain the tip hash and
+ the next block's `nBits` atomically from a single call, without a race
+ against a concurrent tip change between `getblockchaininfo` and
+ `getmininginfo`.
### src/rpc/mining.cpp
@@ -454,6 +454,7 @@ static RPCMethod getmininginfo()
RPCResult::Type::OBJ, "", "",
{
{RPCResult::Type::NUM, "blocks", "The current block"},
+ {RPCResult::Type::STR_HEX, "bestblockhash", "The hash of the current best block"},
{RPCResult::Type::NUM, "currentblockweight", /*optional=*/true, "The block weight (including reserved weight for block header, txs count and coinbase tx) of the last assembled block (only present if a block was ever assembled)"},
{RPCResult::Type::NUM, "currentblocktx", /*optional=*/true, "The number of block transactions (excluding coinbase) of the last assembled block (only present if a block was ever assembled)"},
{RPCResult::Type::STR_HEX, "bits", "The current nBits, compact representation of the block difficulty target"},
@@ -495,6 +496,7 @@ static RPCMethod getmininginfo()
UniValue obj(UniValue::VOBJ);
obj.pushKV("blocks", active_chain.Height());
+ obj.pushKV("bestblockhash", tip.GetBlockHash().GetHex());
if (BlockAssembler::m_last_block_weight) obj.pushKV("currentblockweight", *BlockAssembler::m_last_block_weight);
if (BlockAssembler::m_last_block_num_txs) obj.pushKV("currentblocktx", *BlockAssembler::m_last_block_num_txs);
obj.pushKV("bits", strprintf("%08x", tip.nBits));
### test/functional/mining_basic.py
@@ -432,6 +432,7 @@ def run_test(self):
self.log.info('getmininginfo')
mining_info = node.getmininginfo()
assert_equal(mining_info['blocks'], 200)
+ assert_equal(mining_info['bestblockhash'], node.getbestblockhash())
assert_equal(mining_info['chain'], self.chain)
assert 'currentblocktx' not in mining_info
assert 'currentblockweight' not in mining_info
### test/functional/mining_mainnet.py
@@ -96,6 +96,7 @@ def run_test(self):
self.log.info("Check difficulty adjustment with getmininginfo")
mining_info = node.getmininginfo()
+ assert_equal(mining_info['bestblockhash'], prev_hash)
assert_equal(mining_info['difficulty'], 1)
assert_equal(mining_info['bits'], nbits_str(DIFF_1_N_BITS))
assert_equal(mining_info['target'], target_str(DIFF_1_TARGET))Why this scored 20/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.