diff options
author | Sjors Provoost <sjors@sprovoost.nl> | 2024-07-17 18:33:15 +0200 |
---|---|---|
committer | Sjors Provoost <sjors@sprovoost.nl> | 2024-07-17 18:33:15 +0200 |
commit | c504b6997b1acc9771ad1f52efaa4be2b4966c6c (patch) | |
tree | 86bc76542a141b3025a95ece537465a49d2b9ef1 /src/node | |
parent | 6b4c817d4b978adf69738677c74855ef0675f333 (diff) |
refactor: add coinbase constraints to BlockCreateOptions
When generating a block template through e.g. getblocktemplate RPC,
we reserve 4000 weight units and 400 sigops. Pools use this space
for their coinbase outputs.
At least one pool patched their Bitcoin Core node to adjust
these hardcoded values. They eventually produced an invalid
block which exceeded the sigops limit.
https://bitcoin.stackexchange.com/questions/117837/how-many-sigops-are-in-the-invalid-block-783426
The existince of such patches suggests it may be useful to
make this value configurable. This commit would make such a
change easier.
The main motivation however is that the Stratum v2 spec
requires the pool to communicate the maximum bytes they intend
to add to the coinbase outputs. A proposed change to the spec
would also require them to communicate the maximum number of sigops.
This commit also documents what happens when
-blockmaxweight is lower than the coinbase
reserved value.
Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
Diffstat (limited to 'src/node')
-rw-r--r-- | src/node/miner.cpp | 13 | ||||
-rw-r--r-- | src/node/types.h | 11 |
2 files changed, 19 insertions, 5 deletions
diff --git a/src/node/miner.cpp b/src/node/miner.cpp index 67465b1e70..fa2d979b86 100644 --- a/src/node/miner.cpp +++ b/src/node/miner.cpp @@ -59,8 +59,11 @@ void RegenerateCommitments(CBlock& block, ChainstateManager& chainman) static BlockAssembler::Options ClampOptions(BlockAssembler::Options options) { - // Limit weight to between 4K and DEFAULT_BLOCK_MAX_WEIGHT for sanity: - options.nBlockMaxWeight = std::clamp<size_t>(options.nBlockMaxWeight, 4000, DEFAULT_BLOCK_MAX_WEIGHT); + Assert(options.coinbase_max_additional_weight <= DEFAULT_BLOCK_MAX_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); return options; } @@ -87,8 +90,8 @@ void BlockAssembler::resetBlock() inBlock.clear(); // Reserve space for coinbase tx - nBlockWeight = 4000; - nBlockSigOpsCost = 400; + nBlockWeight = m_options.coinbase_max_additional_weight; + nBlockSigOpsCost = m_options.coinbase_output_max_additional_sigops; // These counters do not include coinbase tx nBlockTx = 0; @@ -379,7 +382,7 @@ void BlockAssembler::addPackageTxs(const CTxMemPool& mempool, int& nPackagesSele ++nConsecutiveFailed; if (nConsecutiveFailed > MAX_CONSECUTIVE_FAILURES && nBlockWeight > - m_options.nBlockMaxWeight - 4000) { + m_options.nBlockMaxWeight - m_options.coinbase_max_additional_weight) { // Give up if we're close to full and haven't succeeded in a while break; } diff --git a/src/node/types.h b/src/node/types.h index d4e7d93015..bb8d17ef43 100644 --- a/src/node/types.h +++ b/src/node/types.h @@ -32,6 +32,17 @@ struct BlockCreateOptions { * Set false to omit mempool transactions */ bool use_mempool{true}; + /** + * The maximum additional weight which the pool will add to the coinbase + * scriptSig, witness and outputs. This must include any additional + * weight needed for larger CompactSize encoded lengths. + */ + size_t coinbase_max_additional_weight{4000}; + /** + * The maximum additional sigops which the pool will add in coinbase + * transaction outputs. + */ + size_t coinbase_output_max_additional_sigops{400}; }; } // namespace node |