我们要感谢 Polygon Zero 团队、Consensys gnark 项目、Pado Labs 和 Delphinus Lab 团队对本篇文章的宝贵评论和反馈。

过去几个月,我们投入了大量时间和精力,开发了利用 zk-SNARK 简洁证明构建的前沿基础设施。 这个下一代创新平台使开发者能够构建前所未有的区块链应用新范例。

在开发工作中,我们测试并使用了多种零知识证明 (ZKP) 开发框架。 虽然这段旅程收获颇丰,但我们也确实意识到,当新的开发者试图找到最适合其特定用例和性能要求的框架时,多种多样的 ZKP 框架通常会给他们带来挑战。 考虑到这一痛点,我们认为需要一个能够提供全面性能测试结果的社区评估平台,这将极大地促进这些新应用的开发。

为了满足这一需求,我们推出了零知识证明开发框架评测平台「万神殿 Patheon」 这一公益社区倡议。 倡议的第一步将鼓励社区分享各种 ZKP 框架的可复现性能测试结果。 我们的最终目标是共同协作创建并维护一个广受认可的测试平台,评估低级电路开发框架、高级 zkVM 和编译器,甚至硬件加速提供商。 我们希望这一举措能够让开发者们在选用框架时能有更多性能比较的参考,从而加快 ZKP 的推广。同时,我们希望通过提供一组普遍可参考的性能测试结果,促进 ZKP 框架本身的升级和迭代。 我们将大力投入这项计划,并邀请所有志同道合的社区成员加入我们,共同为这项工作做出贡献!

第一步:使用 SHA-256 对电路框架进行性能测试

在这篇文章中,我们迈出了构建 ZKP Patheon 的第一步,在一系列低级电路开发框架中使用 SHA-256 提供一组可复现的性能测试结果。 虽然我们承认其他性能测试粒度和原语或许也是可行的,但我们选择 SHA-256 是因为它适用于广泛的 ZKP 用例,包括区块链系统、数字签名、zkDID 等。 另外值得一提的是,我们在自己的系统中也使用了 SHA-256,所以这对我们来说也很方便! 😂

Our benchmark evaluates the performance of SHA-256 on various zk-SNARK and zk-STARK circuit development frameworks. Through this comparison, we seek to provide developers with insights into the efficiency and practicality of each framework. Our goal is that these findings will enable developers to make informed decisions when selecting the most suitable framework for their projects.

我们的性能测试评估了 SHA-256 在各种 zk-SNARK 和 zk-STARK 电路开发框架上的性能。 通过比较,我们力求为开发者提供关于每个框架的效率和实用性的见解。 我们的目标是,希望本次性能测试结果能够为开发者在选择最佳框架时提供参考,使之做出明智的决定。

证明系统

近年来,我们观察到零知识证明系统激增。 跟上该领域所有激动人心的进步是具有挑战性的,我们根据成熟度和开发者采用情况精心挑选了以下证明系统作为测试对象。 我们的目标是提供不同前端/后端组合的代表性样本。

  1. Circom + snarkjs / rapidsnark: Circom 是一种流行的 DSL,用于编写电路和生成 R1CS 约束,而 snarkjs 能够为 Circom 生成 Groth16 或 Plonk 证明。 Rapidsnark 也是 Circom 的证明器,它生成 Groth16 证明,并且由于使用了 ADX 扩展,它通常比 snarkjs 快得多,并尽可能并行化证明生成。

  2. gnark: gnark 是来自 Consensys 的综合 Golang 框架,支持 Groth16、Plonk 和许多更高级的功能。

  3. Arkworks: Arkworks 是一个用于 zk-SNARKs 的综合 Rust 框架。

  4. Halo2 (KZG): Halo2 是 Zcash 与 Plonk 的 zk-SNARK 实现。 它配备了高度灵活的 Plonkish 算术,支持许多有用的原语,例如自定义网关和查找表。 我们使用具有以太坊基金会和 Scroll 支持的 KZG 的 Halo2 分叉。

  5. Plonky2: Plonky2 是基于来自 Polygon Zero 的 PLONK 和 FRI 技术的 SNARK 实现。 Plonky2 使用小的 Goldilocks 字段并支持高效的递归。 在我们的性能测试中,我们以 100 位推测的安全性为目标,并使用为性能测试工作产生最佳证明时间的参数。 具体来说,我们使用了 28 Merkle 查询、8 的放大系数和 16 位工作量证明挑战。 此外,我们设置 num_of_wires = 60 和 num_routed_wires = 60。

  6. Starky: Starky 是 Polygon Zero 的高性能 STARK 框架。 在我们的性能测试中,我们以 100 位推测的安全性为目标,并使用产生最佳证明时间的参数。 具体来说,我们使用了 90 Merkle 查询、2 倍放大系数和 10 位工作量证明挑战。

