初探Succinct Jagged稀疏多项式承诺方案
1. 引言
2025年5月20日,Succinct团队 发布了其论文 Jagged Polynomial Commitments (or: How to Stack Multilinears),以及基于该技术的verifier——https://github.com/succinctlabs/hypercube-verifier/tree/main(Rust),使其能在大约 12 秒内完成对以太坊区块的证明,展示了链上实时证明的可行性。尽管这只代表了平均情况,并且能耗仍然较高,但它是使用 ZK 技术扩展以太坊的一个重大进展。
Jagged Polynomial Commitments (or: How to Stack Multilinears) 论文大量使用了multilinear多线性多项式和 sumcheck 协议,背景参考资料有:
- sumcheck
- GKR
- 以及 Basefold
此外,关于sparse commitments稀疏承诺及其应用的更多背景,可参看:
- Srinath Setty 和 Justin Thaler 2025年论文 Twist and Shout: Faster memory checking arguments via one-hot addressing and increments
- Srinath Setty、Justin Thaler 和 Riad Wahby 2023年论文 Unlocking the lookup singularity with Lasso
如果想了解一次性读取分支程序(read-once branching programs)及其在多线性扩展评估(evaluating multilinear extensions)中的应用,可参看:
- 2018年论文 Delegating Computations with (almost) Minimal Time and Space Overhead。
2. Jagged 函数
典型的算术化方案由若干张表组成(如,一张用于 CPU,一张用于 ALU,另一张用于内存等),并对这些表施加一组代数约束。每张表的每一列都使用单变量或多变量多项式进行编码,之后证明者对这些编码进行承诺(通过多项式承诺方案 PCS)。在所有情况下,都要求每一列的长度为 2 的幂,这使得能够使用快速傅里叶变换(FFT)或多线性拉格朗日基多项式(multilinear Lagrange basis polynomials)进行高效编码。
这种约束带来了若干限制:
- 1)每张表中所有列的长度必须相同;
- 2)需要对列进行填充,使其长度为 2 的幂。
这会带来大量开销,因为必须将所有列填充到相同长度,并在表中存储大量无效(如为零)的占位项。
- 希望使用某种稀疏的数据表示方式,也就是说,只存储所有非占位值。
- 此外,还希望将所有内容压缩成一列,从而只对一个编码进行承诺。
这正是Jagged Polynomial Commitments (or: How to Stack Multilinears)论文的核心贡献之一:
- 找到一种方式,在不使用大量填充的情况下,获得表的稠密表示(需要注意的是,最终的列长度仍需为 2 的幂,可能仍需一定的填充)。
将通过一张表来解释稠密表示(dense representation)背后的思想,但这个思路可以扩展到多张表,只需添加一个额外的变量来记录表的编号以及每张表有多少列。
假设有一张表,共有 32 列( 32 = 2 5 32 = 2^5 32=25)。对于每一列,保留该列的长度 l k l_k lk,即不包含占位项(dummy entries)的真实数据数量。如:
- l 0 = 2 20 l_0 = 2^{20} l0=220
- l 1 = 2 18 + 15 l_1 = 2^{18} + 15 l1=218+15
- l 2 = 2 16 + 1475 l_2 = 2^{16} + 1475 l2=216+1475
- ……等等。
证明者可以构造一个向量 t t t,其每个元素为列长度的累加和。即:
- t 0 = l 0 t_0 = l_0 t0=l0
- t 1 = l 0 + l 1 t_1 = l_0 + l_1 t1=l0+l1
- t 2 = l 0 + l 1 + l 2 t_2 = l_0 + l_1 + l_2 t2=l0+l1+l2
总结起来为:
- t 0 = l 0 t_0 = l_0 t0=l0
- t k + 1 = t k + l k + 1 t_{k+1} = t_k + l_{k+1} tk+1=tk+lk+1
注意,由于所有 l k l_k lk 都是正数,向量 t t t 的元素是非递减的。
可以将所有列按顺序叠加合并成一列。给定合并后的列向量中的某个索引 j j j,可以确定这个元素原本属于哪个列和哪一行:
- 1)首先找出最小的 k k k,使得 j < t k j < t_k j<tk。这个 k k k 就是该元素所在的原始列。
- 2)然后计算行号: i = j − t k − 1 i = j - t_{k-1} i=j−tk−1(如果 k = 0 k = 0 k=0,则 i = j i = j i=j)
这样,在原始表格和合并后的列之间建立了一一对应的关系,将这种表示方式称为稠密表示(dense representation)。
稠密表示的总长度是 2 m 2^m 2m,其中:
m = ⌈ log 2 max ( t ) ⌉ m = \lceil \log_2 \max(t) \rceil m=⌈log2max(t)⌉
由于可以根据索引 j j j 找到对应的列和行,因此可以定义两个函数:
c o l ( j ) = min k { t k > j } \mathrm{col}(j) = \min_k \{ t_k > j \} col(j)=kmin{tk>j}
r o w ( j ) = j − t k − 1 \mathrm{row}(j) = j - t_{k-1} row(j)=j−tk−1
用字母 q q q 表示稠密表示的多线性编码(multilinear encoding),则每个条目对应原始整个表格的多线性扩展(multilinear extension)中的非占位部分 p p p,即:
p ( r o w ( j ) , c o l ( j ) ) = q ( j ) p(\mathrm{row}(j), \mathrm{col}(j)) = q(j) p(row(j),col(j))=q(j)
这种方式节省了大量表示整张表所需的空间,代价是需要证明者发送向量 t t t。
可以进一步证明,如果想要评估 p ( z r , z c ) p(z_r, z_c) p(zr,zc),等价于:
p ( z r , z c ) = ∑ p ( x , y ) ⋅ e q ( x , z r ) ⋅ e q ( y , z c ) = ∑ q ( i ) ⋅ e q ( r o w ( i ) , z r ) ⋅ e q ( c o l ( i ) , z c ) p(z_r, z_c) = \sum p(x, y) \cdot \mathrm{eq}(x, z_r) \cdot \mathrm{eq}(y, z_c) = \sum q(i) \cdot \mathrm{eq}(\mathrm{row}(i), z_r) \cdot \mathrm{eq}(\mathrm{col}(i), z_c) p(zr,zc)=∑p(x,y)⋅eq(x,zr)⋅eq(y,zc)=∑q(i)⋅eq(row(i),zr)⋅eq(col(i),zc)
因为 p ( x , y ) p(x, y) p(x,y) 中的任何零值都不会对总和产生贡献。
3. 为什么 Jagged 函数 对多线性多项式有效?
多变量多项式使用 sumcheck 协议 将 statements 归约为 对多项式在某个随机点的求值。如,可以使用 sumcheck 协议来验证某个多变量多项式 g g g 在 hypercube 超立方体上的求值为零,通过如下的 zero-check 零检验公式:
∑ e q ( r , x ) ⋅ g ( x ) = 0 \sum \mathrm{eq}(r, x) \cdot g(x) = 0 ∑eq(r,x)⋅g(x)=0
在与证明者交互之后,验证者最终只需要对某个点 z z z 进行一次求值计算,即验证:
e q ( r , z ) ⋅ g ( z ) \mathrm{eq}(r, z) \cdot g(z) eq(r,z)⋅g(z)
以及一些与单变量多项式相关的简单检查。
使用多项式承诺方案(PCS),证明者可以向验证者提供对 g g g 的访问权限,并使用 PCS 的evaluation protocol 评估协议对点 z z z 进行求值。
对于单变量多项式,通常通过与定义在某个域 D D D 上的消零多项式(vanishing polynomial) Z D ( x ) Z_D(x) ZD(x) 相除,来验证 g ( x ) g(x) g(x) 是否在 D D D 上为零。如果 D D D 拥有良好的结构(如由 n n n 次单位根组成),那么 Z D ( x ) Z_D(x) ZD(x) 可被高效计算。在这种情况下:
Z D ( x ) = x n − 1 Z_D(x) = x^n - 1 ZD(x)=xn−1
然而,对于稀疏多项式, Z D ( x ) Z_D(x) ZD(x) 的表示可能非常复杂,从而导致难以高效计算。
因此,多线性多项式不需要计算这种商项,并且可以预先在更一般的有限域中工作(相比之下,FFT 需要平滑的域,且通常要求 ∣ F ∣ − 1 = 2 n c |F| - 1 = 2^n c ∣F∣−1=2nc,其中 n n n 至少为 24 24 24)。
4. 如何处理大量列?
Jagged Polynomial Commitments (or: How to Stack Multilinears) 论文提供了两种优化方式以处理大量列的问题:
- 1)Fancy jagged:如果表中所有列的高度(行数)相同,那么可以减少构造向量 t t t 所需传输的信息量。
- 2)承诺列高:证明者可以将每列的高度信息(在表格之前添加)包含在表中,并对其进行承诺。
5. Jagged PCS
Jagged Polynomial Commitments (or: How to Stack Multilinears) 论文的另一个核心内容是:
- 构建适用于稀疏或 jagged 多项式的多项式承诺方案(PCS)。
回顾之前的公式:
p ( z r , z c ) = ∑ p ( x , y ) ⋅ e q ( x , z r ) ⋅ e q ( y , z c ) = ∑ q ( i ) ⋅ e q ( r o w ( i ) , z r ) ⋅ e q ( c o l ( i ) , z c ) p(z_r, z_c) = \sum p(x, y) \cdot \mathrm{eq}(x, z_r) \cdot \mathrm{eq}(y, z_c) = \sum q(i) \cdot \mathrm{eq}(\mathrm{row}(i), z_r) \cdot \mathrm{eq}(\mathrm{col}(i), z_c) p(zr,zc)=∑p(x,y)⋅eq(x,zr)⋅eq(y,zc)=∑q(i)⋅eq(row(i),zr)⋅eq(col(i),zc)
可以将函数 f t f_t ft 的多线性扩展定义为:
f t ( x ) = e q ( r o w ( x ) , z r ) ⋅ e q ( c o l ( x ) , z c ) f_t(x) = \mathrm{eq}(\mathrm{row}(x), z_r) \cdot \mathrm{eq}(\mathrm{col}(x), z_c) ft(x)=eq(row(x),zr)⋅eq(col(x),zc)
使用适用于多线性函数乘积的 sumcheck 协议,只需向验证者证明:
v = q ( α ) ⋅ f t ( α ) v = q(\alpha) \cdot f_t(\alpha) v=q(α)⋅ft(α)
进一步拆分为:
q ( α ) = β 1 , f t ( α ) = β 2 q(\alpha) = \beta_1,\quad f_t(\alpha) = \beta_2 q(α)=β1,ft(α)=β2
关键点在于:验证者可以高效计算 f t f_t ft。这一点在论文中的 Claim 3.2.1 中进行了证明。
为了证明函数 f t f_t ft 可以被高效计算,Jagged Polynomial Commitments (or: How to Stack Multilinears) 论文引入了一个函数 g ( w , x , y , z ) g(w, x, y, z) g(w,x,y,z),该函数满足:
g ( w , x , y , z ) = 1 ⟺ x < z 且 x = w + y g(w, x, y, z) = 1 \iff x < z \quad \text{且} \quad x = w + y g(w,x,y,z)=1⟺x<z且x=w+y
该函数 g g g 可直接与 f t f_t ft 相关联,并且可以通过一个 宽度为 4 的分支程序(branching program) 高效计算:
f t ( z r , z c , i ) = ∑ y e q ( z r , y ) ⋅ g ( z c , y , t y − 1 , t y ) f_t(z_r, z_c, i) = \sum_y \mathrm{eq}(z_r, y) \cdot g(z_c, y, t_{y-1}, t_y) ft(zr,zc,i)=y∑eq(zr,y)⋅g(zc,y,ty−1,ty)
这个证明依赖于多线性扩展的唯一性,因此只需在输入 z r , z c , i z_r, z_c, i zr,zc,i 作为二进制字符串的情形下检查上述等式是否成立。
如果 g ( z r , i , t y − 1 , t y ) = 1 g(z_r, i, t_{y-1}, t_y) = 1 g(zr,i,ty−1,ty)=1,那么:
- i < t y i < t_y i<ty
- i = z r + t y − 1 i = z_r + t_{y-1} i=zr+ty−1
由于 z r ≥ 0 z_r \ge 0 zr≥0,可以推出:
- t y − 1 ≤ i < t y t_{y-1} \le i < t_y ty−1≤i<ty
- z r = i − t y − 1 z_r = i - t_{y-1} zr=i−ty−1
又因为有:
- c o l t ( i ) = z c \mathrm{col}_t(i) = z_c colt(i)=zc
- r o w t ( i ) = z r \mathrm{row}_t(i) = z_r rowt(i)=zr
所以可以推出:
f t ( z r , z c , i ) = 1 f_t(z_r, z_c, i) = 1 ft(zr,zc,i)=1
反过来,如果 f t ( z r , z c , i ) = 1 f_t(z_r, z_c, i) = 1 ft(zr,zc,i)=1,那么变量 w , x , y , z w, x, y, z w,x,y,z 自然满足 g ( w , x , y , z ) = 1 g(w, x, y, z) = 1 g(w,x,y,z)=1 的条件。
从上述分析可知,可以通过进行 2 k 2^k 2k 次 g g g 的求值来计算 f t f_t ft。根据claim 3.2.2,一个宽度为 4 的只读分支程序(read-once branching program)可以高效计算 g g g,方法是:
- 逐位读取 w , x , y , z w, x, y, z w,x,y,z,并按流式方式处理。
判断 g g g 是否非零的两个条件:
- i < t y i < t_y i<ty
- z r = i − t y − 1 z_r = i - t_{y-1} zr=i−ty−1
可以通过一次查看 4 位 并 跟踪两个额外变量来完成检查。
接下来,Jagged Polynomial Commitments (or: How to Stack Multilinears) 论文讨论了如何使用只读矩阵分支程序(read-once matrix branching program)来实现符号求值(symbolic evaluation),这是在批量证明多个求值点时所需要的。
这个程序由一系列矩阵 M = M j σ M = M_j^{\sigma} M=Mjσ 构成,其中:
- σ ∈ { 0 , 1 } b \sigma \in \{0,1\}^b σ∈{0,1}b
- j = 1 , 2 , … , n j = 1, 2, \dots, n j=1,2,…,n
- 还有一个sink vector 终结向量 u u u
对于输入 x ∈ { 0 , 1 } n x \in \{0,1\}^n x∈{0,1}n,该程序的输出是如下向量的第一项:
( ∏ j M j x j ) u \left( \prod_j M_j^{x_j} \right) u (j∏Mjxj)u
即:
e 1 T ( ∏ j M j x j ) u e_1^T \left( \prod_j M_j^{x_j} \right) u e1T(j∏Mjxj)u
其中 e 1 j = δ 1 j e_1^j = \delta_{1j} e1j=δ1j——当且仅当 j = 1 j=1 j=1 时,其值为1,其它情况均为0值。
如果矩阵是布尔矩阵(即每个元素都是 0 或 1),那么矩阵乘法仅涉及加法操作。Jagged Polynomial Commitments (or: How to Stack Multilinears) 论文称这样的矩阵是乘法友好型(multiplication friendly),因为它们的乘法只涉及线性数量的加法、不需要乘法。
当终结向量 u u u 尚未给出时,可以以符号形式完成计算;当最终给出 u u u 时,即可获得整个矩阵分支程序的最终值。
关键思想是,可以得到一个向量 res \text{res} res,使得:
res ⋅ u = f M , u ( z ) \text{res} \cdot u = f_{M,u}(z) res⋅u=fM,u(z)
其中:
- f f f 是由矩阵 M M M 和向量 u u u 所定义的矩阵分支程序的多线性扩展。
- 向量 res 的表达式为:
res = e 1 t ∏ j ( ∑ σ eq ( z j , σ ) M j σ ) \text{res} = e_1^t \prod_j \left( \sum_{\sigma} \text{eq}(z_j, \sigma) M_j^\sigma \right) res=e1tj∏(σ∑eq(zj,σ)Mjσ)
6. 多点求值的批量证明(Batch-proving of multiple evaluations)
在此面临的问题是:
- 验证者需要计算 k k k 个不同点上的多项式取值,这可能非常昂贵。
然而,通过与证明者的交互,可以将所有这些求值归约为一次求值。这是一种标准技巧,方法是:
- 验证者选取一组随机权重 α 0 , α 1 , … , α k − 1 \alpha_0, \alpha_1, \ldots, \alpha_{k-1} α0,α1,…,αk−1,然后证明者执行一次随机线性组合。
具体来说,假设希望证明:
h ( z 0 ) = v 0 h ( z 1 ) = v 1 ⋮ h ( z k − 1 ) = v k − 1 \begin{aligned} h(z_0) &= v_0 \\ h(z_1) &= v_1 \\ &\vdots \\ h(z_{k-1}) &= v_{k-1} \end{aligned} h(z0)h(z1)h(zk−1)=v0=v1⋮=vk−1
证明者将上述求值按权重 α j \alpha_j αj 做线性组合:
∑ j α j h ( z j ) = ∑ j α j v j \sum_j \alpha_j h(z_j) = \sum_j \alpha_j v_j j∑αjh(zj)=j∑αjvj
证明者的目标是说服验证者每个 h ( z j ) = v j h(z_j) = v_j h(zj)=vj 成立,因此将所有 v j v_j vj 发送给验证者,而验证者可以自行计算右边的线性组合 ∑ α j v j \sum \alpha_j v_j ∑αjvj。
对于左边,证明者可以高效计算。注意:
h ( z j ) = ∑ h ( b ) e q ( b , z j ) = ∑ h k e q ( b , z j ) h( z_j ) = \sum h (b) \mathrm{eq} (b , z_j) = \sum h_k \mathrm{eq} (b , z_j) h(zj)=∑h(b)eq(b,zj)=∑hkeq(b,zj)
其中 k = ∑ j b j 2 j k = \sum_j b_j 2^j k=∑jbj2j, b = b 0 b 1 b 2 . . . b k − 1 b = b_0 b_1 b_2 ... b_{ k - 1} b=b0b1b2...bk−1。
也就是说,可以将 h ( z j ) h(z_j) h(zj) 看作是向量 h h h (其中 h k = h ( b ) h_k = h(b) hk=h(b)) 与 Lagrange basis polynomials拉格朗日基多项式向量 eq ( b , z j ) \text{eq}(b, z_j) eq(b,zj) 的内积。
由于内积是(bi)linear 线性运算,可以将整体线性组合写为:
∑ α j h ( z j ) = ∑ h ( b ) ( ∑ α j e q ( b , z j ) ) \sum \alpha_j h( z_j ) = \sum h(b) \left(\sum \alpha_j \mathrm{eq} (b , z_j) \right) ∑αjh(zj)=∑h(b)(∑αjeq(b,zj))
于是,证明者和验证者可以在函数:
h ( b ) ⋅ ∑ α j ⋅ eq ( b , z j ) h(b) \cdot \sum \alpha_j \cdot \text{eq}(b, z_j) h(b)⋅∑αj⋅eq(b,zj)
上执行 sumcheck 协议,最终,验证者只需在随机点 ρ \rho ρ 上计算一次:
h ( ρ ) ⋅ ∑ α j ⋅ eq ( ρ , z j ) h(\rho) \cdot \sum \alpha_j \cdot \text{eq}(\rho, z_j) h(ρ)⋅∑αj⋅eq(ρ,zj)
这在实践中意味着:
- 对 h h h 进行一次 oracle 查询,并计算一次线性组合 ∑ α j ⋅ eq ( ρ , z j ) \sum \alpha_j \cdot \text{eq}(\rho, z_j) ∑αj⋅eq(ρ,zj)。
一些与 sumcheck 协议相关的优化可以参考:
- 2024年Polygon团队论文 Some Improvements for the PIOP for ZeroCheck。
7. 所有这些技术的意义与未来工作方向
“Jagged(不规则)表示法”使得能够仅对表格中非零部分进行承诺(commit),从而在内存消耗和承诺时间上节省大量资源。
如果将这一思想与 M3(Multi-Multiset Matching) 代数化方案 结合使用——在该方案中,不需要为可以通过 trace 多项式某些操作计算得到的虚拟多项式(virtual polynomials)进行承诺——那么将能极大地减少工作量。
这将进一步降低:
- 证明时间
- 证明成本
- 内存开销
最终目标是:支持更大的以太坊(Ethereum)和 Layer 2 区块证明,从而提升可扩展性,吸引更多用户并激发更多用例。
参考资料
[1] LambdaClass团队 2025年6月6日博客 Our Succinct explanation of jagged polynomial commitments