@@ -415,9 +415,6 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet,
415
415
// Allowing partial spends means no grouping. Each COutput gets its own OutputGroup
416
416
for (const auto & [type, outputs] : coins.coins ) {
417
417
for (const COutput& output : outputs) {
418
- // Skip outputs we cannot spend
419
- if (!output.spendable ) continue ;
420
-
421
418
// Get mempool info
422
419
size_t ancestors, descendants;
423
420
wallet.chain ().getTransactionAncestry (output.outpoint .hash , ancestors, descendants);
@@ -444,11 +441,10 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet,
444
441
// to the last OutputGroup in the vector for the scriptPubKey. When the last OutputGroup has
445
442
// OUTPUT_GROUP_MAX_ENTRIES COutputs, a new OutputGroup is added to the end of the vector.
446
443
typedef std::map<std::pair<CScript, OutputType>, std::vector<OutputGroup>> ScriptPubKeyToOutgroup;
447
- const auto & group_outputs = [](
448
- const COutput& output, OutputType type, size_t ancestors, size_t descendants,
449
- ScriptPubKeyToOutgroup& groups_map, const CoinSelectionParams& coin_sel_params,
450
- bool positive_only) {
451
- std::vector<OutputGroup>& groups = groups_map[std::make_pair (output.txout .scriptPubKey ,type)];
444
+ const auto & insert_output = [&](
445
+ const std::shared_ptr<COutput>& output, OutputType type, size_t ancestors, size_t descendants,
446
+ ScriptPubKeyToOutgroup& groups_map) {
447
+ std::vector<OutputGroup>& groups = groups_map[std::make_pair (output->txout .scriptPubKey ,type)];
452
448
453
449
if (groups.size () == 0 ) {
454
450
// No OutputGroups for this scriptPubKey yet, add one
@@ -467,25 +463,24 @@ FilteredOutputGroups GroupOutputs(const CWallet& wallet,
467
463
group = &groups.back ();
468
464
}
469
465
470
- // Filter for positive only before adding the output to group
471
- if (!positive_only || output.GetEffectiveValue () > 0 ) {
472
- group->Insert (std::make_shared<COutput>(output), ancestors, descendants);
473
- }
466
+ group->Insert (output, ancestors, descendants);
474
467
};
475
468
476
469
ScriptPubKeyToOutgroup spk_to_groups_map;
477
470
ScriptPubKeyToOutgroup spk_to_positive_groups_map;
478
471
for (const auto & [type, outs] : coins.coins ) {
479
472
for (const COutput& output : outs) {
480
- // Skip outputs we cannot spend
481
- if (!output.spendable ) continue ;
482
-
483
473
size_t ancestors, descendants;
484
474
wallet.chain ().getTransactionAncestry (output.outpoint .hash , ancestors, descendants);
485
475
486
- group_outputs (output, type, ancestors, descendants, spk_to_groups_map, coin_sel_params, /* positive_only=*/ false );
487
- group_outputs (output, type, ancestors, descendants, spk_to_positive_groups_map,
488
- coin_sel_params, /* positive_only=*/ true );
476
+ const auto & shared_output = std::make_shared<COutput>(output);
477
+ // Filter for positive only before adding the output
478
+ if (output.GetEffectiveValue () > 0 ) {
479
+ insert_output (shared_output, type, ancestors, descendants, spk_to_positive_groups_map);
480
+ }
481
+
482
+ // 'All' groups
483
+ insert_output (shared_output, type, ancestors, descendants, spk_to_groups_map);
489
484
}
490
485
}
491
486
@@ -622,7 +617,7 @@ util::Result<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& av
622
617
}
623
618
624
619
// Start wallet Coin Selection procedure
625
- auto op_selection_result = AutomaticCoinSelection (wallet, available_coins, selection_target, coin_control, coin_selection_params);
620
+ auto op_selection_result = AutomaticCoinSelection (wallet, available_coins, selection_target, coin_selection_params);
626
621
if (!op_selection_result) return op_selection_result;
627
622
628
623
// If needed, add preset inputs to the automatic coin selection result
@@ -637,7 +632,7 @@ util::Result<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& av
637
632
return op_selection_result;
638
633
}
639
634
640
- util::Result<SelectionResult> AutomaticCoinSelection (const CWallet& wallet, CoinsResult& available_coins, const CAmount& value_to_select, const CCoinControl& coin_control, const CoinSelectionParams& coin_selection_params)
635
+ util::Result<SelectionResult> AutomaticCoinSelection (const CWallet& wallet, CoinsResult& available_coins, const CAmount& value_to_select, const CoinSelectionParams& coin_selection_params)
641
636
{
642
637
unsigned int limit_ancestor_count = 0 ;
643
638
unsigned int limit_descendant_count = 0 ;
@@ -646,12 +641,10 @@ util::Result<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, Coin
646
641
const size_t max_descendants = (size_t )std::max<int64_t >(1 , limit_descendant_count);
647
642
const bool fRejectLongChains = gArgs .GetBoolArg (" -walletrejectlongchains" , DEFAULT_WALLET_REJECT_LONG_CHAINS);
648
643
649
- // form groups from remaining coins; note that preset coins will not
650
- // automatically have their associated (same address) coins included
651
- if (coin_control.m_avoid_partial_spends && available_coins.Size () > OUTPUT_GROUP_MAX_ENTRIES) {
652
- // Cases where we have 101+ outputs all pointing to the same destination may result in
653
- // privacy leaks as they will potentially be deterministically sorted. We solve that by
654
- // explicitly shuffling the outputs before processing
644
+ // Cases where we have 101+ outputs all pointing to the same destination may result in
645
+ // privacy leaks as they will potentially be deterministically sorted. We solve that by
646
+ // explicitly shuffling the outputs before processing
647
+ if (coin_selection_params.m_avoid_partial_spends && available_coins.Size () > OUTPUT_GROUP_MAX_ENTRIES) {
655
648
available_coins.Shuffle (coin_selection_params.rng_fast );
656
649
}
657
650
@@ -678,7 +671,7 @@ util::Result<SelectionResult> AutomaticCoinSelection(const CWallet& wallet, Coin
678
671
ordered_filters.push_back ({CoinEligibilityFilter (0 , 1 , max_ancestors-1 , max_descendants-1 , /* include_partial=*/ true )});
679
672
// Try with unsafe inputs if they are allowed. This may spend unconfirmed outputs
680
673
// received from other wallets.
681
- if (coin_control .m_include_unsafe_inputs ) {
674
+ if (coin_selection_params .m_include_unsafe_inputs ) {
682
675
ordered_filters.push_back ({CoinEligibilityFilter (/* conf_mine=*/ 0 , /* conf_theirs*/ 0 , max_ancestors-1 , max_descendants-1 , /* include_partial=*/ true )});
683
676
}
684
677
// Try with unlimited ancestors/descendants. The transaction will still need to meet
@@ -809,6 +802,7 @@ static util::Result<CreatedTransactionResult> CreateTransactionInternal(
809
802
810
803
CoinSelectionParams coin_selection_params{rng_fast}; // Parameters for coin selection, init with dummy
811
804
coin_selection_params.m_avoid_partial_spends = coin_control.m_avoid_partial_spends ;
805
+ coin_selection_params.m_include_unsafe_inputs = coin_control.m_include_unsafe_inputs ;
812
806
813
807
// Set the long term feerate estimate to the wallet's consolidate feerate
814
808
coin_selection_params.m_long_term_feerate = wallet.m_consolidate_feerate ;
0 commit comments