文章介绍了Jolt,一个新的SNARK设计方法,其在性能和可扩展性上优于现有zkVM,速度提升可达2倍。Jolt通过采用sum-check协议和多变量多项式来解决当前zkVM设计的复杂性和低效问题,旨在提升SNARK的开发体验,降低错误概率,并简化扩展工作。本文阐述了Jolt的架构、初步性能比较以及未来的优化方向。
今天,a16z crypto 的研究和工程团队发布了实现的初步版本Jolt,这是一种新的 SNARK 设计方法,速度比最新的技术提高了多达 2 倍,未来还将有更多改进。有关此工作的高级概述,请查看这篇文章,另外,请查看这篇文章以了解基准测试和代码,以及这篇文章以获取有关 Jolt 架构和性能与现有 zkVMs 的技术细节。
今天我们推出了 Jolt,可以说是迄今为止最快的 zkVM,它在现有技术的基础上提供了最多 2 倍的提升。该初步实现只是一个起点,预计将在未来几周和几个月内有显著改进。
速度虽然重要,但只是故事的一半:与今天的任何 zkVM 相比,Jolt 更简单,更容易审计和扩展。这降低了错误发生的可能性,并将促进高保证实现的构建。其性能和可扩展性意味着更多人将能够在更多应用中应用它。
SNARK 设计中的挑战。 Jolt 是一个 zkVM(零知识虚拟机)——一种让证明者能够证明其正确运行了指定计算机程序的 SNARK,其中程序是用某种简单 CPU 的汇编语言编写的。zkVM 提供了极好的开发者体验:它使得任何能够编写计算机程序的人都能使用 SNARK,消除了对深入密码学知识的需求。但是,可用性是有代价的。如今的 zkVM 极其复杂,并且为证明者提供了很差的性能。目前,证明 计算机程序正确运行的速度比简单的 运行 程序慢数百万倍。
为了解决这些挑战,Jolt 在设计方法上显著偏离了以前的 zkVM。在这篇文章中,我将解释 Jolt 的方法有何不同,以及它为何具有重要优势。(有关如何使用 Jolt 以及我们如何将 Jolt 工程化的概述,请参见我同事的这篇文章。)
求和检查协议与查找奇点。 Jolt 的核心是求和检查协议。虽然今天流行的 SNARK 使用单变量多项式和所谓的多项式 IOP,只使用一两轮,但求和检查协议基于多变量多项式,并使用多轮交互。它利用这种交互来缓解证明者的关键性能瓶颈,而不会显著增加验证者的成本。
在更高的抽象层面上,Jolt 建立在我们早期的工作称为Lasso之上,Lasso 是一种查找证明:一种让证明者密码学上承诺多个值并证明这些值都存在于预定表中的方法。像 Jolt 本身一样,Lasso 使用求和检查协议来确保该证明快速计算。
Jolt 使用 Lasso 来实例化查找奇点。这意味着,与今天部署的 zkVM 不同,协议设计者手动指定的优化约束系统以捕捉 CPU 的基本指令,Jolt 只需将 Lasso 应用于包含所有指令评估的表。这个表的大小远超过任何人能够明确写下的,但在 Lasso 中,证明者和验证者从未需要这样做。这是因为该表高度结构化:对大表的任何查找都可以通过执行少量对更小表的查找来回答。
Jolt 的性能。 在 CPU 上,初始 Jolt 实现比 RISC Zero 快约 6 倍,相比最近发布的 SP1 快多达 2 倍(虽然比较有点复杂)。初始 Jolt 实现使用了一种名为Hyrax的基于椭圆曲线的承诺方案。(我们使用 Hyrax 是因为它简单且透明:其性能可与其他曲线基础承诺方案相媲美,而其验证成本要低得多。)
一些简单的工程优化仍未实施,这些将在未来几周内使 Jolt 的速度提高约 1.5 倍。更重要的是,我们将很快用名为Binius的基于哈希的方案替换 Hyrax,其开发受到了 Lasso 和 Jolt 的部分启发。Binius 承诺方案在承诺小值时特别快速,而这些是 Jolt 中唯一需要承诺的值。将 Binius 纳入将为 Jolt 证明者带来额外 5 倍的加速,甚至可能更多。
额外的好处。 尽管 Jolt 已经是迄今为止最快的 zkVM,但它在性能之外还有令人兴奋的好处。例如,因为 Jolt实例化了查找奇点,所以只需几天的开发者时间即可将指令集扩展到更丰富的 ISA,如 RV64IM(支持 64 位,而不是 Jolt 当前支持的 32 位数据类型)。
通过查找处理所有指令的一个主要好处是:要将原始指令添加到 VM,只需指定将新指令“分解”为在较小数据类型上操作的“子指令”。从开发者的角度来看,指定这些分解是轻松的工作。
Jolt 方法的许多其他好处可以在我的伴随 FAQ的第 1 条中找到。
影响。 在 2023 年 9 月发布 Lasso 和 Jolt 论文时,我做了几个被强烈质疑的声明(有关细节,请参见我的伴随 FAQ)。重温这些声明是值得的。
在 Jolt 出现之前,甚至到今天,社区中的许多人声称,旨在“SNARK 友好”的非常简单的指令集会导致更快的 zkVM(见 Cairo、Miden、Valida 等)。事实上,Jolt 在每个指令上的速度几乎与那些拥有更简单指令集的先前 zkVM 相当(在某些情况下甚至更快)。并且对于满足自然可分解性属性的任何指令集,Jolt 的速度与其一样快。这包括 RISC-V,一种比声称 SNARK 友好的指令集复杂得多的指令集。
这表明,使指令集与传统硬件兼容的特性同样 使它们友好于像 Jolt 这样的基于求和检查的 SNARK。因此,当前流行的 zkVM 设计方法,即设计定制的“SNARK 友好”指令集,是双重 错误的:它伤害 而不是帮助性能,并且切断了对 RISC-V 等已知 ISA 开发的广泛工具的访问。有关进一步讨论,请参见我的伴随 FAQ的第 7 条。
这是 Lasso 和 Jolt 背后的顶层设计理念。
为数据进行承诺对证明者来说是昂贵的。除此之外,证明者还必须证明已承诺的数据是“良性”的,即这些数据符合某些预定义标准。换句话说,证明者必须展示他们已承诺的是“正确”的数据,而不是错误或无效的数据。
证明者承诺的数据越多,计算承诺所需的成本就越高,并且 证明者需要为证明数据是良性所做的工作也随之增加。
求和检查协议使用多轮交互(后通过 Fiat-Shamir 转换去除)来最小化承诺的数据量。这使得承诺_和_证明承诺是良性的变得迅速。
与之相对的是,目前流行的 SNARK 都使用常量轮数的多项式 IOPs。这并不是获得快速证明者的最佳途径。证据表明,多项式 IOP 要么需要很多轮(即求和检查协议),要么需要承诺大量数据。许多人仍未理解这一点,因为可以提供具有一轮或两轮多项式 IOP 的 SNARK,它们只是成本很高。Jolt 应该帮助人们最终理解。
尽管 Jolt 相对于目前的方法的速度提升现在可能看起来不大,但随着已知优化的实施,它们有望加速。此外,随着 Jolt 所基于的技术吸引更多关注和审查,更多改进应该会随之而来。
重申我之前提到过的观点,直到今天,人们普遍认为基于哈希的承诺方案比基于曲线的方案快的主要原因是,流行的 SNARK(如 Plonk)要求证明者承诺随机域元素而不是小域元素,而在这种情况下,基于曲线的承诺的速度非常慢。(Plonk 要求证明者对每个门承诺 11 个域元素,其中 8 个是随机的。)
Lasso 和 Jolt 证明了证明者不需要对随机域元素进行承诺。它们还显著减少了承诺的域元素的数量。考虑到这一点,基于曲线的 SNARK 可以比当前这一代基于哈希的 SNARK 更快。
当我在九月提出这一声明时,受到了相当大的质疑。Jolt 的初步性能表明,这种反应并没有根据。在我的伴随 FAQ中,我详细解释了最突出的(也是最不正确的)分析的错误所在。
这不应该令任何人感到惊讶。与普遍信念相反,大量明确的证据已经显示,基于曲线的 SNARK 可以比目前基于哈希的 SNARK 更快。
Binius以其对于小值的极快承诺以及新减少的证明大小而有望最终让基于哈希的方案优于基于曲线的方案,可能优于相当大的幅度(至少对于可以自然表示为特征为二的域的应用)。但这只能在将 Binius 承诺方案与基于求和检查的多项式 IOP(如 Lasso 和 Jolt)结合时才有效。之前对基于曲线的方案的批评是毫无根据的。
zkVM 提供了极好的开发者体验,使得任何希望部署 SNARK 的人都可以用任何编译为 VM 汇编语言的高级编程语言编写其见证检查程序(即 Jolt 的 RISC-V)。然而,它们的证明者超载非常庞大。
相较于原生执行 RISC-V 程序,Jolt 证明者现在的速度慢了多少?答案是大约 500,000 倍。
由于 Jolt 比部署的 zkVM(如 RISC Zero、Stone 等)快 6 倍(或更多),这意味着今天的部署相较于原生执行实际上慢了数百万倍。市场部门可以说任何他们想说的话。现实是如此巨大的超载使今天部署的 zkVM 无法用于其预定应用。
这个 500,000 的数字来自哪里?Jolt 证明者大约将 1/5 的时间花在承诺上(虽然这个比例会在我们进一步优化时增加),这涉及约 100 次每一步 RISC-V CPU 的组操作(其定义在 32 位数据类型上)。每次组操作相当于在 256 位域上进行约 6 次域乘法。而每个域操作(使用 Montgomery 模块乘法)在 32 位寄存器的 CPU 上需要大约 150 个 CPU 周期。因此,证明 RISC-V CPU 的每一步需要 5 ⋅ 100 ⋅ 6 ⋅ 150 = 450,000 个 RISC-V CPU 的周期。
这个计算与 Jolt 证明者今天在 M3 Max 笔记本电脑上运行所需的时间大体一致:在单线程情况下,Jolt 证明者大约每秒能证明 9,000 个 RISC-V 周期(9 kHz),这比 M3 的时钟速度约 40 亿个时钟周期每秒慢了约 500,000 倍。使用 16 个线程,Jolt 今天达到约 90 kHz。
如此差的性能是为什么今天所有部署的 zkVM 使用“预编译”或者为反复出现的特定计算(如 SHA2 或 Keccak 评估)手动优化的协议。但是,对预编译的过度依赖是危险的:设计预编译正是 zkVM 旨在避免的错误易发且耗时的过程。
zkVM 的超载需要减少到与原生执行相对的 10,000 倍――这意味着要比 Jolt 目前的速度快 50 倍――在 zkVM 能够接近其作为区块链可扩展性基石科技的潜力之前。
求和检查协议为何能够最小化证明者的承诺成本?一个答案是它是一个多轮交互证明。在 SNARK 应用中,这通常意味着对数轮,尽管即使将轮数设置为适度的大常量(例如 6 或更多),证明仍然可以很短。
而且,求和检查协议不仅仅是任何多轮交互证明:它是最有效和最强大的一个。例如,在某些设置中我们知道,它在轮复杂性与验证者成本之间达成了最佳权衡。
在 SNARK 设计中,轮复杂性最终并不重要,因为所有交互都是通过 Fiat-Shamir 转换去除的。(通常来说,应用 Fiat-Shamir 于多轮协议可能会导致重大安全损失,即便将哈希函数建模为随机预言机时,这种情况对求和检查协议并不发生,因为它满足一种称为逐轮健全性的技术安全概念。)
所以没有理由 不 使用多轮。然而今天的 SNARK 部署并没有。或者更准确地说,它们几乎所有的交互都是包含在“多项式承诺”方案中,而这并没有帮助提高证明者的速度。
具体而言,今天流行的 SNARK 是基于多项式 IOPs,仅有一轮或两轮。可以在只用一轮或两轮的情况下“模拟”求和检查协议的功能,但这会以更高的证明者成本为代价。
例如,“单变量求和检查协议”是一个一轮的多项式 IOP,它解决了一个类似于求和检查协议本身所解决的问题。(这个名称令人困惑;“单变量求和检查协议”与真正的求和检查协议毫无关系,只是解决了类似的问题。)单变量协议要求证明者做额外的工作,例如计算商多项式并对其进行承诺,并且对使用的有限域施加了限制。
拥抱求和检查协议。 交互是一种降低证明者承诺成本的工具。我们必须充分使用它。过渡到基于求和检查协议和多变量多项式的 SNARK 将需要时间和精力,但这是实现可扩展证明者所必需的。
\\*\
正如快速 SNARK 证明者的路径通过求和检查协议,快速 zkVM 的路径也通过 Jolt。初始实现现已完成,但还有大量的构建工作待做。请查看我们的(部分)路线图任务列表,如果你想贡献,请与我们联系。
\\*\
Justin Thaler 是 a16z 的研究合伙人,同时也是乔治城大学计算机科学系的副教授。他的研究兴趣包括可验证计算、复杂性理论以及大数据集的算法。
- 原文链接: a16zcrypto.com/posts/art...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!