@@ -79,6 +79,32 @@ 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
83
+ {
84
+ return bech32m.size () + bech32.size () + P2SH_segwit.size () + legacy.size () + other.size ();
85
+ }
86
+
87
+ std::vector<COutput> CoinsResult::all () const
88
+ {
89
+ 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 ());
96
+ return all;
97
+ }
98
+
99
+ void CoinsResult::clear ()
100
+ {
101
+ bech32m.clear ();
102
+ bech32.clear ();
103
+ P2SH_segwit.clear ();
104
+ legacy.clear ();
105
+ other.clear ();
106
+ }
107
+
82
108
CoinsResult AvailableCoins (const CWallet& wallet,
83
109
const CCoinControl* coinControl,
84
110
std::optional<CFeeRate> feerate,
@@ -193,10 +219,55 @@ CoinsResult AvailableCoins(const CWallet& wallet,
193
219
// Filter by spendable outputs only
194
220
if (!spendable && only_spendable) continue ;
195
221
222
+ // When parsing a scriptPubKey, Solver returns the parsed pubkeys or hashes (depending on the script)
223
+ // We don't need those here, so we are leaving them in return_values_unused
224
+ std::vector<std::vector<uint8_t >> return_values_unused;
225
+ TxoutType type;
226
+ bool is_from_p2sh{false };
227
+
228
+ // If the Output is P2SH and spendable, we want to know if it is
229
+ // a P2SH (legacy) or one of P2SH-P2WPKH, P2SH-P2WSH (P2SH-Segwit). We can determine
230
+ // this from the redeemScript. If the Output is not spendable, it will be classified
231
+ // as a P2SH (legacy), since we have no way of knowing otherwise without the redeemScript
232
+ if (output.scriptPubKey .IsPayToScriptHash () && solvable) {
233
+ CScript redeemScript;
234
+ CTxDestination destination;
235
+ if (!ExtractDestination (output.scriptPubKey , destination))
236
+ continue ;
237
+ const CScriptID& hash = CScriptID (std::get<ScriptHash>(destination));
238
+ if (!provider->GetCScript (hash, redeemScript))
239
+ continue ;
240
+ type = Solver (redeemScript, return_values_unused);
241
+ is_from_p2sh = true ;
242
+ } else {
243
+ type = Solver (output.scriptPubKey , return_values_unused);
244
+ }
245
+
196
246
int input_bytes = CalculateMaximumSignedInputSize (output, COutPoint (), provider.get (), coinControl);
197
- result.coins .emplace_back (outpoint, output, nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime (), tx_from_me, feerate);
247
+ COutput coin (outpoint, output, nDepth, input_bytes, spendable, solvable, safeTx, wtx.GetTxTime (), tx_from_me, feerate);
248
+ switch (type) {
249
+ case TxoutType::WITNESS_UNKNOWN:
250
+ case TxoutType::WITNESS_V1_TAPROOT:
251
+ result.bech32m .push_back (coin);
252
+ break ;
253
+ case TxoutType::WITNESS_V0_KEYHASH:
254
+ case TxoutType::WITNESS_V0_SCRIPTHASH:
255
+ if (is_from_p2sh) {
256
+ result.P2SH_segwit .push_back (coin);
257
+ break ;
258
+ }
259
+ result.bech32 .push_back (coin);
260
+ break ;
261
+ case TxoutType::SCRIPTHASH:
262
+ case TxoutType::PUBKEYHASH:
263
+ result.legacy .push_back (coin);
264
+ break ;
265
+ default :
266
+ result.other .push_back (coin);
267
+ };
268
+
269
+ // Cache total amount as we go
198
270
result.total_amount += output.nValue ;
199
-
200
271
// Checks the sum amount of all UTXO's.
201
272
if (nMinimumSumAmount != MAX_MONEY) {
202
273
if (result.total_amount >= nMinimumSumAmount) {
@@ -205,7 +276,7 @@ CoinsResult AvailableCoins(const CWallet& wallet,
205
276
}
206
277
207
278
// Checks the maximum number of UTXO's.
208
- if (nMaximumCount > 0 && result.coins . size () >= nMaximumCount) {
279
+ if (nMaximumCount > 0 && result.size () >= nMaximumCount) {
209
280
return result;
210
281
}
211
282
}
@@ -261,7 +332,7 @@ std::map<CTxDestination, std::vector<COutput>> ListCoins(const CWallet& wallet)
261
332
262
333
std::map<CTxDestination, std::vector<COutput>> result;
263
334
264
- for (const COutput& coin : AvailableCoinsListUnspent (wallet).coins ) {
335
+ for (const COutput& coin : AvailableCoinsListUnspent (wallet).all () ) {
265
336
CTxDestination address;
266
337
if ((coin.spendable || (wallet.IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS) && coin.solvable )) &&
267
338
ExtractDestination (FindNonChangeParentOutput (wallet, coin.outpoint ).scriptPubKey , address)) {
@@ -787,7 +858,7 @@ static BResult<CreatedTransactionResult> CreateTransactionInternal(
787
858
0 ); /* nMaximumCount*/
788
859
789
860
// Choose coins to use
790
- std::optional<SelectionResult> result = SelectCoins (wallet, res_available_coins.coins , /* nTargetValue=*/ selection_target, coin_control, coin_selection_params);
861
+ std::optional<SelectionResult> result = SelectCoins (wallet, res_available_coins.all () , /* nTargetValue=*/ selection_target, coin_control, coin_selection_params);
791
862
if (!result) {
792
863
return _ (" Insufficient funds" );
793
864
}
0 commit comments