Skip to content

Commit 7c5de86

Browse files
sipacodablock
authored andcommitted
Merge bitcoin#9404: Smarter coordination of change and fee in CreateTransaction.
20449ef Don't overpay fee if we have selected new coins that result in a smaller transaction. (Alex Morcos) 42f5ce4 Try to reduce change output to make needed fee in CreateTransaction (Alex Morcos)
1 parent 17e51db commit 7c5de86

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

src/wallet/wallet.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3669,8 +3669,37 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
36693669
return false;
36703670
}
36713671

3672-
if (nFeeRet >= nFeeNeeded)
3672+
if (nFeeRet >= nFeeNeeded) {
3673+
// Reduce fee to only the needed amount if we have change
3674+
// output to increase. This prevents potential overpayment
3675+
// in fees if the coins selected to meet nFeeNeeded result
3676+
// in a transaction that requires less fee than the prior
3677+
// iteration.
3678+
// TODO: The case where nSubtractFeeFromAmount > 0 remains
3679+
// to be addressed because it requires returning the fee to
3680+
// the payees and not the change output.
3681+
// TODO: The case where there is no change output remains
3682+
// to be addressed so we avoid creating too small an output.
3683+
if (nFeeRet > nFeeNeeded && nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
3684+
CAmount extraFeePaid = nFeeRet - nFeeNeeded;
3685+
vector<CTxOut>::iterator change_position = txNew.vout.begin()+nChangePosInOut;
3686+
change_position->nValue += extraFeePaid;
3687+
nFeeRet -= extraFeePaid;
3688+
}
36733689
break; // Done, enough fee included.
3690+
}
3691+
3692+
// Try to reduce change to include necessary fee
3693+
if (nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
3694+
CAmount additionalFeeNeeded = nFeeNeeded - nFeeRet;
3695+
vector<CTxOut>::iterator change_position = txNew.vout.begin()+nChangePosInOut;
3696+
// Only reduce change if remaining amount is still a large enough output.
3697+
if (change_position->nValue >= MIN_FINAL_CHANGE + additionalFeeNeeded) {
3698+
change_position->nValue -= additionalFeeNeeded;
3699+
nFeeRet += additionalFeeNeeded;
3700+
break; // Done, able to increase fee from change
3701+
}
3702+
}
36743703

36753704
// Include more fee and try again.
36763705
nFeeRet = nFeeNeeded;

src/wallet/wallet.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@ static const CAmount DEFAULT_TRANSACTION_FEE = 0;
5252
static const CAmount DEFAULT_FALLBACK_FEE = 1000;
5353
//! -mintxfee default
5454
static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000;
55-
//! minimum change amount
55+
//! target minimum change amount
5656
static const CAmount MIN_CHANGE = CENT;
57+
//! final minimum change amount after paying for fees
58+
static const CAmount MIN_FINAL_CHANGE = MIN_CHANGE/2;
5759
//! Default for -spendzeroconfchange
5860
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true;
5961
//! Default for -sendfreetransactions

0 commit comments

Comments
 (0)