Allow all mempool txs to be replaced after a configurable timeout (default 6h) #10823

Open
wants to merge 2 commits into
from
Jump to file or symbol
Failed to load files and symbols.
+12 −9
Split
View
@@ -485,6 +485,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-datacarrier", strprintf(_("Relay and mine data carrier transactions (default: %u)"), DEFAULT_ACCEPT_DATACARRIER));
strUsage += HelpMessageOpt("-datacarriersize", strprintf(_("Maximum size of data in data carrier transactions we relay and mine (default: %u)"), MAX_OP_RETURN_RELAY));
strUsage += HelpMessageOpt("-mempoolreplacement", strprintf(_("Enable transaction replacement in the memory pool (default: %u)"), DEFAULT_ENABLE_REPLACEMENT));
+ strUsage += HelpMessageOpt("-mempoolreplacementtimeout=<n>", strprintf(_("Number of seconds after which transactions in mempool can be replaced (default: %u)"), DEFAULT_REPLACEMENT_TIMEOUT));
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(DEFAULT_MIN_RELAY_TX_FEE)));
strUsage += HelpMessageOpt("-whitelistrelay", strprintf(_("Accept relayed transactions received from whitelisted peers even when not relaying transactions (default: %d)"), DEFAULT_WHITELISTRELAY));
View
@@ -350,7 +350,8 @@ class SaltedTxidHasher
* - a transaction which doesn't meet the minimum fee requirements.
* - a new transaction that double-spends an input of a transaction already in
* the pool where the new transaction does not meet the Replace-By-Fee
- * requirements as defined in BIP 125.
+ * requirements as defined in BIP 125 and the transaction(s) being replaced
+ * has not been in mempool for over a timeout defaulting to 6 hours.
* - a non-standard transaction.
*
* CTxMemPool::mapTx, and CTxMemPoolEntry bookkeeping:
View
@@ -20,6 +20,7 @@
#include "init.h"
#include "policy/fees.h"
#include "policy/policy.h"
+#include "policy/rbf.h"
#include "pow.h"
#include "primitives/block.h"
#include "primitives/transaction.h"
@@ -477,6 +478,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// Check for conflicts with in-memory transactions
std::set<uint256> setConflicts;
+ const int64_t nReplacementTimeout = GetArg("-mempoolreplacementtimeout", DEFAULT_REPLACEMENT_TIMEOUT);
{
LOCK(pool.cs); // protect pool.mapNextTx
for (const CTxIn &txin : tx.vin)
@@ -499,17 +501,14 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
// first-seen mempool behavior should be checking all
// unconfirmed ancestors anyway; doing otherwise is hopelessly
// insecure.
+ //
+ // All transactions in mempool become replaceable after the timeout.
bool fReplacementOptOut = true;
if (fEnableReplacement)
{
- for (const CTxIn &_txin : ptxConflicting->vin)
- {
- if (_txin.nSequence < std::numeric_limits<unsigned int>::max()-1)
- {
- fReplacementOptOut = false;
- break;
- }
- }
+ const int64_t nConflictingTime = pool.info(ptxConflicting->GetHash()).nTime;
+ const bool fConflictingPreTimeout = nAcceptTime - nConflictingTime < nReplacementTimeout;
+ fReplacementOptOut = fConflictingPreTimeout && !SignalsOptInRBF(*ptxConflicting);
}
if (fReplacementOptOut) {
return state.Invalid(false, REJECT_DUPLICATE, "txn-mempool-conflict");
View
@@ -135,6 +135,8 @@ static const unsigned int DEFAULT_BANSCORE_THRESHOLD = 100;
static const bool DEFAULT_PERSIST_MEMPOOL = true;
/** Default for -mempoolreplacement */
static const bool DEFAULT_ENABLE_REPLACEMENT = true;
+/** Default for -mempoolreplacementtimeout in seconds after which transactions in mempool are replaceable (i.e. 6 hours) */
+static const unsigned int DEFAULT_REPLACEMENT_TIMEOUT = 6 * 60 * 60;
/** Default for using fee filter */
static const bool DEFAULT_FEEFILTER = true;