@@ -568,18 +568,14 @@ std::optional<SelectionResult> ChooseSelectionResult(const CWallet& wallet, cons
568
568
return best_result;
569
569
}
570
570
571
- std::optional<SelectionResult> SelectCoins (const CWallet& wallet, CoinsResult& available_coins, const CAmount& nTargetValue, const CCoinControl& coin_control, const CoinSelectionParams& coin_selection_params)
571
+ std::optional<SelectionResult> SelectCoins (const CWallet& wallet, CoinsResult& available_coins, const PreSelectedInputs& pre_set_inputs,
572
+ const CAmount& nTargetValue, const CCoinControl& coin_control,
573
+ const CoinSelectionParams& coin_selection_params)
572
574
{
573
- CAmount value_to_select = nTargetValue;
574
-
575
- util::Result<PreSelectedInputs> pre_selected_inputs = FetchSelectedInputs (wallet, coin_control, coin_selection_params);
576
- if (!pre_selected_inputs) return std::nullopt;
577
- PreSelectedInputs inputs = *pre_selected_inputs;
578
-
579
575
// If automatic coin selection was disabled, we just want to return the preset inputs result
580
576
if (!coin_control.m_allow_other_inputs ) {
581
577
SelectionResult result (nTargetValue, SelectionAlgorithm::MANUAL);
582
- result.AddInputs (inputs .coins , coin_selection_params.m_subtract_fee_outputs );
578
+ result.AddInputs (pre_set_inputs .coins , coin_selection_params.m_subtract_fee_outputs );
583
579
584
580
if (!coin_selection_params.m_subtract_fee_outputs && result.GetSelectedEffectiveValue () < nTargetValue) {
585
581
return std::nullopt;
@@ -591,9 +587,23 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a
591
587
return result;
592
588
}
593
589
594
- // Decrease the already selected amount
595
- value_to_select -= inputs.total_amount ;
590
+ // Decrease the selection target before start the automatic coin selection
591
+ CAmount selection_target = nTargetValue - pre_set_inputs.total_amount ;
592
+ auto op_selection_result = AutomaticCoinSelection (wallet, available_coins, selection_target, coin_control, coin_selection_params);
593
+ if (!op_selection_result) return op_selection_result;
594
+
595
+ // Add preset inputs to the automatic coin selection result
596
+ SelectionResult preselected (pre_set_inputs.total_amount , SelectionAlgorithm::MANUAL);
597
+ preselected.AddInputs (pre_set_inputs.coins , coin_selection_params.m_subtract_fee_outputs );
598
+ op_selection_result->Merge (preselected);
599
+ if (op_selection_result->GetAlgo () == SelectionAlgorithm::MANUAL) {
600
+ op_selection_result->ComputeAndSetWaste (coin_selection_params.min_viable_change , coin_selection_params.m_cost_of_change , coin_selection_params.m_change_fee );
601
+ }
602
+ return op_selection_result;
603
+ }
596
604
605
+ std::optional<SelectionResult> AutomaticCoinSelection (const CWallet& wallet, CoinsResult& available_coins, const CAmount& value_to_select, const CCoinControl& coin_control, const CoinSelectionParams& coin_selection_params)
606
+ {
597
607
unsigned int limit_ancestor_count = 0 ;
598
608
unsigned int limit_descendant_count = 0 ;
599
609
wallet.chain ().getPackageLimits (limit_ancestor_count, limit_descendant_count);
@@ -610,9 +620,6 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a
610
620
available_coins.Shuffle (coin_selection_params.rng_fast );
611
621
}
612
622
613
- SelectionResult preselected (inputs.total_amount , SelectionAlgorithm::MANUAL);
614
- preselected.AddInputs (inputs.coins , coin_selection_params.m_subtract_fee_outputs );
615
-
616
623
// Coin Selection attempts to select inputs from a pool of eligible UTXOs to fund the
617
624
// transaction at a target feerate. If an attempt fails, more attempts may be made using a more
618
625
// permissive CoinEligibilityFilter.
@@ -669,14 +676,6 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a
669
676
return std::optional<SelectionResult>();
670
677
}();
671
678
672
- if (!res) return std::nullopt;
673
-
674
- // Add preset inputs to result
675
- res->Merge (preselected);
676
- if (res->GetAlgo () == SelectionAlgorithm::MANUAL) {
677
- res->ComputeAndSetWaste (coin_selection_params.min_viable_change , coin_selection_params.m_cost_of_change , coin_selection_params.m_change_fee );
678
- }
679
-
680
679
return res;
681
680
}
682
681
@@ -889,6 +888,14 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
889
888
const CAmount not_input_fees = coin_selection_params.m_effective_feerate .GetFee (coin_selection_params.tx_noinputs_size );
890
889
CAmount selection_target = recipients_sum + not_input_fees;
891
890
891
+ // Fetch manually selected coins
892
+ PreSelectedInputs preset_inputs;
893
+ if (coin_control.HasSelected ()) {
894
+ auto res_fetch_inputs = FetchSelectedInputs (wallet, coin_control, coin_selection_params);
895
+ if (!res_fetch_inputs) return util::Error{util::ErrorString (res_fetch_inputs)};
896
+ preset_inputs = *res_fetch_inputs;
897
+ }
898
+
892
899
// Fetch wallet available coins if "other inputs" are
893
900
// allowed (coins automatically selected by the wallet)
894
901
CoinsResult available_coins;
@@ -903,7 +910,7 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
903
910
}
904
911
905
912
// Choose coins to use
906
- std::optional<SelectionResult> result = SelectCoins (wallet, available_coins, /* nTargetValue=*/ selection_target, coin_control, coin_selection_params);
913
+ std::optional<SelectionResult> result = SelectCoins (wallet, available_coins, preset_inputs, /* nTargetValue=*/ selection_target, coin_control, coin_selection_params);
907
914
if (!result) {
908
915
return util::Error{_ (" Insufficient funds" )};
909
916
}
0 commit comments