链眼社区:专注于区块链安全,区块链数据分析, 区块链信息整合,区块链技术服务和区块链技术咨询。

zkEVM 的构建思路
扫地僧
2022-10-08 12:40:27

我们相信 zk-Rollup 是圣杯——一种非常便宜且安全的一流的第 2 层扩展解决方案。然而,现有的 zk-Rollup 是特定于应用程序的,这使得在 zk-Rollup 中构建通用的可组合 DApp 和迁移现有应用程序变得困难。我们引入 zkEVM,它可以生成 zk 证明,用于一般的 EVM 验证。这使我们能够构建一个完全兼容 EVM 的 zk-Rollup,任何现有的以太坊应用程序都可以轻松迁移到该 zk-Rollup。

在本文中,我们确定了 zkEVM 的设计挑战以及为什么它现在成为可能。我们还给出了更具体的直觉,并描述了如何从头开始构建它的高级想法。

一. 背景

zk-Rollup被公认为以太坊的最佳扩容解决方案。它与以太坊第 1 层一样安全,并且与所有其他第 2 层解决方案相比,完成时间最短(此处有详细比较)。

从中长期来看,随着 ZK-SNARK 技术的改进,ZK rollups 将在所有用例中胜出。— 维塔利克·布特林

zk-Rollup 的基本思想是将大量交易聚合到一个 Rollup 块中,并为链下的块生成简洁的证明。然后第 1 层上的智能合约只需要验证证明并直接应用更新的状态,而无需重新执行那些交易。这可以帮助节省一个数量级的 gas 费用,因为证明验证比重新执行计算便宜得多。另一个节省来自数据压缩(即只保留最少的链上数据进行验证)

尽管 zk-Rollup 安全高效,但其应用仍仅限于支付和互换。由于以下两个原因,很难构建通用 DApp。

首先,如果你想在 zk-Rollup 中开发 DApp,你需要使用一种特殊的语言(即R1CS)编写你所有的智能合约逻辑。不仅所需语言的语法复杂,而且这样做还需要极强的零知识证明专业知识。

其次,当前的 zk-Rollup 不支持可组合性(Starkware 声称实现了可组合性, 参考链接)。这意味着不同的 zk-Rollup 应用程序不能在第 2 层内相互交互。这种质量极大地破坏了 DeFi 应用程序的可组合性。

二. 在 zk-Rollup 中构建通用 DApp

在 zk-Rollup 中有两种构建通用 DApp 的方法。

一是为不同的 DApp 构建专用电路(“ASIC”)。 另一个是为智能合约执行构建一个通用的“EVM”电路。 “电路”是指零知识证明中使用的程序表示。例如,如果要证明 hash(x) = y,则需要使用电路形式重新编写散列函数。电路形式只支持非常有限的表达式(即,R1CS 只支持加法和乘法)。因此,使用电路语言编写程序非常困难——您必须使用 add 和 mul 构建所有程序逻辑(包括 if else、循环等)。

第一种方法需要开发人员为不同的 DApp 设计专门的“ASIC”电路。这是使用零知识证明的最传统方式。通过定制电路设计,每个 DApp 都会有更小的开销。然而,由于电路是“静态的”,它带来了可组合性的问题,并且由于需要强大的电路设计专业知识,因此开发人员的体验很糟糕。电路是固定的和静态的。例如,在将程序实现为电路时,不能使用可变上限循环。上限必须固定为其最大值。它不能处理动态逻辑。

第二种方法不需要任何特殊的设计或开发人员的专业知识。这种基于机器的证明的高级思想是任何程序最终都会在CPU上运行,因此我们只需要构建一个通用的CPU电路来验证低级CPU步骤即可。然后我们可以使用这个 CPU 电路来验证任何程序的执行。在我们的场景中,程序是智能合约,CPU 是 EVM。但是,由于开销较大,这种方法在过去几年中并不普遍采用。例如,即使您只想add一步证明结果是正确的,您仍然需要承担整个 EVM 电路的开销。如果您的执行跟踪中有数千个步骤,那么证明方的 EVM 电路开销将是 1000 倍, 为了更清楚,我们在这里详细说明EVM电路的成本。如前所述,电路是固定的和静态的。因此,EVM 电路需要包含所有可能的逻辑(比 pure 大 10000 倍add)。这意味着即使您只想证明add,您仍然需要承担 EVM 电路中所有可能逻辑的开销。它将成本放大 10000 倍。在执行跟踪中,您需要证明一系列操作码,并且每个操作码都会有如此大的开销。。

