Skip to content

Commit 8a94cf8

Browse files
committed
Merge bitcoin/bitcoin#30635: rpc: add optional blockhash to waitfornewblock, unhide wait methods in help
c6e2c31 rpc: unhide waitfor{block,newblock,blockheight} (Sjors Provoost) 0786b75 rpc: add optional blockhash to waitfornewblock (Sjors Provoost) Pull request description: The `waitfornewblock` is inherently racy as the tip may have changed since the last RPC call, and can even change during initial processing of this call. Add an optional `blockhash` argument so the caller can specify their current tip. Return immediately if our tip is different. I've made it fail if `LookupBlockIndex` fails. This should never happen if the user got the block hash from our RPC in the first place. Finally, the `waitfor{block,newblock,blockheight}` RPC methods are no longer hidden in `help`: - the changes in #30409 ensured these methods _could_ work in the GUI - #31785 removed the guards that prevented GUI users from using them - this PR makes `waitfornewblock` reliable So there's no more reason to hide them. ACKs for top commit: TheCharlatan: Re-ACK c6e2c31 ryanofsky: Code review ACK c6e2c31. Just rebased and tweaked documentation since last review. glozow: utACK c6e2c31 Tree-SHA512: 84a0c94cb9a2e4449e7a395cf3dce1650626bd852e30e0e238a1aafae19d57bf440bfac226fd4da44eaa8d1b2fa4a8c1177b6c716235ab862a72ff5bf8fc67ac
2 parents dc78ed2 + c6e2c31 commit 8a94cf8

File tree

3 files changed

+26
-7
lines changed

3 files changed

+26
-7
lines changed

doc/release-30635.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Updated RPCs
2+
------------
3+
4+
- The waitfornewblock now takes an optional `current_tip` argument. It is also no longer hidden. (#30635)
5+
- The waitforblock and waitforblockheight RPCs are no longer hidden. (#30635)

src/rpc/blockchain.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ static RPCHelpMan waitfornewblock()
271271
"\nMake sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)",
272272
{
273273
{"timeout", RPCArg::Type::NUM, RPCArg::Default{0}, "Time in milliseconds to wait for a response. 0 indicates no timeout."},
274+
{"current_tip", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "Method waits for the chain tip to differ from this."},
274275
},
275276
RPCResult{
276277
RPCResult::Type::OBJ, "", "",
@@ -292,10 +293,22 @@ static RPCHelpMan waitfornewblock()
292293
NodeContext& node = EnsureAnyNodeContext(request.context);
293294
Mining& miner = EnsureMining(node);
294295

295-
// Abort if RPC came out of warmup too early
296+
// If the caller provided a current_tip value, pass it to waitTipChanged().
297+
//
298+
// If the caller did not provide a current tip hash, call getTip() to get
299+
// one and wait for the tip to be different from this value. This mode is
300+
// less reliable because if the tip changed between waitfornewblock calls,
301+
// it will need to change a second time before this call returns.
296302
BlockRef current_block{CHECK_NONFATAL(miner.getTip()).value()};
297-
std::optional<BlockRef> block = timeout ? miner.waitTipChanged(current_block.hash, std::chrono::milliseconds(timeout)) :
298-
miner.waitTipChanged(current_block.hash);
303+
304+
uint256 tip_hash{request.params[1].isNull()
305+
? current_block.hash
306+
: ParseHashV(request.params[1], "current_tip")};
307+
308+
// If the user provided an invalid current_tip then this call immediately
309+
// returns the current tip.
310+
std::optional<BlockRef> block = timeout ? miner.waitTipChanged(tip_hash, std::chrono::milliseconds(timeout)) :
311+
miner.waitTipChanged(tip_hash);
299312

300313
// Return current block upon shutdown
301314
if (block) current_block = *block;
@@ -3461,9 +3474,9 @@ void RegisterBlockchainRPCCommands(CRPCTable& t)
34613474
{"blockchain", &getchainstates},
34623475
{"hidden", &invalidateblock},
34633476
{"hidden", &reconsiderblock},
3464-
{"hidden", &waitfornewblock},
3465-
{"hidden", &waitforblock},
3466-
{"hidden", &waitforblockheight},
3477+
{"blockchain", &waitfornewblock},
3478+
{"blockchain", &waitforblock},
3479+
{"blockchain", &waitforblockheight},
34673480
{"hidden", &syncwithvalidationinterfacequeue},
34683481
};
34693482
for (const auto& c : commands) {

test/functional/rpc_blockchain.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,8 @@ def _test_waitforblock(self):
593593
node.reconsiderblock(rollback_hash)
594594
# The chain has probably already been restored by the time reconsiderblock returns,
595595
# but poll anyway.
596-
self.wait_until(lambda: node.waitfornewblock(timeout=100)['hash'] == current_hash)
596+
self.wait_until(lambda: node.waitfornewblock(current_tip=rollback_header['previousblockhash'])['hash'] == current_hash)
597+
597598
assert_raises_rpc_error(-1, "Negative timeout", node.waitfornewblock, -1)
598599

599600
def _test_waitforblockheight(self):

0 commit comments

Comments
 (0)