撰文:Web3.com Ventures, @0xfishylosopher
编译:PANews, 王尔玉
注:本文技术含量较高,读者需要对zk-Proofs和/或zk-Rollups的概念有基本了解。
引言
零知识证明,尤其是 zk-SNARKs(零知识简洁非交互知识论证),或许是Web 3最重要的前沿技术之一。目前,该子领域的大部分媒体和投资注意力都放在了zk-Rollups上面,这是为以太坊等L1区块链提供大规模可扩展性的扩展方案,尽管如此,zk-Rollups绝非zk-SNARKs的唯一用途。本文将深入分析零知识汇编代码(zkASM)概念,评估其在zk-Rollups及其他方面的用例,从理论层面探索其在重新发明互联网方面的潜能。
技术原理
顾名思义,zk-ASM主要包含两个技术组成:ZK和ASM。ZK指zk-SNARKs,即简洁非交互知识论证,ASM指汇编代码(Assembly code)。要了解zk-ASM的潜能,首先要了解这两个看似晦涩的概念的理论基础。
zk-SNARKs
zk-SNARKs是zk-Proofs皇冠上的明珠:它是一种判断某项陈述为“真”的简洁证明方法,且不会暴露任何关于被证明数据的信息。例如,假设有人宣称“我知道存在一个m,可以使C(m) = 0”,其中m是一条千兆字节的信息,C是函数。zk-SNARK将构成一个简短证明(< 1GB),快速验证m的存在,同时不会暴露任何关于m的信息(公开信息除外)。
这个“C(m)”到底是什么?有何用处?这个函数实际上是一个运算电路,或者说是我们要执行的具体函数的有向无环图(DAG)表征,如图所示。本质上,“m”是电路的入口数据,电路中的具体“节点”是单独的逻辑门或运算。例如,“+”节点上可输入“2”和“3”,然后将“5”输出至下一个运算符。如此便可在“运算电路”中对任意算术或逻辑运算进行编码。
运算电路示例。来源:https://cs251.stanford.edu/lectures/lecture14.pdf
将我们要运行的zk-SNARK代码用运算电路表示后,就可以开始构建这个zk-SNARK了。从根本上说,zk-SNARK的可行性是由“代数基本定理”奠定的,根据代数基本定理,“d”次多项式最多有“d”个根。这一数学技巧分为两步:(1)将需要证明的函数“f(m)”转换为多项式,并持续使用该多项式,以及(2)使用“代数基本定理”处理该多项式,并提供简洁证明。用技术术语来说,第一部分称为“多项式承诺方案”(PCS),第二部分称为“多项式交互预言证明”(PIOP)。
高效的通用电路SNARK的组成。来源:https://cs251.stanford.edu/lectures/lecture15.pdf
PCS和PIOP的具体实现方式超出了本文的范围,但我们可藉此得出zk-SNARK核心步骤的粗略草图:
- 选定一个希望在其上运行zk-SNARK的函数(代码函数、数学方程等)
- 将该函数编码为运算电路C(m)
- 运行PCS,得出该运算电路的多项式表征
- 运行PIOP,得出log(m) 大小的简洁证明
现在就有了一个定制的zk-SNARK了,它可以证明某人知道某信息,而又不会暴露信息的具体内容。
汇编代码
zk-ASM的第二块拼图是汇编代码。这是一种包含非常低级的语言指令的类语言,机器易于阅读,但人类很难破译。不同于Python、Java甚至C语言等高级语言,汇编语言包含一些非常原始的函数,及在处理器和寄存器级别的MOVE (移动)、CMP (比较)、ADD (加法)、和JMP (跳转)。例如,在屏幕上打出数字1到9的Python代码为`123456789`:
很好懂吧?再来看看它的x86汇编版本:
实在麻烦多了,这还只是处理一个非常简单的操作。既然如此,干嘛要使用汇编语言呢?如上文所述,虽然这些指令不易被人类阅读,但它们很容易“汇编”为`110011001`的字节代码,供机器读取和执行(称为汇编器)。相比之下,Python、Java等高级语言虽然更易读,但处理器无法直接执行这些语言编写的程序。我们需要“编译器”来将我们编写的Python或Java代码转换为上面那样的汇编代码,交给机器汇编和执行。同一段Python或Java代码之所以能在不同处理器和操作系统上流畅运行,是因为编译器完成了繁重的工作,将源代码编译为了针对具体处理器或操作系统的汇编语言。
因为所有语言都能编译成汇编代码(汇编代码本身还会进一步编译成可执行的二进制文件),所以汇编本质上就像“一切语言之母”。现在假设我们能将一种汇编语言(如x86或RISC-V)中的所有运算对象转换为运算电路表征,我们便可提供这一汇编语言中所有运算对象的zk-SNARK证明。理论上,这意味着我们能为一切使用任意可编译为汇编语言的高级语言(如Python或Java)编写的程序提供zk-SNARK。正因为此,zk-ASM值得我们仔细钻研。
实际应用
zk-EVM Rollups:Polygon zk-ASM
zk-ASM最重要的应用之一是创建与以太坊虚拟机兼容的zk-Rollups,或zk-EVM。zk-EVM对于区块链的可扩展性非常重要,因为藉此,程序员无需对代码进行过多(或任何)修改,便可在基于zk-Rollup的L2链上进行部署。在这方面,Polygon的zk-EVM是一个典型案例,它展现了如何使用zk-ASM来实现这一目标。
EVM与Polygon zk-EVM技术架构对比。
以太坊L1公链上的开发者通常使用Solidity语言,这是一种类似于C语言的高级编程语言。Solidity代码在L1区块链上运行前首先会被编译成一系列EVM操作代码,如ADD、SLOAD、EQ等。默认情况下,这个过程显然不会创建任何zk-Proof。Polygon的巧思是创建一种方法,将每个EVM操作代码翻译至他们自定义编写的zk-ASM中,这对zk-SNARK非常友好。然后,他们的L2 zk-EVM会执行zk-ASM,同时创建ASM的zk-SNARK电路,以创建zk-SNARK证明。例如,EVM中的ADD操作代码将被翻译成Polygon的zk-ASM,如下所示:
EVM ADD操作代码的Polygon zk-ASM翻译示例。来源:https://wiki.polygon.technology/docs/zkEVM/zkASM/some-examples
由于Polygon zk-EVM的戏法发生在汇编层级,它比普通以太坊接触的代码层, “Solidity” 层,要“低”两层。 正因为此,多数开发人员可将他们为以太坊主网构建的EVM代码直接移植到Polygon zk-EVM。同时,Polygon zk-EVM一直到操作代码层级都“保留”了以太坊的技术堆栈,所有依赖于分析已编译的操作代码的调试基础设施仍可完整使用。这不同于其他不在操作代码级别提供zk-Proof的zk-EVM设计,例如zk-Sync。因此,尽管Polygon发明和验证了自己的汇编语言,如V神所说,“它仍然可以验证EVM代码,只是使用了不一样的内部逻辑。”
超越Rollups:zk-WASM
zk-EVM绝非zk-ASM的唯一用例。上文说过,汇编语言本质上是“一切语言之母”,而创建zk-ASM将为使用任何可编译为汇编语言的语言编写的通用程序解锁zk-Proofs。Web Assembly(WASM)是最重要的新兴汇编语言之一,最早发布于2018年,旨在提高Web应用的执行速度,以及为Javascript(Web背后的主要编程语言)提供执行补充。
本质上,随着Web的多年发展,Web应用程序的规模和复杂性不断提升,这意味着浏览器要编译所有用Javascript编写的内容,速度经常奇慢无比,而且要不断重复复杂的“编译-优化-重新加载”流程。WebAssembly通过提供便携、模块化且易于执行的汇编语言,消除了对复杂的浏览器执行引擎的依赖。此外,WASM作为一种汇编语言,允许程序员使用C、C++、Rust、Java或Ruby等可直接在浏览器中运行的语言来编写代码段。WASM因此成为了“提供分布式无服务器功能”的首选技术。
zk-SNARKs在这方面能发挥什么作用呢?WASM的独特之处在于它是一种客户端技术,能直接与用户输入的数据进行交互。这通常包括密码和个人信息等敏感数据,因此我们需要一种技术(1)确保程序准确执行,以及(2)确保敏感信息不被泄露。zk-SNARK正是应对这两个问题的完美解决方案,因此也是成就WASM的重要拼图。
开发zk-WASM的工作仍处于早期阶段,但最近一些项目发布了用于WebAssembly的原型zk-SNARK电路。例如,Delphinus Lab的“ZAWA”zk-SNARK模拟器带来了一种将WASM虚拟机的运算对象和语义编码至运算电路中的方法,使其能够得出zk-SNARK证明。zk-WASM电路一定会持续优化,藉此,使用通用语言(如C、C++、Rust和Ruby)编写的程序将能采纳zk-Proofs的范式。
结论
本文探索了zk-ASM的理论基础,研究了zk-ASM的两个范式用例:Polygon利用zk-ASM创建了操作代码层级的zk-EVM;以及对WebAssembly应用zk-SNARKs,以创建zk-WASM。最终,zk-ASM有望将Web 2的互操作性和规模与Web 3的无需信任和安全性结合起来。
一方面,区块链越来越多地寻求突破当前的处理量瓶颈,另一方面,Web 2方法因未能充分保护用户数据和隐私,受到了越来越多的挞伐。随着程序员能够在Web 2代码中使用Web 3设计范式,并将Web 2语言和代码引入区块链,通用zk-ASM有望成为Web 2和Web 3世界的一个交汇点。有鉴于此,zk-ASM或许能让我们重新构想一个更安全和无需信任的互联网。