SP1 是一种基于 RISC-V 指令集和 STARK 的 zkVM 证明系统,支持递归证明,可以将 STARK 证明转换为 SNARK 证明。文章详细介绍了 SP1 的证明过程、分片证明的生成,递归证明的生成,并与 RISC0 进行了对比,最后评估了 SP1 zkVM 在生成 Taiko 块证明时的性能,包括运行时间、CPU 使用率和内存消耗。
TL;DR(太长不看)
SP1 是一个基于 RISC-V 指令集和 STARK (Scalable Transparent Argument of Knowledge,可扩展的透明知识论证) 的 zkVM (zero-knowledge Virtual Machine,零知识虚拟机) 证明系统。它支持递归证明,能够为任何程序的执行过程生成大小相同的证明。此外,SP1 可以使用 Groth16 或 Plonk 将通过递归获得的 STARK 证明转换为 SNARK 证明,进一步压缩证明大小。
由于 SP1 的证明过程与 RISC0 的证明过程类似,并且我们之前已经分析过 RISC0 的证明过程 ( https://medium.com/p/0666216b654b/edit ),我们将简要介绍 SP1 的证明过程和关键步骤。在此之后,我们将它与 RISC0 进行比较,最后讨论证明 Taiko 区块时的性能、CPU 和内存使用情况。
图 1. SP1 zkVM 证明过程
如上图所示,对于要证明的程序(由大量 RISC-V 指令组成,由 Rust 等高级语言编译而来)及其给定的输入,SP1 zkVM 执行该程序并生成一个证明文件,以验证该程序是否已正确执行。此证明文件不得包含任何敏感信息,例如执行过程中生成的数据或私有输入。
为了实现这一点,SP1 zkVM 执行以下步骤:
A. 执行程序,将其拆分为多个 Shards/Checkpoints(分片/检查点),并记录执行每个 Shard 所需的所有内存数据。
B. 使用 STARK 协议单独为每个 Shard 生成证明。
C. 通过递归证明将上一步骤中的证明合并为单个证明,确保不同大小的程序的证明结果都是长度相同的证明文件。
D. 使用 Groth16 或 Plonk 将递归证明生成的证明转换为 SNARK 证明,进一步减小证明大小。由于生成 Shard 证明消耗的内存和计算资源最多,因此以下部分将简要解释 Shard 证明生成过程。
图 2:Shard 证明生成过程
如上图所示,在为程序生成 Shard 证明时,SP1 采用三个独立的线程:Checkpoint Generation(检查点生成)、Trace Generation(Trace 生成)和 Shard Proof Generation(Shard 证明生成)。这使得可以并行处理多个任务,从而显着提高性能。
详细信息如下:
A. Checkpoint Generation Thread(检查点生成线程)。此线程执行要证明的程序,根据预定义的 Shard 大小将其拆分为多个 Shard,并记录每个 Shard 中的指令以及执行它们所需的内存数据。
B. Trace Generation Thread(Trace 生成线程)。对于 Checkpoint 线程生成的每个 Shard,此线程按顺序执行 Shard 中的指令,记录寄存器状态和内存访问模式,并最终生成一个正常的执行 Trace。值得注意的是,所有 Shard 都是独立处理的,允许硬件加速(例如,GPU 或多 CPU 并行)以实现高性能。
C. Shard Proof Generation Thread(Shard 证明生成线程)。使用 STARK 协议,此线程为从 Trace 线程获得的 Trace 生成承诺和打开证明,从而生成最终的 Shard 证明。
最终证明的大小大致与要证明的程序的执行 Trace 的长度成正比。换句话说,程序越长,生成的 Shard(以及相应的 Shard 证明)就越多,而证明大小是证明系统的关键指标(因为证明必须从证明者传输到验证者)。
为了最大限度地减少最终证明的大小,SP1 支持使用 STARK 协议将成对的相邻 Shard 证明压缩为 Reduce Proofs。然后,这些 Reduce Proofs 会被进一步递归压缩,直到生成单个根证明。这确保了无论程序大小如何,最终证明的大小都将是固定长度的。
最后,递归树底部的根证明被包装成与 Groth16 兼容的证明,以便在链上进行高效验证。图 3 说明了这个过程。
图 3:SP1 递归证明(来源:SP1 技术白皮书 —— 简洁性)
5.1. 相似之处
基本原理:它们的基本原理没有根本区别。如图 1 和图 4 所示,两个证明过程都遵循以下步骤:
图 4:RISC0 证明过程(来源:https://dev.risczero.com/proof-system/)
A. 将程序拆分为多个部分(RISC0 中为 Segments,SP1 中为 Shards)。
B. 使用 STARK 为每个部分生成证明。
C. 通过基于 STARK 的递归证明以递归方式合并证明。
D. 将最终的递归证明转换为与 Groth16 兼容的证明以进行验证。
两个证明系统所基于的有限域是相同的有限域结构:基础域:BabyBear,扩展域:4 度扩展。
5.2. 差异
实现透明度:SP1:完全开源的 CPU 实现(GPU 实现是闭源的)。代码是模块化的,更容易审计。RISC0:关键组件(例如,Trace 生成、多项式检查)是通过 Zirgen 自动生成的,这使得代码更难理解或修改。
硬件加速:SP1:针对 AVX256/512 和 CUDA(闭源 GPU 代码)进行了优化。RISC0:不支持 SIMD,但支持 Metal(Apple GPU)和 CUDA。
Precompile 支持:SP1:允许自定义 precompiles(例如,椭圆曲线运算),通过手动设计 Trace 表和约束,减少 Trace 长度并提高性能。RISC0:Precompiles 是通过 Zirgen 自动生成的,限制了用户添加自定义电路的灵活性。证明生成
依赖关系:SP1:依赖于 Plonky3 库(开源)来实现承诺、FRI 和其他证明组件。RISC0:内部实现所有组件。
为了评估 SP1 在证明生成方面的性能,我们测试了一个实际用例:使用 SP1 生成 Taiko 区块的证明,并在本地验证其正确性。
我们测量了运行时间、CPU 使用率和内存消耗。结果如下。
测试配置:硬件:AMD Ryzen 9 9950X 16 核处理器,96 GB 内存。区块详细信息:Gas limit 为 5,944,801(590 万),证明生成期间统计的总周期数:488,808,529(4.88 亿)。
结果:总证明生成时间:约 1.5 小时。Shard 证明阶段:约 1 小时,在最终 Shard 证明生成期间内存峰值达到 50 GB。递归证明阶段:约 0.5 小时,主要用于合并证明。CPU 和内存使用率:下图显示了证明生成过程中的 CPU 和内存利用率。
图 5:为 Taiko 区块生成 SP1 证明期间的 CPU/内存使用情况。
- 原文链接: medium.com/@CFrontier_La...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!