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 | |
图中箭头表示一种常见的研究路线,不代表所有 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 与双线性配对验证:
核心取舍:紧凑的单点证明与(主要配对次数)常数级验证,代价是必须安全管理结构化参数(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(X)=1+2X+3X^2+4X^3\),在 \(z=2\) 时,系数向量是 \((1,2,3,4)\),幂向量是 \((1,2,4,8)\)。所谓"内积"就是逐项相乘再相加:
因此 IPA 并没有换一道题目;它只是把"多项式在某点的值是多少"改写成"两个向量的内积是多少"。
"证明 \(f(z)=y\)"因而可转化为"证明被承诺的 \(\mathbf a\) 与公开的 \(\mathbf b(z)\) 的内积是 \(y\)"。一种概念性的向量承诺写法是
其中 \(G_i,H\) 是公开生成元,\(r\) 是否使用取决于方案的隐藏性设计。这只是原理示意,不能替代具体 IPA 多项式承诺实现中的度数约束、transcript、盲化和批处理细节。
4.2 "折叠"到底折叠了什么¶
"折叠"指用更短的向量,继续代表原先较长向量的内积关系。它不是把后一半直接扔掉;若只保留前一半就会丢失信息。协议要保留足够的交叉项,让验证者知道短问题是由原问题正确变来的。
先看一次可手算的演示,暂时用普通有理数。原始两个向量为 \(\mathbf a=(2,4)\)、\(\mathbf b=(3,5)\),内积为 \(2\times3+4\times5=26\)。取折叠系数 \(u=2\),把两个数压成一个数:
新内积为 \(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\),定义
展开内积得到
前两项正是原始内积,后两项是折叠产生的交叉项。实际 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\)。记
若承诺为 \(C=\langle\mathbf a,\mathbf G\rangle\),要证明 \(\langle\mathbf a,\mathbf b\rangle=y\),验证者构造本轮初始群元素
若声称正确,这等价于
右边是待验证的关系:同一个 \(P\) 同时包含两组向量承诺及其内积。
每轮把向量和生成元各自切成左右两半。证明者发送两个群元素:
验证者根据已收到的 transcript(前面所有消息)生成或抽取非零挑战 \(u\)。交互式协议由验证者随机抽取;非交互式实现通常用哈希 transcript 派生。双方用同一个挑战折叠:
验证者同步更新
为什么要加上 \(L\) 和 \(R\)?把折叠后的新关系展开,原来同一半的项仍由 \(P\) 提供,左右交叉项正好由 \(u^2L\) 和 \(u^{-2}R\) 补上,因此有
此时向量长度减半。重复 \(k=\log_2 n\) 轮后,只剩标量 \(a_*,b_*\) 和生成元 \(G_*,H_*\),验证者检查
若等式成立,最后这一步就把整条折叠链收束成一个群等式。安全性直觉是:证明者不能在看到挑战前预先决定左右交叉项的权重;挑战由 transcript 绑定消息,伪造者要同时让每轮更新关系和最终等式成立。
把前面的 4 维例子接到群更新上¶
在 \(\mathbb F_{101}\) 中取
第一轮挑战 \(u_1=2\),其逆元为 \(51\),折叠后
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\) 方向上的系数同步从
第二轮为手算方便,取挑战 \(u_2=3\),逆元为 \(34\),得到 \(a_*=63\)、\(b_*=37\),最终内积为 \(63\cdot37=8\pmod{101}\)。这轮的两个交叉内积分别是 \(9\) 和 \(51\),且 \(u_2^2=9\)、\(u_2^{-2}=45\),因此验证者的 \(U\) 方向系数也更新为
因此最后检查不是把 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 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\),计算被拆成
取见证向量 \(\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\) 的每一行分别为表中三个系数向量,则全部约束统一为
\(\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)\),要求它们在两个检查位置分别给出对应的数字:
这里的"插值"不神秘:过 \((1,2)\)、\((2,12)\) 两点的一次多项式斜率为 \((12-2)/(2-1)=10\),因此 \(L(X)=10X-8\)。同理,\(R\) 的斜率为 \(-1\),\(O\) 的斜率为 8。在素数 \(p>13\) 的有限域中,以普通整数书写这个演算,得到
上面先从已知见证算出每一行的数值,再插值得到 \(L,R,O\),有助于手算理解"约束行值如何打包"。标准 QAP 构造更系统:先针对每个变量列,分别把 R1CS 矩阵中的系数插值成多项式,再用见证向量做线性组合。设 \(A_i(X),B_i(X),C_i(X)\) 分别对应变量 \(w_i\) 在矩阵 \(A,B,C\) 中的第 \(i\) 列,则
对本例,变量顺序为 \((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)\):
这就解释了前面出现的三个多项式并非证明者任意挑出来的:矩阵列多项式由电路固定,证明者只能按自己的见证系数做线性组合。实际证明系统还需将公开输入、见证承诺和协议随机性绑定起来;上面的手算只是 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 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"中的 > 并不是有限域自带的整数顺序。要对有界整数解释比较,须先约定比特宽度和合法范围,再把数值分解为比特:
随后才可用比较电路限制最终输出。故"电路能表达更一般的计算"并非"表达任意计算都没有代价":比较需要额外约束,循环需要约定次数或设计递归证明,域内计算也必须与原始程序的整数语义保持一致。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 | |
三轮合计 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 |
怎样看图: 横轴是系数数量,不是运行次数;纵轴是对应操作耗时,越低表示该操作越快。本配置下观察到:
- 两种实现的 Commit/Open 都随规模增大而变慢;IPA Commit 较快,Marlin-KZG Open 较快。
- Marlin-KZG Verify 在约 2.6–2.7 ms,随 \(n\) 增长大致稳定;IPA Verify 从 1.469 ms 增至 5.083 ms。
- 小规模时 IPA Verify 低于本次 KZG 实现,大规模时高于它。因此不能简单说"IPA 在任何规模都慢"。
- 有限规模测量支持趋势判断,不是严格渐进复杂度证明,也没有完成瓶颈剖析。
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 | |
七、综合讨论与结论¶
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。典型内积论证中交叉项、挑战折叠与最终验证关系的参考。
延伸阅读(本系列)¶
- zk-SNARK 原理详解:从直觉到可运行实现 — R1CS/QAP 的整体直觉、Groth16 配对验证式
- KZG 多项式承诺:原理、构造与研究进展 — 路线一(配对 + 秘密陷门)的完整构造与可信设置
- 现代密码学发展 — 零知识证明、后量子 PCS 与透明承诺的整体图景
- 比特币体系:从零开始理解加密货币 — 区块链为何需要可验证计算与数据可用性
- 密码协议与应用 — Fiat–Shamir 变换、承诺方案在真实协议中的角色
- 数论基础 — 有限域、多项式与因式定理的数学底子