作者:以太坊研究员 Justin Drake,ethresearch;编译:陶朱,
这篇文章的功劳要归功于更广泛的以太坊研发社区。关键贡献源自 2017 年,多年来设计有了重大的增量解锁。最近的 zkVM 工程突破引发了彻底的设计空间探索。本文只是尽最大努力尝试为一个可能终于到来的大创意拼凑出一个连贯的设计。
摘要
我们提出了一种优雅而强大的 EXECUTE 预编译,将原生 L1 EVM 执行引擎暴露给应用层。原生执行汇总(简称“原生汇总”)是一种使用 EXECUTE 来验证批量用户交易的 EVM 状态转换的汇总。可以将原生汇总视为“可编程执行分片”,将预编译包装在派生函数中以处理 EVM 外的系统逻辑,例如排序、桥接、强制包含、治理。
由于 EXECUTE 预编译由验证器直接执行,因此它享有 (zk)EL 客户端多样性并提供 EVM 等效性,该等效性在构造上无错误,并且与通过 L1 硬分叉进行的 EVM 升级向前兼容。对于希望完全继承以太坊安全性的 EVM 等效汇总,像 EXECUTE 预编译这样的 EVM 自省形式是必要的。我们将完全继承以太坊安全性的汇总称为“无需信任的汇总”。
EXECUTE 预编译大大简化了 EVM 等效汇总的开发,因为无需复杂的基础设施(例如防欺诈游戏、SNARK 电路、安全委员会)即可进行 EVM 模拟和维护。使用 EXECUTE,只需几行 Solidity 代码,使用简单的派生函数即可部署最小的原生汇总和基于汇总,从而无需对排序、强制包含或治理进行特殊处理。
最重要的是,原生汇总可以享受实时结算,而无需担心实时证明,从而大大简化了同步可组合性。
本文分为两部分,首先介绍拟议的预编译,最后讨论原生汇总。
第 1 部分 — EXECUTE 预编译
结构
EXECUTE 预编译接受输入 pre_state_root、post_state_root、trace 和 gas_used。当且仅当满足以下条件时,它才返回 true:
trace 是格式良好的执行跟踪(例如 L2 交易列表和相应的状态访问证明)
trace 的无状态执行从 pre_state_root 开始,在 post_state_root 结束
trace 的无状态执行恰好消耗 gas_used gas
有一种 EIP-1559 式机制,用于计量和定价 L1 区块中所有 EXECUTE 调用所消耗的累计 gas。具体来说,有一个累计 gas 限制 EXECUTE_CUMULATIVE_GAS_LIMIT,以及一个累计 gas 目标 EXECUTE_CUMULATIVE_GAS_TARGET。(当 L1 EVM 可由验证者无状态执行时,累计限制和目标可以与 L1 EIP-1559 机制合并。)
调用预编译需要花费固定数量的 L1 gas、EXECUTE_GAS_COST,加上 gas_used * gas_price,其中 gas_price(以 ETH/gas 计价)由 EIP-1559 式机制设置。即使预编译返回 false,也会提取全额预付款。
跟踪必须指向来自调用数据、blob、状态或内存的可用以太坊数据。
重新执行
如果 EXECUTE_CUMULATIVE_GAS_LIMIT 足够小,验证器可以简单地重新执行跟踪以强制执行 EXECUTE 调用的正确性。基于重新执行的预编译的初始部署可以作为垫脚石,类似于原始 danksharding 的简单重新下载 blob 到完整 danksharding。请注意,简单的重新执行不会给验证器带来状态增长或带宽开销,并且任何执行开销都可以在 CPU 核心之间并行化。
验证器必须持有跟踪的明确副本以进行重新执行,从而防止使用通过 DAS 采样(而不是下载)的 blob 数据的指针。请注意,乐观的本机汇总可能仍会以 blob 的形式发布汇总数据,仅在欺诈证明游戏中回退到调用数据。还要注意的是,乐观的原生汇总可以具有远远超过 EXECUTE_CUMULATIVE_GAS_LIMIT 的 gas 限制,因为 EXECUTE 预编译只需要在小型 EVM 段上调用一次即可解决欺诈证明挑战。
作为历史记录,2017 年 Vitalik 提出了类似的“EVM inside EVM”预编译 16,称为 EXECTX。
通过 SNARK 执行
要解锁较大的 EXECUTE_CUMULATIVE_GAS_LIMIT,自然会让验证者选择性地验证 SNARK 证明。从现在开始,我们假设一个时隙延迟执行,其中无效块(或无效交易)被视为无操作。(有关延迟执行的更多信息,请参阅此 ethresearch 帖子 15、此 EIP 18 和 Francesco 的此设计 19。)一个时隙延迟执行会产生几秒钟(整个时隙)用于证明。它们还避免激励 MEV 驱动的证明竞赛,这将引入集中化向量。
请注意,即使 EXECUTE 由 SNARK 强制执行,也没有明确的证明系统或电路被纳入共识。(请注意,EXECUTE 预编译不会将任何明确的证明作为输入。)相反,每个质押操作员都可以自由选择他们最喜欢的 zkEL 验证器客户端,类似于今天主观选择 EL 客户端的方式。下一节“链下证明”将解释此设计决策的好处。
从现在开始,我们假设执行提议者在具有交替执行和共识时隙的证明者-提议者分离 (APS) 的背景下是成熟的。为了激励理性的执行提议者及时生成证明(在 1 个时隙内),我们要求证明者仅在执行块 n 的证明可用时才证明执行块 n+1。(我们建议在 p2p 层将块 n+1 与块 n 的 EXECUTE 证明捆绑在一起。)跳过证明的执行提议者可能会错过他们的时隙,导致错过费用和 MEV。我们进一步对错过的执行时隙施加固定惩罚,将其设置得足够高(例如 1 ETH)以始终超过证明的成本。
请注意,在 APS 的背景下,共识块的生成不会因错过的执行时隙而受阻。然而,及时生成证明对于轻客户端来说很重要,这样他们就可以在链端轻松读取状态,而无需无状态重新执行。为了确保及时为轻客户端生成证明,即使在下一个执行提议者错过其时隙的特殊情况下,我们也依赖于利他少数证明者假设。单个利他证明者足以在 1 个时隙内生成证明。为了避免不必要的冗余证明,大多数利他证明者可以等待待命,并且仅在 1 个时隙内没有证明到达时才启动,从而充当最多 2 个时隙延迟的故障安全措施。
请注意,EXECUTE_CUMULATIVE_GAS_LIMIT 需要设置得足够低,以使利他少数证明者假设可信(以及使执行提议不会不切实际地复杂化)。保守的策略可以是设置 EXECUTE_CUMULATIVE_GAS_LIMIT,以便笔记本电脑(例如高端 MacBook Pro)可以访问单时隙证明。更务实和积极的政策可能是瞄准一小部分 GPU,并且一旦它们充分商品化,最终可能会瞄准 SNARK ASIC 证明器。
链下证明
重申一下,我们建议不要将 zkEL EXECUTE 证明放在链上,而是在链下共享。不保存证明是一个好主意,由 Vitalik 22 首次提出,它有几个优点:
多样性:验证者可以自由地从他们信任的开发团队中选择证明验证器(包括证明系统和电路),类似于验证者选择他们信任的 EL 客户端的方式。这通过多样性提供了稳健性。zkEL 验证器客户端(以及一些客户端的基础 zkVM)是复杂的加密软件。任何一个客户端中的错误都不应该导致以太坊崩溃。
中立性:拥有 zkEL 验证器客户端市场允许共识层不选择技术赢家。例如,zkVM 市场竞争激烈,选择获胜供应商(如 Risc0、Succinct 或许多其他供应商 31)可能不会被视为中立。
简单性:共识层不需要包含特定的 SNARK 验证器,从而大大简化了共识层的规范。只需包含状态访问证明的格式,而不是特定的证明验证器实现细节。
灵活性:如果发现错误或优化,受影响的验证者可以更新他们的客户端,而无需硬分叉。
拥有链下证明确实会带来一些可控的复杂情况:
证明负载和 p2p 碎片化:由于没有单一的规范证明,因此需要生成多个证明(每个 zkEL 客户端至少一个)。每个 zkEL 客户端定制(例如将一个 RISC-V zkVM 换成另一个)都需要不同的证明。同样,每个 zkEL 版本升级都需要不同的证明。这将导致证明负载增加。如果每个证明类型都有单独的八卦渠道,它还会进一步碎片化 p2p 网络。
少数 zkEL:很难激励少数 zkEL 生成证明。理性执行提议者可能只会生成足够的证明,以达到绝大多数证明者,而不会错过他们的时段。为了解决这个问题,可以从社会上鼓励质押运营商并行运行多个 zkEL 客户端,类似于今天的 Vouch 4 运营商。运行 k-of-n 设置还有提高安全性的额外好处,特别是可以防止健全性漏洞,这种漏洞允许攻击者为任意 EXECUTE 调用制作证明(这种情况对于传统的 EL 客户端来说并不常见)。
链下证明还会降低实时结算 L2 的效率:
无替代 DA:由于 EXECUTE 的跟踪输入需要提供给 L1 验证者,因此实时结算的 L2(即立即更新其规范状态根的 L2)必须消耗 L1 DA,即汇总。请注意,通过欺诈证明游戏延迟结算的乐观 L2 没有此限制,即可以是有效值。
状态访问开销:由于跟踪必须是无状态可执行的,因此它必须包括读取或写入的状态 trie 叶子,这比典型的 L2 块引入了少量 DA 开销。请注意,乐观 L2 没有此限制,因为仅在欺诈证明挑战中才需要状态 trie 叶子,挑战者可以重新计算 trie 叶子。
无状态差异:由于给定跟踪,证明应该是无需许可的,因此无法进行汇总状态差异。但是,如果相应的专门证明被纳入共识,则可以压缩无状态访问证明或 EVM 交易签名。
RISC-V 原生执行
鉴于当今事实上向 RISC-V zkVM 31 的趋同,可能有机会将 RISC-V 状态转换本地暴露给 EVM(类似于 Arbitrum Stylus 5 环境中的 WASM)并保持 SNARK 友好性。
第 2 部分 — 原生 Rollup
命名
我们首先讨论原生 Rollup 的命名,以解决几个容易引起混淆的问题:
替代名称:原生汇总以前被称为 enshrined 汇总,例如,请参阅本文 13 和本文 7。(术语“规范汇总”也曾在 Polynya 12 中短暂使用过。)术语“enshrined”后来被放弃,取而代之的是“原生”,以表明现有的 EVM 等效汇总可以选择升级为原生。“原生”这个名字是 Dan Robinson 和一位希望保持匿名的 Lido 贡献者于 2022 年 11 月独立提出的。
基于汇总:基于汇总和原生汇总是正交概念:“基于”与 L1 排序有关,而“原生”与 L1 执行有关。同时基于和原生的汇总被异想天开地称为“超音速汇总”。
执行分片:执行分片(即 L1 EVM 链的 enshrined 副本)是一个与原生汇总相关的不同但相关的概念,比原生汇总早几年。 (执行分片之前是以太坊 2.0 路线图的“第 2 阶段”。)与原生 rollup 不同,执行分片不可编程,即没有自定义治理、自定义排序、自定义 gas 代币等选项。执行分片通常也以固定数量实例化(例如 64 或 1,024 个分片)。不幸的是,Martin Köppelmann 在 2024 年 Devcon 上关于执行分片的演讲中使用了“原生 L2”一词 7。
好处
Native Rollups 有几个好处,我们将在下面详细介绍:
简单性:原生 rollup VM 的大部分复杂性都可以通过预编译来封装。如今,与 EVM 相当的 optimism 和 zk-rollup 有数千行代码用于其欺诈证明游戏或 SNARK 验证器,这些代码可以压缩为一行代码。原生 rollup 也不需要辅助基础设施,如证明网络、瞭望塔和安全委员会。
安全性:构建无错误的 EVM 欺诈证明游戏或 SNARK 验证器是一项非常困难的工程任务,可能需要深度形式验证。如今,每个 optimism 和 zk EVM rollup 在其 EVM 状态转换函数中都很可能存在严重漏洞。为了防范漏洞,集中排序通常被用作控制对抗性区块生产的拐杖。原生执行预编译允许安全部署无需许可的排序。完全继承 L1 安全性的无需信任的 rollup 还完全继承了 L1 资产可互换性。
EVM 等效性:如今,rollup 与 L1 EVM 规则保持同步的唯一方法是让治理(通常是安全委员会和/或治理代币)镜像 L1 EVM 升级。(EVM 更新仍然通过大约每年一次的硬分叉定期进行。)治理不仅是一种攻击媒介,严格来说,它背离了 L1 EVM,并阻止任何 rollup 实现真正的长期 EVM 等效性。另一方面,原生 rollup 可以与 L1 同步升级,无需治理。
SNARK gas 成本:在链上验证 SNARK 的成本很高。因此,许多 zk-rollup 很少结算以尽量降低成本。由于 SNARK 未在链上验证,因此可以使用 EXECUTE 预编译来降低验证成本。如果使用 SNARK 递归对一个块中多个调用的 EXECUTE 证明进行批处理,则 EXECUTE_GAS_COST 可以设置得相对较低。
同步可组合性:如今,与 L1 的同步可组合性需要同槽实时证明。对于 zk rollups 来说,实现超低延迟证明(例如 100 毫秒左右)是一项特别具有挑战性的工程任务。使用单槽延迟状态根,可以将本机执行预编译的证明延迟放宽到一个完整槽。