mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-06-01 00:34:01 +02:00
coin selection: knapsack, select closest UTXO above target if result exceeds max tx size
The simplest scenario where this is useful is on the 'check_max_weight' unit test already: We create 1515 UTXOs with 0.033 BTC each, and 1 UTXO with 50 BTC. Then perform Coin Selection. As the selection of the 1515 small UTXOs exceeds the max allowed tx size, the expectation here is to receive a selection result that only contain the big UTXO (which is not happening for the reasons stated below). As knapsack returns a result that exceeds the max allowed transaction size, we fallback to SRD, which selects coins randomly up until the target is met. So we end up with a selection result with lot more coins than what is needed.
This commit is contained in:
@@ -563,12 +563,18 @@ util::Result<SelectionResult> ChooseSelectionResult(const CAmount& nTargetValue,
|
||||
}
|
||||
};
|
||||
|
||||
// Maximum allowed weight
|
||||
int max_inputs_weight = MAX_STANDARD_TX_WEIGHT - (coin_selection_params.tx_noinputs_size * WITNESS_SCALE_FACTOR);
|
||||
|
||||
if (auto bnb_result{SelectCoinsBnB(groups.positive_group, nTargetValue, coin_selection_params.m_cost_of_change)}) {
|
||||
results.push_back(*bnb_result);
|
||||
} else append_error(bnb_result);
|
||||
|
||||
// As Knapsack and SRD can create change, also deduce change weight.
|
||||
max_inputs_weight -= (coin_selection_params.change_output_size * WITNESS_SCALE_FACTOR);
|
||||
|
||||
// The knapsack solver has some legacy behavior where it will spend dust outputs. We retain this behavior, so don't filter for positive only here.
|
||||
if (auto knapsack_result{KnapsackSolver(groups.mixed_group, nTargetValue, coin_selection_params.m_min_change_target, coin_selection_params.rng_fast)}) {
|
||||
if (auto knapsack_result{KnapsackSolver(groups.mixed_group, nTargetValue, coin_selection_params.m_min_change_target, coin_selection_params.rng_fast, max_inputs_weight)}) {
|
||||
knapsack_result->ComputeAndSetWaste(coin_selection_params.min_viable_change, coin_selection_params.m_cost_of_change, coin_selection_params.m_change_fee);
|
||||
results.push_back(*knapsack_result);
|
||||
} else append_error(knapsack_result);
|
||||
|
||||
Reference in New Issue
Block a user