This commit is contained in:
Fabian Jahr 2025-04-29 11:55:52 +02:00 committed by GitHub
commit 1dfd7eecf1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -129,14 +129,34 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
// Make a copy to preserve determinism.
std::deque<COutPoint> available_coins = g_available_coins;
std::vector<CTransactionRef> 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<bool> 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<size_t>(2, 5);
size_t num_inputs = std::min(size_t{2}, available_coins.size());
size_t num_outputs = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(50, 500);
if (min_size_tx.has_value() && min_size_tx.value()) {
num_inputs = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 5);
num_outputs = fuzzed_data_provider.ConsumeIntegralInRange<size_t>(1, 5);
}
for (size_t n{0}; n < num_inputs; ++n) {
auto prevout = available_coins.at(0);
mtx.vin.emplace_back(prevout, CScript());
@ -158,10 +178,17 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
}
}
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) >= 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));
@ -184,6 +211,11 @@ FUZZ_TARGET(mini_miner_selection, .init = initialize_miner)
node::BlockAssembler::Options miner_options;
miner_options.blockMinFeeRate = target_feerate;
miner_options.nBlockMaxWeight = MAX_BLOCK_WEIGHT;
// Only setting reserved weight when necessary based on the template size
const auto reserved_weight = MAX_BLOCK_WEIGHT - pool.GetTotalTxSize() * 4;
if (reserved_weight < DEFAULT_BLOCK_RESERVED_WEIGHT) {
miner_options.block_reserved_weight = reserved_weight - 1;
}
miner_options.test_block_validity = false;
miner_options.coinbase_output_script = CScript() << OP_0;