@@ -165,17 +165,12 @@ CoinsResult AvailableCoins(const CWallet& wallet,
165165 break ;
166166 }
167167 } // no default case, so the compiler can warn about missing cases
168- if (!found) continue ;
169-
170- // Only consider selected coins if add_inputs is false
171- if (coinControl && !coinControl->m_add_inputs && !coinControl->IsSelected (outpoint)) {
172- continue ;
173- }
168+ if (!found) continue ;
174169
175170 if (output.nValue < nMinimumAmount || output.nValue > nMaximumAmount)
176171 continue ;
177172
178- if (coinControl && coinControl->HasSelected () && !coinControl->fAllowOtherInputs && !coinControl->IsSelected (outpoint))
173+ if (coinControl && coinControl->HasSelected () && !coinControl->m_allow_other_inputs && !coinControl->IsSelected (outpoint))
179174 continue ;
180175
181176 if (wallet.IsLockedCoin (outpoint) && nCoinType != CoinType::ONLY_MASTERNODE_COLLATERAL)
@@ -454,41 +449,6 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
454449
455450 OutputGroup preset_inputs (coin_selection_params);
456451
457- // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
458- if (coin_control.HasSelected () && !coin_control.fAllowOtherInputs )
459- {
460- for (const COutput& out : vCoins) {
461- if (!out.spendable ) continue ;
462- /* Set ancestors and descendants to 0 as these don't matter for preset inputs as no actual selection is being done.
463- * positive_only is set to false because we want to include all preset inputs, even if they are dust.
464- */
465- preset_inputs.Insert (out, /* ancestors=*/ 0 , /* descendants=*/ 0 , /* positive_only=*/ false );
466- }
467- SelectionResult result (nTargetValue, SelectionAlgorithm::MANUAL);
468- bool all_inputs{coin_control.fRequireAllInputs };
469- if (!all_inputs) {
470- // Calculate the smallest set of inputs required to meet nTargetValue
471- bool success{false };
472- OutputGroup preset_candidates (coin_selection_params);
473- for (const auto & output : preset_inputs.m_outputs ) {
474- preset_candidates.Insert (output, /* ancestors=*/ 0 , /* descendants=*/ 0 , /* positive_only=*/ false );
475- if (preset_candidates.GetSelectionAmount () >= nTargetValue) {
476- result.AddInput (preset_candidates);
477- success = true ;
478- break ;
479- }
480- }
481- // Couldn't meet target, add all inputs
482- if (!success) all_inputs = true ;
483- }
484- if (all_inputs) {
485- result.AddInput (preset_inputs);
486- }
487- if (result.GetSelectedValue () < nTargetValue) return std::nullopt ;
488- result.ComputeAndSetWaste (coin_selection_params.m_cost_of_change );
489- return result;
490- }
491-
492452 // calculate value from preset inputs and store them
493453 std::set<COutPoint> preset_coins;
494454
@@ -497,15 +457,14 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
497457 for (const COutPoint& outpoint : vPresetInputs) {
498458 int input_bytes = -1 ;
499459 CTxOut txout;
500- std::map<uint256, CWalletTx>::const_iterator it = wallet.mapWallet .find (outpoint.hash );
501- if (it != wallet.mapWallet .end ()) {
502- const CWalletTx& wtx = it->second ;
460+ auto ptr_wtx = wallet.GetWalletTx (outpoint.hash );
461+ if (ptr_wtx) {
503462 // Clearly invalid input, fail
504- if (wtx. tx ->vout .size () <= outpoint.n ) {
463+ if (ptr_wtx-> tx ->vout .size () <= outpoint.n ) {
505464 return std::nullopt ;
506465 }
507- input_bytes = GetTxSpendSize (wallet, wtx , outpoint.n , false );
508- txout = wtx. tx ->vout .at (outpoint.n );
466+ input_bytes = GetTxSpendSize (wallet, *ptr_wtx , outpoint.n , false );
467+ txout = ptr_wtx-> tx ->vout .at (outpoint.n );
509468 } else {
510469 // The input is external. We did not find the tx in mapWallet.
511470 if (!coin_control.GetExternalOutput (outpoint, txout)) {
@@ -536,6 +495,36 @@ std::optional<SelectionResult> SelectCoins(const CWallet& wallet, const std::vec
536495 preset_inputs.Insert (output, /* ancestors=*/ 0 , /* descendants=*/ 0 , /* positive_only=*/ false );
537496 }
538497
498+ // coin control -> return all selected outputs (we want all selected to go into the transaction for sure)
499+ if (coin_control.HasSelected () && !coin_control.m_allow_other_inputs ) {
500+ SelectionResult result (nTargetValue, SelectionAlgorithm::MANUAL);
501+ bool all_inputs{coin_control.fRequireAllInputs };
502+ if (!all_inputs) {
503+ // Calculate the smallest set of inputs required to meet nTargetValue from vCoins
504+ bool success{false };
505+ OutputGroup preset_candidates (coin_selection_params);
506+ for (const COutput& out : vCoins) {
507+ if (!out.spendable ) continue ;
508+ if (preset_coins.count (out.outpoint )) {
509+ preset_candidates.Insert (out, /* ancestors=*/ 0 , /* descendants=*/ 0 , /* positive_only=*/ false );
510+ }
511+ if (preset_candidates.GetSelectionAmount () >= nTargetValue) {
512+ result.AddInput (preset_candidates);
513+ success = true ;
514+ break ;
515+ }
516+ }
517+ // Couldn't meet target, add all inputs
518+ if (!success) all_inputs = true ;
519+ }
520+ if (all_inputs) {
521+ result.AddInput (preset_inputs);
522+ }
523+ if (result.GetSelectedValue () < nTargetValue) return std::nullopt ;
524+ result.ComputeAndSetWaste (coin_selection_params.m_cost_of_change );
525+ return result;
526+ }
527+
539528 // remove preset inputs from vCoins so that Coin Selection doesn't pick them.
540529 for (std::vector<COutput>::iterator it = vCoins.begin (); it != vCoins.end () && coin_control.HasSelected ();)
541530 {
@@ -1102,8 +1091,6 @@ bool FundTransaction(CWallet& wallet, CMutableTransaction& tx, CAmount& nFeeRet,
11021091 vecSend.push_back (recipient);
11031092 }
11041093
1105- coinControl.fAllowOtherInputs = true ;
1106-
11071094 // Acquire the locks to prevent races to the new locked unspents between the
11081095 // CreateTransaction call and LockCoin calls (when lockUnspents is true).
11091096 LOCK (wallet.cs_wallet );
0 commit comments