Skip to content

Commit 05117e6

Browse files
committed
rpc: clarify longpoll behavior
Move the comparison to hashWatchedChain inside the while loop. Although this early return prevents the GetTransactionsUpdated() call in cases where the tip updates, it's only done to improve readability. The check itself is very cheap (although a more useful check might not be). Also add code comments.
1 parent 5315278 commit 05117e6

File tree

1 file changed

+27
-7
lines changed

1 file changed

+27
-7
lines changed

src/rpc/mining.cpp

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -776,9 +776,22 @@ static RPCHelpMan getblocktemplate()
776776
static unsigned int nTransactionsUpdatedLast;
777777
const CTxMemPool& mempool = EnsureMemPool(node);
778778

779-
if (!lpval.isNull())
780-
{
781-
// Wait to respond until either the best block changes, OR a minute has passed and there are more transactions
779+
// Long Polling (BIP22)
780+
if (!lpval.isNull()) {
781+
/**
782+
* Wait to respond until either the best block changes, OR there are more
783+
* transactions.
784+
*
785+
* The check for new transactions first happens after 1 minute and
786+
* subsequently every 10 seconds. BIP22 does not require this particular interval.
787+
* On mainnet the mempool changes frequently enough that in practice this RPC
788+
* returns after 60 seconds, or sooner if the best block changes.
789+
*
790+
* getblocktemplate is unlikely to be called by bitcoin-cli, so
791+
* -rpcclienttimeout is not a concern. BIP22 recommends a long request timeout.
792+
*
793+
* The longpollid is assumed to be a tip hash if it has the right format.
794+
*/
782795
uint256 hashWatchedChain;
783796
unsigned int nTransactionsUpdatedLastLP;
784797

@@ -787,6 +800,8 @@ static RPCHelpMan getblocktemplate()
787800
// Format: <hashBestChain><nTransactionsUpdatedLast>
788801
const std::string& lpstr = lpval.get_str();
789802

803+
// Assume the longpollid is a block hash. If it's not then we return
804+
// early below.
790805
hashWatchedChain = ParseHashV(lpstr.substr(0, 64), "longpollid");
791806
nTransactionsUpdatedLastLP = LocaleIndependentAtoi<int64_t>(lpstr.substr(64));
792807
}
@@ -801,15 +816,20 @@ static RPCHelpMan getblocktemplate()
801816
LEAVE_CRITICAL_SECTION(cs_main);
802817
{
803818
MillisecondsDouble checktxtime{std::chrono::minutes(1)};
804-
while (tip == hashWatchedChain && IsRPCRunning()) {
819+
while (IsRPCRunning()) {
820+
// If hashWatchedChain is not a real block hash, this will
821+
// return immediately.
805822
std::optional<BlockRef> maybe_tip{miner.waitTipChanged(hashWatchedChain, checktxtime)};
806823
// Node is shutting down
807824
if (!maybe_tip) break;
808825
tip = maybe_tip->hash;
809-
// Timeout: Check transactions for update
810-
// without holding the mempool lock to avoid deadlocks
811-
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP)
826+
if (tip != hashWatchedChain) break;
827+
828+
// Check transactions for update without holding the mempool
829+
// lock to avoid deadlocks.
830+
if (mempool.GetTransactionsUpdated() != nTransactionsUpdatedLastLP) {
812831
break;
832+
}
813833
checktxtime = std::chrono::seconds(10);
814834
}
815835
}

0 commit comments

Comments
 (0)