Introduce -dustrelayfee
This commit is contained in:
parent
7b1add3c28
commit
eb30d1a5b2
8 changed files with 37 additions and 17 deletions
11
src/init.cpp
11
src/init.cpp
|
@ -468,6 +468,7 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
if (showDebug) {
|
if (showDebug) {
|
||||||
strUsage += HelpMessageOpt("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !Params(CBaseChainParams::TESTNET).RequireStandard()));
|
strUsage += HelpMessageOpt("-acceptnonstdtxn", strprintf("Relay and mine \"non-standard\" transactions (%sdefault: %u)", "testnet/regtest only; ", !Params(CBaseChainParams::TESTNET).RequireStandard()));
|
||||||
strUsage += HelpMessageOpt("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)));
|
strUsage += HelpMessageOpt("-incrementalrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to define cost of relay, used for mempool limiting and BIP 125 replacement. (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_INCREMENTAL_RELAY_FEE)));
|
||||||
|
strUsage += HelpMessageOpt("-dustrelayfee=<amt>", strprintf("Fee rate (in %s/kB) used to defined 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("-bytespersigop", strprintf(_("Equivalent bytes per sigop in transactions for relay and mining (default: %u)"), DEFAULT_BYTES_PER_SIGOP));
|
strUsage += HelpMessageOpt("-bytespersigop", strprintf(_("Equivalent bytes per sigop in transactions for relay and mining (default: %u)"), DEFAULT_BYTES_PER_SIGOP));
|
||||||
strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), DEFAULT_ACCEPT_DATACARRIER));
|
strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), DEFAULT_ACCEPT_DATACARRIER));
|
||||||
|
@ -995,6 +996,16 @@ bool AppInitParameterInteraction()
|
||||||
return InitError(AmountErrMsg("blockmintxfee", GetArg("-blockmintxfee", "")));
|
return InitError(AmountErrMsg("blockmintxfee", GetArg("-blockmintxfee", "")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Feerate used to define dust. Shouldn't be changed lightly as old
|
||||||
|
// implementations may inadvertently create non-standard transactions
|
||||||
|
if (IsArgSet("-dustrelayfee"))
|
||||||
|
{
|
||||||
|
CAmount n = 0;
|
||||||
|
if (!ParseMoney(GetArg("-dustrelayfee", ""), n) || 0 == n)
|
||||||
|
return InitError(AmountErrMsg("dustrelayfee", GetArg("-dustrelayfee", "")));
|
||||||
|
dustRelayFee = CFeeRate(n);
|
||||||
|
}
|
||||||
|
|
||||||
fRequireStandard = !GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
|
fRequireStandard = !GetBoolArg("-acceptnonstdtxn", !chainparams.RequireStandard());
|
||||||
if (chainparams.RequireStandard() && !fRequireStandard)
|
if (chainparams.RequireStandard() && !fRequireStandard)
|
||||||
return InitError(strprintf("acceptnonstdtxn is not currently supported for %s chain", chainparams.NetworkIDString()));
|
return InitError(strprintf("acceptnonstdtxn is not currently supported for %s chain", chainparams.NetworkIDString()));
|
||||||
|
|
|
@ -105,7 +105,7 @@ bool IsStandardTx(const CTransaction& tx, std::string& reason, const bool witnes
|
||||||
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
|
else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
|
||||||
reason = "bare-multisig";
|
reason = "bare-multisig";
|
||||||
return false;
|
return false;
|
||||||
} else if (txout.IsDust(::minRelayTxFee)) {
|
} else if (txout.IsDust(dustRelayFee)) {
|
||||||
reason = "dust";
|
reason = "dust";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -207,6 +207,7 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
||||||
}
|
}
|
||||||
|
|
||||||
CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
|
CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
|
||||||
|
CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
|
||||||
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
|
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
|
||||||
|
|
||||||
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost)
|
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost)
|
||||||
|
|
|
@ -40,6 +40,12 @@ static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEMS = 100;
|
||||||
static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEM_SIZE = 80;
|
static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEM_SIZE = 80;
|
||||||
/** The maximum size of a standard witnessScript */
|
/** The maximum size of a standard witnessScript */
|
||||||
static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600;
|
static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600;
|
||||||
|
/** 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 = 1000;
|
||||||
/**
|
/**
|
||||||
* Standard script verification flags that standard transactions will comply
|
* Standard script verification flags that standard transactions will comply
|
||||||
* with. However scripts violating these flags may still be present in valid
|
* with. However scripts violating these flags may still be present in valid
|
||||||
|
@ -88,6 +94,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
||||||
bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
|
bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
|
||||||
|
|
||||||
extern CFeeRate incrementalRelayFee;
|
extern CFeeRate incrementalRelayFee;
|
||||||
|
extern CFeeRate dustRelayFee;
|
||||||
extern unsigned int nBytesPerSigOp;
|
extern unsigned int nBytesPerSigOp;
|
||||||
|
|
||||||
/** Compute the virtual transaction size (weight reinterpreted as bytes). */
|
/** Compute the virtual transaction size (weight reinterpreted as bytes). */
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
|
|
||||||
#include "wallet/coincontrol.h"
|
#include "wallet/coincontrol.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "validation.h" // For minRelayTxFee
|
#include "policy/policy.h"
|
||||||
|
#include "validation.h" // For mempool
|
||||||
#include "wallet/wallet.h"
|
#include "wallet/wallet.h"
|
||||||
|
|
||||||
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
|
#include <boost/assign/list_of.hpp> // for 'map_list_of()'
|
||||||
|
@ -432,7 +433,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
||||||
{
|
{
|
||||||
CTxOut txout(amount, (CScript)std::vector<unsigned char>(24, 0));
|
CTxOut txout(amount, (CScript)std::vector<unsigned char>(24, 0));
|
||||||
txDummy.vout.push_back(txout);
|
txDummy.vout.push_back(txout);
|
||||||
if (txout.IsDust(::minRelayTxFee))
|
if (txout.IsDust(dustRelayFee))
|
||||||
fDust = true;
|
fDust = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -545,10 +546,10 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
||||||
if (nChange > 0 && nChange < MIN_CHANGE)
|
if (nChange > 0 && nChange < MIN_CHANGE)
|
||||||
{
|
{
|
||||||
CTxOut txout(nChange, (CScript)std::vector<unsigned char>(24, 0));
|
CTxOut txout(nChange, (CScript)std::vector<unsigned char>(24, 0));
|
||||||
if (txout.IsDust(::minRelayTxFee))
|
if (txout.IsDust(dustRelayFee))
|
||||||
{
|
{
|
||||||
if (CoinControlDialog::fSubtractFeeFromAmount) // dust-change will be raised until no dust
|
if (CoinControlDialog::fSubtractFeeFromAmount) // dust-change will be raised until no dust
|
||||||
nChange = txout.GetDustThreshold(::minRelayTxFee);
|
nChange = txout.GetDustThreshold(dustRelayFee);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nPayFee += nChange;
|
nPayFee += nChange;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
#include "primitives/transaction.h"
|
#include "primitives/transaction.h"
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#include "validation.h" // For minRelayTxFee
|
#include "policy/policy.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "script/script.h"
|
#include "script/script.h"
|
||||||
#include "script/standard.h"
|
#include "script/standard.h"
|
||||||
|
@ -257,7 +257,7 @@ bool isDust(const QString& address, const CAmount& amount)
|
||||||
CTxDestination dest = CBitcoinAddress(address.toStdString()).Get();
|
CTxDestination dest = CBitcoinAddress(address.toStdString()).Get();
|
||||||
CScript script = GetScriptForDestination(dest);
|
CScript script = GetScriptForDestination(dest);
|
||||||
CTxOut txOut(amount, script);
|
CTxOut txOut(amount, script);
|
||||||
return txOut.IsDust(::minRelayTxFee);
|
return txOut.IsDust(dustRelayFee);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString HtmlEscape(const QString& str, bool fMultiLine)
|
QString HtmlEscape(const QString& str, bool fMultiLine)
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
#include "base58.h"
|
#include "base58.h"
|
||||||
#include "chainparams.h"
|
#include "chainparams.h"
|
||||||
#include "validation.h" // For minRelayTxFee
|
#include "policy/policy.h"
|
||||||
#include "ui_interface.h"
|
#include "ui_interface.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "wallet/wallet.h"
|
#include "wallet/wallet.h"
|
||||||
|
@ -582,7 +582,7 @@ bool PaymentServer::processPaymentRequest(const PaymentRequestPlus& request, Sen
|
||||||
|
|
||||||
// Extract and check amounts
|
// Extract and check amounts
|
||||||
CTxOut txOut(sendingTo.second, sendingTo.first);
|
CTxOut txOut(sendingTo.second, sendingTo.first);
|
||||||
if (txOut.IsDust(::minRelayTxFee)) {
|
if (txOut.IsDust(dustRelayFee)) {
|
||||||
Q_EMIT message(tr("Payment request error"), tr("Requested payment amount of %1 is too small (considered dust).")
|
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)),
|
.arg(BitcoinUnits::formatWithUnit(optionsModel->getDisplayUnit(), sendingTo.second)),
|
||||||
CClientUIInterface::MSG_ERROR);
|
CClientUIInterface::MSG_ERROR);
|
||||||
|
|
|
@ -692,7 +692,7 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||||
BOOST_CHECK(IsStandardTx(t, reason));
|
BOOST_CHECK(IsStandardTx(t, reason));
|
||||||
|
|
||||||
// Check dust with default relay fee:
|
// Check dust with default relay fee:
|
||||||
CAmount nDustThreshold = 182 * minRelayTxFee.GetFeePerK()/1000 * 3;
|
CAmount nDustThreshold = 182 * dustRelayFee.GetFeePerK()/1000 * 3;
|
||||||
BOOST_CHECK_EQUAL(nDustThreshold, 546);
|
BOOST_CHECK_EQUAL(nDustThreshold, 546);
|
||||||
// dust:
|
// dust:
|
||||||
t.vout[0].nValue = nDustThreshold - 1;
|
t.vout[0].nValue = nDustThreshold - 1;
|
||||||
|
@ -703,14 +703,14 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
||||||
|
|
||||||
// Check dust with odd relay fee to verify rounding:
|
// Check dust with odd relay fee to verify rounding:
|
||||||
// nDustThreshold = 182 * 1234 / 1000 * 3
|
// nDustThreshold = 182 * 1234 / 1000 * 3
|
||||||
minRelayTxFee = CFeeRate(1234);
|
dustRelayFee = CFeeRate(1234);
|
||||||
// dust:
|
// dust:
|
||||||
t.vout[0].nValue = 672 - 1;
|
t.vout[0].nValue = 672 - 1;
|
||||||
BOOST_CHECK(!IsStandardTx(t, reason));
|
BOOST_CHECK(!IsStandardTx(t, reason));
|
||||||
// not dust:
|
// not dust:
|
||||||
t.vout[0].nValue = 672;
|
t.vout[0].nValue = 672;
|
||||||
BOOST_CHECK(IsStandardTx(t, reason));
|
BOOST_CHECK(IsStandardTx(t, reason));
|
||||||
minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE);
|
dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
|
||||||
|
|
||||||
t.vout[0].scriptPubKey = CScript() << OP_1;
|
t.vout[0].scriptPubKey = CScript() << OP_1;
|
||||||
BOOST_CHECK(!IsStandardTx(t, reason));
|
BOOST_CHECK(!IsStandardTx(t, reason));
|
||||||
|
|
|
@ -2335,7 +2335,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (txout.IsDust(::minRelayTxFee))
|
if (txout.IsDust(dustRelayFee))
|
||||||
{
|
{
|
||||||
if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
|
if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
|
||||||
{
|
{
|
||||||
|
@ -2413,16 +2413,16 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
||||||
// We do not move dust-change to fees, because the sender would end up paying more than requested.
|
// We do not move dust-change to fees, because the sender would end up paying more than requested.
|
||||||
// This would be against the purpose of the all-inclusive feature.
|
// This would be against the purpose of the all-inclusive feature.
|
||||||
// So instead we raise the change and deduct from the recipient.
|
// So instead we raise the change and deduct from the recipient.
|
||||||
if (nSubtractFeeFromAmount > 0 && newTxOut.IsDust(::minRelayTxFee))
|
if (nSubtractFeeFromAmount > 0 && newTxOut.IsDust(dustRelayFee))
|
||||||
{
|
{
|
||||||
CAmount nDust = newTxOut.GetDustThreshold(::minRelayTxFee) - newTxOut.nValue;
|
CAmount nDust = newTxOut.GetDustThreshold(dustRelayFee) - newTxOut.nValue;
|
||||||
newTxOut.nValue += nDust; // raise change until no more dust
|
newTxOut.nValue += nDust; // raise change until no more dust
|
||||||
for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient
|
for (unsigned int i = 0; i < vecSend.size(); i++) // subtract from first recipient
|
||||||
{
|
{
|
||||||
if (vecSend[i].fSubtractFeeFromAmount)
|
if (vecSend[i].fSubtractFeeFromAmount)
|
||||||
{
|
{
|
||||||
txNew.vout[i].nValue -= nDust;
|
txNew.vout[i].nValue -= nDust;
|
||||||
if (txNew.vout[i].IsDust(::minRelayTxFee))
|
if (txNew.vout[i].IsDust(dustRelayFee))
|
||||||
{
|
{
|
||||||
strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
|
strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
|
||||||
return false;
|
return false;
|
||||||
|
@ -2434,7 +2434,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
||||||
|
|
||||||
// Never create dust outputs; if we would, just
|
// Never create dust outputs; if we would, just
|
||||||
// add the dust to the fee.
|
// add the dust to the fee.
|
||||||
if (newTxOut.IsDust(::minRelayTxFee))
|
if (newTxOut.IsDust(dustRelayFee))
|
||||||
{
|
{
|
||||||
nChangePosInOut = -1;
|
nChangePosInOut = -1;
|
||||||
nFeeRet += nChange;
|
nFeeRet += nChange;
|
||||||
|
|
Loading…
Reference in a new issue