No longer allow "free" transactions
Remove -limitfreerelay and always enforce minRelayTxFee in the mempool (except from disconnected blocks) Remove -relaypriority, the option was only used for the ability to allow free transactions to be relayed regardless of their priority. Both notions no longer apply.
This commit is contained in:
parent
ad727f4eaf
commit
f838005444
10 changed files with 10 additions and 53 deletions
|
@ -80,7 +80,6 @@ class AbandonConflictTest(BitcoinTestFramework):
|
||||||
|
|
||||||
# Restart the node with a higher min relay fee so the parent tx is no longer in mempool
|
# Restart the node with a higher min relay fee so the parent tx is no longer in mempool
|
||||||
# TODO: redo with eviction
|
# TODO: redo with eviction
|
||||||
# Note had to make sure tx did not have AllowFree priority
|
|
||||||
stop_node(self.nodes[0],0)
|
stop_node(self.nodes[0],0)
|
||||||
self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.0001"])
|
self.nodes[0]=start_node(0, self.options.tmpdir, ["-debug","-logtimemicros","-minrelaytxfee=0.0001"])
|
||||||
|
|
||||||
|
|
|
@ -188,8 +188,7 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||||
|
|
||||||
# Now we can connect the other nodes, didn't want to connect them earlier
|
# Now we can connect the other nodes, didn't want to connect them earlier
|
||||||
# so the estimates would not be affected by the splitting transactions
|
# so the estimates would not be affected by the splitting transactions
|
||||||
# Node1 mines small blocks but that are bigger than the expected transaction rate,
|
# Node1 mines small blocks but that are bigger than the expected transaction rate.
|
||||||
# and allows free transactions.
|
|
||||||
# NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes,
|
# NOTE: the CreateNewBlock code starts counting block size at 1,000 bytes,
|
||||||
# (17k is room enough for 110 or so transactions)
|
# (17k is room enough for 110 or so transactions)
|
||||||
self.nodes.append(start_node(1, self.options.tmpdir,
|
self.nodes.append(start_node(1, self.options.tmpdir,
|
||||||
|
|
|
@ -444,8 +444,6 @@ std::string HelpMessage(HelpMessageMode mode)
|
||||||
{
|
{
|
||||||
strUsage += HelpMessageOpt("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS));
|
strUsage += HelpMessageOpt("-logtimemicros", strprintf("Add microsecond precision to debug timestamps (default: %u)", DEFAULT_LOGTIMEMICROS));
|
||||||
strUsage += HelpMessageOpt("-mocktime=<n>", "Replace actual time with <n> seconds since epoch (default: 0)");
|
strUsage += HelpMessageOpt("-mocktime=<n>", "Replace actual time with <n> seconds since epoch (default: 0)");
|
||||||
strUsage += HelpMessageOpt("-limitfreerelay=<n>", strprintf("Continuously rate-limit free transactions to <n>*1000 bytes per minute (default: %u)", DEFAULT_LIMITFREERELAY));
|
|
||||||
strUsage += HelpMessageOpt("-relaypriority", strprintf("Require high priority for relaying free or low-fee transactions (default: %u)", DEFAULT_RELAYPRIORITY));
|
|
||||||
strUsage += HelpMessageOpt("-maxsigcachesize=<n>", strprintf("Limit size of signature cache to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE));
|
strUsage += HelpMessageOpt("-maxsigcachesize=<n>", strprintf("Limit size of signature cache to <n> MiB (default: %u)", DEFAULT_MAX_SIG_CACHE_SIZE));
|
||||||
strUsage += HelpMessageOpt("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE));
|
strUsage += HelpMessageOpt("-maxtipage=<n>", strprintf("Maximum tip age in seconds to consider node in initial block download (default: %u)", DEFAULT_MAX_TIP_AGE));
|
||||||
}
|
}
|
||||||
|
@ -975,7 +973,7 @@ bool AppInitParameterInteraction()
|
||||||
if (nConnectTimeout <= 0)
|
if (nConnectTimeout <= 0)
|
||||||
nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
|
nConnectTimeout = DEFAULT_CONNECT_TIMEOUT;
|
||||||
|
|
||||||
// Fee-per-kilobyte amount considered the same as "free"
|
// Fee-per-kilobyte amount required for mempool acceptance and relay
|
||||||
// If you are mining, be careful setting this:
|
// If you are mining, be careful setting this:
|
||||||
// if you set it to zero then
|
// if you set it to zero then
|
||||||
// a transaction spammer can cheaply fill blocks using
|
// a transaction spammer can cheaply fill blocks using
|
||||||
|
|
|
@ -1853,7 +1853,7 @@ bool static ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStr
|
||||||
LogPrint("mempool", " invalid orphan tx %s\n", orphanHash.ToString());
|
LogPrint("mempool", " invalid orphan tx %s\n", orphanHash.ToString());
|
||||||
}
|
}
|
||||||
// Has inputs but not accepted to mempool
|
// Has inputs but not accepted to mempool
|
||||||
// Probably non-standard or insufficient fee/priority
|
// Probably non-standard or insufficient fee
|
||||||
LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString());
|
LogPrint("mempool", " removed orphan tx %s\n", orphanHash.ToString());
|
||||||
vEraseQueue.push_back(orphanHash);
|
vEraseQueue.push_back(orphanHash);
|
||||||
if (!orphanTx.HasWitness() && !stateDummy.CorruptionPossible()) {
|
if (!orphanTx.HasWitness() && !stateDummy.CorruptionPossible()) {
|
||||||
|
@ -3249,9 +3249,8 @@ bool SendMessages(CNode* pto, CConnman& connman, const std::atomic<bool>& interr
|
||||||
static CFeeRate default_feerate(DEFAULT_MIN_RELAY_TX_FEE);
|
static CFeeRate default_feerate(DEFAULT_MIN_RELAY_TX_FEE);
|
||||||
static FeeFilterRounder filterRounder(default_feerate);
|
static FeeFilterRounder filterRounder(default_feerate);
|
||||||
CAmount filterToSend = filterRounder.round(currentFilter);
|
CAmount filterToSend = filterRounder.round(currentFilter);
|
||||||
// If we don't allow free transactions, then we always have a fee filter of at least minRelayTxFee
|
// We always have a fee filter of at least minRelayTxFee
|
||||||
if (GetArg("-limitfreerelay", DEFAULT_LIMITFREERELAY) <= 0)
|
filterToSend = std::max(filterToSend, ::minRelayTxFee.GetFeePerK());
|
||||||
filterToSend = std::max(filterToSend, ::minRelayTxFee.GetFeePerK());
|
|
||||||
if (filterToSend != pto->lastSentFeeFilter) {
|
if (filterToSend != pto->lastSentFeeFilter) {
|
||||||
connman.PushMessage(pto, msgMaker.Make(NetMsgType::FEEFILTER, filterToSend));
|
connman.PushMessage(pto, msgMaker.Make(NetMsgType::FEEFILTER, filterToSend));
|
||||||
pto->lastSentFeeFilter = filterToSend;
|
pto->lastSentFeeFilter = filterToSend;
|
||||||
|
|
|
@ -61,7 +61,7 @@ UniValue getinfo(const JSONRPCRequest& request)
|
||||||
" \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
|
" \"keypoolsize\": xxxx, (numeric) how many new keys are pre-generated\n"
|
||||||
" \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
|
" \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
|
||||||
" \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n"
|
" \"paytxfee\": x.xxxx, (numeric) the transaction fee set in " + CURRENCY_UNIT + "/kB\n"
|
||||||
" \"relayfee\": x.xxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n"
|
" \"relayfee\": x.xxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n"
|
||||||
" \"errors\": \"...\" (string) any error messages\n"
|
" \"errors\": \"...\" (string) any error messages\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"\nExamples:\n"
|
"\nExamples:\n"
|
||||||
|
|
|
@ -417,7 +417,7 @@ UniValue getnetworkinfo(const JSONRPCRequest& request)
|
||||||
" }\n"
|
" }\n"
|
||||||
" ,...\n"
|
" ,...\n"
|
||||||
" ],\n"
|
" ],\n"
|
||||||
" \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for non-free transactions in " + CURRENCY_UNIT + "/kB\n"
|
" \"relayfee\": x.xxxxxxxx, (numeric) minimum relay fee for transactions in " + CURRENCY_UNIT + "/kB\n"
|
||||||
" \"incrementalfee\": x.xxxxxxxx, (numeric) minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB\n"
|
" \"incrementalfee\": x.xxxxxxxx, (numeric) minimum fee increment for mempool limiting or BIP 125 replacement in " + CURRENCY_UNIT + "/kB\n"
|
||||||
" \"localaddresses\": [ (array) list of local addresses\n"
|
" \"localaddresses\": [ (array) list of local addresses\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
|
|
|
@ -30,18 +30,6 @@
|
||||||
class CAutoFile;
|
class CAutoFile;
|
||||||
class CBlockIndex;
|
class CBlockIndex;
|
||||||
|
|
||||||
inline double AllowFreeThreshold()
|
|
||||||
{
|
|
||||||
return COIN * 144 / 250;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool AllowFree(double dPriority)
|
|
||||||
{
|
|
||||||
// Large (in bytes) low-priority (new, small-coin) transactions
|
|
||||||
// need a fee.
|
|
||||||
return dPriority > AllowFreeThreshold();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Fake height value used in CCoins to signify they are only in the memory pool (since 0.8) */
|
/** Fake height value used in CCoins to signify they are only in the memory pool (since 0.8) */
|
||||||
static const unsigned int MEMPOOL_HEIGHT = 0x7FFFFFFF;
|
static const unsigned int MEMPOOL_HEIGHT = 0x7FFFFFFF;
|
||||||
|
|
||||||
|
|
|
@ -753,32 +753,11 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
||||||
CAmount mempoolRejectFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize);
|
CAmount mempoolRejectFee = pool.GetMinFee(GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000).GetFee(nSize);
|
||||||
if (mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) {
|
if (mempoolRejectFee > 0 && nModifiedFees < mempoolRejectFee) {
|
||||||
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", false, strprintf("%d < %d", nFees, mempoolRejectFee));
|
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", false, strprintf("%d < %d", nFees, mempoolRejectFee));
|
||||||
} else if (GetBoolArg("-relaypriority", DEFAULT_RELAYPRIORITY) && nModifiedFees < ::minRelayTxFee.GetFee(nSize) && !AllowFree(entry.GetPriority(chainActive.Height() + 1))) {
|
|
||||||
// Require that free transactions have sufficient priority to be mined in the next block.
|
|
||||||
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "insufficient priority");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continuously rate-limit free (really, very-low-fee) transactions
|
// No transactions are allowed below minRelayTxFee except from disconnected blocks
|
||||||
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
|
if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFee(nSize)) {
|
||||||
// be annoying or make others' transactions take longer to confirm.
|
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "min relay fee not met");
|
||||||
if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFee(nSize))
|
|
||||||
{
|
|
||||||
static CCriticalSection csFreeLimiter;
|
|
||||||
static double dFreeCount;
|
|
||||||
static int64_t nLastTime;
|
|
||||||
int64_t nNow = GetTime();
|
|
||||||
|
|
||||||
LOCK(csFreeLimiter);
|
|
||||||
|
|
||||||
// Use an exponentially decaying ~10-minute window:
|
|
||||||
dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
|
|
||||||
nLastTime = nNow;
|
|
||||||
// -limitfreerelay unit is thousand-bytes-per-minute
|
|
||||||
// At default rate it would take over a month to fill 1GB
|
|
||||||
if (dFreeCount + nSize >= GetArg("-limitfreerelay", DEFAULT_LIMITFREERELAY) * 10 * 1000)
|
|
||||||
return state.DoS(0, false, REJECT_INSUFFICIENTFEE, "rate limited free transaction");
|
|
||||||
LogPrint("mempool", "Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
|
|
||||||
dFreeCount += nSize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nAbsurdFee && nFees > nAbsurdFee)
|
if (nAbsurdFee && nFees > nAbsurdFee)
|
||||||
|
|
|
@ -122,8 +122,6 @@ static const int64_t BLOCK_DOWNLOAD_TIMEOUT_BASE = 1000000;
|
||||||
/** Additional block download timeout per parallel downloading peer (i.e. 5 min) */
|
/** Additional block download timeout per parallel downloading peer (i.e. 5 min) */
|
||||||
static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000;
|
static const int64_t BLOCK_DOWNLOAD_TIMEOUT_PER_PEER = 500000;
|
||||||
|
|
||||||
static const unsigned int DEFAULT_LIMITFREERELAY = 0;
|
|
||||||
static const bool DEFAULT_RELAYPRIORITY = true;
|
|
||||||
static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
|
static const int64_t DEFAULT_MAX_TIP_AGE = 24 * 60 * 60;
|
||||||
/** Maximum age of our tip in seconds for us to be considered current for fee estimation */
|
/** Maximum age of our tip in seconds for us to be considered current for fee estimation */
|
||||||
static const int64_t MAX_FEE_ESTIMATION_TIP_AGE = 3 * 60 * 60;
|
static const int64_t MAX_FEE_ESTIMATION_TIP_AGE = 3 * 60 * 60;
|
||||||
|
|
|
@ -3842,9 +3842,6 @@ bool CWallet::ParameterInteraction()
|
||||||
bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
|
bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
|
||||||
fWalletRbf = GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
|
fWalletRbf = GetBoolArg("-walletrbf", DEFAULT_WALLET_RBF);
|
||||||
|
|
||||||
if (GetBoolArg("-sendfreetransactions", false))
|
|
||||||
InitWarning("The argument -sendfreetransactions is no longer supported.");
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue