模幂的Gas按公式计价:EIP-2565的三段式定价拆解 图 1
模幂的Gas按公式计价:EIP-2565的三段式定价拆解 · 图 1

以太坊的预编译合约住在地址 0x010x08 一带,普通账户或合约永远不可能出现在这些地址上,它们是协议内置的原生算法入口。其中地址 0x0000000000000000000000000000000000000005 对应模幂运算(ModExp),即给定底数、模数和指数,计算底数的指数次方对模数取余的结果。模幂是签名验证、可验证延迟函数、部分零知识证明电路的基础构件,它的定价高低直接影响上层密码学应用划不划算。

从固定套路到按公式计费

在柏林升级之前,ModExp 的 Gas 由 EIP-198 定义的复杂度函数决定:取底数和模数中较大的字节长度,套一个分段二次函数近似卡拉楚卡乘法的代价,再乘上指数需要的迭代次数。问题出在迭代次数的估计方式过于粗糙,而且复杂度函数与真实执行时间的拟合并不好。作者实测后发现这个预编译整体被定贵了——同样的计算,收费所对应的每秒杀伤力明显高于其他预编译——于是 EIP-2565 提出换公式而不是简单地打个折扣。

模幂的Gas按公式计价:EIP-2565的三段式定价拆解 图 2
模幂的Gas按公式计价:EIP-2565的三段式定价拆解 · 图 2

新公式的三段结构

EIP-2565 于 2019 年提交,最终在 2021 年的柏林升级中生效。规范给出的计算分三步。第一步是乘法复杂度:取底数与模数长度的较大值,按每 8 字节一段折算成大数运算的 limb 数,再取平方。除以 8 这一步是对多精度算术中 limb 划分的建模,比 EIP-198 直接拿字节数开平方更贴近大数库的真实行为。第二步是迭代次数:如果指数长度不超过 32 字节,迭代数等于指数本身的二进制有效位长度减一;指数超过 32 字节时,超出部分每字节按 8 次迭代累加,再加上低 256 位的有效位长度减一;结果至少为 1,指数恰好为零且不超过 32 字节时为 0。第三步把两者相乘再除以常数 3、向下取整,最后与 200 取较大值兜底。这个 200 的下限防止有人用极小输入把预编译当成近乎免费的计算入口。

用规范里的测试向量感受一下量级:一个平方级别的基准用例从旧定价的 204 Gas 降到 200,一个小指数开幂的用例从 3276 降到 341,大指数场景的降幅更明显。也就是说,新公式不是普降价,而是把过去被高估得最厉害的输入形状压回来,让价格曲线重新贴合执行时间。

常见的误读

第一种误读是把 EIP-2565 说成”免费午餐”。它调整的是同一算法内部不同输入形状之间的相对价格,调用者仍要为每一次乘法迭代付 Gas。第二种误读是把它和后来的 EIP-7883、EIP-7823 混为一谈:2565 是柏林时代定下的定价公式,7883 是在更晚的阶段调整公式中的除法常数、把价格重新上调,7823 则给输入位宽设了上限。三者处理的是同一个预编译在不同时期的不同问题,引用时务必写清是哪一条。第三种误读是把它与 BLS 预编译集合(EIP-2537)混在一起讨论,BLS 是另一批新增入口,与模幂公式无关。

安全与使用提示

对合约开发者来说,模幂的输入完全由调用方控制,Gas 随输入长度和指数规模增长,因此把外部传入的指数不加限制地喂给预编译会引入不可预期的成本,甚至被用来构造重执行交易。工程上应当约束输入长度、用 try/catch 或 Gas 快照包裹调用,并针对目标链当前生效的定价版本(2565、7883 的组合因升级高度而异)做基准测试,而不是照搬别处的经验数字。

需要强调的是,本文只是对已生效协议规则的技术说明,不构成任何投资建议;围绕 Gas 参数的提案状态会随网络升级变化,落笔时以 EIPs 仓库中各条目的最新状态为准。