From 76dde290655ffd49a658234d43c29d6eb435f1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Haf?= Date: Wed, 23 Apr 2025 18:03:36 +0200 Subject: [PATCH] add `-maxrelaytxfee` option --- src/init.cpp | 2 ++ src/interfaces/chain.h | 3 +++ src/kernel/mempool_options.h | 1 + src/node/interfaces.cpp | 5 +++++ src/node/mempool_args.cpp | 8 ++++++++ src/policy/policy.h | 2 ++ src/validation.cpp | 6 ++++++ 7 files changed, 27 insertions(+) diff --git a/src/init.cpp b/src/init.cpp index 64ed601bc1..093ded97e1 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -703,6 +703,8 @@ void SetupServerArgs(ArgsManager& argsman) OptionsCategory::NODE_RELAY); argsman.AddArg("-minrelaytxfee=", strprintf("Fees (in %s/kvB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)", CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); + argsman.AddArg("-maxrelaytxfee=", strprintf("Fees (in %s/kvB) bigger than this are considered zero fee for relaying, mining and transaction creation (set to 0 to disable) (default: %s)", + CURRENCY_UNIT, DEFAULT_MAX_RELAY_TX_FEE), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-rejectparasites", strprintf("Refuse to relay or mine parasitic overlay protocols (default: %u)", DEFAULT_REJECT_PARASITES), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY); argsman.AddArg("-rejecttokens", strprintf("Refuse to relay or mine transactions involving non-bitcoin tokens (default: %u)", diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h index e8d264645e..5a50231b24 100644 --- a/src/interfaces/chain.h +++ b/src/interfaces/chain.h @@ -295,6 +295,9 @@ public: //! Relay incremental fee setting (-incrementalrelayfee), reflecting cost of relay. virtual CFeeRate relayIncrementalFee() = 0; + //! Relay current maximum fee. + virtual CFeeRate relayMaxFee() = 0; + //! Relay dust fee setting (-dustrelayfee), reflecting lowest rate it's economical to spend. virtual CFeeRate relayDustFee() = 0; diff --git a/src/kernel/mempool_options.h b/src/kernel/mempool_options.h index 8fab5d2ec3..4e585819da 100644 --- a/src/kernel/mempool_options.h +++ b/src/kernel/mempool_options.h @@ -56,6 +56,7 @@ struct MemPoolOptions { CFeeRate incremental_relay_feerate{DEFAULT_INCREMENTAL_RELAY_FEE}; /** A fee rate smaller than this is considered zero fee (for relaying, mining and transaction creation) */ CFeeRate min_relay_feerate{DEFAULT_MIN_RELAY_TX_FEE}; + CFeeRate max_relay_feerate{DEFAULT_MAX_RELAY_TX_FEE}; CFeeRate dust_relay_feerate{DUST_RELAY_TX_FEE}; CFeeRate dust_relay_feerate_floor{DUST_RELAY_TX_FEE}; /** Negative for a target number of blocks, positive for target kB into current mempool. */ diff --git a/src/node/interfaces.cpp b/src/node/interfaces.cpp index 2f87717736..14c2c67cba 100644 --- a/src/node/interfaces.cpp +++ b/src/node/interfaces.cpp @@ -779,6 +779,11 @@ public: if (!m_node.mempool) return CFeeRate{DEFAULT_INCREMENTAL_RELAY_FEE}; return m_node.mempool->m_opts.incremental_relay_feerate; } + CFeeRate relayMaxFee() override + { + if (!m_node.mempool) return CFeeRate{DEFAULT_MAX_RELAY_TX_FEE}; + return m_node.mempool->m_opts.max_relay_feerate; + } CFeeRate relayDustFee() override { if (!m_node.mempool) return CFeeRate{DUST_RELAY_TX_FEE}; diff --git a/src/node/mempool_args.cpp b/src/node/mempool_args.cpp index 52c16227a0..0be1504589 100644 --- a/src/node/mempool_args.cpp +++ b/src/node/mempool_args.cpp @@ -122,6 +122,14 @@ util::Result ApplyArgsManOptions(const ArgsManager& argsman, const CChainP LogPrintf("Increasing minrelaytxfee to %s to match incrementalrelayfee\n", mempool_opts.min_relay_feerate.ToString()); } + if (argsman.IsArgSet("-maxrelaytxfee")) { + if (std::optional max_relay_feerate = ParseMoney(argsman.GetArg("-maxrelaytxfee", ""))) { + mempool_opts.max_relay_feerate = CFeeRate{max_relay_feerate.value()}; + } else { + return util::Error{AmountErrMsg("maxrelayfee", argsman.GetArg("-maxrelaytxfee", ""))}; + } + } + // Feerate used to define dust. Shouldn't be changed lightly as old // implementations may inadvertently create non-standard transactions if (argsman.IsArgSet("-dustrelayfee")) { diff --git a/src/policy/policy.h b/src/policy/policy.h index 83195a588d..572defa65e 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -81,6 +81,8 @@ static const int DEFAULT_DUST_RELAY_MULTIPLIER{3'000}; static const std::string DEFAULT_SPKREUSE{"allow"}; /** Default for -minrelaytxfee, minimum relay fee for transactions */ static constexpr unsigned int DEFAULT_MIN_RELAY_TX_FEE{1000}; +/** Default for -maxrelaytxfee, minimum relay fee for transactions */ +static constexpr unsigned int DEFAULT_MAX_RELAY_TX_FEE{0}; /** Default for -limitancestorcount, max number of in-mempool ancestors */ static constexpr unsigned int DEFAULT_ANCESTOR_LIMIT{25}; /** Default for -limitancestorsize, maximum kilobytes of tx + all in-mempool ancestors */ diff --git a/src/validation.cpp b/src/validation.cpp index 388ba9de56..a0d8e2aac2 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -1086,6 +1086,12 @@ bool MemPoolAccept::PreChecks(ATMPArgs& args, Workspace& ws) // feerate later. if (!args.m_package_feerates && !CheckFeeRate(ws.m_vsize, ws.m_modified_fees, state, args.m_ignore_rejects)) return false; + + if ((ws.m_ptx->version != TRUC_VERSION || m_pool.m_opts.truc_policy != TRUCPolicy::Enforce) && ws.m_modified_fees > m_pool.m_opts.max_relay_feerate.GetFee(ws.m_vsize) && m_pool.m_opts.max_relay_feerate != CFeeRate{0}) { + return state.Invalid(TxValidationResult::TX_MEMPOOL_POLICY, "max relay fee met", + strprintf("%d < %d", ws.m_modified_fees, m_pool.m_opts.max_relay_feerate.GetFee(ws.m_vsize))); + } + std::set conflicts_as_a_set; std::transform(ws.m_conflicts_incl_policy.begin(), ws.m_conflicts_incl_policy.end(), std::inserter(conflicts_as_a_set, conflicts_as_a_set.end()),