mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 02:25:40 +01:00
wallet: ensure m_min_change_target always covers change fee
This commit is contained in:
parent
dc9d662683
commit
c8cf08ea74
@ -389,14 +389,14 @@ CAmount GetSelectionWaste(const std::set<COutput>& inputs, CAmount change_cost,
|
||||
return waste;
|
||||
}
|
||||
|
||||
CAmount GenerateChangeTarget(CAmount payment_value, FastRandomContext& rng)
|
||||
CAmount GenerateChangeTarget(const CAmount payment_value, const CAmount change_fee, FastRandomContext& rng)
|
||||
{
|
||||
if (payment_value <= CHANGE_LOWER / 2) {
|
||||
return CHANGE_LOWER;
|
||||
return change_fee + CHANGE_LOWER;
|
||||
} else {
|
||||
// random value between 50ksat and min (payment_value * 2, 1milsat)
|
||||
const auto upper_bound = std::min(payment_value * 2, CHANGE_UPPER);
|
||||
return rng.randrange(upper_bound - CHANGE_LOWER) + CHANGE_LOWER;
|
||||
return change_fee + rng.randrange(upper_bound - CHANGE_LOWER) + CHANGE_LOWER;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,6 +252,7 @@ struct OutputGroup
|
||||
|
||||
/** Choose a random change target for each transaction to make it harder to fingerprint the Core
|
||||
* wallet based on the change output values of transactions it creates.
|
||||
* Change target covers at least change fees and adds a random value on top of it.
|
||||
* The random value is between 50ksat and min(2 * payment_value, 1milsat)
|
||||
* When payment_value <= 25ksat, the value is just 50ksat.
|
||||
*
|
||||
@ -261,8 +262,9 @@ struct OutputGroup
|
||||
* coins selected are just sufficient to cover the payment amount ("unnecessary input" heuristic).
|
||||
*
|
||||
* @param[in] payment_value Average payment value of the transaction output(s).
|
||||
* @param[in] change_fee Fee for creating a change output.
|
||||
*/
|
||||
[[nodiscard]] CAmount GenerateChangeTarget(CAmount payment_value, FastRandomContext& rng);
|
||||
[[nodiscard]] CAmount GenerateChangeTarget(const CAmount payment_value, const CAmount change_fee, FastRandomContext& rng);
|
||||
|
||||
enum class SelectionAlgorithm : uint8_t
|
||||
{
|
||||
|
@ -794,7 +794,6 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
|
||||
coin_selection_params.m_subtract_fee_outputs = true;
|
||||
}
|
||||
}
|
||||
coin_selection_params.m_min_change_target = GenerateChangeTarget(std::floor(recipients_sum / vecSend.size()), rng_fast);
|
||||
|
||||
// Create change script that will be used if we need change
|
||||
CScript scriptChange;
|
||||
@ -863,6 +862,8 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
|
||||
coin_selection_params.m_change_fee = coin_selection_params.m_effective_feerate.GetFee(coin_selection_params.change_output_size);
|
||||
coin_selection_params.m_cost_of_change = coin_selection_params.m_discard_feerate.GetFee(coin_selection_params.change_spend_size) + coin_selection_params.m_change_fee;
|
||||
|
||||
coin_selection_params.m_min_change_target = GenerateChangeTarget(std::floor(recipients_sum / vecSend.size()), coin_selection_params.m_change_fee, rng_fast);
|
||||
|
||||
// vouts to the payees
|
||||
if (!coin_selection_params.m_subtract_fee_outputs) {
|
||||
coin_selection_params.tx_noinputs_size = 10; // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 witness overhead (dummy, flag, stack size)
|
||||
|
@ -58,6 +58,8 @@ FUZZ_TARGET(coinselection)
|
||||
coin_params.m_subtract_fee_outputs = subtract_fee_outputs;
|
||||
coin_params.m_long_term_feerate = long_term_fee_rate;
|
||||
coin_params.m_effective_feerate = effective_fee_rate;
|
||||
coin_params.change_output_size = fuzzed_data_provider.ConsumeIntegralInRange<int>(10, 1000);
|
||||
coin_params.m_change_fee = effective_fee_rate.GetFee(coin_params.change_output_size);
|
||||
|
||||
// Create some coins
|
||||
CAmount total_balance{0};
|
||||
@ -85,7 +87,7 @@ FUZZ_TARGET(coinselection)
|
||||
auto result_srd = SelectCoinsSRD(group_pos, target, fast_random_context);
|
||||
if (result_srd) result_srd->ComputeAndSetWaste(cost_of_change);
|
||||
|
||||
CAmount change_target{GenerateChangeTarget(target, fast_random_context)};
|
||||
CAmount change_target{GenerateChangeTarget(target, coin_params.m_change_fee, fast_random_context)};
|
||||
auto result_knapsack = KnapsackSolver(group_all, target, change_target, fast_random_context);
|
||||
if (result_knapsack) result_knapsack->ComputeAndSetWaste(cost_of_change);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user