前序博客有:
由上图可知,zkEVM会借助SNARK来“验证((验证STARK证明)的SNARK证明)”:
约束表达:
序号 | x x x | A \mathbf{A} A( l 2 ( x ) l_2(x) l2(x)多项式) | B \mathbf{B} B( l 1 ( x ) l_1(x) l1(x)多项式) | i s I n i t i a l \mathbf{isInitial} isInitial( L 1 ( x ) L_1(x) L1(x)多项式) | i s L a s t \mathbf{isLast} isLast( L L A S T ( x ) LLAST(x) LLAST(x)多项式) |
---|---|---|---|---|---|
0 | ω 0 \omega^0 ω0 | 1 | 2 | 1 | 0 |
1 | ω 1 \omega^1 ω1 | 2 | 5 | 0 | 0 |
2 | ω 2 \omega^2 ω2 | 5 | 29 | 0 | 0 |
⋮ \vdots ⋮ | ⋮ \vdots ⋮ | ⋮ \vdots ⋮ | ⋮ \vdots ⋮ | ⋮ \vdots ⋮ | ⋮ \vdots ⋮ |
1023 | ω 1023 \omega^{1023} ω1023 | … | 74469561660084004 | 0 | 1 |
以PIL-STARK 中的Fibonacci为例,在验证其STARK proof的Plonk表达中,除以上 Q m , Q l , Q r , Q o , Q k Q_m,Q_l,Q_r,Q_o,Q_k Qm,Ql,Qr,Qo,Qk selector之外,还额外引入了定制门 selector Q M D S , Q C M U L Q_{MDS},Q_{CMUL} QMDS,QCMUL:
pol constant Qm, Ql, Qr, Qo, Qk, QMDS, QCMul; //selector
fibonacci.c12.pil
约束中的execution trace输入每行有12个:
pol commit a[12]; // 输入寄存器,粒度为单个Goldilocks基域元素
公开输入的约束为:
public pub0 = a[0](0); //公开输入,对应Goldilocks基域
public pub1 = a[1](0);
public pub2 = a[2](0);
Global.L1 * (a[0] - :pub0) = 0; //L1为常量多项式
Global.L1 * (a[1] - :pub1) = 0;
Global.L1 * (a[2] - :pub2) = 0;
对于常规Plonk equation来说,execution trace中每一行的12个输入,每3个输入对应一个Plonk约束,一行对应4个Plonk约束:
// Normal plonk equations //标准Plonk 电路,一行有4个Plonk 标准电路
pol a01 = a[0]*a[1];
Qm*a01 + Ql*a[0] + Qr*a[1] + Qo*a[2] + Qk = 0;
pol a34 = a[3]*a[4];
Qm*a34 + Ql*a[3] + Qr*a[4] + Qo*a[5] + Qk = 0;
pol a67 = a[6]*a[7];
Qm*a67 + Ql*a[6] + Qr*a[7] + Qo*a[8] +Qk = 0;
pol a910 = a[9]*a[10];
Qm*a910 + Ql*a[9] + Qr*a[10] + Qo*a[11] +Qk = 0;
对于MDS定制电路,execution trace下一行与上一行值的约束关系为:【MDS定制电路,需使用execution trace中的2行输入】
// MDS 定制电路,一个电路占用两行
QMDS * (a[ 0]' - (25*a[0] + 15*a[1] + 41*a[2] + 16*a[3] + 2*a[4] + 28*a[5] + 13*a[6] + 13*a[7] + 39*a[8] + 18*a[9] + 34*a[10] + 20*a[11])) = 0;
QMDS * (a[ 1]' - (20*a[0] + 17*a[1] + 15*a[2] + 41*a[3] + 16*a[4] + 2*a[5] + 28*a[6] + 13*a[7] + 13*a[8] + 39*a[9] + 18*a[10] + 34*a[11])) = 0;
QMDS * (a[ 2]' - (34*a[0] + 20*a[1] + 17*a[2] + 15*a[3] + 41*a[4] + 16*a[5] + 2*a[6] + 28*a[7] + 13*a[8] + 13*a[9] + 39*a[10] + 18*a[11])) = 0;
QMDS * (a[ 3]' - (18*a[0] + 34*a[1] + 20*a[2] + 17*a[3] + 15*a[4] + 41*a[5] + 16*a[6] + 2*a[7] + 28*a[8] + 13*a[9] + 13*a[10] + 39*a[11])) = 0;
QMDS * (a[ 4]' - (39*a[0] + 18*a[1] + 34*a[2] + 20*a[3] + 17*a[4] + 15*a[5] + 41*a[6] + 16*a[7] + 2*a[8] + 28*a[9] + 13*a[10] + 13*a[11])) = 0;
QMDS * (a[ 5]' - (13*a[0] + 39*a[1] + 18*a[2] + 34*a[3] + 20*a[4] + 17*a[5] + 15*a[6] + 41*a[7] + 16*a[8] + 2*a[9] + 28*a[10] + 13*a[11])) = 0;
QMDS * (a[ 6]' - (13*a[0] + 13*a[1] + 39*a[2] + 18*a[3] + 34*a[4] + 20*a[5] + 17*a[6] + 15*a[7] + 41*a[8] + 16*a[9] + 2*a[10] + 28*a[11])) = 0;
QMDS * (a[ 7]' - (28*a[0] + 13*a[1] + 13*a[2] + 39*a[3] + 18*a[4] + 34*a[5] + 20*a[6] + 17*a[7] + 15*a[8] + 41*a[9] + 16*a[10] + 2*a[11])) = 0;
QMDS * (a[ 8]' - ( 2*a[0] + 28*a[1] + 13*a[2] + 13*a[3] + 39*a[4] + 18*a[5] + 34*a[6] + 20*a[7] + 17*a[8] + 15*a[9] + 41*a[10] + 16*a[11])) = 0;
QMDS * (a[ 9]' - (16*a[0] + 2*a[1] + 28*a[2] + 13*a[3] + 13*a[4] + 39*a[5] + 18*a[6] + 34*a[7] + 20*a[8] + 17*a[9] + 15*a[10] + 41*a[11])) = 0;
QMDS * (a[10]' - (41*a[0] + 16*a[1] + 2*a[2] + 28*a[3] + 13*a[4] + 13*a[5] + 39*a[6] + 18*a[7] + 34*a[8] + 20*a[9] + 17*a[10] + 15*a[11])) = 0;
QMDS * (a[11]' - (15*a[0] + 41*a[1] + 16*a[2] + 2*a[3] + 28*a[4] + 13*a[5] + 13*a[6] + 39*a[7] + 18*a[8] + 34*a[9] + 20*a[10] + 17*a[11])) = 0;
Goldilocks extension 3域乘法运算逻辑为:
mul(a, b) {
if (typeof(a) == "bigint") { //a为整数,Goldilocks基域
if (typeof(b) == "bigint") { //b为整数,Goldilocks基域
return (a*b) % this.p;
} else { //b为Goldilocks extension 3域
return [(a*b[0]) % this.p, (a*b[1]) % this.p, (a*b[2]) % this.p];
}
} else if (typeof(b) == "bigint") { //b为整数,Goldilocks基域
return [(a[0]*b) % this.p, (a[1]*b) % this.p, (a[2]*b) % this.p];
} else { //a和b均为Goldilocks extension 3域
const A = (a[0] + a[1]) * (b[0] + b[1]);
const B = (a[0] + a[2]) * (b[0] + b[2]);
const C = (a[1] + a[2]) * (b[1] + b[2]);
const D = a[0]*b[0];
const E = a[1]*b[1];
const F = a[2]*b[2];
const G = D - E;
return [ (C + G - F)%this.p, (A + C - E -E - D )%this.p,(B-G)%this.p ];
}
}
当a和b均为Goldilocks extension 3域时,计算 c = a ∗ b c=a*b c=a∗b的约束表示为,将execution trace一行中的前3个输入表示为 a a a,接下来3个输入表示为 b b b,再接下来的3个输入表示为 c c c:
// CMUL // mul 乘法定制电路,一个占用一行
pol A = (a[0] + a[1]) * (a[3] + a[4]);
pol B = (a[0] + a[2]) * (a[3] + a[5]);
pol C = (a[1] + a[2]) * (a[4] + a[5]);
pol D = a[0]*a[3];
pol E = a[1]*a[4];
pol F = a[2]*a[5];
QCMul * (a[6] - (C + D - E - F)) = 0;
QCMul * (a[7] - (A + C - 2*E - D)) = 0;
QCMul * (a[8] - (B - D + E)) = 0;
为了表示execution trace中各元素之间的copy constraints关系,引入了:
pol constant S[12]; // 用于copy constraints
// Connection equations
{a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11]} connect
{S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10], S[11]};