Tangerine Whistle 升级:以太坊如何用 Gas 重定价堵住读状态的耗损漏洞 图 1
Tangerine Whistle 升级:以太坊如何用 Gas 重定价堵住读状态的耗损漏洞 · 图 1

便宜的读操作成了武器

以太坊的 Gas 价目表最早按一个朴素假设定价:所有操作对节点的负担大致可以用运算量衡量。现实给了设计者一课。从状态树里读一个账户或一条存储槽,意味着节点可能要做磁盘查找,成本远高于加减乘除这类纯内存操作,可当时的价目表里,BALANCE、SLOAD、CALL 这些读写状态的操作只收几十个 Gas。2016 年下半年,有人反复发送专门构造的交易,用少量 Gas 触发节点大量状态读取,部分节点的同步与验证明显滞后——这不是要偷谁的钱,而是用最低的成本让整个网络打喷嚏。这类拒绝服务攻击暴露的规则漏洞是:只要单位 Gas 能购买的磁盘工作量不均衡,攻击者永远有套利空间。

Tangerine Whistle 升级:以太坊如何用 Gas 重定价堵住读状态的耗损漏洞 图 2
Tangerine Whistle 升级:以太坊如何用 Gas 重定价堵住读状态的耗损漏洞 · 图 2

硬分叉的重定价清单

应对方案最终走的是硬分叉路线,代号 Tangerine Whistle(橙色口哨),由 EIP-608 作为升级元文件汇总,核心是 EIP-150。按 EIP-150 的规范,从主网第 2463000 个区块起:EXTCODESIZE 和 EXTCODECOPY 的基础价格从 20 涨到 700,BALANCE 从 20 涨到 400,SLOAD 从 50 涨到 200,CALL 与 DELEGATECALL、CALLCODE 从 40 涨到 700,SELFDESTRUCT 从 0 涨到 5000、若命中新建账户还要额外加 25000。数字本身不是重点,重点是定价逻辑的转向:读状态类操作按最坏情况的磁盘开销重新标定,规范解释里提到目标是一条区块最多让节点读取约 8 MB 状态数据。同一次升级还顺手把区块 Gas 上限的建议值提到 550 万,抵消涨价对普通交易吞吐的影响。

六十四分之一规则保护了什么

EIP-150 还有一个容易被忽略的贡献:调用燃料的六十四分之一规则。在此之前,合约调用时可以把自己剩下的全部 Gas 传给被调用方,因此调用成本必须是不变量,否则所有既有合约里 Gas 减去 40 这类写法全部失效。重定价让 Gas 传递出现例外:父调用最多把剩余量的六十四分之六十三传下去,永远给自己留六十四分之一。后果之一是子调用无论怎么耗尽燃料,父合约总能拿到一点 Gas 把日志和状态收尾写完;之二是调用栈深度不再靠一个 1024 层的硬上限约束,而是被 Gas 自然限制在三百多层,一类栈深攻击就此消失。开发者后来熟悉的错误串里那句 out of gas 之外的 stack 类报错,源头就在这里。

对今天的合约意味着什么

这次升级之后,读写链上状态不再是廉价操作。合约开发者把重复的外部调用移出循环、用一次调用取回多项数据再本地处理,这些优化习惯的起点就在 EIP-150 之后:状态访问单价上台阶,循环里的调用从省钱技巧变成风险点。对普通用户,直观感受是当年一部分老合约的逻辑调用开始变贵,而攻击者的套利通道被关掉,节点在同等信息量下的验证时间回到可控区间。评估任何 Gas 提案时,它是否让付款与节点真实负担重新对齐,是比涨价多少更本质的问题。

快速问答

问:这次升级改普通转账的费用了吗? 答:没有,改的是合约调用与状态读取类操作码,简单转账的基础 21000 不变。

问:攻击者是靠什么让节点变慢的? 答:用极低 Gas 的循环调用触发海量状态树读取,让验证的磁盘时间远超 Gas 预算对应的假设时间。

问:Tangerine Whistle 和 Spurious Dragon 什么关系? 答:相隔数月先后上线的两次硬分叉,前者重定 Gas 价,后者清理状态膨胀并补上重放保护等规则,EIP-608 也被后者列为前置依赖。

一条判断线

这次升级留下的长期遗产,是以太坊给所有人的一条经验:Gas 定价必须逼近最坏情况的真实资源消耗,否则价目表本身会成为攻击面。后来 EIP-2929 给冷存储与热存储分价、账户访问列表等设计,本质上都是同一思路的延续——把节点负担与用户付费对齐。理解这条线,再看任何一次 Gas 调整提案,就能快速判断它在解决什么问题。

常见误区

一是把它读成那次攻击偷走了资金,它属于耗损型攻击,漏洞在定价而非资产所有权。二是以为涨价后读状态依旧便宜,恰恰相反,这之后读账户成了有零有整的贵操作。三是把六十四分之一规则记成 Gas 退款上限,那是另一个机制,两者无关。

风险提示:本文为协议历史科普,不构成任何投资建议;合约交互的 Gas 行为随网络升级变化,请以当期规范与实测为准。