const resP = await starkGen(comPols, constPols, constTree, starkInfo)
其中输入有:
starkGen
函数内各关键变量含义为:
各关键变量定义为:
N = 2 nBits N=2^{\text{nBits}} N=2nBits
Next = 2 nBitsExt \text{Next}=2^{\text{nBitsExt}} Next=2nBitsExt
extendBits = nBitsExt − nBits \text{extendBits}=\text{nBitsExt}-\text{nBits} extendBits=nBitsExt−nBits
令 w w w为 F F F域内的 N N N-th root of unity, w ′ w' w′为 F F F域内的 Next \text{Next} Next-th root of unity。
令 g g g为 F . shift F.\text{shift} F.shift, e e e为 F F F域内的 2 extendBits 2^{\text{extendBits}} 2extendBits-th root of unity。
ctx.Zi \text{ctx.Zi} ctx.Zi 表示的是长度为 Next \text{Next} Next的数组,其每个元素i为:
1 ( g w ′ ) 2 nBits − 1 = 1 ( g 2 nBits ∗ e i ) − 1 = 1 g N ∗ e i − 1 \frac{1}{(gw')^{2^{\text{nBits}}}-1}=\frac{1}{(g^{2^{\text{nBits}}}*e^i)-1}=\frac{1}{g^N*e^i-1} (gw′)2nBits−11=(g2nBits∗ei)−11=gN∗ei−11
x_n为长度为N的数组,其每个元素 i i i为: w i w^i wi,其中 w w w为 F F F域内的 N N N-th root of unity。【ctx.x_n
为trace domain的插值点】
x_2ns为长度为 Next \text{Next} Next的数组,其每个元素 i i i为: g w ′ i gw'^i gw′i,其中 w ′ w' w′为 F F F域内的 Next \text{Next} Next-th root of unity。【ctx.x_2ns
为low degree extension domain的插值点】
令challenge[7]= x i x_i xi,有: xis = x i / g , wxis = ( w x i ) / g \text{xis}=x_i/g,\text{wxis}=(wx_i)/g xis=xi/g,wxis=(wxi)/g。构建长度为 N N N的数组LEv_tmp,其每个元素 i i i为: ( x i / g ) i (x_i/g)^i (xi/g)i;构建长度为 N N N的数组LpEv_tmp,其每个元素 i i i为: ( ( w x i / g ) i ((wx_i/g)^i ((wxi/g)i。以LEv_tmp中值为插值点 y y y坐标,以x_n为插值点 x x x坐标,ifft获得多项式系数数组LEv;同理以LpEv_tmp中值为插值点 y y y坐标,以x_n为插值点 x x x坐标,ifft获得多项式系数数组LpEv。
l = ev.prime ? LpEv : LEv;
。根据ev.type取相应的扩域ctx.*_2ns evaluations中依次取第0、1<共N个值 v v v,计算 ctx.evals [ i ] = ∑ k = 0 N − 1 v [ k ] ∗ l [ k ] \text{ctx.evals}[i]=\sum_{k=0}^{N-1}v[k]*l[k] ctx.evals[i]=∑k=0N−1v[k]∗l[k]。ctx.evals数组的长度为starkInfo.evMap.length。【后续计算FRI多项式扩域值ctx.exps_withoutq_2ns需用到。】
令 wxi = w x i \text{wxi}=wx_i wxi=wxi,其中 w w w为 F F F域内的 N N N-th root of unity。
ctx.xDivXSubXi 和 ctx.xDivXSubWXi 均为长度为 N \text{N} N的数组,其每个元素 i i i均为Goldilocks extension 3 域元素,表示为 [ a i , b i , c i ] [a_i,b_i,c_i] [ai,bi,ci]。
starkInfo.json中的“Zi”标签,在compileCode
时翻译为ctx.Zi(i)
。
以Fibonacci为例:
namespace Fibonacci(%N);
pol constant L1, LLAST; //constant多项式
pol commit l1,l2; //commit多项式
pol l2c = l2; //中间多项式
//公开变量值
public in1 = l2c(0);
public in2 = l1(0);
public out = l1(%N-1);
(l2' - l1)*(1-LLAST) = 0; //约束1
pol next = l1*l1 + l2*l2; //中间多项式
(l1' - next)*(1-LLAST) = 0; //约束2
L1 * (l2 - :in1) = 0; //约束3
L1 * (l1 - :in2) = 0; //约束4
LLAST * (l1 - :out) = 0; //约束5
序号 | 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 |
L1->constP_0,LLAST->constP_1,l1->cmP_0,l2->cmP_1,l2c->imP_0,next->imP_2
pol next = l1*l1 + l2*l2;
;polyIdentity
多项式(也为中间多项式,有idQ标签)为借助challenges[4]将所有polIdentities约束合并为一个的多项式。【其中polyIdentity
多项式基于Goldilocks extension 3 域,其每个evaluation值由 [ a , b , c ] [a,b,c] [a,b,c]三个元素表示。】)compileCode
后对应的函数为:【本质为计算中间多项式next和polyIdentity在trace domain的evaluation值】(function anonymous(ctx,i
) {
ctx.tmp[0] = ctx.F.mul(ctx.cm1_n[0 + i*2], ctx.cm1_n[0 + i*2]); //l1*l1
ctx.tmp[1] = ctx.F.mul(ctx.cm1_n[1 + i*2], ctx.cm1_n[1 + i*2]); //l2*l2
ctx.exps_withq_n[0 + i*4] = ctx.F.add(ctx.tmp[0], ctx.tmp[1]);// next=l1*l1+l2*l2
ctx.tmp[2] = ctx.F.sub(ctx.cm1_n[1 + ((i + 1)%1024)*2], ctx.cm1_n[0 + i*2]); //l2'-l1
ctx.tmp[3] = ctx.F.sub(1n, ctx.const_n[1 + i*2]); //1-LLAST
ctx.tmp[4] = ctx.F.mul(ctx.tmp[2], ctx.tmp[3]); //(l2'-l1)*(1-LLAST)
ctx.tmp[21] = ctx.F.sub(ctx.tmp[4], 0n); //(l2'-l1)*(1-LLAST)-0,约束1
ctx.tmp[5] = ctx.F.sub(ctx.cm1_n[0 + ((i + 1)%1024)*2], ctx.exps_withq_n[0 + i*4]);//l1'-next
ctx.tmp[6] = ctx.F.sub(1n, ctx.const_n[1 + i*2]);//1-LLAST
ctx.tmp[7] = ctx.F.mul(ctx.tmp[5], ctx.tmp[6]);//(l1'-next)*(1-LLAST)
ctx.tmp[22] = ctx.F.sub(ctx.tmp[7], 0n);//(l1'-next)*(1-LLAST)-0,约束2
ctx.tmp[8] = ctx.F.sub(ctx.cm1_n[1 + i*2], ctx.publics[0]);//l2-in1
ctx.tmp[9] = ctx.F.mul(ctx.const_n[0 + i*2], ctx.tmp[8]); //L1*(l2-in1)
ctx.tmp[23] = ctx.F.sub(ctx.tmp[9], 0n);//L1*(l2-in1)-0,约束3
ctx.tmp[10] = ctx.F.sub(ctx.cm1_n[0 + i*2], ctx.publics[1]);//l1-in2
ctx.tmp[11] = ctx.F.mul(ctx.const_n[0 + i*2], ctx.tmp[10]);//L1*(l1-in2)
ctx.tmp[24] = ctx.F.sub(ctx.tmp[11], 0n);//L1*(l1-in2)-0,约束4
ctx.tmp[12] = ctx.F.sub(ctx.cm1_n[0 + i*2], ctx.publics[2]);//l1-out
ctx.tmp[13] = ctx.F.mul(ctx.const_n[1 + i*2], ctx.tmp[12]);//LLAST*(l1-out)
ctx.tmp[25] = ctx.F.sub(ctx.tmp[13], 0n);//LLAST*(l1-out)-0,约束5
ctx.tmp[14] = ctx.F.mul(ctx.challenges[4], ctx.tmp[21]);
ctx.tmp[15] = ctx.F.add(ctx.tmp[14], ctx.tmp[22]);
ctx.tmp[16] = ctx.F.mul(ctx.challenges[4], ctx.tmp[15]);
ctx.tmp[17] = ctx.F.add(ctx.tmp[16], ctx.tmp[23]);
ctx.tmp[18] = ctx.F.mul(ctx.challenges[4], ctx.tmp[17]);
ctx.tmp[19] = ctx.F.add(ctx.tmp[18], ctx.tmp[24]);
ctx.tmp[20] = ctx.F.mul(ctx.challenges[4], ctx.tmp[19]);
//借助challenges[4],将以上5个约束合并为一个约束多项式polyIdentity
[ ctx.exps_withq_n[1 + i*4] , ctx.exps_withq_n[1 + i*4 + 1] , ctx.exps_withq_n[1 + i*4 + 2] ]
= ctx.F.add(ctx.tmp[20], ctx.tmp[25]);
})
extend
计算在low degree extension domain中相应的evaluation值ctx.const_2ns/cm1_2ns/cm2_2ns/cm3_2ns/exps_withq_2ns。
pol next = l1*l1 + l2*l2;
;polyIdentity
多项式(也为中间多项式,有idQ标签)为借助challenges[4]将所有polIdentities约束合并为一个的多项式。【其中polyIdentity
多项式基于Goldilocks extension 3 域,其每个evaluation值由 [ a , b , c ] [a,b,c] [a,b,c]三个元素表示。】)compileCode
后对应的函数为:【本质为,构建中间多项式next和polyIdentity在扩域的约束,并均乘以Zi(i),获得ctx.q_2ns
。】(function anonymous(ctx,i
) {
ctx.tmp[0] = ctx.F.mul(ctx.cm1_2ns[0 + i*2], ctx.cm1_2ns[0 + i*2]); //l1*l1
ctx.tmp[1] = ctx.F.mul(ctx.cm1_2ns[1 + i*2], ctx.cm1_2ns[1 + i*2]);//l2*l2
ctx.tmp[2] = ctx.F.add(ctx.tmp[0], ctx.tmp[1]);//l1*l1+l2*l2
ctx.tmp[3] = ctx.F.sub(ctx.tmp[2], ctx.exps_withq_2ns[0 + i*4]);//l1*l1+l2*l2-next,构建中间多项式next在扩域的约束
ctx.q_2ns[0 + i*4] = ctx.F.mul(ctx.Zi(i), ctx.tmp[3]);//(l1*l1+l2*l2-next)*Zi(i),中间多项式next约束扩域值与Zi(i)相乘
ctx.tmp[4] = ctx.F.sub(ctx.cm1_2ns[1 + ((i + 2)%2048)*2], ctx.cm1_2ns[0 + i*2]); // l2'-l1
ctx.tmp[5] = ctx.F.sub(1n, ctx.const_2ns[1 + i*2]);//1-LLAST
ctx.tmp[6] = ctx.F.mul(ctx.tmp[4], ctx.tmp[5]);//(l2'-l1)*(1-LLAST)
ctx.tmp[25] = ctx.F.sub(ctx.tmp[6], 0n);//(l2'-l1)*(1-LLAST)-0,约束1
ctx.tmp[7] = ctx.F.sub(ctx.cm1_2ns[0 + ((i + 2)%2048)*2], ctx.exps_withq_2ns[0 + i*4]);//l1'-next
ctx.tmp[8] = ctx.F.sub(1n, ctx.const_2ns[1 + i*2])//1-LLAST
ctx.tmp[9] = ctx.F.mul(ctx.tmp[7], ctx.tmp[8]);//(l1'-next)*(1-LLAST)
ctx.tmp[26] = ctx.F.sub(ctx.tmp[9], 0n);//(l1'-next)*(1-LLAST)-0,约束2
ctx.tmp[10] = ctx.F.sub(ctx.cm1_2ns[1 + i*2], ctx.publics[0]);//l2-in1
ctx.tmp[11] = ctx.F.mul(ctx.const_2ns[0 + i*2], ctx.tmp[10]);//L1*(l2-in1)
ctx.tmp[27] = ctx.F.sub(ctx.tmp[11], 0n);//L1*(l2-in1)-0,约束3
ctx.tmp[12] = ctx.F.sub(ctx.cm1_2ns[0 + i*2], ctx.publics[1]);//l1-in2
ctx.tmp[13] = ctx.F.mul(ctx.const_2ns[0 + i*2], ctx.tmp[12]);//L1*(l1-in2)
ctx.tmp[28] = ctx.F.sub(ctx.tmp[13], 0n);//L1*(l1-in2)-0,约束4
ctx.tmp[14] = ctx.F.sub(ctx.cm1_2ns[0 + i*2], ctx.publics[2]);//l1-out
ctx.tmp[15] = ctx.F.mul(ctx.const_2ns[1 + i*2], ctx.tmp[14]);//LLAST*(l1-out)
ctx.tmp[29] = ctx.F.sub(ctx.tmp[15], 0n);//LLAST*(l1-out)-0,约束5
ctx.tmp[16] = ctx.F.mul(ctx.challenges[4], ctx.tmp[25]);
ctx.tmp[17] = ctx.F.add(ctx.tmp[16], ctx.tmp[26]);
ctx.tmp[18] = ctx.F.mul(ctx.challenges[4], ctx.tmp[17]);
ctx.tmp[19] = ctx.F.add(ctx.tmp[18], ctx.tmp[27]);
ctx.tmp[20] = ctx.F.mul(ctx.challenges[4], ctx.tmp[19]);
ctx.tmp[21] = ctx.F.add(ctx.tmp[20], ctx.tmp[28]);
ctx.tmp[22] = ctx.F.mul(ctx.challenges[4], ctx.tmp[21]);
ctx.tmp[23] = ctx.F.add(ctx.tmp[22], ctx.tmp[29]);
//引入challenges[4]将所有约束合并为一个中间多项式polyIdentity,
//构建中间多项式polyIdentity在扩域的约束
ctx.tmp[24] = ctx.F.sub(ctx.tmp[23], [ ctx.exps_withq_2ns[1 + i*4] , ctx.exps_withq_2ns[1 + i*4 + 1] ,
ctx.exps_withq_2ns[1 + i*4 + 2] ]);
//中间多项式polyIdentity约束扩域值与Zi(i)相乘
[ ctx.q_2ns[1 + i*4] , ctx.q_2ns[1 + i*4 + 1] , ctx.q_2ns[1 + i*4 + 2] ] = ctx.F.mul(ctx.Zi(i), ctx.tmp[24]);
})
compileCode
后对应的函数为:【负责将多个多项式合并为一个多项式——FRI多项式,如下面的exp8即为FRI多项式。并计算FRI多项式在扩域的插值ctx.exps_withoutq_2ns,其每个元素为Goldilocks extension 3 域元素。】
starkGen
函数中的friPol
变量,即为FRI多项式的扩域插值,friPol
本质就是ctx.exps_withoutq_2ns,friPol
数组长度为 Next \text{Next} Next。】(function anonymous(ctx,i
) {
ctx.tmp[25] = ctx.F.mul(ctx.challenges[5], ctx.cm1_2ns[0 + i*2]);
ctx.tmp[26] = ctx.F.add(ctx.tmp[25], ctx.cm1_2ns[1 + i*2]);
ctx.tmp[27] = ctx.F.mul(ctx.challenges[5], ctx.tmp[26]);
ctx.tmp[28] = ctx.F.add(ctx.tmp[27], ctx.q_2ns[0 + i*4]);
ctx.tmp[29] = ctx.F.mul(ctx.challenges[5], ctx.tmp[28]);
ctx.tmp[30] = ctx.F.add(ctx.tmp[29], [ ctx.q_2ns[1 + i*4] , ctx.q_2ns[1 + i*4 + 1] , ctx.q_2ns[1 + i*4 + 2] ]);
ctx.tmp[31] = ctx.F.mul(ctx.challenges[5], ctx.tmp[30]);
ctx.tmp[32] = ctx.F.sub(ctx.cm1_2ns[0 + i*2], ctx.evals[1]);
ctx.tmp[33] = ctx.F.mul(ctx.tmp[32], ctx.challenges[6]);
ctx.tmp[34] = ctx.F.sub(ctx.const_2ns[1 + i*2], ctx.evals[2]);
ctx.tmp[35] = ctx.F.add(ctx.tmp[33], ctx.tmp[34]);
ctx.tmp[36] = ctx.F.mul(ctx.tmp[35], ctx.challenges[6]);
ctx.tmp[37] = ctx.F.sub(ctx.cm1_2ns[1 + i*2], ctx.evals[3]);
ctx.tmp[38] = ctx.F.add(ctx.tmp[36], ctx.tmp[37]);
ctx.tmp[39] = ctx.F.mul(ctx.tmp[38], ctx.challenges[6]);
ctx.tmp[40] = ctx.F.sub(ctx.q_2ns[0 + i*4], ctx.evals[4]);
ctx.tmp[41] = ctx.F.add(ctx.tmp[39], ctx.tmp[40]);
ctx.tmp[42] = ctx.F.mul(ctx.tmp[41], ctx.challenges[6]);
ctx.tmp[43] = ctx.F.sub(ctx.const_2ns[0 + i*2], ctx.evals[6]);
ctx.tmp[44] = ctx.F.add(ctx.tmp[42], ctx.tmp[43]);
ctx.tmp[45] = ctx.F.mul(ctx.tmp[44], ctx.challenges[6]);
ctx.tmp[46] = ctx.F.sub([ ctx.q_2ns[1 + i*4] , ctx.q_2ns[1 + i*4 + 1] , ctx.q_2ns[1 + i*4 + 2] ], ctx.evals[7]);
ctx.tmp[47] = ctx.F.add(ctx.tmp[45], ctx.tmp[46]);
ctx.tmp[48] = ctx.F.mul(ctx.tmp[47], [ctx.xDivXSubXi[3*i], ctx.xDivXSubXi[3*i+1], ctx.xDivXSubXi[3*i+2]]);
ctx.tmp[49] = ctx.F.add(ctx.tmp[31], ctx.tmp[48]);
ctx.tmp[50] = ctx.F.mul(ctx.challenges[5], ctx.tmp[49]);
ctx.tmp[51] = ctx.F.sub(ctx.cm1_2ns[1 + i*2], ctx.evals[0]);
ctx.tmp[52] = ctx.F.mul(ctx.tmp[51], ctx.challenges[6]);
ctx.tmp[53] = ctx.F.sub(ctx.cm1_2ns[0 + i*2], ctx.evals[5]);
ctx.tmp[54] = ctx.F.add(ctx.tmp[52], ctx.tmp[53]);
ctx.tmp[55] = ctx.F.mul(ctx.tmp[54], [ctx.xDivXSubWXi[3*i], ctx.xDivXSubWXi[3*i+1], ctx.xDivXSubWXi[3*i+2]]);
[ ctx.exps_withoutq_2ns[0 + i*3] , ctx.exps_withoutq_2ns[0 + i*3 + 1] , ctx.exps_withoutq_2ns[0 + i*3 + 2] ] = ctx.F.add(ctx.tmp[50], ctx.tmp[55]);
})
const friProof = await fri.prove(transcript, friPol, queryPol);
,其中:
"steps": [
{"nBits": 11},
{"nBits": 7},
{"nBits": 3}
]