Skip to content

Commit b94b27c

Browse files
SjorsTheCharlatan
andcommitted
Add waitTipChanged to Mining interface
Co-authored-by: TheCharlatan <[email protected]>
1 parent 7eccdaf commit b94b27c

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

src/interfaces/mining.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <primitives/transaction.h> // for CTransactionRef
1313
#include <stdint.h> // for int64_t
1414
#include <uint256.h> // for uint256
15+
#include <util/time.h> // for MillisecondsDouble
1516

1617
#include <memory> // for unique_ptr, shared_ptr
1718
#include <optional> // for optional
@@ -60,6 +61,17 @@ class Mining
6061
virtual std::optional<BlockRef> getTip() = 0;
6162

6263
/**
64+
* Waits for the tip to change
65+
*
66+
* @param[in] current_tip block hash of the current chain tip. Function waits
67+
* for the chain tip to change if this matches, otherwise
68+
* it returns right away.
69+
* @param[in] timeout how long to wait for a new tip
70+
* @returns Hash and height of the current chain tip after this call.
71+
*/
72+
virtual BlockRef waitTipChanged(uint256 current_tip, MillisecondsDouble timeout = MillisecondsDouble::max()) = 0;
73+
74+
/**
6375
* Construct a new block template
6476
*
6577
* @param[in] script_pub_key the coinbase output

src/node/interfaces.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <node/interface_ui.h>
3535
#include <node/mini_miner.h>
3636
#include <node/miner.h>
37+
#include <node/kernel_notifications.h>
3738
#include <node/transaction.h>
3839
#include <node/types.h>
3940
#include <node/warnings.h>
@@ -935,6 +936,27 @@ class MinerImpl : public Mining
935936
return BlockRef{tip->GetBlockHash(), tip->nHeight};
936937
}
937938

939+
BlockRef waitTipChanged(uint256 current_tip, MillisecondsDouble timeout) override
940+
{
941+
// Interrupt check interval
942+
const MillisecondsDouble tick{1000};
943+
auto now{std::chrono::steady_clock::now()};
944+
auto deadline = now + timeout;
945+
// std::chrono does not check against overflow
946+
if (deadline < now) deadline = std::chrono::steady_clock::time_point::max();
947+
{
948+
WAIT_LOCK(notifications().m_tip_block_mutex, lock);
949+
while ((notifications().m_tip_block == uint256() || notifications().m_tip_block == current_tip) && !chainman().m_interrupt) {
950+
now = std::chrono::steady_clock::now();
951+
if (now >= deadline) break;
952+
notifications().m_tip_block_cv.wait_until(lock, std::min(deadline, now + tick));
953+
}
954+
}
955+
// Must release m_tip_block_mutex before locking cs_main, to avoid deadlocks.
956+
LOCK(::cs_main);
957+
return BlockRef{chainman().ActiveChain().Tip()->GetBlockHash(), chainman().ActiveChain().Tip()->nHeight};
958+
}
959+
938960
bool processNewBlock(const std::shared_ptr<const CBlock>& block, bool* new_block) override
939961
{
940962
return chainman().ProcessNewBlock(block, /*force_processing=*/true, /*min_pow_checked=*/true, /*new_block=*/new_block);
@@ -967,6 +989,7 @@ class MinerImpl : public Mining
967989

968990
NodeContext* context() override { return &m_node; }
969991
ChainstateManager& chainman() { return *Assert(m_node.chainman); }
992+
KernelNotifications& notifications() { return *Assert(m_node.notifications); }
970993
NodeContext& m_node;
971994
};
972995
} // namespace

0 commit comments

Comments
 (0)