Skip to content

Commit

Permalink
[Policy] Introduce -dustrelayfee
Browse files Browse the repository at this point in the history
>>> adapted from bitcoin/bitcoin@eb30d1a
  • Loading branch information
random-zebra committed Jun 2, 2021
1 parent 9fb29cc commit a1c56fd
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 26 deletions.
10 changes: 10 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-minrelaytxfee=<amt>", strprintf(_("Fees (in %s/Kb) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)"), CURRENCY_UNIT, FormatMoney(::minRelayTxFee.GetFeePerK())));
strUsage += HelpMessageOpt("-printtoconsole", strprintf(_("Send trace/debug info to console instead of debug.log file (default: %u)"), 0));
if (showDebug) {
strUsage += HelpMessageOpt("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define dust, the value of an output such that it will cost about 1/3 of its value in fees at this fee rate to spend it. (default: %s)", CURRENCY_UNIT, FormatMoney(DUST_RELAY_TX_FEE)));
strUsage += HelpMessageOpt("-printpriority", strprintf(_("Log transaction priority and fee per kB when mining blocks (default: %u)"), DEFAULT_PRINTPRIORITY));
}
strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)"));
Expand Down Expand Up @@ -1146,6 +1147,15 @@ bool AppInitParameterInteraction()
if (!chainparams.IsTestChain() && !fRequireStandard)
return UIError(strprintf("%s is not currently supported for %s chain", "-acceptnonstdtxn", chainparams.NetworkIDString()));

// Feerate used to define dust. Shouldn't be changed lightly as old
// implementations may inadvertently create non-standard transactions
if (gArgs.IsArgSet("-dustrelayfee")) {
CAmount n = 0;
if (!ParseMoney(gArgs.GetArg("-dustrelayfee", ""), n) || 0 == n)
return UIError(AmountErrMsg("dustrelayfee", gArgs.GetArg("-dustrelayfee", "")));
dustRelayFee = CFeeRate(n);
}

#ifdef ENABLE_WALLET
strWalletFile = gArgs.GetArg("-wallet", DEFAULT_WALLET_DAT);
if (!CWallet::ParameterInteraction())
Expand Down
24 changes: 13 additions & 11 deletions src/policy/policy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;

CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee)
CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);

CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
{
// "Dust" is defined in terms of dustRelayFee,
// which has units satoshis-per-kilobyte.
Expand All @@ -31,26 +33,26 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee)

size_t nSize = GetSerializeSize(txout, SER_DISK, 0);
nSize += (32 + 4 + 1 + 107 + 4); // the 148 mentioned above
return 3 * dustRelayFee.GetFee(nSize);
return 3 * dustRelayFeeIn.GetFee(nSize);
}

CAmount GetDustThreshold(const CFeeRate& dustRelayFee)
CAmount GetDustThreshold(const CFeeRate& dustRelayFeeIn)
{
// return the dust threshold for a typical 34 bytes output
return 3 * dustRelayFee.GetFee(182);
return 3 * dustRelayFeeIn.GetFee(182);
}

bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee)
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
{
return (txout.nValue < GetDustThreshold(txout, dustRelayFee));
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
}

CAmount GetShieldedDustThreshold(const CFeeRate& dustRelayFee)
CAmount GetShieldedDustThreshold(const CFeeRate& dustRelayFeeIn)
{
unsigned int K = DEFAULT_SHIELDEDTXFEE_K; // Fixed (100) for now
return 3 * K * dustRelayFee.GetFee(SPENDDESCRIPTION_SIZE +
CTXOUT_REGULAR_SIZE +
BINDINGSIG_SIZE);
return 3 * K * dustRelayFeeIn.GetFee(SPENDDESCRIPTION_SIZE +
CTXOUT_REGULAR_SIZE +
BINDINGSIG_SIZE);
}

/**
Expand Down Expand Up @@ -174,7 +176,7 @@ bool IsStandardTx(const CTransactionRef& tx, int nBlockHeight, std::string& reas
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
reason = "bare-multisig";
return false;
} else if (IsDust(txout, ::minRelayTxFee)) {
} else if (IsDust(txout, dustRelayFee)) {
reason = "dust";
return false;
}
Expand Down
16 changes: 12 additions & 4 deletions src/policy/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
/** Default for -permitbaremultisig */
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
extern bool fIsBareMultisigStd;
/** Min feerate for defining dust. Historically this has been the same as the
* minRelayTxFee, however changing the dust limit changes which transactions are
* standard and should be done with care and ideally rarely. It makes sense to
* only increase the dust limit after prior releases were already not creating
* outputs below the new threshold */
static const unsigned int DUST_RELAY_TX_FEE = 10000;

/**
* Standard script verification flags that standard transactions will comply
Expand All @@ -50,12 +56,12 @@ static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCR
BOOST_STATIC_ASSERT(DEFAULT_BLOCK_MAX_SIZE <= MAX_BLOCK_SIZE_CURRENT);
BOOST_STATIC_ASSERT(DEFAULT_BLOCK_PRIORITY_SIZE <= DEFAULT_BLOCK_MAX_SIZE);

CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn);

bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn);

CAmount GetDustThreshold(const CFeeRate& dustRelayFee);
CAmount GetShieldedDustThreshold(const CFeeRate& dustRelayFee);
CAmount GetDustThreshold(const CFeeRate& dustRelayFeeIn);
CAmount GetShieldedDustThreshold(const CFeeRate& dustRelayFeeIn);

bool IsStandard(const CScript& scriptPubKey, txnouttype& whichType);

Expand All @@ -71,4 +77,6 @@ bool IsStandardTx(const CTransactionRef& tx, int nBlockHeight, std::string& reas
*/
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);

