Merge bitcoin/bitcoin#31384: mining: bugfix: Fix duplicate coinbase tx weight reservation

386eecff5f doc: add release notes (ismaelsadeeq)
3eaa0a3b66 miner: init: add `-blockreservedweight` startup option (ismaelsadeeq)
777434a2cd doc: rpc: improve `getmininginfo` help text (ismaelsadeeq)
c8acd4032d init: fail to start when `-blockmaxweight` exceeds `MAX_BLOCK_WEIGHT` (ismaelsadeeq)
5bb31633cc test: add `-blockmaxweight` startup option functional test (ismaelsadeeq)
2c7d90a6d6 miner: bugfix: fix duplicate weight reservation in block assembler (ismaelsadeeq)

Pull request description:

  * This PR attempts to fix the duplicate coinbase weight reservation issue we currently have.
  * Fixes #21950

  We reserve 4000 weight units for coinbase transaction in `DEFAULT_BLOCK_MAX_WEIGHT`

  7590e93bc7/src/policy/policy.h (L23)

  And also reserve additional `4000` weight units in the default `BlockCreationOptions` struct.

  7590e93bc7/src/node/types.h (L36-L40)

  **Motivation**

  - This issue was first noticed during a review here https://github.com/bitcoin/bitcoin/pull/11100#discussion_r136157411)
  - It was later reported in issue #21950.
  - I also came across the bug while writing a test for building the block template. I could not create a block template above `3,992,000` in the block assembler, and this was not documented anywhere. It took me a while to realize that we were reserving space for the coinbase transaction weight twice.

  ---
  This PR fixes this by consolidating the reservation to be in a single location in the codebase.

  This PR then adds a new startup option `-blockreservedweight` whose default is `8000` that can be used to lower or increase the block reserved weight for block header, txs count, coinbase tx.

ACKs for top commit:
  Sjors:
    ACK 386eecff5f
  fjahr:
    Code review ACK 386eecff5f
  glozow:
    utACK 386eecff5f, nonblocking nits. I do think the release notes should be clarified more
  pinheadmz:
    ACK 386eecff5f

Tree-SHA512: f27efa1da57947b7f4d42b9322b83d13afe73dd749dd9cac49360002824dd41c99a876a610554ac2d67bad7485020b9dcc423a8e6748fc79d6a10de6d4357d4c
This commit is contained in:
glozow
2025-02-10 08:14:50 -05:00
11 changed files with 202 additions and 19 deletions

View File

@@ -74,11 +74,12 @@ void RegenerateCommitments(CBlock& block, ChainstateManager& chainman)
static BlockAssembler::Options ClampOptions(BlockAssembler::Options options)
{
Assert(options.coinbase_max_additional_weight <= DEFAULT_BLOCK_MAX_WEIGHT);
Assert(options.block_reserved_weight <= MAX_BLOCK_WEIGHT);
Assert(options.block_reserved_weight >= MINIMUM_BLOCK_RESERVED_WEIGHT);
Assert(options.coinbase_output_max_additional_sigops <= MAX_BLOCK_SIGOPS_COST);
// Limit weight to between coinbase_max_additional_weight and DEFAULT_BLOCK_MAX_WEIGHT for sanity:
// Coinbase (reserved) outputs can safely exceed -blockmaxweight, but the rest of the block template will be empty.
options.nBlockMaxWeight = std::clamp<size_t>(options.nBlockMaxWeight, options.coinbase_max_additional_weight, DEFAULT_BLOCK_MAX_WEIGHT);
// Limit weight to between block_reserved_weight and MAX_BLOCK_WEIGHT for sanity:
// block_reserved_weight can safely exceed -blockmaxweight, but the rest of the block template will be empty.
options.nBlockMaxWeight = std::clamp<size_t>(options.nBlockMaxWeight, options.block_reserved_weight, MAX_BLOCK_WEIGHT);
return options;
}
@@ -98,14 +99,15 @@ void ApplyArgsManOptions(const ArgsManager& args, BlockAssembler::Options& optio
if (const auto parsed{ParseMoney(*blockmintxfee)}) options.blockMinFeeRate = CFeeRate{*parsed};
}
options.print_modified_fee = args.GetBoolArg("-printpriority", options.print_modified_fee);
options.block_reserved_weight = args.GetIntArg("-blockreservedweight", options.block_reserved_weight);
}
void BlockAssembler::resetBlock()
{
inBlock.clear();
// Reserve space for coinbase tx
nBlockWeight = m_options.coinbase_max_additional_weight;
// Reserve space for fixed-size block header, txs count, and coinbase tx.
nBlockWeight = m_options.block_reserved_weight;
nBlockSigOpsCost = m_options.coinbase_output_max_additional_sigops;
// These counters do not include coinbase tx
@@ -393,7 +395,7 @@ void BlockAssembler::addPackageTxs(int& nPackagesSelected, int& nDescendantsUpda
++nConsecutiveFailed;
if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight >
m_options.nBlockMaxWeight - m_options.coinbase_max_additional_weight) {
m_options.nBlockMaxWeight - m_options.block_reserved_weight) {
// Give up if we're close to full and haven't succeeded in a while
break;
}