下表总结了上述框架以及我们性能测试中使用的相关配置。 这个列表绝不是详尽的,我们还将在未来研究许多最先进的框架/技术(例如,Nova、GKR、Hyperplonk)。

请注意,这些性能测试结果仅适用于电路开发框架。 我们计划在未来发布一篇单独的文章,对不同的 zkVM(例如,Scroll、Polygon zkEVM、Consensys zkEVM、zkSync、Risc Zero、zkWasm)和 IR 编译器框架(例如,Noir、zkLLVM)进行性能测试。

框架

算术化

算法

数域

其他配置

Circom + snarkjs / rapidsnark

R1CS

Groth16

BN254 scalar

 

gnark

R1CS

Groth16

BN254 scalar

 

Arkworks

R1CS

Groth16

BN254 scalar

 

Halo2 (KZG)

Plonkish

KZG

BN254 scalar

 

Plonky2

Plonk

FRI

Goldilocks

blowup factor = 8

proof of work bits = 16

query rounds = 28

num_of_wires = 60 num_routed_wires = 60

Starky

AIR

FRI

Goldilocks

blowup factor = 2

proof of work bits = 10

query rounds = 90

性能评测方法论

为了对这些不同的证明系统进行性能测试,我们计算了 N 字节数据的 SHA-256 哈希值,其中我们对 N = 64、128、...、64K 进行了实验(Starky 是一个例外,其中电路重复 SHA-256 固定 64 字节输入的计算,但保持相同的消息块总数)。 可以在此存储库中找到性能代码和 SHA-256 电路配置。

此外,我们使用以下性能指标对每个系统进行了性能测试:

  • 证明生成时间(包括见证生成时间)

  • 证明生成期间的内存使用峰值

  • 证明生成期间的平均 CPU 使用率百分比。 (该指标反映了证明生成过程中的并行化程度)

请注意,我们正在对证明大小和证明验证成本做一些“随意”的假设,因为这些方面可以通过在上链之前与 Groth16 或 KZG 组合来减轻。

机器

我们在两台不同的机器上进行了性能测试:

  • Linux 服务器:20 核 @2.3 GHz,384GB 内存

  • Macbook M1 Pro:10 核 @3.2Ghz,16GB 内存

Linux 服务器用于模拟 CPU 核数多、内存充裕的场景。 而通常用于研发的 Macbook M1 Pro 拥有更强大的 CPU,但内核较少。

我们启用了可选的多线程,但我们没有在此性能测试中使用 GPU 加速。 我们计划在未来进行GPU 性能测试。

性能评测结果

约束数量

在我们继续讨论详细的性能测试结果之前,首先通过查看每个证明系统中的约束数量来了解 SHA-256 的复杂性是很有用的。 重要的是要注意不能直接比较不同算术方案中的约束数量。

下面的结果对应 64KB 的原像尺寸。 虽然结果可能因其他原像尺寸而异,但它们可以粗略地线性缩放。

  • Circom、gnark、Arkworks 都使用相同的 R1CS 算法,计算 64KB SHA-256 的 R1CS 约束数量大致在 30M 到 45M 之间。 Circom、gnark 和 Arkworks 之间的差异可能是由于配置差异造成的。

  • Halo2 和 Plonky2 都使用 Plonkish 算术,其中行数范围从 2^22 到 2^23。 由于使用查找表,Halo2 的 SHA-256 实现效率比 Plonky2 的高得多。

  • Starky 使用 AIR 算法,其中执行跟踪表需要 2^16 个转换步骤。

