@@ -622,6 +622,11 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a
622
622
return op_selection_result;
623
623
}
624
624
625
+ struct SelectionFilter {
626
+ CoinEligibilityFilter filter;
627
+ bool allow_mixed_output_types{true };
628
+ };
629
+
625
630
std::optional<SelectionResult> AutomaticCoinSelection (const CWallet& wallet, CoinsResult& available_coins, const CAmount& value_to_select, const CCoinControl& coin_control, const CoinSelectionParams& coin_selection_params)
626
631
{
627
632
unsigned int limit_ancestor_count = 0 ;
@@ -644,51 +649,43 @@ std::optional<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, Coi
644
649
// transaction at a target feerate. If an attempt fails, more attempts may be made using a more
645
650
// permissive CoinEligibilityFilter.
646
651
std::optional<SelectionResult> res = [&] {
647
- // If possible, fund the transaction with confirmed UTXOs only. Prefer at least six
648
- // confirmations on outputs received from other wallets and only spend confirmed change.
649
- if (auto r1{AttemptSelection (wallet, value_to_select, CoinEligibilityFilter (1 , 6 , 0 ), available_coins, coin_selection_params, /* allow_mixed_output_types=*/ false )}) return r1;
650
- // Allow mixing only if no solution from any single output type can be found
651
- if (auto r2{AttemptSelection (wallet, value_to_select, CoinEligibilityFilter (1 , 1 , 0 ), available_coins, coin_selection_params, /* allow_mixed_output_types=*/ true )}) return r2;
652
-
652
+ // Place coins eligibility filters on a scope increasing order.
653
+ std::vector<SelectionFilter> ordered_filters{
654
+ // If possible, fund the transaction with confirmed UTXOs only. Prefer at least six
655
+ // confirmations on outputs received from other wallets and only spend confirmed change.
656
+ {CoinEligibilityFilter (1 , 6 , 0 ), /* allow_mixed_output_types=*/ false },
657
+ {CoinEligibilityFilter (1 , 1 , 0 )},
658
+ };
653
659
// Fall back to using zero confirmation change (but with as few ancestors in the mempool as
654
660
// possible) if we cannot fund the transaction otherwise.
655
661
if (wallet.m_spend_zero_conf_change ) {
656
- if (auto r3{AttemptSelection (wallet, value_to_select, CoinEligibilityFilter (0 , 1 , 2 ), available_coins, coin_selection_params, /* allow_mixed_output_types=*/ true )}) return r3;
657
- if (auto r4{AttemptSelection (wallet, value_to_select, CoinEligibilityFilter (0 , 1 , std::min ((size_t )4 , max_ancestors/3 ), std::min ((size_t )4 , max_descendants/3 )),
658
- available_coins, coin_selection_params, /* allow_mixed_output_types=*/ true )}) {
659
- return r4;
660
- }
661
- if (auto r5{AttemptSelection (wallet, value_to_select, CoinEligibilityFilter (0 , 1 , max_ancestors/2 , max_descendants/2 ),
662
- available_coins, coin_selection_params, /* allow_mixed_output_types=*/ true )}) {
663
- return r5;
664
- }
662
+ ordered_filters.push_back ({CoinEligibilityFilter (0 , 1 , 2 )});
663
+ ordered_filters.push_back ({CoinEligibilityFilter (0 , 1 , std::min ((size_t )4 , max_ancestors/3 ), std::min ((size_t )4 , max_descendants/3 ))});
664
+ ordered_filters.push_back ({CoinEligibilityFilter (0 , 1 , max_ancestors/2 , max_descendants/2 )});
665
665
// If partial groups are allowed, relax the requirement of spending OutputGroups (groups
666
666
// of UTXOs sent to the same address, which are obviously controlled by a single wallet)
667
667
// in their entirety.
668
- if (auto r6{AttemptSelection (wallet, value_to_select, CoinEligibilityFilter (0 , 1 , max_ancestors-1 , max_descendants-1 , /* include_partial=*/ true ),
669
- available_coins, coin_selection_params, /* allow_mixed_output_types=*/ true )}) {
670
- return r6;
671
- }
668
+ ordered_filters.push_back ({CoinEligibilityFilter (0 , 1 , max_ancestors-1 , max_descendants-1 , /* include_partial=*/ true )});
672
669
// Try with unsafe inputs if they are allowed. This may spend unconfirmed outputs
673
670
// received from other wallets.
674
671
if (coin_control.m_include_unsafe_inputs ) {
675
- if (auto r7{AttemptSelection (wallet, value_to_select,
676
- CoinEligibilityFilter (/* conf_mine=*/ 0 , /* conf_theirs=*/ 0 , max_ancestors-1 , max_descendants-1 , /* include_partial=*/ true ),
677
- available_coins, coin_selection_params, /* allow_mixed_output_types=*/ true )}) {
678
- return r7;
679
- }
672
+ ordered_filters.push_back ({CoinEligibilityFilter (/* conf_mine=*/ 0 , /* conf_theirs*/ 0 , max_ancestors-1 , max_descendants-1 , /* include_partial=*/ true )});
680
673
}
681
674
// Try with unlimited ancestors/descendants. The transaction will still need to meet
682
675
// mempool ancestor/descendant policy to be accepted to mempool and broadcasted, but
683
676
// OutputGroups use heuristics that may overestimate ancestor/descendant counts.
684
677
if (!fRejectLongChains ) {
685
- if (auto r8{AttemptSelection (wallet, value_to_select,
686
- CoinEligibilityFilter (0 , 1 , std::numeric_limits<uint64_t >::max (), std::numeric_limits<uint64_t >::max (), /* include_partial=*/ true ),
687
- available_coins, coin_selection_params, /* allow_mixed_output_types=*/ true )}) {
688
- return r8;
689
- }
678
+ ordered_filters.push_back ({CoinEligibilityFilter (0 , 1 , std::numeric_limits<uint64_t >::max (),
679
+ std::numeric_limits<uint64_t >::max (),
680
+ /* include_partial=*/ true )});
690
681
}
691
682
}
683
+
684
+ // Walk-through the filters until the solution gets found
685
+ for (const auto & select_filter : ordered_filters) {
686
+ if (auto res{AttemptSelection (wallet, value_to_select, select_filter.filter , available_coins,
687
+ coin_selection_params, select_filter.allow_mixed_output_types )}) return res;
688
+ }
692
689
// Coin Selection failed.
693
690
return std::optional<SelectionResult>();
694
691
}();
0 commit comments