用 getblock 看区块详情的人都知道 verbosity 分档:0 返回整块十六进制原文,1 给元数据加交易哈希列表,2 把每笔交易展开成完整对象,3 再补上每个输入的 prevout 细节。但 Bitcoin Core v31.0 在这套阶梯上做了一个小手术:从 verbosity 1 到 3,返回值里多了一个独立的 coinbase_tx 对象,专门放铸币交易的关键字段。这个新增看起来是便利品,实际省掉的流量比想象大。这篇讲清这个对象里有什么、为什么单独为第一笔交易开小灶、以及它和原有各档的关系。
先看 coinbase_tx 对象的内容。按 v31.0 源码 rpc/blockchain.cpp 的结果声明,它有五个字段:version(铸币交易版本号)、locktime(nLockTime)、sequence(第一个输入的序列号)、coinbase(第一个输入的脚本,即 coinbase 脚本,十六进制)、witness(第一个输入的第一个见证元素,存在时给出,十六进制)。正好覆盖分析铸币交易的常用字段清单——矿机签名与额外随机数(extranonce)在 coinbase 脚本里,合并挖矿承诺与隔离见证承诺在 witness 里,版本与高度编码规则(BIP34 把区块高度写进脚本前几个字节)也都从这些字段可推。顺带说明:v31 同期给 IPC 挖矿接口做了配套的 CoinbaseTx 结构化返回,“铸币交易从字节团升级为结构化对象”是这个版本的一致方向。
为什么单独为它开口子?因为铸币交易在结构上是区块里唯一的”非数据载体”:它没有真实输入,却常被协议扩展塞进各种承诺数据;分析挖矿行为、核对矿池署名、验证合并挖矿的 coinbase 承诺时,你几乎永远只需要这”第一笔交易”。在没有这个字段之前,拿到这些信息的姿势很别扭:verbosity 1 只给交易哈希列表,仍然定位不到脚本内容;要拿完整交易对象得升到 verbosity 2 甚至 3,一个接近四百万权重上限的大区块,JSON 轻松到几十兆;verbosity 0 给整块十六进制,还要客户端自己反序列化定位第一笔;或者用 getblockheader 加 getrawtransaction 单独再拉。v31 的做法是把最高频的那几列直接塞进任何一档返回里:你查一个区块的元信息,顺手就免费拿到矿机指纹,无需第二次调用。源码实现也印证了轻量:blockToJSON 里对第一笔交易走的是专门的精简序列化函数,只输出上述五列,而不是完整交易对象。
用起来的注意点有几条。第一,它出现在 verbosity 1、2、3 三档的顶层返回中(v31.0 发行说明的口径),而 verbosity 0 那一档只返回序列化十六进制字符串、没有任何结构化字段;另外 witness 字段本身是可选的(铸币输入没有见证时不出现),做字段解析要按可选处理。第二,它是只读元数据,不会改变你这台节点验证过的东西:coinbase 承诺是否合法的共识校验发生在更早的验证阶段,这个字段只是把已经验过的内容展示出来。第三,想核对脚本内容时记住编码差异:coinbase 字段是脚本的十六进制原文。BIP34 生效后的主网区块里,脚本以一个压操作码开头,压入按小端编码的区块高度——在当前高度区间是 3 个字节(直到高度接近 2 的 24 次方才需要 4 字节),之后才是矿池自己填的额外数据,解析 extranonce 前先按这个结构对齐。第四,这也是 v31 新增:给混合版本节点群写分析脚本时,先探测返回值里有没有 coinbase_tx 键再依赖它;旧版本上你得退回 verbosity 1 加全量交易对象的路子。
一句话总结这次手术的性质:它没有改变任何共识或接口语义,只是给一个”每次都要用、每档都缺”的字段开了固定窗口。接口演进的常见方式——不删旧档、只加新键——在 RPC 兼容性上是对下游最友好的路径,这次是个标准示范。
风险提示:区块与交易分析脚本依赖 RPC 字段时请注意版本兼容设计,避免把可选字段当必然存在;本文不构成投资建议。

发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。