snarkjs学习

Tiny Hill

新开一个贴来学习zk-snark的一个工具snarkjs,之前看过很多zk的帖子,但是对于数学基础弱的人来说,看起来还是太累了,而且很多原理上的东西,做应用的人确实也不需要太理解。这次尝试从工具的角度入手,看看zk到底是干什么的。

https://github.com/iden3/snarkjs

0x01

什么是ZK(零知识证明)?已经有太多介绍,这里就简单带过,零知识证明使我们能够证明自己的某些特定特征,而无需透露任何额外的信息。零知识证明在加密货币中有非常多的应用,特别是在隐私方面。著名的应用有zcash隐私币和tornado cash混币器。其次是在扩容方面,zk-rollup是理想的layer2扩容方案

0x02

zkSNARK 是零知识证明 的一种形式。 zkSNARK 很简洁,可以被快速验证,验证时间不会随验证计算量的增长而线形增加。 zkSNARK 是非交互式的,证明者和验证者之间少有交互,因此也更高效。snarkjs是 zkSNARK 和 的 JavaScript 和 纯 Web Assembly 实现。

0x03

该库中用于多方计算(MPC)的格式与 Semaphore 的 Perpetual Powers of Tau 和其他实现中使用的格式兼容。该库使用由 circom 编译器生成的编译电路。
上条和该条可能看不懂,先不着急,往下看。

0x04

库的guide中,第一步就是Start a new powers of tau ceremony。这是为了完成 zkSNARK 的一个前置 “trusted setup”,即在一个可信的环境中生成一些参数。这些参数通常是一些随机值,用于生成公开的密钥和其他必要的参数,以便进行零知识证明。这些随机值必须严格保密,否则就会破坏协议的安全性。

0x05

因此,这个 “trusted setup” 的目的是为了确保这些随机值只有在生成参数的时候使用,并且不会被泄露。在这种情况下,只有在 “trusted setup” 的过程中的参与者是可信的,才能确保 zkSNARK 协议的安全性。

0x06

库的教程中,前8步都是构建”trusted setup” 的过程,具体干什么事情,先不用太在意。接下去就是构建电路(circuit),zksnarks 不能直接应用于任何计算问题。在使用之前,首先需要将问题转换为代数电路。此处参考
https://w3hitchhiker.mirror.xyz

0x07

配套snarkjs有一个电路设计语言和工具库circom,https://github.com/iden3/circom,来进行电路逻辑的编码和编译。图片是一个最简单的电路逻辑,有输入信号a和b,还有输出信号c,约束是 c=a*b。这个电路构造出的证明文件,在公开c和不公开a、b的情况下可以证明你确实知道a和b的数字。这是个非常简单的例子
例子

0x08

然后x.circom的电路代码会被编译生成 x.r1cs(r1cs 电路的二进制格式约束系统)和 x.wasm(wasm 代码用来生成见证 witness)。接下去就是要针对具体的输入内容来构造witness和proof,输入文件input.json包含a和b的值,使用snarkjs工具和上面的wasm来生成一个witness备用

0x09

接下来就是要构造证明了,先要生成一个私钥zkey,生成的过程很复杂不展开了,这个zkey会导出一个公开的verification_key.json后续用来验证证明。使用zkey和witness(由输入内容生成)可以计算出proof.json(证明文件)和public.json(公开信息,如上面提到的c)

0x0a

proof/public/verification_key这三个公开的文件就构成了证明的全部。验证者使用snarkjs工具可以验证证明者是否诚实(知道输入a和b的值),同时snarkjs还可以导出solidity验证代码和调用合约的calldata,https://gist.github.com/qiushaoxi/1db8a02efd2c2a57f49132ec9fada1a5 这是一段示例代码,大部分是密码学的逻辑,可以在remix跑一下试试

0x0b

简单总结一下,snarkjs/circom是一套工具,可以进行零知识证明的初始化、电路编译、密钥生成、witness生成、执行电路生成证明以及证明验证的功能。除此之外还可以生成用来验证的solidity合约代码。其实大部分跑在以太坊上的zk应用大体也是这样的步骤,知识逻辑会复杂很多。

0x0c

通过对snarkjs的浅浅的学习,对zksnark和零知识证明应用是干什么的和怎么干的有了更多的了解和体会。希望可以帮到各位。

0x0d

在twitter搜了一下snarkjs,发现tornado-cash也是用snarkjs和circom来实现的,那么下期就继续学习tornado cash吧。