mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-21 15:50:07 +01:00
Merge bitcoin/bitcoin#31785: Have createNewBlock() wait for tip, make rpc handle shutdown during long poll and wait methods
05117e6e17rpc: clarify longpoll behavior (Sjors Provoost)5315278e7cHave createNewBlock() wait for a tip (Sjors Provoost)64a2795fd4rpc: handle shutdown during long poll and wait methods (Sjors Provoost)a3bf43343frpc: drop unneeded IsRPCRunning() guards (Sjors Provoost)f9cf8bd0abHandle negative timeout for waitTipChanged() (Sjors Provoost) Pull request description: This PR prevents Mining interface methods from sometimes crashing when called during startup before a tip is connected. It also makes other improvements like making more RPC methods usable from the GUI. Specifically this PR: - Adds an `Assume` check to disallow passing negative timeout values to `Mining::waitTipChanged` - Makes `waitfornewblock`, `waitforblock` and `waitforblockheight` RPC methods usable from the GUI when `-server=1` is not set. - Changes `Mining::waitTipChanged` to return `optional<BlockRef>` instead of `BlockRef` and return `nullopt` instead of crashing if there is a timeout or if the node is shut down before a tip is connected. - Changes `Mining::waitTipChanged` to not time out before a tip is connected, so it is convenient and safe to call during startup, and only returns `nullopt` on early shutdowns. - Changes `Mining::createNewBlock` to block and wait for a tip to be connected if it is called on startup instead of crashing. Also documents that it will return null on early shutdowns. This allows `waitNext()` (added in https://github.com/bitcoin/bitcoin/pull/31283) to safely assume `TipBlock()` isn't `null`, not even during a scenario of early shutdown. Finally this PR clarifies long poll behaviour, mostly by adding code comments, but also through an early `break`. ACKs for top commit: achow101: ACK05117e6e17ryanofsky: Code review ACK05117e6e17, just updated a commit message since last review TheCharlatan: ACK05117e6e17vasild: ACK05117e6e17Tree-SHA512: 277c285a6e73dfff88fd379298190b264254996f98b93c91c062986ab35c2aa5e1fbfec4cd71d7b29dc2d68e33f252b5cfc501345f54939d6bd78599b71fec04
This commit is contained in:
@@ -46,6 +46,7 @@
|
||||
#include <memory>
|
||||
#include <stdint.h>
|
||||
|
||||
using interfaces::BlockRef;
|
||||
using interfaces::BlockTemplate;
|
||||
using interfaces::Mining;
|
||||
using node::BlockAssembler;
|
||||
@@ -775,9 +776,22 @@ static RPCHelpMan getblocktemplate()
|
||||
static unsigned int nTransactionsUpdatedLast;
|
||||
const CTxMemPool& mempool = EnsureMemPool(node);
|
||||
|
||||
if (!lpval.isNull())
|
||||
{
|
||||
// Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
|
||||
// Long Polling (BIP22)
|
||||
if (!lpval.isNull()) {
|
||||
/**
|
||||
* Wait to respond until either the best block changes, OR there are more
|
||||
* transactions.
|
||||
*
|
||||
* The check for new transactions first happens after 1 minute and
|
||||
* subsequently every 10 seconds. BIP22 does not require this particular interval.
|
||||
* On mainnet the mempool changes frequently enough that in practice this RPC
|
||||
* returns after 60 seconds, or sooner if the best block changes.
|
||||
*
|
||||
* getblocktemplate is unlikely to be called by bitcoin-cli, so
|
||||
* -rpcclienttimeout is not a concern. BIP22 recommends a long request timeout.
|
||||
*
|
||||
* The longpollid is assumed to be a tip hash if it has the right format.
|
||||
*/
|
||||
uint256 hashWatchedChain;
|
||||
unsigned int nTransactionsUpdatedLastLP;
|
||||
|
||||
@@ -786,6 +800,8 @@ static RPCHelpMan getblocktemplate()
|
||||
// Format: <hashBestChain><nTransactionsUpdatedLast>
|
||||
const std::string& lpstr = lpval.get_str();
|
||||
|
||||
// Assume the longpollid is a block hash. If it's not then we return
|
||||
// early below.
|
||||
hashWatchedChain = ParseHashV(lpstr.substr(0, 64), "longpollid");
|
||||
nTransactionsUpdatedLastLP = LocaleIndependentAtoi<int64_t>(lpstr.substr(64));
|
||||
}
|
||||
@@ -800,12 +816,20 @@ static RPCHelpMan getblocktemplate()
|
||||
LEAVE_CRITICAL_SECTION(cs_main);
|
||||
{
|
||||
MillisecondsDouble checktxtime{std::chrono::minutes(1)};
|
||||
while (tip == hashWatchedChain && IsRPCRunning()) {
|
||||
tip = miner.waitTipChanged(hashWatchedChain, checktxtime).hash;
|
||||
// Timeout: Check transactions for update
|
||||
// without holding the mempool lock to avoid deadlocks
|
||||
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
|
||||
while (IsRPCRunning()) {
|
||||
// If hashWatchedChain is not a real block hash, this will
|
||||
// return immediately.
|
||||
std::optional<BlockRef> maybe_tip{miner.waitTipChanged(hashWatchedChain, checktxtime)};
|
||||
// Node is shutting down
|
||||
if (!maybe_tip) break;
|
||||
tip = maybe_tip->hash;
|
||||
if (tip != hashWatchedChain) break;
|
||||
|
||||
// Check transactions for update without holding the mempool
|
||||
// lock to avoid deadlocks.
|
||||
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP) {
|
||||
break;
|
||||
}
|
||||
checktxtime = std::chrono::seconds(10);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user