ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

EIP-1418 区块链存储租金(Blockchain Storage Rent Payment)技术解析:为以太坊状态存储建立按块计费机制

EIP-1418 区块链存储租金(Blockchain Storage Rent Payment)技术解析:为以太坊状态存储建立按块计费机制 EIP-1418 区块链存储租金Blockchain Storage Rent Payment技术解析为以太坊状态存储建立按块计费机制【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs导读EIP-1418Blockchain Storage Rent Payment区块链存储租金支付提出了一套为以太坊账户状态存储引入按块持续计费机制的协议级方案每个区块都会根据账户占用的存储量字节数 × 区块数从其租金余额中扣除对应价值从根本上改变当前存储一次性付费、永久占用的定价模型。本仓库ethereum/EIPs 官方改进提案库中的 EIPS/eip-1418.md 是该提案的权威规范文档。阅读本文后你将掌握租金机制的状态变量设计、PAYRENT/RENTBALANCE/SENDRENT等新增操作码的精确语义、账户驱逐eviction与懒评估lazy evaluation的实现思路、常量定价的经济学推导以及与 EIP-1559 访问列表、EIP-2718 交易信封等既有协议的衔接方式。该 EIP 目前状态为Stagnant停滞属于 Standards Track / Core 类别其设计思想为无状态客户端与存储定价提供状态访问成本模型至今仍是研究存储经济学的重要参考。EIP-1418 是什么为存储占用持续定价EIP-1418 的核心主张非常简洁在每个区块根据每个账户占用的存储量从该账户扣除一定数量的价值称为租金。这一机制的目标是修正以太坊存储定价的结构性缺陷。正如提案 Motivation 部分指出的Ethereum is a public utility and we are underpricing the long-term costs of storage. Storage cost can be approximately modeled as bytes × time.即以太坊是一个公共基础设施而当前协议对存储的长期成本严重定价不足。存储的真实成本可以近似建模为字节数 × 时间的乘积——一次SSTORE写入一个存储槽后该数据会被全节点永久保存在状态树中持续消耗磁盘、内存、同步带宽等资源但写入方只支付了一次性的 gas 费用。EIP-1418 试图把这种一次性买断改为持续租赁。该提案是 EIPS/eip-1559.md 的依赖提案requires: 1559两者共同指向一个更深层的方向让节点可以不必记录完整网络状态即可参与共识。EIP-1559 为合约状态引入了 warm access热访问而 EIP-1418 在此基础上进一步为合约代码引入 warm access 概念并为状态数据的持续驻留设定明确的经济对价。规范核心状态变量、常量与新交易类型每个账户新增的状态变量EIP-1418 为每个账户account新增两个状态字段σ[a]_rent—— 账户的租金余额单位为 Wei这是一个有符号值signed value因为驱逐eviction过程中租金可能变为负值需要借用账户余额来补足σ[a]_storageWords—— 账户在存储中占用的字数word 数用于计算按存储量计的租金。注意这里的变量命名采用了黄皮书式的σ[a]状态机状态记号表示这些字段会进入世界状态world state参与状态根state root的哈希计算——这意味着它们是共识层可见的状态变更而非客户端本地数据。新增常量常量含义RENT_WORD_COST每个 word-block 的租金成本WeiRENT_ACCOUNT_COST每个 account-block 的租金成本WeiFORK_BLOCK实现开始生效的区块号新交易类型为合约代码引入 warm accessEIP-1418 引入一种新的交易类型transaction type。文档给出的关键对照是Whereas EIP-1559 introduced warm access for contract state, this new type introduces warm access for contract code.即 EIP-1559更准确地说其依赖链上的 EIPS/eip-2930.md Optional Access Lists 与 EIPS/eip-2929.md 状态访问 opcode 提价引入了合约状态storage slot的热访问列表机制而 EIP-1418 的新交易类型则在访问列表中扩展合约代码contract code的热访问能力。从仓库中已 Final 的 EIPS/eip-2718.md 可以看出TransactionType || TransactionPayload信封机制为新增交易类型提供了标准化挂载点EIPS/eip-2930.md 中accessList的格式rlp([chainId, nonce, gasPrice, gasLimit, to, value, data, accessList, signatureYParity, signatureR, signatureS])正是 EIP-1418 扩展代码热访问的格式基础。EIP-1418 中代码热访问的意义在于当合约因欠租被驱逐后其代码与存储被节点选择性删除此时若交易通过访问列表预先声明要读取该合约的代码并附带证明proof执行仍然可以进行——这与 EIP-2929 中已访问的地址/存储槽享受降价的思路一脉相承。新增操作码RENTBALANCE 与 SENDRENTRENTBALANCE(address)气体成本G_BALANCE与现有BALANCEopcode 相同语义返回账户逻辑上的σ[a]_rent值该值被定义为每个区块递减。规范特意指出实现层面不需要每个区块为每个账户实际改写σ[a]_rent。因为租金随时间线性递减完全可以只在账户被访问时按上次支付区块号rentLastPaid到当前区块号的差值惰性计算从而避免对全量账户做每块更新。这是本提案最重要的实现优化点详见下文懒评估。SENDRENT(address, amount)气体成本G_BASE语义把价值转换为租金并发送给目标账户分两步执行σ[account]_rent amount给目标账户增加租金余额σ[msg.sender]_balance - amount从发送者余额扣除等额 Wei这个操作码的设计意图很明确任何账户包括普通 EOA 和合约都可以为别人充租金。由于它不触发对目标合约的调用SENDRENT属于纯转账式操作不会引入重入reentrancy等调用语义风险。更新后的操作码PAYRENT 子程序与驱逐机制规范建立了一个新的子程序PAYRENT(account)作为SSTORE、SLOAD、CALL等既有操作码的前置步骤。其完整伪代码如下PAYRENT(account) blocks_to_pay NUMBER - σ[account]_rentLastPaid cost_per_block RENT_ACCOUNT_COST RENT_WORD_COST * (⌈∥σ[account]_code∥ / 32⌉ σ[a]_storageWords) rent_to_pay blocks_to_pay * cost_per_block σ[account]_rent - rent_to_pay if σ[account]_rent 0 σ[account]_value σ[account]_rent σ[account]_rent 0 end if σ[account]_value 0 σ[account]_rent σ[account]_value σ[account]_value 0 end σ[account]_rentLastPaid NUMBER σ[account]_rentEvictBlock NUMBER ⌊σ[account]_rent / cost_per_block⌋ END PAYRENT逐行理解 PAYRENT 的计算逻辑blocks_to_pay自上次支付租金以来经过的区块数NUMBER - rentLastPaid。这正是惰性计算的体现——租金欠款只在账户被真正触达时才一次性结算。cost_per_block每区块的租金单价由三部分组成RENT_ACCOUNT_COST账户本身的存在成本无论存储多少都要付RENT_WORD_COST × ⌈∥code∥/32⌉合约代码按 32 字节一个 word 向上取整折算的存储成本RENT_WORD_COST × storageWords存储槽占用的 word 数成本。rent_to_pay blocks_to_pay × cost_per_block累计欠租总额。欠租结算与余额联动若租金余额不足以支付欠租rent 0则从账户价值余额value/ETH 余额中补足差额value rent此时 rent 为负即扣除若价值余额也被扣成负数则把这个负数转回租金余额、价值余额归零——此时账户进入深度欠租状态。更新驱逐区块号rentEvictBlock NUMBER ⌊rent / cost_per_block⌋即按当前剩余租金余额还能支撑多少个区块精确计算出账户被驱逐evicted的时刻。各操作码的租金化改造SSTORE(account, key, value)先执行PAYRENT(account)若账户已被驱逐NUMBER rentEvictBlock交易失败——除非使用新交易类型并附带足够证明proof来验证旧存储根并计算新存储根。随后执行正常SSTORE逻辑并维护storageWords计数旧值为零且新值非零则storageWords旧值非零且新值为零则storageWords--结果小于零时归零。这保证了存储字数是精确的引用计数而非估算值。SLOAD(account, key)先检查驱逐状态驱逐账户的读取同样要求新交易类型 验证现有存储根与存储值的证明之后才执行正常SLOAD。CALL及衍生操作码若目标区块已被驱逐交易失败——除非新交易类型附带验证现有代码的足够证明。这里首次把代码访问纳入了驱逐约束与代码热访问交易类型呼应。CREATE设置σ[account]_rentLastPaid NUMBER执行正常CREATE并将σ[account]_storageWord置零。规范特别提醒这里可能存在创建前遗留的租金余额例如创建前有人为该地址充过租金需要妥善处理。新增内置合约 PAYRENT(address, amount)为了照顾普通账户EOAEIP-1418 还定义了一个内置合约built-in contractPAYRENT(address, amount)它直接调用PAYRENT子程序。动机非常实际simple accounts (CODESIZE 0) cannot call arbitrary opcodes, they can only call CREATE or CALL.普通账户无法直接执行任意 opcode只能通过CREATE或CALL触发逻辑因此需要内置合约作为人类充租金的便利入口。该内置合约的 gas 成本设定为10,000 或更低if possible。驱逐机制的设计权衡懒评估与责任归属驱逐责任交给共识客户端EIP-1418 把驱逐的执行责任交给共识客户端consensus clients而不是依赖外部参与者如监控账户并请求删除以赚取赏金。Rationale 部分给出了三条理由行为可预测驱逐恰好在应该发生的时刻发生不需要额外的激励设计无需退款 gas、无需赏金 bounty无需追踪一个区块内可能驱逐任意数量的账户但这无关紧要——客户端实现不需要跟踪哪些账户被驱逐共识的达成只需各方对被驱逐条件NUMBER rentEvictBlock达成一致即可确定性驱逐条件由状态根中可验证的字段决定天然可被轻客户端与无状态客户端验证。存储清理与未来扩展Storage note 部分说明对于每个被驱逐的账户客户端可以选择性地从磁盘删除其存储。这直接服务于节点不必记录完整网络状态的目标——被驱逐的数据不再要求全节点永久保存。规范同时预留了两个未来 EIP 的方向为保留被驱逐账户的额外数据提供激励付费保留创建客户端之间交换这些存储状态信息的机制。这两点共同构成了存储可以按市场价流转的远期蓝图。租金经济模型常量定价与历史成本推导为什么租金不可逆向转换EIP-1418 明确规定Ether 一旦转换为租金就不能再转回价值余额。Rationale 用了一个巧妙的类比Anybody that works in accounting and knows about gifts cards should tell you this is a good idea.就像礼品卡一样单向转换让系统的推理变得简单SENDRENT的接收方被依赖的合约可以确信这些资金只用于让自己继续存活而不会被其他调用路径挥霍掉。为什么需要独立的租金账户这是本提案最关键的激励机制设计。规范明确回答Because anybody/everybody can contribute to the rent account. If you depend on a contract, you should contribute to its rent. ... By maintaining a separate rent and value balance, this allows people to contribute to the rent while being confident that this is allowing the contract to stay around.即任何依赖某合约的人都应该为它的租金做贡献。如果租金与价值余额混在一起合约可以把所有资金花光导致充值者以为在续命、实际却被消耗的囚徒困境。分离的租金余额让外部贡献者有信心——他们的捐赠确实只用于延长合约的存续时间。常量定价的历史推导Economics constants 部分给出了一个非常具体的成本锚点推导2015 年执行一次SSTORE花费 20,000 gas此后经历了约 600 万个区块同期 gas 价格约 1~50 Gwei由此估算每个 word 每区块约 4,000 Wei进一步假设存储一个账户比存储一个 word的代价高 10 倍但规范随后又指出G_transaction21,000与G_sstore20,000量级相近二者都可以创建新账户/新 word因此实际定价倾向于让账户成本与 word 成本对齐。最终建议的常量值RENT_WORD_COST4,000 WeiRENT_ACCOUNT_COST4,000 WeiFORK_BLOCK 实现启动的区块号规范强调租金以硬通货 Ether计价不由客户端协商、不是动态的The rent is priced in cold, hard Ether. It is not negotiated by clients, it is not dynamic.。但同时也预留了未来改进为动态定价的路径——例如要求区块公证人notary证明其持有当前存储数据集不含驱逐项或额外证明持有含驱逐项的完整数据集以赚取额外费用用相对存储量与附加费用的比值形成市场反馈为存储设定市场价格。宏观量级参考规范提供了一个量级估算以太坊主网数据集约有150 亿15B个 word全网已开采约1 亿100METH。如果全部 ETH 都按当前提议价格用于存储相当于400 terabyte-yearsTB·年的存储量。作者对此的评价是我不确定这样看问题是否有帮助——意在说明该定价是粗略的经验锚点而非精密的供需均衡解。向后兼容性与存量账户的 storageWords 估算兼容性基础EIP-1418 明确以 EIP-1559 为兼容性前提EIP-1559 already introduces a mechanism for nodes to participate without recording the full network state and for clients to warm cache with storage data in their type 2 transactions.即 EIP-1559及其依赖的 EIPS/eip-2718.md 类型化交易信封、EIPS/eip-2930.md 访问列表已经为节点不记录完整网络状态即可参与和type 2 交易预热存储缓存铺好了路EIP-1418 的代码热访问交易类型与驱逐机制正是在此基础上叠加。存量账户 storageWords 的迁移难题对已有账户计算σ[account]_storageWord是一个**尚未解决DRAFT**的迁移问题。规范明确设定了两条约束不可接受的方案在分叉块要求只有知道每个账户完整存储量的归档节点archive nodes参与——这会破坏去中心化可接受的方案所需值可以基于新交易活动增量计算或估计。作者初步构想了一个无偏估计器unbiased estimator对传统账户首次访问某 key 的SSTORE增加 1 bit 存储每层 trie 增加 log(n) bits假设存储 key 是随机变量。该方案在文档中仍标注为 DRAFTTo think more about...说明存量迁移是提案落地的主要开放难点之一。对既有合约的影响Backwards Compatibility 部分坦承了两个现实风险用户需要被教育Users will need to be educated租金是全新的心智模型许多智能合约允许任何人无限制地使用其存储Many smart contracts allow anybody to use an arbitrary amount of storage in them——这类公共存储池合约在租金机制下可能被恶意塞满存储后拖欠租金进而影响该合约的可用性。这也是 Security Considerations 部分唯一强调的风险点。推荐实现变量每账户为了让σ[a]_rent的惰性计算可落地规范推荐在每个账户上维护两个实现变量σ[a]_rentLastPaid—— 上次支付租金的区块号。在以下事件发生时更新价值转入账户CREATE、CALL、SELFDESTRUCT账户代码被设置CREATE账户存储被更新SSTORE。 所有账户的初始逻辑值为FORK_BLOCK。σ[a]_rentEvictBlock—— 账户将被驱逐的区块号由PAYRENT末尾的公式计算得出。这两个变量与σ[a]_rent配合使客户端可以在任意时刻只通过(rentLastPaid, rentEvictBlock, rent)三元组推算账户的实时租金状态而无需每块遍历全量账户。安全考量与遗留问题安全考量规范重申了兼容性章节的担忧——允许任意人占用存储的合约公共存储池在租金机制下面临被滥用拖垮的风险这是部署前必须评估的核心安全问题。规范 TODO草稿注释中的开放问题被驱逐的账户在补缴欠租后是否允许复活un-evicted文档将Can/should an evicted account be allowed to be un-evicted when paying past due rent?列为待讨论议题未给出结论。总结与展望EIP-1418 是存储经济学领域一份影响深远的设计提案它把存储成本从一次性 gas重构为按块持续租金通过PAYRENT惰性结算、独立租金账户、RENTBALANCE/SENDRENT操作码与内置合约、以及基于 EIP-1559 访问列表体系扩展出的代码热访问交易类型构成了一套自洽的存储续租与驱逐框架。其驱逐责任由共识客户端承担、客户端无需追踪驱逐清单的懒评估思想以及租金单向不可逆、外部贡献者可安心充值的激励机制对后续所有研究状态膨胀state growth与存储定价的提案包括状态过期 state expiry 方向都具有直接的参考价值。虽然该提案目前处于 Stagnant 状态σ[account]_storageWords的存量迁移方案也仍停留在 DRAFT但其字节 × 时间的成本模型、驱逐区块号的确定性计算方式以及为无状态客户端铺路的思路至今仍是理解以太坊存储经济学绕不开的起点。想深入原文可直接阅读仓库中的 EIPS/eip-1418.md并对照其依赖链 EIPS/eip-1559.md、EIPS/eip-2718.md、EIPS/eip-2930.md 与 EIPS/eip-2929.md 了解完整的协议演进脉络。【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进