diff options
author | Sjors Provoost <sjors@sprovoost.nl> | 2024-06-07 11:51:18 +0200 |
---|---|---|
committer | Sjors Provoost <sjors@sprovoost.nl> | 2024-06-18 18:47:52 +0200 |
commit | dda0b0834faf7be7e8938bf63e7bb01cd54a416a (patch) | |
tree | c63148232d2de5d4cb3a7b8125bdc952813a53d8 | |
parent | 7b4d3249ced93ec5986500e43b324005ed89502f (diff) |
rpc: minize getTipHash() calls in gbt
Set tip at the start of the function and only update it for a long poll.
Additionally have getTipHash return an optional, so the
caller can explicitly check that a tip exists.
-rw-r--r-- | src/interfaces/mining.h | 5 | ||||
-rw-r--r-- | src/node/interfaces.cpp | 4 | ||||
-rw-r--r-- | src/rpc/mining.cpp | 17 |
3 files changed, 17 insertions, 9 deletions
diff --git a/src/interfaces/mining.h b/src/interfaces/mining.h index cd092397f3..6e47333fd5 100644 --- a/src/interfaces/mining.h +++ b/src/interfaces/mining.h @@ -5,6 +5,7 @@ #ifndef BITCOIN_INTERFACES_MINING_H #define BITCOIN_INTERFACES_MINING_H +#include <optional> #include <uint256.h> namespace node { @@ -29,8 +30,8 @@ public: //! If this chain is exclusively used for testing virtual bool isTestChain() = 0; - //! Returns the hash for the tip of this chain, 0 if none - virtual uint256 getTipHash() = 0; + //! Returns the hash for the tip of this chain + virtual std::optional<uint256> getTipHash() = 0; /** * Construct a new block template diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 2633ff1b98..68c1c598cd 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -847,11 +847,11 @@ public: return chainman().GetParams().IsTestChain(); } - uint256 getTipHash() override + std::optional<uint256> getTipHash() override { LOCK(::cs_main); CBlockIndex* tip{chainman().ActiveChain().Tip()}; - if (!tip) return uint256{0}; + if (!tip) return {}; return tip->GetBlockHash(); } diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index e404cea90f..9324ba4a1c 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -667,6 +667,9 @@ static RPCHelpMan getblocktemplate() ChainstateManager& chainman = EnsureChainman(node); Mining& miner = EnsureMining(node); LOCK(cs_main); + std::optional<uint256> maybe_tip{miner.getTipHash()}; + CHECK_NONFATAL(maybe_tip); + uint256 tip{maybe_tip.value()}; std::string strMode = "template"; UniValue lpval = NullUniValue; @@ -706,7 +709,7 @@ static RPCHelpMan getblocktemplate() } // testBlockValidity only supports blocks built on the current Tip - if (block.hashPrevBlock != miner.getTipHash()) { + if (block.hashPrevBlock != tip) { return "inconclusive-not-best-prevblk"; } BlockValidationState state; @@ -757,7 +760,7 @@ static RPCHelpMan getblocktemplate() else { // NOTE: Spec does not specify behaviour for non-string longpollid, but this makes testing easier - hashWatchedChain = miner.getTipHash(); + hashWatchedChain = tip; nTransactionsUpdatedLastLP = nTransactionsUpdatedLast; } @@ -781,6 +784,10 @@ static RPCHelpMan getblocktemplate() } ENTER_CRITICAL_SECTION(cs_main); + std::optional<uint256> maybe_tip{miner.getTipHash()}; + CHECK_NONFATAL(maybe_tip); + tip = maybe_tip.value(); + if (!IsRPCRunning()) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Shutting down"); // TODO: Maybe recheck connections/IBD and (if something wrong) send an expires-immediately template to stop miners? @@ -802,7 +809,7 @@ static RPCHelpMan getblocktemplate() static CBlockIndex* pindexPrev; static int64_t time_start; static std::unique_ptr<CBlockTemplate> pblocktemplate; - if (!pindexPrev || pindexPrev->GetBlockHash() != miner.getTipHash() || + if (!pindexPrev || pindexPrev->GetBlockHash() != tip || (miner.getTransactionsUpdated() != nTransactionsUpdatedLast && GetTime() - time_start > 5)) { // Clear pindexPrev so future calls make a new block, despite any failures from here on @@ -810,7 +817,7 @@ static RPCHelpMan getblocktemplate() // Store the pindexBest used before createNewBlock, to avoid races nTransactionsUpdatedLast = miner.getTransactionsUpdated(); - CBlockIndex* pindexPrevNew = chainman.m_blockman.LookupBlockIndex(miner.getTipHash()); + CBlockIndex* pindexPrevNew = chainman.m_blockman.LookupBlockIndex(tip); time_start = GetTime(); // Create new block @@ -943,7 +950,7 @@ static RPCHelpMan getblocktemplate() result.pushKV("transactions", std::move(transactions)); result.pushKV("coinbaseaux", std::move(aux)); result.pushKV("coinbasevalue", (int64_t)pblock->vtx[0]->vout[0].nValue); - result.pushKV("longpollid", miner.getTipHash().GetHex() + ToString(nTransactionsUpdatedLast)); + result.pushKV("longpollid", tip.GetHex() + ToString(nTransactionsUpdatedLast)); result.pushKV("target", hashTarget.GetHex()); result.pushKV("mintime", (int64_t)pindexPrev->GetMedianTimePast()+1); result.pushKV("mutable", std::move(aMutable)); |