news 2026/9/15 15:25:02

EIP-7792 可验证日志:用链上日志累积器让 eth_getLogs 响应可验证

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
EIP-7792 可验证日志:用链上日志累积器让 eth_getLogs 响应可验证

EIP-7792 可验证日志:用链上日志累积器让 eth_getLogs 响应可验证

【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs

本指南以仓库中的 EIPS/eip-7792.md 为蓝本,系统讲解如何通过一个位于固定地址、无代码的"日志累积合约",将每个区块产生的日志承诺增量地写入状态存储,从而让钱包在不必信任数据提供商的前提下,高效验证eth_getLogs返回结果的正确性与完整性。读完本文,你将掌握其存储布局、SSZ 数据结构、累积算法伪代码、blockTimestamp字段扩展以及完整的四步验证流程,并理解它为何选择在元数据中记录区块号与交易索引而非区块哈希。

背景:为什么eth_getLogs的响应需要可验证

eth_getLogs是钱包获取某个账户或某个主题(topic)相关交易历史的核心 JSON-RPC 端点。然而在默认情况下,它的响应来自钱包所连接的数据提供商(节点),响应是否正确且完整(没有被省略、没有夹带无关日志)完全依赖提供商的诚信。

在 EIP-7792 出现之前,唯一可用的验证手段是:钱包自行获取所有相关区块头,再逐一对照日志布隆过滤器(logs bloom)做存在性检查。这一机制存在两个根本性问题:

  1. 误报率高:布隆过滤器本质上是概率性数据结构,命中并不代表日志真的存在,验证结论不可靠;
  2. 网络往返过多:为验证一段跨区块范围的日志,需要逐个拉取区块头,涉及不切实际的大量 RPC 往返,实践中难以落地。

EIP-7792(标题为Verifiable logs,状态Stagnant,类型为 Standards Track / Core,创建于 2024-10-21,作者包括 Etan Kissling、Gajinder Singh 与 Vitalik Buterin)正是为此定义了一个替代机制:以增量、高效的方式验证eth_getLogs响应的正确性与完整性。根据仓库中的 EIPS/eip-1.md 对 EIP 状态的说明,Stagnant表示该提案在 Draft/Review/Last Call 阶段超过 6 个月无活动而被暂时搁置,但仍可被作者或编辑恢复,读者应将其视为一份处于早期设计阶段的技术方案而非已定稿的协议标准。

方案总览

EIP-7792 的核心思路可以概括为一句话:让日志的可验证性从"下载区块头查布隆过滤器"转变为"在链上增量累积日志承诺(commitment),再用 Merkle 证明去校验累积结果"

具体包含三个组成部分:

  • 链上日志累积器(Log Accumulator):每个区块执行完所有交易后,将该区块所有日志的承诺写入一个固定地址LOG_CONTRACT_ADDRESS的存储槽中;
  • SSZ 结构化日志条目:为每条日志附加区块时间戳、区块号、交易索引等元数据,形成统一的LogEntry结构,其根即被累积;
  • 扩展的 JSON-RPC 与验证流程eth_getLogs响应新增blockTimestamp字段,配合区块头与eth_getProof完成端到端校验。

配置:日志累积合约地址

规范首先定义了一个全协议统一的常量:

| 名称 | 值 | | - | - | |LOG_CONTRACT_ADDRESS|0xfffffffffffffffffffffffffffffffffffffffe|

该地址上的"合约"实际上没有任何代码(no code),它仅仅作为状态存储的载体存在。之所以要用这种形式,是因为它复用了以太坊世界状态(state trie)中现成的存储证明能力——eth_getProof可以直接对该地址的存储槽生成 Merkle 证明,而无需引入新的密码学原语。

日志累积:存储布局与累积算法

存储布局与 EIP-158 防护

在区块内所有交易执行完毕后,该区块产生的所有日志承诺都会被累积到LOG_CONTRACT_ADDRESS的存储中。存储布局由三个mapping类型的槽位构成:

| 名称 | 槽位 | 类型 | | - | - | - | |LOG_ADDRESS_STORAGE_SLOT|0|mapping(address => bytes32)| |LOG_TOPICS_STORAGE_SLOT|1|mapping(bytes32 => bytes32)| |LOG_ADDRESS_TOPICS_STORAGE_SLOT|2|mapping(bytes32 => bytes32)|

