keystore 管钥匙,walletstore 管钱包:ERC-2386 的文件字段怎么读 图 1
keystore 管钥匙,walletstore 管钱包:ERC-2386 的文件字段怎么读 · 图 1

keystore 管钥匙,walletstore 管钱包:ERC-2386 的文件字段怎么读

用过以太坊签名工具的人多半见过 keystore JSON:一段加密的私钥,配密码派生参数。ERC-2386 创建于 2019 年 11 月 21 日,仓库记录状态为 Stagnant,它觉得这个抽象少了一层:对分层确定性钱包来说,真正的资产单元不是单把私钥,而是那粒种子和它派生出的整棵树。于是标准提出 walletstore——一个定义钱包本身及其造键规则的文件,概念上与定义密钥的 keystore 并列。

四个必备字段

文件是一个 JSON 对象。uuid 是按 RFC 4122 生成的 4 型随机 UUID,作为这个钱包的 128 位代理标识,工具之间引用“哪一个钱包”时用它在多个文件间对齐。version 是 walletstore 格式自身的版本号,非负整数。type 说明钱包类型,原文对 v1 只允许一个取值:字符串 hierarchical deterministic,即分层确定性钱包,它决定工具用什么方式生成密钥。crypto 是密钥材料的安全存储,对 HD 钱包来说就是那粒种子,加密结构沿用 EIP-2335 的 keystore 模块,钱包类型需要它时该字段必须存在。还有一个条件字段 nextaccount:整数,表示下一次创建新私钥时要填入派生路径的账号索引。

keystore 管钥匙,walletstore 管钱包:ERC-2386 的文件字段怎么读 图 2
keystore 管钥匙,walletstore 管钱包:ERC-2386 的文件字段怎么读 · 图 2

那个看似眼熟的派生路径

原文规定新私钥按 m/12381/60/索引/0 的路径派生,格式遵循 EIP-2334。这里的 12381 不是以太坊的.coin9 编号(60 才是以太坊在 SLIP-44 里的编号),它借用的是信标链验证者密钥的路径习惯——60 指以太坊账户空间,12381 指在这个空间下为质押身份单独开的一层。这个细节提醒读者:walletstore 从诞生起就带着多角色钱包的设想——同一粒种子,账户层和验证者层分开数。每创建一个新账户,nextaccount 加一;若文件在这之后没有更新,两个客户端就会从同一个索引重新派生,产生互相覆盖的地址窗口问题,这是 HD 钱包恢复时最经典的坑之一。

用 JSON 模式校验文件

标准附带 JSON Schema 用于机器校验:字段齐不齐、类型对不对,工具可以本地跑一遍而不必信任软件展示。对恢复场景,模式里最关键的约束是 type 必须精确等于分层确定性声明、nextaccount 必须为非负整数这两条——前者防止文件被当成别的钱包类型误用,后者防止索引被负数或空值悄悄污染。标准还给出测试向量:同样的字段输入应当得到可复算的派生结果,钱包软件读到 walletstore 后先跑向量,再生成地址,这一步能把实现偏差挡在导入私钥之前。

它没有处理的部分

walletstore 定义钱包,但没有定义钱包的安全边界。crypto 字段沿用 keystore 的加密结构,强度取决于用户密码的熵,标准不评估也不背书任何派生参数组合;文件本身不含访问策略,谁能读文件谁就能尝试解密,与 keystore 同命。它也没有定义多文件钱包:一份 walletstore 对应一棵密钥树,跨设备的同步、并发派生的索引冲突处理全部留给实现。把这些空缺放在一起看,就能理解为什么标准停在 Stagnant:概念干净,但落地需要钱包厂商共同约定一套文件交换协议,而各家更愿意锁住自家格式。今天迁移钱包时最常见的事故——旧客户端没写回最新索引、新客户端从 0 重新扫描——正是这套协议缺失的代价。

现实中的读法

标准没有成为任何主流钱包的落盘格式,今天没有钱包用 walletstore 这个词。但它的四段式抽象——身份、版本、类型、密钥材料——在各类钱包备份格式里反复出现,只是字段名不同。拿到任何钱包定义文件时,按这四个问题检查:这个文件指向哪个钱包、格式版本能否被当前软件读懂、声明的派生方式与实际地址能否对上、下一次派生索引是否领先于所有已知客户端。最后一问的答案错了,丢的不是文件,是文件没算进去的那批地址。

本文为机制说明,不构成任何投资建议。