eth_getProof如何验证账户和存储值? 图 1
eth_getProof如何验证账户和存储值? · 图 1

调用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证明的是当前账户代码,业务实现可能位于另一个地址;升级权限仍需独立核验。与合约交互前的风险检查可结合连接智能合约前要检查什么

最小验证清单

  1. 固定chainId、block number与block hash。
  2. 从可信来源取得该块stateRoot。
  3. 计算地址路径和真实storage slot。
  4. 校验accountProof并解出四字段账户对象。
  5. 以已证明的storageHash校验每个storageProof。
  6. 对零值执行不存在证明判断。
  7. 记录客户端版本、请求参数和原始proof以便复现。

本文用于以太坊状态证明与RPC安全教育,不构成智能合约审计或资产保证。Merkle证明验证实现涉及RLP、Hex-Prefix编码与Trie路径细节,生产系统应使用经过测试的库、官方测试向量和多客户端兼容性测试。