3 个版本

0.2.2 2024 年 8 月 6 日
0.2.1 2024 年 7 月 31 日
0.2.0 2024 年 7 月 5 日

#996 in 魔法豆

Download history 5800/week @ 2024-07-05 2591/week @ 2024-07-12 6546/week @ 2024-07-19 13138/week @ 2024-07-26 7656/week @ 2024-08-02 6655/week @ 2024-08-09

34,270 次每月下载
37 个crate中使用(5 直接使用)

MIT/Apache

3MB
63K SLoC

Boojum

Logo

zkSync Era 是一个使用零知识证明来扩展以太坊而不牺牲安全性和去中心化的第二层rollup。由于其与EVM兼容(Solidity/Vyper),99%的以太坊项目可以重新部署,无需重构或审计任何代码行。zkSync Era 还使用基于 LLVM 的编译器,最终将允许开发者使用 C++、Rust 和其他流行语言编写智能合约。

关于

此库的目的是与一个非常特定的算术化工作,并对字段大小进行额外的假设。大致来说,我们期望有一个字段 F,其|F| ~ 64位(机器字的大小)(关于字段大小的假设对算术化和门放置的策略不重要,但在特定函数的gadget实现中进行了断言,这些函数依赖于特定的字段大小)。

系统具有逻辑函数(部件)的层次结构 - 门(可以将其自身写入跟踪的实体) - 以及评估器(多项式之间的关系)。评估器以特性(trait)的形式编写,允许我们后来自动组合函数来检查可满足性和计算证明,以及合成普通和递归验证器。门附带了额外的工具,允许门本身跟踪它们应在跟踪中放置的逻辑。请注意,我们依赖于Plonk的复制约束,并基于“变量”的可复制逻辑实体来组合最终的可证明语句。该系统不是用于AIR算术化,也不允许表达跨越跟踪多行的约束。

一般来说,跟踪约束了少量列的变体。主要的区分是

  • 通用列 - 其中可以允许某些变量列(可复制的)、证人(不可复制的,有时也称为“建议”列)和常量由不同类型的门使用,从而导致在商多项式的前面放置选择器的必要性。对于这些通用列,放置逻辑很简单:我们试图将尽可能多的同一关系重复放入门/评估器允许的次数,基于系统中指定类型的相应列的数量。稍后,当选择器实现时,可以添加一些额外的常量列。一般来说,门默认的行为是尝试“摊销”常量,在某种意义上,在相同的行中,我们尝试放置使用相同常量的门。这是一个合理的做法,因为大多数电路在实践中都是“循环”,所以我们可以“填充”行。
  • “专用”列 - 其中可以将一组单独的列指定给特定的门/评估器,因此评估器强制执行的关系必须在这些列的每一行上成立。在某些电路中,如果某个门使用非常频繁,这可能是有益的。在为同一关系使用多个集合的情况下,可以指定这些列的几种不同利用模式,即是否在集合之间共享常量。

此外,跟踪允许您添加查找参数,这些参数也可以使用专用列来存放查找表的条目,或者只是使用通用列。目前,表仅编码为多项式集的一组,因此跟踪的总长度必须大于表中的条目总数。

请注意,每个“门”(作为Rust类型)都是唯一的,因此门只能放置在专用或通用列中,但不能同时放置。如果需要此类功能,则可以创建新的类型包装器。

高级逻辑函数(如布尔分解、范围检查、零检查等)用于使电路在内部以不同的方式记录自己,具体取决于某些门在CS的特定实例中是否允许。具有不同门集的CS实例被认为是Rust视角中的不同类型,我们依赖于某些内联/常量属性/编译器工作来减少分支到静态跳转。

关于构建子部分的说明

  • 仅实现了2^64 - 2^32 + 1字段。非向量化的数学实现基于为Plonky2开发的实现,但已重新构造成const特性
  • 主要对加法执行自动向量化,其中效益明显
  • Poseidon MDS和轮常量与Plonky2相同,以便与用户具有一些兼容性
  • Poseidon2轮常量重用了Poseidon常量
  • 算术化约束仅影响一行。放置策略是通过行列铺砖尽可能多地摊销常量
  • 复制排列参数来自Plonk(基于大积的)。以后可能会改为对数导数(加法的一个)
  • 查找参数是对数导数(加法的一个)
  • 目前,电路中的查找表必须具有相同的宽度
  • 无法将列从预言机中分离出来,并输入到另一个证明中
  • 目前,将移动到扩展域的操作仅在FRI聚合(因此在前一阶段挑战是|F|并且我们必须重复论证)上执行,但将进行更改,以便在提交见证后尽可能快地移动到扩展域,以避免分母中出现零的概率相当大。这在证明中的计算开销影响非常微小
  • 零知识尚未实现,但已计划(门本身将决定如何将其满意的、但随机的见证放入它们尚未使用的行)
  • FFT尚未优化
  • 哈希函数有所优化
  • 实现的门以及算术化都是具有偏见的

关于查找论证的说明

我们使用通过关系强制执行的查找论证\sum_i selector(x_i) / (witness(x_i) + beta) == \sum_i multiplicity(x_i) / (table(x_i) + beta)执行,其中对特殊列的查找selector(x_i)只是一个恒等式。我们也没有将表编码为较低阶的多项式以消除额外的度数界限检查,而是用零填充它们。请注意,表条目永远不会包含一个元素(0,0,...,0),因为我们使用单独的ID列来处理表类型,以防有多个表(即使只使用一个表),这样的ID从1开始。

