没被批准的 RPC 宪法:EIP-1474 与 eth_ 方法名的事实标准 图 1
没被批准的 RPC 宪法:EIP-1474 与 eth_ 方法名的事实标准 · 图 1

钱包调用节点时写的每一个 eth_call、eth_getBalance、eth_sendRawTransaction,都没有一条被正式批准的”法律”规定它们必须存在、参数长什么样。这段空白的来历值得讲一遍。

一次认真的立法尝试

2018 年 10 月,Paul Bouchon 与 Erik Marks 提交了 EIP-1474,Interface 类别,动机写得很直白:当时的各款客户端暴露的 RPC 方法互不兼容,而以太坊从没有一份正式的 RPC 规范。这份文件试图把节点该实现的方法集合定义齐,并严格规定参数类型。它把值分成两族:Quantity 必须十六进制编码、带 0x 前缀、每字节用最少的位数表达,零必须写成 0x0——0x00 这种带前导零的写法被判非法,空串 0x 同样非法;Data 则是保持原样的十六进制字节,允许 0x 表示空。需要指定区块的方法(余额、存储、nonce、代码、调用、证明这一族)引用 EIP-1898 的写法,允许用区块哈希或区块高度二选一。

没被批准的 RPC 宪法:EIP-1474 与 eth_ 方法名的事实标准 图 2
没被批准的 RPC 宪法:EIP-1474 与 eth_ 方法名的事实标准 · 图 2

为什么它没有活下来

EIP-1474 从未走完批准流程,今天在 EIP 仓库里的状态是 Stagnant。原因不在文本质量,而在形态:它是一份静态文档。RPC 接口是每天都在长新方法的活物,一份需要逐条修订的规格书天然追不上实现,客户端团队也没有义务按它对齐。接管这件事的是 ethereum/execution-apis 仓库——其 README 的原话是,以太坊 JSON-RPC 是所有执行层客户端都实现的一组标准方法集合,是用户与网络之间的规范接口,让下游工具可以把不同客户端当成可互换的模块。关键差别在于形态:仓库里每个方法都有对应的结构化规格文件,配套测试目录,贡献流程要求改动兼容 OpenRPC 格式、能通过自动生成的跨客户端测试;新方法的增删要有 EIP 编号走流程。规范从”一篇文章”变成了”一套持续运行的契约”。仓库的贡献者指南里还有一条经验法则点破了节奏来源:新方法因协议演进而生——EIP-2930 让访问清单查询有了入口,EIP-1559 让 eth_feeHistory 成为必需,协议每长一块新数据,接口层就得补一个取数通道。先问需求、再开方法、最后进契约,这正是静态文档型标准做不到的循环。

类型纪律留下的遗产

立法虽败,类型纪律留了下来。Quantity 与 Data 的分界至今写在 execution-apis 的规格里,也是新手调 RPC 最容易翻车的地方:同样是”0x 开头的数”,余额、区块号、gas 用量走 Quantity 规则——必须用最少的位数、不许前导零、零必须写成 0x0;交易哈希、调用数据走 Data 规则——每字节必须两个十六进制位、0x 是合法的空数据而 0x0 反而是非法的。两个规则互为镜像,把区块号写成带前导零的形式、或者把哈希写成奇数位,都能让同一份代码在不同客户端上给出不同脸色。EIP-1474 的示例表当年逐条枚举了这些合法与非法的组合,今天回看,那张表比它所在提案本身活得更久。

用户今天看到的边界

正因为有跨客户端测试压着,eth_call、nonce 查询、余额查询这些核心方法在 Geth、Nethermind、Erigon 上的行为与错误码基本可互换,换节点商不用重写调用层。但法外之地依然存在:eth_subscribe 这族推送订阅只在 WebSocket 通道存在,HTTP 端点调用它会直接失败;trace_ 家族长期是 Geth 方言,debug_ 系列同理;各服务商私有的加速、资产聚合方法更是无标可依。判断某个方法能不能依赖,比查文档更硬的办法是看它在 execution-apis 仓库有没有对应的 schema 与测试文件——有,才是跨客户端标准;没有,就把它当厂商扩展,换厂商时准备重写。另外注意,这份仓库的标准不覆盖共识层:信标链的 API 在另一套规范里,两者端口、命名、鉴权都不同。本文只讨论接口机制,不构成任何投资建议。