Polygon zkEVM PIL编译器——pilcom 代码解析

1. 引言

开源代码见:

  • https://github.com/0xPolygonHermez/pilcom(JavaScript)

pilcom为Polygon zkEVM的PIL(Polynomial Identity Language)编译器。

test/examples下的arrays.pil代码为例:


namespace Arrays2(2**16);
    pol constant d[2];
    pol commit c;

    d[0]+d[1] = c*d[0]; //第6行

namespace Arrays1(2**16);
    pol commit a, b[3], c;

    a*b[0] = 1; //第11行
    b[1]*b[1] = b[2]*Arrays2.d[1]; //第12行

    b[1] {b[0], a} in Arrays2.d[0] { Arrays2.c, Arrays2.d[1]}; //第14行
$ node src/pil.js test/examples/arrays.pil -o zyd.json
Debugger attached.
Input Pol Commitmets: 6
Q Pol Commitmets: 0
Constant Pols: 2
Im Pols: 0
plookupIdentities: 1
permutationIdentities: 0
connectionIdentities: 0
polIdentities: 3
Waiting for the debugger to disconnect...

pil.js代码本质为调用compile将pil代码编译为JSON格式。

	const out = await compile(F, fullFileName, null, config);
	
	console.log("Input Pol Commitmets: " + out.nCommitments); // 以`pol commit`表示的多项式总数
    console.log("Q Pol Commitmets: " + out.nQ); // 以多项式本身为粒度,若degree为2,则nQ++,如`pol next = l1*l1 + l2*l2;`,需nQ++。
    console.log("Constant Pols: " + out.nConstants); // 以`pol constant`表示的多项式总数
    console.log("Im Pols: " + out.nIm); // 仅以`pol`,而非`pol constant`或`pol commit`表示的多项式总数
    console.log("plookupIdentities: " + out.plookupIdentities.length); // 即pil中的`in`表示的约束总数
    console.log("permutationIdentities: " + out.permutationIdentities.length); // 即pil中的`is`表示的约束总数
    console.log("connectionIdentities: " + out.connectionIdentities.length); // 即pil中的`connect`表示的约束总数
    console.log("polIdentities: " + out.polIdentities.length); // 即pil中的`=`表示的约束总数

    await fs.promises.writeFile(outputFile.trim(), JSON.stringify(out, null, 1) + "\n", "utf8");

