Skip to content

Commit a1c56fd

Browse files
committed
[Policy] Introduce -dustrelayfee
>>> adapted from bitcoin/bitcoin@eb30d1a
1 parent 9fb29cc commit a1c56fd

File tree

8 files changed

+46
-26
lines changed

8 files changed

+46
-26
lines changed

src/init.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ std::string HelpMessage(HelpMessageMode mode)
561561
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())));
562562
strUsage += HelpMessageOpt("-printtoconsole", strprintf(_("Send trace/debug info to console instead of debug.log file (default: %u)"), 0));
563563
if (showDebug) {
564+
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)));
564565
strUsage += HelpMessageOpt("-printpriority", strprintf(_("Log transaction priority and fee per kB when mining blocks (default: %u)"), DEFAULT_PRINTPRIORITY));
565566
}
566567
strUsage += HelpMessageOpt("-shrinkdebugfile", _("Shrink debug.log file on client startup (default: 1 when no -debug)"));
@@ -1146,6 +1147,15 @@ bool AppInitParameterInteraction()
11461147
if (!chainparams.IsTestChain() && !fRequireStandard)
11471148
return UIError(strprintf("%s is not currently supported for %s chain", "-acceptnonstdtxn", chainparams.NetworkIDString()));
11481149

1150+
// Feerate used to define dust. Shouldn't be changed lightly as old
1151+
// implementations may inadvertently create non-standard transactions
1152+
if (gArgs.IsArgSet("-dustrelayfee")) {
1153+
CAmount n = 0;
1154+
if (!ParseMoney(gArgs.GetArg("-dustrelayfee", ""), n) || 0 == n)
1155+
return UIError(AmountErrMsg("dustrelayfee", gArgs.GetArg("-dustrelayfee", "")));
1156+
dustRelayFee = CFeeRate(n);
1157+
}
1158+
11491159
#ifdef ENABLE_WALLET
11501160
strWalletFile = gArgs.GetArg("-wallet", DEFAULT_WALLET_DAT);
11511161
if (!CWallet::ParameterInteraction())

src/policy/policy.cpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616

1717
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
1818

19-
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee)
19+
CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
20+
21+
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
2022
{
2123
// "Dust" is defined in terms of dustRelayFee,
2224
// which has units satoshis-per-kilobyte.
@@ -31,26 +33,26 @@ CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee)
3133

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

37-
CAmount GetDustThreshold(const CFeeRate& dustRelayFee)
39+
CAmount GetDustThreshold(const CFeeRate& dustRelayFeeIn)
3840
{
3941
// return the dust threshold for a typical 34 bytes output
40-
return 3 * dustRelayFee.GetFee(182);
42+
return 3 * dustRelayFeeIn.GetFee(182);
4143
}
4244

43-
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee)
45+
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
4446
{
45-
return (txout.nValue < GetDustThreshold(txout, dustRelayFee));
47+
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
4648
}
4749

48-
CAmount GetShieldedDustThreshold(const CFeeRate& dustRelayFee)
50+
CAmount GetShieldedDustThreshold(const CFeeRate& dustRelayFeeIn)
4951
{
5052
unsigned int K = DEFAULT_SHIELDEDTXFEE_K; // Fixed (100) for now
51-
return 3 * K * dustRelayFee.GetFee(SPENDDESCRIPTION_SIZE +
52-
CTXOUT_REGULAR_SIZE +
53-
BINDINGSIG_SIZE);
53+
return 3 * K * dustRelayFeeIn.GetFee(SPENDDESCRIPTION_SIZE +
54+
CTXOUT_REGULAR_SIZE +
55+
BINDINGSIG_SIZE);
5456
}
5557

5658
/**
@@ -174,7 +176,7 @@ bool IsStandardTx(const CTransactionRef& tx, int nBlockHeight, std::string& reas
174176
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
175177
reason = "bare-multisig";
176178
return false;
177-
} else if (IsDust(txout, ::minRelayTxFee)) {
179+
} else if (IsDust(txout, dustRelayFee)) {
178180
reason = "dust";
179181
return false;
180182
}

src/policy/policy.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
2929
/** Default for -permitbaremultisig */
3030
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
3131
extern bool fIsBareMultisigStd;
32+
/** Min feerate for defining dust. Historically this has been the same as the
33+
* minRelayTxFee, however changing the dust limit changes which transactions are
34+
* standard and should be done with care and ideally rarely. It makes sense to
35+
* only increase the dust limit after prior releases were already not creating
36+
* outputs below the new threshold */
37+
static const unsigned int DUST_RELAY_TX_FEE = 10000;
3238

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

53-
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
59+
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn);
5460

55-
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
61+
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn);
5662

