RPC 返回值的文档自检:rpcdoccheck 这个调试开关查的是什么
比特币核心的每条 RPC 命令都带着一份机器可读的文档:参数是什么类型、返回值应当长成什么样。平时这份文档只被用来生成 help 文本,但在一个隐藏开关打开时,节点会在每次调用后拿真实返回值和文档逐字段对账。这个开关是 -rpcdoccheck,它的行为边界值得单独讲清楚,因为它很容易被误当成”参数校验开关”。本文以 Bitcoin Core v31.0 源码为准。
先分清两道检查:入参检查一直在,返回检查才有开关
第一道检查不需要任何开关:每条命令执行前,节点把请求参数和文档里声明的类型逐个比对,不匹配就抛出 RPC_TYPE_ERROR,错误文本是”Wrong type passed”加一份逐项列出哪一位参数、叫什么名字、哪里不对的 JSON。任何发行版上这都是无条件行为,这就是为什么给数字参数传了字符串会立刻被挡回来。
第二道检查才是 rpcdoccheck 管的:命令执行完之后,节点拿真实返回的 JSON 去比对文档声明的每一种可能结果形态。全部对得上就放行;对不上就抛出一个内部错误,文本形如 RPC call “xxx” returned incorrect type,后面跟着每个候选结果不匹配的细节;若文档根本没定义可能的结果,还会给出”no possible results defined”。这道检查的成本是每次调用都要遍历结构,所以它不是给生产环境默认开的。
默认值随构建类型变:调试构建才为真
源码里 DEFAULT_RPC_DOC_CHECK 是一个编译期常量:只有在定义了 RPC_DOC_CHECK 宏的构建里为真,而 CMake 把它挂在与 DEBUG 同一组的调试编译定义里。换句话说,官方发行包跑的是非调试构建,rpcdoccheck 的默认值是关;从源码以 Debug 模式构建的开发版本,默认就是开。参数注册时还带着 DEBUG_ONLY 旗标,属于调试类选项,普通帮助里不显眼。这也是为什么有人在生产节点上把它打开后突然看到内部错误——它暴露的往往不是你的调用有问题,而是这个开发版构建在替你抓文档与实现的偏差。
它抓到的是什么级别的 bug
返回类型不符通常来自三种偏差:命令改了新返回字段但文档没同步;条件分支下少给了某个键;把应当是数组的东西在某些状态下返回成了对象。这类问题平时完全静默,因为文档并不参与解析,只有工具链按文档做严格校验时才会撞墙。开启这道自检的贡献者测试与集成测试里尤其有用:测试跑过的每条命令都顺手接受了一次契约审查。
使用建议:把它当开发期显微镜
自建的调试版节点保持默认即可;生产节点如果想开启,先想清楚后果——它抛的是内部错误,一次文档与实现不一致会让那次调用直接失败,而不是打一行警告。给外部脚本做类型防御的正确层次依然是:消费返回值时容忍新增字段、用固定命令加固定参数,而不是指望节点的自检替你兜底。
一个具体的对账例子
假设某开发版节点里,一个新命令在钱包未加载的分支下把返回值里的对象字段退化成了空对象,而文档声明的结构里那个位置必须是一个带键的对象。不开自检时,这个差异要等到下游工具解析报错才暴露,而且报错点离引入点很远;开着 rpcdoccheck,第一次测试跑到这条命令就在服务端现场报出”哪个候选结果、哪个字段、什么类型对不上”。两类错误码的分工也顺便清楚了:入参类型错是调用者的锅,返回类型错是实现或文档的锅——自检开关的价值就在于把后一类锅在编译验证阶段就端出来,而不是留给生产环境的用户去发现。对日常使用官方发行版的读者来说,记住这个参数存在、并且知道它默认关,就足以理解为什么某些开发讨论里会出现”returned incorrect type”这种看起来吓人的内部错误。
风险提示:RPC 行为随版本变化,跨大版本部署脚本前建议重跑一轮调用回归;本文为机制说明,不构成投资建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。