From a54c7b94f8825e9b52fec9066fe7c1d5b6f53482 Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Fri, 25 Aug 2017 14:46:07 -0500 Subject: [PATCH 1/2] Fix rounding errors in calculation of minimum change size --- src/wallet/wallet.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 291bcc7a2..503354b66 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2861,13 +2861,15 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT // new inputs. We now know we only need the smaller fee // (because of reduced tx size) and so we should add a // change output. Only try this once. - CAmount fee_needed_for_change = GetMinimumFee(change_prototype_size, coin_control, ::mempool, ::feeEstimator, nullptr); - CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, discard_rate); - CAmount max_excess_fee = fee_needed_for_change + minimum_value_for_change; - if (nFeeRet > nFeeNeeded + max_excess_fee && nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) { - pick_new_inputs = false; - nFeeRet = nFeeNeeded + fee_needed_for_change; - continue; + if (nChangePosInOut == -1 && nSubtractFeeFromAmount == 0 && pick_new_inputs) { + unsigned int tx_size_with_change = nBytes + change_prototype_size + 2; // Add 2 as a buffer in case increasing # of outputs changes compact size + CAmount fee_needed_with_change = GetMinimumFee(tx_size_with_change, coin_control, ::mempool, ::feeEstimator, nullptr); + CAmount minimum_value_for_change = GetDustThreshold(change_prototype_txout, discard_rate); + if (nFeeRet >= fee_needed_with_change + minimum_value_for_change) { + pick_new_inputs = false; + nFeeRet = fee_needed_with_change; + continue; + } } // If we have change output already, just increase it From 6af49dddeaeec7f134e86d6f8cf839c55870b7ab Mon Sep 17 00:00:00 2001 From: Alex Morcos Date: Fri, 25 Aug 2017 14:49:44 -0500 Subject: [PATCH 2/2] Output a bit more information for fee calculation report. --- src/wallet/wallet.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 503354b66..8c0daf6cb 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -2679,6 +2679,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT assert(txNew.nLockTime <= (unsigned int)chainActive.Height()); assert(txNew.nLockTime < LOCKTIME_THRESHOLD); FeeCalculation feeCalc; + CAmount nFeeNeeded; unsigned int nBytes; { std::set setCoins; @@ -2840,7 +2841,7 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT vin.scriptWitness.SetNull(); } - CAmount nFeeNeeded = GetMinimumFee(nBytes, coin_control, ::mempool, ::feeEstimator, &feeCalc); + nFeeNeeded = GetMinimumFee(nBytes, coin_control, ::mempool, ::feeEstimator, &feeCalc); // If we made it here and we aren't even able to meet the relay fee on the next pass, give up // because we must be at the maximum allowed fee. @@ -2964,8 +2965,8 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT } } - LogPrintf("Fee Calculation: Fee:%d Bytes:%u Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n", - nFeeRet, nBytes, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay, + LogPrintf("Fee Calculation: Fee:%d Bytes:%u Needed:%d Tgt:%d (requested %d) Reason:\"%s\" Decay %.5f: Estimation: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out) Fail: (%g - %g) %.2f%% %.1f/(%.1f %d mem %.1f out)\n", + nFeeRet, nBytes, nFeeNeeded, feeCalc.returnedTarget, feeCalc.desiredTarget, StringForFeeReason(feeCalc.reason), feeCalc.est.decay, feeCalc.est.pass.start, feeCalc.est.pass.end, 100 * feeCalc.est.pass.withinTarget / (feeCalc.est.pass.totalConfirmed + feeCalc.est.pass.inMempool + feeCalc.est.pass.leftMempool), feeCalc.est.pass.withinTarget, feeCalc.est.pass.totalConfirmed, feeCalc.est.pass.inMempool, feeCalc.est.pass.leftMempool,