跳转至

IPA 多项式承诺与 R1CS:原理、关系及代码实验

在zk-SNARK 原理详解里,我们把"计算正确性"翻译成多项式的整除关系;在KZG 多项式承诺里,讲了第一种经典承诺构造——它借助双线性配对与必须安全销毁的秘密陷门 \(\tau\)。本篇把镜头转向两条互补的内容:

  • IPA 多项式承诺:基于内积论证(inner-product argument)做承诺,不需要 KZG 式的信任陷门,代价是证明大小随规模呈对数增长;
  • R1CS:把一段实际程序编译成可验证的代数约束,再进一步变成 QAP 的多项式整除关系——它处在比承诺更上游的"计算表达层"。

KZG 的构造、可信设置风险与多方仪式已在《KZG 多项式承诺》一文中完整展开,下文只在对比时简记其结论,不再重复推导。

本文区分理论性质、具体实现的实测趋势与尚未验证的研究设想;代码实验基于 arkworks 的 IPA-PC 与 Marlin-KZG10,在系数数量 16–1024 范围内完成。

摘要

多项式承诺使证明者先对多项式作出承诺,再以较短证明说明其在指定点的取值,而无须发送完整多项式。KZG 采用双线性配对,单点打开证明为常数大小,但依赖结构化参考字符串(SRS)及其生成过程的安全性。**基于内积论证的多项式承诺(下文简称 IPA 承诺)**走另一条技术路线:把多项式求值表示为向量内积,通过递归折叠压缩证明,不需要 KZG 式的秘密陷门;代价是在证明大小、验证计算与公开参数管理上有不同取舍。另一方面,R1CS 并不是第三种承诺方案,而是把一般计算表示为代数约束的方法,某些证明系统进一步将约束转化为多项式关系,再借助包括 KZG 或 IPA 在内的承诺方案进行检查。

关键词: 零知识证明;多项式承诺;KZG;IPA;可信设置;R1CS;性能评估。

阅读提示:先抓住三个问题

读完第三节,应能回答"KZG 为什么需要秘密参数,泄露后究竟能伪造什么?"(简记,详见 KZG 专文);读完第四节,应能回答"IPA 为什么不需要那种秘密参数,却会付出另一类开销?";读完第五节,应能回答"现实中的一次计算怎样变成可以证明的等式?"。第六节汇总已完成的代码实验:测什么、怎样测、得到什么,以及不能据此声称什么。

文中反复使用的记号:

记号 含义 直观理解
\(\mathbb F_p\) 模素数 \(p\) 运算的有限域 公式实际运行的"数字世界"
\(f(X),d\) 多项式及其最高次数 要承诺的对象及其规模
\(z,y\) 查询点和声称的值,\(y=f(z)\) "在 \(z\) 处,答案是 \(y\)"
\(C,\pi\) 承诺和打开证明 先锁定对象,后提供可验证的说明
\(\tau\) KZG 设置时使用的秘密参数 验证者不能获知的隐藏求值点
\(n\) IPA 中向量的长度 通常与多项式系数数量有关,可能需要补齐

一、研究背景与整体问题

在证明计算正确性时,证明者与验证者掌握的信息不同。例如证明者知道秘密输入 \(x\),声称公开输出 \(y\) 满足某个程序 \(y=F(x)\)。理想情况下,验证者希望确认计算正确,却不需要获得所有秘密数据,也不愿重新执行一个庞大的计算。

这项工作可拆成两个不同问题。第一,如何表达要证明的计算? R1CS 等约束系统把程序编译为有限域上的代数等式。第二,如何让验证者高效检查由这些等式产生的多项式关系? 多项式承诺是可供某些证明系统选用的工具,KZG 和 IPA 承诺则是其不同构造。因此三者的关系不是"KZG、IPA、R1CS 三种同类算法的比较",而是"计算表达层与多项式承诺层的衔接"。

1
2
3
4
5
6
7
待证明的计算 F(x)=y
        ↓ 电路设计、变量与约束
算术电路 / R1CS
        ↓ 具体证明系统的代数化,例如 QAP 或多项式 IOP
多项式关系及取值检查
        ↓ 在采用 PCS 的方案中选择承诺构造
KZG 或 IPA 承诺、打开与验证

图中箭头表示一种常见的研究路线,不代表所有 zk-SNARK 都经过同一协议流程。例如 Groth16 的 QAP 与配对证明并不能简单等同于"R1CS 加一个独立 KZG";Marlin 等方案则明确讨论 R1CS 上的代数化协议与多项式承诺的组合。

二、多项式承诺解决什么问题

2.1 读公式前先认识的数学对象

本文的运算在有限域 \(\mathbb F_p\) 中进行,可理解为"所有运算都按模 \(p\) 计算"。例如在 \(\mathbb F_{101}\) 中,\(104=3\);非零元素 \(4\) 的乘法逆元是 \(76\),因为 \(4\times76=304\equiv1\pmod{101}\)。IPA 折叠里的 \(u^{-1}\) 就是这种有限域乘法逆元,不是普通实数除法。

椭圆曲线群可暂时看成一套公开的、可计算的点加法规则。给定生成元 \(G\) 和标量 \(a\),\([a]=aG\) 表示把 \(a\) 编码成一个群元素;通常很难仅从 \(G\) 和 \([a]\) 反推 \(a\)。配对 \(e\) 满足双线性 \(e(aG_1,bG_2)=e(G_1,G_2)^{ab}\),让验证者能检查群元素隐藏的乘法关系。读者不需先掌握椭圆曲线构造,但应记住:KZG 用配对检查乘法关系,IPA 用群元素加法关系逐轮折叠。

还需区分三个承诺性质:完备性是诚实证明正确命题会通过;绑定性是同一承诺难以被打开成两个互相矛盾的答案;隐藏性是承诺本身不泄漏被承诺的内容。不同方案及其变体提供的性质不同,不能看到"承诺"就默认三者都具备。

2.2 承诺方案的四个算法

设 \(f(X)=a_0+a_1X+\cdots+a_dX^d\) 是 \(\mathbb F_p\) 上的多项式。证明者希望先发布承诺 \(C\),以后回答验证者指定的点 \(z\),给出取值 \(y=f(z)\) 和证明 \(\pi\)。验证者根据 \((C,z,y,\pi)\) 判断取值是否与承诺一致。

算法 输入与作用 输出
Setup 确定曲线、最高支持次数等系统参数 公共参数;某些方案的生成过程还涉及秘密陷门
Commit 接收 \(f\),生成对它的承诺 \(C\)
Open 接收 \(f,z\),证明 \(f(z)=y\) \(y,\pi\)
Verify 接收公共参数与 \(C,z,y,\pi\) 接受或拒绝

方案至少需保证:诚实生成的正确取值可被接受;攻击者难以把同一承诺在同一点打开为两个不同的值(绑定性)。是否隐藏多项式系数、能否高效批量打开、参数能否更新,则依具体构造而定。承诺或打开证明短,并不自动意味着零知识;隐藏性需要额外条件或盲化设计。

三、KZG 承诺:路线一(简记)

KZG 把取值证明转化为商多项式整除关系,借助秘密点 \(\tau\) 的 SRS 与双线性配对验证:

\[ e(C-[y]_1,[1]_2)\stackrel{?}{=}e(\pi,[\tau-z]_2),\qquad [\tau-z]_2=[\tau]_2-z[1]_2. \]

核心取舍:紧凑的单点证明与(主要配对次数)常数级验证,代价是必须安全管理结构化参数(SRS)的生成陷门——若 \(\tau\) 泄露,攻击者可构造同一承诺、同一查询点的互相矛盾打开,破坏绑定性(详见《KZG 多项式承诺》)。可共享、可更新的 SRS 减轻对单方的信任,却不免除部署与审计成本。后文与 IPA 的对比都建立在这一取舍之上。

四、IPA 承诺:不使用 KZG 式陷门的另一条路线

4.1 为什么多项式求值可以写成内积

把多项式系数写成向量 \(\mathbf a=(a_0,a_1,\ldots,a_{n-1})\),不足 \(n\) 项的高位补零;再写出点 \(z\) 的幂向量 \(\mathbf b(z)=(1,z,z^2,\ldots,z^{n-1})\)。于是

\[ f(z)=\sum_{i=0}^{n-1}a_i z^i=\langle\mathbf a,\mathbf b(z)\rangle. \]

例如 \(f(X)=1+2X+3X^2+4X^3\),在 \(z=2\) 时,系数向量是 \((1,2,3,4)\),幂向量是 \((1,2,4,8)\)。所谓"内积"就是逐项相乘再相加:

\[ f(2)=1\cdot1+2\cdot2+3\cdot4+4\cdot8=49. \]

因此 IPA 并没有换一道题目;它只是把"多项式在某点的值是多少"改写成"两个向量的内积是多少"。

"证明 \(f(z)=y\)"因而可转化为"证明被承诺的 \(\mathbf a\) 与公开的 \(\mathbf b(z)\) 的内积是 \(y\)"。一种概念性的向量承诺写法是

\[ C=\sum_{i=0}^{n-1}a_iG_i+rH, \]

其中 \(G_i,H\) 是公开生成元,\(r\) 是否使用取决于方案的隐藏性设计。这只是原理示意,不能替代具体 IPA 多项式承诺实现中的度数约束、transcript、盲化和批处理细节。

4.2 "折叠"到底折叠了什么

"折叠"指用更短的向量,继续代表原先较长向量的内积关系。它不是把后一半直接扔掉;若只保留前一半就会丢失信息。协议要保留足够的交叉项,让验证者知道短问题是由原问题正确变来的。

先看一次可手算的演示,暂时用普通有理数。原始两个向量为 \(\mathbf a=(2,4)\)、\(\mathbf b=(3,5)\),内积为 \(2\times3+4\times5=26\)。取折叠系数 \(u=2\),把两个数压成一个数:

\[ a'=u\cdot2+u^{-1}\cdot4=2\times2+\tfrac12\times4=6,\qquad b'=u^{-1}\cdot3+u\cdot5=\tfrac12\times3+2\times5=11.5. \]

