Skip to content

Commit ef1808a

Browse files
laanwjknst
authored andcommitted
Merge bitcoin#19655: rpc: Catch listsinceblock target_confirmations exceeding block count
c133cdc Cap listsinceblock target_confirmations param (Adam Stein) Pull request description: This addresses an issue brought up in bitcoin#19587. Currently, the `target_confirmations` parameter to `listsinceblock` is not checked for being too large. When `target_confirmations` is greater than one more than the current number of blocks, `listsinceblock` fails with error code -1. In comparison, when `target_confirmations` is less than 1, a -8 "Invalid parameter" error code is thrown. This PR fixes the issue by returning a -8 "Invalid parameter" error if the `target_confirmations` value corresponds to a block with more confirmations than the genesis block. This happens if `target_confirmations` exceeds one more than the number of blocks. ACKs for top commit: laanwj: Code review ACK c133cdc ryanofsky: Code review ACK c133cdc. Just suggested changes since last review. Thanks! Tree-SHA512: 02680f4cb937d2c24d5019abd0ebfa188b8a50679a1e64e9c26bfe5c17eef6aea906832e6e2d492ba8a2ea160041bf185d66795ee691e340f6793db03c21b89a
1 parent 75a77fa commit ef1808a

File tree

2 files changed

+24
-1
lines changed

2 files changed

+24
-1
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1573,7 +1573,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
15731573
{RPCResult::Type::ARR, "removed", "<structure is the same as \"transactions\" above, only present if include_removed=true>\n"
15741574
"Note: transactions that were re-added in the active chain will appear as-is in this array, and may thus have a positive confirmation count."
15751575
, {{RPCResult::Type::ELISION, "", ""},}},
1576-
{RPCResult::Type::STR_HEX, "lastblockhash", "The hash of the block (target_confirmations-1) from the best block on the main chain. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones."}
1576+
{RPCResult::Type::STR_HEX, "lastblockhash", "The hash of the block (target_confirmations-1) from the best block on the main chain, or the genesis hash if the referenced block does not exist yet. This is typically used to feed back into listsinceblock the next time you call it. So you would generally use a target_confirmations of say 6, so you will be continually re-notified of transactions until they've reached 6 confirmations plus any new ones."}
15771577
}
15781578
},
15791579
RPCExamples{
@@ -1655,6 +1655,7 @@ static UniValue listsinceblock(const JSONRPCRequest& request)
16551655
}
16561656

16571657
uint256 lastblock;
1658+
target_confirms = std::min(target_confirms, wallet.GetLastBlockHeight() + 1);
16581659
CHECK_NONFATAL(wallet.chain().findAncestorByHeight(wallet.GetLastBlockHash(), wallet.GetLastBlockHeight() + 1 - target_confirms, FoundBlock().hash(lastblock)));
16591660

16601661
UniValue ret(UniValue::VOBJ);

test/functional/wallet_listsinceblock.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ def run_test(self):
3636
self.test_double_spend()
3737
self.test_double_send()
3838
self.double_spends_filtered()
39+
self.test_targetconfirmations()
3940

4041
def test_no_blockhash(self):
4142
self.log.info("Test no blockhash")
@@ -74,6 +75,27 @@ def test_invalid_blockhash(self):
7475
assert_raises_rpc_error(-8, "blockhash must be hexadecimal string (not 'Z000000000000000000000000000000000000000000000000000000000000000')", self.nodes[0].listsinceblock,
7576
"Z000000000000000000000000000000000000000000000000000000000000000")
7677

78+
def test_targetconfirmations(self):
79+
'''
80+
This tests when the value of target_confirmations exceeds the number of
81+
blocks in the main chain. In this case, the genesis block hash should be
82+
given for the `lastblock` property. If target_confirmations is < 1, then
83+
a -8 invalid parameter error is thrown.
84+
'''
85+
self.log.info("Test target_confirmations")
86+
blockhash, = self.nodes[2].generate(1)
87+
blockheight = self.nodes[2].getblockheader(blockhash)['height']
88+
self.sync_all()
89+
90+
assert_equal(
91+
self.nodes[0].getblockhash(0),
92+
self.nodes[0].listsinceblock(blockhash, blockheight + 1)['lastblock'])
93+
assert_equal(
94+
self.nodes[0].getblockhash(0),
95+
self.nodes[0].listsinceblock(blockhash, blockheight + 1000)['lastblock'])
96+
assert_raises_rpc_error(-8, "Invalid parameter",
97+
self.nodes[0].listsinceblock, blockhash, 0)
98+
7799
def test_reorg(self):
78100
'''
79101
`listsinceblock` did not behave correctly when handed a block that was

0 commit comments

Comments
 (0)