协议演进 / BIP/比特币改进提案 / BIP-389
BIP-389
给描述符密钥表达式加多路径写法 <0;1>:用一份描述符同时表示收款与找零两套几乎相同的描述符。本 BIP 目前处于草案状态。
一、档案卡
| 编号 | BIP-389 |
|---|---|
| 标题 | Multipath Descriptor Key Expressions |
| 作者 | Ava Chow <[email protected]> |
| 指定日期 | 2022-07-26 |
| 层级 | Applications(应用) |
| 类型 | Specification(规范类) |
| 状态 | Draft(草案) |
| 依赖 | BIP-380 |
| 阅读版 | https://bips.dev/389 |
| 官方原文 | https://github.com/bitcoin/bips/blob/master/bip-0389.mediawiki |
二、放在哪一族
输出脚本描述符族的一个语法扩展,不新增脚本表达式,只改 BIP-380 里“密钥表达式”的写法。
BIP-380:描述符通用操作,密钥表达式的原定义出自这里,本篇依赖并修改它
BIP-381 至 BIP-387:各类脚本表达式——凡用到扩展密钥派生路径的地方,都可以套用本篇的多路径写法
BIP-388:钱包策略——它的 /** 就是本篇 <0;1> 的双路特例,但那边严格限定只能有两个选项
BIP-32:分层确定性钱包——多路径里的每个数值,本质上是 BIP-32 的一步派生索引
原文还点名与 BIP-88(分层确定性路径模板)的思路作对比:那类方案允许在单个路径元素里放多个派生索引;本篇刻意收紧限制,理由见第四节。
三、它要解决什么
描述符能描述一个钱包所监视的脚本集合,但钱包通常至少需要两份描述符:一份生成收款地址,一份生成找零地址。
这两份描述符往往极其相似:产出的脚本类型相同、源自主密钥相同、派生路径几乎逐字一致,唯一的差别只是路径中某一步的数值不同——收款走 0、找零走 1 是最典型的情形。
维护两份近乎重复的文本,既啰嗦又容易出错:改一处忘了改另一处,两份描述符就会悄悄不一致。原文的解法是给密钥表达式加一种记法:在那一步派生上写出一组候选值,让一份描述符同时代表展开后的多份描述符。备份、导入、导出时只需处理一份,钱包内部再按位置展开使用。
四、规则本身
4.1 多路径元素
在扩展密钥(xpub 或 xprv)之后的派生路径中,可以出现至多一个多路径元素,形如:
<NUM;NUM;...;NUM>
每个 NUM 是一步 BIP-32 派生索引,后面可以跟 h 或 ' 表示硬化派生。多路径元素可以出现在路径的中间:它之前、之后都还可以再接普通的 /NUM 步骤,路径末尾照例可以接 /* 表示全部直接子密钥。
按 BIP-380 的原定义,路径元素只有 /NUM、/NUMh 与末尾的 /* 等形式;本篇把定义改写为允许在其中插入恰好一个这样的元组元素。
4.2 如何展开
遇到 <NUM;NUM;...;NUM> 时,解析器应视为同时存在多份描述符:第一份取元组中的第一个 NUM,第二份取第二个,依次类推,直到每个值都被用上。这一展开同时适用于公钥、脚本与地址的产生,以及描述符的导入与导出操作。
最常见的用法是表示收款与找零:元素通常写作 <0;1>。按此用法的约定,钱包应以展开后的第一份描述符生成收款地址、第二份生成找零地址。
4.3 三条硬性限制
- 每个密钥表达式只许有一个多路径说明符:出现两个(如
/<0;1>/<2;3>)无效; - 各密钥表达式的元组长度必须完全相同:同一描述符里若有多个密钥表达式带多路径,它们的元组必须等长,以便像
/*路径那样同步(lockstep)派生;长度不一致无效; - 元组内数值不得重复,且多路径说明符不得出现在密钥来源信息(origin)里,空元组
<>、缺尖括号、缺数值等写法全部无效。
元组长度并不限于 2:测试向量中也有 <0;1;2>、<1;2;3> 这类三元组,展开为三份描述符。限定两个选项的是 BIP-388 的钱包策略,不是本篇。
4.4 向后兼容
本篇是对 BIP-380 密钥表达式的增补:不带多路径的旧写法完全兼容,支持本篇的解析器照样能读;但旧解析器读不了带多路径的新描述符。新用到的两个字符 < 与 ; 本就在描述符字符集内、受校验和算法覆盖,此前未被使用,旧解析器不会把它们误认作别的东西。
与 BIP-88 一类方案相比,本篇限制更严,原文给出的理由是:减少展开出的描述符数量、避免展开方式上的含混、避免产生用户预期之外的描述符。参考实现见原文所引的 Bitcoin Core PR #22838。
五、谁必须动
普通持币人:无直接动作。在钱包备份或导出文本里看到 <0;1> 时,知道它表示“同一路径在此分出收款与找零两支”即可;只用支持本写法的钱包导入这类描述符。
钱包开发者:要支持这种简写,必须实现展开逻辑:导入时按元组位置拆成多份描述符,产生地址时严格同序使用(第一份收款、第二份找零),多密钥场景校验元组等长,并拒绝重复数值、多个说明符等无效写法。不支持的钱包应明确报错,而不是把 <0;1> 当普通路径误读。
全节点与矿工、共识层:无须改动。展开后的每一份描述符产出的都是普通脚本与地址,链上无从区分资金来自单路径还是多路径描述符。
六、现在算不算数,以及一个常见误读
状态为 Draft(草案):规范已经写成并附有完整测试向量与参考实现引用,但状态尚未推进。在描述符生态里它属于“写法约定”层面的提案——算不算数,取决于钱包是否实现同一套展开规则;在用它备份钱包之前,应先确认目标钱包确实支持多路径描述符,否则恢复时会读不懂。
常见误读:
“<0;1> 是 BIP-32 派生路径本身的新语法,节点也要跟着认。”
不对。多路径只是描述符文本层面的简写记法,不是 BIP-32 路径、更不是共识或网络协议的一部分。钱包在内部先把一份描述符展开成多份普通描述符,之后每一步派生、每个脚本都与旧写法完全相同;全节点既看不到、也不需要认识 <0;1>。
七、延伸
- 阅读版:https://bips.dev/389
- 官方原文:https://github.com/bitcoin/bips/blob/master/bip-0389.mediawiki
- 相关:BIP-380 描述符通用操作、BIP-388 钱包策略、BIP-32 分层确定性钱包、BIP-88 路径模板
- 仓库总目录:https://github.com/bitcoin/bips
