十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

EIPs 项目详解:EIP-1087 SSTORE 净燃气计量(Net Gas Metering)机制与后续演进

EIPs 项目详解:EIP-1087 SSTORE 净燃气计量(Net Gas Metering)机制与后续演进 EIPs 项目详解EIP-1087 SSTORE 净燃气计量Net Gas Metering机制与后续演进【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs导读EIP-1087Net gas metering for SSTORE operations是 Ethereum Improvement Proposal 仓库中针对 EVMSSTORE指令燃气计费提出的一项核心改进提案目标是消除合约存储多次写入场景下的过度收费问题并为重入锁、跨调用上下文传递等此前因成本过高而不可行的存储使用模式打开空间。本文以 EIPS/eip-1087.md 为骨架结合仓库中 EIP-1283、EIP-2200、EIP-1706、EIP-1153 等后续提案与测试用例完整还原其动机、规范、成本复算、测试向量与最终演进脉络帮助读者理解现代以太坊存储燃气模型的设计源头。背景传统SSTORE计费方式的痛点在 EIP-1087 提出之前EVM 中SSTORE0x55指令的燃气收费规则为将存储槽从 0 写为非 0扣除20,000 gas其他任何值变更扣除5,000 gas将存储槽从非 0 写回 0交易结束时给予10,000 gas 退款。该提案的作者 Nick Johnson 在 Motivation 中指出当一笔交易只对某个存储值做单次更新时上述成本与节点实际消耗的资源基本匹配但当同一交易内出现多次更新序列时收费便显得过高。原文给出了三个典型例子写回原值场景空存储合约先将 slot 0 设为 1再设回 0会被收取20000 5000 - 10000 15000gas——尽管这组操作实际上不需要任何磁盘写入。多次自增场景空存储合约将 slot 0 自增 5 次会被收取20000 5 * 5000 45000gas——尽管这组操作所需的磁盘活动与单次写入20000 gas相当。余额转移场景账户 A 转给 B、再转给 C且所有账户期初、期末余额均非 0需要5000 * 4 20000gas。这种按操作次数线性收费、不区分是否产生净变化的模型直接抑制了以交易结束时存储无净变化为特征的用例例如防止重入的互斥锁mutex、在多次合约调用之间传递的上下文信息等。作者特别提到approveAndCall这类单笔交易内先授权再调用的操作若没有成本优化将要求代币标准为兼容而专门改造合约。核心规范基于脏映射dirty map的净计量EIP-1087 的 Specification 对 EVM 提出如下修改核心是引入一张按交易维度的脏映射来跟踪本交易内被修改过的所有合约存储槽脏映射dirty map为每笔交易维护记录当前交易中所有合约里被修改过的存储槽其作用域与存储更新保持一致——即在后续 revert 的调用帧内对脏映射的修改不会被保留。写入当前值当向存储槽写入其已包含的值时扣除200 gas。首次变更当存储槽值首次变更时将该槽标记为脏若该槽此前为 0扣除20,000 gas否则扣除5,000 gas。重复写入脏槽当已处于脏映射中的存储槽再次被写入时扣除200 gas。交易结束时结算退款对脏映射中的每个槽若槽在交易前为 0、交易结束时仍为 0退款19,800 gas若槽在交易前非 0、且值未发生变化退款4,800 gas若槽在交易前非 0、交易结束时为 0退款15,000 gas。关键设计在于首次变更承担全部冷启动成本后续重复写入只收 200 gas 的廉价操作费而最终回到初始状态的槽则通过退款机制把多收的费用返还。这样交易的最终燃气消耗只与该槽的净状态变化挂钩而非操作次数。改进效果三个动机示例的复算按新规则复算 Motivation 中的三个例子写回原值场景20000 200 - 19800 400gas从 15000 大幅降至 400多次自增场景20000 5 * 200 21000gas从 45000 降至 21000余额转移场景5000 * 3 200 - 4800 10400gas从 20000 降至 10400。可以验证只对存储槽做单次变更的交易成本保持原样而多次变更的合约将看到显著的成本下降。设计取舍Rationale为何不用更简单的方案提案作者认为上述机制是在收费不合理场景下降低存储燃气成本的最简单方式并在 Rationale 中逐一驳斥了三种备选方案备选一统一收取 200 gas 交易末尾追加收费。对所有SSTORE统一收 200 gas交易结束时再对新增/变更值追加 19800 / 4800 gas。该方案更简单、甚至无需脏映射但把一大块燃气消耗推迟到交易末尾结算会复杂化调试、削弱合约限制被调用方燃气消耗的能力并给 EVM 引入全新机制。备选二为存储退款维护独立退款计数器。可避免退款被限制为消耗燃气的一半这一问题的干扰本提案并不依赖该限制但需要额外跟踪增加复杂度。备选三每次写回初始值即时退款。会引入即时退款新机制、复杂化合约间调用的燃气记账甚至可能导致负执行成本的合约调用。从仓库中后续提案的表述看这一设计取舍被 EIP-1283、EIP-2200 继承并形式化两者均明确指出对于绝对燃气消耗实际燃气减去退款本 EIP 在所有场景下与 EIP-1087 等价见 EIPS/eip-1283.md 与 EIPS/eip-2200.md 的 Rationale 部分。向后兼容性与硬分叉要求EIP-1087 明确要求硬分叉方可实施。由于新规则下任何合约都不会出现燃气成本上升、多数合约反而成本下降提案预期合约层不存在向后兼容问题。这一点与后续 EIP-1283、EIP-2200 的 Backwards Compatibility 表述一致——后者还补充说明执行SSTORE从未在低于 5000 gas 的情况下成为可能因此不引入与主网的不兼容。测试用例十二组验收向量原文档提供了一组覆盖各类组合的测试用例是理解新计费规则最直接的验收依据以下全部继承自 EIPS/eip-1087.md 的 Test Cases 章节#场景燃气/退款1向值为 0 的槽写入非 0 值 x20k gas无退款2向值为 x 的槽写入 yx≠y 且 x≠05k gas无退款3向值为 x 的槽写入 0x≠05k gas10k 退款4向已为 0 的槽写入 0200 gas无退款5向已为 x 的槽写入 xx≠0200 gas无退款6向值为 0 的槽依次写 x、yx≠y20200 gas无退款7向值为 0 的槽依次写 x、y、zx≠y≠z 且 x≠05200 gas无退款8向值为 0 的槽依次写 x、0x≠020200 gas19800 退款9向值为 y 的槽依次写 x、yx≠y≠05200 gas4800 退款10向值为 0 的槽写 x、0随后 revert 所在栈帧20200 gas无退款11向值为 y 的槽写 x、y随后 revert 所在栈帧5200 gas无退款12嵌套帧中向值为 0 的槽写 x、返回再写 020200 gas19800 退款注意第 10、11 条直接验证了脏映射的作用域规则——被 revert 的帧内产生的写入不会保留脏标记因此退款也不生效第 12 条则验证跨调用帧场景下脏映射与退款依然正确工作。源码级佐证从 EIP-1087 到最终采纳方案的演进EIP-1087 在仓库中状态为Stagnant并未被直接采纳但其思想经由 EIP-1283、EIP-2200 两个 Final 状态的提案最终落地。仓库中的演进脉络如下EIP-1283Net gas metering for SSTORE without dirty maps由 Wei Tang 提出的替代方案自述作为 EIP-1087 的替代对采用不同存储变更缓存优化策略的实现更友好。它放弃了脏映射改用三个各实现普遍可得的信息——存储槽原始值original value、当前值current value与退款计数器——并将计费归纳为 No-op / Fresh / Dirty 三种状态配套给出了 17 条含字节码如0x60016000556000600055的测试向量与附录数学证明归纳法证明最终值为 0 时收费200*N、最终值为非 0 时收费20000 200*(N-1)等性质。其 Rationale 也明确指出了 EIP-1087 方案的实现局限脏映射隐式假设交易内存储变更在交易结束时才提交到存储 trie这对采用内存 trie 或不可变数据结构做存储缓存的客户端不友好——它们能得知原始值与当前值却无法在无额外内存/处理开销的前提下遍历全部存储变更。EIP-2200Structured Definitions for Net Gas MeteringEIP-1283 与 EIP-1706 的合并版本将数值参数化为SLOAD_GAS、SSTORE_SET_GAS、SSTORE_RESET_GAS、SSTORE_CLEARS_SCHEDULE四个变量并加入gasleft 低于 2300 stipend 时禁止SSTORE的安全条款——该条款正是为修复 EIP-1283 引发的新型重入攻击Solidity 默认向 transfer/send 授予 2300 gas stipend而引入的。在测试用例中可以看到参数化的效果SLOAD_GAS从 200 改为 800 后同名字节码测试的 Used Gas 相应平移如0x60016000556000600055从 20212 变为 20812。EIP-1153Transient storage opcodesEIP-1087 动机中提到的互斥锁、跨帧上下文传递等用例的最终归宿。它引入TLOAD/TSTORE两个新指令用交易级临时存储直接解决帧间通信问题并在 Rationale 中说明 EIP-3529 将退款上限压缩至交易燃气 20% 后单纯依赖SSTORE退款已不足以支撑这些用例。下述状态转移图来自 EIP-1283 的 assets/eip-1283/state.png以状态节点currentorig0、current!orig、currentorig!0、current0与箭头上的燃气/退款标注直观展示了净燃气计量下存储槽在不同原始值/当前值组合之间的迁移成本——它与 EIP-1087 的脏映射方案在绝对燃气消耗上等价可作为理解本提案结算逻辑的可视化辅助实现状态与总结原文档的 Implementation 章节标注为 TBD待定这与其 Stagnant 状态相符——EIP-1087 更多承担了提出净计量思想、明确问题域的开创性角色而具体实现最终由无脏映射的 EIP-1283 / EIP-2200 完成并被客户端采纳。对读者而言理解本提案的价值在于掌握存储燃气模型的核心矛盾按操作次数线性收费与节点实际磁盘工作只取决于净变化之间的错配理解净计量的通用框架首次变更承担全量成本、重复写入廉价化、回到初始状态触发退款这一框架在 EIP-1283 的三态模型No-op/Fresh/Dirty与 EIP-2200 的参数化定义中一脉相承读懂测试向量的验收逻辑退款与脏标记的作用域规则revert 帧不保留是所有后续实现必须满足的兼容性底线。如需深入可继续阅读 EIPS/eip-1283.md含完整状态转移表与附录证明、EIPS/eip-2200.md参数化定义与 gasleft 条款以及 EIPS/eip-1153.md这些存储用例的最终落地方案。版权说明本提案原文版权已按 LICENSE.md 中声明的 CC0 协议放弃本文仅作技术解读。【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表