Skip to content

Commit 12e3112

Browse files
committed
Merge #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)
2 parents 8c87f17 + 20449ef commit 12e3112

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
@@ -2534,8 +2534,37 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
25342534
return false;
25352535
}
25362536

2537-
if (nFeeRet >= nFeeNeeded)
2537+
if (nFeeRet >= nFeeNeeded) {
2538+
// Reduce fee to only the needed amount if we have change
2539+
// output to increase. This prevents potential overpayment
2540+
// in fees if the coins selected to meet nFeeNeeded result
2541+
// in a transaction that requires less fee than the prior
2542+
// iteration.
2543+
// TODO: The case where nSubtractFeeFromAmount > 0 remains
2544+
// to be addressed because it requires returning the fee to
2545+
// the payees and not the change output.
2546+
// TODO: The case where there is no change output remains
2547+
// to be addressed so we avoid creating too small an output.
2548+
if (nFeeRet > nFeeNeeded && nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
2549+
CAmount extraFeePaid = nFeeRet - nFeeNeeded;
2550+
vector<CTxOut>::iterator change_position = txNew.vout.begin()+nChangePosInOut;
2551+
change_position->nValue += extraFeePaid;
2552+
nFeeRet -= extraFeePaid;
2553+
}
25382554
break; // Done, enough fee included.
2555+
}
2556+
2557+
// Try to reduce change to include necessary fee
2558+
if (nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
2559+
CAmount additionalFeeNeeded = nFeeNeeded - nFeeRet;
2560+
vector<CTxOut>::iterator change_position = txNew.vout.begin()+nChangePosInOut;
2561+
// Only reduce change if remaining amount is still a large enough output.
2562+
if (change_position->nValue >= MIN_FINAL_CHANGE + additionalFeeNeeded) {
2563+
change_position->nValue -= additionalFeeNeeded;
2564+
nFeeRet += additionalFeeNeeded;
2565+
break; // Done, able to increase fee from change
2566+
}
2567+
}
25392568

25402569
// Include more fee and try again.
25412570
nFeeRet = nFeeNeeded;

src/wallet/wallet.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ static const CAmount DEFAULT_TRANSACTION_FEE = 0;
4848
static const CAmount DEFAULT_FALLBACK_FEE = 20000;
4949
//! -mintxfee default
5050
static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000;
51-
//! minimum change amount
51+
//! target minimum change amount
5252
static const CAmount MIN_CHANGE = CENT;
53+
//! final minimum change amount after paying for fees
54+
static const CAmount MIN_FINAL_CHANGE = MIN_CHANGE/2;
5355
//! Default for -spendzeroconfchange
5456
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true;
5557
//! Default for -sendfreetransactions

0 commit comments

Comments
 (0)