最近,有很多研究在按照这两种方法优化 zk 证明,包括(i)提出新的 zk 友好原语,即Poseidon 哈希可以在电路中实现 100 倍于 SHA256 的效率,(ii)正在进行的提高效率的工作通用可验证虚拟机,如TinyRAM,以及 (iii) 越来越多的通用优化技巧,如 Plookup,甚至更普遍更快的密码库。

在我们之前的文章中,我们建议为每个 DApp 设计“ASIC”电路,让它们通过密码承诺进行通信。但是,根据社区的反馈,我们改变了优先级,将重点关注在第二种方法之后首先构建通用 EVM 电路(所谓的“zkEVM”)。zkEVM 将提供与在 Layer 1 上开发完全相同的开发人员体验。我们不会将设计复杂性留给开发人员,而是接管它并通过定制的 EVM 电路设计来解决效率问题。

三. zkEVM 的设计挑战

zkEVM 很难构建。尽管多年来直觉很清楚,但没有人成功构建原生 EVM 电路。与 TinyRAM 不同,zkEVM 的设计和实现更具挑战性,原因如下:

首先,EVM 对椭圆曲线的支持有限。目前,EVM 仅支持 BN254 配对。由于不直接支持循环椭圆曲线,因此很难进行证明递归。在此设置下也很难使用其他专用协议。验证算法必须是 EVM 友好的。

其次,EVM 字长为 256 位。 EVM 在 256 位整数上运行(很像大多数常规 VM 在 32-64 位整数上运行),而 zk 证明最“自然”地在素数字段上工作。在电路内部进行“不匹配场算术”需要范围证明,这将在每个 EVM 步骤中增加约 100 个约束。这将使 EVM 电路尺寸扩大两个数量级。

第三,EVM 有很多特殊的操作码。EVM 与传统 VM 不同,它有许多特殊的操作码,例如CALL,它也有与执行上下文和气体相关的错误类型。这将给电路设计带来新的挑战。

第四,EVM 是基于堆栈的虚拟机。SyncVM ( zksync ) 和Cairo (starkware) 架构在基于寄存器的模型中定义了自己的 IR/AIR。他们构建了一个专门的编译器,将智能合约代码编译成一个新的 zk 友好的 IR。他们的方法是语言兼容而不是原生 EVM 兼容。基于堆栈的模型和直接支持原生工具链更难证明。

第五,以太坊存储布局带来巨大开销。以太坊存储布局高度依赖Keccak和巨大的MPT(EVM 本身并没有与 Merkle Patricia 树紧密绑定。MPT 就是目前以太坊状态的存储方式。一个不同的可以很容易地插入(即,当前用Verkle 树替换 MPT 的提议)。) ,它们都不是 zk 友好的,并且具有巨大的证明开销。例如,Keccak 哈希比电路中的波塞冬哈希大 1000 倍。但是,如果将 Keccak 替换为另一个哈希,则会对现有的以太坊基础设施造成一些兼容性问题。

第六,基于机器的证明有巨大的开销。即使您能够妥善处理所有上述问题,您仍然需要找到一种有效的方法将它们组合在一起以获得完整的 EVM 电路。正如我在上一节中提到的,即使是简单的操作码也add可能会导致整个 EVM 电路的开销。

四. 为什么现在可能?

感谢研究人员在这方面取得的巨大进步,近两年来解决了越来越多的效率问题,zkEVM 的证明成本最终是可行的!最大的技术进步来自以下几个方面:

多项式承诺的使用。在过去的几年里,大多数简洁的零知识证明协议都坚持使用 R1CS,在特定于应用程序的可信设置中编码 PCP 查询。电路尺寸通常会爆炸,并且您无法进行许多自定义优化,因为每个约束的程度需要为 2(双线性配对仅允许指数中的一次乘法)。使用多项式承诺方案,您可以通过通用设置甚至透明设置将约束提升到任何程度。这为后端的选择提供了极大的灵活性。

查找表参数和自定义小工具的外观。另一个强大的优化来自查找表的使用。优化首先在Arya中提出,然后在Plookup中进行优化。这可以为 zk 不友好的原语(即,AND、XOR 等按位运算)节省很多。定制的小工具可以让您高效地进行高度约束。TurboPlonk和UltraPlonk定义了优雅的程序语法,以便更轻松地使用查找表和定义自定义小工具。这对于减少 EVM 电路的开销非常有帮助。

