脚本开销从签名之外算起:BIP-440 的 varops 预算 图 1
脚本开销从签名之外算起:BIP-440 的 varops 预算 · 图 1

比特币对脚本执行一直有一条暗线:防止单块脚本把验证者算力榨干。历史上最直接的手段出现在 2010 年——一批操作码因安全缺陷被批量禁用,随后引入的 sigops 预算给每个区块的签名验证工作量设了硬顶。但这套账本只记“验签”这一项;对搬运、拼接、比较栈上数据的操作,协议层一直没有一个通用计费框架,导致每个新脚本提案都得自己论证“我的操作不会让节点卡死”,各造各的轮子。BIP-440 想把这把尺子统一出来。

从 sigops 到 varops

提案的命名直接点题:把 BIP-342 给 tapscript 设计的 sigops 预算思路,推广到非签名操作,于是叫 varops——变量操作数(variable operand size)的缩写。计费单位不是调用次数,而是每次操作触碰的栈数据的字节长度:一个操作把多长的数据搬进搬出,就按那个长度计入预算。理由藏在模型假设里:在没有对操作数尺寸硬性小帽的前提下,脚本性能瓶颈几乎总是数据处理时间,而不是栈本身的管理(丢弃、复制栈元素这类动作可以视为常数开销,OP_ROLL 是显著例外;内存分配与脚本解释本身的开销分别被归入可忽略与受块尺寸天然约束两类)。按最坏情况用线性行为来假设,整套模型只需要数一遍字节长度,就能对整段脚本给出静态可算的上界。

脚本开销从签名之外算起:BIP-440 的 varops 预算 图 2
脚本开销从签名之外算起:BIP-440 的 varops 预算 · 图 2

它想替代什么

提案自我定位是“供其他 BIP 引用的框架”,并附(opcode)示例表明按这套预算执行会比现行规则更宽松而非更严。换句话说,varops 不新增限制,而是给未来想做以下事情的人一个公共答案:想在 tapscript 里加一个处理任意长数据的操作码,不必再单独发明“每块最多调 N 次”这种与块大小、数据分布都脱钩的拍脑袋限额,只需声明该操作按 varops 记账。对审稿人来说,这把尺子也方便:一个脚本族是否可能在最坏输入下超支,可以用静态分析回答,不必跑遍真实流量。

状态与阅读姿势

BIP-440 是 Specification 类 Draft(编号于 2026 年 3 月分配),尚未构成任何共识变化;现网节点执行的仍是旧规则(含历史上因安全缺陷被禁用的那批操作码、各版本的块大小与 sigops 限制)。讨论 varops 时把“提案设计了什么”与“现网执行什么”分开,是读这类文档最重要的习惯,任何声称比特币已经启用 varops 的说法都值得立即质疑并回查官方实现。

一条直觉算术

给 varops 一个数量级直觉:假设某块预算按提案示例折算后允许每块处理若干兆字节的栈数据流量,那么一段每次搬运一千字节数据的脚本,在一个块里最多合法出现几千次量级;而把同样操作嵌进循环、每轮触碰一百万字节的数据,预算会在第一轮就爆掉。计费跟的是“数据被搬了多远、多宽”,不是“代码写了几行”。这正是静态分析能提前判死刑或放行原因:循环展开后数据流量可算,与运行时输入无关的最坏界也能写进合约验证工具里。对设计者来说,这把尺子的价值在于把性能论证从“请相信我们做过压测”变成“请看这道算术”。

快速问答

问:varops 会让交易手续费变贵吗? 答:不会直接改变费率;它约束的是每块脚本工作量的验证上界,与计价是两个坐标系。

问:和 sigops 冲突吗? 答:不冲突,两者各管一段:验签开销继续走 sigops,数据处理开销走 varops。

问:为什么按长度而不是按 CPU 时间计费? 答:CPU 时间跨实现波动、无法进共识;字节长度对所有节点确定一致,且与处理时间强相关。

风险提示:本文仅科普脚本机制提案,不构成投资建议;执行层的任何变化都以官方实现与激活信号为准。