新内积为 \(6\times11.5=69\),并不是原来的 26。差出的 43 是折叠时额外产生的两项:\(u^2(2\times5)+u^{-2}(4\times3)=4\times10+\tfrac14\times12=43\),于是 \(69=26+43\)。真正的 IPA 论证会让验证者检查这些交叉项是否与先前承诺一致,不能由证明者随意报出 43。这解释了为什么"向量越来越短"仍可能保留可验证的信息。演示中的小数和分数仅用于直观计算;实际协议在有限域中用乘法逆元,不用浮点数。

推广到长度 \(n\) 的向量,先忽略承诺、只观察标量恒等式。将两个向量各分左右两半:\(\mathbf a=(\mathbf a_L,\mathbf a_R)\)、\(\mathbf b=(\mathbf b_L,\mathbf b_R)\)。令挑战 \(u\ne0\),定义

\[ \mathbf a'=u\mathbf a_L+u^{-1}\mathbf a_R,\qquad \mathbf b'=u^{-1}\mathbf b_L+u\mathbf b_R. \]

展开内积得到

\[ \langle\mathbf a',\mathbf b'\rangle :=\langle\mathbf a_L,\mathbf b_L\rangle +\langle\mathbf a_R,\mathbf b_R\rangle +u^2\langle\mathbf a_L,\mathbf b_R\rangle +u^{-2}\langle\mathbf a_R,\mathbf b_L\rangle. \]

前两项正是原始内积,后两项是折叠产生的交叉项。实际 IPA 协议还要通过相应的群元素消息约束这些交叉项,挑战由 transcript 派生,以便验证者检查更新后的承诺与声称内积。每轮向量长度减半,经过约 \(\log_2 n\) 轮到达单元素情形。上式只解释折叠的代数直觉,不是完整的安全协议。

例如长度 8 的向量,折叠后依次是 4、2、1,因此只需 3 轮;一般长度 \(n=2^k\) 时是 \(k=\log_2 n\) 轮。证明通常为每轮保留少量群元素,因此大小大体随轮数增长,而不会像发送完整系数向量那样随 \(n\) 线性增长。但验证者仍可能要处理很多公开生成元;证明短不代表验证计算也只需 3 步。

IPA 承诺不需要 KZG 中必须保密销毁的 \(\tau\),通常称为透明或无需此类可信设置的路线。但它仍需要选择安全曲线、确定公开生成元以及规范挑战生成方式;"无可信设置"并非"不需要任何参数"。生成元还要用透明、带域分离的方式导出,避免某方知道它们之间的离散对数关系;否则承诺的绑定性也可能受影响。

4.3 一轮完整的内积论证:L、R、挑战与最终检查

前一小节只看了标量向量怎样折叠。现在把群元素也放进来,补齐一个典型内积论证(inner-product argument)的核心流程。它是 IPA 多项式承诺所使用的基础组件之一;不同多项式承诺实现可能会增加盲化、度数处理或批量打开步骤,所以本节不是某个仓库全部 API 的逐行描述。

设向量长度 \(n=2^k\)。公开生成元向量为 \(\mathbf G=(G_1,\ldots,G_n)\)、\(\mathbf H=(H_1,\ldots,H_n)\),另有群元素 \(U\)。证明者持有秘密向量 \(\mathbf a\),验证者已知公开向量 \(\mathbf b\) 和声称内积 \(y\)。记

\[ \langle\mathbf a,\mathbf G\rangle=\sum_i a_iG_i,\qquad \langle\mathbf b,\mathbf H\rangle=\sum_i b_iH_i. \]

若承诺为 \(C=\langle\mathbf a,\mathbf G\rangle\),要证明 \(\langle\mathbf a,\mathbf b\rangle=y\),验证者构造本轮初始群元素

\[ P=C+\langle\mathbf b,\mathbf H\rangle+yU. \]

若声称正确,这等价于

\[ P=\langle\mathbf a,\mathbf G\rangle+\langle\mathbf b,\mathbf H\rangle+\langle\mathbf a,\mathbf b\rangle U. \]

右边是待验证的关系:同一个 \(P\) 同时包含两组向量承诺及其内积。

每轮把向量和生成元各自切成左右两半。证明者发送两个群元素:

\[ L=\langle\mathbf a_L,\mathbf G_R\rangle+\langle\mathbf b_R,\mathbf H_L\rangle+\langle\mathbf a_L,\mathbf b_R\rangle U, \]
\[ R=\langle\mathbf a_R,\mathbf G_L\rangle+\langle\mathbf b_L,\mathbf H_R\rangle+\langle\mathbf a_R,\mathbf b_L\rangle U. \]

验证者根据已收到的 transcript(前面所有消息)生成或抽取非零挑战 \(u\)。交互式协议由验证者随机抽取;非交互式实现通常用哈希 transcript 派生。双方用同一个挑战折叠:

\[ \begin{aligned} \mathbf a'&=u\mathbf a_L+u^{-1}\mathbf a_R,& \mathbf b'&=u^{-1}\mathbf b_L+u\mathbf b_R,\\ \mathbf G'&=u^{-1}\mathbf G_L+u\mathbf G_R,& \mathbf H'&=u\mathbf H_L+u^{-1}\mathbf H_R. \end{aligned} \]

