前序博客有:
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
,
其中
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

从而有:
相应的计算见: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