Repository: bitcoin/bitcoin
File: src/node/miner.h (C/C++)

Code before:
void AddMerkleRootAndCoinbase(CBlock& block, CTransactionRef coinbase, uint32_t version, uint32_t timestamp, uint32_t nonce);


/* Interrupt the current wait for the next block template. */
void InterruptWait(KernelNotifications& kernel_notifications, bool& interrupt_wait);
/**
 * Return a new block template when fees rise to a certain threshold or after a
 * new tip; return nullopt if timeout is reached.
 */
std::unique_ptr<CBlockTemplate> WaitAndCreateNewBlock(ChainstateManager& chainman,
                                                      KernelNotifications& kernel_notifications,
                                                      CTxMemPool* mempool,
                                                      const std::unique_ptr<CBlockTemplate>& block_template,
                                                      const BlockWaitOptions& options,
                                                      const BlockAssembler::Options& assemble_options,
                                                      bool& interrupt_wait);

/* Locks cs_main and returns the block hash and block height of the active chain if it exists; otherwise, returns nullopt.*/
std::optional<BlockRef> GetTip(ChainstateManager& chainman);

/* 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`).
 * Returns the current tip, or nullopt if the node is shutting down. */
std::optional<BlockRef> WaitTipChanged(ChainstateManager& chainman, KernelNotifications& kernel_notifications, const uint256& current_tip, MillisecondsDouble& timeout);

/**
 * Pause block template creation when the best header chain is ahead of the tip.
 *
 * @param last_tip tip at the start of the cooldown window.
 *
 * @returns false if interrupted.
 */
bool CooldownIfHeadersAhead(ChainstateManager& chainman, KernelNotifications& kernel_notifications, const BlockRef& last_tip);
} // namespace node

#endif // BITCOIN_NODE_MINER_H


Review comment (suggestion):
In commit "mining: createNewBlock() waits if tip is updating" (9817657d463ff1d8502a5edf0641e88b9b1d4853)

This is a little vague. I think it would be helpful to describe this in terms of observable behavior, maybe:

```
/**
 * Wait while the best known header extends the current chain tip
 * AND at least one block per second is being added to the tip.
 *
 * Returns false if interrupted.
 */
```

Might also be good to add the "not safe to keep waiting" info from your commit description, and maybe say something about how we think this is safe to use for createNewBlock since miners should only call it once on startup, but are avoiding it in waitNext.

Code after:


/* Interrupt a blocking call. */
void InterruptWait(KernelNotifications& kernel_notifications, bool& interrupt_wait);
/**
 * Return a new block template when fees rise to a certain threshold or after a
 * new tip; return nullopt if timeout is reached.
 */
std::unique_ptr<CBlockTemplate> WaitAndCreateNewBlock(ChainstateManager& chainman,
                                                      KernelNotifications& kernel_notifications,
                                                      CTxMemPool* mempool,
                                                      const std::unique_ptr<CBlockTemplate>& block_template,
                                                      const BlockWaitOptions& options,
                                                      const BlockAssembler::Options& assemble_options,
                                                      bool& interrupt_wait);

/* Locks cs_main and returns the block hash and block height of the active chain if it exists; otherwise, returns nullopt.*/
std::optional<BlockRef> GetTip(ChainstateManager& chainman);

/* 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`).
 * Returns the current tip, or nullopt if the node is shutting down or interrupt()
 * is called.
 */
std::optional<BlockRef> WaitTipChanged(ChainstateManager& chainman, KernelNotifications& kernel_notifications, const uint256& current_tip, MillisecondsDouble& timeout, bool& interrupt);

/**
 * Wait while the best known header extends the current chain tip AND at least
 * one block is being added to the tip every 3 seconds. If the tip is
 * sufficiently far behind, allow up to 20 seconds for the next tip update.
 *
 * It’s not safe to keep waiting, because a malicious miner could announce a
 * header and delay revealing the block, causing all other miners using this
 * software to stall. At the same time, we need to balance between the default
 * waiting time being brief, but not ending the cooldown prematurely when a
 * random block is slow to download (or process).
 *
 * The cooldown only applies to createNewBlock(), which is typically called
 * once per connected client. Subsequent templates are provided by waitNext().
 *
 * @param last_tip tip at the start of the cooldown window.
 * @param interrupt_mining set to true to interrupt the cooldown.
 *
 * @returns false if interrupted.
 */
bool CooldownIfHeadersAhead(ChainstateManager& chainman, KernelNotifications& kernel_notifications, const BlockRef& last_tip, bool& interrupt_mining);
} // namespace node

#endif // BITCOIN_NODE_MINER_H