验证者同步更新

\[ P'=P+u^2L+u^{-2}R. \]

为什么要加上 \(L\) 和 \(R\)?把折叠后的新关系展开,原来同一半的项仍由 \(P\) 提供,左右交叉项正好由 \(u^2L\) 和 \(u^{-2}R\) 补上,因此有

\[ P'=\langle\mathbf a',\mathbf G'\rangle+\langle\mathbf b',\mathbf H'\rangle+\langle\mathbf a',\mathbf b'\rangle U. \]

此时向量长度减半。重复 \(k=\log_2 n\) 轮后,只剩标量 \(a_*,b_*\) 和生成元 \(G_*,H_*\),验证者检查

\[ P_*=a_*G_*+b_*H_*+a_*b_*U. \]

若等式成立,最后这一步就把整条折叠链收束成一个群等式。安全性直觉是:证明者不能在看到挑战前预先决定左右交叉项的权重;挑战由 transcript 绑定消息,伪造者要同时让每轮更新关系和最终等式成立。

把前面的 4 维例子接到群更新上

在 \(\mathbb F_{101}\) 中取

\[ \mathbf a=(1,2,3,4),\quad \mathbf b=(1,2,4,8),\quad y=\langle\mathbf a,\mathbf b\rangle=49. \]

第一轮挑战 \(u_1=2\),其逆元为 \(51\),折叠后

\[ \mathbf a'=(54,6),\qquad \mathbf b'=(59,17),\qquad \langle\mathbf a',\mathbf b'\rangle=56\pmod{101}. \]

56 不等于原来的 49,并不表示论证失败:这一轮的 \(L\) 含有内积交叉项 \(\langle\mathbf a_L,\mathbf b_R\rangle=20\),\(R\) 含有 \(\langle\mathbf a_R,\mathbf b_L\rangle=11\)。验证者更新 \(P'=P+u_1^2L+u_1^{-2}R\),其中 \(u_1^2=4\)、\(u_1^{-2}=76\)(模 101),所以 \(U\) 方向上的系数同步从

\[ 49\quad\text{更新为}\quad49+4\cdot20+76\cdot11=56\pmod{101}. \]

第二轮为手算方便,取挑战 \(u_2=3\),逆元为 \(34\),得到 \(a_*=63\)、\(b_*=37\),最终内积为 \(63\cdot37=8\pmod{101}\)。这轮的两个交叉内积分别是 \(9\) 和 \(51\),且 \(u_2^2=9\)、\(u_2^{-2}=45\),因此验证者的 \(U\) 方向系数也更新为

\[ 56+9\cdot9+45\cdot51=8\pmod{101}. \]

因此最后检查不是把 8 硬和最初的 49 比较;验证者已通过每轮的 \(L,R\) 将公开等式同步更新为对应折叠后的等式。完整协议中的 \(L,R\) 是群元素,上面列出的 20、11、9、51 是它们乘在 \(U\) 上的内积系数,用来帮助手算理解。这里把挑战固定为 2 和 3 只是为了演示算术;真实协议中的挑战须由验证者随机产生,或由完整 transcript 经安全哈希派生,不能由证明者任意挑选。

4.4 KZG 与 IPA 的主要取舍

可以先记住一个不失准确性的对比:KZG 把"商多项式关系"交给配对检查,换来紧凑证明,但必须处理秘密 SRS;IPA 把"多项式求值"写成向量内积,再反复折叠,不依赖这种秘密陷门,却通常需要更长的证明或更多验证工作。两者解决同一类问题,但让谁付出代价的方式不同。

维度 KZG(典型单点构造) IPA 承诺(典型构造)
核心代数工具 双线性配对;商多项式 内积论证;向量递归折叠
参数信任 结构化 SRS 有必须保密的生成陷门 不需要 KZG 式秘密陷门,但仍有公开生成元
单点证明大小 通常为常数个群元素 通常随向量长度呈对数增长
典型渐进开销 Commit/Open 随次数 \(d\) 线性或由 FFT 优化;单点 Verify 为常数个群/配对操作 Commit/Prove 随长度 \(n\) 线性;证明为 \(O(\log n)\) 个群元素,Verify 常需处理规模随 \(n\) 增长的生成元多重标量乘
验证计算 单点检查的主要配对次数固定,变体另有开销 基础实现可能仍有随向量长度增长的群运算,不能由证明长度直接推出验证时间
参数规模 支持的最大次数越大,SRS 通常越大 公开生成元数量通常与支持的向量长度有关
安全基础 配对群及对应假设、正确处理 SRS 素数阶群中的离散对数类假设、正确生成挑战与参数

表中"通常"指所讨论的典型方案,并非所有变体的统一定理。证明者时间、验证者时间、参数下载量、证明大小和参数信任不能压缩成一个"谁更好"。尤其 \(O(\log n)\) 的证明大小不等于 \(O(\log n)\) 的整体验证时间。最后判断必须结合具体代码版本、曲线、规模和实验边界。

五、R1CS:把计算变成可验证的代数约束

5.1 一个从程序到约束的完整例子

R1CS 的英文为 Rank-1 Constraint System,准确地说是"秩一约束系统"(中文资料中也常写作"一阶约束系统",但 Rank-1 指代数意义上的秩一,并非一阶逻辑)。每条约束均为

\[ (\mathbf a_j\cdot\mathbf w)(\mathbf b_j\cdot\mathbf w)=\mathbf c_j\cdot\mathbf w, \]

其中 \(\mathbf w\) 是由常数 1、输入、中间变量、输出组成的向量;\(\mathbf a_j,\mathbf b_j,\mathbf c_j\) 指定第 \(j\) 条约束两侧的线性组合。所有运算都在指定有限域中完成。

以程序 \(y=x^2+3x+2\) 为例,取秘密输入 \(x=2\),公开输出 \(y=12\)。引入中间变量 \(t=x^2=4\),计算被拆成

\[ x\cdot x=t,\qquad(t+3x+2)\cdot1=y. \]

取见证向量 \(\mathbf w=(1,x,t,y)=(1,2,4,12)\),两条约束对应的系数是:

约束 \(\mathbf a_j\) \(\mathbf b_j\) \(\mathbf c_j\)
\(x\cdot x=t\) \((0,1,0,0)\) \((0,1,0,0)\) \((0,0,1,0)\)
\((t+3x+2)\cdot1=y\) \((2,3,1,0)\) \((1,0,0,0)\) \((0,0,0,1)\)

**怎样读这一行系数?**各位置严格对应 \((1,x,t,y)\)。例如 \((2,3,1,0)\cdot\mathbf w=2\cdot1+3x+1t+0y=t+3x+2\);\((1,0,0,0)\cdot\mathbf w=1\);\((0,0,0,1)\cdot\mathbf w=y\)。这些向量不是新变量,而是"从见证中选哪些数、各乘几倍"的配方。

代入可得 \(2\times2=4\) 和 \((4+3\times2+2)\times1=12\)。令矩阵 \(A,B,C\) 的每一行分别为表中三个系数向量,则全部约束统一为

\[ (A\mathbf w)\circ(B\mathbf w)=C\mathbf w, \]

\(\circ\) 表示对应位置相乘。这里的 \(x,t\) 是证明者要提供的见证;\(y\) 被声明为公开输出时,证明系统还必须把公开输入与约束中的 \(y\) 正确绑定,不能仅凭矩阵等式自动得到隐私或公开性。

在本例中,\(A\mathbf w=(2,12)^{\mathsf T}\)、\(B\mathbf w=(2,1)^{\mathsf T}\)、\(C\mathbf w=(4,12)^{\mathsf T}\)。逐位置相乘就是 \((2\times2,12\times1)=(4,12)\),因此两条约束同时满足。"秩一"指单条约束左侧可写成 \(\mathbf w^{\mathsf T}(\mathbf a_j\mathbf b_j^{\mathsf T})\mathbf w\),其中外积矩阵秩至多为一,不是说整个约束矩阵只有一行。

5.2 从 R1CS 到 QAP 的多项式整除关系

**为什么做完 R1CS 还要引入 QAP?**因为原来有许多条独立约束,验证者不想逐条重算。QAP 的办法是给每条约束一个"检查位置",把所有行装入几条多项式,再一次性表达"每个位置都满足乘法等式"。这一步是经典证明系统中的一种代数化路线,不是 R1CS 定义本身。

经典 QAP(quadratic arithmetic program,二次算术程序)将不同约束映射到不同求值点。对上例,设约束点为 \(r_1=1,r_2=2\)。第 1 条约束的左因子、右因子、结果依次是 \(2,2,4\);第 2 条依次是 \(12,1,12\)。把左因子装进 \(L(X)\),右因子装进 \(R(X)\),结果装进 \(O(X)\),要求它们在两个检查位置分别给出对应的数字:

\[ L(1)=2,\ L(2)=12;\qquad R(1)=2,\ R(2)=1;\qquad O(1)=4,\ O(2)=12. \]

这里的"插值"不神秘:过 \((1,2)\)、\((2,12)\) 两点的一次多项式斜率为 \((12-2)/(2-1)=10\),因此 \(L(X)=10X-8\)。同理,\(R\) 的斜率为 \(-1\),\(O\) 的斜率为 8。在素数 \(p>13\) 的有限域中,以普通整数书写这个演算,得到

\[ L(X)=10X-8,\qquad R(X)=3-X,\qquad O(X)=8X-4. \]

上面先从已知见证算出每一行的数值,再插值得到 \(L,R,O\),有助于手算理解"约束行值如何打包"。标准 QAP 构造更系统:先针对每个变量列,分别把 R1CS 矩阵中的系数插值成多项式,再用见证向量做线性组合。设 \(A_i(X),B_i(X),C_i(X)\) 分别对应变量 \(w_i\) 在矩阵 \(A,B,C\) 中的第 \(i\) 列,则

\[ L(X)=\sum_i w_iA_i(X),\qquad R(X)=\sum_i w_iB_i(X),\qquad O(X)=\sum_i w_iC_i(X). \]

对本例,变量顺序为 \((1,x,t,y)\),约束点为 \(1,2\)。矩阵各列在两行上的值,以及过这两个点的插值多项式为:

变量列 \(A_i(1),A_i(2)\) 与 \(A_i(X)\) \(B_i(1),B_i(2)\) 与 \(B_i(X)\) \(C_i(1),C_i(2)\) 与 \(C_i(X)\)
常数 1 \((0,2)\),\(2X-2\) \((0,1)\),\(X-1\) \((0,0)\),\(0\)
\(x\) \((1,3)\),\(2X-1\) \((1,0)\),\(2-X\) \((0,0)\),\(0\)
\(t\) \((0,1)\),\(X-1\) \((0,0)\),\(0\) \((1,0)\),\(2-X\)
\(y\) \((0,0)\),\(0\) \((0,0)\),\(0\) \((0,1)\),\(X-1\)

再代入见证 \((1,2,4,12)\):

\[ \begin{aligned} L(X)&=(2X-2)+2(2X-1)+4(X-1)=10X-8,\\ R(X)&=(X-1)+2(2-X)=3-X,\\ O(X)&=4(2-X)+12(X-1)=8X-4. \end{aligned} \]

这就解释了前面出现的三个多项式并非证明者任意挑出来的:矩阵列多项式由电路固定,证明者只能按自己的见证系数做线性组合。实际证明系统还需将公开输入、见证承诺和协议随机性绑定起来;上面的手算只是 QAP 的代数转换。

现在逐点检查:当 \(X=1\) 时,\(L(1)R(1)-O(1)=2\times2-4=0\);当 \(X=2\) 时,得到 \(12\times1-12=0\)。于是 \(D(X)=L(X)R(X)-O(X)\) 同时以 1、2 为根。根据因式定理,\(D(X)\) 必须同时含因子 \(X-1\) 和 \(X-2\)。设目标多项式 \(T(X)=(X-1)(X-2)\),便可写成

\[ L(X)R(X)-O(X)=-10(X-1)(X-2)=H(X)T(X),\quad H(X)=-10. \]

所以"两个位置的计算都正确"被打包成"\(L R-O\) 可被 \(T\) 整除"。一般构造先由电路结构对每个变量插值,再按照见证做线性组合;上例直接插值已确定见证下的两行值,仅为让整除关系可手算,不是让证明者随意挑选能够过关的 \(L,R,O\)。也要注意 \(LR-O\) 是在约束点为零,而不是在所有 \(X\) 上都为零。

反过来,如果证明者坚持把公开输出写成 13,但仍使用 \(x=2,t=4\),第 2 条约束就变成 \(12=13\),明显不成立。相应的 \(O(2)\) 会变为 13,于是 \(D(2)=12-13=-1\ne0\);\(D(X)\) 不含因子 \(X-2\),自然不可能被 \(T(X)\) 整除。这说明"整除检查"不是额外的数学装饰,而是把约束是否满足转成了一个统一的可验证条件。

5.3 为什么电路比直接写一个多项式更适合描述程序

普通多项式求值适合表示代数计算,但实际程序还包含条件、比较和范围检查。例如"若 \(x>5\) 则输出 1"中的 > 并不是有限域自带的整数顺序。要对有界整数解释比较,须先约定比特宽度和合法范围,再把数值分解为比特:

\[ x=\sum_{i=0}^{k-1}2^i b_i,\qquad b_i(b_i-1)=0. \]

随后才可用比较电路限制最终输出。故"电路能表达更一般的计算"并非"表达任意计算都没有代价":比较需要额外约束,循环需要约定次数或设计递归证明,域内计算也必须与原始程序的整数语义保持一致。arkworks 的 R1CS gadget 库提供了位、有限域和其他常用组件,但工程实现仍需检查约束是否遗漏。

5.4 R1CS 与 KZG/IPA 到底在哪里相遇

R1CS 回答的是"什么计算结果算正确";QAP、AHP 或多项式 IOP 等代数化方法形成"哪些多项式关系必须成立";在采用多项式承诺的证明系统中,KZG 或 IPA 可用于承诺这些多项式并证明必要的取值关系。这个连接由完整证明系统的协议完成,不是仅把 R1CS 矩阵交给一个 KZG commit() 函数就生成了 zk-SNARK。

由此,三部分在本篇中具有明确分工:KZG 一节解释高效承诺及参数信任问题(简记,详见专文);IPA 一节提出不同取舍并验证性能趋势;R1CS 一节说明承诺工具最终要服务于什么类型的计算命题。

六、KZG 与 IPA 的代码实验:方法、结果与解释

6.1 实验对象与可复现配置

arkworks-rs/poly-commit 提供 IPA 与 KZG 系列实现。本次在同一仓库中编写对照实验入口,选择支持统一 PCS 接口的 IPA-PC 与 MarlinKZG10 进行计时。基础 KZG10 另做端到端正确性测试,不能将其与 Marlin 包装版本的时间、证明大小混称。

项目 实际配置
上游版本 commit 1eaec5090ba5bc87d75a69570ed38f6fcf8b9417
IPA 实现 InnerProductArgPC,JubJub 曲线,Blake2s256
KZG 实现 MarlinKZG10,BLS12-381 配对曲线
输入任务 单个随机多项式、单个随机查询点;不启用隐藏或严格次数界
横轴规模 系数数量 \(n=d+1\):16、32、64、128、256、512、1024
对应次数 \(d\):15、31、63、127、255、511、1023
IPA 内部长度 本次 \(n\) 均为 2 的幂,无额外补齐
平台 Apple M1、macOS、Rust 1.96.0、release 编译、默认 features
重复测量 3 轮独立运行、固定种子;Setup 每点 21 个样本,其他操作每点 90 个样本
统计口径 中位数;时间图阴影为 P10–P90 波动范围
大小口径 规范压缩序列化字节数;底层单点证明不含标签、查询点和值

同仓库不等于完全公平的底层算法竞赛。 两种实现使用不同曲线和内部协议,时间首先表示这些具体实现及本机配置,不是排除一切底层因素后的普遍速度排名。仓库自称学术原型,测试通过不能代替安全审计。

6.2 实验在做什么,正确性怎样检查

实验模拟的是"先承诺一个多项式,再证明它在某点的值"。每个规模执行:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
生成随机 f 和查询点 z
       ↓
Setup / Trim:准备并整理所需参数
       ↓
Commit:生成承诺 C
       ↓
Open:生成 y=f(z) 与证明 π
       ↓
Verify:检查 (C,z,y,π) → 应接受
       ↓
把 y 改为 f(z)+1 → 应拒绝

三轮合计 1260/1260 次正确求值检查通过,42/42 次错误求值检查被拒绝。这说明所测配置下基本流程可以运行,并识别这种错误声明;不意味着已经证明所有攻击都不可能。

Setup/Trim 单独计时,不混入 Commit/Open/Verify。Commit 不含随机多项式与查询点生成,Open/Verify 不含 sponge 初始化,验证返回值检查包含在 Verify 时间中。先预热再计时,并保存逐次原始数据。这里测试的是 PCS,不是完整 zk-SNARK,也没有运行 R1CS 证明系统的性能对照。

实验趋势曲线(提交错误求值被拒绝、证明大小随规模增长等)已生成于本地 KZG-IPA-code-lab/experiment-results/ 目录;下文给出汇总数据表,便于直接对照。

6.3 结果一:Commit、Open、Verify 时间怎样变化

表中单位均为 毫秒(ms) ,数值为中位数。

系数数量 \(n\) IPA Commit IPA Open IPA Verify Marlin-KZG Commit Marlin-KZG Open Marlin-KZG Verify
16 0.326 3.853 1.469 0.483 0.423 2.639
32 0.424 5.216 1.704 0.613 0.570 2.626
64 0.665 7.411 2.135 0.846 0.801 2.630
128 0.805 9.856 2.368 1.186 1.148 2.638
256 1.243 14.312 3.021 1.775 1.796 2.634
512 1.921 21.653 3.864 3.031 2.977 2.652
1024 2.902 34.764 5.083 5.323 5.264 2.718

怎样看图: 横轴是系数数量,不是运行次数;纵轴是对应操作耗时,越低表示该操作越快。本配置下观察到:

  1. 两种实现的 Commit/Open 都随规模增大而变慢;IPA Commit 较快,Marlin-KZG Open 较快。
  2. Marlin-KZG Verify 在约 2.6–2.7 ms,随 \(n\) 增长大致稳定;IPA Verify 从 1.469 ms 增至 5.083 ms。
  3. 小规模时 IPA Verify 低于本次 KZG 实现,大规模时高于它。因此不能简单说"IPA 在任何规模都慢"。
  4. 有限规模测量支持趋势判断,不是严格渐进复杂度证明,也没有完成瓶颈剖析。

6.4 结果二:Setup 与 Trim 的准备开销

Setup 是生成参数;Trim 是从参数中整理出支持所需次数的密钥。Setup 中位数从 \(n=16\) 时 IPA 的 0.261 ms、Marlin-KZG 的 5.481 ms,增至 \(n=1024\) 时的 7.423 ms、14.426 ms。Trim 在本配置中是微秒或更低的本地整理操作。

不能把这张表理解为可信设置仪式的成本。 本地 setup() 生成测试参数,并没有组织多人仪式、检查陷门销毁或审计部署。Setup 也不是每次打开与验证都要重复执行。参数生成快慢与"是否需要信任秘密销毁"是两件事。

6.5 结果三:证明与参数大小怎样变化

单位均为 字节(B),采用压缩序列化。

系数数量 \(n\) IPA 证明 Marlin-KZG 证明 IPA 验证者密钥 Marlin-KZG 验证者密钥 IPA 公开参数 Marlin-KZG 公开参数
16 338 49 592 305 584 1936
32 402 49 1104 305 1096 3600
64 466 49 2128 305 2120 6928
128 530 49 4176 305 4168 13584
256 594 49 8272 305 8264 26896
512 658 49 16464 305 16456 53520
1024 722 49 32848 305 32840 106768

IPA 证明每次规模翻倍增加 64 B,从 338 B 增至 722 B,与增加一轮折叠的结构相符;Marlin-KZG 单点证明固定为 49 B。IPA 验证者密钥从 592 B 增至 32848 B,而 Marlin-KZG 为 305 B。两种实现的公开参数都随规模增长。这不是说所有 KZG 证明都是 49 B:该数值是本次 Marlin 包装实现、曲线及序列化口径的结果。承诺本体分别固定为 IPA 33 B、Marlin-KZG 49 B。

直观地说,IPA 避免了 KZG 式陷门,但并没有免费消除所有成本;短证明之外,验证者仍需处理公开生成元。KZG 的小证明、固定大小验证密钥也不代表整个 SRS 大小固定。

6.6 三个任务的完成状态与复现入口

任务 当前交付 尚可深入的工作
KZG 可信设置梳理 构造、SRS 复用、陷门伪造、多方设置与边界(详见 KZG 专文) 若深化研究,可进一步分析具体设置仪式
理解 IPA,运行 KZG/IPA 并画趋势 IPA 原理、两实现跑通、7 规模 × 3 轮、正确性检查、汇总数据表 同曲线条件对照、批量/隐藏场景、profiling
理解 R1CS 手算程序→约束→矩阵→QAP,说明与 PCS 的关系 未实现完整 R1CS zk-SNARK 性能实验,也不把它算作已完成

复现命令(需在本地 KZG-IPA-code-lab 目录):

1
2
3
4
5
cargo test -p ark-poly-commit --test wrong_evaluation_rejected
cargo run -p ark-poly-commit --example pcs_comparison --release -- experiment-results/run-1
cargo run -p ark-poly-commit --example pcs_comparison --release -- experiment-results/run-2
cargo run -p ark-poly-commit --example pcs_comparison --release -- experiment-results/run-3
python3 experiment-results/analyze.py

七、综合讨论与结论

KZG 的数学核心是把取值证明转化为商多项式的整除关系,并借助秘密点上的 SRS 编码与配对验证。它的主要优势在于单点证明紧凑;重要限制是结构化参数必须安全生成,若陷门被掌握,绑定性可能受到破坏。可共享与可更新的 SRS 减轻单方信任,却不免除部署与审计成本。

IPA 承诺从 \(f(z)=\langle\mathbf a,\mathbf b(z)\rangle\) 出发,通过内积论证折叠向量,避免 KZG 式必须销毁的秘密点。代价并非"必然更慢"或"必然更快",而是证明长度、验证工作量、公开生成元及工程配置之间的不同组合。只有同时报告复杂度分析和固定实现的多规模实测,才有资格回答具体场景下的性能问题。

R1CS 则位于更上游。它把实际计算拆成可检查的乘法约束;经 QAP 或其他代数化路线,约束可进一步呈现为多项式关系。在采用 PCS 的证明系统中,KZG 或 IPA 可承担多项式承诺和取值检查的角色,但它们本身都不等于完整 zk-SNARK,也不自动提供零知识。

因此,本篇的结论是:R1CS 负责表达计算,KZG/IPA 负责某些证明系统中的多项式承诺与打开;两种 PCS 的实际取舍必须同时看参数信任、证明大小、验证计算和参数规模。 本次实验观察与典型理论结构相符,但不构成构造的普遍速度排名或新的密码学成果。

术语边界:本文的"IPA 承诺"特指基于内积论证的一类多项式承诺;不同论文和仓库的实例并非完全同一个协议。文中简化公式用于说明原理,安全性与精确复杂度应以实际选用的构造及其假设为准。

引文

  • [1] Kate, A., Zaverucha, G. M., & Goldberg, I. Constant-Size Commitments to Polynomials and Their Applications. ASIACRYPT 2010. 论文 PDF。KZG 构造、承诺与打开的基础定义(详见《KZG 多项式承诺》)。
  • [2] Chiesa, A., Hu, Y., Maller, M., Mishra, P., Vesely, P., & Ward, N. Marlin: Preprocessing zkSNARKs with Universal and Updatable SRS. EUROCRYPT 2020. IACR ePrint 2019/1047。通用可更新 SRS 及 R1CS 上的 AHP 与证明系统关系。
  • [3] Bünz, B., Chiesa, A., Mishra, P., & Spooner, N. Proof-Carrying Data from Accumulation Schemes. TCC 2020. IACR ePrint 2020/499。arkworks IPA 多项式承诺模块注释所指的技术来源。
  • [4] arkworks-rs/poly-commit 官方仓库。用于确认代码实现、接口和已有实验入口。仓库自称学术原型,未充分安全审查。
  • [5] arkworks-rs/r1cs-std 官方仓库。用于理解位、域与椭圆曲线等计算的 R1CS gadget 实现。
  • [6] Bünz, B., Bootle, J., Boneh, D., Poelstra, A., Wuille, P., & Maxwell, G. Bulletproofs: Short Proofs for Confidential Transactions and More. IEEE S&P 2018. IACR ePrint 2017/1066。典型内积论证中交叉项、挑战折叠与最终验证关系的参考。

延伸阅读(本系列)

本文作者: Wcowin王科文