9#include <chainparams.h>
40 const int height{pindexPrev->
nHeight + 1};
43 if (height % difficulty_adjustment_interval == 0) {
51 int64_t nOldTime = pblock->
nTime;
55 if (nOldTime < nNewTime) {
56 pblock->
nTime = nNewTime;
64 return nNewTime - nOldTime;
91 : chainparams{chainstate.m_chainman.GetParams()},
92 m_mempool{options.use_mempool ? mempool : nullptr},
93 m_chainstate{chainstate},
102 if (
const auto blockmintxfee{
args.
GetArg(
"-blockmintxfee")}) {
105 options.print_modified_fee =
args.
GetBoolArg(
"-printpriority", options.print_modified_fee);
106 if (!options.block_reserved_weight) {
107 options.block_reserved_weight =
args.
GetIntArg(
"-blockreservedweight");
111void BlockAssembler::resetBlock()
114 nBlockWeight = *
Assert(m_options.block_reserved_weight);
115 nBlockSigOpsCost = m_options.coinbase_output_max_additional_sigops;
122std::unique_ptr<CBlockTemplate> BlockAssembler::CreateNewBlock()
124 const auto time_start{SteadyClock::now()};
129 CBlock*
const pblock = &pblocktemplate->block;
133 pblock->
vtx.emplace_back();
136 CBlockIndex* pindexPrev = m_chainstate.m_chain.Tip();
137 assert(pindexPrev !=
nullptr);
140 pblock->
nVersion = m_chainstate.m_chainman.m_versionbitscache.ComputeBlockVersion(pindexPrev, chainparams.GetConsensus());
143 if (chainparams.MineBlocksOnDemand()) {
152 m_mempool->StartBlockBuilding();
154 m_mempool->StopBlockBuilding();
157 const auto time_1{SteadyClock::now()};
159 m_last_block_num_txs = nBlockTx;
160 m_last_block_weight = nBlockWeight;
166 CoinbaseTx& coinbase_tx{pblocktemplate->m_coinbase_tx};
169 coinbaseTx.
vin.resize(1);
170 coinbaseTx.
vin[0].prevout.SetNull();
172 coinbase_tx.sequence = coinbaseTx.
vin[0].nSequence;
175 coinbaseTx.
vout.resize(1);
176 coinbaseTx.
vout[0].scriptPubKey = m_options.coinbase_output_script;
179 coinbaseTx.
vout[0].nValue = block_reward;
180 coinbase_tx.block_reward_remaining = block_reward;
191 coinbase_tx.script_sig_prefix = coinbaseTx.
vin[0].scriptSig;
197 coinbaseTx.
vin[0].scriptSig <<
OP_0;
201 coinbase_tx.lock_time = coinbaseTx.
nLockTime;
204 m_chainstate.m_chainman.GenerateCoinbaseCommitment(*pblock, pindexPrev);
207 if (final_coinbase->HasWitness()) {
208 const auto& witness_stack{final_coinbase->vin[0].scriptWitness.stack};
211 Assert(witness_stack.size() == 1 && witness_stack[0].size() == 32);
212 coinbase_tx.witness =
uint256(witness_stack[0]);
215 Assert(witness_index >= 0 &&
static_cast<size_t>(witness_index) < final_coinbase->vout.size());
216 coinbase_tx.required_outputs.push_back(final_coinbase->vout[witness_index]);
219 LogInfo(
"CreateNewBlock(): block weight: %u txs: %u fees: %ld sigops %d\n",
GetBlockWeight(*pblock), nBlockTx, nFees, nBlockSigOpsCost);
223 UpdateTime(pblock, chainparams.GetConsensus(), pindexPrev);
227 if (m_options.test_block_validity) {
229 throw std::runtime_error(
strprintf(
"TestBlockValidity failed: %s", state.ToString()));
232 const auto time_2{SteadyClock::now()};
235 Ticks<MillisecondsDouble>(time_1 - time_start),
236 Ticks<MillisecondsDouble>(time_2 - time_1),
237 Ticks<MillisecondsDouble>(time_2 - time_start));
239 return std::move(pblocktemplate);
242bool BlockAssembler::TestChunkBlockLimits(
FeePerWeight chunk_feerate, int64_t chunk_sigops_cost)
const
244 if (nBlockWeight + chunk_feerate.
size >= m_options.nBlockMaxWeight) {
255bool BlockAssembler::TestChunkTransactions(
const std::vector<CTxMemPoolEntryRef>& txs)
const
257 for (
const auto tx : txs) {
267 pblocktemplate->block.vtx.emplace_back(entry.
GetSharedTx());
268 pblocktemplate->vTxFees.push_back(entry.
GetFee());
269 pblocktemplate->vTxSigOpsCost.push_back(entry.
GetSigOpCost());
275 if (m_options.print_modified_fee) {
276 LogInfo(
"fee rate %s txid %s\n",
282void BlockAssembler::addChunks()
287 const int64_t MAX_CONSECUTIVE_FAILURES = 1000;
288 constexpr int32_t BLOCK_FULL_ENOUGH_WEIGHT_DELTA = 4000;
289 int64_t nConsecutiveFailed = 0;
291 std::vector<CTxMemPoolEntry::CTxMemPoolEntryRef> selected_transactions;
296 chunk_feerate = m_mempool->GetBlockBuilderChunk(selected_transactions);
299 while (selected_transactions.size() > 0) {
301 if (
ByRatio{chunk_feerate_vsize} <
ByRatio{m_options.blockMinFeeRate.GetFeePerVSize()}) {
306 int64_t chunk_sig_ops = 0;
307 for (
const auto& tx : selected_transactions) {
308 chunk_sig_ops += tx.get().GetSigOpCost();
312 if (!TestChunkBlockLimits(chunk_feerate, chunk_sig_ops) || !TestChunkTransactions(selected_transactions)) {
314 m_mempool->SkipBuilderChunk();
315 ++nConsecutiveFailed;
317 if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight +
318 BLOCK_FULL_ENOUGH_WEIGHT_DELTA > m_options.nBlockMaxWeight) {
323 m_mempool->IncludeBuilderChunk();
326 nConsecutiveFailed = 0;
327 for (
const auto& tx : selected_transactions) {
330 pblocktemplate->m_package_feerates.emplace_back(chunk_feerate_vsize);
333 selected_transactions.clear();
334 chunk_feerate = m_mempool->GetBlockBuilderChunk(selected_transactions);
341 if (block.
vtx.size() == 0) {
342 block.
vtx.emplace_back(coinbase);
344 block.
vtx[0] = coinbase;
347 block.
nTime = timestamp;
360 interrupt_wait =
true;
361 kernel_notifications.m_tip_block_cv.notify_all();
367 const std::unique_ptr<CBlockTemplate>& block_template,
370 bool& interrupt_wait)
379 const auto deadline = now + options.
timeout;
384 bool tip_changed{
false};
389 AssertLockHeld(kernel_notifications.m_tip_block_mutex);
390 const auto tip_block{kernel_notifications.TipBlock()};
394 tip_changed =
Assume(tip_block) && tip_block != block_template->block.hashPrevBlock;
395 return tip_changed || chainman.
m_interrupt || interrupt_wait;
397 if (interrupt_wait) {
398 interrupt_wait =
false;
411 if (!tip_changed && allow_min_difficulty) {
413 if (now > tip_time + 20min) {
434 if (tip_changed)
return new_tmpl;
437 if (current_fees == -1) {
438 current_fees = std::accumulate(block_template->vTxFees.begin(), block_template->vTxFees.end(),
CAmount{0});
442 const CAmount new_fees = std::accumulate(new_tmpl->vTxFees.begin(), new_tmpl->vTxFees.end(),
CAmount{0});
444 if (new_fees >= current_fees + options.
fee_threshold)
return new_tmpl;
448 }
while (now < deadline);
458 return BlockRef{tip->GetBlockHash(), tip->nHeight};
465 while (
const std::optional<int> remaining = chainman.BlocksAheadOfTip()) {
466 const int cooldown_seconds = std::clamp(*remaining, 3, 20);
472 const auto tip_block = kernel_notifications.TipBlock();
473 return chainman.m_interrupt || interrupt_mining || (tip_block && *tip_block != last_tip_hash);
476 interrupt_mining =
false;
481 const auto tip_block = kernel_notifications.
TipBlock();
482 if (tip_block && *tip_block != last_tip_hash) {
483 last_tip_hash = *tip_block;
498 if (timeout < 0ms) timeout = 0ms;
499 if (timeout > std::chrono::years{100}) timeout = std::chrono::years{100};
500 auto deadline{std::chrono::steady_clock::now() + timeout};
508 return kernel_notifications.TipBlock() || chainman.m_interrupt || interrupt;
517 return Assume(kernel_notifications.TipBlock()) != current_tip || chainman.m_interrupt || interrupt;
static constexpr CAmount MAX_MONEY
No amount larger than this (in satoshi) is valid.
int64_t CAmount
Amount in satoshis (Can be negative)
#define Assert(val)
Identity function.
#define Assume(val)
Assume is the identity function.
std::string GetArg(const std::string &strArg, const std::string &strDefault) const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Return string argument or default value.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
bool GetBoolArg(const std::string &strArg, bool fDefault) const EXCLUSIVE_LOCKS_REQUIRED(!cs_args)
Return boolean argument or default value.
Wrapper around FeeFrac & derived types, which adds a feerate-based ordering which treats equal-feerat...
bool m_checked_merkle_root
std::vector< CTransactionRef > vtx
bool m_checked_witness_commitment
The block chain is a tree shaped structure starting with the genesis block at the root,...
uint256 GetBlockHash() const
int64_t GetBlockTime() const
int64_t GetMedianTimePast() const
int nHeight
height of the entry in the chain. The genesis block has height 0
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
const Consensus::Params & GetConsensus() const
Fee rate in satoshis per virtualbyte: CAmount / vB the feerate is represented internally as FeeFrac.
std::string ToString(FeeRateFormat fee_rate_format=FeeRateFormat::BTC_KVB) const
Serialized script, used inside transaction inputs and outputs.
const Txid & GetHash() const LIFETIMEBOUND
static const uint32_t MAX_SEQUENCE_NONFINAL
This is the maximum sequence number that enables both nLockTime and OP_CHECKLOCKTIMEVERIFY (BIP 65).
CTxMemPoolEntry stores data about the corresponding transaction, as well as data about all in-mempool...
const CTransaction & GetTx() const
int32_t GetTxWeight() const
int64_t GetSigOpCost() const
CTransactionRef GetSharedTx() const
int32_t GetTxSize() const
const CAmount & GetFee() const
CAmount GetModifiedFee() const
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Chainstate stores and provides an API to update our local knowledge of the current best chain.
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...
const util::SignalInterrupt & m_interrupt
const CChainParams & GetParams() const
void GenerateCoinbaseCommitment(CBlock &block, const CBlockIndex *pindexPrev) const
Produce the necessary coinbase commitment for a block (modifies the hash, don't call for mined blocks...
CChain & ActiveChain() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Generate a new block, without valid proof-of-work.
BlockAssembler(Chainstate &chainstate, const CTxMemPool *mempool, const Options &options)
CBlockIndex * LookupBlockIndex(const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
std::optional< uint256 > TipBlock() EXCLUSIVE_LOCKS_REQUIRED(m_tip_block_mutex)
The block for which the last blockTip notification was received.
std::string ToString() const
uint256 BlockMerkleRoot(const CBlock &block, bool *mutated)
static constexpr int NO_WITNESS_COMMITMENT
Index marker for when no witness commitment is present in a coinbase transaction.
static int64_t GetBlockWeight(const CBlock &block)
int GetWitnessCommitmentIndex(const CBlock &block)
Compute at which vout of the block's coinbase transaction the witness commitment occurs,...
static constexpr int64_t MAX_TIMEWARP
Maximum number of seconds that the timestamp of the first block of a difficulty adjustment period is ...
static const unsigned int MAX_BLOCK_WEIGHT
The maximum allowed weight for a block, see BIP 141 (network rule)
static const int64_t MAX_BLOCK_SIGOPS_COST
The maximum allowed number of signature check operations in a block (network rule)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
#define LogDebug(category,...)
std::optional< CAmount > ParseMoney(const std::string &money_string)
Parse an amount denoted in full coins.
static BlockAssembler::Options ClampOptions(BlockAssembler::Options options)
void RegenerateCommitments(CBlock &block, ChainstateManager &chainman)
Update an old GenerateCoinbaseCommitment from CreateNewBlock after the block txs have changed.
std::optional< BlockRef > WaitTipChanged(ChainstateManager &chainman, KernelNotifications &kernel_notifications, const uint256 ¤t_tip, MillisecondsDouble &timeout, bool &interrupt)
int64_t UpdateTime(CBlockHeader *pblock, const Consensus::Params &consensusParams, const CBlockIndex *pindexPrev)
util::Result< void > ApplyArgsManOptions(const ArgsManager &args, BlockManager::Options &opts)
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)
Return a new block template when fees rise to a certain threshold or after a new tip; return nullopt ...
int64_t GetMinimumTime(const CBlockIndex *pindexPrev, const int64_t difficulty_adjustment_interval)
Get the minimum time a miner should use in the next block.
void InterruptWait(KernelNotifications &kernel_notifications, bool &interrupt_wait)
void AddMerkleRootAndCoinbase(CBlock &block, CTransactionRef coinbase, uint32_t version, uint32_t timestamp, uint32_t nonce)
bool CooldownIfHeadersAhead(ChainstateManager &chainman, KernelNotifications &kernel_notifications, const BlockRef &last_tip, bool &interrupt_mining)
Wait while the best known header extends the current chain tip AND at least one block is being added ...
std::optional< BlockRef > GetTip(ChainstateManager &chainman)
static constexpr unsigned int DEFAULT_BLOCK_RESERVED_WEIGHT
Default for -blockreservedweight.
static FeePerVSize ToFeePerVSize(FeePerWeight feerate)
static constexpr unsigned int MINIMUM_BLOCK_RESERVED_WEIGHT
This accounts for the block header, var_int encoding of the transaction count and a minimally viable ...
unsigned int GetNextWorkRequired(const CBlockIndex *pindexLast, const CBlockHeader *pblock, const Consensus::Params ¶ms)
static CTransactionRef MakeTransactionRef(Tx &&txIn)
std::shared_ptr< const CTransaction > CTransactionRef
A mutable version of CTransaction.
std::vector< CTxOut > vout
Parameters that influence chain consensus.
int64_t DifficultyAdjustmentInterval() const
bool fPowAllowMinDifficultyBlocks
Tagged wrapper around FeeFrac to avoid unit confusion.
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.
std::optional< size_t > block_reserved_weight
The default reserved weight for the fixed-size block header, transaction count and coinbase transacti...
size_t coinbase_output_max_additional_sigops
The maximum additional sigops which the pool will add in coinbase transaction outputs.
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 ...
Template containing all coinbase transaction fields that are set by our miner code.
#define WAIT_LOCK(cs, name)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
Check if transaction is final and can be included in a block with the specified height and time.
static constexpr unsigned MAX_CLUSTER_COUNT_LIMIT
std::chrono::duration< double, std::chrono::milliseconds::period > MillisecondsDouble
CAmount GetBlockSubsidy(int nHeight, const Consensus::Params &consensusParams)
BlockValidationState TestBlockValidity(Chainstate &chainstate, const CBlock &block, const bool check_pow, const bool check_merkle_root)
Verify a block, including transactions.