Skip to content

Commit dca9231

Browse files
committed
Replace RPCNotifyBlockChange with waitTipChanged()
This refactoring commit uses the newly introduced waitTipChanged mining interface method to replace the RPCNotifyBlockChange mechanism.
1 parent 2a40ee1 commit dca9231

File tree

3 files changed

+39
-57
lines changed

3 files changed

+39
-57
lines changed

src/init.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -429,16 +429,12 @@ static void registerSignalHandler(int signal, void(*handler)(int))
429429
}
430430
#endif
431431

432-
static boost::signals2::connection rpc_notify_block_change_connection;
433432
static void OnRPCStarted()
434433
{
435-
rpc_notify_block_change_connection = uiInterface.NotifyBlockTip_connect(std::bind(RPCNotifyBlockChange, std::placeholders::_2));
436434
}
437435

438436
static void OnRPCStopped()
439437
{
440-
rpc_notify_block_change_connection.disconnect();
441-
RPCNotifyBlockChange(nullptr);
442438
g_best_block_cv.notify_all();
443439
LogDebug(BCLog::RPC, "RPC stopped.\n");
444440
}
@@ -2011,11 +2007,6 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
20112007
// cannot yet be called. Before we make it callable, we need to make sure
20122008
// that the RPC's view of the best block is valid and consistent with
20132009
// ChainstateManager's active tip.
2014-
//
2015-
// If we do not do this, RPC's view of the best block will be height=0 and
2016-
// hash=0x0. This will lead to erroroneous responses for things like
2017-
// waitforblockheight.
2018-
RPCNotifyBlockChange(WITH_LOCK(chainman.GetMutex(), return chainman.ActiveTip()));
20192010
SetRPCWarmupFinished();
20202011

20212012
uiInterface.InitMessage(_("Done loading").translated);

src/rpc/blockchain.cpp

Lines changed: 39 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <hash.h>
2323
#include <index/blockfilterindex.h>
2424
#include <index/coinstatsindex.h>
25+
#include <interfaces/mining.h>
2526
#include <kernel/coinstats.h>
2627
#include <logging/timer.h>
2728
#include <net.h>
@@ -61,21 +62,12 @@
6162
using kernel::CCoinsStats;
6263
using kernel::CoinStatsHashType;
6364

65+
using interfaces::Mining;
6466
using node::BlockManager;
6567
using node::NodeContext;
6668
using node::SnapshotMetadata;
6769
using util::MakeUnorderedList;
6870

69-
struct CUpdatedBlock
70-
{
71-
uint256 hash;
72-
int height;
73-
};
74-
75-
static GlobalMutex cs_blockchange;
76-
static std::condition_variable cond_blockchange;
77-
static CUpdatedBlock latestblock GUARDED_BY(cs_blockchange);
78-
7971
std::tuple<std::unique_ptr<CCoinsViewCursor>, CCoinsStats, const CBlockIndex*>
8072
PrepareUTXOSnapshot(
8173
Chainstate& chainstate,
@@ -262,16 +254,6 @@ static RPCHelpMan getbestblockhash()
262254
};
263255
}
264256

