26#include <condition_variable>
38 : m_mempool(mempool), m_chainman(chainman),
m_notifications(notifications), m_block_create_args(
std::move(block_create_args))
59 explicit SubmitBlockStateCatcher(
const uint256& hash) :
m_hash{hash} {}
62 void BlockChecked(
const std::shared_ptr<const CBlock>& block,
const BlockValidationState& state)
override
64 if (block->GetHash() !=
m_hash)
return;
85 auto sc = std::make_shared<SubmitBlockStateCatcher>(block->GetHash());
93 if (!new_block && accepted) {
95 }
else if (!accepted && (!sc->m_found || sc->m_state.IsValid())) {
100 reason =
"inconclusive";
101 }
else if (!sc->m_found) {
104 reason =
"inconclusive";
105 }
else if (!sc->m_state.IsValid()) {
106 reason = sc->m_state.GetRejectReason();
107 debug = sc->m_state.GetDebugMessage();
109 const bool result{accepted && new_block && reason.empty()};
119 return BlockRef{tip->GetBlockHash(), tip->nHeight};
125 interrupt_wait =
true;
130 const std::unique_ptr<CBlockTemplate>& block_template,
133 bool& interrupt_wait)
142 const auto deadline = now + wait_options.
timeout;
147 bool tip_changed{
false};
152 AssertLockHeld(m_notifications.m_tip_block_mutex);
153 const auto tip_block{m_notifications.TipBlock()};
157 tip_changed =
Assume(tip_block) && tip_block != block_template->block.hashPrevBlock;
160 if (interrupt_wait) {
161 interrupt_wait =
false;
174 if (!tip_changed && allow_min_difficulty) {
176 if (now > tip_time + 20min) {
193 if (tip_changed)
return new_tmpl;
196 if (current_fees == -1) {
197 current_fees = std::accumulate(block_template->vTxFees.begin(), block_template->vTxFees.end(),
CAmount{0});
201 const CAmount new_fees = std::accumulate(new_tmpl->vTxFees.begin(), new_tmpl->vTxFees.end(),
CAmount{0});
203 if (new_fees >= current_fees + wait_options.
fee_threshold)
return new_tmpl;
207 }
while (now < deadline);
212bool BlockTemplateManager::CooldownIfHeadersAhead(
const BlockRef& last_tip,
bool& interrupt_mining)
216 while (
const std::optional<int> remaining = m_chainman.BlocksAheadOfTip()) {
217 const int cooldown_seconds = std::clamp(*remaining, 3, 20);
223 const auto tip_block = m_notifications.TipBlock();
224 return m_chainman.m_interrupt || interrupt_mining || (tip_block && *tip_block != last_tip_hash);
226 if (m_chainman.m_interrupt || interrupt_mining) {
227 interrupt_mining =
false;
233 if (tip_block && *tip_block != last_tip_hash) {
234 last_tip_hash = *tip_block;
248 bool interrupt_wait{
false};
249 return WaitTipChanged(current_tip, timeout, interrupt_wait);
255 if (timeout < 0ms) timeout = 0ms;
256 if (timeout > std::chrono::years{100}) timeout = std::chrono::years{100};
257 auto deadline{std::chrono::steady_clock::now() + timeout};
265 AssertLockHeld(m_notifications.m_tip_block_mutex);
266 return m_notifications.TipBlock() || m_chainman.m_interrupt || interrupt;
268 if (m_chainman.m_interrupt || interrupt) {
275 return Assume(m_notifications.TipBlock()) != current_tip || m_chainman.m_interrupt || interrupt;
277 if (m_chainman.m_interrupt || interrupt) {
constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
int64_t CAmount
Amount in satoshis (Can be negative)
BlockValidationState m_state
#define CHECK_NONFATAL(condition)
Identity function.
#define Assume(val)
Assume is the identity function.
The block chain is a tree shaped structure starting with the genesis block at the root,...
int64_t GetBlockTime() const
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
const Consensus::Params & GetConsensus() const
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Implement this to subscribe to events generated in validation and mempool.
Interface for managing multiple Chainstate objects, where each chainstate is associated with chainsta...
Chainstate & ActiveChainstate() const
Alternatives to CurrentChainstate() used by older code to query latest chainstate information without...
bool ProcessNewBlock(const std::shared_ptr< const CBlock > &block, bool force_processing, bool min_pow_checked, bool *new_block) LOCKS_EXCLUDED(cs_main)
Process an incoming block.
const util::SignalInterrupt & m_interrupt
const CChainParams & GetParams() const
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Generate a new block, without valid proof-of-work.
BlockTemplateManager(CTxMemPool &mempool, ChainstateManager &chainman, KernelNotifications ¬ifications, BlockCreateOptions block_create_args={})
std::unique_ptr< CBlockTemplate > CreateNewTemplate(const BlockCreateOptions &options)
Create a fresh block template, applying init-time defaults to any unset options.
bool SubmitBlock(const std::shared_ptr< const CBlock > &block, std::string &reason, std::string &debug)
Submit a block via ProcessNewBlock and capture validation state.
std::optional< interfaces::BlockRef > GetTip()
Locks cs_main.
const BlockCreateOptions m_block_create_args
ChainstateManager & m_chainman
KernelNotifications & m_notifications
void InterruptWait(bool &interrupt_wait)
Interrupt a blocking wait.
std::unique_ptr< CBlockTemplate > WaitAndCreateNewBlock(const std::unique_ptr< CBlockTemplate > &block_template, const BlockWaitOptions &wait_options, const BlockCreateOptions &create_options, bool &interrupt_wait)
Return a new block template when fees rise to a certain threshold or after a new tip; return nullptr ...
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
BlockCreateOptions MergeMiningOptions(BlockCreateOptions x, const BlockCreateOptions &y)
Merge two BlockCreateOptions structs, replacing null values in x with non-null values from y.
std::shared_ptr< Chain::Notifications > m_notifications
bool fPowAllowMinDifficultyBlocks
static time_point now() noexcept
Return current system time or mocked time, if set.
static time_point now() noexcept
Return current system time or mocked time, if set.
std::chrono::time_point< NodeClock > time_point
Hash/height pair to help track and identify blocks.
ValidationSignals * signals
Block template creation options.
MillisecondsDouble timeout
How long to wait before returning nullptr instead of a new template.
CAmount fee_threshold
The wait method will not return a new template unless it has fees at least fee_threshold sats higher ...
#define WAIT_LOCK(cs, name)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
std::chrono::duration< double, std::chrono::milliseconds::period > MillisecondsDouble