证明系统

约束数量 (64KB SHA-256)

Circom

32M

gnark

45M

Arkworks

43M

Halo2

4M rows (K=22)

Plonky2

8M rows (K=23)

Starky

2^16 transition steps

 

证明生成时间

 

[图 1] 使用 Linux 服务器测试了 SHA-256 的每个框架在各种原图像尺寸上的证明生成时间。 我们可以得到以下发现:

  • 对于 SHA-256,Groth16 框架(rapidsnark、gnark 和 Arkworks)生成证明的速度比 Plonk 框架(Halo2 和 Plonky2)快。 这是因为 SHA-256 主要由位运算组成,其中线值为 0 或 1。对于 Groth16,这减少了从椭圆曲线标量乘法到椭圆曲线点加法的大部分计算。 但是,连线值并不直接用于 Plonk 的计算,因此 SHA-256 中的特殊连线结构不会减少 Plonk 框架中所需的计算量。

  • 在所有 Groth16 框架中,gnark 和 rapidsnark 比 Arkworks 和 snarkjs 快 5 到 10 倍。 这要归功于它们利用多个内核并行化生成证明的卓越能力。 Gnark 比 rapidsnark 快 25%。

  • 对于 Plonk 框架,当使用 >= 4KB 的较大原像尺寸时,Plonky2 的 SHA-256 比 Halo2 的慢 50%。 这是因为 Halo2 的实现主要使用查找表来加速按位运算,导致行数比 Plonky2 少 2 倍。 但是,如果我们比较具有相同行数的 Plonky2 和 Halo2(例如,Halo2 中超过 2KB 的 SHA-256 与 Plonky2 中超过 4KB 的 SHA-256),Plonky2 比 Halo2 快 50%。 如果我们在 Plonky2 中使用查找表实现 SHA-256,我们应该期望 Plonky2 比 Halo2 更快,尽管 Plonky2 的证明尺寸更大。

  • 另一方面,当输入原像尺寸较小(<=512 字节)时,由于查找表的固定设置成本占大部分约束,Halo2 比 Plonky2(和其他框架)慢。 然而,随着原像的增加,Halo2 的性能变得更具竞争力,对于高达 2KB 的原像大小,其证明生成时间保持不变,如图所示,其几乎呈线性扩展。

  • 正如预期的那样,Starky 的证明生成时间比任何 SNARK 框架都短得多 (5倍-50倍),但这是以更大的证明大小为代价的。

  • 另外需要注意的是,即使电路大小与原像大小成线性关系,由于 O(nlogn) FFT,对于 SNARKs 的证明生成也是呈超线性增长的(尽管由于对数刻度,这一现象在图表上并不明显)。

我们还在 Macbook M1 Pro 上进行了证明生成时间性能测试,如 [图 2] 所示。 但是,需要注意的是,由于缺乏对 arm64 架构的支持,rapidsnark 未包含在该性能测试中。 为了在 arm64 上使用 snarkjs,我们必须使用 webassembly 生成见证,这比 Linux 服务器上使用的 C++ 见证生成要慢。

在 Macbook M1 Pro 上运行性能测试时还有几个额外的观察结果:

  • 除了 Starky 之外,所有 SNARK 框架在原像尺寸变大时都会遇到内存不足 (OOM) 错误或使用交换内存(导致证明时间变慢)现象。 具体来说,Groth16 框架(snarkjs、gnark、Arkworks)在原像尺寸>= 8KB 时就开始使用交换内存,而 gnark 在原像尺寸>= 64KB 时出现内存不足。 当原像尺寸>= 32KB 时,Halo2 遇到了内存限制。 当原像尺寸>= 8KB 时,Plonky2 开始使用交换内存。

  • 基于 FRI 的框架(Starky 和 Plonky2)在 Macbook M1 Pro 上比在 Linux 服务器上快大约 60%,而其他框架在两台机器上面的证明时间相似。 因此即使在 Plonky2 中没有使用查找表,它在 Macbook M1 Pro 上实现了与 Halo2 几乎相同的证明时间。 主要原因是 Macbook M1 Pro 拥有更强大的 CPU,但内核更少。 FRI 主要进行哈希运算,对 CPU 时钟周期比较敏感,但并行性不如 KZG 或 Groth16。

 

