Replace RPCNotifyBlockChange with waitTipChanged()

This refactoring commit uses the newly introduced waitTipChanged mining interface method to replace the RPCNotifyBlockChange mechanism.
This commit is contained in:
Sjors Provoost
2024-08-12 12:36:49 +02:00
parent 2a40ee1121
commit dca923150e
3 changed files with 39 additions and 57 deletions

View File

@@ -22,6 +22,7 @@
#include <hash.h>
#include <index/blockfilterindex.h>
#include <index/coinstatsindex.h>
#include <interfaces/mining.h>
#include <kernel/coinstats.h>
#include <logging/timer.h>
#include <net.h>
@@ -61,21 +62,12 @@
using kernel::CCoinsStats;
using kernel::CoinStatsHashType;
using interfaces::Mining;
using node::BlockManager;
using node::NodeContext;
using node::SnapshotMetadata;
using util::MakeUnorderedList;
struct CUpdatedBlock
{
uint256 hash;
int height;
};
static GlobalMutex cs_blockchange;
static std::condition_variable cond_blockchange;
static CUpdatedBlock latestblock GUARDED_BY(cs_blockchange);
std::tuple<std::unique_ptr<CCoinsViewCursor>, CCoinsStats, const CBlockIndex*>
PrepareUTXOSnapshot(
Chainstate& chainstate,
@@ -262,16 +254,6 @@ static RPCHelpMan getbestblockhash()
};
}
void RPCNotifyBlockChange(const CBlockIndex* pindex)
{
if(pindex) {
LOCK(cs_blockchange);
latestblock.hash = pindex->GetBlockHash();
latestblock.height = pindex->nHeight;
}
cond_blockchange.notify_all();
}
static RPCHelpMan waitfornewblock()
{
return RPCHelpMan{"waitfornewblock",
@@ -298,16 +280,14 @@ static RPCHelpMan waitfornewblock()
timeout = request.params[0].getInt<int>();
if (timeout < 0) throw JSONRPCError(RPC_MISC_ERROR, "Negative timeout");
CUpdatedBlock block;
{
WAIT_LOCK(cs_blockchange, lock);
block = latestblock;
if(timeout)
cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&block]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {return latestblock.height != block.height || latestblock.hash != block.hash || !IsRPCRunning(); });
else
cond_blockchange.wait(lock, [&block]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {return latestblock.height != block.height || latestblock.hash != block.hash || !IsRPCRunning(); });
block = latestblock;
NodeContext& node = EnsureAnyNodeContext(request.context);
Mining& miner = EnsureMining(node);
auto block{CHECK_NONFATAL(miner.getTip()).value()};
if (IsRPCRunning()) {
block = timeout ? miner.waitTipChanged(block.hash, std::chrono::milliseconds(timeout)) : miner.waitTipChanged(block.hash);
}
UniValue ret(UniValue::VOBJ);
ret.pushKV("hash", block.hash.GetHex());
ret.pushKV("height", block.height);
@@ -346,14 +326,20 @@ static RPCHelpMan waitforblock()
timeout = request.params[1].getInt<int>();
if (timeout < 0) throw JSONRPCError(RPC_MISC_ERROR, "Negative timeout");
CUpdatedBlock block;
{
WAIT_LOCK(cs_blockchange, lock);
if(timeout)
cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&hash]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {return latestblock.hash == hash || !IsRPCRunning();});
else
cond_blockchange.wait(lock, [&hash]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {return latestblock.hash == hash || !IsRPCRunning(); });
block = latestblock;
NodeContext& node = EnsureAnyNodeContext(request.context);
Mining& miner = EnsureMining(node);
auto block{CHECK_NONFATAL(miner.getTip()).value()};
const auto deadline{std::chrono::steady_clock::now() + 1ms * timeout};
while (IsRPCRunning() && block.hash != hash) {
if (timeout) {
auto now{std::chrono::steady_clock::now()};
if (now >= deadline) break;
const MillisecondsDouble remaining{deadline - now};
block = miner.waitTipChanged(block.hash, remaining);
} else {
block = miner.waitTipChanged(block.hash);
}
}
UniValue ret(UniValue::VOBJ);
@@ -395,15 +381,23 @@ static RPCHelpMan waitforblockheight()
timeout = request.params[1].getInt<int>();
if (timeout < 0) throw JSONRPCError(RPC_MISC_ERROR, "Negative timeout");
CUpdatedBlock block;
{
WAIT_LOCK(cs_blockchange, lock);
if(timeout)
cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&height]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {return latestblock.height >= height || !IsRPCRunning();});
else
cond_blockchange.wait(lock, [&height]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {return latestblock.height >= height || !IsRPCRunning(); });
block = latestblock;
NodeContext& node = EnsureAnyNodeContext(request.context);
Mining& miner = EnsureMining(node);
auto block{CHECK_NONFATAL(miner.getTip()).value()};
const auto deadline{std::chrono::steady_clock::now() + 1ms * timeout};
while (IsRPCRunning() && block.height < height) {
if (timeout) {
auto now{std::chrono::steady_clock::now()};
if (now >= deadline) break;
const MillisecondsDouble remaining{deadline - now};
block = miner.waitTipChanged(block.hash, remaining);
} else {
block = miner.waitTipChanged(block.hash);
}
}
UniValue ret(UniValue::VOBJ);
ret.pushKV("hash", block.hash.GetHex());
ret.pushKV("height", block.height);

View File

@@ -35,9 +35,6 @@ static constexpr int NUM_GETBLOCKSTATS_PERCENTILES = 5;
*/
double GetDifficulty(const CBlockIndex& blockindex);
/** Callback for when block tip changed. */
void RPCNotifyBlockChange(const CBlockIndex*);
/** Block description to JSON */
UniValue blockToJSON(node::BlockManager& blockman, const CBlock& block, const CBlockIndex& tip, const CBlockIndex& blockindex, TxVerbosity verbosity) LOCKS_EXCLUDED(cs_main);