Skip to content

Commit

Permalink
Consensus: Minimal way to move dust out of consensus
Browse files Browse the repository at this point in the history
coming from btc@330bb5a456a5f9c26703fa742e4c80691e1455ab
  • Loading branch information
furszy committed Nov 2, 2020
1 parent 98c6183 commit 9d2dc93
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 29 deletions.
25 changes: 24 additions & 1 deletion src/policy/policy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,29 @@

bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;

CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee)
{
// "Dust" is defined in terms of dustRelayFee,
// which has units satoshis-per-kilobyte.
// If you'd pay more than 1/3 in fees
// to spend something, then we consider it dust.
// A typical spendable txout is 34 bytes big, and will
// need a CTxIn of at least 148 bytes to spend:
// so dust is a spendable txout less than
// 546*dustRelayFee/1000 (in satoshis).
if (txout.scriptPubKey.IsUnspendable())
return 0;

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

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

/**
* Check transaction inputs to mitigate two
* potential denial-of-service attacks:
Expand Down Expand Up @@ -132,7 +155,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason)
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
reason = "bare-multisig";
return false;
} else if (txout.IsDust(::minRelayTxFee)) {
} else if (IsDust(txout, ::minRelayTxFee)) {
reason = "dust";
return false;
}
Expand Down
5 changes: 5 additions & 0 deletions src/policy/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

class CChainParams;
class CCoinsViewCache;
class CTxOut;

/** Default for -blockmaxsize and -blockminsize, which control the range of sizes the mining code will create **/
static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000;
Expand Down Expand Up @@ -48,6 +49,10 @@ 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);

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

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

/** Check for standard transaction types
Expand Down
22 changes: 0 additions & 22 deletions src/primitives/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,28 +194,6 @@ class CTxOut
uint256 GetHash() const;
bool GetKeyIDFromUTXO(CKeyID& keyIDRet) const;

CAmount GetDustThreshold(const CFeeRate &minRelayTxFee) const
{
// "Dust" is defined in terms of CTransaction::minRelayTxFee,
// which has units satoshis-per-kilobyte.
// If you'd pay more than 1/3 in fees
// to spend something, then we consider it dust.
// A typical spendable txout is 34 bytes big, and will
// need a CTxIn of at least 148 bytes to spend:
// so dust is a spendable txout less than 546 satoshis
// with default minRelayTxFee.
if (scriptPubKey.IsUnspendable())
return 0;

size_t nSize = GetSerializeSize(*this, SER_DISK, 0) + 148u;
return 3 * minRelayTxFee.GetFee(nSize);
}

bool IsDust(const CFeeRate& minRelayTxFee) const
{
return (nValue < GetDustThreshold(minRelayTxFee));
}

bool IsZerocoinMint() const;

friend bool operator==(const CTxOut& a, const CTxOut& b)
Expand Down
5 changes: 3 additions & 2 deletions src/qt/coincontroldialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "guiutil.h"
#include "init.h"
#include "optionsmodel.h"
#include "policy/policy.h"
#include "txmempool.h"
#include "wallet/wallet.h"
#include "walletmodel.h"
Expand Down Expand Up @@ -566,7 +567,7 @@ void CoinControlDialog::updateLabels()
nPayAmount += amount;
if (amount > 0) {
CTxOut txout(amount, (CScript)std::vector<unsigned char>(24, 0));
if (txout.IsDust(::minRelayTxFee))
if (IsDust(txout, ::minRelayTxFee))
fDust = true;
}
}
Expand Down Expand Up @@ -669,7 +670,7 @@ void CoinControlDialog::updateLabels()
// Never create dust outputs; if we would, just add the dust to the fee.
if (nChange > 0 && nChange < CENT) {
CTxOut txout(nChange, (CScript)std::vector<unsigned char>(24, 0));
if (txout.IsDust(::minRelayTxFee)) {
if (IsDust(txout, ::minRelayTxFee)) {
nPayFee += nChange;
nChange = 0;
}
Expand Down
3 changes: 2 additions & 1 deletion src/qt/guiutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "walletmodel.h"

#include "init.h"
#include "policy/policy.h"
#include "primitives/transaction.h"
#include "protocol.h"
#include "script/script.h"
Expand Down Expand Up @@ -246,7 +247,7 @@ bool isDust(const QString& address, const CAmount& amount)
CTxDestination dest = DecodeDestination(address.toStdString());
CScript script = GetScriptForDestination(dest);
CTxOut txOut(amount, script);
return txOut.IsDust(::minRelayTxFee);
return IsDust(txOut, ::minRelayTxFee);
}

QString HtmlEscape(const QString& str, bool fMultiLine)
Expand Down
3 changes: 2 additions & 1 deletion src/qt/paymentserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "bitcoinunits.h"
#include "guiutil.h"
#include "optionsmodel.h"
#include "policy/policy.h"

#include "base58.h"
#include "chainparams.h"
Expand Down Expand Up @@ -515,7 +516,7 @@ bool PaymentServer::processPaymentRequest(PaymentRequestPlus& request, SendCoins

// Extract and check amounts
CTxOut txOut(sendingTo.second, sendingTo.first);
if (txOut.IsDust(::minRelayTxFee)) {
if (IsDust(txOut, ::minRelayTxFee)) {
Q_EMIT message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).").arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)),
CClientUIInterface::MSG_ERROR);

Expand Down
4 changes: 2 additions & 2 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2593,7 +2593,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,
if (coinControl && !coinControl->fSplitBlock) {
for (const CRecipient& rec : vecSend) {
CTxOut txout(rec.nAmount, rec.scriptPubKey);
if (txout.IsDust(::minRelayTxFee)) {
if (IsDust(txout, ::minRelayTxFee)) {
strFailReason = _("Transaction amount too small");
return false;
}
Expand Down Expand Up @@ -2700,7 +2700,7 @@ bool CWallet::CreateTransaction(const std::vector<CRecipient>& vecSend,

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

0 comments on commit 9d2dc93

Please sign in to comment.