Polygon zkEVM递归证明技术文档(5)——附录:借助SNARKjs和PIL-STARK实现proof composition

前序博客有:

本文重点关注:

  • 附录:借助SNARKjs和PIL-STARK实现proof composition。

7. 附录:借助SNARKjs和PIL-STARK实现proof composition

本节将展示当前SNARKjs和PIL-STARK工具栈的证明能力。尤其是演示如何实现某些类型的证明组合,从而超过SNARKjs和PIL-STARK原本的能力。

接下来,均以证明如下statement为例:

“I known a (secret) value a 1 = 1 a_1 = 1 a1=1 such that the ( 2 5 + 1 = ) (2^5 + 1 =) (25+1=) 33 33 33-th element of the Fibonacci sequence on (public) input a 0 = 1 a_0 = 1 a0=1 and a 1 a_1 a1 is equal to 3524578 3524578 3524578.”

本文前2小节,将展示如何生成(depth 0)proof。

7.1 Depth 0:Circom + SNARKjs

以Circom来表示上述statement,即意味着将Fibonacci序列计算以R1CS格式表示:
在这里插入图片描述
该电路特定实例(即 a 0 = 1 , a 1 = 1 a_0=1,a_1=1 a0=1,a1=1)的execution trace为:
在这里插入图片描述
其中红色字体数字为仅对Prover已知的信息,而绿色字体数字为对Prover和Verifier都已知的信息。
在以Circom对该电路描述之后,可使用SNARKjs来为其生成有效的zk-SNARK证明:【当前SNARKjs支持Groth16、Fflonk和Plonk。为简化接下来都称为Plonk。】

  • 1)编译电路:
$ mkdir -p build && circom src/fibonacci.circom --r1cs --wasm -o build
template instances: 1
non-linear constraints: 0
linear constraints: 0
public inputs: 1
public outputs: 1
private inputs: 1
private outputs: 0
wires: 3
labels: 35
  • 2)在同一路径下,为该电路创建input.json输入文件:
$ cat <<EOT > input.json
{ "a0": 1, "a1": 1}
EOT
  • 3)为该输入计算witness:
$ snarkjs wc build/fibonacci_js/fibonacci.wasm src/input.json build/fibonacci.wtns
out = 3524578
  • 4)下载足够大的“powers of tau”文件:
$ wget https://hermez.s3-eu-west-1.amazonaws.com/powersOfTau28_hez_final_10.ptau -O build/powersOfTau.ptau
  • 5)对该电路进行预处理:
$ snarkjs pks build/fibonacci.r1cs build/powersOfTau.ptau build/fibonacci.zkey
[INFO] snarkJS: Reading r1cs
[INFO] snarkJS: Plonk constraints: 2
[INFO] snarkJS: Setup Finished
  • 6)导出proof verification的验证秘钥:
$ snarkjs zkev build/fibonacci.zkey build/fibonacci-vk.json
[INFO] snarkJS: EXPORT VERIFICATION KEY STARTED
[INFO] snarkJS: > Detected protocol: plonk
[INFO] snarkJS: EXPORT VERIFICATION KEY FINISHED
  • 7)生成Plonk proof:
$ snarkjs pkp build/fibonacci.zkey build/fibonacci.wtns build/fibonacci.proof.json build/fibonacci.public.json
  • 8)最终,验证该proof:
$ snarkjs pkv build/fibonacci-vk.json build/fibonacci.public.json build/fibonacci.proof.json
[ INFO ] snarkJS : OK!

7.2 Depth 0:PIL + PIL-STARK

以PIL来表示以上statement,即意味着需将Fibonacci序列的计算以AIR格式表示,即基于domain G = < g > G=<g> G=<g>的一组多项式约束。此时,若对所有 x ∈ G x\in G xG,如下约束:
在这里插入图片描述
均满足,则原始statement为true。
此处:

  • L 1 , L 32 L_1,L_{32} L1,L32为第一个和最后一个基于 G G G的Lagrange多项式
  • a 0 , a 1 a_0,a_1 a0,a1定义为维护Finbonacci序列每个state转变值。

在这里插入图片描述
该状态机特定实例(即 a 0 ( g ) = 1 , a 1 ( g ) = 1 a_0(g)=1,a_1(g)=1 a0(g)=1,a1(g)=1)的execution trace为:
在这里插入图片描述
在以PIL描述完电路之后,可使用pil-stark来为以上实例生成有效的eSTARK proof:

  • 1)向execution trace中填充常量多项式:
$ mkdir -p build && node src/main_buildconst.js -o build/fibonacci.const
file Generated Correctly
  • 2)向execution trace中填充committed多项式:
