zk 技术堆栈有哪些技术可用,介绍每个层级的示例工具/技术
去年夏天,Vitalik 撰写了一篇博文,概述了不同类型的 zkEVM(零知识以太坊虚拟机)。他根据性能和兼容性的权衡轴定义了它们。
zk 技术堆栈及其每个层级的示例工具/技术
Arkworks-rs是一个 Rust 库生态系统,提供了 zkSNARK 应用程序的子组件的高效且安全的实现。Arkworks 提供了必要的接口,使开发人员能够定制 zk 应用程序的软件堆栈,而无需重新实现与其他现有库的共同性。
在 Arkworks 之前,创建新的 zk 应用程序的唯一方法是从头开始构建一切。与自定义构建的垂直集成工具相比,Arkworks-rs 的关键优势在于灵活性、减少重复工程和减少审计工作量。Arkworks 的合理接口使得堆栈能够在 zk 技术的快速创新步伐中保持相关性,而无需强制团队从头开始重建一切。
Arkworks 适用于需要对整个 zk 软件堆栈进行精细控制,但又不想从头开始构建所有冗余部分的项目。如果你正在考虑定制电路 DSL 的自定义版本,例如,你正在为新的证明系统做原型,但对承诺方案或相应的椭圆曲线不确定,arkworks 将允许你快速在几个具有共享接口的选项之间切换,而不是从头开始。
为了创建关于某个计算的证明,首先必须以一种 zkSNARK 系统能够理解的形式表达这个计算。一些特定领域的编程语言为此而创建,允许应用开发者以这种方式表达他们的计算。其中包括Aztec Noir,Starknet 的Cairo,Circom,ZoKrates和 Aleo 的Leo等。底层的证明系统和数学细节通常对应用开发者不可见。
zkApp 开发者必须熟练掌握在特定领域语言中编写程序的技巧。其中一些语言看起来很像熟悉的编程语言,而其他一些可能相当难以学习。让我们来了解一下其中几种:
Cairo – Starkware 的 DSL,用于在 Starknet 上构建应用程序。它编译成Cairo特定的汇编语言,可以由Cairo zkVM 解释。
ZoKrates — ZoKrates 是一个工具包,用于满足常见的 SNARK 需求,包括用于编写电路的高级语言。ZoKrates 还可以在曲线、证明方案和后端方面具有一定的灵活性,允许开发者通过简单的命令行参数进行热切换。
Circom — Circom 是一个专门用于构建电路的语言。目前,它是生产中电路的事实标准语言。该语言并不特别易用。语言本身让你非常清楚地意识到你正在编写电路。
Leo — Leo 是为 Aleo 区块链开发的语言。Leo 具有类似 Rust 的语法,专门用于区块链内的状态转换。
Noir – 基于 Rust 的语法。以 IR 为架构,而不是语言本身,这意味着它可以有任意的前端。
Aztec Noir 编译栈具有模块化架构,这是一个显著特点。
任何希望在应用程序中利用 zk 的独特特性的应用程序开发人员。其中一些语言已经通过像 ZCash 和 Starknet 这样的区块链进行了数十亿美元的交易测试。虽然我们将讨论的一些项目目前还不够成熟以用于生产环境,但在这些语言中编写电路目前是最佳策略,除非你需要像 Arkworks 这样的工具包提供的更精细的控制。
zkEVM 的主要目标是使用简洁的零知识正确性证明来验证以太坊状态转换的有效性。正如 Vitalik 在他的文章中提到的,有多种方法可以做到这一点,具有微妙的差异和相应的权衡。
所有这些方法的主要技术差异在于计算在语言栈的哪个位置被转换为可以在证明系统中使用的形式(算术化)。在某些 zkEVM 中,这发生在高级语言(Solidity,Vyper,Yul)阶段,而其他方法则试图将 EVM 证明到操作码级别。这些方法之间的权衡在 Vitalik 的文章中有详细介绍,但我将用一句话总结:转换/算术化在技术栈中发生的位置越低,性能损耗越大。
图来源:https://mirror.xyz/msfew.eth/Yl64OK3lLG48eJpVB3GxqFEhmWOm6yMlAo9sc1VrQP4
创建虚拟机证明的主要挑战是,电路的大小与每个执行的指令的所有可能指令的大小成正比增长。这是因为电路不知道每个程序将执行哪些指令,所以需要支持所有指令。
<p align="center">在通用电路中,每个执行的指令的成本与所有支持的指令的总和成正比。</p>
实际上,这意味着即使你只执行最简单的指令,你也要为最昂贵的可能指令付出(性能成本)。这导致了通用性和性能之间的直接权衡-随着你增加更多指令以实现通用性,你将为每个指令付出代价!
这是通用电路的一个根本问题,但是通过技术的新发展,例如 IVC(增量可验证计算),可以通过将计算分解为具有专门的、较小的子电路的较小块来缓解这个问题。
当今的 zkEVM 实现使用不同的策略来减轻这个问题的影响...例如,zkSync 从主执行证明电路中剥离出更昂贵的操作(主要是密码学预编译,如哈希和 ECDSA),将它们放入单独的电路中,然后通过 snark 递归将它们聚合在一起。zkSync 在意识到大部分成本来自于少数复杂指令后采取了这种方法。
<p align="center">交易成本由少数昂贵的操作主导。</p>
从根本上讲,证明更多 EVM 等效指令集更昂贵的原因是,EVM 并不是为 zk 计算而设计的。在堆栈较早的位置放弃 EVM 允许 zkEVM 在更适用于 zk 的指令集上运行,因此更便宜的证明成本。
zkEVM 的理想客户是需要比 L1 以太坊提供的交易便宜几个数量级的智能合约应用程序。这些开发者不一定具备从头开始编写 zk 应用程序的专业知识或带宽。因此,他们更喜欢使用他们熟悉的高级语言来编写应用程序,比如Solidity。
扩展以太坊目前是 zk 技术最受需求的应用。
zkEVM 是一种以太坊扩展解决方案,可以无缝地缓解限制 L1 dApp 开发者面临的拥堵问题。
zkEVM 的目标是支持尽可能接近当前以太坊开发的开发者体验。完全支持Solidity意味着团队不必构建和维护多个代码库。这在完美实现上有些不切实际,因为 zkEVM 需要在合理的时间内生成合理大小的证明,因此需要在一些兼容性上做出一些权衡。
zkSync 和 Scroll 之间的主要区别在于它们在堆栈中的何时进行算术化转换-也就是说,它们在哪里将普通的 EVM 结构转换为 SNARK 友好的表示形式。对于 zkSync,这发生在将 YUL 字节码转换为他们自己的自定义 zk 指令集时。对于 Scroll,这发生在堆栈最末,当实际执行跟踪生成实际的 EVM 操作码时。
因此,对于 zkSync,与 EVM 的交互方式与以往完全相同,直到生成 zk 字节码。对于 Scroll,一切都与以往相同,直到实际的字节码被执行。这是一个微妙的区别,它在性能和支持之间进行权衡。例如,zkSync 将不会直接支持像调试器这样的 EVM 字节码工具,因为它是完全不同的字节码。而 Scroll 将更难以从为 zk 设计的指令集中获得良好的性能。这两种策略都有利弊,最终有很多外部因素会影响它们的相对成功。
尽管其名称如此,LLVM 并不是一个虚拟机(VM)。LLVM 是一套编译器工具的名称,其核心是一种与编程语言无关的中间表示(IR)。
=nil; Foundation(关于名称,如果你好奇的话,这是一个SQL 注入笑话)正在构建一个编译器,可以将任何 LLVM 前端语言转换为可以在 SNARK 中验证的中间表示。zkLLVM 被设计为现有 LLVM 基础设施的扩展,这是一个支持诸多高级语言(如 Rust、C、C++等)的行业标准工具链。
<p align="center">zkLLVM 架构的草图</p>
想要证明某个计算的用户只需在 C++中实现该计算。zkLLVM 接收这个高级源代码(目前支持他们修改过的 clang 编译器,即 C++),并生成电路的某种中间表示。此时,电路已经准备好进行验证,但用户可能希望基于一些动态输入来验证电路。为了处理动态输入,zkLLVM 还有一个额外的组件,称为分配器(assigner),它生成一个包含所有输入和见证(witnesses)的赋值表,经过完全预处理,准备好与电路一起进行验证。
这两个组件就足以生成一个证明。用户理论上可以自己生成证明,但由于这是一项相对专业的计算任务,他们可能希望支付其他人来为他们完成。为了解决这个对手发现机制,=nil; Foundation 还建立了一个“证明市场”,在这个市场上,证明者竞相为愿意支付他们的用户证明计算。这个自由市场的动态将导致证明者优化最有价值的证明任务。
由于每个要证明的计算任务都是独特的,并且会生成不同的电路,证明者需要能够处理无限数量的电路。这种强制的通用性使得优化单个电路变得困难。引入证明市场允许专门化于市场认为有价值的电路。如果没有这个市场,很难说服证明者优化这个电路,因为存在自然的冷启动问题。
另一个权衡是经典的抽象与控制之间的选择。愿意使用这种易于使用的界面的用户放弃了对底层加密原语的控制。对于许多用户来说,这是一个非常合理的权衡,因为让加密专家为你做出这些决策通常更好。
每个程序都有不同的电路,难以优化(部分通过证明市场解决)
非常难替换/升级内部的零知识库(需要分叉)
zkVM 描述了所有 zk 虚拟机的超集,而 zkEVM 是 zkVM 的一种特定类型,由于其在当今的普遍性,值得将其作为一个单独的主题进行讨论。还有一些其他项目正在构建基于除了定制加密虚拟机之外的 ISA 的更通用的 zkVM。
系统可以证明不同的指令集架构(ISA),例如 RISC-V 或 WASM,而不是证明 EVM。正在开发这些通用 zkVM 的两个项目是 RISC Zero 和 zkWASM。让我们深入了解一下 RISC Zero,以展示这种策略的工作原理以及它的优缺点。
<p align="center"> Risc Zero 证明生成的高层架构 </p>
Risc Zero 能够证明在 RISC-V 架构上执行的任何计算。RISC-V 是一种开源指令集架构(ISA)标准,正在日益流行。RISC(精简指令集计算机)的理念是构建一个极其简单的指令集,具有最小的复杂性。这意味着在堆栈的较高层中的开发人员需要承担更大的负荷,以使用这种架构实现指令,同时使硬件实现更简单。
这种理念也适用于通用计算,ARM 芯片一直在利用 RISC 风格的指令集,并开始主导移动芯片市场。事实证明,更简单的指令集也具有更高的能源和芯片面积效率。
这个类比对于生成零知识证明的效率非常适用。正如之前讨论的那样,在生成 zk 证明时,你需要为每个追踪项中的所有指令的成本总和付费,因此简单且指令总数较少的情况更好。
从开发者的角度来看,使用 RISC Zero 处理 zk 证明就像使用 AWS Lambda 函数处理后端服务器架构一样。开发者通过编写代码与 RISC Zero 或 AWS Lambda 进行交互,而服务会处理所有后端复杂性。
对于 RISC Zero,开发者可以编写 Rust 或 C++ 代码(最终可以编译为 RISC-V)。然后系统会使用编译过程中生成的 ELF 文件作为 VM 电路的输入代码。开发者只需调用 prove 函数,它会返回一个收据(其中包含执行追踪的 zk 证明),任何人都可以从任何地方调用 verify
函数。从开发者的角度来看,无需理解 zk 的工作原理,底层系统会处理所有这些复杂性。
<p align="center">RISC Zero 内部?</p>
优点
缺点
承担了很大的开销(证明大小和生成速度)以支持这样一个通用接口
需要在证明生成技术方面有显著改进,以实现对现有库的广泛支持
对于一些基本且可重用的电路,它们对于区块链应用或其他领域特别有用,团队可能已经为你构建和优化了这些电路。你只需为你特定的用例提供输入即可。例如,默克尔树包含证明是加密应用(空投列表、Tornado Cash 等)中常常需要的一种证明。作为应用开发者,你可以始终重用这些经过实战检验的合约,只需在其上层进行修改,即可创建一个独特的应用。
例如,Tornado Cash 的电路可以用于私人空投应用程序或私人投票应用程序。Manta 和 Semaphore 正在构建一个完整的常见电路工具包,类似这样的工具包可以在Solidity合约中使用,几乎不需要了解底层的 zk moon 数学。
正如我们详细讨论的那样,有许多不同的选项可用于开发 zk 应用程序,每个选项都有其独特的权衡。这个图表将帮助总结这个决策矩阵,以便根据你的 zk 专业知识水平和性能需求,选择最适合工作的工具。这不是一个全面的列表,我计划在未来添加更多在这个领域出现的工具。
何时使用:
何时不使用:
选项:
何时使用:
何时不使用:
选项:
何时使用:
何时不使用:
选项:
何时使用:
何时不使用:
选项:
何时使用:
何时不使用:
选项:
何时使用:
何时不使用:
选项:
zk 技术处于多个技术的前沿,构建它需要对数学、密码学、计算机科学和硬件工程有深入的理解。然而,随着每天可用的抽象层越来越多,应用开发人员可以在没有博士学位的情况下利用 zk 的强大功能。随着在堆栈的所有层面上进行优化,逐渐解除证明时间的限制,我们很可能会看到更简单的工具供普通开发人员使用。
我希望能说服你,这位好奇的软件开发者,你可以立即开始在你的应用程序中使用 zk。快乐编程!
你还在等什么呢,快去构建一些 zk 应用吧。
本翻译由 DeCert.me 协助支持, 来 DeCert 码一个未来, 支持每一位开发者构建自己的可信履历。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!