递归证明越来越可行。递归证明在过去具有巨大的开销,因为它依赖于特殊的配对友好的循环椭圆曲线(即基于 MNT 曲线的构造)。这引入了很大的计算开销。然而,更多的技术在不牺牲效率的情况下使这成为可能。例如,Halo可以避免对配对友好曲线的需要,并使用特殊的内积参数来摊销递归成本。Aztec 表明您可以直接对现有协议进行证明聚合(查找表可以减少非本地字段操作的开销,从而可以使验证电路更小)。它可以极大地提高支持的电路尺寸的可扩展性。

硬件加速使证明更加高效。据我们所知,我们为证明者制造了最快的 GPU 和 ASIC/FPGA 加速器。我们描述 ASIC 证明者的论文已经被今年最大的计算机会议(ISCA)接受。GPU 证明器比Filecoin 的实现快大约 5 到 10 倍。这可以大大提高证明者的计算效率。

五. 好的,那么它是如何工作的以及如何构建它呢?

除了强大的直觉和技术改进之外,我们仍然需要更清楚地了解我们需要证明和找出更具体的架构。我们将在后续文章中介绍更多技术细节和对比。在这里,我们描述了整个工作流程和一些关键思想。

1. 开发人员和用户的工作流程

对于开发人员来说,他们可以使用任何与 EVM 兼容的语言来实现智能合约,并将编译后的字节码部署在 Scroll 上。然后,用户可以发送交易以与那些部署的智能合约进行交互。用户和开发者的体验将与第 1 层完全相同。但是,gas 费用显着降低,并且交易在 Scroll 上即时预先确认(提款只需几分钟即可完成)。

2. zkEVM 的工作流程

即使外面的工作流程保持不变,Layer 1 和 Layer 2 的底层处理过程也完全不同: - 第 1 层依赖于智能合约的重新执行。 - 第 2 层依赖于 zkEVM 电路的有效性证明。

让我们更详细地解释第 1 层和第 2 层交易的情况有何不同。

在第 1 层,已部署的智能合约的字节码存储在以太坊存储中。交易将在 P2P 网络中广播。对于每个事务,每个全节点都需要加载相应的字节码并在 EVM 上执行以达到相同的状态(事务将作为输入数据)。

在第 2 层中,字节码也存储在存储中,用户将以相同的方式进行操作。交易将在链下发送到一个集中的 zkEVM 节点。然后,zkEVM 不仅会执行字节码,还会生成一个简洁的证明,以证明在应用交易后状态已正确更新。最后,Layer 1 合约将验证证明并更新状态,而无需重新执行交易。

让我们深入了解一下执行过程,看看 zkEVM 最终需要证明什么。在原生执行中,EVM 会加载字节码,并从头开始一个一个地执行字节码中的操作码。每个操作码可以被认为是执行以下三个子步骤:(i)从堆栈、内存或存储中读取元素(ii)对这些元素执行一些计算(iii)将结果写回堆栈、内存或存储(这是一个高度简化的抽象。从技术上讲,“EVM 状态”列表更长,包括 PC、剩余气体、调用堆栈(以上所有加上堆栈中每个调用的地址和静态)、一组日志和事务范围的变量(暖存储槽、退款,自毁)。可以使用针对不同调用上下文的附加标识符直接支持可组合性。)。例如,add操作码需要从堆栈中读取两个元素,将它们相加并将结果写回堆栈。

所以,很明显zkEVM的证明需要包含以下与执行过程对应的方面

  • 字节码从持久存储中正确加载 (您正在运行从给定地址加载的正确操作码)
  • 字节码中的操作码一致地一一执行 (它们的字节码按顺序执行,不会丢失或跳过任何操作码)
  • 每个操作码都正确执行 (每个操作码中的三个子步骤都正确执行,R/W + 计算)

3. zkEVM 设计亮点

在设计 zkEVM 的架构时,我们需要一一处理/解决上述三个方面。

3.1. 我们需要为一些密码累加器设计一个电路。

这部分就像一个“可验证的存储”,我们需要一些技术来证明我们正在阅读正确。可以使用密码累加器来有效地实现这一点(我们使用累加器进行存储,因为存储空间很大。对于内存和堆栈,可以使用可编辑的 Plookup(“RAM”可以通过这种方式有效地实现)。)。

我们以默克尔树为例。部署的字节码将作为叶子存储在 Merkle 树中。然后,验证者可以使用简洁的证明来验证从给定地址正确加载的字节码(即验证电路中的默克尔路径)。F或以太坊存储,我们需要电路兼容 Merkle Patricia Trie 和 Keccak 哈希函数。