265-
void RPCNotifyBlockChange(const CBlockIndex* pindex)
266-
{
267-
if(pindex) {
268-
LOCK(cs_blockchange);
269-
latestblock.hash = pindex->GetBlockHash();
270-
latestblock.height = pindex->nHeight;
271-
}
272-
cond_blockchange.notify_all();
273-
}
274-
275257
static RPCHelpMan waitfornewblock()
276258
{
277259
return RPCHelpMan{"waitfornewblock",
@@ -298,16 +280,14 @@ static RPCHelpMan waitfornewblock()
298280
timeout = request.params[0].getInt<int>();
299281
if (timeout < 0) throw JSONRPCError(RPC_MISC_ERROR, "Negative timeout");
300282

301-
CUpdatedBlock block;
302-
{
303-
WAIT_LOCK(cs_blockchange, lock);
304-
block = latestblock;
305-
if(timeout)
306-
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(); });
307-
else
308-
cond_blockchange.wait(lock, [&block]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {return latestblock.height != block.height || latestblock.hash != block.hash || !IsRPCRunning(); });
309-
block = latestblock;
283+
NodeContext& node = EnsureAnyNodeContext(request.context);
284+
Mining& miner = EnsureMining(node);
285+
286+
auto block{CHECK_NONFATAL(miner.getTip()).value()};
287+
if (IsRPCRunning()) {
288+
block = timeout ? miner.waitTipChanged(block.hash, std::chrono::milliseconds(timeout)) : miner.waitTipChanged(block.hash);
310289
}
290+
311291
UniValue ret(UniValue::VOBJ);
312292
ret.pushKV("hash", block.hash.GetHex());
313293
ret.pushKV("height", block.height);
@@ -346,14 +326,20 @@ static RPCHelpMan waitforblock()
346326
timeout = request.params[1].getInt<int>();
347327
if (timeout < 0) throw JSONRPCError(RPC_MISC_ERROR, "Negative timeout");
348328

349-
CUpdatedBlock block;
350-
{
351-
WAIT_LOCK(cs_blockchange, lock);
352-
if(timeout)
353-
cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&hash]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {return latestblock.hash == hash || !IsRPCRunning();});
354-
else
355-
cond_blockchange.wait(lock, [&hash]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {return latestblock.hash == hash || !IsRPCRunning(); });
356-
block = latestblock;
329+
NodeContext& node = EnsureAnyNodeContext(request.context);
330+
Mining& miner = EnsureMining(node);
331+
332+
auto block{CHECK_NONFATAL(miner.getTip()).value()};
333+
const auto deadline{std::chrono::steady_clock::now() + 1ms * timeout};
334+
while (IsRPCRunning() && block.hash != hash) {
335+
if (timeout) {
336+
auto now{std::chrono::steady_clock::now()};
337+
if (now >= deadline) break;
338+
const MillisecondsDouble remaining{deadline - now};
339+
block = miner.waitTipChanged(block.hash, remaining);
340+
} else {
341+
block = miner.waitTipChanged(block.hash);
342+
}
357343
}
358344

359345
UniValue ret(UniValue::VOBJ);
@@ -395,15 +381,23 @@ static RPCHelpMan waitforblockheight()
395381
timeout = request.params[1].getInt<int>();
396382
if (timeout < 0) throw JSONRPCError(RPC_MISC_ERROR, "Negative timeout");
397383

398-
CUpdatedBlock block;
399-
{
400-
WAIT_LOCK(cs_blockchange, lock);
401-
if(timeout)
402-
cond_blockchange.wait_for(lock, std::chrono::milliseconds(timeout), [&height]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {return latestblock.height >= height || !IsRPCRunning();});
403-
else
404-
cond_blockchange.wait(lock, [&height]() EXCLUSIVE_LOCKS_REQUIRED(cs_blockchange) {return latestblock.height >= height || !IsRPCRunning(); });
405-
block = latestblock;
384+
NodeContext& node = EnsureAnyNodeContext(request.context);
385+
Mining& miner = EnsureMining(node);
386+
387+
auto block{CHECK_NONFATAL(miner.getTip()).value()};
388+
const auto deadline{std::chrono::steady_clock::now() + 1ms * timeout};
389+
390+
while (IsRPCRunning() && block.height < height) {
391+
if (timeout) {
392+
auto now{std::chrono::steady_clock::now()};
393+
if (now >= deadline) break;
394+
const MillisecondsDouble remaining{deadline - now};
395+
block = miner.waitTipChanged(block.hash, remaining);
396+
} else {
397+
block = miner.waitTipChanged(block.hash);
398+
}
406399
}
400+
407401
UniValue ret(UniValue::VOBJ);
408402
ret.pushKV("hash", block.hash.GetHex());
409403
ret.pushKV("height", block.height);

src/rpc/blockchain.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ static constexpr int NUM_GETBLOCKSTATS_PERCENTILES = 5;
3535
*/
3636
double GetDifficulty(const CBlockIndex& blockindex);
3737

38-
/** Callback for when block tip changed. */
39-
void RPCNotifyBlockChange(const CBlockIndex*);
40-
4138
/** Block description to JSON */
4239
UniValue blockToJSON(node::BlockManager& blockman, const CBlock& block, const CBlockIndex& tip, const CBlockIndex& blockindex, TxVerbosity verbosity) LOCKS_EXCLUDED(cs_main);
4340

0 commit comments

Comments
 (0)