首页
/ Bitcoin Core 内存池 RPC 弃用字段清理:fullrbf 与 bip125-replaceable 键的移除及 -deprecatedrpc 恢复机制

Bitcoin Core 内存池 RPC 弃用字段清理:fullrbf 与 bip125-replaceable 键的移除及 -deprecatedrpc 恢复机制

2026-09-06 13:09:56作者:董斯意

本文围绕 Bitcoin Core 的内存池(mempool)RPC 接口变更展开:自 v28 起 full-RBF 策略成为默认行为、v29 起 -mempoolfullrbf 启动参数被移除之后,getmempoolinfofullrbf 键与四个 mempool RPC 中的 bip125-replaceable 键也随之退出默认响应,仅可通过 -deprecatedrpc=fullrbf / -deprecatedrpc=bip125 显式恢复。读完本篇,你将理解这笔清理的完整来龙去脉、各 RPC 键的源码位置与判定逻辑,以及自动化脚本、监控工具需要做哪些适配。

背景:full-RBF 策略的演进时间线

要理解这次 RPC 变更,先要回顾 full-RBF(不检查 BIP125 替代信号即允许交易替换)策略在 Bitcoin Core 中的三步演进:

  1. v24.0.1 引入开关:新增 mempoolfullrbf 配置项,允许节点改变对未确认交易的替换中继/挖矿策略,默认仍为关闭(即仅接受 BIP125 opt-in RBF)。该选项在 release-notes-24.0.1.md 中有专门章节,解释了部分比特币服务依赖"先看到、后替换"(first-seen)简化假设的历史背景。
  2. v28 默认开启-mempoolfullrbf 默认值由 0 改为 1,即 mempoolfullrbf=1 成为默认策略(#30493),同时有限度的 package RBF 也被启用(#28984)。见 release-notes-28.0.md
  3. v29 移除开关:由于该策略已被广泛采纳,用户关闭它已无实际收益,-mempoolfullrbf 启动参数被彻底移除,full replace-by-fee 成为标准行为(#30592)。见 release-notes-29.0.md

也就是说,在现行代码中节点行为恒等于 full-RBF,不存在可配置的中间状态。策略侧的证据可见 src/validation.cpp 中 RBF 替换检查处的注释:代码明确注明不再检查交易是否通过 BIP125 或 TRUC 主动声明可替换性(src/validation.cpp 第 967 行附近的注释 "we are not checking whether it opts in to replaceability via BIP125 or TRUC"),替换合法性改由集群(cluster)计数上限与费率图(feerate diagram)改进等规则约束,相关实现位于 src/policy/rbf.cpp

本次变更的核心内容

release-notes-34911.md 的描述,本笔变更包含两个部分:

getmempoolinfo 不再默认返回 fullrbf 键

getmempoolinfo RPC 的响应中停止返回已弃用的 fullrbf 键,除非用户通过 -deprecatedrpc=fullrbf 启动参数显式请求。由于 full-RBF 已是唯一行为,该键此前恒为 true,属于无信息量的遗留字段。

四个 mempool RPC 移除 bip125-replaceable 键

bip125-replaceable 键同样从 mempool RPC 响应中移除(它自 v29 起已被标记为 deprecated),除非用户通过 -deprecatedrpc=bip125 启动参数请求恢复。受影响的 mempool RPC 共四个:

RPC 说明 移除的键
getrawmempool 返回内存池全部交易 ID(verbose 模式返回详情) bip125-replaceable
getmempoolancestors 返回指定交易在池中的全部祖先 bip125-replaceable
getmempooldescendants 返回指定交易在池中的全部后代 bip125-replaceable
getmempoolentry 返回指定交易的内存池条目详情 bip125-replaceable

bip125-replaceable 的语义是:该交易自身通过 nSequence 信号声明了 BIP125 可替换性,或者其某个未确认祖先声明了 BIP125 可替换性。在 full-RBF 成为唯一策略后,这一字段不再决定节点是否接受替换,因此从默认可见性中移除是顺理成章的收尾动作。

源码级实现:弃用键如何被条件化返回

IsDeprecatedRPCEnabled 的判定逻辑

两个弃用键的开关都走同一个判定函数,实现位于 src/rpc/server.cpp

bool IsDeprecatedRPCEnabled(const std::string& method)
{
    const std::vector<std::string> enabled_methods = gArgs.GetArgs("-deprecatedrpc");

    return find(enabled_methods.begin(), enabled_methods.end(), method) != enabled_methods.end();
}

可以观察到:-deprecatedrpc 是一个可重复出现的启动参数,每次调用 GetArgs 取回所有值,函数仅做字符串精确匹配。也就是说,恢复 fullrbf 键与恢复 bip125 键是相互独立的,可以只开其一,也可以同时开启。

getmempoolinfo:fullrbf 键的条件分支

getmempoolinfo 的响应体由 MempoolInfoToJSON 构造(src/rpc/mempool.cpp)。在默认情况下,它输出 loadedsizebytesusagetotal_feemaxmempoolmempoolminfeeminrelaytxfeeincrementalrelayfeeunbroadcastcountpermitbaremultisigmaxdatacarriersizelimitclustercountlimitclustersizeoptimal 等字段,末尾是本次变更的条件分支:

if (IsDeprecatedRPCEnabled("fullrbf")) {
    ret.pushKV("fullrbf", true);
}

注意 fullrbf 的值被硬编码为 true——这与"full-RBF 已是唯一行为"的事实一致。RPC 元数据(RPCResult 描述,供 help 输出与接口文档生成)也做了同样的条件化,见 src/rpc/mempool.cpp:仅当启用 fullrbf 弃用开关时,fullrbf 字段描述("True if the mempool accepts RBF without replaceability signaling inspection (DEPRECATED)")才会出现在结果 schema 中。

四个 RPC 共享 MempoolEntryDescription 与 entryToJSON

四个受影响的 RPC 之所以行为一致,是因为它们共享同一套条目序列化代码:

  • RPC 元数据层MempoolEntryDescription()bip125-replaceable 字段描述被包裹在 if (IsDeprecatedRPCEnabled("bip125")) 分支内(src/rpc/mempool.cpp)。getrawmempool(verbose=true)、getmempoolancestorsgetmempooldescendantsgetmempoolentryRPCResult 均引用该描述函数,因此一个条件控制四处的 schema。
  • 实际响应层entryToJSON() 负责把 CTxMemPoolEntry 序列化为 JSON,其末尾的 RBF 状态段同样条件化(src/rpc/mempool.cpp):
// Add opt-in RBF status
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);
}