57-
CAmount GetDustThreshold(const CFeeRate& dustRelayFee);
58-
CAmount GetShieldedDustThreshold(const CFeeRate& dustRelayFee);
63+
CAmount GetDustThreshold(const CFeeRate& dustRelayFeeIn);
64+
CAmount GetShieldedDustThreshold(const CFeeRate& dustRelayFeeIn);
5965

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

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

80+
extern CFeeRate dustRelayFee;
81+
7482
#endif // BITCOIN_POLICY_H

src/qt/coincontroldialog.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ TotalAmounts CoinControlDialog::getTotals() const
535535
if (shieldedOut) nShieldOuts++;
536536
else nTransOuts++;
537537
if (a.first > 0 && !t.fDust) {
538-
if (a.first < (shieldedOut ? GetShieldedDustThreshold(minRelayTxFee) : GetDustThreshold(minRelayTxFee)))
538+
if (a.first < (shieldedOut ? GetShieldedDustThreshold(dustRelayFee) : GetDustThreshold(dustRelayFee)))
539539
t.fDust = true;
540540
}
541541
t.nBytes += (shieldedOut ? OUTPUTDESCRIPTION_SIZE
@@ -566,8 +566,8 @@ TotalAmounts CoinControlDialog::getTotals() const
566566
t.nChange = t.nAmount - t.nPayFee - t.nPayAmount;
567567

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

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

641641
// how many satoshis the estimated fee can vary per byte we guess wrong
642642
double dFeeVary;

src/qt/guiutil.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ bool isDust(const QString& address, const CAmount& amount)
250250
CTxDestination dest = DecodeDestination(address.toStdString());
251251
CScript script = GetScriptForDestination(dest);
252252
CTxOut txOut(amount, script);
253-
return IsDust(txOut, ::minRelayTxFee);
253+
return IsDust(txOut, dustRelayFee);
254254
}
255255

256256
QString HtmlEscape(const QString& str, bool fMultiLine)

src/sapling/sapling_operation.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ OperationResult SaplingOperation::loadUtxos(TxValues& txValues)
313313
// Final step, append utxo to the transaction
314314

315315
// Get dust threshold
316-
CAmount dustThreshold = GetDustThreshold(minRelayTxFee);
316+
CAmount dustThreshold = GetDustThreshold(dustRelayFee);
317317
CAmount dustChange = -1;
318318

319319
CAmount selectedUTXOAmount = 0;
@@ -445,7 +445,7 @@ OperationResult SaplingOperation::loadUnspentNotes(TxValues& txValues, uint256&
445445
std::vector<libzcash::SaplingNote> notes;
446446
std::vector<libzcash::SaplingExpandedSpendingKey> spendingKeys;
447447
txValues.shieldedInTotal = 0;
448-
CAmount dustThreshold = GetShieldedDustThreshold(minRelayTxFee);
448+
CAmount dustThreshold = GetShieldedDustThreshold(dustRelayFee);
449449
CAmount dustChange = -1;
450450
for (const auto& t : shieldedInputs) {
451451
// Get the spending key for the address.

src/sapling/transaction_builder.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,8 @@ TransactionBuilderResult TransactionBuilder::Build(bool fDummySig)
421421

422422
if (change > 0) {
423423
// If we get here and the change is dust, add it to the fee
424-
CAmount dustThreshold = (spends.empty() && outputs.empty()) ? GetDustThreshold(minRelayTxFee) :
425-
GetShieldedDustThreshold(minRelayTxFee);
424+
CAmount dustThreshold = (spends.empty() && outputs.empty()) ? GetDustThreshold(dustRelayFee)
425+
: GetShieldedDustThreshold(dustRelayFee);
426426
if (change > dustThreshold) {
427427
// Send change to the specified change address. If no change address
428428
// was set, send change to the first Sapling address given as input

src/wallet/wallet.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3133,7 +3133,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
31333133
// Fill outputs
31343134
for (const CRecipient& rec : vecSend) {
31353135
CTxOut txout(rec.nAmount, rec.scriptPubKey);
3136-
if (IsDust(txout, ::minRelayTxFee)) {
3136+
if (IsDust(txout, dustRelayFee)) {
31373137
strFailReason = _("Transaction amount too small");
31383138
return false;
31393139
}
@@ -3198,7 +3198,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
31983198

31993199
// Never create dust outputs; if we would, just
32003200
// add the dust to the fee.
3201-
if (IsDust(newTxOut, ::minRelayTxFee)) {
3201+
if (IsDust(newTxOut, dustRelayFee)) {
32023202
nFeeRet += nChange;
32033203
nChange = 0;
32043204
reservekey.ReturnKey();

0 commit comments

Comments
 (0)