rpc: fix getblock(header) returns target for tip
What changed, and why it matters
This commit fixes a bug in Bitcoin Core's RPC (remote procedure call) responses. When users asked for data about an older block via getblock or getblockheader, the newly added 'target' field was incorrectly showing the current chain tip's target instead of that older block's actual target. The fix simply uses the correct block's data. It is a data accuracy bug, not a security vulnerability that allows theft, denial of service, or code execution.
No urgent security action required. Treat as a normal bug-fix release item. Users or services relying on the 'target' field for historical blocks should upgrade or verify values against other sources until patched.
Security signals we found
Incorrect RPC field value (wrong block target returned)
Data integrity issue in public API output
No memory safety, authentication, or consensus code changed
Evidence from the diff
In src/rpc/blockchain.cpp, blockheaderToJSON() was passing the chain tip (tip) to GetTarget() when serializing the ‘target’ field, rather than the requested blockindex. This caused getblock and getblockheader to return the wrong target for any non-tip block. The one-line change passes blockindex to GetTarget() so the returned target matches the block being queried. A mainnet functional test was added to verify historical target/difficulty/bits values.
Changed components
src/rpc/blockchain.cppgetblock RPCgetblockheader RPCInspect captured patch +13 / −1
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index bd5deedf..4ef863a4 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -166,7 +166,7 @@ UniValue blockheaderToJSON(const CBlockIndex& tip, const CBlockIndex& blockindex
result.pushKV("mediantime", blockindex.GetMedianTimePast());
result.pushKV("nonce", blockindex.nNonce);
result.pushKV("bits", strprintf("%08x", blockindex.nBits));
- result.pushKV("target", GetTarget(tip, pow_limit).GetHex());
+ result.pushKV("target", GetTarget(blockindex, pow_limit).GetHex());
result.pushKV("difficulty", GetDifficulty(blockindex));
result.pushKV("chainwork", blockindex.nChainWork.GetHex());
result.pushKV("nTx", blockindex.nTx);
diff --git a/test/functional/mining_mainnet.py b/test/functional/mining_mainnet.py
index eafa991c..67219100 100755
--- a/test/functional/mining_mainnet.py
+++ b/test/functional/mining_mainnet.py
@@ -109,5 +109,17 @@ class MiningMainnetTest(BitcoinTestFramework):
height = 2016
prev_hash = self.mine(height, prev_hash, blocks, node)
assert_equal(node.getblockcount(), height)
+
+ mining_info = node.getmininginfo()
+ assert_equal(mining_info['difficulty'], 4)
+
+ self.log.info("getblock RPC should show historical target")
+ block_info = node.getblock(node.getblockhash(1))
+
+ assert_equal(block_info['difficulty'], 1)
+ assert_equal(block_info['bits'], nbits_str(DIFF_1_N_BITS))
+ assert_equal(block_info['target'], target_str(DIFF_1_TARGET))
+
+
if __name__ == '__main__':
MiningMainnetTest(__file__).main()
Why this scored 21/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.