From f89d18c3b1c750150832eceb854d97c436d4c8cc Mon Sep 17 00:00:00 2001 From: rkrux Date: Fri, 24 Apr 2026 14:07:34 +0530 Subject: [PATCH 1/3] rpc, mempool: rpcdeprecate `fullrbf` key in getmempoolinfo RPC response mempoolfullrbf=1 behaviour has been the default since v28 and the argument has been removed since v29 subsequently. The getmempoolinfo RPC need not return the deprecated `fullrbf` key in the response anymore unless the user requests it via -deprecatedrpc=fullrbf node argument. --- src/rpc/mempool.cpp | 46 ++++++++++++++++++++-------------- test/functional/feature_rbf.py | 1 + 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 1a94d10bf9f..1b76f7d858a 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -1055,12 +1055,14 @@ UniValue MempoolInfoToJSON(const CTxMemPool& pool) ret.pushKV("minrelaytxfee", ValueFromAmount(pool.m_opts.min_relay_feerate.GetFeePerK())); ret.pushKV("incrementalrelayfee", ValueFromAmount(pool.m_opts.incremental_relay_feerate.GetFeePerK())); ret.pushKV("unbroadcastcount", pool.GetUnbroadcastTxs().size()); - ret.pushKV("fullrbf", true); ret.pushKV("permitbaremultisig", pool.m_opts.permit_bare_multisig); ret.pushKV("maxdatacarriersize", pool.m_opts.max_datacarrier_bytes.value_or(0)); ret.pushKV("limitclustercount", pool.m_opts.limits.cluster_count); ret.pushKV("limitclustersize", pool.m_opts.limits.cluster_size_vbytes); ret.pushKV("optimal", pool.m_txgraph->DoWork(0)); // 0 work is a quick check for known optimality + if (IsDeprecatedRPCEnabled("fullrbf")) { + ret.pushKV("fullrbf", true); + } return ret; } @@ -1071,24 +1073,30 @@ static RPCHelpMan getmempoolinfo() {}, RPCResult{ RPCResult::Type::OBJ, "", "", - { - {RPCResult::Type::BOOL, "loaded", "True if the initial load attempt of the persisted mempool finished"}, - {RPCResult::Type::NUM, "size", "Current tx count"}, - {RPCResult::Type::NUM, "bytes", "Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted"}, - {RPCResult::Type::NUM, "usage", "Total memory usage for the mempool"}, - {RPCResult::Type::STR_AMOUNT, "total_fee", "Total fees for the mempool in " + CURRENCY_UNIT + ", ignoring modified fees through prioritisetransaction"}, - {RPCResult::Type::NUM, "maxmempool", "Maximum memory usage for the mempool"}, - {RPCResult::Type::STR_AMOUNT, "mempoolminfee", "Minimum fee rate in " + CURRENCY_UNIT + "/kvB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee"}, - {RPCResult::Type::STR_AMOUNT, "minrelaytxfee", "Current minimum relay fee for transactions"}, - {RPCResult::Type::NUM, "incrementalrelayfee", "minimum fee rate increment for mempool limiting or replacement in " + CURRENCY_UNIT + "/kvB"}, - {RPCResult::Type::NUM, "unbroadcastcount", "Current number of transactions that haven't passed initial broadcast yet"}, - {RPCResult::Type::BOOL, "fullrbf", "True if the mempool accepts RBF without replaceability signaling inspection (DEPRECATED)"}, - {RPCResult::Type::BOOL, "permitbaremultisig", "True if the mempool accepts transactions with bare multisig outputs"}, - {RPCResult::Type::NUM, "maxdatacarriersize", "Maximum number of bytes that can be used by OP_RETURN outputs in the mempool"}, - {RPCResult::Type::NUM, "limitclustercount", "Maximum number of transactions that can be in a cluster (configured by -limitclustercount)"}, - {RPCResult::Type::NUM, "limitclustersize", "Maximum size of a cluster in virtual bytes (configured by -limitclustersize)"}, - {RPCResult::Type::BOOL, "optimal", "If the mempool is in a known-optimal transaction ordering"}, - }}, + [](){ + std::vector list = { + {RPCResult::Type::BOOL, "loaded", "True if the initial load attempt of the persisted mempool finished"}, + {RPCResult::Type::NUM, "size", "Current tx count"}, + {RPCResult::Type::NUM, "bytes", "Sum of all virtual transaction sizes as defined in BIP 141. Differs from actual serialized size because witness data is discounted"}, + {RPCResult::Type::NUM, "usage", "Total memory usage for the mempool"}, + {RPCResult::Type::STR_AMOUNT, "total_fee", "Total fees for the mempool in " + CURRENCY_UNIT + ", ignoring modified fees through prioritisetransaction"}, + {RPCResult::Type::NUM, "maxmempool", "Maximum memory usage for the mempool"}, + {RPCResult::Type::STR_AMOUNT, "mempoolminfee", "Minimum fee rate in " + CURRENCY_UNIT + "/kvB for tx to be accepted. Is the maximum of minrelaytxfee and minimum mempool fee"}, + {RPCResult::Type::STR_AMOUNT, "minrelaytxfee", "Current minimum relay fee for transactions"}, + {RPCResult::Type::NUM, "incrementalrelayfee", "minimum fee rate increment for mempool limiting or replacement in " + CURRENCY_UNIT + "/kvB"}, + {RPCResult::Type::NUM, "unbroadcastcount", "Current number of transactions that haven't passed initial broadcast yet"}, + {RPCResult::Type::BOOL, "permitbaremultisig", "True if the mempool accepts transactions with bare multisig outputs"}, + {RPCResult::Type::NUM, "maxdatacarriersize", "Maximum number of bytes that can be used by OP_RETURN outputs in the mempool"}, + {RPCResult::Type::NUM, "limitclustercount", "Maximum number of transactions that can be in a cluster (configured by -limitclustercount)"}, + {RPCResult::Type::NUM, "limitclustersize", "Maximum size of a cluster in virtual bytes (configured by -limitclustersize)"}, + {RPCResult::Type::BOOL, "optimal", "If the mempool is in a known-optimal transaction ordering"}, + }; + if (IsDeprecatedRPCEnabled("fullrbf")) { + list.emplace_back(RPCResult::Type::BOOL, "fullrbf", "True if the mempool accepts RBF without replaceability signaling inspection (DEPRECATED)"); + } + return list; + }() + }, RPCExamples{ HelpExampleCli("getmempoolinfo", "") + HelpExampleRpc("getmempoolinfo", "") diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py index a2c8cb606e0..5527f7a946c 100755 --- a/test/functional/feature_rbf.py +++ b/test/functional/feature_rbf.py @@ -28,6 +28,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 self.uses_wallet = None + self.extra_args = [["-deprecatedrpc=fullrbf"], []] def run_test(self): self.wallet = MiniWallet(self.nodes[0]) From 1a85ca1dff1f51561608ab463dee4d03912291d9 Mon Sep 17 00:00:00 2001 From: rkrux Date: Fri, 24 Apr 2026 14:18:39 +0530 Subject: [PATCH 2/3] rpc, mempool: rpcdeprecate `bip125-replaceable` key in mempool RPCs reponses RPCs: getrawmempool, getmempoolancestors, getmempooldescendants, getmempoolentry This key has been marked deprecated since v29, it can be removed from the RPC response now unless the user requests it via the -deprecatedrpc=bip125 node argument. --- src/rpc/mempool.cpp | 26 +++++++++++++++----------- test/functional/feature_rbf.py | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/rpc/mempool.cpp b/src/rpc/mempool.cpp index 1b76f7d858a..e762c6ab9ba 100644 --- a/src/rpc/mempool.cpp +++ b/src/rpc/mempool.cpp @@ -430,7 +430,7 @@ static std::vector ClusterDescription() static std::vector MempoolEntryDescription() { - return { + std::vector list = { RPCResult{RPCResult::Type::NUM, "vsize", "virtual transaction size as defined in BIP 141. This is different from actual serialized size for witness transactions as witness data is discounted."}, RPCResult{RPCResult::Type::NUM, "weight", "transaction weight as defined in BIP 141."}, RPCResult{RPCResult::Type::NUM_TIME, "time", "local time transaction entered pool in seconds since 1 Jan 1970 GMT"}, @@ -453,9 +453,12 @@ static std::vector MempoolEntryDescription() {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "parent transaction id"}}}, RPCResult{RPCResult::Type::ARR, "spentby", "unconfirmed transactions spending outputs from this transaction", {RPCResult{RPCResult::Type::STR_HEX, "transactionid", "child transaction id"}}}, - RPCResult{RPCResult::Type::BOOL, "bip125-replaceable", "Whether this transaction signals BIP125 replaceability or has an unconfirmed ancestor signaling BIP125 replaceability. (DEPRECATED)\n"}, RPCResult{RPCResult::Type::BOOL, "unbroadcast", "Whether this transaction is currently unbroadcast (initial broadcast not yet acknowledged by any peers)"}, }; + if (IsDeprecatedRPCEnabled("bip125")) { + list.emplace_back(RPCResult::Type::BOOL, "bip125-replaceable", "Whether this transaction signals BIP125 replaceability or has an unconfirmed ancestor signaling BIP125 replaceability. (DEPRECATED)\n"); + } + return list; } void AppendChunkInfo(UniValue& all_chunks, FeePerWeight chunk_feerate, std::vector chunk_txs) @@ -554,18 +557,19 @@ static void entryToJSON(const CTxMemPool& pool, UniValue& info, const CTxMemPool } info.pushKV("spentby", std::move(spent)); + info.pushKV("unbroadcast", pool.IsUnbroadcastTx(tx.GetHash())); // Add opt-in RBF status - bool rbfStatus = false; - RBFTransactionState rbfState = IsRBFOptIn(tx, pool); - if (rbfState == RBFTransactionState::UNKNOWN) { - throw JSONRPCError(RPC_MISC_ERROR, "Transaction is not in mempool"); - } else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125) { - rbfStatus = true; + if (IsDeprecatedRPCEnabled("bip125")) { + bool rbfStatus = false; + RBFTransactionState rbfState = IsRBFOptIn(tx, pool); + if (rbfState == RBFTransactionState::UNKNOWN) { + throw JSONRPCError(RPC_MISC_ERROR, "Transaction is not in mempool"); + } else if (rbfState == RBFTransactionState::REPLACEABLE_BIP125) { + rbfStatus = true; + } + info.pushKV("bip125-replaceable", rbfStatus); } - - info.pushKV("bip125-replaceable", rbfStatus); - info.pushKV("unbroadcast", pool.IsUnbroadcastTx(tx.GetHash())); } UniValue MempoolToJSON(const CTxMemPool& pool, bool verbose, bool include_mempool_sequence) diff --git a/test/functional/feature_rbf.py b/test/functional/feature_rbf.py index 5527f7a946c..b26d59ab5d7 100755 --- a/test/functional/feature_rbf.py +++ b/test/functional/feature_rbf.py @@ -28,7 +28,7 @@ class ReplaceByFeeTest(BitcoinTestFramework): def set_test_params(self): self.num_nodes = 2 self.uses_wallet = None - self.extra_args = [["-deprecatedrpc=fullrbf"], []] + self.extra_args = [["-deprecatedrpc=fullrbf", "-deprecatedrpc=bip125"], []] def run_test(self): self.wallet = MiniWallet(self.nodes[0]) From 8deed0df066ef2cbb6f51de4075c891a48b8debd Mon Sep 17 00:00:00 2001 From: rkrux Date: Fri, 24 Apr 2026 14:34:17 +0530 Subject: [PATCH 3/3] doc: add release notes for PR 34911 --- doc/release-notes-34911.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 doc/release-notes-34911.md diff --git a/doc/release-notes-34911.md b/doc/release-notes-34911.md new file mode 100644 index 00000000000..43520296726 --- /dev/null +++ b/doc/release-notes-34911.md @@ -0,0 +1,12 @@ +### Mempool + +mempoolfullrbf=1 behaviour has been the default since v28 and the argument has +been removed since v29 subsequently. The `getmempoolinfo` RPC stops returning the +deprecated `fullrbf` key in the response unless the user requests it via the +`-deprecatedrpc=fullrbf` node argument. + +Also, the `bip125-replaceable` key is removed from the mempool RPCs +responses (because it, too, has been deprecated since v29) unless the user +requests it via `-deprecatedrpc=bip125` node argument. Affected mempool RPCs +are `getrawmempool`, `getmempoolancestors`, `getmempooldescendants`, and +`getmempoolentry`.