@@ -2804,7 +2804,6 @@ bool CWallet::CreateTransactionInternal(
2804
2804
CAmount nValue = 0 ;
2805
2805
const OutputType change_type = TransactionChangeType (coin_control.m_change_type ? *coin_control.m_change_type : m_default_change_type, vecSend);
2806
2806
ReserveDestination reservedest (this , change_type);
2807
- int nChangePosRequest = nChangePosInOut;
2808
2807
unsigned int nSubtractFeeFromAmount = 0 ;
2809
2808
for (const auto & recipient : vecSend)
2810
2809
{
@@ -2909,151 +2908,139 @@ bool CWallet::CreateTransactionInternal(
2909
2908
coin_selection_params.m_change_fee = coin_selection_params.m_effective_feerate .GetFee (coin_selection_params.change_output_size );
2910
2909
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 ;
2911
2910
2912
- nFeeRet = 0 ;
2913
- CAmount nValueIn = 0 ;
2914
-
2915
2911
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)
2918
2918
{
2919
- nChangePosInOut = nChangePosRequest;
2920
- txNew.vin .clear ();
2921
- txNew.vout .clear ();
2919
+ CTxOut txout (recipient.nAmount , recipient.scriptPubKey );
2922
2920
2923
- // vouts to the payees
2921
+ // Include the fee cost for outputs.
2924
2922
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);
2926
2924
}
2927
- for (const auto & recipient : vecSend)
2925
+
2926
+ if (IsDust (txout, chain ().relayDustFee ()))
2928
2927
{
2929
- CTxOut txout (recipient.nAmount , recipient.scriptPubKey );
2928
+ error = _ (" Transaction amount too small" );
2929
+ return false ;
2930
+ }
2931
+ txNew.vout .push_back (txout);
2932
+ }
2930
2933
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;
2935
2937
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
+ }
2943
2946
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);
2947
2952
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
+ }
2956
2963
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);
2962
2966
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
+ }
2973
2972
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);
2976
2981
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
+ }
2982
2987
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
2984
2999
tx_sizes = CalculateMaximumSignedTxSize (CTransaction (txNew), this , coin_control.fAllowWatchOnly );
2985
3000
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
+ }
2991
3003
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
+ }
2997
3008
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)
3003
3015
{
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];
3019
3020
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 )
3026
3022
{
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
3031
3024
3032
- if (recipient. fSubtractFeeFromAmount )
3025
+ if (fFirst ) // first receiver pays the remainder not divisible by output count
3033
3026
{
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
+ }
3041
3030
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" );
3050
3037
}
3038
+ return false ;
3051
3039
}
3052
- ++i;
3053
3040
}
3054
- nFeeRet = fee_needed;
3055
- break ; // The fee has been deducted from the recipients, nothing left to do here
3041
+ ++i;
3056
3042
}
3043
+ nFeeRet = fee_needed;
3057
3044
}
3058
3045
3059
3046
// Give up if change keypool ran out and change is required
0 commit comments