以太坊共识层用 SSZ(简单序列化)编码区块、状态和消息。这套格式的设计哲学是”解码零逻辑”:结构与字节一一对应,长度可预先推算,验证代价极低。但它的类型清单里一直没有一个像样的”可选值”——表示”这里也许有东西,也许没有”要靠各家巧劲。EIP-6475 在 2023 年 2 月提出给 SSZ 加一个 Optional[T] 类型,目前状态为 Stagnant。它解决的问题很小,暴露的取舍很典型。
没有Optional的世界怎么凑合
土办法至少有三种。一种是用全零值当”不存在”的哨兵,但这要求真实值恰好永远避开那个特殊编码——对一个地址或根哈希来说,你无法排除某个合法值真的就是全零。第二种是把可选字段包成长度为零或一的列表,借用 List[T, 1] 的变长特性表达有无,语义正确但读起来别扭,且在多数语言里映射成列表而不是可空类型。第三种是在外层加一个并行的位图,把存在性信息挪到别处维护,字段一多就成了双份账本。三种办法各有一片使用现场,跨实现互操作时,“对方眼里的零是零还是没有”就成了经典事故源。

三条规则:序列化、反序列化、默克尔化
EIP-6475 的方案把规则压到最少。类型定义上,Optional[T] 取值要么是 T 的一个值,要么是表示缺失的 None,默认值即 None。序列化只有一条分支:值为空时输出零字节;有值时输出一个 0x01 字节,后接 T 的常规序列化结果。反序列化靠输入长度做判断:长度为零即 None;否则第一个字节必须是 0x01,余下部分按 T 解。默克尔化则把它定义为长度上限为 1 的列表 List[T, 1]:值为空时列表长度记 0,有值时长度记 1 并以 T 的默克尔根填充。借助既有的列表承诺机制,可选字段在容器承诺里的位置与证明路径都不需要新发明。
一个字节换什么
用一个前导字节标记存在性,代价是有值时多 1 字节,收益是编码自描述:不需要外部位图、不占用值域、不要求字段可取值受限。对哈希类字段(32 字节的根)来说,0x01 + 32字节 与 32 字节的定长形态在字节层面清晰可分,解码器一行长度判断就能分派。反对意见集中在”列表包装已经够用,加类型是重复建设”,这也是它长期停在 Stagnant 的原因之一——共识层的每个新类型都要全体客户端实现、审计、测试,收益不够大就排不进升级清单。
与相邻概念的区分
不要把这份 EIP 与 SSZ 整体的路线图混谈:SSZ 本身早已是信标链的执行标准,而 Optional[T] 只是给这份标准打的类型补丁;也不要与渐进容器(EIP-7495)等前向兼容类型混为一谈,它们服务的问题不同——一个是”有没有”,一个是”将来的字段会不会改变容器形状”。引用这类提案时写清楚编号与当前状态是基本礼貌,草案与已部署的行为差异在链上就是真金白银的分歧。
本文为编码格式的技术说明,不构成投资建议;该提案是否进入未来某个网络升级,以官方升级清单为准。
从提案视角看格式演进
格式标准的演化史里,这类”小补丁提案”命运最分化:有的像可空类型一样最终长进正文,有的永远停在提案区,原因是后来者找到更通用的解法。Optional[T] 的处境属于后一种苗头——渐进容器一类的机制让字段可以整体随版本增减,单独为”可选”造类型的紧迫性下降。但注意两种叙事都不要走极端:不能因为提案停滞就断言”SSZ 不支持可选语义”,包装成长度上限为 1 的列表始终是可用的正规做法;也不能因为它有代码参考就当成已生效规范,在共识关键路径上,未进入升级清单的提案文本没有任何实施义务。判断任何 SSZ 相关特性的现实状态,看的是对应客户端仓库里有没有对应的序列化实现和升级清单里有没有对应的分叉开关,两者都缺位时,一切以提案编号加状态的完整标注呈现才诚实。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。