From 5702c4410de5cd0c1ebc325a184e635e87752075 Mon Sep 17 00:00:00 2001 From: Fabian Jahr Date: Tue, 4 Mar 2025 15:25:38 +0100 Subject: [PATCH] fuzz: Increase number of transactions in block in mini_miner test At the current configuration there was zero chance to hit the size limit of a block. The new configuration uses larger transactions and conditionally adds the maximum possible number of transactions instead of using the previous limited while loop to ensure that with some regularity the test runs into full blocks. --- src/test/fuzz/mini_miner.cpp | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/src/test/fuzz/mini_miner.cpp b/src/test/fuzz/mini_miner.cpp index 2ce10f12a5c..8185fa3ab67 100644 --- a/src/test/fuzz/mini_miner.cpp +++ b/src/test/fuzz/mini_miner.cpp @@ -131,14 +131,32 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner) std::vector transactions; // The maximum block template size we expect to produce const auto block_adjusted_max_weight = MAX_BLOCK_WEIGHT - MINIMUM_BLOCK_RESERVED_WEIGHT; + // When this is set to true we try to fill up the rest of the block with + // a lot of small transactions so we can actually get close to actual + // maximum block size + std::optional min_size_tx{std::nullopt}; + // This decides if we target a larger, potentially full block or a smaller + // block that will complete the test much faster + bool use_limited_loop = fuzzed_data_provider.ConsumeBool(); + auto should_continue = [&]() -> bool { + if (use_limited_loop) { + return fuzzed_data_provider.ConsumeBool(); + } + return true; + }; LOCK2(::cs_main, pool.cs); - LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 100) + // Limited to 500 because of ClusterMempool DoS protection + LIMITED_WHILE(should_continue(), 500) { CMutableTransaction mtx = CMutableTransaction(); assert(!available_coins.empty()); - const size_t num_inputs = std::min(size_t{2}, available_coins.size()); - const size_t num_outputs = fuzzed_data_provider.ConsumeIntegralInRange(2, 5); + size_t num_inputs = std::min(size_t{2}, available_coins.size()); + size_t num_outputs = fuzzed_data_provider.ConsumeIntegralInRange(50, 500); + if (min_size_tx.has_value() && min_size_tx.value()) { + num_inputs = fuzzed_data_provider.ConsumeIntegralInRange(1, 5); + num_outputs = fuzzed_data_provider.ConsumeIntegralInRange(1, 5); + } for (size_t n{0}; n < num_inputs; ++n) { auto prevout = available_coins.at(0); mtx.vin.emplace_back(prevout, CScript()); @@ -162,7 +180,15 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner) // 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)) * 4 >= block_adjusted_max_weight) break; + if ((pool.GetTotalTxSize() + GetVirtualTransactionSize(*tx)) * 4 >= block_adjusted_max_weight) { + // Either stop here or fill up the rest of the block with very small + // transactions and break when the block is close to the possible max + if (!min_size_tx.has_value()) { + min_size_tx = fuzzed_data_provider.ConsumeBool(); + if (!min_size_tx.value()) break; + } + break; + } TestMemPoolEntryHelper entry; const CAmount fee{ConsumeMoney(fuzzed_data_provider, /*max=*/MAX_MONEY/100000)}; assert(MoneyRange(fee));