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)
pull/308/head
Pieter Wuille 8 years ago
commit 12e3112794
No known key found for this signature in database
GPG Key ID: DBA1A67379A1A931

@ -2534,8 +2534,37 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
return false; return false;
} }
if (nFeeRet >= nFeeNeeded) if (nFeeRet >= nFeeNeeded) {
// Reduce fee to only the needed amount if we have change
// output to increase. This prevents potential overpayment
// in fees if the coins selected to meet nFeeNeeded result
// in a transaction that requires less fee than the prior
// iteration.
// TODO: The case where nSubtractFeeFromAmount > 0 remains
// to be addressed because it requires returning the fee to
// the payees and not the change output.
// TODO: The case where there is no change output remains
// to be addressed so we avoid creating too small an output.
if (nFeeRet > nFeeNeeded && nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
CAmount extraFeePaid = nFeeRet - nFeeNeeded;
vector<CTxOut>::iterator change_position = txNew.vout.begin()+nChangePosInOut;
change_position->nValue += extraFeePaid;
nFeeRet -= extraFeePaid;
}
break; // Done, enough fee included. break; // Done, enough fee included.
}
// Try to reduce change to include necessary fee
if (nChangePosInOut != -1 && nSubtractFeeFromAmount == 0) {
CAmount additionalFeeNeeded = nFeeNeeded - nFeeRet;
vector<CTxOut>::iterator change_position = txNew.vout.begin()+nChangePosInOut;
// Only reduce change if remaining amount is still a large enough output.
if (change_position->nValue >= MIN_FINAL_CHANGE + additionalFeeNeeded) {
change_position->nValue -= additionalFeeNeeded;
nFeeRet += additionalFeeNeeded;
break; // Done, able to increase fee from change
}
}
// Include more fee and try again. // Include more fee and try again.
nFeeRet = nFeeNeeded; nFeeRet = nFeeNeeded;

@ -48,8 +48,10 @@ static const CAmount DEFAULT_TRANSACTION_FEE = 0;
static const CAmount DEFAULT_FALLBACK_FEE = 20000; static const CAmount DEFAULT_FALLBACK_FEE = 20000;
//! -mintxfee default //! -mintxfee default
static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000; static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000;
//! minimum change amount //! target minimum change amount
static const CAmount MIN_CHANGE = CENT; static const CAmount MIN_CHANGE = CENT;
//! final minimum change amount after paying for fees
static const CAmount MIN_FINAL_CHANGE = MIN_CHANGE/2;
//! Default for -spendzeroconfchange //! Default for -spendzeroconfchange
static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true; static const bool DEFAULT_SPEND_ZEROCONF_CHANGE = true;
//! Default for -sendfreetransactions //! Default for -sendfreetransactions

Loading…
Cancel
Save