相应的json文件输出为:

  • 1)常量多项式类型为“constP”,对应的values op为“const”,PIL代码内标记为pol constant
  • 2)隐私多项式commitment类型为“cmP”,对应的values op为“cm”,PIL代码内标记为pol commit
  • 3)中间(intermediate)多项式类型“imP”,不允许有offset,对应的values op为“exp”;
  • 4)多项式identities对应的pil代码中的位置,在“polIdentities”中表示:【如本例,分别在第6、11、12行。】
    "polIdentities": [
      {
       "e": 0,
       "fileName": "arrays.pil",
       "line": 6
      },
      {
       "e": 1,
       "fileName": "arrays.pil",
       "line": 11
      },
      {
       "e": 2,
       "fileName": "arrays.pil",
       "line": 12
      }
     ]
    
  • 5)约束中的常量值,如 1 1 1等,其op为“number”,json表示为:
    {
     "op": "number",
     "deg": 0,
     "value": "1"
    }
    
  • 6)运算见“expressions”中的“op”字段,支持的运算有:“neg”、“add”、“sub”、“mul”、“pow”。
  • 7)plookup约束b[1] {b[0], a} in Arrays2.d[0] { Arrays2.c, Arrays2.d[1]};,对应在“expressions”中的JSON表示为:【规则为先in的左侧,再右侧。】
    { # b[0]。在expressions数组的index为3"op": "cm",
    "deg": 1,
    "id": 2,
    "next": false
    },
    { # a。在expressions数组的index为4"op": "cm",
    "deg": 1,
    "id": 1,
    "next": false
    },
    { # b[1]。在expressions数组的index为5"op": "cm",
    "deg": 1,
    "id": 3,
    "next": false
    },
    { # c。在expressions数组的index为6"op": "cm",
    "deg": 1,
    "id": 0,
    "next": false
    },
    { # d[1]。在expressions数组的index为7"op": "const",
    "deg": 1,
    "id": 1,
    "next": false
    },
    { # d[0]。在expressions数组的index为8"op": "const",
    "deg": 1,
    "id": 0,
    "next": false
    }
    
  • 8)plookup约束对应的pil代码中的位置,在“plookupIdentities”中表示:【如本例,在第14行。“f”/“t”,以及"selF"和“selT”的值均为相应项在expression数组内的index值。】
    "plookupIdentities": [
      {
       "f": [
        3,
        4
       ],
       "t": [
        6,
        7
       ],
       "selF": 5,
       "selT": 8,
       "fileName": "arrays.pil",
       "line": 14
      }
     ]
    
  • 9)permutation约束对应在pil代码中的位置,在“permutationIdentities”中表示。
  • 10)connection约束对应在pil代码中的位置,在“connectionIdentities”中表示。
{
 "nCommitments": 6,
 "nQ": 0,
 "nIm": 0,
 "nConstants": 2,
 "publics": [],
 "references": {
  "Arrays2.d": { # namespace.polyName
   "type": "constP",
   "id": 0,
   "polDeg": 65536,
   "isArray": true,
   "len": 2
  },
  "Arrays2.c": {
   "type": "cmP",
   "id": 0,
   "polDeg": 65536,
   "isArray": false
  },
  "Arrays1.a": {
   "type": "cmP",
   "id": 1,
   "polDeg": 65536,
   "isArray": false
  },
  "Arrays1.b": {
   "type": "cmP",
   "id": 2,
   "polDeg": 65536,
   "isArray": true,
   "len": 3
  },
  "Arrays1.c": {
   "type": "cmP",
   "id": 5,
   "polDeg": 65536,
   "isArray": false
  }
 },
 "expressions": [
  { # 对应约束为:d[0]+d[1]-d[0]*c=0
   "op": "sub",
   "deg": 2,
   "values": [
    {
     "op": "add",
     "deg": 1,
     "values": [
      {
       "op": "const",
       "deg": 1,
       "id": 0,
       "next": false
      },
      {
       "op": "const",
       "deg": 1,
       "id": 1,
       "next": false
      }
     ]
    },
    {
     "op": "mul",
     "deg": 2,
     "values": [
      {
       "op": "cm",
       "deg": 1,
       "id": 0,
       "next": false
      },
      {
       "op": "const",
       "deg": 1,
       "id": 0,
       "next": false
      }
     ]
    }
   ]
  },
  { # 对应约束为: a*b[0]-1=0
   "op": "sub",
   "deg": 2,
   "values": [
    {
     "op": "mul",
     "deg": 2,
     "values": [
      {
       "op": "cm",
       "deg": 1,
       "id": 1,
       "next": false
      },
      {
       "op": "cm",
       "deg": 1,
       "id": 2,
       "next": false
      }
     ]
    },
    {
     "op": "number",
     "deg": 0,
     "value": "1"
    }
   ]
  },
  { # 对应约束为:b[1]*b[1]-b[2]*d[1]=0
   "op": "sub",
   "deg": 2,
   "values": [
    {
     "op": "mul",
     "deg": 2,
     "values": [
      {
       "op": "cm",
       "deg": 1,
       "id": 3,
       "next": false
      },
      {
       "op": "cm",
       "deg": 1,
       "id": 3,
       "next": false
      }
     ]
    },
    {
     "op": "mul",
     "deg": 2,
     "values": [
      {
       "op": "cm",
       "deg": 1,
       "id": 4,
       "next": false
      },
      {
       "op": "const",
       "deg": 1,
       "id": 1,
       "next": false
      }
     ]
    }
   ]
  },
  { # b[0]
   "op": "cm",
   "deg": 1,
   "id": 2,
   "next": false
  },
  { # a
   "op": "cm",
   "deg": 1,
   "id": 1,
   "next": false
  },
  { # b[1]
   "op": "cm",
   "deg": 1,
   "id": 3,
   "next": false
  },
  { # c
   "op": "cm",
   "deg": 1,
   "id": 0,
   "next": false
  },
  { # d[1]
   "op": "const",
   "deg": 1,
   "id": 1,
   "next": false
  },
  { # d[0]
   "op": "const",
   "deg": 1,
   "id": 0,
   "next": false
  }
 ],
 "polIdentities": [
  {
   "e": 0,
   "fileName": "arrays.pil",
   "line": 6
  },
  {
   "e": 1,
   "fileName": "arrays.pil",
   "line": 11
  },
  {
   "e": 2,
   "fileName": "arrays.pil",
   "line": 12
  }
 ],
 "plookupIdentities": [
  {
   "f": [
    3,
    4
   ],
   "t": [
    6,
    7
   ],
   "selF": 5,
   "selT": 8,
   "fileName": "arrays.pil",
   "line": 14
  }
 ],
 "permutationIdentities": [],
 "connectionIdentities": []
}

附录:Polygon Hermez 2.0 zkEVM系列博客

  • ZK-Rollups工作原理
  • Polygon zkEVM——Hermez 2.0简介
  • Polygon zkEVM网络节点
  • Polygon zkEVM 基本概念
  • Polygon zkEVM Prover
  • Polygon zkEVM工具——PIL和CIRCOM
  • Polygon zkEVM节点代码解析
  • Polygon zkEVM的pil-stark Fibonacci状态机初体验
  • Polygon zkEVM的pil-stark Fibonacci状态机代码解析

你可能感兴趣的:(zkVM,零知识证明)