aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSjors Provoost <sjors@sprovoost.nl>2024-07-17 18:33:15 +0200
committerSjors Provoost <sjors@sprovoost.nl>2024-07-17 18:33:15 +0200
commitc504b6997b1acc9771ad1f52efaa4be2b4966c6c (patch)
tree86bc76542a141b3025a95ece537465a49d2b9ef1
parent6b4c817d4b978adf69738677c74855ef0675f333 (diff)
downloadbitcoin-c504b6997b1acc9771ad1f52efaa4be2b4966c6c.tar.xz
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>
-rw-r--r--src/node/miner.cpp13
-rw-r--r--src/node/types.h11
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