空账户清场之后:EIP-4747 想把 EIP-161 的历史包袱改写成两份事件清单 图 1
空账户清场之后:EIP-4747 想把 EIP-161 的历史包袱改写成两份事件清单 · 图 1

2022 年 2 月,主网区块 14049881 把最后一批空账户清扫出境。此前还在被工程师反复争论的边缘路径,突然变成没有活体的标本。EIP-4747 就递交在同一个星期——2022 年 2 月 2 日,作者 Peter Davies:既然历史上不会再发生那些情况,为什么不把 EIP-161 复杂的状态清理规则,改写成一份可以用两条事件记录背下来的简化文本?

六年规则的由来

先把时间线立正。2016 年 11 月 22 日,Spurious Dragon 硬分叉在区块 2675000 落地一批规则,处理同年攻击者用批量创建再销毁的账户制造的状态膨胀;那批规则确立了空账户按不存在处理的原则与清理义务。此后六年,空账户在创建、豁免、清理的条件里反复横跳:拜占庭以前,还有交易能批量留下空壳;拜占庭以后,触发清理的事件越来越稀有。提案在安全考量一节干脆立下三个前提——同一笔交易里没有先删后建的空账户、拜占庭起点之后清理事件只有附录列出的那些、所有空账户已被清空——整套简化只有在这三条都成立时才等价于历史规则。

空账户清场之后:EIP-4747 想把 EIP-161 的历史包袱改写成两份事件清单 图 2
空账户清场之后:EIP-4747 想把 EIP-161 的历史包袱改写成两份事件清单 · 图 2

简化后的三条规则

4747 主张从 EIP-161 引入时的区块起,就用新规则回溯替换旧文本。其一,创建账户时,在执行初始化代码之前就把 nonce 置为 1。其二,EVM 执行中一切空账户按不存在处理,任何会造出空账户的操作都停在不存在状态——静态调用语境下的空账户访问也被允许直接按不存在假设。其三,空账户在三种零值事件中消失:收到零值调用、成为零值转账的接收方、或成为零值自毁的受益人;交易或调用回滚时,清理一并回滚;删除可以即时发生,也可以推迟到交易末尾统一处理。文本还保留了一段考古注记:区块 2675119 里对 RIPEMD 预编译地址的一次空值调用因 gas 耗尽而失败,账户却被照常删除——当年的边缘怪癖被逐字写进新规则,当作不可磨灭的先例。

最务实的一段落在历史负担上:主网拜占庭起点之后,实际触发状态清理的事件只有两笔——区块 4457731 里一个地址收到零值自毁被清,与区块 14049881 的批量清扫。客户端可以把这两笔事件硬编码,而不必供养一套通用清理机器;根本不服务历史查询的实现,甚至被允许完全不实现状态清理。安全预防也没少:提案提到以太坊经典为防万一清掉了全部空账户、而多数兼容网络从创世就带着这套规则。

快速问答

问:这是新的共识变更吗? 答:不是硬分叉。它是对既有规则的后验简化,前提是不改变任何历史状态结果,只删掉主网不可能再触发的分支。

问:为什么没人推进落地? 答:清理规则是实现内部机器,简化要每个客户端各自重构;它不解决用户可见问题,优先级天然排不进升级清单,今天状态是 Stagnant。

问:附录那串地址清单是干什么的? 答:提案把区块 14049881 里被清空的全部账户逐个列出,供实现逐条核对——规范文本罕见地长成了一份验尸报告。

一条判断线

读这类给旧规则写简化版的提案,关键问一句:历史数据是否已经把旧规则的所有分支都跑干了?只要还有一个未触发的边缘条件,简化就可能改写出与历史不同的状态承诺。4747 的底气来自那次清场让空账户彻底绝迹,而它把这份底气写成了带完整地址清单的证据——先例可查,规则才可删。

常见误区

一是把处理空账户的规则与同期改交易哈希计价的规则混作一谈,同批落地的几条各管一段;二是以为空账户故事就此终结——此后仍有明令禁止空账户存在的收尾提案;三是忽略这套简化对归档节点的苛刻依赖:需要重放早期历史的实现无法跳过旧规则。

风险提示:本文解释历史规则简化提案,不构成投资建议;规则文本以 EIPs 仓库当期原文为准。