这段代码还保留了一个历史遗留的防御:若交易不在内存池中(IsRBFOptIn 返回 UNKNOWN),会抛出 RPC_MISC_ERROR。正常调用路径下 getmempoolentry 等 RPC 会先校验 txid 在池中,因此该分支实际不会触发。

bip125-replaceable 的判定原理

即便显式恢复了该键,理解其判定逻辑也有助于正确解读旧脚本的输出。判定函数 IsRBFOptIn 位于 src/policy/rbf.cpp,在持有内存池锁的前提下执行:

  1. 先查交易自身:调用 SignalsOptInRBF(tx),若任一输入的 nSequence <= MAX_BIP125_RBF_SEQUENCE 则视为主动声明。该常数是 0xfffffffd(即 SEQUENCE_FINAL - 2),定义于 src/util/rbf.h,也是 send/createrawtransaction 等 RPC 默认使用的"replaceable"序列号(src/wallet/rpc/spend.cppm_signal_bip125_rbf 为真时即写入该值)。
  2. 交易不在本地内存池则返回 UNKNOWN:无法确认其所有输入来源时不做臆断。
  3. 检查未确认祖先:交易自身所有输入 nSequence >= maxint-1 时,仍可能因为其某个未确认祖先声明了 RBF 而被视为可替换(BIP125 的"继承"语义)。

返回的三态枚举(FINAL / REPLACEABLE_BIP125 / UNKNOWN)定义于 src/policy/rbf.hentryToJSON 只把 REPLACEABLE_BIP125 映射为 JSON 布尔 true,其余映射为 false

实操:如何恢复旧字段并验证

启动参数写法

bitcoind 命令行或 bitcoin.conf 中使用(可重复指定以同时恢复多个字段):

-bitcoind -deprecatedrpc=fullrbf
bitcoind -deprecatedrpc=fullrbf -deprecatedrpc=bip125
  • 只开 -deprecatedrpc=fullrbfgetmempoolinfo 恢复 fullrbf 键,四个 mempool 条目 RPC 仍不返回 bip125-replaceable
  • 只开 -deprecatedrpc=bip125:四个 mempool 条目 RPC 恢复 bip125-replaceable 键,getmempoolinfo 仍无 fullrbf
  • 注意该机制是节点级的,无法按单次 RPC 调用切换;需要旧字段的消费方必须在启动参数层面固定开启。

验证方式

可以运行内置功能测试 test/functional/feature_rbf.py,其测试参数即为 self.extra_args = [["-deprecatedrpc=fullrbf", "-deprecatedrpc=bip125"], []],正是本变更配套的回归验证:它依赖两个弃用键同时可用来断言旧响应结构,确保恢复路径仍然工作。本地复现可用 CMake 构建后通过 ctest 执行该测试(构建方式见 INSTALL.md)。

迁移建议

  • 只读取字段的脚本(如监控 getmempoolinfo 的 Grafana 面板、依赖 bip125-replaceable 做 RBF 状态判断的钱包工具):优先改为不依赖这两个字段——full-RBF 下 fullrbf 恒为 truebip125-replaceable 也不影响替换是否被接受;如必须兼容,则在服务启动参数中加 -deprecatedrpc=fullrbf / -deprecatedrpc=bip125,并留意这两个键在后续版本中可能进一步移除。
  • 做 RBF 状态判断的客户端:可以推断,在 full-RBF 节点上更有意义的信号是费率图(getmempoolfeeratediagram)与集群/分块(chunk)信息,而非单条交易的 BIP125 声明;entryToJSON 保留的 feeschunkweightchunks 等字段不受本次变更影响。
  • 关联变更提醒:同一批次还有钱包侧的姊妹变更(release-notes-34917.md):listtransactionslistsinceblockgettransaction 等钱包交易 RPC 中的 bip125-replaceable 键同样标记弃用,仍可通过同一个 -deprecatedrpc=bip125 恢复;-walletrbf 启动选项也已弃用且将在下个版本移除,使用时会在日志中产生警告。注意钱包侧与 mempool 侧共用 bip125 这一个开关名,开启后两处同时恢复。

小结

本次变更(doc/release-notes-34911.md)是 full-RBF 策略落地后的收尾工作:v24.0.1 引入开关、v28 默认开启、v29 移除参数之后,RPC 响应里最后残留的 fullrbfbip125-replaceable 两个弃用键也退出了默认可见性。核心实现集中在 src/rpc/mempool.cppMempoolInfoToJSONentryToJSON 的条件分支)和 src/rpc/server.cppIsDeprecatedRPCEnabled 通用开关),行为回归由 test/functional/feature_rbf.py 覆盖。对下游工具而言,影响面是"两个 JSON 键消失",恢复路径明确且粒度独立,迁移成本可控;但弃用键不应作为长期依赖,建议借机将监控与自动化脚本改为基于费率图、集群信息等 full-RBF 时代的正式字段。

登录后查看全文
热门项目推荐
相关项目推荐