本文介绍 Generalized Lasso,也是 [Lasso] 论文的关键部分之一。与 Lasso 相比,Generalized Lasso 不再对大表格进行拆分,而是把表格作为整体进行证明。为了处理超大尺寸表格,Generalized Lasso 需要要求表格中的每一项是可以通过其 Index 的二进制表示进行计算得到。对于尺寸为 N 的超大表格而言,其 Index 的二进制位数量为 logN,因此表格的表项的计算复杂度一定为 O(logN)。
这样做的一个优势是,Prover 可以不必要对表格进行承诺计算,当 Verifier 挑战表格编码的多项式时,Verifier 可以自行计算挑战点的多项式求值,因为这个运算复杂度仅为 O(logN)。这样 Prover 可以节省大量的计算时间。
按照 [Lasso] 论文的定义,MLE-structured 是指任何 MLE 多项式 t~(X) 可以在 O(logN) 时间的计算复杂度内完成求值运算。这里 N 为 2s,s 为多项式未知数的个数。
哪些表格具有这种 MLE-structured 的性质呢?下面给出一些常用的例子:
- Range check 表格,ti∈[0,N)。
- 连续偶数或者奇数构成的表格,ti=2k,ti∈[0,N)
- Spread 表格。一种在数字二进制表示的相邻两位插入 0 的表格,例如,对于 i=0110,ti=00101000。这种表格用来加速实现位运算。
Generalized Lasso 可以构造针对 MLE-Structured 表格的 Indexed Lookup Argument。其核心是证明下面的等式:
f(X)=y∈{0,1}logN∑M(X,y)⋅t~(y)
这里 f 为查询向量,长度为 m;t 为表格向量,长度为 N;M∈Fm×N 为表格选择矩阵,其中每一行是一个 Unit Vector。而 MLE 多项式 f(X0,X1,…,Xlogm−1) 编码了 f,t(Y0,Y1,…,YlogN−1) 编码了 t,而 M~(X0,X1,…,Xlogm−1,Y0,Y1,…,YlogN−1) 编码了 M 矩阵。
Prover 和 Verifier 需要证明每一个 fi 等于某个表项 tj。他们共同拥有的 Public Inputs 为表格向量与查询向量的多项式承诺,因为我们现在只关注 Indexed Lookup Argument,因此他们还共同拥有 M 的多项式承诺。
协议的第一步是 Verifier 发送一个挑战向量 r∈Fm,使得上面的约束转化为:
f(r)=y∈{0,1}logN∑M(r,y)⋅t~(y)
Verifier 可以通过查询 Oracle f 来得到 f(r) 的值,我们记为 v。于是上面的等式就归约到了一个求和式:
v=y∈{0,1}logN∑M(r,y)⋅t(y)
此刻,Prover 和 Verifier 可以调用 Sumcheck 协议来完成求和式的证明。但是 Prover 需要计算 N 个 M(r,y)⋅t(y) 的值。
在 Sumcheck 协议的结尾,Prover 和 Verifier 可以利用多项式承诺的求值证明,证明 M(r,Y) 和 t(Y) 在 Y=ρ 处的求值。尽管我们可以使用 Spark 稀疏多项式承诺来降低最后的求值证明的开销,但是 Prover 在 Sumcheck 协议过程中的计算量至少是 O(m⋅N)。
下一节我们介绍 Generalized Lasso 如何再次利用 M 矩阵的稀疏性,减少 Prover 在 Sumcheck 协议中的计算量。在此之前,我们先列出 Generalized Lasso 的协议框架:
公共输入:
- 表格向量 t 的承诺:Ct=PCS.Commit(t)
- 查询向量 f 的承诺:Cf=PCS.Commit(f)
- 表格选择矩阵 M 的承诺:CMspark=Spark.Commit(M)
第一轮:Verifier 发送挑战向量 r∈Flogm
第二轮:Prover 计算 f~(r) 的值,并且连同求值证明 πf 一起发送给 Verifier
第三轮:Prover 和 Verifier 进行 Sparse-dense Sumcheck 协议,证明下面的等式:
v=y∈{0,1}logN∑M(r,y)⋅t(y)
经过 Sumcheck 协议,上面的约束等式被归约到:
v′=M(r,ρ)⋅t(ρ)
第四轮:Prover 发送 vM,vt 与 求值证明 πM,πt 给 Verifier
- vM=M~(r,ρ)
- vt=t~(ρ)
第五轮:Verifier 验证下面的等式:
- v′=?vM⋅vt
- PCS.Verify(Ct,vt,πt)=?1
- PCS.Verify(Cf,v,πf)=?1
- Spark.Verify(CMspark,vM,πM)=?1
这一节,我们分析下 Prover 在 Sumcheck 协议中的开销,以及如何利用 M 的稀疏性质来减少 Prover 的计算量。
再重复下 Sumcheck 要证明的求和等式:
v=b∈{0,1}logN∑u(b)⋅t(b)
这里我们用 u(b) 代替 M(r,b),它是一个稀疏的多项式,只有 m 个非零项。而 t~(b) 是一个 MLE-structured 的多项式,它的计算复杂度为 O(logN)。
Sumcheck 协议总共 logN 轮,在每一轮,Prover 主要的计算量为计算一个一元多项式并发送给 Verifier:
h(j)(X)=(bj+1,bj+2,…,blogN)∈{0,1}logN−j−1∑u(r0,r1,…,rj−1,X,bj+1,bj+2,…,blogN−1)⋅t(r0,r1,…,rj−1,X,bj+1,bj+2,…,blogN−1)
注意到这个一元多项式 h(j)(X) 是 O(N) 个项的求和,但是 u(b) 是一个稀疏的 MLE 多项式。如果 u(X) 在 X=y 处的取值为零,那么 Prover 也就可以省去计算 t~(y) 的开销。因此,Prover 实际上只需要计算 O(m) 个项的求和,而不是 O(N) 个项。
进一步展开 u~(b) 的定义,我们可以得到:
u(b0,b1,…,blogN−1)=i∈Su∑ui⋅eqi(b0,b1,…,blogN−1)
其中 Su 定义为 u 中非零项的索引集合。因此 h(j)(X) 求和式可以进一步简化为 m 项的求和:
h(j)(X)=(bj+1,bj+2,…,blogN)∈{0,1}logN−j−1∑u(r0,r1,…,rj−1,X,bj+1,bj+2,…,blogN−1)⋅t(r0,r1,…,rj−1,X,bj+1,bj+2,…,blogN−1)=i∈Su∑ui⋅(bj+1,bj+2,…,blogN)∈{0,1}logN−j−1∑eqi(r0,r1,…,rj−1,X,bj+1,bj+2,…,blogN−1)⋅t(r0,r1,…,rj−1,X,bj+1,bj+2,…,blogN−1)=i∈Su∑ui⋅eqi(r0,r1,…,rj−1,X,ij+1,ij+2,…,ilogN−1)⋅t(r0,r1,…,rj−1,X,ij+1,ij+2,…,ilogN−1)
每一轮,假设当前我们在第 j 轮,Prover 要计算 m 个项的求和,每一项包含两个乘法和两个 MLE 多项式的求值,分别为 eqi 和 t 。接着 Verifier 都会提供一个随机数 rj 来求值 h(j)(X),然后 Sumcheck 进入下一轮,即第 j+1 轮。
在第 j 轮, Prover 的策略是根据上一轮(第 j−1 轮)的 eqi(…,rj−1,ij,…) 和 t(…,rj−1,ij,…) 的求值来增量式的递推计算 eqi(…,rj−1,rj,…) 和 t(…,rj−1,rj,…),即用 rj 来代替 ij。
然后我们观察下 eq~i(r0,r1,…,rj−1,X,ij+1,ij+2,…,ilogN−1) 的定义,
eq~i(r0,r1,…,rj−1,X,ij+1,ij+2,…,ilogN−1)=(k=0∏j−1(1−ik)⋅(1−rk)+ik⋅rk)⋅((1−X)⋅(1−ij)+X⋅ij)⋅(k=j+1∏logN−1(1−ik)(1−ik)+ik⋅ik)
注意到等式右边的三个乘积因子中的最右边一个恒等于 1。如果 X=ij,
eq~i(r0,r1,…,rj−1,ij,ij+1,ij+2,…,ilogN−1)=k=0∏j−1(1−ik)⋅(1−rk)+ik⋅rk
那么当我们用 rj 来代替 ij 时,
eqi(r0,r1,…,rj−1,rj,ij+1,ij+2,…,ilogN−1)=(k=0∏j−1(1−ik)⋅(1−rk)+ik⋅rk)⋅((1−rj)⋅(1−ij)+rj⋅ij)=eqi(r0,r1,…,rj−1,ij,ij+1,ij+2,…,ilogN−1)⋅((1−rj)⋅(1−ij)+rj⋅ij)
因此,根据 ij 是 0 还是 1,Prover 可以仅用一个乘法即可递推地计算出第 j+1 轮所需要的 eqi。又因为总共有 m 个 eqi 需要计算,所以 Prover 要付出 O(m) 的计算量。
Prover 可以维护一个长度为 m 的数组,里面保存 eq~i 的值,每一轮过后就更新这个数组:
eqi(r0,r1,…,rj−1,rj,ij+1,ij+2,…,ilogN−1)={eqi(r0,r1,…,rj−1,ij,ij+1,ij+2,…,ilogN−1)⋅(1−rj)eq~i(r0,r1,…,rj−1,ij,ij+1,ij+2,…,ilogN−1)⋅rjif ij=0if ij=1
但是对于 t(r0,r1,…,rj−1,X,ij+1,ij+2,…,ilogN−1) 这个求值运算,如果 t 没有内部结构,那么 Prover 需要老老实实进行求值运算。这样每一轮中 Prover 仍然需要执行 m 次 MLE 运算求值过程。在 logN 轮的 Sumcheck 协议过程中,Prover 总共的计算量至少为
O(m⋅logN⋅evaltime(t~))
如果 t 恰好具有 MLE-Structured 性质,那么 evaltime(t~) 为 O(logN),那么 Prover 的计算量为 O(m⋅log2N)。
进一步,如果 t 具有「局部 bit 相关」的特性,即我们可以采用计算 eqi 的方法给出 t 的递推计算式:
t(r0,…,rj−1,X,bj+1,…,blogN−1)=m(X,j,bj)⋅t(r0,…,rj−1,bj,bj+1,…,blogN−1)+a(X,j,bj)
这里 ml(X,j,bj) 和 al(X,j,bj) 是两个多项式,他们的计算复杂度为 O(1)。如果 t 的递推计算能满足上面的等式,那么 Prover 就可以同样维护一个长度为 m 的数组,保存 i∈Su 所对应的 t(r0,…,rj−1,rj,ij+1,…,ilogN−1) 的值。这样 Prover
可以在每一轮中只需要总共 O(m) 的计算量来计算更新所有需要用到的 t~ 的值。
这样一来, Prover 的计算量可以进一步降低为 O(m⋅logN)。
下面举一个简单例子,来演示下整个过程。假设 N=8,一个稀疏的向量 u=(0,u1,u2,0,u4,0,0,0) ,表格向量 t=(t0,t1,t2,t3,t4,t5,t6,t7)。稀疏向量的非零值数量为 m=3,Su=(1,2,4)。
Sumcheck 协议要证明的求和式为:
v=b∈{0,1}3∑u(b)⋅t(b)=u1⋅t1+u2⋅t2+u4⋅t4
Prover 预计算 E(0)(i)=eqi(i0,…,ilogN−1) 的值为 1, T(0)(i)=t(i0,…,ilogN−1)=ti
在第 0 轮中,Prover 计算 h(1)(X):
h(1)(X)=b2,b3∈{0,1}∑u(X,b2,b3)⋅t(X,b2,b3)=u1⋅E(0)(1)⋅t(X,0,1)⋅(1−X) +u2⋅E(0)(2)⋅t(X,1,0)⋅(1−X) +u4⋅E(0)(4)⋅t(X,0,0)⋅X=u1⋅E(0)(1)⋅(m(X,j=0,b0=0)⋅t(b0=0,b1=0,b2=1)+a(X,j=0,b0=0))⋅(1−X) +u2⋅E(0)(2)⋅(m(X,j=0,b0=0)⋅t(b0=0,b1=1,b2=0)+a(X,j=0,b0=0))⋅(1−X) +u4⋅E(0)(4)⋅(m(X,j=0,b0=1)⋅t(b0=1,b1=0,b2=0)+a(X,j=0,b0=1))⋅X=u1⋅E(0)(1)⋅(m(X,j=0,b0=0)⋅T(0)(1)+a(X,j=0,b0=0))⋅(1−X) +u2⋅E(0)(2)⋅(m(X,j=0,b0=0)⋅T(0)(2)+a(X,j=0,b0=0))⋅(1−X) +u4⋅E(0)(4)⋅(m(X,j=0,b0=1)⋅T(0)(4)+a(X,j=0,b0=1))⋅X
可以看出,Prover 只需要计算 m(X,0,0),m(X,0,1) ,a(X,0,0),a(X,0,1) 这四个多项式的值。而这四个多项式的计算量为 O(1)。Prover 发送 (h(1)(0)),h(1)(1),h(1)(2))
作为 h(1)(X) 的点值形式发送。
Verifier 发送挑战数 r0,Prover 和 Verifier 检查
v=?h(1)(0)+h(1)(1)
然后共同计算 h(1)(r0) 作为新的求和。
Prover 更新 E(i) 与 T(i) 到 E(1) 与 T(1),
E(1)(1)E(1)(2)E(1)(4)=E(0)(1)⋅(1−r0)=(1−r0)=E(0)(2)⋅(1−r0)=(1−r0)=E(0)(4)⋅r0=r0
T(1)(1)T(1)(2)T(1)(4)=m(r0,0,0)⋅T(0)(1)+a(r0,0,0)=m(r0,0,0)⋅T(0)(2)+a(r0,0,0)=m(r0,0,1)⋅T(0)(4)+a(r0,0,1)
下面是第二轮,Prover 计算 h(2)(X):
h(2)(X)=b3∈{0,1}∑u(r0,X,b3)⋅t(r0,X,b3)=u1⋅E(1)(1)⋅t(r0,X,1)⋅(1−X)+u2⋅E(1)(2)⋅t(r0,X,0)⋅X+u4⋅E(1)(4)⋅t(r0,X,0)⋅(1−X)=u1⋅E(1)(1)⋅(m(X,j=1,b1=0)⋅t(r0,b1=0,b2=1)+a(X,j=1,b1=0))⋅(1−X)+u2⋅E(1)(2)⋅(m(X,j=1,b1=1)⋅t(r0,b1=1,b2=0)+a(X,j=1,b1=1))⋅X+u4⋅E(1)(4)⋅(m(X,j=1,b1=0)⋅t(r0,b1=0,b2=0)+a(X,j=1,b1=0))⋅(1−X)=u1⋅E(1)(1)⋅(m(X,j=1,b0=0)⋅T(1)(1)+a(X,j=1,b1=0))⋅(1−X)+u2⋅E(1)(2)⋅(m(X,j=1,b0=1)⋅T(1)(2)+a(X,j=1,b1=1))⋅X+u4⋅E(1)(4)⋅(m(X,j=1,b0=0)⋅T(1)(4)+a(X,j=1,b1=0))⋅(1−X)
Prover 只需要计算 m(X,1,0),m(X,1,1) ,a(X,1,0),a(X,1,1) 这四个多项式的值。而这四个多项式的计算量为 O(1)。Prover 发送 (h(2)(0)),h(2)(1),h(2)(2))
作为 h(2)(X) 的点值形式发送。
Verifier 发送挑战数 r1,Prover 和 Verifier 检查
h(1)(r1)=?h(2)(0)+h(2)(1)
Prover 维护 E 与 T 数组,更新到 E(2) 与 T(2),
E(2)(1)E(2)(2)E(2)(4)=E(1)(1)⋅(1−r1)=E(1)(2)⋅r1=E(1)(4)⋅(1−r1)=(1−r0)⋅(1−r1)=(1−r0)⋅r1=r0⋅(1−r1)
T(2)(1)T(2)(2)T(2)(4)=m(r1,1,0)⋅T(1)(1)+a(r1,1,0)=m(r1,1,1)⋅T(1)(2)+a(r1,1,1)=m(r1,1,0)⋅T(1)(4)+a(r1,1,0)
到了第三轮,Prover 计算 h(3)(X):
h(3)(X)=u(r0,r1,X)⋅t(r0,r1,X)=u1⋅E(2)(1)⋅t(r0,r1,X)⋅X+u2⋅E(2)(2)⋅t(r0,r1,X)⋅(1−X)+u4⋅E(2)(4)⋅t~(r0,r1,X)⋅(1−X)
如果 t~ 有内部结构,那么
h(3)(X)=u1⋅E(2)(1)⋅(m(X,j=2,b2=1)⋅t(r0,r1,b2=1)+a(X,j=2,b2=1))⋅(1−X)+u2⋅E(2)(2)⋅(m(X,j=2,b2=0)⋅t(r0,r1,b2=0)+a(X,j=2,b2=0))⋅X+u4⋅E(2)(4)⋅(m(X,j=2,b2=0)⋅t~(r0,r1,b2=0)+a(X,j=2,b2=0))⋅(1−X)=u1⋅E(2)(1)⋅(m(X,j=2,b2=1)⋅T(2)(1)+a(X,j=2,b2=1))⋅(1−X)+u2⋅E(2)(2)⋅(m(X,j=2,b2=0)⋅T(2)(2)+a(X,j=2,b2=0))⋅X+u4⋅E(2)(4)⋅(m(X,j=2,b2=0)⋅T(2)(4)+a(X,j=2,b2=0))⋅(1−X)
Prover 发送 (h(3)(0)),h(2)(1),h(3)(2))
作为 h(3)(X) 的点值形式发送。
Verifier 发送挑战数 r2,Prover 和 Verifier 检查
h(2)(r2)=?h(3)(0)+h(3)(1)
Prover 和 Verifier 最后通过 PCS 来验证下面的 Evaluation 等式:
h(3)(r3)=?u(r0,r1,r2)⋅t(r0,r1,r2)
Prover 更新 E 到 E(3),则得到 vu=u~(r0,r1,r2):
E(3)(1)E(3)(2)E(3)(4)=E(2)(1)⋅r2=E(2)(2)⋅(1−r2)=E(2)(4)⋅(1−r2)=(1−r0)⋅(1−r1)⋅r2=(1−r0)⋅r1⋅(1−r2)=r0⋅(1−r1)⋅(1−r2)
Prover 可以通过 E(3) 来计算得到 vu=u~(r0,r1,r2),计算时间复杂度为 O(m):
u~(r0,r1,r2)=u1⋅E(3)(1)+u2⋅E(3)(2)+u4⋅E(3)(4)
Prover 并不需要发送 t~(r0,r1,r2),因为这个值可以由 Verifier 直接计算得到,计算时间复杂度为 O(m)。
综上,Prover 的计算量为 O(m⋅logN)。
标准的 Sparse-dense Sumcheck 可以把 logN 轮的 Sumcheck 过程拆分成 c=logmlogN 个分段,在每个分段中,Prover 都预计算一些辅助的向量,从而避免在接下来的 Sumcheck 分段中做一些重复的计算。这个分段加预计算的步骤被称为 Condensation。通过这种方法,Prover 的计算量可以从 O(m⋅logN) 降到 O(c⋅m),其中 c=logmlogN,即 N=mc。
我们先描述一个 Sparse-dense Sumcheck 简单情况。假设查询表格 t 中的每一个表项 ti 都可以用它的 index 的二进制位来计算,例如 ti 的值可以通过下面的方式计算:
t(i0,i1,…,is−1)=d0i0+d1i1+⋯+ds−1is−1
其中 i=i0+i1⋅2+⋯+is−1⋅2s−1 为 ti 的表格索引。 那么如果给定 t(i0,…,ik,…,is−1) 的值,我们可以在常数时间内计算 t(i0,…,c,…,is−1) 的值。
t(i0,…,c,…,is−1)=t(i0,…,ik,…,is−1)+dk⋅(c−ik)
上面这个等式想要表达的含义是:表格的每一项可以表达为该表项的索引(Index)的线性组合,并且是关于 Index 的二进制位的一次多项式。例如 RangeCheck 表格就满足这个特征。
回忆 Generalized Lasso 协议,其核心是证明下面的等式:
f(X)=y∈{0,1}logN∑M(X,y)⋅t~(y)
通过 Verifier 提供的一个随机挑战数,上面的等式可以转化为:
f(r)=y∈{0,1}logN∑M(r,y)⋅t~(y)
令 u=M~(r,y),那么等式转换为一个 Inner Product 的形式:
f(r)=b∈{0,1}logN∑u(b)⋅t~(b)
等式右边是一个 N 项的求和式,如果直接让 Prover 去计算每一项中的 u(b) 和 t(b),那么 Prover 的计算量至少为 2N 次 evaluation。但是我们可以利用 u(b) 和 t(b) 的内部结构来进行优化。首先 u(b) 编码了一个长度为 N 的向量,记为 u,它相当于也编码了矩阵 M 的信息,只有 m 个非零值。因此我们只需要 O(m) 就可以计算出所有的 u(X) 在所有 X=b 处的取值。其次 t(b) 编码了 t,它是一个 MLE-structured 的表格,其每一项都与 Index 的二进制位有关,因此每一个表项 ti 都可以在 O(logN) 时间内计算得到。最后,考虑求和式 ∑b∈{0,1}logNu(b)⋅t(b) 中若 u(b)=0,那么我们就不需要再计算 t~(b)。因此,这个求和式整体上也只需要 O(m) 次 evaluation 即可。
这个 N 项的求和过程如果使用 Sumcheck 协议来证明,那么需要 logN 轮。在第 j 轮中,由于我们都可以根据上一轮 t(r0,r1,…,rj−1,bj,…,blogN−1) 来计算 t(r0,r1,…,rj−1,rj,…,blogN−1),因此只需要常数时间的计算量。
我们引入两个辅助的向量 q 与 z,Prover 可以在 Sumcheck 协议运行前就计算好 q 与 z 的值,然后 Prover 可以利用这些预计算的向量,在 Sumcheck 协议的前 logm 轮中(记住,Sumcheck 协议总共有 logN 轮,我们假设 logN>logm)加速计算求和式。这两个向量的每个元素 qk 与 zk,k∈[0,m) 定义如下:
qk=y∈extend(k,logm,logN)∑u(y)⋅t(y)
zk=y∈extend(k,logm,logN)∑u~(y)
这里我们引入了一个新的符号:extend(k,logm,logN),它是一个二进制串的集合
extend(k,logm,logN)={y∈{0,1}logN∣prefix(y)=bits(k)}
然后筛选那些二进制串的前 logm 位与 k 的二进制位相等(我们采用 Big-endian 的表示方式,前面的位为高位),而后面的 logN−logm 位可以任意值。例如,extend(10(2),2,4)={1000(2),1001(2),1010(2),1011(2)}。这个集合中每一个二进制串都是以 10 打头。
那么 q 向量的每一个元素 qi,是筛选出那些高位等于 bits(i) 的二进制串(长度为 logN)y,然后通过 y 为索引,计算 u(y)⋅t(y) 的求和。换句话说,我们通过 q 把前面 N 项求和式 ∑b∈{0,1}logNu(b)⋅t(b) 划分为了 logm 个子集,然后分别对其进行求和。由于 u~ 的 O(m) 稀疏性,q 的计算量也是 O(m)。
再换一个思路去理解,如果我们把 N 项求和式的计算过程描述成一棵深度为 logN 的二叉树,其中树根(第 0 层)为最后的和。而其中每个叶子节点都是 u(b)⋅t(b),这里 b∈{0,1}logN,因此总共有 N 个叶子。那么向量 q 就是这颗二叉树中第 logm−1 层的所有节点。
同样, k 是叶子结点为 u~(b) 的求和二叉树中的第 logm−1 层。
接下来,我们看看 Prover 在 Sumcheck 协议中前 logm 轮的计算过程(总共有 logN 轮),并且看下这两个辅助向量的作用。
在第一轮中,Prover 要构造一个一元多项式 h(1)(X)
h(1)(X)=(b1,b2,…,blogN−1)∈{0,1}logN−1∑u(X,b1,b2,…,blogN−1)⋅t(X,b1,b2,…,blogN−1)
我们把 u~(X,b1,b2,…,blogN−1) 按照定义展开,可以得到:
h(1)(X)=(b1,b2,…,blogN−1)∈{0,1}logN−1∑(i∈Su∑ui⋅eqi(X,b1,b2,…,blogN−1))⋅t(X,b1,b2,…,blogN−1)
这里的 Su 表示 u 中非零元素的索引(的二进制表示)的集合。然后把所有的求和号都展开,我们发现当 bits(i)=(i0,i1,…,ilogN−1)∈Su 时,ui=0,因此,我们只要关注上面求和式中 b=bits(i) 对应的那些非零项(这时候 ui=0):
h(1)(X)=i∈Su∑ui⋅eqi(X,i1,i2,…,ilogN−1)⋅t(X,i1,i2,…,ilogN−1)
上面的等式已经变成了一个 m 项的求和式。接下来我们根据 t 的结构性,展开 t(X,i1,i2,…,ilogN−1),并且根据 eqi(X,i1,i2,…,ilogN−1) 的 Tensor 结构,即 eqi(X,i1,i2,…,ilogN−1)=eqi0(X)⋅eqi(i1,…,ilogN−1)=eqi0(X), 我们可以得到:
h(1)(X)=i∈Su∑ui⋅eqi0(X)⋅(t(i0,i1,i2,…,ilogN−1)+(X−i0)⋅d0)
我们再展开 eq~i0(X)=(1−X)⋅(1−i0)+X⋅i0,可得:
h(1)(X)=i∈Su∑ui⋅((1−X)⋅(1−i0)+X⋅i0)⋅(t(i0,i1,i2,…,ilogN−1)+(X−i0)⋅d0)=i=(i0=0,i2,…,ilogN−1)∈Su∑(1−X)⋅ui⋅t(i0,i1,i2,…,ilogN−1)+(1−X)⋅X⋅d0⋅ui+i=(i0=1,i2,…,ilogN−1)∈Su∑X⋅ui⋅t~(i0,i1,i2,…,ilogN−1)+X⋅(X−1)⋅d0⋅ui
这时候,我们可以代入之前计算的辅助向量 q 与 z,其中第 k 项为
qkzk=q(k0,k1,…,klogm−1)=(j0,j1,…,jlogN−logm−1)∈{0,1}logN−logm∑u(k0,k1,…,klogm−1,j0,j1,…,jlogN−logm−1)⋅t(k0,k1,…,klogm−1,j0,j1,…,jlogN−logm−1)=z(k0,k1,…,klogm−1)=(j0,j1,…,jlogN−logm−1)∈{0,1}logN−logm∑u~(k0,k1,…,klogm−1,j0,j1,…,jlogN−logm−1)
注意到,qk 与 zk 是按照前 logm 位进行划分后的第 k 个子集的求和。我们可以把 h(1)(X) 重新写成 两个 logm 项的求和式:
h(1)(X)=(0,k1,k2,…,klogm−1)∈{0,1}logm∑(1−X)⋅qk+d0⋅(1−X)X⋅zk+(1,k1,k2,…,klogm−1)∈{0,1}logm∑X⋅qk+d0⋅(1−X)X⋅zk
这样 Prover 只需要 O(m) 的计算量就可以完成第一轮的计算,这个计算包括计算 h(1)(X) 在 X=0,1,2 处的求值运算。
那么第二轮开始到第 logm 轮,每一轮 Prover 都只需要 O(m) 的计算量就可以完成计算 h(j)(X) 在 X=0,1,2 处的求值。
但是到了 第 logm+1 轮,情况会发生变化,因为这时候 Prover 要计算 N−m 个项的求和,并且 q 和 z 两个辅助向量已经失效。因此,对于下面新的 logm 个轮次,Prover 需要重新计算 q 与 z,然后按照上面的方案继续。这样相当于把 logN 轮的 Sumcheck 按照 logm 的数量进行划分,每一个 logm 轮次,Prover 都需要重新计算 q 与 z,然后保证 h(j)(X) 的计算始终是 2m 个项的求和式。每次重新计算 q 与 z 的操作被称为 Condensation。
上一小节的讨论基于一个比较强的表格结构:
t(i0,i1,…,is−1)=d0i0+d1i1+⋯+ds−1is−1
对于 AND 表格与 SLT 表格等不满足上面结构要求的表格,我们需要放松表格的结构条件。首先, t 可以是多个多项式之和,并且每一个多项式 tl 的计算过程基于 index 的二进制表示,当 index 发生变化时,t~ 的值的变化只需要常数个加法和乘法操作:
t=l=0∑η−1tl
tl(r0,…,rj−1,X,bj+1,…,blogN−1)=ml(X,j,bj)⋅tl(r0,…,rj−1,bj,bj+1,…,blogN−1)+dl⋅(X−rj)+al(X,j,bj)