@@ -79,30 +79,27 @@ TxSize CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *walle
79
79
return CalculateMaximumSignedTxSize (tx, wallet, txouts, coin_control);
80
80
}
81
81
82
- uint64_t CoinsResult::Size () const
82
+ size_t CoinsResult::Size () const
83
83
{
84
- return bech32m.size () + bech32.size () + P2SH_segwit.size () + legacy.size () + other.size ();
84
+ size_t size{0 };
85
+ for (const auto & it : coins) {
86
+ size += it.second .size ();
87
+ }
88
+ return size;
85
89
}
86
90
87
91
std::vector<COutput> CoinsResult::All () const
88
92
{
89
93
std::vector<COutput> all;
90
- all.reserve (this ->Size ());
91
- all.insert (all.end (), bech32m.begin (), bech32m.end ());
92
- all.insert (all.end (), bech32.begin (), bech32.end ());
93
- all.insert (all.end (), P2SH_segwit.begin (), P2SH_segwit.end ());
94
- all.insert (all.end (), legacy.begin (), legacy.end ());
95
- all.insert (all.end (), other.begin (), other.end ());
94
+ all.reserve (coins.size ());
95
+ for (const auto & it : coins) {
96
+ all.insert (all.end (), it.second .begin (), it.second .end ());
97
+ }
96
98
return all;
97
99
}
98
100
99
- void CoinsResult::Clear ()
100
- {
101
- bech32m.clear ();
102
- bech32.clear ();
103
- P2SH_segwit.clear ();
104
- legacy.clear ();
105
- other.clear ();
101
+ void CoinsResult::Clear () {
102
+ coins.clear ();
106
103
}
107
104
108
105
void CoinsResult::Erase (std::set<COutPoint>& preset_coins)
@@ -263,51 +260,32 @@ CoinsResult AvailableCoins(const CWallet& wallet,
263
260
// Filter by spendable outputs only
264
261
if (!spendable && only_spendable) continue ;
265
262
266
- // When parsing a scriptPubKey, Solver returns the parsed pubkeys or hashes (depending on the script)
267
- // We don't need those here, so we are leaving them in return_values_unused
268
- std::vector<std::vector<uint8_t >> return_values_unused;
269
- TxoutType type;
270
- bool is_from_p2sh{false };
271
-
272
263
// If the Output is P2SH and spendable, we want to know if it is
273
264
// a P2SH (legacy) or one of P2SH-P2WPKH, P2SH-P2WSH (P2SH-Segwit). We can determine
274
265
// this from the redeemScript. If the Output is not spendable, it will be classified
275
266
// as a P2SH (legacy), since we have no way of knowing otherwise without the redeemScript
267
+ CScript script;
268
+ bool is_from_p2sh{false };
276
269
if (output.scriptPubKey .IsPayToScriptHash () && solvable) {
277
- CScript redeemScript;
278
270
CTxDestination destination;
279
271
if (!ExtractDestination (output.scriptPubKey , destination))
280
272
continue ;
281
273
const CScriptID& hash = CScriptID (std::get<ScriptHash>(destination));
282
- if (!provider->GetCScript (hash, redeemScript ))
274
+ if (!provider->GetCScript (hash, script ))
283
275
continue ;
284
- type = Solver (redeemScript, return_values_unused);
285
276
is_from_p2sh = true ;
286
277
} else {
287
- type = Solver ( output.scriptPubKey , return_values_unused) ;
278
+ script = output.scriptPubKey ;
288
279
}
289
280
290
281
COutput coin (outpoint, output, nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime (), tx_from_me, feerate);
291
- switch (type) {
292
- case TxoutType::WITNESS_UNKNOWN:
293
- case TxoutType::WITNESS_V1_TAPROOT:
294
- result.bech32m .push_back (coin);
295
- break ;
296
- case TxoutType::WITNESS_V0_KEYHASH:
297
- case TxoutType::WITNESS_V0_SCRIPTHASH:
298
- if (is_from_p2sh) {
299
- result.P2SH_segwit .push_back (coin);
300
- break ;
301
- }
302
- result.bech32 .push_back (coin);
303
- break ;
304
- case TxoutType::SCRIPTHASH:
305
- case TxoutType::PUBKEYHASH:
306
- result.legacy .push_back (coin);
307
- break ;
308
- default :
309
- result.other .push_back (coin);
310
- };
282
+
283
+ // When parsing a scriptPubKey, Solver returns the parsed pubkeys or hashes (depending on the script)
284
+ // We don't need those here, so we are leaving them in return_values_unused
285
+ std::vector<std::vector<uint8_t >> return_values_unused;
286
+ TxoutType type;
287
+ type = Solver (script, return_values_unused);
288
+ result.Add (GetOutputType (type, is_from_p2sh), coin);
311
289
312
290
// Cache total amount as we go
313
291
result.total_amount += output.nValue ;
@@ -498,17 +476,10 @@ std::optional<SelectionResult> AttemptSelection(const CWallet& wallet, const CAm
498
476
{
499
477
// Run coin selection on each OutputType and compute the Waste Metric
500
478
std::vector<SelectionResult> results;
501
- if (auto result{ChooseSelectionResult (wallet, nTargetValue, eligibility_filter, available_coins.legacy , coin_selection_params)}) {
502
- results.push_back (*result);
503
- }
504
- if (auto result{ChooseSelectionResult (wallet, nTargetValue, eligibility_filter, available_coins.P2SH_segwit , coin_selection_params)}) {
505
- results.push_back (*result);
506
- }
507
- if (auto result{ChooseSelectionResult (wallet, nTargetValue, eligibility_filter, available_coins.bech32 , coin_selection_params)}) {
508
- results.push_back (*result);
509
- }
510
- if (auto result{ChooseSelectionResult (wallet, nTargetValue, eligibility_filter, available_coins.bech32m , coin_selection_params)}) {
511
- results.push_back (*result);
479
+ for (const auto & it : available_coins.coins ) {
480
+ if (auto result{ChooseSelectionResult (wallet, nTargetValue, eligibility_filter, it.second , coin_selection_params)}) {
481
+ results.push_back (*result);
482
+ }
512
483
}
513
484
514
485
// If we can't fund the transaction from any individual OutputType, run coin selection
@@ -633,11 +604,7 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a
633
604
634
605
// remove preset inputs from coins so that Coin Selection doesn't pick them.
635
606
if (coin_control.HasSelected ()) {
636
- available_coins.legacy .erase (remove_if (available_coins.legacy .begin (), available_coins.legacy .end (), [&](const COutput& c) { return preset_coins.count (c.outpoint ); }), available_coins.legacy .end ());
637
- available_coins.P2SH_segwit .erase (remove_if (available_coins.P2SH_segwit .begin (), available_coins.P2SH_segwit .end (), [&](const COutput& c) { return preset_coins.count (c.outpoint ); }), available_coins.P2SH_segwit .end ());
638
- available_coins.bech32 .erase (remove_if (available_coins.bech32 .begin (), available_coins.bech32 .end (), [&](const COutput& c) { return preset_coins.count (c.outpoint ); }), available_coins.bech32 .end ());
639
- available_coins.bech32m .erase (remove_if (available_coins.bech32m .begin (), available_coins.bech32m .end (), [&](const COutput& c) { return preset_coins.count (c.outpoint ); }), available_coins.bech32m .end ());
640
- available_coins.other .erase (remove_if (available_coins.other .begin (), available_coins.other .end (), [&](const COutput& c) { return preset_coins.count (c.outpoint ); }), available_coins.other .end ());
607
+ available_coins.Erase (preset_coins);
641
608
}
642
609
643
610
unsigned int limit_ancestor_count = 0 ;
@@ -653,11 +620,7 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, CoinsResult& a
653
620
// Cases where we have 101+ outputs all pointing to the same destination may result in
654
621
// privacy leaks as they will potentially be deterministically sorted. We solve that by
655
622
// explicitly shuffling the outputs before processing
656
- Shuffle (available_coins.legacy .begin (), available_coins.legacy .end (), coin_selection_params.rng_fast );
657
- Shuffle (available_coins.P2SH_segwit .begin (), available_coins.P2SH_segwit .end (), coin_selection_params.rng_fast );
658
- Shuffle (available_coins.bech32 .begin (), available_coins.bech32 .end (), coin_selection_params.rng_fast );
659
- Shuffle (available_coins.bech32m .begin (), available_coins.bech32m .end (), coin_selection_params.rng_fast );
660
- Shuffle (available_coins.other .begin (), available_coins.other .end (), coin_selection_params.rng_fast );
623
+ available_coins.Shuffle (coin_selection_params.rng_fast );
661
624
}
662
625
663
626
// Coin Selection attempts to select inputs from a pool of eligible UTXOs to fund the
0 commit comments