调用eth_getBalance或eth_getStorageAt,只能得到某个RPC节点声称的数值;如果你不完全信任节点,还需要证明该值确实属于某个区块的状态。eth_getProof把账户字段、账户证明和指定storage slot的证明一起返回,验证者可从可信区块头stateRoot出发,先验证账户,再从账户storageHash验证存储值。
它解决的是“数据如何锚定到状态根”,不是“合约业务逻辑是否安全”。
请求需要固定三类输入
EIP-1186定义的请求包含账户地址、要证明的32字节存储键数组,以及区块参数。只查账户而不查slot时,存储键数组可为空;要验证mapping或变量,必须先按Solidity存储布局计算真实slot。
区块参数若使用latest,连续两次请求可能落在不同区块。生产验证应先选定区块号或实现支持的明确区块语境,再取得同一块的header与stateRoot。
返回对象分成账户和存储两层
| 字段 | 所属层 | 用途 |
|---|---|---|
| balance、nonce | 账户 | 验证余额与交易序号 |
| codeHash | 账户 | 锚定账户代码哈希 |
| storageHash | 账户 | 作为该账户存储树根 |
| accountProof | 状态树 | 从stateRoot证明账户对象 |
| storageProof[].key/value | 存储树 | 标记请求的slot和值 |
| storageProof[].proof | 存储树 | 从storageHash证明该slot |
accountProof与storageProof都是一组RLP编码的Merkle Patricia Trie节点。不能只检查数组非空;必须按路径、节点类型和哈希规则逐层验证。
第一级:从stateRoot到账户
以太坊状态树用keccak(address)派生账户路径。验证器从区块头stateRoot开始,逐个解析accountProof节点,确认父节点引用与路径一致,最终得到包含nonce、balance、storageRoot与codeHash的账户对象。
返回对象中的balance、nonce、storageHash和codeHash应与证明解出的账户一致。若只相信RPC返回的这些明文字段而不解proof,就没有完成独立验证。
第二级:从storageHash到slot
每个storageProof条目对应一个请求键。验证器从已证明账户的storageHash出发,沿该slot的安全Trie路径检查节点,最后得到value。mapping的slot通常需要先对键和声明槽编码后做keccak,数组和结构体也有各自布局;传错键可能得到一个合法的“该位置为空”证明。
不存在也能被证明。证明路径会在无法继续匹配的位置结束,显示目标账户或slot不在Trie中。不能因为value为0就自动判定“证明失败”,零值与不存在需要按Trie规则解释。
可信stateRoot从哪里来
Merkle证明只能把数据锚定到某个根。若stateRoot也来自同一个不可信RPC,节点可以同时伪造根和证明。轻客户端会通过共识验证获得可信header;审计系统也可从多个独立节点或已验证区块来源交叉确认。
区块浏览器适合人工定位,但不能替代信任模型。基础查询方法可参考区块链浏览器怎么用,交易执行证据则见以太坊交易回执怎么看。
latest漂移的具体问题
假设先调用eth_getProof(latest),随后再调用eth_getBlockByNumber(latest)。两次之间如果产生新区块,proof属于旧stateRoot,header却来自新块,验证自然失败。更危险的是程序为“修复”失败而忽略块号,最后接受未锚定数据。
正确顺序是固定区块标识,取得header,记录blockHash与stateRoot,再对同一块请求proof。若RPC接口只接受区块号,还要在返回后确认该高度的hash未因重组变化。
EIP状态与客户端差异
EIP-1186页面目前标记为Stagnant,但eth_getProof已被主要执行客户端采用。历史EIP与当前Execution API、不同客户端在存储键编码和标签支持上可能存在细节差异。实现时应针对目标客户端做兼容测试,不要只把EIP示例复制到生产代码。
合约采用代理时,codeHash证明的是当前账户代码,业务实现可能位于另一个地址;升级权限仍需独立核验。与合约交互前的风险检查可结合连接智能合约前要检查什么。
最小验证清单
- 固定chainId、block number与block hash。
- 从可信来源取得该块stateRoot。
- 计算地址路径和真实storage slot。
- 校验accountProof并解出四字段账户对象。
- 以已证明的storageHash校验每个storageProof。
- 对零值执行不存在证明判断。
- 记录客户端版本、请求参数和原始proof以便复现。
本文用于以太坊状态证明与RPC安全教育,不构成智能合约审计或资产保证。Merkle证明验证实现涉及RLP、Hex-Prefix编码与Trie路径细节,生产系统应使用经过测试的库、官方测试向量和多客户端兼容性测试。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。