From 8c223a3dc826a432eb1094f2885172368af6e30d Mon Sep 17 00:00:00 2001 From: Lawrence Nahum Date: Thu, 13 Jul 2017 00:00:57 +0200 Subject: [PATCH] Allow all mempool transactions to be replaced after a configurable timeout (default 6h) --- src/init.cpp | 1 + src/txmempool.h | 3 ++- src/validation.cpp | 14 ++++++-------- src/validation.h | 2 ++ 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 0ee828ce92b..72cc53aa3ec 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -487,6 +487,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=", strprintf(_("Number of seconds after which transactions in mempool can be replaced (default: %u)"), DEFAULT_REPLACEMENT_TIMEOUT)); strUsage += HelpMessageOpt("-minrelaytxfee=", 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)); diff --git a/src/txmempool.h b/src/txmempool.h index d272114a7c5..64c781ee5ff 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -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: diff --git a/src/validation.cpp b/src/validation.cpp index babf6f15221..74bc1d0221c 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -478,6 +478,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool // Check for conflicts with in-memory transactions std::set setConflicts; + const int64_t nReplacementTimeout = GetArg("-mempoolreplacementtimeout", DEFAULT_REPLACEMENT_TIMEOUT); { LOCK(pool.cs); // protect pool.mapNextTx for (const CTxIn &txin : tx.vin) @@ -500,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 <= MAX_BIP125_RBF_SEQUENCE) - { - 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"); diff --git a/src/validation.h b/src/validation.h index b44b72d2d4e..b77f3ac5c16 100644 --- a/src/validation.h +++ b/src/validation.h @@ -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;