MCPcopy Create free account
hub / github.com/bitcoin/bitcoin / FuzzCoinSelectionAlgorithm

Function FuzzCoinSelectionAlgorithm

src/wallet/test/fuzz/coinselection.cpp:353–472  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

351
352template<CoinSelectionAlgorithm Algorithm>
353void FuzzCoinSelectionAlgorithm(std::span<const uint8_t> buffer) {
354 SeedRandomStateForTest(SeedRand::ZEROS);
355 FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
356 std::vector<COutput> utxo_pool;
357
358 const CFeeRate long_term_fee_rate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
359 const CFeeRate effective_fee_rate{ConsumeMoney(fuzzed_data_provider, /*max=*/COIN)};
360 // Discard feerate must be at least dust relay feerate
361 const CFeeRate discard_fee_rate{fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(DUST_RELAY_TX_FEE, COIN)};
362 const CAmount target{fuzzed_data_provider.ConsumeIntegralInRange<CAmount>(1, MAX_MONEY)};
363 const bool subtract_fee_outputs{fuzzed_data_provider.ConsumeBool()};
364
365 FastRandomContext fast_random_context{ConsumeUInt256(fuzzed_data_provider)};
366 CoinSelectionParams coin_params{fast_random_context};
367 coin_params.m_subtract_fee_outputs = subtract_fee_outputs;
368 coin_params.m_long_term_feerate = long_term_fee_rate;
369 coin_params.m_effective_feerate = effective_fee_rate;
370 coin_params.change_output_size = fuzzed_data_provider.ConsumeIntegralInRange(1, MAX_SCRIPT_SIZE);
371 coin_params.m_change_fee = effective_fee_rate.GetFee(coin_params.change_output_size);
372 coin_params.m_discard_feerate = discard_fee_rate;
373 coin_params.change_spend_size = fuzzed_data_provider.ConsumeIntegralInRange<int>(41, 1000);
374 const auto change_spend_fee{coin_params.m_discard_feerate.GetFee(coin_params.change_spend_size)};
375 coin_params.m_cost_of_change = coin_params.m_change_fee + change_spend_fee;
376 CScript change_out_script = CScript() << std::vector<unsigned char>(coin_params.change_output_size, OP_TRUE);
377 const auto dust{GetDustThreshold(CTxOut{/*nValueIn=*/0, change_out_script}, coin_params.m_discard_feerate)};
378 coin_params.min_viable_change = std::max(change_spend_fee + 1, dust);
379
380 int next_locktime{0};
381 CAmount total_balance{CreateCoins(fuzzed_data_provider, utxo_pool, coin_params, next_locktime)};
382
383 std::vector<OutputGroup> group_pos;
384 GroupCoins(fuzzed_data_provider, utxo_pool, coin_params, /*positive_only=*/true, group_pos);
385
386 int max_selection_weight = fuzzed_data_provider.ConsumeIntegralInRange<int>(0, std::numeric_limits<int>::max());
387
388 std::optional<SelectionResult> result;
389
390 if constexpr (Algorithm == CoinSelectionAlgorithm::BNB) {
391 if (!coin_params.m_subtract_fee_outputs) {
392 auto result_bnb = SelectCoinsBnB(group_pos, target, coin_params.m_cost_of_change, max_selection_weight);
393 if (result_bnb) {
394 result = *result_bnb;
395 assert(result_bnb->GetChange(coin_params.min_viable_change, coin_params.m_change_fee) == 0);
396 assert(result_bnb->GetSelectedValue() >= target);
397 assert(result_bnb->GetWeight() <= max_selection_weight);
398 (void)result_bnb->GetShuffledInputVector();
399 (void)result_bnb->GetInputSet();
400 }
401 }
402 }
403
404 if constexpr (Algorithm == CoinSelectionAlgorithm::SRD) {
405 auto result_srd = SelectCoinsSRD(group_pos, target, coin_params.m_change_fee, fast_random_context, max_selection_weight);
406 if (result_srd) {
407 result = *result_srd;
408 assert(result_srd->GetSelectedValue() >= target);
409 assert(result_srd->GetChange(CHANGE_LOWER, coin_params.m_change_fee) > 0);
410 assert(result_srd->GetWeight() <= max_selection_weight);

Callers

nothing calls this directly

Calls 15

SeedRandomStateForTestFunction · 0.85
ConsumeMoneyFunction · 0.85
ConsumeUInt256Function · 0.85
GetDustThresholdFunction · 0.85
CreateCoinsFunction · 0.85
GroupCoinsFunction · 0.85
SelectCoinsSRDFunction · 0.85
GenerateChangeTargetFunction · 0.85
ManualSelectionFunction · 0.85
ConsumeBoolMethod · 0.80
GetChangeMethod · 0.80

Tested by

no test coverage detected