From 53c911860cc07e9fa7270b3ccae446676a0a007f Mon Sep 17 00:00:00 2001 From: Sjors Provoost Date: Mon, 12 Aug 2024 15:55:44 +0200 Subject: [PATCH] rpc: add optional blockhash to waitfornewblock --- doc/release-30635.md | 4 ++++ src/rpc/blockchain.cpp | 16 ++++++++++++++++ test/functional/rpc_blockchain.py | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 doc/release-30635.md diff --git a/doc/release-30635.md b/doc/release-30635.md new file mode 100644 index 00000000000000..085112dcb27f82 --- /dev/null +++ b/doc/release-30635.md @@ -0,0 +1,4 @@ +Updated RPCs +------------ + +- The waitfornewblock RPC takes an optional `blockhash` argument. (#30635) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 9d7ad99f6387da..105e82dde53e23 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -259,6 +259,7 @@ static RPCHelpMan waitfornewblock() "\nMake sure to use no RPC timeout (bitcoin-cli -rpcclienttimeout=0)", { {"timeout", RPCArg::Type::NUM, RPCArg::Default{0}, "Time in milliseconds to wait for a response. 0 indicates no timeout."}, + {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "Last known block hash. Returns immediately if the tip is different."}, }, RPCResult{ RPCResult::Type::OBJ, "", "", @@ -280,7 +281,22 @@ static RPCHelpMan waitfornewblock() NodeContext& node = EnsureAnyNodeContext(request.context); Mining& miner = EnsureMining(node); + // Use tip as reference block, unless a block hash was provided. auto block{CHECK_NONFATAL(miner.getTip()).value()}; + if (!request.params[1].isNull()) { + uint256 hash(ParseHashV(request.params[1], "blockhash")); + { + ChainstateManager& chainman = EnsureAnyChainman(request.context); + LOCK(cs_main); + const CBlockIndex* block_index{chainman.m_blockman.LookupBlockIndex(hash)}; + if (!block_index) { + throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); + } + block.hash = block_index->GetBlockHash(); + block.height = block_index->nHeight; + } + } + if (IsRPCRunning()) { block = timeout ? miner.waitTipChanged(block.hash, std::chrono::milliseconds(timeout)) : miner.waitTipChanged(block.hash); } diff --git a/test/functional/rpc_blockchain.py b/test/functional/rpc_blockchain.py index 82c67256717012..5fc166b54c0bb3 100755 --- a/test/functional/rpc_blockchain.py +++ b/test/functional/rpc_blockchain.py @@ -536,7 +536,7 @@ def _test_waitforblock(self): node.reconsiderblock(rollback_hash) # The chain has probably already been restored by the time reconsiderblock returns, # but poll anyway. - self.wait_until(lambda: node.waitfornewblock(timeout=100)['hash'] == current_hash) + self.wait_until(lambda: node.waitfornewblock(blockhash=rollback_header['previousblockhash'])['hash'] == current_hash) def _test_waitforblockheight(self): self.log.info("Test waitforblockheight")