pil2circom 实现过程

2023-09-20  本文已影响0人  雪落无留痕

本文以Fibonacci 为例,分析整个实现过程:

实现过程

/usr/local/bin/node --max-old-space-size=32000 src/main_pil2circom.js -p /Users/tron/test/polygon_zkevm/pil-stark/test/sm_fibonacci/fibonacci_main.pil -s /Users/tron/test/polygon_zkevm/pil-stark/test/sm_fibonacci/fibonacci.starkstruct.json -v /Users/tron/test/polygon_zkevm/pil-stark/tmp/fibonacci.verkey.json -o /Users/tron/test/polygon_zkevm/pil-stark/tmp/fibonacci.verifier.circom

输入为:

namespace Fibonacci(%N);


    pol constant L1, LLAST;
    pol commit l1,l2;

    pol l2c = l2;

    public in1 = l2c(0);
    public in2 = l1(0);
    public out = l1(%N-1);

    (l2' - l1)*(1-LLAST) = 0;

    pol next = l1*l1 + l2*l2;

    (l1' - next)*(1-LLAST) = 0;

    L1 * (l2 - :in1) = 0;
    L1 * (l1 - :in2) = 0;
    LLAST * (l1 - :out) = 0;

{
            "nBits": 10,
            "nBitsExt": 11,
            "nQueries": 8,
            "verificationHashType": "GL",
            "steps": [
                {"nBits": 11},
                {"nBits": 7},
                {"nBits": 3}
            ]
}
{
 "constRoot": [
  8072859658275330050,
  6129740704102247485,
  16008196867495226449,
  2863018592730207411
 ]
}

输出为生成的circom 电路:

Fibonacci.verifier.circom

主要采用 ejs ,将Fibonacci 的信息注入stark 验证电路模板中,生成最后的Fibonacci stark 证明的验证电路。

    const obj = {
        F: F,
        starkInfo: starkInfo,
        starkStruct: starkStruct,
        constRoot: constRoot,
        pil: pil,
        options: options
    };

    return ejs.render(template ,  obj);

verifier.circom

下面以fibonacci.verrifer.circom 过程为例,分析生成的用于验证STARK 证明的circom 电路。

maincircom 程序的入口,其中publics 声明为公开输入。

component main {public [publics]}= StarkVerifier();

Merkle 树

下面的代码声明验证需要用的Merkle 根:

    signal input publics[3];  // Fibonacci中的三个公开输入
    signal input root1[4];  // commit多项式对应的Merkle 根  
    signal input root2[4];  // plookup 多项式对应的Merkle 根
    signal input root3[4];  // plookup/permutation/connection Z 多项式对应的根
    signal input root4[4];  // q多项式 约束对应的Merkle 根

    signal rootC[4];  // 常量多项式对应的Merkle 根
    rootC[0] <== 8072859658275330050;   //从fibonacci.verkey.json 导入的常量根
    rootC[1] <== 6129740704102247485;
    rootC[2] <== 16008196867495226449;
    rootC[3] <== 2863018592730207411;

以下涉及FRI 过程对应的叶子节点和Merkle 路径:

    signal input evals[8][3];  // 对应starkinfo 中 evMap中各个承诺多项式的值。

    signal input s0_vals1[8][2];  // 8 表示查询点的个数,2表示commit多项式的个数(cm1_2ns)
    signal input s0_vals4[8][4];  // 8 表示查询点的个数,4表示q多项式的个数(q_2ns)
    //注:Fibonacci s0_vals2, so_vals3对应的约束不存在,所有没有生成
    signal input s0_valsC[8][2];   //  8 表示查询点的个数,2表示 常量多项式 的个数(q_2ns)
    signal input s0_siblings1[8][11][4]; //s0_vals1对应的Merkle 路径,有11层,每个节点由4个Goldilocks 元素组成
    signal input s0_siblings4[8][11][4]; 
    signal input s0_siblingsC[8][11][4];

    signal input s1_root[4];  // fri step 1 root
    signal input s2_root[4];  // fri step 2 root

    signal input s1_vals[8][48];         // fri 1 tree对应查询点的叶子节点,48为对应叶子width, 即: (1 <<   
                                        // (starkStruct.steps[s-1].nBits -   starkStruct.steps[s].nBits))*3
   
    signal input s1_siblings[8][7][4]; // fri 1 tree 对应的Merkle路径
    signal input s2_vals[8][48];     //与以上类似
    signal input s2_siblings[8][3][4];

    signal input finalPol[8][3];  // 最后一轮,每个都为宽度为3的值

FRI 参数

FRI 的相关参数值定义:

    signal enable;  // enable input 
    enable <== 1;


    signal challenges[8][3];  // 固定的8个chanllenge 值
    signal s0_specialX[3];   // fri计算过程中涉及到的special_x, 和fri的 steps 个数相等
    signal s1_specialX[3];
    signal s2_specialX[3];

    signal ys[8][11];     // 查询点索引值

FRI 相关参数值的计算:

    component tcHahs_0 = Poseidon(12);
    tcHahs_0.in[0] <== root1[0];
    tcHahs_0.in[1] <== root1[1];
    tcHahs_0.in[2] <== root1[2];
    tcHahs_0.in[3] <== root1[3];
    tcHahs_0.in[4] <== 0;
    tcHahs_0.in[5] <== 0;
    tcHahs_0.in[6] <== 0;
    tcHahs_0.in[7] <== 0;
    tcHahs_0.capacity[0] <== 0;
    tcHahs_0.capacity[1] <== 0;
    tcHahs_0.capacity[2] <== 0;
    tcHahs_0.capacity[3] <== 0;
    challenges[0][0] <== tcHahs_0.out[0];
    challenges[0][1] <== tcHahs_0.out[1];
    challenges[0][2] <== tcHahs_0.out[2];
    challenges[1][0] <== tcHahs_0.out[3];
    challenges[1][1] <== tcHahs_0.out[4];
    challenges[1][2] <== tcHahs_0.out[5];
    ......

后续代码类似,依次完成challenge, special_x, ys 计算过程。

约束多项式检查

///////////
// Constrain polynomial check in vauations
///////////
    component verifyEvaluations = VerifyEvaluations();
    verifyEvaluations.enable <== enable;
    for (var i=0; i<8; i++) {
        for (var k=0; k<3; k++) {
            verifyEvaluations.challenges[i][k] <== challenges[i][k];
        }
    }
    for (var i=0; i<3; i++) {
        verifyEvaluations.publics[i] <== publics[i];
    }
    for (var i=0; i<8; i++) {
        for (var k=0; k<3; k++) {
            verifyEvaluations.evals[i][k] <== evals[i][k];
        }
    }

FRI 表达式验证

///////////
// Step0 Check and evaluate queries
///////////

    component verifyQueries[8];
    component s0_merkle1[8];


    component s0_merkle4[8];
    component s0_merkleC[8];
    component s0_lowValues[8];
    
    ...

FRI tree 1 验证

    component s1_merkle[8];
    component s1_fft[8];
    component s1_evalPol[8];
    component s1_lowValues[8];
    signal s1_sx[8][7];
    
    ......

FRI tree 2 验证

    component s2_merkle[8];
    component s2_fft[8];
    component s2_evalPol[8];
    component s2_lowValues[8];
    signal s2_sx[8][3];
    ...

低度测试

最后一轮的低度,判定最后的多项式次数小于4。

///////
// Check Degree last pol
///////
// Last FFT
    component lastIFFT = FFT(3, 3, 1, 1 );

    for (var k=0; k< 8; k++ ){
        for (var e=0; e<3; e++) {
            lastIFFT.in[k][e] <== finalPol[k][e];
        }
    }

    for (var k= 4; k< 8; k++ ) {  
        for (var e=0; e<3; e++) {
            enable * lastIFFT.out[k][e] === 0;
        }
    }

参考

https://github.com/0xPolygonHermez/pil-stark/blob/main/src/main_pil2circom.js

https://docs.circom.io/

上一篇 下一篇

猜你喜欢

热点阅读