3.2. 我们需要设计一个电路来将字节码与真实的执行跟踪联系起来。

将字节码移动到静态电路中的一个问题是条件操作码jump(对应于循环,智能合约中的 if else 语句)。它可以跳到任何地方。在使用特定输入运行字节码之前无法确定目的地。这就是我们需要验证真实执行跟踪的原因。执行跟踪可以被认为是“展开的字节码”,它将包含操作码在实际执行顺序中的序列(即,如果你跳转到另一个位置,跟踪将包含目标操作码和位置)。

Prover 将直接提供执行跟踪作为电路的见证。我们需要证明提供的执行跟踪确实是从具有特定输入的字节码中“展开”的。这个想法是强制程序计数器的值保持一致。为了处理未确定的目的地,我们的想法是让证明者提供一切。然后,您可以使用查找参数有效地检查一致性(即,证明具有适当全局计数器的操作码包含在“总线”中)。

3.3. 我们需要为每个操作码设计电路(证明每个操作码中的读、写和计算都是正确的)。

这是最重要的部分——证明执行跟踪中的每个操作码都是正确且一致的。如果将所有东西直接放在一起,将会带来巨大的开销。这里重要的优化思想是

我们可以将 R/W 和计算分成两个证明。将所有操作码所需的元素提取到“总线”中。另一个将证明对来自“总线”的元素执行的计算是正确执行的。这可以大大减少每个部分的开销(即,您不需要在计算证明中考虑整个 EVM 存储)。在更详细的规范中,第一个称为“状态证明”,第二个称为“EVM 证明”。另一个观察是“总线映射”可以通过查找参数有效地处理。

我们可以为每个操作码设计更高程度的定制约束(即,EVM 字可以通过将其分成几个块来有效地解决)。我们可以根据需要选择是否通过选择多项式“打开”约束。这样可以避免每个步骤中整个EVM电路的开销。

该架构首先由以太坊基金会指定。它仍处于早期阶段并正在积极开发中。我们正在与他们密切合作,以找到实现 EVM 电路的最佳方法。到目前为止,最重要的特征已经定义,一些操作码已经在这里实现(使用 Halo2 存储库中的 UltraPlonk 语法)。更多细节将在后续文章中介绍。我们推荐有兴趣的读者阅读这份文件。开发过程将是透明的。这将是一个社区努力和完全开源的设计。希望更多的人能够加入并为此做出贡献。

六. 它还能带来什么?

zkEVM 不仅仅是第 2 层扩展。它可以被认为是通过第 1 层有效性证明来扩展以太坊第 1 层的直接方法。这意味着您可以扩展现有的第 1 层,而无需任何特殊的第 2 层。

例如,您可以使用 zkEVM 作为全节点。该证明可用于直接证明现有状态之间的转换——无需将任何东西移植到第 2 层,您可以直接证明所有第 1 层交易!更广泛地说,你可以使用 zkEVM 像 Mina 一样为整个以太坊生成简洁的证明。您唯一需要添加的是证明递归(即将块的验证电路嵌入到 zkEVM)[7]。

zkEVM 不仅仅是第 2 层扩展。它可以被认为是通过第 1 层有效性证明来扩展以太坊第 1 层的直接方法。这意味着您可以扩展现有的第 1 层,而无需任何特殊的第 2 层。

例如,您可以使用 zkEVM 作为全节点。该证明可用于直接证明现有状态之间的转换——无需将任何东西移植到第 2 层,您可以直接证明所有第 1 层交易!更广泛地说,你可以使用 zkEVM 像 Mina 一样为整个以太坊生成简洁的证明。您唯一需要添加的是证明递归(即将块的验证电路嵌入到 zkEVM),向 zkEVM 电路添加完整的递归证明并非易事。进行递归的最好方法仍然是使用循环椭圆曲线(即 Pasta 曲线)。需要一些“包装”过程以使其在以太坊第 1 层上可验证。

七. 结论

zkEVM 可以为开发者和用户提供相同的体验。在不牺牲安全性的情况下,它的价格要便宜几个数量级。已经提出了以模块化方式构建它的架构。它利用最近在零知识证明方面的突破来减少开销(包括自定义约束、查找参数、证明递归和硬件加速)。我们期待看到更多的人加入 zkEVM 社区,与我们一起集思广益!

本文翻译自: https://hackmd.io/@yezhang/S1_KMMbGt

合作伙伴