过程
-
环境安装
1.1安装circom
安装rust环境
安装成功
编译circom
编译完成
安装circom
安装完成
1.2安装snarkjs
安装npm
Snarkjs安装完成
2.构建电路与证明的准备部分
2.1准备工作--电路部分
准备好一个电路文件 circuit.circom
这里用ri参数可以查看电路信息(或者用r1cs info也可以)
使用rp参数查看电路中的约束(或者用print r1cs也可以)
准备好一个输入电路文件 input.json(字符串形式输入a,b)
执行命令生成witness文件
生成cpp文件
2.2准备工作--可信设置部分
Groth16
第一部分:τ的幂次(与电路无关)
利用 new 命令生成τ的幂次,生成之后会在目录下得到一个 pot12_0000.ptau 文件
要用 contribute 命令,使用新的贡献来创建一个ptau文件
利用参数-e将命令变成非交互式,再执行一次contribution
更新完成之后,用 verify 命令验证截止至目前为止的ptau(只执行了一次更新,所以验证0001这个ptau文件)
这里注意一点,每当新的zk-snark需要执行可信设置时,只需要对最新的ptau文件执行verify命令,即可验证截止到目前为止的整个挑战和相应链
接下来是利用beacon命令创建一个ptau文件,这个ptau文件会以随机beacon的形式对ptau文件完成贡献,可信设置的第一阶段需要对其应用一个随机beacon
利用了以太坊第16668892个区块的Hash值作为beacon值,后面的参数10表示以该beacon值作为输入,计算2^10次Hash
第二部分:phase 2(这一部分取决于电路)
phase 2用到的命令为 prepare phase2 ,该命令会用到前面输出的 pot12_beacon.ptau 文件,并基于该文件计算拉氏插值多项式
用 verify 命令验证一下最终ptau文件
3.熟悉circom语法,根据要求编写下列circom电路,并以智能合约的方式完成验证
准备完毕之后,接下来是根据电路构建证明与验证密钥
3.1密钥生成
首先需要用电路和上面的最终ptau文件生成一个zkey文件,该文件是一个零知识密钥文件,包含phase2的所有贡献,以及用于证明和验证的密钥,利用这个zkey文件可以验证其是否属于特定的电路
这里得到的 circuit_0000.zkey 文件不包含任何贡献,不能用于最终电路的证明,因此需要执行前面的贡献更新步骤。接下来使用 zkey 命令来对zkey文件进行贡献更新(前面用的是 powersoftau 命令,基本流程是一样的)
更新贡献
验证
然后引入随机beacon值:
验证:
验证通过
基于该zkey文件,导出一个验证密钥,导出的密钥为json格式。导出json文件
3.2证明生成
利用电路和证明密钥来构建证明
命令执行完毕后,可以得到两个json文件,一个是 public.json ,也就是statement. 另一个是 proof.json ,里面包含用于验证的元素
3.3验证
验证通过
修改public.json的值“33”为“32”再次验证
验证不通过
或者修改proof.json中的群元素pi_a,将首位数字2改为1
验证也不通过
3.4模拟执行
将验证密钥导出为Solidity智能合约,就可以将这个合约发布到链上了
snarkjs给了一个模拟验证执行的命令,利用上面的两个json文件可以模拟Verifier在remix中的验证过程
输出是三个群元素和公共输入,均编码为HEX形式
这里Verifier会调用verifyProof函数来对上述这堆东西进行验证,这里可以把上面的那个智能合约导入到
remix来模拟一下,这里给一个网址:http://remix.ethereum.org/
进去之后,先把刚刚导出的sol文件上传
导入sol文件
编译刚刚上传的智能合约文件
下面有一个已部署的智能合约,把上面得到的那一串数字粘贴到verifyProof里面,点一下call来调用智能合约
右侧主界面可以看到正在调用,decode output这里输出true ,验证通过