一句话先说清
EIP-196 是 2017 年 2 月提出、随拜占庭升级上线的一条核心类标准提案。它做的事情很具体:在以太坊上开出两个预编译合约地址,0x0000000000000000000000000000000000000006 负责椭圆曲线上的点加法,0x0000000000000000000000000000000000000007 负责标量乘法,用的是一条叫 alt_bn128 的配对友好曲线。它和负责配对检查的 EIP-197 合在一起,才让”在智能合约里验证一笔 zkSNARK 证明”这件事从理论变成跑得动的工程。

为什么非要单独做两个地址
EVM 本身能算椭圆曲线运算,但算得极慢。一条曲线的点加法要在素域上做模逆、模乘,写成 EVM 字节码就是几十次 MULMOD、ADDMOD 与循环判断,标量乘法更是把点加法重复几百次。EIP-196 原文的动机段落把话说明白了:以太坊的智能合约执行完全透明,不适合处理位置、身份、历史交易这类隐私信息;zkSNARK 是出路,但 EVM 理论上能用,实际开销大到塞不进区块Gas上限。所以这条提案选择把最底层、最耗算力、又被反复调用的两个原语交给客户端用原生代码实现,Gas 直接按固定档位收,而不是按字节码执行步数计量。
预编译的代价是”锁死参数”。曲线方程、素数模数都写死在协议里。EIP-196 特别解释了这不是缩水:zkSNARK 的通用性来自证明系统本身可以任意裁剪电路,而底层曲线的这几个常数是所有电路共用的地基,固定它们不影响能表达的问题种类。
曲线与编码的硬事实
alt_bn128 的定义写在提案规范里:曲线是 Y^2 = X^3 + 3,定义在素域 F_p 上,模数 p 等于 21888242871839275222246405745257275088696311157297823662689037894645226208583。调用时的编码规则同样明确:域元素和标量都用三十二字节大端整数表示,一个曲线点用两个域元素 (x, y) 表示,无穷远点写成 (0, 0)。多个对象就是首尾拼接。一个容易被忽略的细节是:如果调用时传进的输入比预期短,会被视作在右侧补零后再解析,这一点在实现和调试里都踩过坑。
它和 EIP-197 是怎么分工的
只有加法和标量乘,验不了证明。配对运算(把两个曲线点映射到另一个域的元素并比较等式)才是真正的判定环节,那部分由同期的 EIP-197 提供,地址是 0x0000000000000000000000000000000000000008。三条凑齐,合约里就能写出”给我证明、公开输入,我告诉你是真是假”的接口。后来大量在以太坊主网上跑的零知识应用,包括汇总交易的证明校验、私有交易网络的验证合约,走的都是这套预编译组合。
一条直觉账:预编译省在哪
假设某个验证路径需要在曲线上做上百次标量乘。用字节码硬算,每次标量乘的Gas消耗会直接把整笔交易推过区块上限,交易永远发不出去;用预编译,同样的计算按提案定价收固定的Gas,一次验证落在几十万Gas的量级,一笔普通交易承担得起。这里的直觉是:预编译不是”优化”,是把原本不可能完成的计算变成可能性边界之内的事,而它的成本是用协议层的固定参数换来的。
现在的处境
alt_bn128 这条曲线后来在社区里通常被叫作 BN254 或者 alt_bn128,它的配对实现后来因为安全性与性能的讨论,被以 BLS12-381 为曲线的新一批预编译(EIP-2537 一线)当作 predecessor 讨论。读老合约时会发现大量验证器仍然只依赖 0x6、0x7、0x8 这三个地址,读新方案时会看到它们被并列摆放。这不是互相替代的历史遗留,而是同一条工程路线上的两代选择。
快速问答
问:预编译地址算合约吗?
答:它们地址上有代码哈希之外的特殊处理,EXTCODEHASH 与调用语义在协议里被单列,不是任何账户创建出来的普通合约,也不能被自毁。
问:为什么两个运算要分成两个地址? 答:分开定价、分开编码、调用方按需选择。点加法比标量乘便宜一个数量级,塞进同一个地址反而不好计费。
问:普通用户需要关心这条提案吗? 答:一般只在你读懂某笔交易为什么Gas异常时会碰到:调用了证明验证合约,那笔交易的Gas 大头就是在为这些预编译付钱。
风险提示:本文只做协议机制说明,不涉及任何资产估值、收益预期或买卖时机判断。协议参数以官方提案与客户端实现为准。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。