extern CFeeRate dustRelayFee;

#endif // BITCOIN_POLICY_H
8 changes: 4 additions & 4 deletions src/qt/coincontroldialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ TotalAmounts CoinControlDialog::getTotals() const
if (shieldedOut) nShieldOuts++;
else nTransOuts++;
if (a.first > 0 && !t.fDust) {
if (a.first < (shieldedOut ? GetShieldedDustThreshold(minRelayTxFee) : GetDustThreshold(minRelayTxFee)))
if (a.first < (shieldedOut ? GetShieldedDustThreshold(dustRelayFee) : GetDustThreshold(dustRelayFee)))
t.fDust = true;
}
t.nBytes += (shieldedOut ? OUTPUTDESCRIPTION_SIZE
Expand Down Expand Up @@ -566,8 +566,8 @@ TotalAmounts CoinControlDialog::getTotals() const
t.nChange = t.nAmount - t.nPayFee - t.nPayAmount;

// Never create dust outputs; if we would, just add the dust to the fee.
CAmount dustThreshold = fSelectTransparent ? GetDustThreshold(minRelayTxFee) :
GetShieldedDustThreshold(minRelayTxFee);
CAmount dustThreshold = fSelectTransparent ? GetDustThreshold(dustRelayFee)
: GetShieldedDustThreshold(dustRelayFee);
if (t.nChange > 0 && t.nChange < dustThreshold) {
t.nPayFee += t.nChange;
t.nChange = 0;
Expand Down Expand Up @@ -636,7 +636,7 @@ void CoinControlDialog::updateLabels()
toolTip1 += tr("Can vary +/- 1 byte per input.");

QString toolTip3 = tr("This label turns red, if recipient receives an amount smaller than %1 (transparent) / %2 (shield)."
).arg(BitcoinUnits::formatWithUnit(nDisplayUnit, GetDustThreshold(minRelayTxFee))).arg(BitcoinUnits::formatWithUnit(nDisplayUnit, GetShieldedDustThreshold(minRelayTxFee)));
).arg(BitcoinUnits::formatWithUnit(nDisplayUnit, GetDustThreshold(dustRelayFee))).arg(BitcoinUnits::formatWithUnit(nDisplayUnit, GetShieldedDustThreshold(dustRelayFee)));

// how many satoshis the estimated fee can vary per byte we guess wrong
double dFeeVary;
Expand Down
2 changes: 1 addition & 1 deletion src/qt/guiutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ bool isDust(const QString& address, const CAmount& amount)
CTxDestination dest = DecodeDestination(address.toStdString());
CScript script = GetScriptForDestination(dest);
CTxOut txOut(amount, script);
return IsDust(txOut, ::minRelayTxFee);
return IsDust(txOut, dustRelayFee);
}

QString HtmlEscape(const QString& str, bool fMultiLine)
Expand Down
4 changes: 2 additions & 2 deletions src/sapling/sapling_operation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ OperationResult SaplingOperation::loadUtxos(TxValues& txValues)
// Final step, append utxo to the transaction

// Get dust threshold
CAmount dustThreshold = GetDustThreshold(minRelayTxFee);
CAmount dustThreshold = GetDustThreshold(dustRelayFee);
CAmount dustChange = -1;

CAmount selectedUTXOAmount = 0;
Expand Down Expand Up @@ -445,7 +445,7 @@ OperationResult SaplingOperation::loadUnspentNotes(TxValues& txValues, uint256&
std::vector<libzcash::SaplingNote> notes;
std::vector<libzcash::SaplingExpandedSpendingKey> spendingKeys;
txValues.shieldedInTotal = 0;
CAmount dustThreshold = GetShieldedDustThreshold(minRelayTxFee);
CAmount dustThreshold = GetShieldedDustThreshold(dustRelayFee);
CAmount dustChange = -1;
for (const auto& t : shieldedInputs) {
// Get the spending key for the address.
Expand Down
4 changes: 2 additions & 2 deletions src/sapling/transaction_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,8 +421,8 @@ TransactionBuilderResult TransactionBuilder::Build(bool fDummySig)

if (change > 0) {
// If we get here and the change is dust, add it to the fee
CAmount dustThreshold = (spends.empty() && outputs.empty()) ? GetDustThreshold(minRelayTxFee) :
GetShieldedDustThreshold(minRelayTxFee);
CAmount dustThreshold = (spends.empty() && outputs.empty()) ? GetDustThreshold(dustRelayFee)
: GetShieldedDustThreshold(dustRelayFee);
if (change > dustThreshold) {
// Send change to the specified change address. If no change address
// was set, send change to the first Sapling address given as input
Expand Down
4 changes: 2 additions & 2 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3133,7 +3133,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
// Fill outputs
for (const CRecipient& rec : vecSend) {
CTxOut txout(rec.nAmount, rec.scriptPubKey);
if (IsDust(txout, ::minRelayTxFee)) {
if (IsDust(txout, dustRelayFee)) {
strFailReason = _("Transaction amount too small");
return false;
}
Expand Down Expand Up @@ -3198,7 +3198,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,

// Never create dust outputs; if we would, just
// add the dust to the fee.
if (IsDust(newTxOut, ::minRelayTxFee)) {
if (IsDust(newTxOut, dustRelayFee)) {
nFeeRet += nChange;
nChange = 0;
reservekey.ReturnKey();
Expand Down

0 comments on commit a1c56fd

Please sign in to comment.