前序博客有:
Polygon zkEVM中将某类特定的计算表示为状态机。
Arithmetic状态机为Polygon zkEVM的6个二级状态机之一,主要由2大部分组成:
详细可参看审计培训视频Polygon zkEVM Training for Auditors - Arith state machine。
Polygon zkEVM的Arithmetic状态机主要是基于Secp256K1椭圆曲线E( y 2 = x 3 + 7 y^2=x^3+7 y2=x3+7,基域为 p = 2 256 − 2 32 − 2 9 − 2 8 − 2 7 − 2 6 − 2 4 − 1 p=2^{256}-2^{32}-2^9-2^8-2^7-2^6-2^4-1 p=2256−232−29−28−27−26−24−1)上的如下运算:【二进制表示为0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fL,与pil实现中eq公式内的p[0]p[1]等常量值对应。】
将以上运算以约束形式表示为:
EQ 0 : x 1 ⋅ y 1 + x 2 − y 2 ⋅ 2 256 − y 3 = 0 , EQ 1 : s ⋅ x 2 − s ⋅ x 1 − y 2 + y 1 + q 0 ⋅ p = 0 , EQ 2 : 2 ⋅ s ⋅ y 1 − 3 ⋅ x 1 ⋅ x 1 + q 0 ⋅ p = 0 , EQ 3 : s ⋅ s − x 1 − x 2 − x 3 + q 1 ⋅ p = 0 , EQ 4 : s ⋅ x 1 − s ⋅ x 3 − y 1 − y 3 + q 2 ⋅ p = 0 , \begin{aligned} \text{EQ}_0 \colon \quad &x_1 \cdot y_1 + x_2 - y_2 \cdot 2^{256} - y_3 = 0, \\ \text{EQ}_1 \colon \quad &s \cdot x_2 - s \cdot x_1 -y_2 + y_1 + q_0 \cdot p = 0, \\ \text{EQ}_2 \colon \quad & 2 \cdot s \cdot y_1 - 3 \cdot x_1 \cdot x_1 + q_0 \cdot p = 0, \\ \text{EQ}_3 \colon \quad & s \cdot s - x_1 - x_2 - x_3 + q_1 \cdot p = 0, \\ \text{EQ}_4 \colon \quad & s \cdot x_1 - s \cdot x_3 - y_1 - y_3 + q_2 \cdot p = 0, \end{aligned} EQ0:EQ1:EQ2:EQ3:EQ4:x1⋅y1+x2−y2⋅2256−y3=0,s⋅x2−s⋅x1−y2+y1+q0⋅p=0,2⋅s⋅y1−3⋅x1⋅x1+q0⋅p=0,s⋅s−x1−x2−x3+q1⋅p=0,s⋅x1−s⋅x3−y1−y3+q2⋅p=0,
其中 q 0 , q 1 , q 2 ∈ Z q_0,q_1,q_2 \in \mathbb{Z} q0,q1,q2∈Z为整数,使得以上等式成立。这种表达可避免对 p p p做除法运算。
这些约束对应3个可能的计算场景:
由于在以上任意场景下, E Q 1 EQ_1 EQ1和 E Q 2 EQ_2 EQ2最多只能激活一个,因此二者可“共享”相同的 q 0 q_0 q0。
为实现以上运算,Arithmetic状态机内需包含以下寄存器:
x 1 , y 1 , x 2 , y 2 , x 3 , y 3 , s , q 0 , q 1 , q 2 x_1,y_1,x_2,y_2,x_3,y_3,s,q_0,q_1,q_2 x1,y1,x2,y2,x3,y3,s,q0,q1,q2
这些寄存器均为256-bit field elements,实际构建时,将每个寄存器切分为16个子寄存器,每个子寄存器容量为16-bit(2个字节),为此,PIL中的定义为:
pol commit x1[16];
pol commit y1[16];
pol commit x2[16];
pol commit y2[16];
pol commit x3[16];
pol commit y3[16];
pol commit s[16];
pol commit q0[16];
pol commit q1[16];
pol commit q2[16];
以zkevm-proverjs/test/zkasm/counters/arith.zkasm为例:【$ npm run test:counters:arith
】
start:
STEP => A
0 :ASSERT
0 => A
CNT_ARITH :ASSERT
CNT_BINARY :ASSERT
CNT_KECCAK_F: ASSERT
CNT_MEM_ALIGN :ASSERT
CNT_POSEIDON_G :ASSERT
CNT_PADDING_PG :ASSERT
0 => A,B,C,D :ARITH #清零
CNT_ARITH => A
1 :ASSERT
CNT_ARITH => A
1 :ASSERT
0x2000000000000000000000000000000000000000000000000000000000000001n => A
0x100 => B
0x73 => C
0x20 => D
0x173 :ARITH #赋值
2 => A
CNT_ARITH :ASSERT
0 => A
CNT_KECCAK_F: ASSERT
CNT_MEM_ALIGN :ASSERT
CNT_POSEIDON_G :ASSERT
CNT_PADDING_PG :ASSERT
end:
0 => A,B,C,D,E,CTX, SP, PC, GAS, MAXMEM, SR
finalWait:
${beforeLast()} : JMPN(finalWait)
: JMP(start)
opINVALID:
经const rom = await zkasm.compile(path.join(__dirname, "zkasm", zkasmFile));
zkasmcom 编译后的结果为:
{
"program": [
{
"inSTEP": "1",
"setA": 1,
"line": 3,
"fileName": "arith.zkasm",
"lineStr": " STEP => A"
},
{
"CONST": "0",
"assert": 1,
"line": 4,
"fileName": "arith.zkasm",
"lineStr": " 0 :ASSERT"
},
{
"CONST": "0",
"setA": 1,
"line": 6,
"fileName": "arith.zkasm",
"lineStr": " 0 => A"
},
{
"inCntArith": "1",
"assert": 1,
"line": 7,
"fileName": "arith.zkasm",
"lineStr": " CNT_ARITH :ASSERT"
},
{
"inCntBinary": "1",
"assert": 1,
"line": 8,
"fileName": "arith.zkasm",
"lineStr": " CNT_BINARY :ASSERT"
},
{
"inCntKeccakF": "1",
"assert": 1,
"line": 9,
"fileName": "arith.zkasm",
"lineStr": " CNT_KECCAK_F: ASSERT"
},
{
"inCntMemAlign": "1",
"assert": 1,
"line": 10,
"fileName": "arith.zkasm",
"lineStr": " CNT_MEM_ALIGN :ASSERT"
},
{
"inCntPoseidonG": "1",
"assert": 1,
"line": 11,
"fileName": "arith.zkasm",
"lineStr": " CNT_POSEIDON_G :ASSERT"
},
{
"inCntPaddingPG": "1",
"assert": 1,
"line": 12,
"fileName": "arith.zkasm",
"lineStr": " CNT_PADDING_PG :ASSERT"
},
{
"CONST": "0",
"setA": 1,
"setB": 1,
"setC": 1,
"setD": 1,
"arith": 1,
"arithEq0": 1,
"line": 14,
"fileName": "arith.zkasm",
"lineStr": " 0 => A,B,C,D :ARITH"
},
{
"inCntArith": "1",
"setA": 1,
"line": 16,
"fileName": "arith.zkasm",
"lineStr": " CNT_ARITH => A"
},
{
"CONST": "1",
"assert": 1,
"line": 17,
"fileName": "arith.zkasm",
"lineStr": " 1 :ASSERT"
},
{
"inCntArith": "1",
"setA": 1,
"line": 19,
"fileName": "arith.zkasm",
"lineStr": " CNT_ARITH => A"
},
{
"CONST": "1",
"assert": 1,
"line": 20,
"fileName": "arith.zkasm",
"lineStr": " 1 :ASSERT"
},
{
"CONSTL": "14474011154664524427946373126085988481658748083205070504932198000989141204993",
"setA": 1,
"line": 22,
"fileName": "arith.zkasm",
"lineStr": " 0x2000000000000000000000000000000000000000000000000000000000000001n => A"
},
{
"CONST": "256",
"setB": 1,
"line": 23,
"fileName": "arith.zkasm",
"lineStr": " 0x100 => B"
},
{
"CONST": "115",
"setC": 1,
"line": 24,
"fileName": "arith.zkasm",
"lineStr": " 0x73 => C"
},
{
"CONST": "32",
"setD": 1,
"line": 25,
"fileName": "arith.zkasm",
"lineStr": " 0x20 => D"
},
{
"CONST": "371",
"arith": 1,
"arithEq0": 1,
"line": 26,
"fileName": "arith.zkasm",
"lineStr": " 0x173 :ARITH"
},
{
"CONST": "2",
"setA": 1,
"line": 29,
"fileName": "arith.zkasm",
"lineStr": " 2 => A"
},
{
"inCntArith": "1",
"assert": 1,
"line": 30,
"fileName": "arith.zkasm",
"lineStr": " CNT_ARITH :ASSERT"
},
{
"CONST": "0",
"setA": 1,
"line": 32,
"fileName": "arith.zkasm",
"lineStr": " 0 => A"
},
{
"inCntKeccakF": "1",
"assert": 1,
"line": 33,
"fileName": "arith.zkasm",
"lineStr": " CNT_KECCAK_F: ASSERT"
},
{
"inCntMemAlign": "1",
"assert": 1,
"line": 34,
"fileName": "arith.zkasm",
"lineStr": " CNT_MEM_ALIGN :ASSERT"
},
{
"inCntPoseidonG": "1",
"assert": 1,
"line": 35,
"fileName": "arith.zkasm",
"lineStr": " CNT_POSEIDON_G :ASSERT"
},
{
"inCntPaddingPG": "1",
"assert": 1,
"line": 36,
"fileName": "arith.zkasm",
"lineStr": " CNT_PADDING_PG :ASSERT"
},
{
"CONST": "0",
"setA": 1,
"setB": 1,
"setC": 1,
"setD": 1,
"setE": 1,
"setCTX": 1,
"setSP": 1,
"setPC": 1,
"setGAS": 1,
"setMAXMEM": 1,
"setSR": 1,
"line": 39,
"fileName": "arith.zkasm",
"lineStr": " 0 => A,B,C,D,E,CTX, SP, PC, GAS, MAXMEM, SR"
},
{
"freeInTag": {
"op": "functionCall",
"funcName": "beforeLast",
"params": []
},
"inFREE": "1",
"JMPC": 0,
"JMPN": 1,
"offset": 27,
"line": 42,
"offsetLabel": "finalWait",
"fileName": "arith.zkasm",
"lineStr": " ${beforeLast()} : JMPN(finalWait)"
},
{
"JMP": 1,
"JMPC": 0,
"JMPN": 0,
"offset": 0,
"line": 44,
"offsetLabel": "start",
"fileName": "arith.zkasm",
"lineStr": " : JMP(start)"
}
],
"labels": {
"start": 0,
"end": 26,
"finalWait": 27,
"opINVALID": 29
}
}
【Executor本质上是一种名为zkASM的汇编语言解释器。
使用zkASM语言来构建名为zkROM的程序,Executor运行zkROM程序来提供合适的execution trace。
在zkROM程序中,每个EVM opcode都以一组zkASM指令集来实现。
每个zkASM指令利用了execution trace矩阵中的一行,又名zkEVM的一个“step”。】即意味着const rom = await zkasm.compile(path.join(__dirname, "zkasm", zkasmFile));
zkasm编译的结果,会作为rom.pil的输入:
await smRom.buildConstants(constPols.Rom, rom);
:给rom.pil的常量多项式赋值。【实际上,Rom中全是常量多项式,为只读模式】const requiredMain = await smMain.execute(cmPols.Main, input, rom);
:根据zkasm编译的.rom.json文件和input(如../tools/build-genesis/input-executor.json
),获得main.pil的execution trace。以zkevm-proverjs中的 "test:counters:arith": "mocha -max-old-space-size=51200 test/counters/arith.js",
为例:
describe("Test Arith Counter", async function () {
this.timeout(10000000);
it("Verify Arith Zkasm Test", async () => {
await verifyZkasm("../zkasm/counters/arith.zkasm", true,
{ defines: {N: 2 ** 21},
namespaces: ['Global', 'Main', 'Rom', 'Byte4', 'Arith'], //只对这些namespace操作。
verbose: true,
color: true,
disableUnusedError: true});
});
});
基本流程为:
const requiredMain = await smMain.execute(cmPols.Main, input, rom);
await smByte4.execute(cmPols.Byte4, requiredMain.Byte4);
await smBinary.execute(cmPols.Binary, requiredMain.Binary || []);
接下来重点关注以上4)5)6)步骤的execution trace赋值细节。
其中的input为../tools/build-genesis/input-executor.json
:
{
"oldStateRoot": "0x2dc4db4293af236cb329700be43f08ace740a05088f8c7654736871709687e90",
"db": {
"0x2dc4db4293af236cb329700be43f08ace740a05088f8c7654736871709687e90": [
"0000000000000000",
"0000000000000000",
"0000000000000000",
"0000000000000000",
"0d1f0da5a7b620c8",
"43fd1e18e59fd724",
"d428d25da0cb1888",
"e31f5542ac227c06",
"0000000000000000",
"0000000000000000",
"0000000000000000",
"0000000000000000"
],
"0xe31f5542ac227c06d428d25da0cb188843fd1e18e59fd7240d1f0da5a7b620c8": [
"ed22ec7734d89ff2",
"b2e639153607b7c5",
"42b2bd6ec2788851",
"b781932941084783",
"3e63658ee0db910d",
"0b3e34316e81aa10",
"e0dc203d93f4e3e5",
"e10053d0ebc64602",
"0000000000000000",
"0000000000000000",
"0000000000000000",
"0000000000000000"
],
"0xb78193294108478342b2bd6ec2788851b2e639153607b7c5ed22ec7734d89ff2": [
"16dde42596b907f0",
"49015d7e991a1528",
"94dd9dadd060910b",
"60b4d5e9af514018",
"b69b044f5e694795",
"f57d81efba5d4445",
"339438195426ad0a",
"3efad1dd58c2259d",
"0000000000000001",
"0000000000000000",
"0000000000000000",
"0000000000000000"
],
"0x3efad1dd58c2259d339438195426ad0af57d81efba5d4445b69b044f5e694795": [
"00000000dea00000",
"0000000035c9adc5",
"0000000000000036",
"0000000000000000",
"0000000000000000",
"0000000000000000",
"0000000000000000",
"0000000000000000"
],
"0xe10053d0ebc64602e0dc203d93f4e3e50b3e34316e81aa103e63658ee0db910d": [
"66ee2be0687eea76",
"6926f8ca8796c78a",
"4c2f3e938869b82d",
"649e63bfe1247ba4",
"b69b044f5e694795",
"f57d81efba5d4445",
"339438195426ad0a",
"3efad1dd58c2259d",
"0000000000000001",
"0000000000000000",
"0000000000000000",
"0000000000000000"
]
},
"sequencerAddr": "0x617b3a3528F9cDd6630fd3301B9c8911F7Bf063D",
"batchL2Data": "0xee80843b9aca00830186a0944d5cf5032b2a844602278b01199ed191a86c93ff88016345785d8a0000808203e880801cee7e01dc62f69a12c3510c6d64de04ee6346d84b6a017f3e786c7d87f963e75d8cc91fa983cd6d9cf55fff80d73bd26cd333b0f098acc1e58edb1fd484ad731b",
"newStateRoot": "0xbff23fc2c168c033aaac77503ce18f958e9689d5cdaebb88c5524ce5c0319de3",
"oldLocalExitRoot": "0x17c04c3760510b48c6012742c540a81aba4bca2f78b9d14bfd2f123e2e53ea3e",
"newLocalExitRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
"globalExitRoot": "0x090bcaf734c4f06c93954a827b45a6e8c67b8e0fd1e0a35a1c5982d6961828f9",
"numBatch": 1,
"timestamp": 1944498031,
"contractsBytecode": {}
}
基于input-executor.json和arith.rom.json,对main.pil中的 隐私多项式赋值:
const requiredMain = await smMain.execute(cmPols.Main, input, rom);
smMain.execute
的核心流程为:
const db = new MemDB(Fr, input.db);
const smt = new SMT(db, poseidon, Fr);
initState(Fr, pols);
preprocessTxs
,取input-executor.json中的sequencerAddr、batchL2Data、newStateRoot、oldLocalExitRoot、newLocalExitRoot、globalExitRoot、numBatch、timestamp、oldStateRoot信息:
ethers.utils.solidityKeccak256
进行哈希运算】ctx.input.batchHashData = calculateBatchHashData(
ctx.input.batchL2Data,
globalExitRoot,
sequencerAddr
);
ethers.utils.solidityKeccak256
进行哈希运算】ctx.globalHash = calculateStarkInput(
oldStateRoot,
oldLocalExitRoot,
newStateRoot,
newLocalExitRoot,
ctx.input.batchHashData,
numBatch,
timestamp
);
{
"inSTEP": "1",
"setA": 1,
"line": 3,
"fileName": "arith.zkasm",
"lineStr": " STEP => A"
},
i | inSTEP | setA | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | isNeg | zkPC | JMP | JMPN | JMPC |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | l.inSTEP | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 1 |
{
"CONST": "0",
"assert": 1,
"line": 4,
"fileName": "arith.zkasm",
"lineStr": " 0 :ASSERT"
}
i | inSTEP | setA | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | isNeg | zkPC | JMP | JMPN | JMPC | assert | CONST0 | CONST1 | CONST2 | CONST3 | CONST4 | CONST5 | CONST6 | CONST7 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | l.inSTEP | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 1 | 0 | 0 | 0 | 1 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 2 |
{
"CONST": "0",
"setA": 1,
"line": 6,
"fileName": "arith.zkasm",
"lineStr": " 0 => A"
}
i | inSTEP | setA | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | isNeg | zkPC | JMP | JMPN | JMPC | assert | CONST0 | CONST1 | CONST2 | CONST3 | CONST4 | CONST5 | CONST6 | CONST7 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | l.inSTEP | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 1 | 0 | 0 | 0 | 1 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 1 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 2 | 0 | 0 | 0 | 0 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
3 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 3 |
{
"inCntArith": "1",
"assert": 1,
"line": 7,
"fileName": "arith.zkasm",
"lineStr": " CNT_ARITH :ASSERT"
}
i | inSTEP | setA | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | isNeg | zkPC | JMP | JMPN | JMPC | assert | CONST0 | CONST1 | CONST2 | CONST3 | CONST4 | CONST5 | CONST6 | CONST7 | inCntArith | cntArith |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | l.inSTEP | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 1 | 0 | 0 | 0 | 1 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 1 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 2 | 0 | 0 | 0 | 0 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
3 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 3 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntArith | 0 | |
4 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 4 |
{
"inCntBinary": "1",
"assert": 1,
"line": 8,
"fileName": "arith.zkasm",
"lineStr": " CNT_BINARY :ASSERT"
}
i | inSTEP | setA | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | isNeg | zkPC | JMP | JMPN | JMPC | assert | CONST0 | CONST1 | CONST2 | CONST3 | CONST4 | CONST5 | CONST6 | CONST7 | inCntArith | cntArith | inCntBinary | cntBinary |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | l.inSTEP | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 1 | 0 | 0 | 0 | 1 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 1 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 2 | 0 | 0 | 0 | 0 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | |
3 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 3 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntArith | 0 | 0 | 0 | |
4 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 4 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | inCntBinary | 0 | |
5 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 5 |
{
"inCntKeccakF": "1",
"assert": 1,
"line": 9,
"fileName": "arith.zkasm",
"lineStr": " CNT_KECCAK_F: ASSERT"
}
i | inSTEP | setA | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | isNeg | zkPC | JMP | JMPN | JMPC | assert | CONST0 | CONST1 | CONST2 | CONST3 | CONST4 | CONST5 | CONST6 | CONST7 | inCntArith | cntArith | inCntBinary | cntBinary | inCntKeccakF | cntKeccakF |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | l.inSTEP | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 1 | 0 | 0 | 0 | 1 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 1 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 2 | 0 | 0 | 0 | 0 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 3 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntArith | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 4 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | inCntBinary | 0 | 0 | 0 |
5 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntKeccakF | 0 |
6 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 6 |
{
"inCntMemAlign": "1",
"assert": 1,
"line": 10,
"fileName": "arith.zkasm",
"lineStr": " CNT_MEM_ALIGN :ASSERT"
},
i | inSTEP | setA | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | isNeg | zkPC | JMP | JMPN | JMPC | assert | CONST0 | CONST1 | CONST2 | CONST3 | CONST4 | CONST5 | CONST6 | CONST7 | inCntArith | cntArith | inCntBinary | cntBinary | inCntKeccakF | cntKeccakF | inCntMemAlign | cntMemAlign |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | l.inSTEP | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 1 | 0 | 0 | 0 | 1 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 1 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 2 | 0 | 0 | 0 | 0 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 3 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntArith | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 4 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | inCntBinary | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntKeccakF | 0 | 0 | 0 |
6 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 6 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntMemAlign | 0 |
7 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 7 |
{
"inCntPoseidonG": "1",
"assert": 1,
"line": 11,
"fileName": "arith.zkasm",
"lineStr": " CNT_POSEIDON_G :ASSERT"
},
i | inSTEP | setA | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | isNeg | zkPC | JMP | JMPN | JMPC | assert | CONST0 | CONST1 | CONST2 | CONST3 | CONST4 | CONST5 | CONST6 | CONST7 | inCntArith | cntArith | inCntBinary | cntBinary | inCntKeccakF | cntKeccakF | inCntMemAlign | cntMemAlign | inCntPoseidonG | cntPoseidonG |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | l.inSTEP | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 1 | 0 | 0 | 0 | 1 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 1 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 2 | 0 | 0 | 0 | 0 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 3 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntArith | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 4 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | inCntBinary | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntKeccakF | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 6 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntMemAlign | 0 | 0 | 0 |
7 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 7 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0l.inCntPoseidonG | 0 |
8 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 8 |
{
"inCntPaddingPG": "1",
"assert": 1,
"line": 12,
"fileName": "arith.zkasm",
"lineStr": " CNT_PADDING_PG :ASSERT"
}
i | inSTEP | setA | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | isNeg | zkPC | JMP | JMPN | JMPC | assert | CONST0 | CONST1 | CONST2 | CONST3 | CONST4 | CONST5 | CONST6 | CONST7 | inCntArith | cntArith | inCntBinary | cntBinary | inCntKeccakF | cntKeccakF | inCntMemAlign | cntMemAlign | inCntPoseidonG | cntPoseidonG | inCntPaddingPG | cntPaddingPG |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | l.inSTEP | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 1 | 0 | 0 | 0 | 1 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 1 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 2 | 0 | 0 | 0 | 0 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 3 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntArith | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 4 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | inCntBinary | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntKeccakF | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 6 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntMemAlign | 0 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 7 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0l.inCntPoseidonG | 0 | 0 | 0 |
8 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 8 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntPaddingPG | 0 |
9 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 9 |
{
"CONST": "0",
"setA": 1,
"setB": 1,
"setC": 1,
"setD": 1,
"arith": 1,
"arithEq0": 1,
"line": 14,
"fileName": "arith.zkasm",
"lineStr": " 0 => A,B,C,D :ARITH"
},
required.Arith.push({x1: A, y1: B, x2: C, y2: D, x3: Fr.zero, y3: op, selEq0: 1, selEq1: 0, selEq2: 0, selEq3: 0});
。
i | inSTEP | setA | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | isNeg | zkPC | JMP | JMPN | JMPC | assert | CONST0 | CONST1 | CONST2 | CONST3 | CONST4 | CONST5 | CONST6 | CONST7 | inCntArith | cntArith | inCntBinary | cntBinary | inCntKeccakF | cntKeccakF | inCntMemAlign | cntMemAlign | inCntPoseidonG | cntPoseidonG | inCntPaddingPG | cntPaddingPG | arith | arithEq0 | setB | B0-B7 | setC | C0-C7 | setD | D0-D7 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | l.inSTEP | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 1 | 0 | 0 | 0 | 1 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 1 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 2 | 0 | 0 | 0 | 0 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 3 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntArith | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 4 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | inCntBinary | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntKeccakF | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 6 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntMemAlign | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 7 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0l.inCntPoseidonG | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
8 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 8 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntPaddingPG | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
9 | 0 | 1 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 |
10 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 10 | 1 | op0-op7 | op0-op7 | op0-op7 |
{
"inCntArith": "1",
"setA": 1,
"line": 16,
"fileName": "arith.zkasm",
"lineStr": " CNT_ARITH => A"
}
i | inSTEP | setA | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | isNeg | zkPC | JMP | JMPN | JMPC | assert | CONST0 | CONST1 | CONST2 | CONST3 | CONST4 | CONST5 | CONST6 | CONST7 | inCntArith | cntArith | inCntBinary | cntBinary | inCntKeccakF | cntKeccakF | inCntMemAlign | cntMemAlign | inCntPoseidonG | cntPoseidonG | inCntPaddingPG | cntPaddingPG | arith | arithEq0 | setB | B0-B7 | setC | C0-C7 | setD | D0-D7 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | l.inSTEP | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
1 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 1 | 0 | 0 | 0 | 1 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
2 | 0 | 1 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 2 | 0 | 0 | 0 | 0 | l.CONST | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
3 | 0 | 0 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 3 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntArith | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
4 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 4 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | inCntBinary | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
5 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 5 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntKeccakF | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
6 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 6 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntMemAlign | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
7 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 7 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0l.inCntPoseidonG | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
8 | 0 | 0 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 8 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntPaddingPG | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
9 | 0 | 1 | op0(同上一行) | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 9 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 |
10 | 0 | 1 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 10 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | l.inCntArith | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | op0-op7 | 0 | op0-op7 | 0 | op0-op7 |
11 | op0 | op1 | op2 | op3 | op4 | op5 | op6 | op7 | 0 | 11 | 1 | op0-op7(同上一行) | op0-op7(同上一行) | op0-op7(同上一行) |
。。。。。
以此类推,给各个二级状态机的input信息见required
内容:
const required = {
Byte4: {},
Arith: [],
Binary: [],
PaddingKK: [],
PaddingPG: [],
PoseidonG: [],
Mem: [],
MemAlign: [],
Storage: []
};
如本例中:
{
"0": true,
"4294967295": true
}
required.Arith.push({x1: A, y1: B, x2: C, y2: D, x3: Fr.zero, y3: op, selEq0: 1, selEq1: 0, selEq2: 0, selEq3: 0});
smByte4.execute(cmPols.Byte4, requiredMain.Byte4);
如本例中,给Byte4的input为:【 4294967295 = 2 32 − 1 4294967295=2^{32}-1 4294967295=232−1】
{
"0": true,
"4294967295": true
}
byte4 execution trace执行逻辑为:
module.exports.execute = async function (pols, input) {
const N = pols.freeIN.length;
let p=0;
let last = 0;
Object.keys(input).forEach( (n) => {
const num = Number(n);
pols.freeIN[p] = BigInt(num >>> 16);//存储num的高16位
pols.out[p] = BigInt(last);//存储上一num值
p++;
pols.freeIN[p] = BigInt(num & 0xFFFF); //存储num的低16位
pols.out[p] = BigInt(num >>> 16);//存储num的高16位,即等于freeIN[p-1]
p++;
last = num;
});
pols.freeIN[p] = 0n;
pols.out[p] = BigInt(last);//存储上一num值
p++;
pols.freeIN[p] = 0n;
pols.out[p] = 0n;
p++;
if (p >= N) {
throw new Error("Too many byte4");
}
while (p<N) {
pols.freeIN[p] = 0n;
pols.out[p] = 0n;
p++;
}
}
byte4常量多项式逻辑为:
module.exports.buildConstants = async function (pols) {
const N = pols.SET.length;
for ( let i=0; i<N; i++) pols.SET[i] = (i % 2 == 0) ? 1n : 0n;
}
即本例实际赋值情况为:
index | SET | pols.freeIN | pols.out |
---|---|---|---|
0 | 1 | 0 | 0 |
1 | 0 | 0 | 0 |
2 | 1 | 65535 | 0 |
4 | 0 | 65535 | 65535 |
5 | 1 | 0 | 4294967295 |
6 | 0 | 0 | 0 |
7 | 1 | 0 | 0 |
⋮ \vdots ⋮ | ⋮ \vdots ⋮ | ⋮ \vdots ⋮ |
根据byte4.pil可知,相应的约束逻辑为:
/*
This state machine is able to builds any number of 4 bytes (32 bits)
Example for building numbers: 0x00030007, 0x12345678, 0x00050009 and 0
SET freeIN out out'
w^0 1 3 0 3
w^1 0 7 3 0x00030007
w^2 1 0x1234 0x00030007 0x1234
w^3 0 0x5678 0x1234 0x12345678
w^4 1 5 0x12345678 5
w^5 0 9 5 0x50009
w^6 1 0 0x50009 0
w^7 0 0 0 0
*/
include "global.pil";
namespace Byte4(%N);
/// Constant Polynomials
pol constant SET; // 1, 0, 1, 0, 1, 0 ......
/// State Polynomials
pol commit freeIN;
pol commit out;
freeIN in Global.BYTE2; // 0, 1, 2, , 65535
out' = SET*freeIN +
(1-SET)*(out * 2**16 + freeIN);
给Arith的input为:
required.Arith.push({x1: A, y1: B, x2: C, y2: D, x3: Fr.zero, y3: op, selEq0: 1, selEq1: 0, selEq2: 0, selEq3: 0});
本例中具体值为:
A: 14474011154664524427946373126085988481658748083205070504932198000989141204993 (0x2000000000000000000000000000000000000000000000000000000000000001)
B: 256 (0x100)
C: 115 (0x73)
D: 32 (0x20)
op: 371 (0x173)
满足的EQ0关系为: A ∗ B + C = D ∗ 2 256 + o p A*B+C=D*2^{256}+op A∗B+C=D∗2256+op。
arith.pil中的常量多项式赋值见:Polygon zkEVM中的常量多项式 中“7. arith.pil中的常量多项式”。
仍然以EQ0为例, EQ 0 : x 1 ⋅ y 1 + x 2 − y 2 ⋅ 2 256 − y 3 = 0 \begin{aligned} \text{EQ}_0 \colon \quad &x_1 \cdot y_1 + x_2 - y_2 \cdot 2^{256} - y_3 = 0\end{aligned} EQ0:x1⋅y1+x2−y2⋅2256−y3=0,将每个寄存器以16个16bit寄存器表示,并借助school multiplication算法:
从而有:
相应的计算见:sm_arith_eq0.js
。
不过,以上计算中未考虑进位(carry)的情况。需引入临时变量let carry = [0n, 0n, 0n];
来存储进位信息( e q + carry = carry ′ ⋅ 2 16 \mathbf{eq}+\text{carry}=\text{carry}'\cdot 2^{16} eq+carry=carry′⋅216),并将每一步累计的进位信息分别存储在carryL和carryH两个寄存器中: carry = carry L + carry H ⋅ 2 18 \text{carry} = \text{carry}_L + \text{carry}_H \cdot 2^{18} carry=carryL+carryH⋅218。
let carry = [0n, 0n, 0n];
const eqIndexToCarryIndex = [0, 0, 0, 1, 2];
for (let step = 0; step < 32; ++step) {
eqIndexes.forEach((eqIndex) => {
let carryIndex = eqIndexToCarryIndex[eqIndex];
eq[eqIndex] = eqCalculates[eqIndex](pols, step, offset); //调用sm_arith_eq0.js
pols.carryL[carryIndex][offset + step] = Fr.e((carry[carryIndex]) % (2n**18n));
pols.carryH[carryIndex][offset + step] = Fr.e((carry[carryIndex]) / (2n**18n));
carry[carryIndex] = (eq[eqIndex] + carry[carryIndex]) / (2n ** 16n);
});
}
arith.pil中包含的约束有:
x1[0]*CLK[0] + x1[1]*CLK[1] + x1[2]*CLK[2] + x1[3]*CLK[3] + x1[4]*CLK[4] + x1[5]*CLK[5] + x1[6]*CLK[6] + x1[7]*CLK[7]
+ x1[8]*CLK[8] + x1[9]*CLK[9] + x1[10]*CLK[10] + x1[11]*CLK[11] + x1[12]*CLK[12] + x1[13]*CLK[13] + x1[14]*CLK[14] + x1[15]*CLK[15]
+ y1[0]*CLK[16] + y1[1]*CLK[17] + y1[2]*CLK[18] + y1[3]*CLK[19] + y1[4]*CLK[20] + y1[5]*CLK[21] + y1[6]*CLK[22] + y1[7]*CLK[23]
+ y1[8]*CLK[24] + y1[9]*CLK[25] + y1[10]*CLK[26] + y1[11]*CLK[27] + y1[12]*CLK[28] + y1[13]*CLK[29] + y1[14]*CLK[30] + y1[15]*CLK[31] in Global.BYTE2;
pol eq0 = eq0_0*CLK[0] + eq0_1*CLK[1] + eq0_2*CLK[2] + eq0_3*CLK[3] + eq0_4*CLK[4] + eq0_5*CLK[5] + eq0_6*CLK[6] + eq0_7*CLK[7]
+ eq0_8*CLK[8] + eq0_9*CLK[9] + eq0_10*CLK[10] + eq0_11*CLK[11] + eq0_12*CLK[12] + eq0_13*CLK[13] + eq0_14*CLK[14] + eq0_15*CLK[15]
+ eq0_16*CLK[16] + eq0_17*CLK[17] + eq0_18*CLK[18] + eq0_19*CLK[19] + eq0_20*CLK[20] + eq0_21*CLK[21] + eq0_22*CLK[22] + eq0_23*CLK[23]
+ eq0_24*CLK[24] + eq0_25*CLK[25] + eq0_26*CLK[26] + eq0_27*CLK[27] + eq0_28*CLK[28] + eq0_29*CLK[29] + eq0_30*CLK[30] + eq0_31*CLK[31];
selEq[0] * (1-selEq[0]) = 0;
selEq[1] * (1-selEq[1]) = 0;
selEq[2] * (1-selEq[2]) = 0;
selEq[3] * (1-selEq[3]) = 0;
carryL[0] in GL_SIGNED_18BITS;
carryL[1] in GL_SIGNED_18BITS;
carryL[2] in GL_SIGNED_18BITS;
{carryH[0], carryH[1], carryH[2]} in {GL_SIGNED_4BITS_C0, GL_SIGNED_4BITS_C1, GL_SIGNED_4BITS_C2}; // 3 * (4+1) = 15 bits
// eq + carry = carry' * 2**16
// carry = cl + ch * 2**18
// eq + cl + ch * 2**18 = cl 2**16 + ch * 2**34
selEq[0] * (eq0 + carryL[0] + 2**18 * carryH[0]) = selEq[0] * (carryL[0]' * 2**16 + carryH[0]' * 2**34);
[1] The Arithmetic State Machine