From a8a75346d7e7247596c8a580d65ceaad49c97b97 Mon Sep 17 00:00:00 2001 From: furszy Date: Wed, 24 Aug 2022 15:03:13 -0300 Subject: [PATCH] wallet: SelectCoins, return early if target is covered by preset-inputs --- src/wallet/spend.cpp | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/src/wallet/spend.cpp b/src/wallet/spend.cpp index f17a53348b..644b2b587c 100644 --- a/src/wallet/spend.cpp +++ b/src/wallet/spend.cpp @@ -575,11 +575,11 @@ std::optional SelectCoins(const CWallet& wallet, CoinsResult& a // Deduct preset inputs amount from the search target CAmount selection_target = nTargetValue - pre_set_inputs.total_amount; - // If automatic coin selection was disabled, we just want to return the preset inputs result - if (!coin_control.m_allow_other_inputs) { - // 'selection_target' is computed on `PreSelectedInputs::Insert` which decides whether to use the effective value - // or the raw output value based on the 'subtract_fee_outputs' flag. - if (selection_target > 0) return std::nullopt; + // Return if automatic coin selection is disabled, and we don't cover the selection target + if (!coin_control.m_allow_other_inputs && selection_target > 0) return std::nullopt; + + // Return if we can cover the target only with the preset inputs + if (selection_target <= 0) { SelectionResult result(nTargetValue, SelectionAlgorithm::MANUAL); result.AddInputs(pre_set_inputs.coins, coin_selection_params.m_subtract_fee_outputs); result.ComputeAndSetWaste(coin_selection_params.min_viable_change, coin_selection_params.m_cost_of_change, coin_selection_params.m_change_fee); @@ -590,12 +590,14 @@ std::optional SelectCoins(const CWallet& wallet, CoinsResult& a auto op_selection_result = AutomaticCoinSelection(wallet, available_coins, selection_target, coin_control, coin_selection_params); if (!op_selection_result) return op_selection_result; - // Add preset inputs to the automatic coin selection result - SelectionResult preselected(pre_set_inputs.total_amount, SelectionAlgorithm::MANUAL); - preselected.AddInputs(pre_set_inputs.coins, coin_selection_params.m_subtract_fee_outputs); - op_selection_result->Merge(preselected); - if (op_selection_result->GetAlgo() == SelectionAlgorithm::MANUAL) { - op_selection_result->ComputeAndSetWaste(coin_selection_params.min_viable_change, coin_selection_params.m_cost_of_change, coin_selection_params.m_change_fee); + // If needed, add preset inputs to the automatic coin selection result + if (!pre_set_inputs.coins.empty()) { + SelectionResult preselected(pre_set_inputs.total_amount, SelectionAlgorithm::MANUAL); + preselected.AddInputs(pre_set_inputs.coins, coin_selection_params.m_subtract_fee_outputs); + op_selection_result->Merge(preselected); + op_selection_result->ComputeAndSetWaste(coin_selection_params.min_viable_change, + coin_selection_params.m_cost_of_change, + coin_selection_params.m_change_fee); } return op_selection_result; } @@ -622,9 +624,6 @@ std::optional AutomaticCoinSelection(const CWallet& wallet, Coi // transaction at a target feerate. If an attempt fails, more attempts may be made using a more // permissive CoinEligibilityFilter. std::optional res = [&] { - // Pre-selected inputs already cover the target amount. - if (value_to_select <= 0) return std::make_optional(SelectionResult(value_to_select, SelectionAlgorithm::MANUAL)); - // If possible, fund the transaction with confirmed UTXOs only. Prefer at least six // confirmations on outputs received from other wallets and only spend confirmed change. if (auto r1{AttemptSelection(wallet, value_to_select, CoinEligibilityFilter(1, 6, 0), available_coins, coin_selection_params, /*allow_mixed_output_types=*/false)}) return r1;