三个槽位分别服务于三种过滤场景:仅按address过滤、仅按topics过滤、按address+topics组合过滤。

一个容易被忽略但至关重要的细节是:合约的 nonce 必须在首次写入时被设为1。原因在于 EIPS/eip-158.md(State clearing)规定:当一次状态变更使账户变为"空账户"(nonce=0、balance=0、code 为空、storage 为空)时,该账户会被直接删除。日志累积合约虽然只有存储没有代码,但如果它的 nonce 保持为 0,那么在某个区块没有产生任何日志(没有写入)时,它就会满足空账户条件而被清理,从而导致累积状态丢失。将 nonce 预置为 1 可以确保该账户始终"存活",这一手法与 EIP-4788 等系统合约的部署方式类似。

日志条目的 SSZ 结构

每条被累积的日志都会携带来源元数据。规范复用了 EIP-6466(SSZ receipts,即把 RLP 收据迁移为 SSZ 编码)中定义的Log类型,并在此基础上扩展出LogMetaLogEntry

class BlockMeta(Container): timestamp: uint64 number: uint64 class LogMeta(Container): block: BlockMeta transaction_index: uint64 class Log(Container): address: ExecutionAddress topics: List[Bytes32, MAX_TOPICS_PER_LOG] data: ByteList[MAX_LOG_DATA_SIZE] class LogEntry(Container): meta: LogMeta log: Log

其中Log各字段的含义在 EIPS/eip-6466.md 中有更完整的定义:MAX_TOPICS_PER_LOG4(对应LOG0~LOG4操作码允许 0~4 个主题),address是 20 字节的执行层地址,data是日志负载字节串。EIP-7792 将其中的data表述为有界类型ByteList[MAX_LOG_DATA_SIZE],并额外引入BlockMeta(区块时间戳与区块号)与LogMeta(区块元数据 + 交易索引)作为每条日志的来源证明。最终被累积进链上存储的,是hash_tree_root(LogEntry)这个 32 字节承诺根。

累积算法:SHA256 链式哈希

累积过程使用 SHA256 而非以太坊常用的 KECCAK256,其算法如下:

def accumulate_log(evm: Evm, entry_root: Bytes32, key: Bytes32): root = hashlib.sha256() root.update(entry_root) root.update(sload(evm.env.state, LOG_CONTRACT_ADDRESS, key)) sstore(evm.env.state, LOG_CONTRACT_ADDRESS, key, root.digest()) def track_log(evm: Evm, entry: LogEntry) -> None: entry_root = entry.hash_tree_root() # Allow verification via `address` filter key = keccak256(abi.encode(entry.log.address, LOG_ADDRESS_STORAGE_SLOT)) accumulate_log(evm, entry_root, key) for topic in entry.log.topics: # Allow verification via `topics` filter key = keccak256(abi.encode(topic, LOG_TOPICS_STORAGE_SLOT)) accumulate_log(evm, entry_root, key) # Allow verification via combined `address` + `topics` filter key = keccak256(abi.encode(entry.log.address, topic)) key = keccak256(abi.encode(key, LOG_ADDRESS_TOPICS_STORAGE_SLOT)) accumulate_log(evm, entry_root, key)

可以将其理解为一条按过滤键(key)分组的哈希链:对于每个 key,新累积值 =SHA256(新条目根 || 旧累积值)。这样设计有三个关键性质:

  1. 可增量验证:验证者只需从某个历史累积值出发,按响应中的日志顺序逐个重放accumulate_log,即可得到当前累积值,无需重放整个区块;
  2. 覆盖三种过滤方式:同一日志会同时被写入"按地址"、"按每个主题"、"按地址+主题组合"三条链,因此无论钱包以何种过滤器发起查询,都能找到对应的累积链来校验;
  3. key 的计算遵循 Solidity 的mapping槽位规则keccak256(abi.encode(key, slot)),这正是eth_getProofmapping存储槽生成证明时使用的寻址方式,保证了证明与链上存储一一对应。

