升级虚拟机却不碰老合约:EIP-1702 的账户版本化设想 图 1
升级虚拟机却不碰老合约:EIP-1702 的账户版本化设想 · 图 1

以太坊每一次硬分叉都像一场全场同步换发动机:所有账户、所有合约在同一区块高度进入新规则。于是有人问:能不能只给新合约开新功能,老合约原地不动、永远按老规矩跑?2017 年底提交的 EIP-1702 给出了一个系统化的答案:给账户状态加一个版本字段,让多个版本的虚拟机在同一条链、同一个区块里合法并存。它的状态如今是 Stagnant,从未激活,但作为兼容策略的反事实样本,至今仍然值得一读。

机制长什么样

今天以太坊的账户状态存四项:nonce、余额、存储根、代码哈希。1702 把它扩成五项,多出一个 256 位标量版本字段:版本为 0 时账户照旧按四项编码,与全部现存账户天然兼容;版本非零时,该账户进入对应版本自己的规则空间,甚至可以定义附加状态字段。执行语义围绕代码版本展开:合约代码记着部署时的版本,谁调用它就在哪个版本下执行;用委托调用跨合约时,执行帧沿用被调用代码的版本而不是调用方的版本。合约创建管得最严——创建交易本身在当前代码版本下执行,部署出的新合约直接拿当前版本。这套约束的目的很明确:防止新语义代码被嫁接进旧执行环境,或者反过来。

升级虚拟机却不碰老合约:EIP-1702 的账户版本化设想 图 2
升级虚拟机却不碰老合约:EIP-1702 的账户版本化设想 · 图 2

它为什么没走下去

这个提案与 eWASM 的兴衰深度绑定:1702 的主要动机就是让 EVM 与未来的 WebAssembly 虚拟机长期共存,老合约不迁移、新合约自愿进新虚拟机。后来 WASM 路线在协议层降温,同区块跑两种虚拟机这个第一动力随之消失。更根本的阻力是复杂度:每个客户端都要在执行引擎里并行维护两套甚至多套规则,硬分叉审查从验证一套改动变成验证一张版本组合矩阵,测试负担成倍膨胀。而且它未必对付得了最危险的情形——提案自己也承认,面对网络攻击触发的紧急硬分叉,版本化框架能不能兜住需要个案评估,届时直接全网统一改规则可能反而是更安全的选择。

对照现实的分叉策略

以太坊实际走的路线,可以参考 硬分叉是什么?与软分叉、升级有何区别 里对硬分叉的定义:所有节点在约定高度切换到同一套新规则,兼容性靠改动本身足够保守来保证。历次升级都遵循这个纪律:行为变更尽量做成对存量合约透明,确需破坏性的改动则用多年的预告、客户端审计和测试网演练来铺垫。换句话说,社区选择把兼容成本一次性付在流程里,而不是永久背在每条账户状态里。1702 提供的是相反方向的权衡:账户级别的隔离保证,换取协议永久携带版本分支的复杂度。两条路没有绝对对错,只有把风险放在流程端还是状态端的取舍。

对钱包用户的用处

这条老提案对日常最有价值的一句话是:主网升级影响所有地址,不存在我的老合约还停在旧虚拟机上所以免疫这类安全叙事。看到某代币因为链未升级而不受漏洞影响的说法,先分清它讲的是合约代码自己有没有用到出问题的功能,而不是协议还停留在旧版本——前者成立,后者在以太坊上从来不成立。反过来也一样有用:合约的可升级指的是项目方部署了代理结构、可以换实现地址,那是应用层的工程选择,跟协议版本化完全是两码事。把协议升级和合约升级混在一句话里讲的项目公告,值得多追问几句它到底改了什么、谁有权改。

小结

EIP-1702 是一个体面失败的想法:设计自洽、动机真实,但整个生态最终选择了用流程买兼容、用工程买升级,而不是在状态里长出一个永久版本号。读懂它,你对以太坊升级为什么总是全网一刀切的直觉会完整一块,也会记住这条隐含纪律:能保持全局一致的,绝不轻易做成局部特殊。