mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 23:09:44 -04:00
interfaces: refactor: move waitTipChanged
implementation to miner
- This commit creates a function `ChainTipChanged` that waits for the connected tip to change until timeout elapsed. - This function is now used by `waitTipChanged`
This commit is contained in:
parent
d11db291d4
commit
c8a3fabe40
3 changed files with 33 additions and 26 deletions
|
@ -974,32 +974,8 @@ public:
|
|||
|
||||
std::optional<BlockRef> waitTipChanged(uint256 current_tip, MillisecondsDouble timeout) override
|
||||
{
|
||||
Assume(timeout >= 0ms); // No internal callers should use a negative timeout
|
||||
if (timeout < 0ms) timeout = 0ms;
|
||||
if (timeout > std::chrono::years{100}) timeout = std::chrono::years{100}; // Upper bound to avoid UB in std::chrono
|
||||
auto deadline{std::chrono::steady_clock::now() + timeout};
|
||||
{
|
||||
WAIT_LOCK(notifications().m_tip_block_mutex, lock);
|
||||
// For callers convenience, wait longer than the provided timeout
|
||||
// during startup for the tip to be non-null. That way this function
|
||||
// always returns valid tip information when possible and only
|
||||
// returns null when shutting down, not when timing out.
|
||||
notifications().m_tip_block_cv.wait(lock, [&]() EXCLUSIVE_LOCKS_REQUIRED(notifications().m_tip_block_mutex) {
|
||||
return notifications().TipBlock() || chainman().m_interrupt;
|
||||
});
|
||||
if (chainman().m_interrupt) return {};
|
||||
// At this point TipBlock is set, so continue to wait until it is
|
||||
// different then `current_tip` provided by caller.
|
||||
notifications().m_tip_block_cv.wait_until(lock, deadline, [&]() EXCLUSIVE_LOCKS_REQUIRED(notifications().m_tip_block_mutex) {
|
||||
return Assume(notifications().TipBlock()) != current_tip || chainman().m_interrupt;
|
||||
});
|
||||
}
|
||||
|
||||
if (chainman().m_interrupt) return {};
|
||||
|
||||
// Must release m_tip_block_mutex before getTip() locks cs_main, to
|
||||
// avoid deadlocks.
|
||||
return getTip();
|
||||
if (ChainTipChanged(chainman(), notifications(), current_tip, timeout)) return getTip();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::unique_ptr<BlockTemplate> createNewBlock(const BlockCreateOptions& options) override
|
||||
|
|
|
@ -538,4 +538,32 @@ std::optional<std::unique_ptr<CBlockTemplate>> WaitNext(ChainstateManager& chain
|
|||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool ChainTipChanged(ChainstateManager& chainman, KernelNotifications& kernel_notifications, const uint256& current_tip, MillisecondsDouble& timeout)
|
||||
{
|
||||
Assume(timeout >= 0ms); // No internal callers should use a negative timeout
|
||||
if (timeout < 0ms) timeout = 0ms;
|
||||
if (timeout > std::chrono::years{100}) timeout = std::chrono::years{100}; // Upper bound to avoid UB in std::chrono
|
||||
auto deadline{std::chrono::steady_clock::now() + timeout};
|
||||
{
|
||||
WAIT_LOCK(kernel_notifications.m_tip_block_mutex, lock);
|
||||
// For callers convenience, wait longer than the provided timeout
|
||||
// during startup for the tip to be non-null. That way this function
|
||||
// always returns valid tip information when possible and only
|
||||
// returns null when shutting down, not when timing out.
|
||||
kernel_notifications.m_tip_block_cv.wait(lock, [&]() EXCLUSIVE_LOCKS_REQUIRED(kernel_notifications.m_tip_block_mutex) {
|
||||
return kernel_notifications.TipBlock() || chainman.m_interrupt;
|
||||
});
|
||||
if (chainman.m_interrupt) return false;
|
||||
// At this point TipBlock is set, so continue to wait until it is
|
||||
// different then `current_tip` provided by caller.
|
||||
kernel_notifications.m_tip_block_cv.wait_until(lock, deadline, [&]() EXCLUSIVE_LOCKS_REQUIRED(kernel_notifications.m_tip_block_mutex) {
|
||||
return Assume(kernel_notifications.TipBlock()) != current_tip || chainman.m_interrupt;
|
||||
});
|
||||
}
|
||||
|
||||
if (chainman.m_interrupt) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace node
|
||||
|
|
|
@ -238,6 +238,9 @@ void AddMerkleRootAndCoinbase(CBlock& block, CTransactionRef coinbase, uint32_t
|
|||
/* Return a new block template when fees rise to a certain threshold or after a new tip; return nullopt if timeout is reached. */
|
||||
std::optional<std::unique_ptr<CBlockTemplate>> WaitNext(ChainstateManager& chainman, KernelNotifications& kernel_notifications, CTxMemPool* mempool, const uint256& prev_block_hash,
|
||||
const std::vector<CAmount>& tx_fees, const BlockWaitOptions& options, const BlockAssembler::Options& assemble_options);
|
||||
|
||||
/* Waits for the connected tip to change until timeout has elapsed. During node initialization, this will wait until the tip is connected (regardless of `timeout`). */
|
||||
bool ChainTipChanged(ChainstateManager& chainman, KernelNotifications& kernel_notifications, const uint256& current_tip, MillisecondsDouble& timeout);
|
||||
} // namespace node
|
||||
|
||||
#endif // BITCOIN_NODE_MINER_H
|
||||
|
|
Loading…
Add table
Reference in a new issue