值得注意的是,track_log为每条日志的每个主题都执行了accumulate_log,而同一个entry_root会被写入多个 key 的链中——这也意味着存储写入量随日志数量线性增长,是后续 Gas 成本讨论的根源。

JSON-RPC API 扩展:新增blockTimestamp

为了让验证者能够将响应条目与区块头对应起来,eth_getLogs的响应格式被扩展,每个日志对象新增一个字段:

  • blockTimestampQUANTITY—— 该日志所在区块(由blockHash指向)的timestamp字段。

按照 EIPS/eip-1474.md 中关于Quantity编码的约定,该字段必须是0x前缀的十六进制、使用最少的十六进制位数表达,且零值表示为0x0blockTimestamp的加入让验证者无需单独查询区块头即可获得验证BlockMeta.timestamp所需的输入。

验证流程:四步增量校验

对于一次eth_getLogs(address, topics, fromBlock, toBlock)请求,响应数据的正确性与完整性可以通过以下四步验证:

  1. 获取并校验区块头:取得fromBlocktoBlock的区块头,并与它们已知的哈希值(blockHash)比对;
  2. 获取fromBlock的父区块头:取得fromBlockparentBlock头,并用fromBlock.parentHash校验之;
  3. 获取历史累积值:基于给定的过滤器,通过eth_getProof取得parentBlock处对应的历史日志累积值(即"起点状态");
  4. 获取终点累积值:同样通过eth_getProof,基于相同过滤器取得toBlock处的日志累积值(即"终点状态")。

随后,验证者从步骤 (3) 的历史累积值出发,将响应中的每一条日志条目按与accumulate_log兼容的方式逐一应用(即构造LogEntry、计算entry_root、SHA256 链接旧值)。如果最终计算出的累积值与步骤 (4) 从链上证明获得的累积值一致,则响应数据是正确且完整的,由它推导出的LogEntry可以被信任。

这套流程完全复用了现有的两条证明基建——eth_getProof(对世界状态存储槽的 Merkle 证明)与 SSZ Merkle 证明(来自 EIP-6466 的 receipts 根),没有引入任何新的密码学假设,因此安全性建立在以太坊既有的状态树安全模型之上。

设计权衡与 Rationale

为何做:摆脱对可信数据提供商的依赖

eth_getLogs响应可验证,本质上是为钱包补上"安全属性":钱包可以不再依赖任何可信的数据提供商,从而不再受制于特定提供商的隐私政策,最终提升钱包的隐私保证——它无需向提供商暴露完整的查询意图,也能自行核验结果的真实性。

Gas 成本:显著高于LOG#操作码方案

规范明确承认,该方案的 Gas 成本显著高于Prague 升级中LOG#操作码方案,原因主要有两点:

  • 每条日志的每次累积都涉及额外的SLOAD/SSTORE
  • SHA256操作码的成本是KECCAK256操作码的两倍,而累积链恰好使用 SHA256。

这些增加的成本超过了因去掉日志布隆过滤器(logs bloom)而节省的开销。规范进一步给出了备选演进方向:如果该机制即便经过优化仍然过于昂贵,则可能需要将日志累积器迁移到独立优化的数据结构中(不放入state_root),或交给协议外的零知识(zk)系统。即便如此,日志的 Gas 成本也应反映更新典型协议外累积器的真实总成本,以阻止日志垃圾攻击(log spamming)。

为何元数据用区块号/交易索引而非区块哈希

一个深刻的循环依赖问题:只要累积器存储在状态树(state trie)中,它就不能引用区块哈希——因为区块哈希本身是对状态树求哈希得到的,引用会产生循环依赖(cycle)。因此规范选择在BlockMeta中记录numbertimestamp、在LogMeta中记录transaction_index。而如果改用外部系统(如协议外累积器),则可以在元数据中包含哈希,因为那种场景下状态根不再受 IVC(incremental verifiable computation,增量可验证计算)影响。

向后兼容性

该方案对现有生态是渐进式的:

  • 来自可信服务器的eth_getLogs响应仍然可以原样处理,不强制要求验证;
  • 唯一需要客户端适配的点是:对响应做严格字段校验的客户端应用,可能需要更新以允许额外的blockTimestamp字段

