aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Morcos <morcos@chaincode.com>2017-07-06 14:00:46 -0400
committerAlex Morcos <morcos@chaincode.com>2017-07-17 13:40:30 -0400
commitf4d00e63f7951469c840edede3f675d07249f62a (patch)
treeb18d0d106aa0928780b64c0d3e23425800024537
parentb1385852ef2ba45fd6926d75497646debf79e686 (diff)
Add a discard_rate
Any change output which would be dust at the discard_rate you are willing to discard completely and add to fee (as well as continuing to pay the fee that would have been needed for creating the change).
-rw-r--r--src/wallet/wallet.cpp31
-rw-r--r--src/wallet/wallet.h3
2 files changed, 32 insertions, 2 deletions
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 13da7bb2c2..e230ee0eb0 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -57,6 +57,8 @@ CFeeRate CWallet::minTxFee = CFeeRate(DEFAULT_TRANSACTION_MINFEE);
*/
CFeeRate CWallet::fallbackFee = CFeeRate(DEFAULT_FALLBACK_FEE);
+CFeeRate CWallet::m_discard_rate = CFeeRate(DEFAULT_DISCARD_FEE);
+
const uint256 CMerkleTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
/** @defgroup mapWallet
@@ -2501,6 +2503,17 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
return true;
}
+static CFeeRate GetDiscardRate(const CBlockPolicyEstimator& estimator)
+{
+ unsigned int highest_target = estimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
+ CFeeRate discard_rate = estimator.estimateSmartFee(highest_target, nullptr /* FeeCalculation */, false /* conservative */);
+ // Don't let discard_rate be greater than longest possible fee estimate if we get a valid fee estimate
+ discard_rate = (discard_rate == CFeeRate(0)) ? CWallet::m_discard_rate : std::min(discard_rate, CWallet::m_discard_rate);
+ // Discard rate must be at least dustRelayFee
+ discard_rate = std::max(discard_rate, ::dustRelayFee);
+ return discard_rate;
+}
+
bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletTx& wtxNew, CReserveKey& reservekey, CAmount& nFeeRet,
int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign)
{
@@ -2600,6 +2613,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
CTxOut change_prototype_txout(0, scriptChange);
size_t change_prototype_size = GetSerializeSize(change_prototype_txout, SER_DISK, 0);
+ CFeeRate discard_rate = GetDiscardRate(::feeEstimator);
nFeeRet = 0;
bool pick_new_inputs = true;
CAmount nValueIn = 0;
@@ -2667,7 +2681,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// Never create dust outputs; if we would, just
// add the dust to the fee.
- if (IsDust(newTxOut, ::dustRelayFee))
+ if (IsDust(newTxOut, discard_rate))
{
nChangePosInOut = -1;
nFeeRet += nChange;
@@ -2747,7 +2761,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend, CWalletT
// (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, ::dustRelayFee);
+ 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;
@@ -3788,6 +3802,9 @@ std::string CWallet::GetWalletHelpString(bool showDebug)
strUsage += HelpMessageOpt("-keypool=<n>", strprintf(_("Set key pool size to <n> (default: %u)"), DEFAULT_KEYPOOL_SIZE));
strUsage += HelpMessageOpt("-fallbackfee=<amt>", strprintf(_("A fee rate (in %s/kB) that will be used when fee estimation has insufficient data (default: %s)"),
CURRENCY_UNIT, FormatMoney(DEFAULT_FALLBACK_FEE)));
+ strUsage += HelpMessageOpt("-discardfee=<amt>", strprintf(_("The fee rate (in %s/kB) used to discard change (to fee) if it would be dust at this fee rate (default: %s) "
+ "Note: We will always discard up to the dust relay fee and a discard fee above that is limited by the longest target fee estimate"),
+ CURRENCY_UNIT, FormatMoney(DEFAULT_DISCARD_FEE)));
strUsage += HelpMessageOpt("-mintxfee=<amt>", strprintf(_("Fees (in %s/kB) smaller than this are considered zero fee for transaction creation (default: %s)"),
CURRENCY_UNIT, FormatMoney(DEFAULT_TRANSACTION_MINFEE)));
strUsage += HelpMessageOpt("-paytxfee=<amt>", strprintf(_("Fee (in %s/kB) to add to transactions you send (default: %s)"),
@@ -4113,6 +4130,16 @@ bool CWallet::ParameterInteraction()
_("This is the transaction fee you may pay when fee estimates are not available."));
CWallet::fallbackFee = CFeeRate(nFeePerK);
}
+ if (IsArgSet("-discardfee"))
+ {
+ CAmount nFeePerK = 0;
+ if (!ParseMoney(GetArg("-discardfee", ""), nFeePerK))
+ return InitError(strprintf(_("Invalid amount for -discardfee=<amount>: '%s'"), GetArg("-discardfee", "")));
+ if (nFeePerK > HIGH_TX_FEE_PER_KB)
+ InitWarning(AmountHighWarn("-discardfee") + " " +
+ _("This is the transaction fee you may discard if change is smaller than dust at this level"));
+ CWallet::m_discard_rate = CFeeRate(nFeePerK);
+ }
if (IsArgSet("-paytxfee"))
{
CAmount nFeePerK = 0;
diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h
index b716e46a7d..a7fef8a802 100644
--- a/src/wallet/wallet.h
+++ b/src/wallet/wallet.h
@@ -45,6 +45,8 @@ static const unsigned int DEFAULT_KEYPOOL_SIZE = 100;
static const CAmount DEFAULT_TRANSACTION_FEE = 0;
//! -fallbackfee default
static const CAmount DEFAULT_FALLBACK_FEE = 20000;
+//! -m_discard_rate default
+static const CAmount DEFAULT_DISCARD_FEE = 10000;
//! -mintxfee default
static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000;
//! minimum recommended increment for BIP 125 replacement txs
@@ -965,6 +967,7 @@ public:
static CFeeRate minTxFee;
static CFeeRate fallbackFee;
+ static CFeeRate m_discard_rate;
/**
* Estimate the minimum fee considering user set parameters
* and the required fee