以太坊质押里,同一笔钱、同一个验证者索引,可以合法地签出至少六种完全不同的东西:提议区块、出验证、声明随机数、自愿退出、聚合投票、以及为进入某个委员会出具资格证明。它们是六种不同”用途”的签名,绝不能互相挪用。把这笔隔离做扎实的是两层设计:签名域(domain)与域名分隔的签名根(signing root)。理解它们,比理解任何一条 EIP 都更能说明”为什么一个签名不能被搬到别处用”。
域是什么:给签名盖一个用途章
共识层规定每个验证者消息都必须在一个 32 字节的”域”下签名。这个域由两部分拼成:前 4 字节是用途编号,后 28 字节是”分叉数据根”的前 28 字节。用途编号一眼可读:提议区块、出验证、随机数、存款、自愿退出、资格证明、聚合投票各有专属编号。分叉数据根则由当前分叉版本和创世验证者根哈希而来,作用是把签名钉死在特定链和特定分叉上。两部分拼起来就回答了”谁、在哪条链、哪个分叉、为做什么而签”。
签名根:两层哈希的封装

有了域,还要决定”签什么”。共识层不直接签对象本身,而是算一个签名根:把对象的 SSZ 哈希根和域一起塞进一个叫 SigningData 的小容器,再对这个容器取一次哈希根。这一层封装保证了:即使两个对象的内容字节相同,只要用途或分叉不同,签名根必然不同。存款消息是唯一的例外——它使用固定的创世域,原因是签名发生在验证者进入活跃集之前。
分叉切换怎么办
域里那 28 字节随分叉版本而变,于是分叉那一刻出现了过渡窗口。规范的处理方式是:签名所用的分叉版本取决于消息所属的纪元。若该纪元早于当前分叉纪元,用分叉前的版本号;否则用分叉后的版本号。验证者客户端在分叉前后重启不需要重新注册密钥,因为它们签的仍是同一个域家族,只是域里的版本字节换了。这解释了一个常见运维现象:升级时客户端日志会打印分叉版本号变化,而不是密钥变动。
为什么要这么麻烦
如果没有域,一个”提议区块”的签名在字节层面可能同时是一个合法的”自愿退出”签名——只要攻击者能构造出内容重合的对象,就能拿你无心的一次签名完成一次自杀式退出或跨用途挪用。加上分叉数据根之后,签名还被钉在创世根上:一条分叉链即使复制了全部验证者密钥,也无法让旧链上的签名在它这边合法生效。这正是以太坊主网与各类测试网、以及硬分叉后旧链的签名彼此隔离的原因。同一套思路也体现在网络层:节点之间的对等发现使用 4 字节的分叉摘要,它同样从当前分叉版本与创世信息派生,版本对不上的节点在握手阶段就被过滤,进不了同一条 gossip 网络。签名域管”签的内容不被串用”,分叉摘要管”说话的人不串链”,两者共用同一份分叉数据。
工程含义
运行验证者时要注意三件事。其一,域和签名根由共识层定义,验证者客户端必须与网络分叉版本严格匹配,跨分叉混跑会表现为大面积签名校验失败而不是密钥错误。其二,多链或多分叉运维时,隔离靠的是创世根和分叉版本,运维配置必须确保不会把同一把 BLS 密钥同时接入两条创世根相同的链。其三,读到链上或工具里的 4 字节用途编号,可以对照规范里的 DOMAIN_* 表逐一识别,这对读日志与排障非常直接。规范与客户端实现可能随升级调整,以官方规范与所用客户端文档为准。本文只讲机制,不构成任何操作或投资建议。
发表评论
还没有评论,来说两句吧。
评论区为展示样式,提交不会被处理。