内存使用峰值

[图 3] 和 [图 4] 分别显示了在 Linux Server 和 Macbook M1 Pro 上生成证明期间的内存使用峰值。 根据这些性能测试结果可以得出以下观察结果:

  • 在所有 SNARK 框架中,rapidsnark 是内存效率最高的。 我们还看到,由于查找表的固定设置成本,当原像尺寸较小时,Halo2 使用更多内存,但当原像尺寸较大时,整体消耗的内存较少。

  • Starky 的内存效率比 SNARK 框架高 10 倍以上。 部分原因是它使用了更少的行。

  • 应该注意的是,由于使用交换内存,原像尺寸变大,因此 Macbook M1 Pro 上的内存使用量峰值保持相对平稳。

 

CPU 利用率

我们通过测量 SHA-256 在 4KB 原像输入的证明生成期间的平均 CPU 利用率来评估每个证明系统的并行化程度。下表显示了 Linux Server(20 核)和 Macbook M1 Pro(10 核)上的平均 CPU 利用率(括号中为每个内核的平均利用率 ) 。

主要观察结果如下:

  • Gnark 和 rapidsnark 在 Linux 服务器上表现出最高的 CPU 利用率,表明它们能够有效地使用多核且并行化生成证明。 Halo2 也展现了良好的并行化性能。

  • 大多数框架在 Linux 服务器上的 CPU 利用率是在 Macbook Pro M1 的 2 倍,只有 snarkjs 例外。

  • 尽管最初预计基于 FRI 的框架(Plonky2 和 Starky)可能难以有效地使用多核,但它们在我们的性能测试中的表现并不比某些 Groth16 或 KZG 框架差。 在具有更多内核(例如 100 个内核)的机器上,CPU 利用率是否会有差异还有待观察。 

证明系统

CPU 利用率(平均每核利用率)

(Linux 服务器)

CPU 利用率(平均每核利用率)

(MBP M1)

snarkjs

557% (27.85%)

486% (48.6%)

rapidsnark

1542% (77.1%)

N/A

gnark

1624% (81.2%)

720% (72%)

Arkworks

935% (46.75%)

504% (50.4%)

Halo2 (KZG)

1227% (61.35%)

588% (58.8%)

Plonky2

892% (44.6%)

429% (42.9%)

Starky

849% (42.45%)

335% (33.5%)

 

结论及未来研究

这篇文章全面比较了 SHA-256 在各种 zk-SNARK 和 zk-STARK 开发框架上的性能测试结果。 通过比较,我们深入了解了每种框架的效率和实用性,以期可以帮助需要为SHA-256 操作生成简洁证明的开发者。 我们发现 Groth16 框架(例如 rapidsnark、gnark)在生成证明方面比 Plonk 框架(例如 Halo2、Plonky2)更快。 Plonkish 算术化中的查找表在使用较大的原像尺寸时显着减少了 SHA-256 的约束和证明时间。 此外,gnark 和 rapidsnark 展示了利用多核以并行化运作的出色能力。 另一方面,Starky 的证明生成时间要短得多,但代价是证明大小要大得多。 在内存效率方面,rapidsnark 和 Starky 优于其他框架。

 

作为构建零知识证明评测平台 「万神殿 Patheon」 的第一步,我们承认本次性能测试结果远不足以成为最终我们希望构建的一个综合测试平台。 我们欢迎并乐于接受反馈和批评,并邀请所有人为这项倡议做出贡献,以便开发者更容易、低门槛地使用零知识证明。 我们也愿意为个人独立贡献者提供资助,以支付大规模性能测试的计算资源成本。 我们希望可以共同提高 ZKP 的效率和实用性,更为广泛地造福社区。

 

最后,我们要感谢 Polygon Zero 团队、Consensys 的 gnark 团队、Pado Labs 以及 Delphinus Lab 团队,感谢他们对性能测试结果的宝贵审查和反馈。