ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

解读 EIP-2029:State Rent 路线图中的状态计数器合约(State counters contract)

解读 EIP-2029:State Rent 路线图中的状态计数器合约(State counters contract) 解读 EIP-2029State Rent 路线图中的状态计数器合约State counters contract【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs导读EIP-2029State Rent A - State counters contract是以太坊State Rent状态租金v3 路线图中的第一块拼图由 Alexey AkhunovErigon/ledgerwatch 创始人于 2019 年 5 月提出。它设计了一个以CREATE2确定性部署在所有网络同一地址的系统合约合约代码极简仅 11 个字节功能仅为按存储槽键读取对应值从而在以太坊状态中开辟出一个存放全局状态计数器如总交易数、账户数的专用位置。阅读本文你将掌握该合约字节码的逐字节语义与 EVM 栈操作推演、CREATE2确定性地址的推导方式、它如何被下游的 EIP-2031Net transaction counter用于txCount计数与非重放保护以及它与扩展状态树结构、Extended State Oracle 两条替代路线的取舍逻辑。该 EIP 当前状态为Stagnant是研究以太坊状态管理演进史的重要文献。State Rent 路线图与 EIP-2029 的定位EIP-2029 属于作者提出的 State Rent v3 提案系列中的 Change A。该系列以字母编号A/B/C/H 等拆分出多个相互关联的独立 EIP共同目标是解决以太坊状态无限膨胀的问题EIP-2029A状态计数器合约—— 本文主题先在状态中开辟存放计数器的位置EIP-2031BNet transaction counter —— 依赖 2029在计数器合约的存储槽 0 维护总交易数EIP-2027CNet contract size accounting —— 追踪合约存储槽数量的净变化EIP-2026HFixed Prepayment for accounts —— 新建账户需一次性预付租金EIP-2035Stateless Clients —— 重新定价SLOAD/SSTORE以支付区块证明带宽EIP-2028已 Final将 Calldata 非零字节 gas 从 68 降至 16为上述重新定价提供数据定价模型。EIP-2029 自身并不产生计数行为它只提供一个被动读取存储的通用入口。真正写入计数器的是后续 EIP 规定的区块处理逻辑其中最直接的就是 EIP-2031 对txCount的递增。动机以太坊状态中缺少计数器的位置EIP-2029 明确指出EIPS/eip-2029.md Motivation 一节Ethereum currently does not have a special place in the state for tracking state counters such as number of transactions or number of accounts.以太坊当前状态由 MPT 状态树表示的账户集合中没有任何专门字段承载总交易数账户总数这类全局指标。而 State Rent 的推进需要这类指标例如按账户粒度做状态驱逐/恢复时需要一种与区块高度无关、不可被重放攻击绕过的 nonce 生成方式。计数器合约正是为了给这类指标提供显式、可被 Merkle 化、可通过区块证明验证的落点。这与 EIP-210Blockhash refactoring的思路一脉相承——后者也是把原本游离在状态树之外的隐含状态blockhash 历史显式写进状态让协议更纯粹、更易于被轻客户端与证明机制使用。核心规范11 字节的存储读取合约运行时字节码EIP-2029 规定在区块 AState Rent 路线图中的激活区块编号之前部署一个运行时字节码为以下 11 字节的合约0x60 0x20 0x60 0x00 0x80 0x80 0x35 0x54 0x90 0x52 0xF3它对应的汇编为PUSH1 32 PUSH1 0 DUP1 DUP1 CALLDATALOAD SLOAD SWAP1 MSTORE RETURN逐字节与逐指令语义字节操作码助记符语义0x60 0x200x60PUSH1 32压入立即数 32返回数据长度0x60 0x000x60PUSH1 0压入立即数 0内存偏移0x800x80DUP1复制栈顶 00x800x80DUP1再次复制栈顶 0作为 CALLDATALOAD 偏移0x350x35CALLDATALOAD从 calldata 偏移 0 读取 32 字节即参数x0x540x54SLOAD读取存储槽x的值0x900x90SWAP1交换栈顶两个元素0x520x52MSTORE将值写入内存偏移 00xF30xF3RETURN返回内存偏移 0 起的 32 字节栈操作推演按 EVM 栈栈顶在右逐步推演PUSH1 32→[32]PUSH1 0→[0, 32]DUP1→[0, 0, 32]DUP1→[0, 0, 0, 32]CALLDATALOAD→[x, 0, 0, 32]x calldata[0:32]按大端无符号整数解释不足 32 字节右侧补零SLOAD→[storage[x], 0, 0, 32]SWAP1→[0, storage[x], 0, 32]MSTORE弹出 offset0 与 valuestorage[x]→[0, 32]RETURN弹出 offset0 与 size32→ 返回内存[0:32]即storage[x]调用约定调用该合约只需传入一个 32 字节参数x合约返回存储槽x的当前值。由于整个逻辑不含任何状态写入、也不依赖msg.sender该调用天然是无副作用的适用于普通CALL乃至STATICCALLEIP-214 引入的静态调用场景。这与 EIP-2014 中建议用STATICCALL查询系统合约的约定一致。CREATE2 确定性部署任何网络同一地址EIP-2029 规定该合约必须使用CREATE2操作码部署in such a way that it has the same address on any networkEIPS/eip-2029.md Specification 一节。依据 EIP-1014Skinny CREATE2的定义CREATE2生成地址的公式为new_address keccak256(0xff deploying_address salt keccak256(init_code))[12:]其中0xff为单字节前缀确保CREATE2地址永远不会与传统的keccak256(rlp([sender, nonce]))派生地址冲突0xff作为 RLP 首字节只可能出现在长度达 PB 级的数据中见 EIPS/eip-1014.md Rationaledeploying_address为部署者地址salt为部署者自由选择的 32 字节盐值init_code为部署交易的 init code。只要所有网络使用相同的deploying_address、salt与init_code最终地址便完全确定且跨网络一致。这也意味着计数器合约的实际地址可以由这三元组提前计算任何客户端、合约或工具都可以在部署发生前获知它而无需在协议中硬编码一个魔法地址。EIP-2029 本身不指定deploying_address与salt的具体取值留待实现阶段确定。计数器如何被消费EIP-2031 的 txCount 与重放保护存储槽 0 即交易计数器EIP-2029 只定义了读取任意存储槽的机制而 EIP-2031State Rent B在此之上定义了第一个计数器A new field, with the location 0 ... is added to the state counter contract. It will eventually containtxCount, the total number of transactions processed up until that point.即存储槽 0存放txCount截至当前已处理的总交易数。由于 EIP-2029 合约的读取语义是以参数x为存储槽键读取txCount的方式就是以 32 个零字节作为参数调用该合约。EIP-2031 进一步规定自区块 B 起或自计数器合约部署起取先到者每处理完一笔交易后递增txCount且These changes are never reverted——计数器更新不随交易回滚这是它作为全局单调计数器的关键性质EIPS/eip-2031.md Specification 一节。用交易计数填充新建账户 nonce为什么需要全局交易计数EIP-2029 的 Abstract 给出答案这个计数器将用于填充新建非合约账户的 nonce...this counter will be used to populate the nonces of newly created non-contract accounts. This way of populating nonce ensures replay protection for accounts that were evicted and then brought back by sending ether to them.在 State Rent 设想下账户可能因未支付租金被驱逐从状态中移除之后又因被转入 ether 而恢复。若恢复后的账户 nonce 归零则攻击者可以重放该账户被驱逐前签名过的旧交易。将新建账户的 nonce 初始化为全局交易计数由 EIP-2031 维护、单调递增、永不回滚可以保证恢复后的 nonce 必然大于任何历史 nonce从而提供重放保护。EIP-2031 的 Rationale 中还对比了两个替代方案EIPS/eip-2031.md时间性重放保护valid-until字段存在副作用——nonce 不仅用于重放保护还参与合约地址推导除CREATE2外的keccak256(rlp([sender, nonce]))引入有效期字段会扰动该机制以区块号为基准设置 nonce需要人为设定单块最大交易数这一任意参数否则新建 nonce 可能与既有 nonce 冲突对私有网络尤其麻烦。全局交易计数方案规避了上述两个问题。设计取舍为什么不用另外两条路线EIP-2029 的 Rationale 明确记录了当时考虑过的两种替代方案及其被否决的原因方案一扩展状态结构引入更多字段直接扩展以太坊状态的数据结构、加入计数器字段会改变状态根state root的构造方式。凡是与状态根构造耦合的软件——尤其是依赖从状态根派生的Merkle 证明的工具与协议——都将受到影响迁移成本高、破坏面大。方案二Extended State OracleEIP-2014EIP-2014 提议在地址0x...09部署一个扩展状态预言机ESO系统合约通过标准 ABI 接口返回链标识、区块哈希等扩展数据。它的核心问题在于预言机返回的数据并不显式存在于状态树中因而不被 Merkle 化not Merkelised。这意味着快照同步snapshot sync时必须把全部计数器额外加入快照它们仍存在于状态但只是隐式地。对于需要可证明性、可验证性的 State Rent 目标而言这是不可接受的。结论EIP-2029 选择把计数器作为普通合约的普通存储槽落地——它天然位于状态树内、天然被 Merkle 化、天然可被区块证明覆盖。这正是 EIP-2014 中Proposals wanting to introduce more data to the state ... should aim to extend the ESO所指向的边界计数器这类需要进状态的数据不应停留在预言机层面。向后兼容与激活方式EIP-2029 明确声明EIPS/eip-2029.md Backwards Compatibility 一节This change is backwards compatible and does not require hard fork to be activated.该设计刻意将部署计数器合约实现为一条可由任意以太坊地址广播的普通交易见 Implementation 一节Implementation is envisaged as a transaction that can be posted from any Ethereum address任何人都可以构造并广播这笔交易触发计数器合约的CREATE2部署。由于部署动作本身不改变任何既有交易、账户或操作码语义因此无需硬分叉即可完成部署。需要区分的是部署本身无需硬分叉但后续对计数器的写入如 EIP-2031 的txCount递增涉及区块处理逻辑变更EIP-2031 即声明自身不向后兼容、需要硬分叉激活EIPS/eip-2031.md Backwards Compatibility 一节。这也解释了为何 EIP-2029 与 EIP-2031 分属两个独立 EIP前者铺路、后者消费。测试与实现状态Test CasesEIP-2029 提出将创建测试用例确保计数器合约能正确返回其存储槽内容——即对任意 32 字节参数x合约返回值与状态树中存储槽x的实际值一致。Implementation如前述实现形态为一条可被任意地址广播的部署交易具体的 init code 包装运行时字节码加部署前缀与salt取值留待参考实现阶段确定。从仓库现状看EIP-2029 与其依赖链上的 EIP-2026、EIP-2027、EIP-2031、EIP-2035 均处于Stagnant状态未进入任何已激活的网络升级EIP-2029 中提到的 EIP-2014 同样为Stagnant。作为对照该系列中只有 EIP-2028Calldata gas 降低最终成为Final且其 Rationale 中明确说明数据定价模型将服务于 State Rent v4 的 stateless client 方案。这从侧面反映出 State Rent 整体方案的演进方向早期状态租金设计逐步被 stateless/verkle 化思路吸收替代但**将关键全局指标显式纳入状态**这一核心思想仍然成立。总结EIP-2029 用 11 字节运行时字节码回答了一个关键架构问题以太坊状态中的全局计数器应该放在哪里它的答案是通过CREATE2确定性部署一个通用的存储槽读取器合约让计数器以最朴素、最可证明的形式普通存储槽存在于状态树中。由此衍生出的txCountEIP-2031、基于交易计数的账户 nonce 初始化与重放保护方案构成了 State Rent 路线图中账户生命周期管理的基础设施。对于希望理解以太坊状态模型演进、Merkle 化数据与系统合约设计权衡的读者EIP-2029 是一份言简意赅但信息密度极高的标本文献。本文相关原始资料EIPS/eip-2029.md主体、EIPS/eip-2031.md消费方、EIPS/eip-1014.mdCREATE2 地址公式、EIPS/eip-2014.md替代方案、EIPS/eip-2026.md、EIPS/eip-2027.md、EIPS/eip-2028.md、EIPS/eip-2035.mdState Rent 系列。【免费下载链接】EIPsThe Ethereum Improvement Proposal repository项目地址: https://gitcode.com/GitHub_Trending/ei/EIPs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表