In 1881848e0c: "test: fuzz BlockTemplateManager"
The fuzz target looks good, but i do not see where this exercises the non-default BlockCreateArgs default arguments. I think this prevents it from exercising the merging cases.
I think perhpas we could construct a local BlockTemplateManager with the init-time options for each iteration, this would cover the options behavior
codex suggested this
index 297713d620..332a3a3ba1 100644
--- a/src/test/fuzz/block_template_manager.cpp
+++ b/src/test/fuzz/block_template_manager.cpp
@@ -159,8 +159,9 @@ FUZZ_TARGET(block_template_manager, .init = initialize_block_template_manager)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
const auto& node = g_setup->m_node;
- auto& block_template_manager = *Assert(node.block_template_manager);
auto& mempool = *Assert(node.mempool);
+ auto& chainman = *Assert(node.chainman);
+ auto& notifications = *Assert(node.notifications);
SeedRandomStateForTest(SeedRand::ZEROS);
SetMockTime(WITH_LOCK(node.chainman->GetMutex(),
return node.chainman->ActiveTip()->Time()));
@@ -179,6 +180,26 @@ FUZZ_TARGET(block_template_manager, .init = initialize_block_template_manager)
}
LIMITED_WHILE(fuzzed_data_provider.remaining_bytes() > 0, 10)
{
+ BlockCreateOptions init_options;
+ if (fuzzed_data_provider.ConsumeBool()) {
+ const CAmount fee_amount = fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(0, COIN);
+ const int32_t fee_size = fuzzed_data_provider.ConsumeIntegralInRange<int32_t>(1, MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR);
+ init_options.block_min_fee_rate = CFeeRate(fee_amount, fee_size);
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ init_options.print_modified_fee = fuzzed_data_provider.ConsumeBool();
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ init_options.block_reserved_weight = fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(
+ MINIMUM_BLOCK_RESERVED_WEIGHT, MAX_BLOCK_WEIGHT);
+ }
+ if (fuzzed_data_provider.ConsumeBool()) {
+ init_options.block_max_weight = fuzzed_data_provider.ConsumeIntegralInRange<uint64_t>(
+ MINIMUM_BLOCK_RESERVED_WEIGHT, MAX_BLOCK_WEIGHT);
+ }
+ // Match ReadMiningArgs(), which rejects invalid init-time options.
+ if (!node::CheckMiningOptions(init_options, /*use_argnames=*/false)) continue;
+
BlockCreateOptions options;
options.test_block_validity = use_valid_transactions;
if (fuzzed_data_provider.ConsumeBool()) {
@@ -207,9 +228,14 @@ FUZZ_TARGET(block_template_manager, .init = initialize_block_template_manager)
if (!use_valid_transactions && fuzzed_data_provider.ConsumeBool()) {
options.coinbase_output_script = ConsumeScript(fuzzed_data_provider);
}
+ const auto resolved{node::FlattenMiningOptions(node::MergeMiningOptions(options, init_options))};
+ // Per-call options must also result in a valid effective configuration.
+ if (!node::CheckMiningOptions(resolved, /*use_argnames=*/false)) continue;
+
+ node::BlockTemplateManager block_template_manager{
+ mempool, chainman, notifications, std::move(init_options)};
auto block_template = block_template_manager.CreateNewTemplate(options);
assert(block_template);
- const auto resolved{node::FlattenMiningOptions(node::MergeMiningOptions(options, block_template_manager.BlockCreateArgs()))};
const CBlock& block{block_template->block};
// Coinbase is first; the per-tx vectors exclude it and track the block.
assert(!block.vtx.empty() && block.vtx[0]->IsCoinBase());