getpeerinfo 少了 startingheight:v31 的 deprecatedrpc 门闩与三步弃用 图 1
getpeerinfo 少了 startingheight:v31 的 deprecatedrpc 门闩与三步弃用 · 图 1

写比特币节点监控脚本的人,迟早会碰到 getpeerinfo 返回值的一次”静默变化”:某个一直能读到的字段突然没了,解析代码拿到空值。Bitcoin Core v31.0 就对 getpeerinfo 动了一次这样的刀——startingheight 字段默认不再返回,必须显式启动 -deprecatedrpc=startingheight 才能继续看到它,而发行说明同时预告:下一个大版本它将彻底移除。这篇讲清这个字段原本是什么、为什么被废弃、以及依赖它的脚本该怎么办。

先还原 startingheight 的原意。两台节点建立 P2P 连接时,version 消息里会各带一个起始块高度,表示”我在握手那一刻同步到哪一身高”。getpeerinfo 的 startingheight 就是这个握手高度的回显。它历史上被用于两类判断:一是粗略估计对端是不是落后很多(握手高度远低于我的高度,可能是轻节点、旧节点或还在追赶的节点);二是排障时确认”这台对端连上来的起点是哪天”。问题出在两个字:过时、误导。握手发生在连接建立那一刻,之后对端会持续同步,这个字段永远停在连接建立时的值——把它当作”对端当前高度”来用,本身就是一个常见误读;而且连接活过几天之后,这个数字的可信度越来越低。更麻烦的是,网络里大量对端是带隐私设置的实现,握手高度可能故意虚报或含糊,拿它做监控阈值会得出噪声结论。

v31.0 的处理方式是典型的三步弃用:先标废弃、再默认隐藏、最后删除。源码 rpc/net.cpp 的结果声明里,startingheight 被注明”DEPRECATED,仅当配置了 -deprecatedrpc=startingheight 才返回”;实现上用一个 IsDeprecatedRPCEnabled 的开关包住字段写入。也就是说,v31 里默认调用 getpeerinfo 看不到这个键,但字段没有消失,只是被收进了带门闩的抽屉。注意 -deprecatedrpc 本身的定位:它在参数解析里是 DEBUG_ONLY 类别,意思是”这是调试和过渡工具,不是给你长期跑生产的功能开关”,发行说明也明说下个主要版本移掉。所以这个开关是逃生舱,不是长期方案。

如果你的脚本在读 startingheight,正确姿势分三层。第一层是立即改用替代信号:想知道对端当前同步到哪,getpeerinfo 里持续更新的 synced_headerssynced_blocks(本机与该对端已共同确认的最后一个区块头/区块高度)才是活口径;想判断对端是不是旧软件,useragent 字段更直接;想监控连接健康,ping/pong 时延与最后活跃时间才是稳的指标。第二层是防御式解析:从 v31 起把 startingheight 当”可能不存在的可选键”处理,取不到时用默认值继续,而不是让整条流水线因为 KeyError 崩掉——这次是一个字段,以后还会有别的,RPC 输出的稳定性声明从来不是”永远不删字段”。第三层是过渡期的临时兼容:确实需要旧字段跑对照迁移时,短暂加 -deprecatedrpc=startingheight 启动,并在迁移窗口结束后删掉——把它长期写进生产配置,等于把技术债钉死在启动参数里。

再补一个容易被忽视的对照实验方法:升级前后各抓一次 getpeerinfo 的完整 JSON,把两份返回的键集合做差集,一次性找出这台机器上所有被隐藏或新增的字段,比逐条读发行说明更快也更不容易漏——RPC 输出的字段增删散落在各处文档里,键集合差集是唯一不会说谎的口径。同样的手法也适用于 wallet、mempool 类 RPC 的版本升级验证。

给监控从业者一个版本时间线备忘:v31.0 起默认隐藏、可用开关恢复;下一个主要版本(v32 及之后)完全移除、开关也救不回来。这个口径来自 v31.0 发行说明原文,属于软件接口策略而非共识规则,不同发行版分支可能提前或推迟执行。另外提醒:-deprecatedrpc 只影响 RPC 层的行为,不会让你绕过任何共识或政策校验,别把它和调试后门混淆。

风险提示:监控脚本的字段容错设计关系到告警系统能否长期可信,请定期复审所依赖 RPC 字段的版本兼容性;本文不构成投资建议。

getpeerinfo 少了 startingheight:v31 的 deprecatedrpc 门闩与三步弃用 图 2
getpeerinfo 少了 startingheight:v31 的 deprecatedrpc 门闩与三步弃用 · 图 2