是谁偷走了你的 Gas?揭示以太坊存储过度收费的真相

  • hzysvilla
  • 发布于 2025-08-11 00:56
  • 阅读 77

是谁偷走了以太坊交易gas? 从区块链存储角度给出新答案,不是网络拥堵,也不是矿工贪心;是计费“算法”在误把缓存当成磁盘。

本文内容源于发表在USENIX FAST25会议上的研究论文《Analyzing and Optimizing Overcharge on Blockchain Storage》, 作者如下:

image.png

<!--StartFragment-->

一、动机(Motivation)

区块链系统中的交易费用机制(TFM)由两部分组成:一是 gas cost,用来对链上各类资源(计算、存储、带宽等)计费;二是 gas price,由用户根据网络拥堵程度自行设定以激励矿工或验证者。例如,以太坊中对存储的单次读取操作(SLOAD)会根据数据是否驻留在内存或落盘收取不同费用,若从磁盘加载则需支付 2,100 gas,而若数据已缓存于内存仅收取 100 gas。理想情况下,gas cost 应当贴合实际资源消耗,但我们的研究发现,现行实现中对存储资源的收费常常高于实际消耗,出现了“大幅过度收费”现象。以太坊用户在 2023 年因交易支付了 24 亿美元的费用,其中高达约 42% 的开销源于对缓存数据的重复或跨块访问仍被错误地按磁盘操作计费。此外,尽管已有 EIP-2929 等提案针对“同一事务内”首次访问与重复访问调整 gas cost,但它们仅在单个交易范围内生效,无法消除跨交易、跨区块乃至重复部署合约带来的过度收费问题。


二、背景(Background)

e391757f4d1ed74075b4e5ba59b0802.png

为提升状态访问性能,以太坊在节点中实现了多层缓存机制:首先,CoW cache(区块缓存)在执行当前区块时以写时复制方式临时保存修改;其次,SSAS cache(跨区块缓存)维护了最近 128 个区块的账户和平变量快照,以减少跨块访问的磁盘 I/O;最后,MPT cache(状态树缓存)则缓存了 Merkle Patricia Trie 节点,用于加速世界状态的查验与更新。这三层缓存各司其职:CoW cache 针对同区块内的重复访问,SSAS cache 跨多个区块重复访问,MPT cache 则服务于整棵状态树的高效校验。但在多客户端实现与硬件差异的共同作用下,缓存命中后的访问仍被误计为高昂的磁盘费用,从而成为过度收费的根源。论文进一步指出,类似问题普遍存在于多个以太坊客户端(如 geth、besu、nethermind、erigon)及其衍生链(如 Binance Smart Chain)。


三、问题

本文在分析多款主流以太坊客户端(geth、besu、nethermind、erigon)时发现,三种典型的过度收费场景广泛存在:

  1. 同一区块内重复访问:如果一个账户或存储槽在同一区块里被多次读写,后续访问虽命中 CoW cache,却仍被当成磁盘访问计费;

  2. 跨块缓存失效:对于最近 128 个区块内已访问过的对象,命中 SSAS cache 理应只付内存费,却依然被错误收取磁盘费用;

  3. 重复合约部署:部署与链上已存在字节码相同的合约,本应只做一次磁盘写入并重用存储,结果却对每次部署均全额收取磁盘写入费。

image.png

基于对以太坊18M到19M的高度观察,这三类过度收费累计影响了超过 70% 的交易和约 42% 的交易费用 (1.47亿美元),无论是普通转账、合约调用还是合约创建,用户都在为缓存中的数据反复付出不必要的高额 gas 支出。


四、设计(Design)

image.png

为应对上述挑战,作者设计了一个名为 Maat 的系统,旨在识别并优化区块链系统中的过度收费问题。Maat 的设计遵循三个核心原则:共识性(所有节点对优化后的 gas 收费保持一致)、公平性(收费与实际资源消耗一致)、效率(优化过程不能显著拖慢系统性能)。系统包括三个核心模块:

  1. Fine-grained data collection:从存储操作层面而非 opcode 层面采集精细化的 gas 费用信息,聚焦于账户/插槽/字节码的高层语义访问操作,确保优化具有针对性。具体来说,通过挂钩存储组件,将 gas cost 精细分解到每一次账户读取、存储槽访问和合约字节码操作上,以便精确定位那些本应按内存费率计价却被当作磁盘访问计费的操作。
  2. Consensus-oriented optimization:通过形式化规则(如 O1–O4),根据缓存状态和历史访问行为推测是否应将某次存储访问从磁盘费用调整为内存费用,确保 gas 优化在所有节点上一致。具体来说,将优化规则形式化为区块、交易、opcode 和状态访问位置等具备链上共识的数据结构条件,使得每条规则(如同一区块内、近 128 个区块跨交易访问或重复部署合约)在所有节点都能以一致方式触发并计算,从而不会破坏共识安全性。
  3. Resource pre-allocation:为确保所有节点具备一致的缓存行为,预分配必要的缓存空间,使优化规则在多客户端和异构节点之间都可一致生效。具体来说,利用以太坊区块的 gas 上限(当前为 30M gas)与单次账户访问的最大 gas(2,600 gas)分析出最坏情况下预分配所需的缓存内存上限(约 230 MiB可维护128个区块的内存消耗),通过“以内存换取一致性”的方式确保各客户端和异构硬件在执行优化规则时拥有足够的缓存空间,不会因缓存不足而回落到高费率磁盘访问,进而实现安全的“以空间换取交易费”的权衡。

五、实现(Implementation)

作者在 go-ethereum v1.12.2 上实现了 Maat 的原型系统,共 2,717 行代码,采用多线程设计以提高效率。实现中通过钩子函数监控特定的存储操作(如读取账户、插槽、字节码)并收集其 gas 费用信息,然后依据规则在运行时进行 gas 优化。优化器通过 Golang 的 channel 接收操作信息,并应用相应规则进行费用调整。系统对四类过度收费行为设计了具体优化规则,分别对应于在同一区块/128个区块内的重复访问,以及重复合约部署的情况。


六、实验(Evaluation)

image.png Maat 在以太坊和 BSC 两大主流链上均展示出显著的优化效果。以以太坊为例,在 100 万个区块(2023 年 8 月至 2024 年 1 月)范围内,Maat 共节省了 2.01 万亿 gas、58,358 ETH(约合 1.12 亿美元),优化率达 32%,几乎是 EIP-2929 的三倍。在 BSC 上,Maat 节省了 4.56 万亿 gas(7.71 百万美元),优化率为 31%。同时,Maat 的系统开销也控制在较低水平,仅增加了 1.4% 的区块处理时间和 5.6% 的内存使用。此外,作者还在 50 个复用以太坊代码库的区块链上验证了 Maat 的适用性,证明了其良好的可扩展性。


七、总结

本文通过系统性地识别区块链存储中的过度收费问题,并设计了可行的优化系统 Maat,实现了高效、共识一致、资源感知的交易费用优化。Maat 不仅大幅降低了用户费用,也为以太坊生态的可持续发展提供了基础设施级的改进方向,并已促成了相关社区提案 EIP-7863。

点赞 0
收藏 0
分享

0 条评论

请先 登录 后评论
hzysvilla
hzysvilla
江湖只有他的大名,没有他的介绍。