合约里怎么验一条零知识证明:EIP-197 的配对预编译 图 1
合约里怎么验一条零知识证明:EIP-197 的配对预编译 · 图 1

智能合约自己验一条零知识证明,听起来像让计算器做微积分——直到协议在机器里装了一个专用芯片。EIP-197 就是这个芯片的图纸:2017 年 2 月 6 日由 Vitalik Buterin 与 Christian Reitwiessner 起草,状态 Final,随拜占庭升级在主网区块 4,370,000 生效。它在地址 0x0000000000000000000000000000000000000008 处放入一个配对检验函数,从此合约可以用一笔调用完成 SNARK 验证的最后一步。它的 Simple Summary 写得毫不掩饰:在区块燃料上限内完成 zkSNARK 验证,需要曲线配对预编译。

输入输出的样子

这个预编译的接口很朴素。输入是一串每份一百九十二字节的点对:前面一百二十八字节是第一个群里的点,后面六十四字节是第二个群里的点,几份就是几对;输入长度必须是一百九十二的整数倍,否则调用直接失败,空输入合法且返回一。它对每对点做双线性配对再乘起来,检验乘积是否落在单位元上——用提案的离散对数写法:各组元素的离散对数两两相乘求和,若在标量域上等于零就返回一,否则返回零。对使用者,只需要记住:给一组点,它回答一个是否成立的问题。

为什么验证离不开配对

主流 SNARK 的验证等式形如’若干配对之积相等’。配对的本质是把两个群 G1、G2 的元素映到第三个目标群里,从而允许把’指乘’折成’积’——这正是把一组椭圆曲线方程压缩成一条等式的机制。纯 EVM 算不了配对:目标群在几百万位的扩张域上,逐位模拟的 Gas 会爆表。预编译的意义就是把唯一算不动的一步做成指令级的黑盒,其余域运算仍由合约字节码完成。两个群的曲线是同一阶数 q 的 alt_bn128(也叫 BN256):G1 在 y² = x³ + 3 上,G2 定义在其二次扩张域上,群参数全部写死在规范里,防止任何人塞进一条自己带后门的’曲线’。

和 EIP-196 的分工

EIP-197 从不单独出场。同批进场的 EIP-196 提供 0x06 地址上的 G1 点加与数乘,验证等式左边那些点运算靠它。分工线划得很清楚:合约自己做加和数乘,配对检验交给 0x08。这个预编译后来在伊斯坦布尔升级里与点运算伙伴一同被重新定过价,接口从未动过。

为什么把曲线焊死而不是传参

提案的 Rationale 交代了一个被否决的方案:把曲线与域参数也放进输入,让预编译支持任意曲线。否决理由有两层,第一条是工程性的:参数化会让 Gas 公式几乎无法确定;第二条是安全性的:无法排除有人调用一条’名字叫椭圆曲线但密码学上不安全’的曲线,或一条根本不存在高效配对实现的曲线。把曲线锁死成一条经过公开审视的常数曲线,等于用灵活性换确定性——对一个给几十亿美元锁作公证的函数,这笔交换被反复证明是划算的。这个’少即是安全’的取舍,和比特币把脚本操作码做减法的精神是同一个流派的。

一条直觉账

配对检验的代价有多大?预编译版本按每对点收固定 Gas,节点内部跑的是一次毫秒级的配对运算。若改为链上字节码逐位模拟,一个目标群元素的乘法要在几百万位域上做,一条验证的 Gas 会轻松超出单块上限几个量级——这正是’预编译存在论’的最佳教材:协议不替所有人算一切,只把所有人都不约而同要算、且字节码算不动的那一小撮,铸进机器。

快速问答

问:这和 BLS 签名用的配对是同一回事吗? 答:数学工具同源(双线性配对),曲线与协议不同。alt_bn128 是一条为 SNARK 优化的旧曲线,BLS 体系用的是新曲线族,两者地址与接口互不相干。

问:这个预编译会不会被证明系统换代淘汰? 答:接口层面它长期是链上 SNARK 验证的地基;曲线与证明系统在演进,但只要链上还住着用它搭的验证器,这个插座就拆不动。

风险提示:本文为协议机制科普,不构成任何投资建议;曲线参数与Gas价格以共识规范与 EIP 仓库当期文本为准。