如何为以太坊状态租金铺路)
EIP-2027 深度解析State Rent C 净合约存储计数storagesize如何为以太坊状态租金铺路【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs本篇文章围绕以太坊改进提案 EIP-2027State Rent C - Net contract size accounting展开它属于 Alexey Akhunov 提出的State Rent状态租金路线图中的一环目标是在以太坊状态中为每个合约引入storagesize字段以净变化方式计数合约存储槽storage slot的填满与清空。读完本文你将理解为什么以太坊必须知道每个合约占用了多少存储槽、SSTORE语义将如何改变、HUGE_NUMBER常量在设计中的作用以及这一字段如何支撑未来的块证明block proofs重定价与快照同步协议。背景State Rent 路线图与净计数的定位以太坊状态state由账户包括外部账户与合约账户及其存储组成且随着链上活动无限增长。State Rent 是一组旨在为状态占用引入持续性成本的提案其系列 EIP 按字母编号分布在当前仓库中EIP名称在路线图中的角色EIP-2029State Rent A - State counters contract部署一个读取自身存储槽的状态计数器合约为各类状态计数器提供存储位置EIP-2031State Rent B - Net transaction counter每笔交易后递增计数器合约 0 号槽位的txCountEIP-2027State Rent C - Net contract size accounting为每个合约引入storagesize净计数存储槽数量EIP-2026State Rent H - Fixed Prepayment for accounts新账户创建/首次修改时向rentbalance字段预缴固定租金EIP-2035Stateless Clients - Repricing SLOAD and SSTORE提高SLOAD/SSTORE的 gas 成本以支付块证明的额外带宽EIP-2027 的Simple Summary清楚地说明了它在这条路线中的位置以太坊开始计数合约中被填满和被清空的存储槽数量。由于当前状态中并未记录既有槽位的数量因此实际上只能跟踪槽位数量的净变化net change而在后续被称作Gross contract size accounting毛计数的变更中才会开始跟踪存储槽的总数。也就是说EIP-2027 是通向毛计数的先行步骤——单独看它价值有限但它是后续一切存储大小相关机制的基础设施。动机为什么需要知道合约的存储规模EIP-2027 的Motivation段落直接点明了问题的根源Ethereum currently does not track the number of contract storage slots at all, and producing such number given the downloaded state cannot be done in constantO(1)time.即以太坊目前完全不跟踪合约存储槽的数量而且即便已经下载了完整状态要在常数时间 O(1) 内得到该数量也是不可能的——它需要对整个状态做扫描无法通过简单的 Merkle 证明快速取回。而一旦把该数量写进状态它就成为状态树中可证明provable的一部分可以被任何轻节点或同步协议通过 Merkle 证明验证。两个直接受益方向Abstract中列出了该字段带来的两个核心收益SLOAD与SSTORE的 gas 成本重定价未来SLOAD和SSTORE的 gas 成本需要提高以补偿块证明block proofs消耗的额外带宽。起初成本可以是固定的之后可以根据SLOAD/SSTORE所操作的合约大小自动校准——这正是 EIP-2027 提供的合约大小数据。快照同步协议fast sync、warp sync、firehose、red queen等快照同步方案将受益于状态中拥有正确的合约存储大小因而可以通过 Merkle 证明验证。核心规范storagesize字段与SSTORE语义变更字段定义与适用范围EIP-2027 的Specification规定Each contract (account withcodeHashfield not equal to0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470, which the hash of the empty code) gets a new uint64 field, calledstoragesize.每个合约账户即codeHash不等于空代码哈希0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470的账户获得一个新的uint64 字段storagesize。该哈希正是 keccak256 空代码的哈希值用于区分普通账户/空合约与真正带代码的合约。该字段在区块C及之后生效区块号C由后续硬分叉协商确定原文未给出具体数值。SSTORE 的新语义自区块C起操作SSTORE(location, value)的语义变更如下写入前的location值写入后的value对storagesize的影响0非 0increment递增storagesize非 00decrement递减storagesize其他组合—不变这实质上是在跟踪每个合约当前非零存储槽的数量槽位从零变非零意味着新增一个占用槽从非零变零意味着释放一个槽。回滚语义与普通存储值同等的处理规范特别强调As with other state changes, changes ofstoragesizeget reverted when the execution frame reverts, i.e. it needs to use the same techniques as storage values, like journalling (in Geth), and substates (in Parity).即storagesize的变更与普通存储值一样在执行帧回滚revert时必须一并回滚。实现上需复用既有的回滚机制Geth 使用日志记录journallingParity 使用子状态substates机制。这一点直接决定了它在客户端中的落地方式——它不是一个独立于交易执行之外的特殊计数器而是状态的一部分。合约不可观测Value ofstoragesizeis not observable from contracts at this point.现阶段storagesize对合约不可观测——EVM 中没有暴露读取它的操作码。这与后续 EIP-1682Storage Rent已 Withdrawn设想中的SSIZE操作码形成对比见下文设计脉络一节。语义细节increment 与 decrement 的缺失字段处理由于该字段是新增的存量合约在区块C之前不存在storagesize字段。规范为此定义了特殊的缺失语义increment递增若storagesize不存在storagesize HUGE_NUMBER 1若storagesize存在storagesize storagesize 1decrement递减若storagesize不存在storagesize HUGE_NUMBER - 1若storagesize存在storagesize storagesize - 1HUGE_NUMBER 的作用与取值HUGE_NUMBER是规范中引入的一个关键常量需要满足两个约束足够大使得任何真实指标合约存储大小、账户数量、合约数量、代码总大小、存储总大小永远不会达到该数值足够小能够放进一个无符号 64 位整数uint64中。原文建议Current suggestion is to haveHUGE_NUMBER 2^63, which is binary representation is the a single bit in a 64-bit number.即HUGE_NUMBER 2^63其二进制表示就是 64 位整数中的单个最高位。这个设计的精妙之处在于为未来决策提供了两个可判定条件字段是否曾经被递增/递减过通过字段的存在性presence判断。从未被触碰的存量合约没有该字段一旦被SSTORE触碰字段即被创建。是否已从净计数转换为毛计数通过数值大小判断——如果storagesize的值小于HUGE_NUMBER/2即 2^62说明已经完成了净→毛的转换因为任何合约在区块C时刻的实际大小都不可能超过 2^62 个存储槽。换言之HUGE_NUMBER像一个哨兵基准值净计数阶段所有值都围绕 2^63 上下浮动2^63 ± 实际槽位数而毛计数阶段则从 0 开始累计真实槽位数。二者通过数值区间即可无歧义区分无需额外的迁移标记。设计权衡为什么不用估算算法在Rationale中作者比较了另一种思路通过某种机制估算合约存储大小。该方案曾在作者早前的文章中提出原 EIP 中附有外部链接但被否决原因非常明确But it does have a big drawback of introducing a lot of complexity into the consensus (in the form of estimation algorithm, which has quite a few edge cases to cater for different sizes of the storage).估算算法需要在共识层引入大量复杂性——它必须针对不同规模的存储处理大量边界情况edge cases。相比之下EIP-2027 的显式记账方案把槽位计数直接写入状态逻辑简单、可证明、无边界情况代价仅仅是每个合约多一个 uint64 字段。这也解释了为什么采用先净计数、后毛计数的两步走存量状态无法在 O(1) 时间内算出每个合约的既有槽位总数因此只能从区块C开始增量地跟踪净变化待后续毛计数变更以及可能的全量状态迁移实施后再获得精确总数。收益落地块证明重定价与快照同步块证明与 SLOAD/SSTORE 重定价EIP-2027 的核心收益之一是服务于无状态客户端stateless clients下的块证明机制。仓库中的 EIP-2035 正是这一方向的落地提案块证明让节点无需访问合约存储即可执行区块内交易但矿工需要额外构造和传输块证明因此需要对SLOAD/SSTORE引入额外收费EIP-2035 指出经验分析表明 1 次未缓存的SSTORE或SLOAD至多向块证明增加 1 kB 数据按当时 68 gas/字节 的传输成本换算两个操作需增加约 69k gas——而在 EIP-2028交易数据 gas 成本从 68 降至 16 gas/字节状态为 Final生效后增加幅度可以大幅缩小尤为关键的是EIP-2035 明确提出未来变体将依据合约存储大小来差异化定价对较小合约的SLOAD/SSTORE更便宜而这一大小数据正是 EIP-2027 的storagesize字段所提供的。EIP-2035 原文写道Future variant (will be possible after the implementation of theGross contract size accounting) is researched, where the increase is varied depending on the size of the contract storage。尽管差异化定价依赖毛计数但净计数字段及其存在性/区间编码是建立这套机制的第一步。快照同步协议在快照同步场景中fast sync、warp sync、firehose、red queen等节点需要获取状态的某个一致快照。如果合约存储大小作为状态的一部分被记录则同步时可以直接通过 Merkle 证明验证该合约确实占用了这么多存储而无需下载完整存储再自行统计——这正是 Abstract 中being provable via Merkle proofs的含义。与 State Rent 系列其他 EIP 的协作关系从仓库中同系列提案可以拼出完整的上下文EIP-2029State Rent A部署状态计数器合约以CREATE2部署到所有网络同一地址代码为0x60 0x20 0x60 0x00 0x80 0x80 0x35 0x54 0x90 0x52 0xF3即PUSH1 32 PUSH1 0 DUP1 DUP1 CALLDATALOAD SLOAD SWAP1 MSTORE RETURN为状态计数器提供存储位置。该提案在 Rationale 中对比了扩展状态结构与扩展状态预言机EIP-2014两种替代方案。EIP-2031State Rent B在计数器合约 0 号槽位维护txCount用于为被驱逐后又恢复的账户填充 nonce 以提供重放保护。它与 EIP-2027 同属在状态中记账的技术路线——EIP-2027 记的是合约存储槽数EIP-2031 记的是交易数。EIP-2026State Rent H账户创建/首次修改时向rentbalance预缴固定租金其设计哲学与 EIP-2027 一致把状态占用成本显式地写进状态而不是仅靠提高 gas 价格。EIP-2035无状态客户端重定价如上文所述是storagesize数据的直接消费方。值得一提的是storagesize这一概念并非凭空出现。仓库中更早的 EIP-1682Storage Rent状态为 Withdrawn作者 Felix J Lange 与 Martin Holst Swende就曾为账户引入过三元组扩展account [nonce, balance, storageroot, codehash, rentbalance, rentblock, storagesize]其中storagesize表示当前已设置的存储槽数量并配套提出SSIZE、PAYRENT、RESTORETO等操作码。EIP-2027 的净计数方案可视为对这一早期设计的共识简化先不追求绝对精确而是用最小的共识改动一个字段 两条 SSTORE 规则起步。兼容性、测试与实现状态向后兼容性This change is not backwards compatible and requires hard fork to be activated. Since the newly introduced field is not observable, this change does not impact any operations of the existing smart contracts.EIP-2027不向后兼容必须通过硬分叉激活涉及状态结构扩展与共识规则变更但由于新字段对合约不可观测因此不会影响任何既有智能合约的操作行为——这一点使其成为 State Rent 系列中共识改动小、外部影响小的一环。相比之下同系列的 EIP-2026 明确承认可能因账户创建所需 gas 增加而对既有合约产生不利影响而 EIP-2027 没有此类顾虑。测试用例Tests cases will be generated out of a reference implementation.测试用例将由参考实现生成——即先实现参考客户端再据其行为生成共识测试。这是 EIP 流程中常见做法确保规范与实现的一致性。实现状态There will be proof of concept implementation to refine and clarify the specification.计划提供概念验证proof of concept实现来细化与澄清规范。截至当前仓库中的状态该 EIP 的 front matter 标注为Status: Stagnant停滞、Type: Standards Track / Category: Core创建于 2019-05-14作者为 Alexey Akhunov。这意味着它属于已提出但未进入激活流程的历史性提案——其价值更多在于记录了状态租金/无状态客户端路线图的设计思路与演进脉络而非当前生效的以太坊共识规则。版权原文采用 CC0 放弃版权Copyright and related rights waived via CC0与以太坊 EIP 仓库的通用惯例一致。总结EIP-2027 用最简的共识改动回答了每个合约到底占用了多少存储这个基础问题为每个合约新增一个 uint64 字段storagesize从区块C起随SSTORE的槽位从零变非零递增/从非零变零递减而净增减缺失字段以HUGE_NUMBER2^63为基准初始化使字段是否被触碰过与是否已完成净→毛转换均可通过存在性与数值区间判定字段不可观测、随执行帧回滚不影响既有合约但需要硬分叉激活它为两条下游路线提供数据基础一是 EIP-2035 所设想的依据合约大小差异化重定价SLOAD/SSTORE支付块证明带宽二是快照同步协议对可证明的合约存储规模的依赖。理解 EIP-2027就理解了以太坊状态租金提案的核心方法论与其在共识层引入复杂的估算算法不如把一个看似难以计算的指标显式地、增量地记进状态——先用净计数以最小成本起步再在后续变更中演进为毛计数。这一设计思路至今仍是理解无状态客户端与状态增长治理讨论的关键背景知识。【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考