这与 EIPS/eip-234.md(为过滤器选项增加blockHash)的历史经验一脉相承:每次为eth_getLogs增加字段,都会要求严格校验的客户端放宽 schema,但老客户端在信任模式下不受影响。

安全考虑

规范声称该方案不引入新的安全风险:它复用了已有的eth_getProof与 SSZ Merkle 证明机制,安全边界完全落在以太坊现有状态树与收据树的密码学保证之上。验证者需要自行承担的风险仍与过去一致——即区块头哈希的来源必须是可信的(通常通过轻客户端或共识层轻同步获得)。

在仓库中的定位与延伸阅读

本提案属于以太坊"日志可验证性"路线图的一部分,与本仓库中以下文档构成完整的知识链:

  • EIPS/eip-6466.md:SSZ receipts,定义了本文复用的Log类型与 receipts 的 SSZ 迁移,是hash_tree_root(LogEntry)的编码基础;
  • EIPS/eip-158.md:State clearing,解释了为何必须将累积合约 nonce 置 1 以防被清理;
  • EIPS/eip-234.md:为eth_getLogs过滤器增加blockHash选项的既有接口演进先例;
  • EIPS/eip-1474.md:JSON-RPC 规范,定义了QUANTITY编码规则,是blockTimestamp字段的格式依据。

总结

EIP-7792 通过"固定地址 + 无代码合约 + 三个 mapping 存储槽 + SSZ 日志条目 + SHA256 链式累积"的组合,为eth_getLogs构建了一套可增量验证的链上日志累积机制。它的设计精髓在于:把验证所需的全部证据沉淀进以太坊世界状态,从而复用成熟的eth_getProof基建,让钱包能够以"获取两个区块头 + 两个 Merkle 证明 + 本地重放累积"的轻量方式,获得对日志响应正确性与完整性的密码学保证。尽管当前其 Gas 成本仍高于直接方案,且提案处于Stagnant状态,但它为"钱包脱离可信提供商、提升隐私"这一目标提供了一条清晰的、基于现有共识层原语的技术路径。

说明:本文基于本仓库 EIPS/eip-7792.md 及其依赖文档撰写,代码与伪代码均直接引自仓库原文;文中涉及的协议状态、常量与算法均以该文档当前版本为准。

【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 15:24:35

基于51单片机的智能滴灌控制系统设计与实现

简介:基于51单片机的滴灌控制系统资料包,面向单片机学习者、课程设计与毕业设计人群,解决温室或农田场景下依据温湿度自动滴灌的工程问题。系统通过PT100测温,配合模拟量湿度传感器或仿真电位器监测湿度,用户可按键设定…

作者头像 李华
网站建设 2026/9/15 15:24:23

微信外卖点餐小程序模板二次开发:从zip导入到购物车订单联调

简介:美食餐饮外卖点餐微信小程序模板,是为餐饮商户与小程序开发者打造的一站式解决方案,帮助快速搭建外卖点餐与门店展示平台,无需从零编写代码,适合预算有限或希望快速试水的团队。压缩包共68个文件,其中…

作者头像 李华
网站建设 2026/9/15 15:23:33

深入 @scalar/void-server:Scalar 开源 HTTP 请求镜像服务器的设计与演进

深入 scalar/void-server:Scalar 开源 HTTP 请求镜像服务器的设计与演进 【免费下载链接】scalar Scalar is an open-source API platform:                                       🌐 Modern REST API Client …

作者头像 李华
网站建设 2026/9/15 15:23:32

D3Dhook通杀所有DirectX版本:COM虚表与Present锚点解析

简介:面向需要深入Direct3D底层渲染控制与Hook技术研究的开发者,提供一份精简的C源文件,呈现D3DHook的完整实现思路,能够通过API钩子与内存钩子方式,对多个DirectX版本的渲染管线进行统一拦截与功能扩展,适…

作者头像 李华
网站建设 2026/9/15 15:23:15

MRAC模型参考自适应控制详解:MATLAB仿真与TM4C123移植实践

简介:这套MRAC算法控制MATLAB代码包,专为自动化、计算机、电子信息工程及数学等专业学生打造,可广泛应用于课程设计、期末大作业或本科毕业设计,兼容MATLAB 2014/2019a/2021a三个版本。压缩包共212个文件,大小仅3.93MB…

作者头像 李华