SNARK性能三要素
SNARK (Signal Controling,非交互知识参数)是一种用于发掘区块链可扩充性(如L2 Rollup)和隐私的关键代码。SNARK允许有人将某些数据(如一组有效的交易)展示给不信任的验证程序 V,比如以太坊区块链。最简单的方式就是向 V发送数据, V就能直接检验它的正确性。SNARK也能达到相同的效果,但是 V的代价要大得多。尤其是 SNARK的证明要比原始的证明更短,因为它包括了数据本身。
SNARK的认证费用也许会有差异,但是结果往往是非常好的。举例来说, PlonK的证明费用大约是29万美元,而 StarkWare则是500万美元。SNARK可以在区块链以外的多种设置中应用,比如,可以让你的服务器和硬件运行速度很快,但是不受信任。
但是 SNARK认证一般都是廉价的,所以适用范围的主要取决于 SNARK认证的费用。本文将说明如何估计这些费用,以便决定 SNARK在什么时候被合理地利用,并且在将来还会有什么方法来改善 SNARK。应该指出,这是一个迅速发展的领域,而本文所述的一些项目也在不断地改进它的性能。
怎样部署 SNARK?
在 SNARK部署中,开发者经常会写一种电脑程式ψ,把证人所说的资料 w当作输入(w表示验证者),然后检验 w是否有效。比如,在 Rollup里,这个程序会检测 w里的所有事务是否都是用数码方式签署的,它会使账户的结余降到0以下。然后,在 SNARK的前端输入一个程序ψ,这个程序会被编译为一个更好的 SNARK技术的应用。这个 SNARK友好的格式被称作“中间码”(IR).
一般而言, IR是一个相当于φ的电路满足度的例子。这就意味着, C的输入是由数据 w和其他的输入,这些输入通常被称作“不确定的推荐”,并且在 w上运行ψ。这些推荐的输入可以在使 C保持更少的 C的情况下,帮助 C执行ψ。比如,每次用 x和 y除x和 y,商的数量 q和余数 r都可以被推荐给 C, C只需对 x= qy+ r进行检验。这个检验要比让 C执行除法运算从零开始计算 q和 r要低得多。
RISC Zero的做法与 Cairo相似,但是其虚拟机是RISC-V结构,一个拥有大量软件生态的开放源码体系结构正在日益流行。作为一组简单的指令,使用 SNARK的有效支持其前端(至少与x86、 ARM等复杂架构相比)要容易得多。到五月为止, RISC Zero公司已经把原来的RISC-V指令转化成了3行和160列的5层 AIR。这相当于每个RISC-V CPU的至少500个门电路。预期在近期内还会有更多的改善。
诸如 zkSync2.0, Scroll, zkEVM等不同的 zkEVM项目将虚拟机用作以太坊虚拟机。与单纯的 Cairo和RISC-V体系结构相比,把每个 EVM指令转化成相应的“小工具”(也就是最优化的电路)。由于种种原因,有些 zkEVM工程没有直接执行 EVM的指令,而是把它编译为其它的汇编语言,然后再把它转换成一个更高级的 Solidity程序。目前还没有决定这些工程的绩效。
比如RISC-V和 Cairo公司的“CPU模拟器”计划,它会生成一个能在汇编语言中处理全部程序的单一电路。另外一种是与 ASIC芯片相似的,它可以根据不同的程序生成不同的电路。该方法与 ASIC相似,能使某些程序的电路更少,尤其是在每一时刻,程序所执行的汇编指令与程序的输入无关。比如,它可能彻底地避免了诸如初始矩阵乘法之类的线性编程的前端开销。但是 ASIC的方式看起来也很局限/我不知道怎样才能在没有事先定义好的迭代边界的情况下支持循环。
SNARK要多久才能扩充?
关键的问题在于 SNARK证明程序与单纯的重新处理数据相关,要花多少时间?答案是 SNARK的确认过程,与直接的验证器进行比较。后面的表达式是在最初的证明中,当 P向 V传送 w时, V用φ来检验 w的正确性。
将验证开销划分为“前端开销”与“后端开销”两种情况,具有一定的优势。如果一个接一个地运算 C的费用是一个运行ψ的 F,则我们把它叫做 F。如果使用后端确认器对 C的花费比逐个评价 C高出 B倍,则我们称之为 B。整个确认器的开销是 F乘 B。这种乘法代价很大,即便 F和 B都不是很大。
事实上, F和 B可能都大于1000。这就意味着,与直接验证员核实相比,该认证程序的总体费用可能在100,000至1000,000以上。在一台手提电脑上运行一秒钟的程序,很可能会使 SNARK认证程序花费几十天甚至几百天(单线程)。所幸的是,工作一般是平行的(根据 SNARK)。
总的来说,如果您希望在您的应用中使用 SNARK,您需要符合下列三项之一:
1.不超过一秒,就可以在一台笔记本上进行验证。
2.在电路中尤其适用于直接验证器,所以前端的费用非常低。
3.您准备在 SNARK确认过程中等候多日,或者为大量的平行运算资源付费。
这篇文章后面的内容将说明前端和后台的开销是怎么来的,还有我怎样估计出各种 SNARK。并展望了今后的发展。
区别前后
由于不同的后台支持的电路种类不同,因此很难将前后端的区别开来。因此,前端可能会因其需要与其进行交互而变化。
最后一个前端开销是由所有 SNARK都在限制区域中运行的线路所决定的。你的手提计算机中的 CPU可以把两个整数乘以或相加,只需一条机器指令。只要前端输出电路具有较大的场域特征,基本上可以用对应的场运算对其进行仿真。但是,要在实际 CPU上执行字段,往往需要大量的计算机指令(虽然有些现代的处理器的确会支持特定的字段)。
有些 SNARK后台支持更多的域选项。比如,当一个后端使用一个加密的 G群时,这个电路的字段就会和 G中的单元数目相匹配。另外,在实际应用中, FFT算法也不是全部都能得到支持。
仅有一个 SNARK的实现,即 Brakedown,它支持任何(充分)域的计算。除了下一代,它在 SNARK所支援的域中,已经被公认为是最快速的,但是现在,它的证明对很多区块链应用程序而言都是过大的。近来的研究尝试改善证明的规模,但是证明程序太慢了,而且看起来不太实用。
一些工程会在计算速度非常高的地方工作。举例来说,Plonky2和其它的算法都采用了264-232+1的特征字段,这是由于这个字段的运算速度是非结构字段的数倍。但是,如果采用这么小的功能,就很难用域运算来表达整数的运算了。(举例来说,如果把一个32比特的无正负号整数与超过232的数值相乘,则会得到比字段特性更大的结果。所以,字段的选取当然只能是32位的运算。)
不过,不管怎么说,现在流行的 SNARK都要想达到128比特(无需大幅提高确认费用),就得在超过2128的网域上运行。就我所知道的,这就是说,每一个字段的运算都要用10次64位的计算机进行运算,还要加上大量的加、位操作。所以,因为电路必须要在有限的区域内工作,所以必须要考虑到至少一个量级的前端开销。
最后,在 C语言中引入了符合性电路 SNARK。这叫做 SNARK后台。在某些结构复杂的问题上,例如矩阵乘法、卷积以及某些图解问题, SNARK可以避免这些前端/后台设计,因此能够快速地进行验证。但是,这篇文章主要集中在一个共同的 SNARK上。
我们可以看出, SNARK后台的验证费用会随着 C的大小而增加。由于电路是一种非常有限的运算形式,所以使 C尽量小是一个难题。他们包括一扇门和一根导线。为每一门 g输入几个数值,然后将一个很简单的功能应用到它们上。然后,由 g所发射的线路把结果送到“下游”栅极。
SNARK的后台一般都支持一个被称为“运算”的电路,即一个电路的输入是一个有限区域的一个单元,并且这个单元的门可以对两个区域的单元进行相加和相乘。这些电路基本上与线性电脑程式(没有分支、条件语句等)基本相同,即其原始资料类型为栏位元件。
事实上,大多数的后台都支持大多数的运算电路,一般都是Rank-1限制满足(R1CS)。除了Groth16及其先驱外, SNARK还能用于其它 IR。比如, StarkWare采用了一种称为“代数中间表达”的方式,它与 PlonK以及其它后台支持的 PlonKish算术操作相似。有些后端能够支持更多的通用 IR,可以降低前端生成 IR的费用。
后台也会因为它的本地支持有限的域而变化。我会在下一节中对此进行更深入的探讨。
多个前端方式
有些电脑程序(很特别)与算数电路相对应。例如,一个电脑程序,它可以在特定的区域上进行简单的矩阵乘法。但是大部分电脑程式都没有线性或代数。这些操作一般涉及条件语句,整数除法,浮点数操作等,这些操作都是与有限区域操作不相适应的。在这种情形中,前端的费用会很高。
一种流行的前端处理方式是产生一个基础电路,并通过一步一步的方式来实现某些所谓的虚拟机。前端设计者会规定一套与真实的电脑处理器相似的基础动作集。如果开发者希望使用前面的话,可以直接用汇编语言写一个"验证器检验器",或者用高级的语言例如 Solidity来写一个"验证器检验器",并将其程序自动地编译为一个汇编代码。
比如, StarkWare的 Cairo就是一个很有限制的汇编语言,它的汇编指令可以在有限的区域里做一些简单的加、乘操作,函数调用,以及读取和写入不能改变的内存。Cairo VM是冯·诺伊曼体系结构,它的前端所生成的电路实质上是把 Cairo程序当作一个共同的输入,并且在目击者的面前运行。Cairo语言是一个完整的图灵,虽然其指令集很少,但是可以模仿更多的标准体系结构,虽然代价高昂。Cairo前端把 Cairo程序转化成了“2层 AIR, T行,50列左右。”不管这是怎么回事,但是 SNARK的证明,就像 Cairo CPU中的每一个 T步都有50至100个门电路。