mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-22 15:04:44 +01:00
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: ACK386eecff5f
fjahr: Code review ACK386eecff5f
glozow: utACK386eecff5f
, nonblocking nits. I do think the release notes should be clarified more pinheadmz: ACK386eecff5f
Tree-SHA512: f27efa1da57947b7f4d42b9322b83d13afe73dd749dd9cac49360002824dd41c99a876a610554ac2d67bad7485020b9dcc423a8e6748fc79d6a10de6d4357d4c
This commit is contained in:
commit
6b165f5906
11 changed files with 202 additions and 19 deletions
34
doc/release-notes-31384.md
Normal file
34
doc/release-notes-31384.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
- Node and Mining
|
||||
|
||||
---
|
||||
|
||||
- **PR #31384** fixed an issue where block reserved weight for fixed-size block header, transactions count,
|
||||
and coinbase transaction was done in two separate places.
|
||||
Before this pull request, the policy default for the maximum block weight was `3,996,000` WU, calculated by
|
||||
subtracting `4,000 WU` from the `4,000,000 WU` consensus limit to account for the fixed-size block header,
|
||||
transactions count, and coinbase transaction. During block assembly, Bitcoin Core clamped custom `-blockmaxweight`
|
||||
value to not be more than the policy default.
|
||||
|
||||
Additionally, the mining code added another `4,000 WU` to the initial reservation, reducing the effective block template
|
||||
size to `3,992,000 WU`.
|
||||
|
||||
Due to this issue, the total reserved weight was always `8,000 WU`, meaning that even when specifying a `-blockmaxweight`
|
||||
higher than the policy default, the actual block size never exceeded `3,992,000 WU`.
|
||||
|
||||
The fix consolidates the reservation into a single place and introduces a new startup option,
|
||||
`-blockreservedweight` (default: `8,000 WU`). This startup option specifies the reserved weight for
|
||||
the fixed-size block header, transactions count, and coinbase transaction.
|
||||
The default value of `-blockreservedweight` was chosen to preserve the previous behavior.
|
||||
|
||||
**Upgrade Note:** The default `-blockreservedweight` ensures backward compatibility for users who relied on the previous behavior.
|
||||
|
||||
Users who manually set `-blockmaxweight` to its maximum value of `4,000,000 WU` should be aware that this
|
||||
value previously had no effect since it was clamped to `3,996,000 WU`.
|
||||
|
||||
Users lowering `-blockreservedweight` should ensure that the total weight (for the block header, transaction count, and coinbase transaction)
|
||||
does not exceed the reduced value.
|
||||
|
||||
As a safety check, Bitcoin core will **fail to start** when `-blockreservedweight` init parameter value is lower than `2000` weight units.
|
||||
|
||||
Bitcoin Core will also **fail to start** if the `-blockmaxweight` or `-blockreservedweight` init parameter exceeds
|
||||
consensus limit of `4,000,000` weight units.
|
19
src/init.cpp
19
src/init.cpp
|
@ -19,6 +19,7 @@
|
|||
#include <common/args.h>
|
||||
#include <common/system.h>
|
||||
#include <consensus/amount.h>
|
||||
#include <consensus/consensus.h>
|
||||
#include <deploymentstatus.h>
|
||||
#include <hash.h>
|
||||
#include <httprpc.h>
|
||||
|
@ -648,6 +649,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
|
|||
|
||||
|
||||
argsman.AddArg("-blockmaxweight=<n>", strprintf("Set maximum BIP141 block weight (default: %d)", DEFAULT_BLOCK_MAX_WEIGHT), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
|
||||
argsman.AddArg("-blockreservedweight=<n>", strprintf("Reserve space for the fixed-size block header plus the largest coinbase transaction the mining software may add to the block. (default: %d).", DEFAULT_BLOCK_RESERVED_WEIGHT), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
|
||||
argsman.AddArg("-blockmintxfee=<amt>", strprintf("Set lowest fee rate (in %s/kvB) for transactions to be included in block creation. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_BLOCK_MIN_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
|
||||
argsman.AddArg("-blockversion=<n>", "Override block version to test forking scenarios", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::BLOCK_CREATION);
|
||||
|
||||
|
@ -1015,6 +1017,23 @@ bool AppInitParameterInteraction(const ArgsManager& args)
|
|||
}
|
||||
}
|
||||
|
||||
if (args.IsArgSet("-blockmaxweight")) {
|
||||
const auto max_block_weight = args.GetIntArg("-blockmaxweight", DEFAULT_BLOCK_MAX_WEIGHT);
|
||||
if (max_block_weight > MAX_BLOCK_WEIGHT) {
|
||||
return InitError(strprintf(_("Specified -blockmaxweight (%d) exceeds consensus maximum block weight (%d)"), max_block_weight, MAX_BLOCK_WEIGHT));
|
||||
}
|
||||
}
|
||||
|
||||
if (args.IsArgSet("-blockreservedweight")) {
|
||||
const auto block_reserved_weight = args.GetIntArg("-blockreservedweight", DEFAULT_BLOCK_RESERVED_WEIGHT);
|
||||
if (block_reserved_weight > MAX_BLOCK_WEIGHT) {
|
||||
return InitError(strprintf(_("Specified -blockreservedweight (%d) exceeds consensus maximum block weight (%d)"), block_reserved_weight, MAX_BLOCK_WEIGHT));
|
||||
}
|
||||
if (block_reserved_weight < MINIMUM_BLOCK_RESERVED_WEIGHT) {
|
||||
return InitError(strprintf(_("Specified -blockreservedweight (%d) is lower than minimum safety value of (%d)"), block_reserved_weight, MINIMUM_BLOCK_RESERVED_WEIGHT));
|
||||
}
|
||||
}
|
||||
|
||||
nBytesPerSigOp = args.GetIntArg("-bytespersigop", nBytesPerSigOp);
|
||||
|
||||
if (!g_wallet_init_interface.ParameterInteraction()) return false;
|
||||
|
|
|
@ -35,7 +35,7 @@ interface BlockTemplate $Proxy.wrap("interfaces::BlockTemplate") {
|
|||
|
||||
struct BlockCreateOptions $Proxy.wrap("node::BlockCreateOptions") {
|
||||
useMempool @0 :Bool $Proxy.name("use_mempool");
|
||||
coinbaseMaxAdditionalWeight @1 :UInt64 $Proxy.name("coinbase_max_additional_weight");
|
||||
blockReservedWeight @1 :UInt64 $Proxy.name("block_reserved_weight");
|
||||
coinbaseOutputMaxAdditionalSigops @2 :UInt64 $Proxy.name("coinbase_output_max_additional_sigops");
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -176,7 +176,9 @@ public:
|
|||
/** Construct a new block template */
|
||||
std::unique_ptr<CBlockTemplate> CreateNewBlock();
|
||||
|
||||
/** The number of transactions in the last assembled block (excluding coinbase transaction) */
|
||||
inline static std::optional<int64_t> m_last_block_num_txs{};
|
||||
/** The weight of the last assembled block (including reserved weight for block header, txs count and coinbase tx) */
|
||||
inline static std::optional<int64_t> m_last_block_weight{};
|
||||
|
||||
private:
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#define BITCOIN_NODE_TYPES_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <policy/policy.h>
|
||||
#include <script/script.h>
|
||||
|
||||
namespace node {
|
||||
|
@ -34,11 +35,10 @@ struct BlockCreateOptions {
|
|||
*/
|
||||
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.
|
||||
* The default reserved weight for the fixed-size block header,
|
||||
* transaction count and coinbase transaction.
|
||||
*/
|
||||
size_t coinbase_max_additional_weight{4000};
|
||||
size_t block_reserved_weight{DEFAULT_BLOCK_RESERVED_WEIGHT};
|
||||
/**
|
||||
* The maximum additional sigops which the pool will add in coinbase
|
||||
* transaction outputs.
|
||||
|
|
|
@ -20,7 +20,14 @@ class CFeeRate;
|
|||
class CScript;
|
||||
|
||||
/** Default for -blockmaxweight, which controls the range of block weights the mining code will create **/
|
||||
static constexpr unsigned int DEFAULT_BLOCK_MAX_WEIGHT{MAX_BLOCK_WEIGHT - 4000};
|
||||
static constexpr unsigned int DEFAULT_BLOCK_MAX_WEIGHT{MAX_BLOCK_WEIGHT};
|
||||
/** Default for -blockreservedweight **/
|
||||
static constexpr unsigned int DEFAULT_BLOCK_RESERVED_WEIGHT{8000};
|
||||
/** This accounts for the block header, var_int encoding of the transaction count and a minimally viable
|
||||
* coinbase transaction. It adds an additional safety margin, because even with a thorough understanding
|
||||
* of block serialization, it's easy to make a costly mistake when trying to squeeze every last byte.
|
||||
* Setting a lower value is prevented at startup. */
|
||||
static constexpr unsigned int MINIMUM_BLOCK_RESERVED_WEIGHT{2000};
|
||||
/** Default for -blockmintxfee, which sets the minimum feerate for a transaction in blocks created by mining code **/
|
||||
static constexpr unsigned int DEFAULT_BLOCK_MIN_TX_FEE{1000};
|
||||
/** The maximum weight for transactions we're willing to relay/mine */
|
||||
|
|
|
@ -420,8 +420,8 @@ static RPCHelpMan getmininginfo()
|
|||
RPCResult::Type::OBJ, "", "",
|
||||
{
|
||||
{RPCResult::Type::NUM, "blocks", "The current block"},
|
||||
{RPCResult::Type::NUM, "currentblockweight", /*optional=*/true, "The block weight of the last assembled block (only present if a block was ever assembled)"},
|
||||
{RPCResult::Type::NUM, "currentblocktx", /*optional=*/true, "The number of block transactions of the last assembled block (only present if a block was ever assembled)"},
|
||||
{RPCResult::Type::NUM, "currentblockweight", /*optional=*/true, "The block weight (including reserved weight for block header, txs count and coinbase tx) of the last assembled block (only present if a block was ever assembled)"},
|
||||
{RPCResult::Type::NUM, "currentblocktx", /*optional=*/true, "The number of block transactions (excluding coinbase) of the last assembled block (only present if a block was ever assembled)"},
|
||||
{RPCResult::Type::STR_HEX, "bits", "The current nBits, compact representation of the block difficulty target"},
|
||||
{RPCResult::Type::NUM, "difficulty", "The current difficulty"},
|
||||
{RPCResult::Type::STR_HEX, "target", "The current target"},
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include <node/miner.h>
|
||||
#include <node/mini_miner.h>
|
||||
#include <node/types.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <random.h>
|
||||
#include <txmempool.h>
|
||||
|
@ -157,9 +158,10 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
|
|||
}
|
||||
}
|
||||
|
||||
// Stop if pool reaches DEFAULT_BLOCK_MAX_WEIGHT because BlockAssembler will stop when the
|
||||
const auto block_adjusted_max_weight = MAX_BLOCK_WEIGHT - DEFAULT_BLOCK_RESERVED_WEIGHT;
|
||||
// Stop if pool reaches block_adjusted_max_weight because BlockAssembler will stop when the
|
||||
// block template reaches that, but the MiniMiner will keep going.
|
||||
if (pool.GetTotalTxSize() + GetVirtualTransactionSize(*tx) >= DEFAULT_BLOCK_MAX_WEIGHT) break;
|
||||
if (pool.GetTotalTxSize() + GetVirtualTransactionSize(*tx) >= block_adjusted_max_weight) break;
|
||||
TestMemPoolEntryHelper entry;
|
||||
const CAmount fee{ConsumeMoney(fuzzed_data_provider, /*max=*/MAX_MONEY/100000)};
|
||||
assert(MoneyRange(fee));
|
||||
|
@ -181,7 +183,7 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
|
|||
|
||||
node::BlockAssembler::Options miner_options;
|
||||
miner_options.blockMinFeeRate = target_feerate;
|
||||
miner_options.nBlockMaxWeight = DEFAULT_BLOCK_MAX_WEIGHT;
|
||||
miner_options.nBlockMaxWeight = MAX_BLOCK_WEIGHT;
|
||||
miner_options.test_block_validity = false;
|
||||
miner_options.coinbase_output_script = CScript() << OP_0;
|
||||
|
||||
|
|
|
@ -26,7 +26,11 @@ from test_framework.messages import (
|
|||
CBlock,
|
||||
CBlockHeader,
|
||||
COIN,
|
||||
DEFAULT_BLOCK_RESERVED_WEIGHT,
|
||||
MAX_BLOCK_WEIGHT,
|
||||
MINIMUM_BLOCK_RESERVED_WEIGHT,
|
||||
ser_uint256,
|
||||
WITNESS_SCALE_FACTOR
|
||||
)
|
||||
from test_framework.p2p import P2PDataStore
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
|
@ -77,7 +81,7 @@ class MiningTest(BitcoinTestFramework):
|
|||
mining_info = self.nodes[0].getmininginfo()
|
||||
assert_equal(mining_info['blocks'], 200)
|
||||
assert_equal(mining_info['currentblocktx'], 0)
|
||||
assert_equal(mining_info['currentblockweight'], 4000)
|
||||
assert_equal(mining_info['currentblockweight'], DEFAULT_BLOCK_RESERVED_WEIGHT)
|
||||
|
||||
self.log.info('test blockversion')
|
||||
self.restart_node(0, extra_args=[f'-mocktime={t}', '-blockversion=1337'])
|
||||
|
@ -195,6 +199,116 @@ class MiningTest(BitcoinTestFramework):
|
|||
assert_equal(result, "inconclusive")
|
||||
assert_equal(prune_node.getblock(pruned_blockhash, verbosity=0), pruned_block)
|
||||
|
||||
|
||||
def send_transactions(self, utxos, fee_rate, target_vsize):
|
||||
"""
|
||||
Helper to create and send transactions with the specified target virtual size and fee rate.
|
||||
"""
|
||||
for utxo in utxos:
|
||||
self.wallet.send_self_transfer(
|
||||
from_node=self.nodes[0],
|
||||
utxo_to_spend=utxo,
|
||||
target_vsize=target_vsize,
|
||||
fee_rate=fee_rate,
|
||||
)
|
||||
|
||||
def verify_block_template(self, expected_tx_count, expected_weight):
|
||||
"""
|
||||
Create a block template and check that it satisfies the expected transaction count and total weight.
|
||||
"""
|
||||
response = self.nodes[0].getblocktemplate(NORMAL_GBT_REQUEST_PARAMS)
|
||||
self.log.info(f"Testing block template: contains {expected_tx_count} transactions, and total weight <= {expected_weight}")
|
||||
assert_equal(len(response["transactions"]), expected_tx_count)
|
||||
total_weight = sum(transaction["weight"] for transaction in response["transactions"])
|
||||
assert_greater_than_or_equal(expected_weight, total_weight)
|
||||
|
||||
def test_block_max_weight(self):
|
||||
self.log.info("Testing default and custom -blockmaxweight startup options.")
|
||||
|
||||
# Restart the node to allow large transactions
|
||||
LARGE_TXS_COUNT = 10
|
||||
LARGE_VSIZE = int(((MAX_BLOCK_WEIGHT - DEFAULT_BLOCK_RESERVED_WEIGHT) / WITNESS_SCALE_FACTOR) / LARGE_TXS_COUNT)
|
||||
HIGH_FEERATE = Decimal("0.0003")
|
||||
self.restart_node(0, extra_args=[f"-datacarriersize={LARGE_VSIZE}"])
|
||||
|
||||
# Ensure the mempool is empty
|
||||
assert_equal(len(self.nodes[0].getrawmempool()), 0)
|
||||
|
||||
# Generate UTXOs and send 10 large transactions with a high fee rate
|
||||
utxos = [self.wallet.get_utxo(confirmed_only=True) for _ in range(LARGE_TXS_COUNT + 4)] # Add 4 more utxos that will be used in the test later
|
||||
self.send_transactions(utxos[:LARGE_TXS_COUNT], HIGH_FEERATE, LARGE_VSIZE)
|
||||
|
||||
# Send 2 normal transactions with a lower fee rate
|
||||
NORMAL_VSIZE = int(2000 / WITNESS_SCALE_FACTOR)
|
||||
NORMAL_FEERATE = Decimal("0.0001")
|
||||
self.send_transactions(utxos[LARGE_TXS_COUNT:LARGE_TXS_COUNT + 2], NORMAL_FEERATE, NORMAL_VSIZE)
|
||||
|
||||
# Check that the mempool contains all transactions
|
||||
self.log.info(f"Testing that the mempool contains {LARGE_TXS_COUNT + 2} transactions.")
|
||||
assert_equal(len(self.nodes[0].getrawmempool()), LARGE_TXS_COUNT + 2)
|
||||
|
||||
# Verify the block template includes only the 10 high-fee transactions
|
||||
self.log.info("Testing that the block template includes only the 10 large transactions.")
|
||||
self.verify_block_template(
|
||||
expected_tx_count=LARGE_TXS_COUNT,
|
||||
expected_weight=MAX_BLOCK_WEIGHT - DEFAULT_BLOCK_RESERVED_WEIGHT,
|
||||
)
|
||||
|
||||
# Test block template creation with custom -blockmaxweight
|
||||
custom_block_weight = MAX_BLOCK_WEIGHT - 2000
|
||||
# Reducing the weight by 2000 units will prevent 1 large transaction from fitting into the block.
|
||||
self.restart_node(0, extra_args=[f"-datacarriersize={LARGE_VSIZE}", f"-blockmaxweight={custom_block_weight}"])
|
||||
|
||||
self.log.info("Testing the block template with custom -blockmaxweight to include 9 large and 2 normal transactions.")
|
||||
self.verify_block_template(
|
||||
expected_tx_count=11,
|
||||
expected_weight=MAX_BLOCK_WEIGHT - DEFAULT_BLOCK_RESERVED_WEIGHT - 2000,
|
||||
)
|
||||
|
||||
# Ensure the block weight does not exceed the maximum
|
||||
self.log.info(f"Testing that the block weight will never exceed {MAX_BLOCK_WEIGHT - DEFAULT_BLOCK_RESERVED_WEIGHT}.")
|
||||
self.restart_node(0, extra_args=[f"-datacarriersize={LARGE_VSIZE}", f"-blockmaxweight={MAX_BLOCK_WEIGHT}"])
|
||||
self.log.info("Sending 2 additional normal transactions to fill the mempool to the maximum block weight.")
|
||||
self.send_transactions(utxos[LARGE_TXS_COUNT + 2:], NORMAL_FEERATE, NORMAL_VSIZE)
|
||||
self.log.info(f"Testing that the mempool's weight matches the maximum block weight: {MAX_BLOCK_WEIGHT}.")
|
||||
assert_equal(self.nodes[0].getmempoolinfo()['bytes'] * WITNESS_SCALE_FACTOR, MAX_BLOCK_WEIGHT)
|
||||
|
||||
self.log.info("Testing that the block template includes only 10 transactions and cannot reach full block weight.")
|
||||
self.verify_block_template(
|
||||
expected_tx_count=LARGE_TXS_COUNT,
|
||||
expected_weight=MAX_BLOCK_WEIGHT - DEFAULT_BLOCK_RESERVED_WEIGHT,
|
||||
)
|
||||
|
||||
self.log.info("Test -blockreservedweight startup option.")
|
||||
# Lowering the -blockreservedweight by 4000 will allow for two more transactions.
|
||||
self.restart_node(0, extra_args=[f"-datacarriersize={LARGE_VSIZE}", "-blockreservedweight=4000"])
|
||||
self.verify_block_template(
|
||||
expected_tx_count=12,
|
||||
expected_weight=MAX_BLOCK_WEIGHT - 4000,
|
||||
)
|
||||
|
||||
self.log.info("Test that node will fail to start when user provide invalid -blockreservedweight")
|
||||
self.stop_node(0)
|
||||
self.nodes[0].assert_start_raises_init_error(
|
||||
extra_args=[f"-blockreservedweight={MAX_BLOCK_WEIGHT + 1}"],
|
||||
expected_msg=f"Error: Specified -blockreservedweight ({MAX_BLOCK_WEIGHT + 1}) exceeds consensus maximum block weight ({MAX_BLOCK_WEIGHT})",
|
||||
)
|
||||
|
||||
self.log.info(f"Test that node will fail to start when user provide -blockreservedweight below {MINIMUM_BLOCK_RESERVED_WEIGHT}")
|
||||
self.stop_node(0)
|
||||
self.nodes[0].assert_start_raises_init_error(
|
||||
extra_args=[f"-blockreservedweight={MINIMUM_BLOCK_RESERVED_WEIGHT - 1}"],
|
||||
expected_msg=f"Error: Specified -blockreservedweight ({MINIMUM_BLOCK_RESERVED_WEIGHT - 1}) is lower than minimum safety value of ({MINIMUM_BLOCK_RESERVED_WEIGHT})",
|
||||
)
|
||||
|
||||
self.log.info("Test that node will fail to start when user provide invalid -blockmaxweight")
|
||||
self.stop_node(0)
|
||||
self.nodes[0].assert_start_raises_init_error(
|
||||
extra_args=[f"-blockmaxweight={MAX_BLOCK_WEIGHT + 1}"],
|
||||
expected_msg=f"Error: Specified -blockmaxweight ({MAX_BLOCK_WEIGHT + 1}) exceeds consensus maximum block weight ({MAX_BLOCK_WEIGHT})",
|
||||
)
|
||||
|
||||
|
||||
def run_test(self):
|
||||
node = self.nodes[0]
|
||||
self.wallet = MiniWallet(node)
|
||||
|
@ -420,6 +534,7 @@ class MiningTest(BitcoinTestFramework):
|
|||
assert_equal(node.submitblock(hexdata=block.serialize().hex()), 'duplicate') # valid
|
||||
|
||||
self.test_blockmintxfee_parameter()
|
||||
self.test_block_max_weight()
|
||||
self.test_timewarp()
|
||||
self.test_pruning()
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ from test_framework.util import assert_equal
|
|||
|
||||
MAX_LOCATOR_SZ = 101
|
||||
MAX_BLOCK_WEIGHT = 4000000
|
||||
DEFAULT_BLOCK_RESERVED_WEIGHT = 8000
|
||||
MINIMUM_BLOCK_RESERVED_WEIGHT = 2000
|
||||
MAX_BLOOM_FILTER_SIZE = 36000
|
||||
MAX_BLOOM_HASH_FUNCS = 50
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue