@@ -2804,7 +2804,6 @@ bool CWallet::CreateTransactionInternal(
28042804 CAmount nValue = 0 ;
28052805 const OutputType change_type = TransactionChangeType (coin_control.m_change_type ? *coin_control.m_change_type : m_default_change_type, vecSend);
28062806 ReserveDestination reservedest (this , change_type);
2807- int nChangePosRequest = nChangePosInOut;
28082807 unsigned int nSubtractFeeFromAmount = 0 ;
28092808 for (const auto & recipient : vecSend)
28102809 {
@@ -2909,151 +2908,139 @@ bool CWallet::CreateTransactionInternal(
29092908 coin_selection_params.m_change_fee = coin_selection_params.m_effective_feerate .GetFee (coin_selection_params.change_output_size );
29102909 coin_selection_params.m_cost_of_change = coin_selection_params.m_discard_feerate .GetFee (coin_selection_params.change_spend_size ) + coin_selection_params.m_change_fee ;
29112910
2912- nFeeRet = 0 ;
2913- CAmount nValueIn = 0 ;
2914-
29152911 coin_selection_params.m_subtract_fee_outputs = nSubtractFeeFromAmount != 0 ; // If we are doing subtract fee from recipient, don't use effective values
2916- // Start with no fee and loop until there is enough fee
2917- while (true )
2912+
2913+ // vouts to the payees
2914+ if (!coin_selection_params.m_subtract_fee_outputs ) {
2915+ coin_selection_params.tx_noinputs_size = 11 ; // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 output count, 1 witness overhead (dummy, flag, stack size)
2916+ }
2917+ for (const auto & recipient : vecSend)
29182918 {
2919- nChangePosInOut = nChangePosRequest;
2920- txNew.vin .clear ();
2921- txNew.vout .clear ();
2919+ CTxOut txout (recipient.nAmount , recipient.scriptPubKey );
29222920
2923- // vouts to the payees
2921+ // Include the fee cost for outputs.
29242922 if (!coin_selection_params.m_subtract_fee_outputs ) {
2925- coin_selection_params.tx_noinputs_size = 11 ; // Static vsize overhead + outputs vsize. 4 nVersion, 4 nLocktime, 1 input count, 1 output count, 1 witness overhead (dummy, flag, stack size)
2923+ coin_selection_params.tx_noinputs_size += :: GetSerializeSize (txout, PROTOCOL_VERSION);
29262924 }
2927- for (const auto & recipient : vecSend)
2925+
2926+ if (IsDust (txout, chain ().relayDustFee ()))
29282927 {
2929- CTxOut txout (recipient.nAmount , recipient.scriptPubKey );
2928+ error = _ (" Transaction amount too small" );
2929+ return false ;
2930+ }
2931+ txNew.vout .push_back (txout);
2932+ }
29302933
2931- // Include the fee cost for outputs.
2932- if (!coin_selection_params.m_subtract_fee_outputs ) {
2933- coin_selection_params.tx_noinputs_size += ::GetSerializeSize (txout, PROTOCOL_VERSION);
2934- }
2934+ // Include the fees for things that aren't inputs, excluding the change output
2935+ const CAmount not_input_fees = coin_selection_params.m_effective_feerate .GetFee (coin_selection_params.tx_noinputs_size );
2936+ CAmount nValueToSelect = nValue + not_input_fees;
29352937
2936- if (IsDust (txout, chain ().relayDustFee ()))
2937- {
2938- error = _ (" Transaction amount too small" );
2939- return false ;
2940- }
2941- txNew.vout .push_back (txout);
2942- }
2938+ // Choose coins to use
2939+ CAmount inputs_sum = 0 ;
2940+ setCoins.clear ();
2941+ if (!SelectCoins (vAvailableCoins, /* nTargetValue */ nValueToSelect, setCoins, inputs_sum, coin_control, coin_selection_params))
2942+ {
2943+ error = _ (" Insufficient funds" );
2944+ return false ;
2945+ }
29432946
2944- // Include the fees for things that aren't inputs, excluding the change output
2945- const CAmount not_input_fees = coin_selection_params.m_effective_feerate .GetFee (coin_selection_params.tx_noinputs_size );
2946- CAmount nValueToSelect = nValue + not_input_fees;
2947+ // Always make a change output
2948+ // We will reduce the fee from this change output later, and remove the output if it is too small.
2949+ const CAmount change_and_fee = inputs_sum - nValue;
2950+ assert (change_and_fee >= 0 );
2951+ CTxOut newTxOut (change_and_fee, scriptChange);
29472952
2948- // Choose coins to use
2949- nValueIn = 0 ;
2950- setCoins.clear ();
2951- if (!SelectCoins (vAvailableCoins, /* nTargetValue */ nValueToSelect, setCoins, nValueIn, coin_control, coin_selection_params))
2952- {
2953- error = _ (" Insufficient funds" );
2954- return false ;
2955- }
2953+ if (nChangePosInOut == -1 )
2954+ {
2955+ // Insert change txn at random position:
2956+ nChangePosInOut = GetRandInt (txNew.vout .size ()+1 );
2957+ }
2958+ else if ((unsigned int )nChangePosInOut > txNew.vout .size ())
2959+ {
2960+ error = _ (" Change index out of range" );
2961+ return false ;
2962+ }
29562963
2957- // Always make a change output
2958- // We will reduce the fee from this change output later, and remove the output if it is too small.
2959- const CAmount change_and_fee = nValueIn - nValue;
2960- assert (change_and_fee >= 0 );
2961- CTxOut newTxOut (change_and_fee, scriptChange);
2964+ assert (nChangePosInOut != -1 );
2965+ auto change_position = txNew.vout .insert (txNew.vout .begin () + nChangePosInOut, newTxOut);
29622966
2963- if (nChangePosInOut == -1 )
2964- {
2965- // Insert change txn at random position:
2966- nChangePosInOut = GetRandInt (txNew.vout .size ()+1 );
2967- }
2968- else if ((unsigned int )nChangePosInOut > txNew.vout .size ())
2969- {
2970- error = _ (" Change index out of range" );
2971- return false ;
2972- }
2967+ // Dummy fill vin for maximum size estimation
2968+ //
2969+ for (const auto & coin : setCoins) {
2970+ txNew.vin .push_back (CTxIn (coin.outpoint ,CScript ()));
2971+ }
29732972
2974- assert (nChangePosInOut != -1 );
2975- auto change_position = txNew.vout .insert (txNew.vout .begin () + nChangePosInOut, newTxOut);
2973+ // Calculate the transaction fee
2974+ tx_sizes = CalculateMaximumSignedTxSize (CTransaction (txNew), this , coin_control.fAllowWatchOnly );
2975+ nBytes = tx_sizes.first ;
2976+ if (nBytes < 0 ) {
2977+ error = _ (" Signing transaction failed" );
2978+ return false ;
2979+ }
2980+ nFeeRet = coin_selection_params.m_effective_feerate .GetFee (nBytes);
29762981
2977- // Dummy fill vin for maximum size estimation
2978- //
2979- for ( const auto & coin : setCoins ) {
2980- txNew. vin . push_back ( CTxIn (coin. outpoint , CScript ())) ;
2981- }
2982+ // Subtract fee from the change output if not subtrating it from recipient outputs
2983+ CAmount fee_needed = nFeeRet;
2984+ if (nSubtractFeeFromAmount == 0 ) {
2985+ change_position-> nValue -= fee_needed ;
2986+ }
29822987
2983- // Calculate the transaction fee
2988+ // We want to drop the change to fees if:
2989+ // 1. The change output would be dust
2990+ // 2. The change is within the (almost) exact match window, i.e. it is less than or equal to the cost of the change output (cost_of_change)
2991+ CAmount change_amount = change_position->nValue ;
2992+ if (IsDust (*change_position, coin_selection_params.m_discard_feerate ) || change_amount <= coin_selection_params.m_cost_of_change )
2993+ {
2994+ nChangePosInOut = -1 ;
2995+ change_amount = 0 ;
2996+ txNew.vout .erase (change_position);
2997+
2998+ // Because we have dropped this change, the tx size and required fee will be different, so let's recalculate those
29842999 tx_sizes = CalculateMaximumSignedTxSize (CTransaction (txNew), this , coin_control.fAllowWatchOnly );
29853000 nBytes = tx_sizes.first ;
2986- if (nBytes < 0 ) {
2987- error = _ (" Signing transaction failed" );
2988- return false ;
2989- }
2990- nFeeRet = coin_selection_params.m_effective_feerate .GetFee (nBytes);
3001+ fee_needed = coin_selection_params.m_effective_feerate .GetFee (nBytes);
3002+ }
29913003
2992- // Subtract fee from the change output if not subtrating it from recipient outputs
2993- CAmount fee_needed = nFeeRet;
2994- if (nSubtractFeeFromAmount == 0 ) {
2995- change_position->nValue -= fee_needed;
2996- }
3004+ // Update nFeeRet in case fee_needed changed due to dropping the change output
3005+ if (fee_needed <= change_and_fee - change_amount) {
3006+ nFeeRet = change_and_fee - change_amount;
3007+ }
29973008
2998- // We want to drop the change to fees if:
2999- // 1. The change output would be dust
3000- // 2. The change is within the (almost) exact match window, i.e. it is less than or equal to the cost of the change output (cost_of_change)
3001- CAmount change_amount = change_position->nValue ;
3002- if (IsDust (*change_position, coin_selection_params.m_discard_feerate ) || change_amount <= coin_selection_params.m_cost_of_change )
3009+ // Reduce output values for subtractFeeFromAmount
3010+ if (nSubtractFeeFromAmount != 0 ) {
3011+ CAmount to_reduce = fee_needed + change_amount - change_and_fee;
3012+ int i = 0 ;
3013+ bool fFirst = true ;
3014+ for (const auto & recipient : vecSend)
30033015 {
3004- nChangePosInOut = -1 ;
3005- change_amount = 0 ;
3006- txNew.vout .erase (change_position);
3007-
3008- // Because we have dropped this change, the tx size and required fee will be different, so let's recalculate those
3009- tx_sizes = CalculateMaximumSignedTxSize (CTransaction (txNew), this , coin_control.fAllowWatchOnly );
3010- nBytes = tx_sizes.first ;
3011- fee_needed = coin_selection_params.m_effective_feerate .GetFee (nBytes);
3012- }
3013-
3014- // If the fee is covered, there's no need to loop or subtract from recipients
3015- if (fee_needed <= change_and_fee - change_amount) {
3016- nFeeRet = change_and_fee - change_amount;
3017- break ;
3018- }
3016+ if (i == nChangePosInOut) {
3017+ ++i;
3018+ }
3019+ CTxOut& txout = txNew.vout [i];
30193020
3020- // Reduce output values for subtractFeeFromAmount
3021- if (nSubtractFeeFromAmount != 0 ) {
3022- CAmount to_reduce = fee_needed + change_amount - change_and_fee;
3023- int i = 0 ;
3024- bool fFirst = true ;
3025- for (const auto & recipient : vecSend)
3021+ if (recipient.fSubtractFeeFromAmount )
30263022 {
3027- if (i == nChangePosInOut) {
3028- ++i;
3029- }
3030- CTxOut& txout = txNew.vout [i];
3023+ txout.nValue -= to_reduce / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient
30313024
3032- if (recipient. fSubtractFeeFromAmount )
3025+ if (fFirst ) // first receiver pays the remainder not divisible by output count
30333026 {
3034- txout.nValue -= to_reduce / nSubtractFeeFromAmount; // Subtract fee equally from each selected recipient
3035-
3036- if (fFirst ) // first receiver pays the remainder not divisible by output count
3037- {
3038- fFirst = false ;
3039- txout.nValue -= to_reduce % nSubtractFeeFromAmount;
3040- }
3027+ fFirst = false ;
3028+ txout.nValue -= to_reduce % nSubtractFeeFromAmount;
3029+ }
30413030
3042- // Error if this output is reduced to be below dust
3043- if (IsDust (txout, chain ().relayDustFee ())) {
3044- if (txout.nValue < 0 ) {
3045- error = _ (" The transaction amount is too small to pay the fee" );
3046- } else {
3047- error = _ (" The transaction amount is too small to send after the fee has been deducted" );
3048- }
3049- return false ;
3031+ // Error if this output is reduced to be below dust
3032+ if (IsDust (txout, chain ().relayDustFee ())) {
3033+ if (txout.nValue < 0 ) {
3034+ error = _ (" The transaction amount is too small to pay the fee" );
3035+ } else {
3036+ error = _ (" The transaction amount is too small to send after the fee has been deducted" );
30503037 }
3038+ return false ;
30513039 }
3052- ++i;
30533040 }
3054- nFeeRet = fee_needed;
3055- break ; // The fee has been deducted from the recipients, nothing left to do here
3041+ ++i;
30563042 }
3043+ nFeeRet = fee_needed;
30573044 }
30583045
30593046 // Give up if change keypool ran out and change is required
0 commit comments