Appearance
1. INTRO:Circom、SnarJS & zkrepl
此处参考SnarkJS官方文档
Circom
代码
下面以一个简单的布尔可满足性问题为例:
js
pragma circom 2.1.6;
// proof (a or b) and (not c) == 1
template BoolSatisfy () {
signal input a;
signal input b;
signal input c;
signal output finalout;
signal invC <== 1 - 1*c;
signal orAB <== a + b - a * b;
signal out <== orAB * invC;
out === 1;
finalout <== out;
log("Assertion passed");
}
component main = BoolSatisfy();
/* INPUT = {
"a": "1",
"b": "0",
"c": "0"
} */编译
生成R1CS、WASM和符号文件:
bash
circom BoolSatisfy.circom --r1cs --wasm --sym -o output--r1cs:生成R1CS文件--wasm:生成WASM文件--sym:生成符号文件-o output:指定输出目录为output
sh
# output
template instances: 1
non-linear constraints: 2
linear constraints: 1
public inputs: 0
private inputs: 3 (2 belong to witness)
public outputs: 1
wires: 6
labels: 8
Written successfully: ./output\boolsatis.r1cs
Written successfully: ./output\boolsatis.sym
Written successfully: ./output\boolsatis_js\boolsatis.wasm
Everything went okay在output下会生成如下文件,在后面会讲如何使用
sh
./output
├── boolsatis_js
│ ├── boolsatis.wasm
│ ├── generate_witness.js
│ └── witness_calculator.js
├── boolsatis.r1cs
└── boolsatis.sym生成witness
- 准备输入文件
input.json
json
{
"a": "1",
"b": "0",
"c": "0"
}- 生成witness
bash
node output/boolsatis_js/generate_witness.js output/boolsatis_js/boolsatis.wasm input.json output/witness.wtns
# 或者
snarkjs wtns calculate output/boolsatis_js/boolsatis.wasm input.json output/witness.wtns最后会在 output目录下生成witness.wtns文件
SnarkJS
检查输出信息
- 查看R1CS信息
bash
➜ snarkjs r1cs info output/boolsatis.r1cs
[INFO] snarkJS: Curve: bn-128
[INFO] snarkJS: # of Wires: 6
[INFO] snarkJS: # of Constraints: 3
[INFO] snarkJS: # of Private Inputs: 3
[INFO] snarkJS: # of Public Inputs: 0
[INFO] snarkJS: # of Labels: 7
[INFO] snarkJS: # of Outputs: 0- 查看约束信息
bash
➜ snarkjs r1cs print output/boolsatis.r1cs output/boolsatis.sym
[INFO] snarkJS: [ main.a ] * [ main.b ] - [ main.a +main.b +21888242871839275222246405745257275088548364400416034343698204186575808495616main.orAB ] = 0
[INFO] snarkJS: [ 21888242871839275222246405745257275088548364400416034343698204186575808495616main.orAB ] * [ main.invC ] - [ 218882428718392752222464057452572750885483644004160343436982041865758084956161 ] = 0
[INFO] snarkJS: [ ] * [ ] - [ 1 +21888242871839275222246405745257275088548364400416034343698204186575808495616main.c +21888242871839275222246405745257275088548364400416034343698204186575808495616main.invC ] = 0- 导出r1cs到json格式
bash
snarkjs r1cs export json output/boolsatis.r1cs output/boolsatis.json生成可信设置(Trusted Setup)
- 生成zkey密钥
在这里下载生成好的随机数文件,以下使用powersOfTau28_hez_final_12.ptau
在zk-snark系统中,我们在前面提到了构建多项式承诺时需要一个可信设置的过程以生成公共参考字符串CRS,并且安全性由生成的随机数 Powers of tau仪式,tau指一个随机的秘密值(trapdoor),常表示为 ptau文件就是这个过程Phrase 1的产物,ptau文件是一个多轮的可信设置过程的结果,可以被多个电路所使用,并且在这个基础上可以生成特定电路的Phrase 2的zkey文件。
这里的12代表支持
Refer 1: Scalable Multi-party Computation for zk-SNARK Parameters in the Random Beacon Model
Refer 2: https://zkproof.org/2021/06/30/setup-ceremonies/
Refer 3: Powers of tau
Refer 4: https://github.com/ebfull/powersoftau
bash
# 验证ptau
snarkjs powersoftau verify powersOfTau28_hez_final_12.ptaubash
# groth16
➜ snarkjs groth16 setup output/boolsatis.r1cs powersOfTau28_hez_final_12.ptau output/boolsatis_0000.zkey
[INFO] snarkJS: Reading r1cs
[INFO] snarkJS: Reading tauG1
[INFO] snarkJS: Reading tauG2
[INFO] snarkJS: Reading alphatauG1
[INFO] snarkJS: Reading betatauG1
[INFO] snarkJS: Circuit hash:
9a5e0601 c3477687 e28476b5 b1edeffc
10588950 5549d196 7a67bb6c fa1d6acc
43b044af fbfe9de6 7ba63fba 35f05d4f
07b21ef3 e265b3b8 fb15afef 3582aa99
# plonk
➜ snarkjs plonk setup output/boolsatis.r1cs powersOfTau28_hez_final_12.ptau output/boolsatis_final.zkey
[INFO] snarkJS: Reading r1cs
[INFO] snarkJS: Plonk constraints: 5
[INFO] snarkJS: Setup Finished对于Groth16来说,上面的命令会生成一个初始的zkey文件boolsatis_0000.zkey,这个文件还不包含任何贡献,对于每个电路要进行单独的可信设置。而对于Plonk来说,直接生成了最终的zkey文件boolsatis_final.zkey,因为Plonk的可信设置是通用的,不需要每个电路单独贡献,可以跳过下面的步骤2~5。
原文对Goth16-zkey的描述:The zkey is a zero-knowledge key that includes both the proving and verification keys as well as phase 2 contributions.Importantly, one can verify whether a zkey belongs to a specific circuit or not.Note that circuit_0000.zkey (the output of the zkey command above) does not include any contributions yet, so it cannot be used in a final circuit.
IMPORTANT
Do not use this zkey in production, as it's not safe. It requires at least one contribution.
既我们还需再Contribute一次
- Contribute
bash
➜ snarkjs zkey contribute output/boolsatis_0000.zkey output/boolsatis_0001.zkey --name="First contribution" -v
Enter a random text. (Entropy): klizz
[DEBUG] snarkJS: Applying key: L Section: 0/5
[DEBUG] snarkJS: Applying key: H Section: 0/4
[INFO] snarkJS: Circuit Hash:
9a5e0601 c3477687 e28476b5 b1edeffc
10588950 5549d196 7a67bb6c fa1d6acc
43b044af fbfe9de6 7ba63fba 35f05d4f
07b21ef3 e265b3b8 fb15afef 3582aa99
[INFO] snarkJS: Contribution Hash:
17555388 16bff776 834a25f9 c506b937
864416db 681dc0d2 bfe65505 0db3b581
24803f7c a75522f3 2f92dd45 2dc5f1e3
e1950478 f568cb16 bfcc7275 d9abe6a5bash
➜ snarkjs zkey contribute output/boolsatis_0001.zkey output/boolsatis_0002.zkey --name="Second contribution" -v -e="klizz"
[DEBUG] snarkJS: Applying key: L Section: 0/5
[DEBUG] snarkJS: Applying key: H Section: 0/4
[INFO] snarkJS: Circuit Hash:
9a5e0601 c3477687 e28476b5 b1edeffc
10588950 5549d196 7a67bb6c fa1d6acc
43b044af fbfe9de6 7ba63fba 35f05d4f
07b21ef3 e265b3b8 fb15afef 3582aa99
[INFO] snarkJS: Contribution Hash:
74f3c314 54e4a761 eb6ce8d1 e4539b85
df38f74f 408f49ce 2d87cea2 29902b69
900a1454 f576ccf7 2a85d0e4 eb8ba825
369a8600 4bcfb2d3 1dc69fcc 33f53203- 验证latest
zkey
bash
➜ snarkjs zkey verify output/boolsatis.r1cs powersOfTau28_hez_final_12.ptau output/boolsatis_0002.zkey输出
bash
[INFO] snarkJS: Reading r1cs
[INFO] snarkJS: Reading tauG1
[INFO] snarkJS: Reading tauG2
[INFO] snarkJS: Reading alphatauG1
[INFO] snarkJS: Reading betatauG1
[INFO] snarkJS: Circuit hash:
9a5e0601 c3477687 e28476b5 b1edeffc
10588950 5549d196 7a67bb6c fa1d6acc
43b044af fbfe9de6 7ba63fba 35f05d4f
07b21ef3 e265b3b8 fb15afef 3582aa99
[INFO] snarkJS: Circuit Hash:
9a5e0601 c3477687 e28476b5 b1edeffc
10588950 5549d196 7a67bb6c fa1d6acc
43b044af fbfe9de6 7ba63fba 35f05d4f
07b21ef3 e265b3b8 fb15afef 3582aa99
[INFO] snarkJS: -------------------------
[INFO] snarkJS: contribution #2 Second contribution:
74f3c314 54e4a761 eb6ce8d1 e4539b85
df38f74f 408f49ce 2d87cea2 29902b69
900a1454 f576ccf7 2a85d0e4 eb8ba825
369a8600 4bcfb2d3 1dc69fcc 33f53203
[INFO] snarkJS: -------------------------
[INFO] snarkJS: contribution #1 First contribution:
17555388 16bff776 834a25f9 c506b937
864416db 681dc0d2 bfe65505 0db3b581
24803f7c a75522f3 2f92dd45 2dc5f1e3
e1950478 f568cb16 bfcc7275 d9abe6a5
[INFO] snarkJS: -------------------------
[INFO] snarkJS: ZKey Ok!- 应用随机信标链生成
final zkey
bash
➜ snarkjs zkey beacon output/boolsatis_0002.zkey output/boolsatis_final_groth16.zkey 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 10 -n="final Beacon"
[INFO] snarkJS: Contribution Hash:
938966da b531b627 d8ae01a4 fdcb5218
f9beae18 1c5b446c 2d259275 6965ad34
11b0f2d2 70d6e342 e3ece933 cc2bcf7d
542d4f3e 9a938f8a 6e3fba23 a9e04d11- 验证
final zkey
bash
➜ snarkjs zkey verify output/boolsatis.r1cs powersOfTau28_hez_final_12.ptau output/boolsatis_final_groth16.zkey输出
bash
[INFO] snarkJS: Reading r1cs
[INFO] snarkJS: Reading tauG1
[INFO] snarkJS: Reading tauG2
[INFO] snarkJS: Reading alphatauG1
[INFO] snarkJS: Reading betatauG1
[INFO] snarkJS: Circuit hash:
9a5e0601 c3477687 e28476b5 b1edeffc
10588950 5549d196 7a67bb6c fa1d6acc
43b044af fbfe9de6 7ba63fba 35f05d4f
07b21ef3 e265b3b8 fb15afef 3582aa99
[INFO] snarkJS: Circuit Hash:
9a5e0601 c3477687 e28476b5 b1edeffc
10588950 5549d196 7a67bb6c fa1d6acc
43b044af fbfe9de6 7ba63fba 35f05d4f
07b21ef3 e265b3b8 fb15afef 3582aa99
[INFO] snarkJS: -------------------------
[INFO] snarkJS: contribution #3 final Beacon:
938966da b531b627 d8ae01a4 fdcb5218
f9beae18 1c5b446c 2d259275 6965ad34
11b0f2d2 70d6e342 e3ece933 cc2bcf7d
542d4f3e 9a938f8a 6e3fba23 a9e04d11
[INFO] snarkJS: Beacon generator: 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
[INFO] snarkJS: Beacon iterations Exp: 10
[INFO] snarkJS: -------------------------
[INFO] snarkJS: contribution #2 Second contribution:
74f3c314 54e4a761 eb6ce8d1 e4539b85
df38f74f 408f49ce 2d87cea2 29902b69
900a1454 f576ccf7 2a85d0e4 eb8ba825
369a8600 4bcfb2d3 1dc69fcc 33f53203
[INFO] snarkJS: -------------------------
[INFO] snarkJS: contribution #1 First contribution:
17555388 16bff776 834a25f9 c506b937
864416db 681dc0d2 bfe65505 0db3b581
24803f7c a75522f3 2f92dd45 2dc5f1e3
e1950478 f568cb16 bfcc7275 d9abe6a5
[INFO] snarkJS: -------------------------
[INFO] snarkJS: ZKey Ok!- 导出为json
bash
➜ snarkjs zkey export verificationkey output/boolsatis_final_groth16.zkey output/verification_key.json
[INFO] snarkJS: EXPORT VERIFICATION KEY STARTED
[INFO] snarkJS: > Detected protocol: groth16
[INFO] snarkJS: EXPORT VERIFICATION KEY FINISHEDbash
➜ snarkjs zkey export verificationkey output/boolsatis_final.zkey output/verification_key_plonk.json
[INFO] snarkJS: EXPORT VERIFICATION KEY STARTED
[INFO] snarkJS: > Detected protocol: plonk
[INFO] snarkJS: EXPORT VERIFICATION KEY FINISHED生成证明Proof
bash
snarkjs groth16 prove output/boolsatis_final_groth16.zkey output/witness.wtns output/proof_groth16.json output/public_groth16.json
# 也可以使用如下命令 (直接使用input.json跳过circom生成witness阶段)
snarkjs groth16 fullprove input.json output/boolsatis_js/boolsatis.wasm output/boolsatis_final_groth16.zkey output/proof_groth16.json output/public_groth16.json这里会生成proof和public两个文件,分别存储证明和公开输入,proof里会包含 groth16 中的三个元素
bash
snarkjs plonk prove output/boolsatis_final.zkey output/witness.wtns output/proof_plonk.json output/public_plonk.json对于Plonk来说,生成的proof文件会稍大一些,这里为
验证证明
bash
➜ snarkjs groth16 verify output/verification_key.json output/public_groth16.json output/proof_groth16.json
[INFO] snarkJS: OK!bash
➜ snarkjs plonk verify output/verification_key_plonk.json output/public_plonk.json output/proof_plonk.json -v输出
bash
[DEBUG] snarkJS: > Reading witness file
[DEBUG] snarkJS: > Reading zkey file
[DEBUG] snarkJS: ----------------------------
[DEBUG] snarkJS: PLONK PROVE SETTINGS
[DEBUG] snarkJS: Curve: bn128
[DEBUG] snarkJS: Circuit power: 3
[DEBUG] snarkJS: Domain size: 8
[DEBUG] snarkJS: Vars: 9
[DEBUG] snarkJS: Public vars: 1
[DEBUG] snarkJS: Constraints: 7
[DEBUG] snarkJS: Additions: 2
[DEBUG] snarkJS: ----------------------------
[DEBUG] snarkJS: > Reading witness file data
[DEBUG] snarkJS: > Reading Section 3. Additions
[DEBUG] snarkJS: ··· Computing additions
[DEBUG] snarkJS: > Reading Section 12. Sigma1, Sigma2 & Sigma 3
[DEBUG] snarkJS: ··· Reading Sigma polynomials
[DEBUG] snarkJS: ··· Reading Sigma evaluations
[DEBUG] snarkJS: > Reading Section 14. Powers of Tau
[DEBUG] snarkJS:
[DEBUG] snarkJS: > ROUND 1
[DEBUG] snarkJS: > Computing A, B, C wire polynomials
[DEBUG] snarkJS: ··· Reading data from zkey file
[DEBUG] snarkJS: ··· Computing A ifft
[DEBUG] snarkJS: ··· Computing B ifft
[DEBUG] snarkJS: ··· Computing C ifft
[DEBUG] snarkJS: ··· Computing A fft
[DEBUG] snarkJS: ··· Computing B fft
[DEBUG] snarkJS: ··· Computing C fft
[DEBUG] snarkJS: > Computing A, B, C MSM
[DEBUG] snarkJS: Multiexp start: A: 0/10
[DEBUG] snarkJS: Multiexp end: A: 0/10
[DEBUG] snarkJS: Multiexp start: B: 0/10
[DEBUG] snarkJS: Multiexp end: B: 0/10
[DEBUG] snarkJS: Multiexp start: C: 0/10
[DEBUG] snarkJS: Multiexp end: C: 0/10
[DEBUG] snarkJS: > ROUND 2
[DEBUG] snarkJS: > Computing challenges beta and gamma
[DEBUG] snarkJS: ··· challenges.beta: 21dccc105f892709aa1498f0f527d56d6cec0f789821b2282370a2b5cd09a537
[DEBUG] snarkJS: ··· challenges.gamma: 1c61154c804c70dcca6961cf12b68b34849d194eb480d5e66e987e4e24fc26b2
[DEBUG] snarkJS: > Computing Z polynomial
[DEBUG] snarkJS: ··· Computing Z evaluations
[DEBUG] snarkJS: ··· Computing Z ifft
[DEBUG] snarkJS: ··· Computing Z fft
[DEBUG] snarkJS: > Computing Z MSM
[DEBUG] snarkJS: Multiexp start: Z: 0/11
[DEBUG] snarkJS: Multiexp end: Z: 0/11
[DEBUG] snarkJS: > ROUND 3
[DEBUG] snarkJS: > Computing challenge alpha
[DEBUG] snarkJS: ··· challenges.alpha: ad48a29166f8a9f02f53a5d12954253d12d9c7b8f555bd7776a6c8354a7cae0
[DEBUG] snarkJS: > Computing T polynomial
[DEBUG] snarkJS: ··· Reading sections 8, 9, 7, 10, 11. Q selectors
[DEBUG] snarkJS: ··· Computing T evaluations
[DEBUG] snarkJS: ··· Computing T ifft
[DEBUG] snarkJS: ··· Computing T / ZH
[DEBUG] snarkJS: ··· Computing Tz ifft
[DEBUG] snarkJS: ··· Computing T1, T2, T3 polynomials
[DEBUG] snarkJS: > Computing T MSM
[DEBUG] snarkJS: Multiexp start: T1: 0/9
[DEBUG] snarkJS: Multiexp end: T1: 0/9
[DEBUG] snarkJS: Multiexp start: T2: 0/9
[DEBUG] snarkJS: Multiexp end: T2: 0/9
[DEBUG] snarkJS: Multiexp start: T3: 0/14
[DEBUG] snarkJS: Multiexp end: T3: 0/14
[DEBUG] snarkJS: > ROUND 4
[DEBUG] snarkJS: > Computing challenge xi
[DEBUG] snarkJS: ··· challenges.xi: 4552349c75e650709f5ccd84198e8d640afa562491fc71eeedfb47bbb1c76aa
[DEBUG] snarkJS: > ROUND 5
[DEBUG] snarkJS: > Computing challenge v
[DEBUG] snarkJS: ··· challenges.v: 2cf9d00aca9272ce28db3f939dad109b47f5f2a54dbfe407cca7d7306297b930
[DEBUG] snarkJS: > Computing linearisation polynomial R(X)
[DEBUG] snarkJS: Lagrange Evaluations:
[DEBUG] snarkJS: L1(xi)=32b5992a742704f9221d67a86ac7e2c7c36686103d0d9748e249b8ba379edd3
[DEBUG] snarkJS: PI: 2d38f4e039ef2fda262e6f3bfad4da30abfd7fe775e8971cb5bd5a084c86122e
[DEBUG] snarkJS: r0: 1e78dcc7ee18384de2ce777db537a93c1f1ec4891810b09af14d51d180c17086
[DEBUG] snarkJS: > Computing opening proof polynomial Wxi(X) polynomial
[DEBUG] snarkJS: > Computing opening proof polynomial Wxiw(X) polynomial
[DEBUG] snarkJS: > Computing Wxi, Wxiw MSM
[DEBUG] snarkJS: Multiexp start: Wxi: 0/14
[DEBUG] snarkJS: Multiexp end: Wxi: 0/14
[DEBUG] snarkJS: Multiexp start: Wxiw: 0/11
[DEBUG] snarkJS: Multiexp end: Wxiw: 0/11
[DEBUG] snarkJS: PLONK PROVER FINISHEDOptional:导出为智能合约
bash
snarkjs zkey export solidityverifier output/boolsatis_final output/BoolSatisfyVerifier.sol后面会讲如何调用
zk-repl
简单来说就是省略了上面一些命令行的步骤,包括编译、生成witness、zkey和proof等,并且可以导出一个网页demo。
