From d749d52cdeb3e85f2c94a1fd9728ed9f5b5b9e93 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 6 Dec 2022 01:55:25 +0000 Subject: [PATCH 1/7] validation: Make LimitMempoolSize public --- src/validation.cpp | 2 +- src/validation.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/validation.cpp b/src/validation.cpp index 1fd8f0e326..35ae9ddaba 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -260,7 +260,7 @@ bool CheckSequenceLocksAtTip(CBlockIndex* tip, // Returns the script flags which should be checked for a given block static unsigned int GetBlockScriptFlags(const CBlockIndex& block_index, const ChainstateManager& chainman); -static void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache) +void LimitMempoolSize(CTxMemPool& pool, CCoinsViewCache& coins_cache) EXCLUSIVE_LOCKS_REQUIRED(::cs_main, pool.cs) { AssertLockHeld(::cs_main); diff --git a/src/validation.h b/src/validation.h index fd0e2115f7..dec35ccba8 100644 --- a/src/validation.h +++ b/src/validation.h @@ -302,6 +302,8 @@ std::optional CalculateLockPointsAtTip( bool CheckSequenceLocksAtTip(CBlockIndex* tip, const LockPoints& lock_points); +void LimitMempoolSize(CTxMemPool&, CCoinsViewCache&); + /** * Closure representing one script verification * Note that this stores references to the spending transaction From 997cf91108eba5b9773ef8e593c5ebe2b917cea0 Mon Sep 17 00:00:00 2001 From: R E Broadley Date: Sun, 25 Apr 2021 19:12:33 +0100 Subject: [PATCH 2/7] Add maxmempool RPC Github-Pull: #21780 Rebased-From: 040b280c6613ac81a92a324f356f0b4cc205ef8d --- src/rpc/client.cpp | 1 + src/rpc/mempool.cpp | 31 +++++++++++++++++++++++++++++++ src/txmempool.h | 2 +- 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index 4459dd71aa..87c387efdc 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -66,6 +66,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getbalance", 3, "avoid_reuse" }, { "getblockfrompeer", 1, "peer_id" }, { "getblockhash", 0, "height" }, + { "maxmempool", 0, "megabytes" }, { "waitforblockheight", 0, "height" }, { "waitforblockheight", 1, "timeout" }, { "waitforblock", 1, "timeout" }, diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 927b4ce1fc..cc119c7d01 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -378,6 +378,36 @@ UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose, bool include_mempoo } } +static RPCHelpMan maxmempool() +{ + return RPCHelpMan{"maxmempool", + "\nSets the allocated memory for the memory pool.\n", + { + {"megabytes", RPCArg::Type::NUM, RPCArg::Optional::NO, "The memory allocated in MB"}, + }, + RPCResult{ + RPCResult::Type::NONE, "", ""}, + RPCExamples{ + HelpExampleCli("maxmempool", "150") + HelpExampleRpc("maxmempool", "150") + }, + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue +{ + int nSize = request.params[0].getInt(); + int64_t nMempoolSizeMax = nSize * 1000000; + + CTxMemPool& mempool = EnsureAnyMemPool(request.context); + LOCK(mempool.cs); + + int64_t nMempoolSizeMin = mempool.m_limits.descendant_size_vbytes * 40; + if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin) + throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("MaxMempool size %d is too small", nSize)); + mempool.m_max_size_bytes = nSize; + + return NullUniValue; +} + }; +} + static RPCHelpMan getrawmempool() { return RPCHelpMan{"getrawmempool", @@ -922,6 +952,7 @@ void RegisterMempoolRPCCommands(CRPCTable& t) {"blockchain", &getmempoolinfo}, {"blockchain", &getrawmempool}, {"blockchain", &savemempool}, + {"blockchain", &maxmempool}, {"hidden", &submitpackage}, }; for (const auto& c : commands) { diff --git a/src/txmempool.h b/src/txmempool.h index 2c3cb7e9db..e2d2187add 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -451,7 +451,7 @@ public: using Options = kernel::MemPoolOptions; - const int64_t m_max_size_bytes; + int64_t m_max_size_bytes; const std::chrono::seconds m_expiry; const CFeeRate m_incremental_relay_feerate; const CFeeRate m_min_relay_feerate; From 937191ff611c77290acd31c051d6c2d2119a4181 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Sun, 24 Apr 2022 03:09:15 +0000 Subject: [PATCH 3/7] Abstract minimum maxmempool to maxmempoolMinimumBytes function (in txmempool) --- src/init.cpp | 2 +- src/rpc/mempool.cpp | 2 +- src/txmempool.h | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/init.cpp b/src/init.cpp index 1122496539..369d919d23 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -1467,7 +1467,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) } mempool_opts.check_ratio = std::clamp(mempool_opts.check_ratio, 0, 1'000'000); - int64_t descendant_limit_bytes = mempool_opts.limits.descendant_size_vbytes * 40; + int64_t descendant_limit_bytes = maxmempoolMinimumBytes(mempool_opts.limits.descendant_size_vbytes); if (mempool_opts.max_size_bytes < 0 || mempool_opts.max_size_bytes < descendant_limit_bytes) { return InitError(strprintf(_("-maxmempool must be at least %d MB"), std::ceil(descendant_limit_bytes / 1'000'000.0))); } diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index cc119c7d01..f5064c2ef0 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -398,7 +398,7 @@ static RPCHelpMan maxmempool() CTxMemPool& mempool = EnsureAnyMemPool(request.context); LOCK(mempool.cs); - int64_t nMempoolSizeMin = mempool.m_limits.descendant_size_vbytes * 40; + int64_t nMempoolSizeMin = maxmempoolMinimumBytes(mempool.m_limits.descendant_size_vbytes); if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin) throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("MaxMempool size %d is too small", nSize)); mempool.m_max_size_bytes = nSize; diff --git a/src/txmempool.h b/src/txmempool.h index e2d2187add..abbf406046 100644 --- a/src/txmempool.h +++ b/src/txmempool.h @@ -44,6 +44,10 @@ class Chainstate; /** Fake height value used in Coin to signify they are only in the memory pool (since 0.8) */ static const uint32_t MEMPOOL_HEIGHT = 0x7FFFFFFF; +inline int64_t maxmempoolMinimumBytes(const int64_t descendant_size_vbytes) { + return descendant_size_vbytes * 40; +} + /** * Test whether the LockPoints height and time are still valid on the current chain */ From bdb3e2ef9bc3f5a24a38f5749be72c1301b1f111 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 25 Jun 2021 03:03:31 +0000 Subject: [PATCH 4/7] Bugfix: RPC/blockchain: Use int64 for maxmempool param --- src/rpc/mempool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index f5064c2ef0..5530b0b993 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -392,7 +392,7 @@ static RPCHelpMan maxmempool() }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - int nSize = request.params[0].getInt(); + int64_t nSize = request.params[0].getInt(); int64_t nMempoolSizeMax = nSize * 1000000; CTxMemPool& mempool = EnsureAnyMemPool(request.context); From 82a7e194c5c23219b95e06e370f47607ff9cab16 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Fri, 25 Jun 2021 03:11:00 +0000 Subject: [PATCH 5/7] Bugfix: RPC/blockchain: Immediately apply new limit set by maxmempool method --- src/rpc/mempool.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 5530b0b993..bd4fc7ee8a 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ #include #include #include +#include #include #include @@ -396,13 +398,19 @@ static RPCHelpMan maxmempool() int64_t nMempoolSizeMax = nSize * 1000000; CTxMemPool& mempool = EnsureAnyMemPool(request.context); - LOCK(mempool.cs); + LOCK2(cs_main, mempool.cs); int64_t nMempoolSizeMin = maxmempoolMinimumBytes(mempool.m_limits.descendant_size_vbytes); if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin) throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("MaxMempool size %d is too small", nSize)); mempool.m_max_size_bytes = nSize; + auto node_context = util::AnyPtr(request.context); + if (node_context && node_context->chainman) { + Chainstate& active_chainstate = node_context->chainman->ActiveChainstate(); + LimitMempoolSize(mempool, active_chainstate.CoinsTip()); + } + return NullUniValue; } }; From 79118c42b34e3ddde43abb7fa2320e4babf49801 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 6 Dec 2022 01:59:59 +0000 Subject: [PATCH 6/7] Bugfix: RPC/blockchain: Use int32 for maxmempool param range checking Since we immediately multiply by 1000000 without overflow checking, and even 2^31 is unreasonably large, just use int32_t for the range check, and immediately cast to int64 as before --- src/rpc/mempool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index bd4fc7ee8a..6602c2ff0b 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -394,7 +394,7 @@ static RPCHelpMan maxmempool() }, [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue { - int64_t nSize = request.params[0].getInt(); + int64_t nSize = request.params[0].getInt(); int64_t nMempoolSizeMax = nSize * 1000000; CTxMemPool& mempool = EnsureAnyMemPool(request.context); From 233565f1a8c92d355d234533fcbfdfb1100e1544 Mon Sep 17 00:00:00 2001 From: Luke Dashjr Date: Tue, 10 Oct 2023 00:31:56 +0000 Subject: [PATCH 7/7] Bugfix: QA/fuzz: Add maxmempool to RPC_COMMANDS_SAFE_FOR_FUZZING --- src/test/fuzz/rpc.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/fuzz/rpc.cpp b/src/test/fuzz/rpc.cpp index 2578137471..2dbb3fee3c 100644 --- a/src/test/fuzz/rpc.cpp +++ b/src/test/fuzz/rpc.cpp @@ -146,6 +146,7 @@ const std::vector RPC_COMMANDS_SAFE_FOR_FUZZING{ "joinpsbts", "listbanned", "logging", + "maxmempool", "mockscheduler", "ping", "preciousblock",