这种查找参数的一个优点是,由于其加性本质,如果我们对多个witness多项式进行查找,而不是为每个(多项式)元组重复论证(这将需要一个单独的次数列,以及后续一些中间多项式),我们可以“相加”次数,并将论证转化为类似以下形式:\sum_i selector_0(x_i) / (witness_0(x_i) + beta) + \sum_i selector_1(x_i) / (witness_1(x_i) + beta) == \sum_i total_multiplicity(x_i) / (table(x_i) + beta),这样查找的总成本就只是一个次数列,以及2个(与见证相关的)+1个(与表相关的)中间多项式来编码根单位上的左右关系。

这个论证的正确性是明显的。对于可靠性,我们使用“快速查找的缓存商”论文中的原始论证,引理2.4。我们需要证明只需要对total_multiplicity进行承诺,而不是对witness_0witness_1的次数分别进行承诺。

假设以下方程成立:\sum_i selector_0(x_i) / (witness_0(x_i) + X) + \sum_i selector_1(x_i) / (witness_1(x_i) + X) == \sum_i total_multiplicity(x_i) / (table(x_i) + X)。我们需要证明witness_0witness_1包含在表t中。设f = (witness_0 | witness_1),为值的连接。上述方程意味着\sum_i selector_i / (f_i + X) == \sum_i total_multiplicity_i / (t_i + X)(注意LHS上i的区间长度是上面的两倍)。根据引理2.4,我们得到f \subset t:“子集”意味着向量f的每个坐标也是t的坐标。特别是,witness_0, witness_1 \subset f \subset t

请注意,上述论点也适用于多个witness_i。对于选定的\beta,其余的鲁棒性论证与上述工作直接相同。

计划扩展

  • 允许不同“宽度”的查找表(目前不太可能,我们需要稍微更新类型系统)
  • 将CS分成一个“可配置”的部分(可以允许门和静态工具),以及一个“可编写”的部分(可以放置变量、门等)。因此,首先配置,然后“冻结”,然后编写,并且在过程中不会出错
  • 允许替代选择器模式(对于需要它的罕见电路,用树代替单个实例)因为无论如何,我们都有大量的设置多项式,所以平面选择器并不昂贵,如果它们允许避免推动2x的商度
  • 让u16/u32使用“静态”缓存进行分解,而不是“动态”缓存
  • 制作“dyn”验证器,使其所有后代都是“Self”。注意:很可能是不必要的
  • 提前转移到域扩展“earlier”,因为它只影响复制排列乘积和查找论证部分,并且与2^-40的机会相比,得到0的分母是可接受的折衷
  • 切换到通用日志记录
  • 默认切换到Poseidon2
    • 关于单体:尽管它非常快,但它有一个缺点,即很难将其展开为单个“行”,因为它混合了查找和代数关系。它可能不适合大宽度电路实例
  • 实际上优化FFT
  • 检查在通用列上评估门的最优策略
  • 合并新的DAG解析器(10-100x更快)
  • 调整辅助查找多项式的致性检查,以利用如果它是“免费”的更高度约束(如果我们已经因为复制排列或门而进行更高度扩展,那么)

仅针对基准测试中的curions

对于8KB的SHA256,我们使用了我们认为相对最优的门和表配置来构建SHA256电路。请注意,尽管证明者运行得相当快,但我们并未对FFT进行适当优化,并且在预期证明将用于递归的场景中仍然使用了Poseidon(而不是Poseidon2)。两个脚本sha256_bench_recursive.shsha256_bench_non_recursive.sh允许您运行相应的测试(是否预期在递归中使用证明),您应该查找包含Proving is done, taken ...的行来查看证明时间,因为随后运行的验证器相当冗长。这些基准使用了8的LDE因子,尽管我们所有的约束都是4次或更低——然而,它是在一些其他公开基准中使用的一个参数。我们还在那些证明中不使用PoW,因为20位的PoW可以忽略不计(30ms),而且我们目前还不支持在代数散列上使用PoW(然而这些只有约2倍慢,所以也可以忽略不计)。安全性大约是100位,但可以通过增加查询次数来提高FRI的鲁棒性,而增加查询次数不会增加证明者时间(不要与改变FRI速率混淆)。跟踪长度是2^16,并使用了60个通用列和8个宽度为4的查找参数。

注意:基准测试仅尝试编译到本地架构,目前通常只对AArch64(即Apple M1)架构进行端到端测试。x86-64算术实现已通过验证性测试,但在完整证明中并未进行端到端测试。请注意,x86-64的最大性能需要额外的编译器功能标志,除了cpu = native(即使是在本地CPU上,Rust编译器也不使用AVX512集)之外。

许可证

Boojum证明者根据您的选择以以下条款之一进行分发:

任选其一。

免责声明

zkSync Era已经进行了大量测试和审计。尽管它已经上线,但仍然处于alpha状态,并将通过更多的审计和漏洞赏金计划。我们非常乐意听取社区对我们产品的想法和建议!重要的是要指出,现在分叉它可能会错过重要的安全更新、关键功能和性能改进。

第三方声明

此软件包含来自第三方的组件。有关这些组件及其许可证的完整列表,请参阅THIRD PARTY NOTICES文件

依赖项

~9MB
~171K SLoC