EIP-3076 罚保交换格式:换验证者客户端时签名历史怎么搬 图 1
EIP-3076 罚保交换格式:换验证者客户端时签名历史怎么搬 · 图 1

为什么罚保数据必须能搬家

以太坊验证者的安全底线之一是“绝不签名两条冲突信息”:同一时隙签两个区块、或在重叠的见证轮次里对两条分叉投票,都可能触发罚没。各验证者客户端为此维护本地罚保数据库,记录这把密钥签过的每一笔区块与见证。问题出现在换客户端的时候:如果新客户端不知道旧客户端签到了哪个时隙、哪个轮次,它就可能把一把“有历史”的密钥当成全新的用,在旧实例还活着或历史水位未知时签下冲突消息。EIP-3076 给出的答案是一个 JSON 交换格式:把签过的区块与见证打包成文件,让罚保数据跨客户端携带。EIP 页面当前标注的状态是 Last Call,创建于 2020 年 10 月,页面自注的 Last Call 截止标注为 2021 年 11 月;落地程度请以各客户端当前文档为准。

什么时候必须动这份文件

配图 三类场景绕不开它:一是主动换客户端软件,把验证者从一套实现迁到另一套;二是更换或升级托管环境,比如从家用机器迁到机房、重建虚拟机,即使软件不变,只要旧环境不再回滚,也应导出导入明确交接;三是应急接管,主站故障后由备份站顶上时,交换文件是唯一能让备份端“知道历史”的凭据。反过来,纯粹重启同一台机器、同一套软件并不需要动这份文件——罚保库还在原地,多此一举的导入导出反而制造了操作窗口。判断标准很简单:只要“签名权的持有者”发生了更换或重建,就应当走一次正式的导出导入,而不是靠回忆。

文件里有什么

按规范里的 JSON Schema,交换文件分两块。metadata 记录交换格式版本与创世验证者根;创世根把文件钉死在一条链上,防止主网文件被挪去用于另一个分叉。data 是数组,每个元素对应一把验证者公钥,含三组必填内容:公钥本身、signed_blocks 与 signed_attestations。前者记录签过区块的时隙号与签名根;后者记录见证的来源轮次、目标轮次与签名根,槽位与轮次用十进制字符串,签名根是零 x 前缀的十六进制。看懂这些字段就够用了:导入方真正关心的是“这把密钥的时间线推到哪了”,工程上称低水位线——低于水位线的签名会被拒绝,避免倒回去签旧消息。

迁移时的实操边界

以 Lighthouse 官方文档为例:它支持按 EIP-3076 格式导入导出,罚保库是验证者客户端数据目录下的 SQLite 文件;文档说明自 1.6.0 版起,导入时会忽略文件里的可罚没数据并安全抬高水位线,对每把密钥只保留最大时隙的区块与最大来源/目标轮次的见证。这类行为差异正是实操要点:不要假设各客户端对同一个文件的处理完全一致。稳妥顺序是:确认当前版本对导入导出的描述,在停机窗口内让旧端彻底停止签名,导出文件,在新端导入并核对,新端确认接管后再撤掉旧端;任何一步没确认,都保持旧端与新端不同时持钥。最危险的场景不是换软件本身,而是双实例并存:两个进程各自记各自的账,单机罚保库救不了互不知晓的对手。

故障排查:三个高频现场

第一类:导入后新客户端拒绝签名并报“低于水位线”。这不是文件坏了,而是保护生效——说明这把密钥的历史时间线高于请求签名的位置,正确动作是检查是不是旧端还在继续签名,而不是强行改库或降版本。第二类:导入工具报错、字段不认识。多半是版本字段或创世根不匹配,检查文件里 metadata 的格式版本与创世验证者根是否属于当前网络;跨网络的文件必须拒绝。第三类:迁移后某一时隙漏签。静默几分钟再确认接管方身份,比“赶紧重启另一边试试”更安全——任何一次“两边都跑一下看看谁在签”的操作,本身就制造了冲突窗口。还有一个常见误区:把多个客户端的导出文件简单合并。交换格式没有规定合并语义,正确做法是按最保守的历史水位逐把密钥人工核对。另需分清:罚保交换文件不是密钥备份,私钥的保管是另一套纪律;端到端的运行要求另有专文;如何运行以太坊验证者?硬件要求与质押方式。本文为机制与操作边界说明,不构成任何投资建议。