$ node src/main_buildcommit.js -i src/input.json -o build/fibonacci.commit
Result: 3524578
file Generated Correctly
  • 3)验证前2步生成的execution trace是否有效:
$ node node_modules/pilcom/src/main_pilverifier.js build/fibonacci.commit -p src / fibonacci.pil -c build/fibonacci.const
PIL OK !!
  • 4)在同一路径下,创建具有eSTARK参数的starkstruct.json文件:
$ cat << EOT > starkstruct.json
{
"nBits": 5,
"nBitsExt": 6,
"nQueries": 64,
"verificationHashType": "GL",
"steps": [
{ "nBits": 6},
{ "nBits": 4},
{ "nBits": 2}
]
}
EOT
  • 5)根据starkstruct.json文件,生成,生成eSTARK所需的starkinfo.json文件:
$ node node_modules/pil-stark/src/main_genstarkinfo.js -p src/fibonacci.pil -s src/starkstruct.json -i build/starkinfo.json
files Generated Correctly
  • 6)预处理状态机:
$ node node_modules/pil-stark/src/main_buildconsttree.js -c build/fibonacci.const -p src/fibonacci.pil -s src/starkstruct.json -t build/fibonacci.consttree -v build/fibonacci.verkey.json
files Generated Correctly
  • 7)生成eSTARK proof:
$ node node_modules/pil-stark/src/main_prover.js -m build/fibonacci.commit -c build/fibonacci.const -t build/fibonacci.consttree -p src/fibonacci.pil -s build/starkinfo.json -o build/fibonacci.proof.json -z build/fibonacci.zkin.json -b build/fibonacci.public.json
files Generated Correctly
  • 8)最后验证该eSTARK proof:
$ node node_modules/pil-stark/src/main_verifier.js -p src/fibonacci.pil -s build/starkinfo.json -v build/fibonacci.verkey.json -o build/fibonacci.proof.json -b build/fibonacci.public.json
Verification Ok!!

7.3 Depth 0:Circom + PIL-STARK

本节将展示如何为以Circom直接编写的Fibonacci电路生成eSTARK proof:

  • 1)编译电路:【指定采用Goldilocks域】
    $ mkdir -p build && circom src/fibonacci.circom --O1 --prime goldilocks --r1cs --wasm -o build
    template instances: 1
    non-linear constraints: 0
    linear constraints: 31
    public inputs: 1
    public outputs: 1
    private inputs: 1
    private outputs: 0
    wires: 34
    labels: 35
    
    注意此处采用Goldilocks素数域,而不是(Circom中默认的)定义BN128椭圆曲线的素数域。原因在于,当前以PIL编写的状态机仅支持Goldilocks域。
  • 2)在同一路径下,为该电路创建输入文件input.json
$ cat << EOT > input.json
{ "a0": 1 , "a1": 1}
EOT
  • 3)基于输入,计算witness:
$ snarkjs wc build/fibonacci_js/fibonacci.wasm src/input.json build/fibonacci.wtns
out = 3524578
  • 4)目前已计算出witness(准确来说是R1CS witness),接下来需将电路的R1CS表示,转换为等价的同一电路的Plonk表示:
$ node node_modules/pil-stark/src/main_plonksetup.js -r build/fibonacci.r1cs -p build/fibonacci.pil -e build/fibonacci.exec -c build/fibonacci.const
files Generated Correctly

输出的fibonacci.pil中,以PIL编写的状态机为:【该转换过程中还会生成一个包含constant多项式的文件fibonacci.const。】

constant % N = 2**6;
namespace Global(%N);
pol constant L1 ;
pol constant L2 ;
namespace PlonkCircuit(%N) ;
pol constant S[3];
pol constant Qm, Ql, Qr, Qo, Qk;
pol commit a[3];
public pub0 = a[0](0) ;
public pub1 = a[0](1) ;
Global.L1 * (a[0] - :pub0) = 0;
Global.L2 * (a[0] - :pub1) = 0;
// Normal plonk ecuations
pol a01 = a[0]*a[1];
Qm*a01 + Ql*a[0] + Qr*a[1] + Qo*a[2] + Qk = 0;
// Connection equations
{a[0] , a[1] , a[2]} connect {S[0], S[1], S[2]};
  • 5)将committed多项式填充到execution trace中:
$ node node_modules/pil-stark/src/main_plonkexec.js -w build/fibonacci.wtns -p build/fibonacci.pil -e build/fibonacci.exec -m build/fibonacci.commit
file Generated Correctly
  • 6)验证之前2步所生成的execution trace是否有效:
$ node node_modules/pilcom/src/main_pilverifier.js build/fibonacci.commit -p build/fibonacci.pil -c build/fibonacci.const
PIL OK!!
  • 7)在同一路径下创建具有eSTARK参数的strakstruct.json文件:
    $ cat << EOT > starkstruct.json
    {
    "nBits": 6,
    "nBitsExt": 7,
    "nQueries": 64,
    "verificationHashType": "BN128",
    "steps": [
    { "nBits": 7},
    { "nBits": 5},
    { "nBits": 3}
    ]
    }
    EOT
    
    需注意,此处所需的nBits值需由5增加到6,因为将R1CS转换为Plonk的开销(具体可见上面的fibonacci.pil状态机)。
    接下来就是重复之前7.2节类似的流程来生成eSTARK proof了。
  • 8)根据starkstruct.json文件,生成,生成eSTARK所需的starkinfo.json文件:
$ node node_modules/pil-stark/src/main_genstarkinfo.js -p src/fibonacci.pil -s src/starkstruct.json -i build/starkinfo.json
files Generated Correctly
  • 9)预处理状态机:
$ node node_modules/pil-stark/src/main_buildconsttree.js -c build/fibonacci.const -p src/fibonacci.pil -s src/starkstruct.json -t build/fibonacci.consttree -v build/fibonacci.verkey.json
files Generated Correctly
  • 10)生成eSTARK proof:
$ node node_modules/pil-stark/src/main_prover.js -m build/fibonacci.commit -c build/fibonacci.const -t build/fibonacci.consttree -p src/fibonacci.pil -s build/starkinfo.json -o build/fibonacci.proof.json -z build/fibonacci.zkin.json -b build/fibonacci.public.json
files Generated Correctly
  • 11)最后验证该eSTARK proof:
$ node node_modules/pil-stark/src/main_verifier.js -p src/fibonacci.pil -s build/starkinfo.json -v build/fibonacci.verkey.json -o build/fibonacci.proof.json -b build/fibonacci.public.json
Verification Ok!!

接下来的小节中,将使用"PIL-STARK + PIL-STARK" 或 “PIL-STARK + SNARKjs” 组合来展开之前的2个流程。

7.4 Depth 1:Circom + PIL-STARK + SNARKjs

接下来将展示,如何为,以Circom表示的statement的eSTARK proof有效,而生成的SNARK proof:

  • 1)编译电路:
$ mkdir -p build && circom src/fibonacci.circom --O1 --prime goldilocks --r1cs --wasm -o build
Everything went okay, circom safe
  • 2)在同一路径下,创建该电路的输入文件input.json
$ cat << EOT > input.json
{ "a0": 1, "a1": 1}
EOT
  • 3)基于该输入计算witness:
$ snarkjs wc build/fibonacci_js/fibonacci.wasm src/input.json build/fibonacci.wtns
out = 3524578
  • 4)根据所计算的witness(准确来说是R1CS),将电路的R1CS表示,转换为同一电路等价的Plonk表示:
$ node node_modules/pil-stark/src/main_plonksetup.js -r build/fibonacci.r1cs -p build/fibonacci.pil -e build/fibonacci.exec -c build/fibonacci.const
files Generated Correctly
  • 5)向execution trace填充committed多项式:
$ node node_modules/pil-stark/src/main_plonkexec.js -w build/fibonacci.wtns -p build/fibonacci.pil -e build/fibonacci.exec -m build/fibonacci.commit
file Generated Correctly
  • 6)验证前2步所生成的execution trace是否有效:
$ node node_modules/pilcom/src/main_pilverifier.js build/fibonacci.commit -p build/fibonacci.pil -c build/fibonacci.const
PIL OK!!
  • 7)在同一路径下创建具有eSTARK参数的strakstruct.json文件:
$ cat << EOT > starkstruct.json
{
"nBits": 6,
"nBitsExt": 7,
"nQueries": 64,
"verificationHashType": "BN128",
"steps": [
{ "nBits": 7},
{ "nBits": 5},
{ "nBits": 3}
]
}
EOT
  • 8)根据starkstruct.json文件,生成,生成eSTARK proof所需的strakinfo.json文件:
$ node node_modules/pil-stark/src/main_genstarkinfo.js -p build/fibonacci.pil -s src/starkstruct.json -i build/starkinfo.json
files Generated Correctly
  • 9)预处理状态机:
$ node node_modules/pil-stark/src/main_buildconsttree.js -c build/fibonacci.const -p build/fibonacci.pil -s src/starkstruct.json -t build/fibonacci.consttree -v build/fibonacci.verkey.json
files Generated Correctly
  • 10)生成eSTARK proof:
$ node node_modules/pil-stark/src/main_prover.js -m build/fibonacci.commit -c build/fibonacci.const -t build/fibonacci.consttree -p build/fibonacci.pil -s build/starkinfo.json -o build/fibonacci.proof.json -z build/fibonacci.zkin.json -b build/fibonacci.public.json --proverAddr 0x7BAbF98C66454aF8a3C366F893f99EBa26a15c66
files Generated Correctly
  • 11)验证该eSTARK proof是否正确:
$ node node_modules/pil-stark/src/main_verifier.js -p build/fibonacci.pil -s build/starkinfo.json -v build/fibonacci.verkey.json -o build/fibonacci.proof.json -b build/fibonacci.public.json
Verification Ok!!
  • 12)接下来,将eSTARK verifier生成为Circom电路:
    $ node node_modules/pil-stark/src/main_pil2circom.js -p build/fibonacci.pil -s build/starkinfo.json -v build/fibonacci.verkey.json -o build/verifier.circom
    file Generated Correctly
    
    此处支持递归性:若以之前生成的eSTARK proof为输入,生成了一个有效的SNARK,则可证明该eSTARK proof是有效的。
  • 13)需使用circuits.gl中的电路来编译该eSTARK verifier电路:
$ circom build/verifier circom --r1cs --wasm -l node_modules/pil-stark/circuits.bn128 -l node_modules/circomlib/circuits -o build
template instances: 465
non-linear constraints: 2123834
linear constraints: 0
public inputs: 0
public outputs: 1
private inputs: 14682
private outputs: 0
wires: 2125925
labels: 5010997
  • 14)在同一路径下为该电路创建输入文件input.json
$ cat << EOT > input.json
{ "a0": 1, "a1": 1}
EOT
  • 15)基于输入计算witness:
$ snarkjs wc build/verifier_js/verifier.wasm build/fibonacci.zkin.json build/verifier.wtns
out = 3524578
  • 16)下载足够大的“powers of tau”文件:
$ wget https://hermez.s3-eu-west-1.amazonaws.com/powersOfTau28_hez_final_16.ptau -O build/powersOfTau.ptau
  • 17)预处理电路:
$ snarkjs pks build/verifier.r1cs build/powersOfTau.ptau build/fibonacci.zkey
[INFO] snarkJS: Reading r1cs
[INFO] snarkJS: Plonk constraints: 2
[INFO] snarkJS: Setup Finished
  • 18)导出验证proof所需的验证密钥:
$ snarkjs zkev build/veirifer.zkey build/veirifer-vk.json
[INFO] snarkJS: EXPORT VERIFICATION KEY STARTED
[INFO] snarkJS: > Detected protocol: plonk
[INFO] snarkJS: EXPORT VERIFICATION KEY FINISHED
  • 19)生成Plonk proof:
$ snarkjs pkp build/veirifer.zkey build/veirifer.wtns build/veirifer.proof.json build/veirifer.public.json
  • 20)验证该Plonk proof:
$ snarkjs pkv build/veirifer-vk.json build/veirifer.public.json build/veirifer.proof.json
[INFO] snarkJS: OK!

7.5 unlimited depth with PIL-STARK

本节,将针对:

  • 以PIL编写的Fibonacci序列
  • 为其生成eSTARK proof
  • 并为该eSTARK proof的有效性,生成eSTARK proof

以上相同的流程可不停重复,从而实现无限深度的proof composition。如之前各小节所示,无限的eSTARK composition最终以final SNARK结尾。

以下流程展示了PIL-STARK和SNARKjs工具栈的强大之处:

  • 1)向execution trace中填充constant多项式:
$ mkdir -p build && node src/main_buildconst.js -o build/fibonacci.const
file Generated Correctly
  • 2)向execution trace中填充committed多项式:
$ node src/main_buildcommit.js -i src/input.json -o build/fibonacci.commit
Result: 3524578
file Generated Correctly
  • 3)验证前2步所生成的execution trace是否有效:
$ node node_modules/pilcom/src/main_pilverifier.js build/fibonacci.commit -p src/fibonacci.pil -c build/fibonacci.const
PIL OK!!
  • 4)在同一路径下创建具有eSTARK参数的strakstruct.json文件:
$ cat << EOT > fibonacci.starkstruct.json
{
"nBits": 5,
"nBitsExt": 6,
"nQueries": 64,
"verificationHashType": "GL",
"steps": [
{ "nBits": 6},
{ "nBits": 4},
{ "nBits": 2}
]
}
EOT
  • 5)基于strakstruct.json文件,生成,生成eSTARK proof所需的starkinfo.json文件:
$ node node_modules/pil-stark/src/main_genstarkinfo.js -p src/fibonacci.pil -s src/fibonacci.starkstruct.json -i build/starkinfo.json
files Generated Correctly
  • 6)预处理状态机:
$ node node_modules/pil-stark/src/main_buildconsttree.js -c build/fibonacci.const -p src/fibonacci.pil -s src/fibonacci.starkstruct.json -t build/fibonacci.consttree -v build/fibonacci.verkey.json
files Generated Correctly
  • 7)生成eSTARK proof:
$ node node_modules/pil-stark/src/main_prover.js -m build/fibonacci.commit -c build/fibonacci.const -t build/fibonacci.consttree -p src/fibonacci.pil -s build/starkinfo.json -o build/fibonacci.proof.json -z build/fibonacci.zkin.json -b build/fibonacci.public.json
files Generated Correctly
  • 8)验证该eSTARK proof是否正确:
$ node node_modules/pil-stark/src/main_verifier.js -p src/fibonacci.pil -s build/starkinfo.json -v build/fibonacci.verkey.json -o build/fibonacci.proof.json -b build/fibonacci.public.json
Verification Ok!!
  • 9)为eSTARK verifier生成Circom电路:
$ node node_modules/pil-stark/src/main_pil2circom.js -p src/fibonacci.pil -s build/starkinfo.json -v build/fibonacci.verkey.json -o build/verifier.circom
Verification Ok!!
  • 10)编译该verifier circom电路:
$ circom --O1 --prime goldilocks --r1cs --wasm build/verifier.circom -l node_modules/pil-stark/circuits.gl -o build
Verification Ok!!
  • 11)基于输入计算witness
$ snarkjs wc build/verifier_js/verifier.wasm build/fibonacci.zkin.json build/verifier.wtns
out = 3524578
  • 12)将所生成的verifier circom(r1cs)电路转换为状态机:
$ node node_modules/pil-stark/src/main_plonksetup.js -r build/verifier.r1cs -p build/verifier.pil -c build/verifier.const -e build/verifier.exec
files Generated Correctly
  • 13)向execution trace中填充committed多项式:
$ node node_modules/pil-stark/src/main_plonkexec.js -w build/verifier.wtns -p build/verifier.pil -e build/verifier.exec -m build/verifier.commit
files Generated Correctly
  • 14)验证前2步所生成的execution trace是否有效:
$ node node_modules/pilcom/src/main_pilverifier.js build/verifier.commit -p build/verifier.pil -c build/verifier.const
PIL OK!!
  • 15)在同一路径下创建具有eSTARK参数的verifier.starkstruct.json文件:
    $ cat << EOT > verifier.starkstruct.json
    {
    "nBits": 16,
    "nBitsExt": 17,
    "nQueries": 64,
    "verificationHashType": "GL",
    "steps": [
    { "nBits": 17},
    { "nBits": 14},
    { "nBits": 10},
    { "nBits": 6}
    ]
    }
    EOT
    
    至此,就可采用之前的流程来生成eSTARK proof。
  • 16)根据verifier.starkstruct.json文件,生成,生成eSTARK proof所需的verifier.starkinfo.json文件:
$ node node_modules/pil-stark/src/main_genstarkinfo.js -p build/verifier.pil -s src/verifier.starkstruct.json -i build/verifier.starkinfo.json
files Generated Correctly
  • 17)预处理状态机verifier.pil
$ node node_modules/pil-stark/src/main_buildconsttree.js -c build/verifier.const -p build/verifier.pil -s src/verifier.starkstruct.json -t build/verifier.consttree -v build/verifier.verkey.json
files Generated Correctly
  • 18)生成eSTARK proof:
$ node node_modules/pil-stark/src/main_prover.js -m build/verifier.commit -c build/verifier.const -t build/verifier.consttree -p build/verifier.pil -s build/verifier.starkinfo.json -o build/verifier.proof.json -z build/verifier.zkin.json -b build/verifier.public.json
files Generated Correctly
  • 19)验证该eSTARK proof:
$ node node_modules/pil-stark/src/main_verifier.js -p build/verifier.pil -s build/verifier.starkinfo.json -v build/verifier.verkey.json -o build/verifier.proof.json -b build/verifier.public.json
Verification Ok !!

正如之前所提及的,可为eSTARK verifier生成Circom电路,并遵循10-18步骤来重复以上流程,其中每次重复会创建一个starkstruct.json文件。

参考资料

[1] Polygon zkEVM技术文档 Recursion, aggregation and composition of proofs v.1.1

附录:Polygon Hermez 2.0 zkEVM系列博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值