协议演进 / BIP/比特币改进提案 / BIP-388

BIP-388 描述符钱包的钱包策略

在描述符之上定义钱包策略:用 @0、@1 占位符加一份外置的密钥信息表,紧凑地表示一整个账户,让硬件签名器也能核对和注册。本 BIP 目前处于已完成状态。

一、档案卡

档案卡
编号BIP-388
标题Wallet Policies for Descriptor Wallets
作者Salvatore Ingala <[email protected]>
指定日期2023-12-26
讨论日期2022-05-10
层级Applications(应用)
类型Specification(规范类)
状态Complete(已完成)
阅读版https://bips.dev/388
官方原文https://github.com/bitcoin/bips/blob/master/bip-0388.mediawiki

二、放在哪一族

描述符族的上层应用:不是再添一种脚本表达式,而是把整套描述符改造成“账户级”的表示。

BIP-380:输出脚本描述符通用操作——钱包策略的语言与它刻意保持相似

BIP-389:多路径密钥表达式 <0;1>——钱包策略的 /** 正是它的双路特例

BIP-379:Miniscript——策略模板在 wsh()、tr() 里可以容纳 Miniscript 模板;注意原文特意澄清:钱包策略(wallet policies)与 Miniscript 的上层“策略语言”(policy language)不是一回事,后者是编译成 Miniscript 的高级语言

BIP-129:比特币安全多签设置(BSMS)——多方如何安全协调一个描述符钱包不在本篇范围,原文把读者指给它;注册流程解决的是其中“用户在签名器屏幕上核对花费条件”这一环

理解顺序是:描述符描述“一个输出脚本集合”,钱包策略描述“一个账户的全部收款与找零描述符”,并且要短到能在小屏幕上核对、能被内存有限的设备保存。

三、它要解决什么

软件钱包与硬件签名设备通常把资金按“账户”划分。签名或展示一笔交易时,受影响的各账户的资金流汇总应当展示给用户看。一个账户逻辑上包含整组收款地址与找零地址;钱包策略就是用一份紧凑、可核查的表示,把描述一个账户所需的全部描述符一次说清。

为什么不直接用描述符?原文指出,描述符是为通用计算机上的 Bitcoin Core 设计的通用灵活语言,与硬件签名设备的典型条件并不合拍:

而核对恰恰是安全的根基:与签名设备相连的电脑被视为不可信,攻击者可能完全控制它、篡改请求。设备必须保证:用户清楚知道资金受什么“策略”约束,找零确实回到同一策略之下,攻击者无法偷偷换掉策略来盗走或烧毁资金。复杂的 Miniscript 与 Taproot 树让屏幕核对更加困难;同一把扩展公钥在描述符里反复出现(一个 xpub 就有 118 字节),还会让描述符体积成倍膨胀——原文举例:一个 3-of-5 门限钱包配合 MuSig2 密钥路径与 11 片叶子的脚本树,描述符会大到无法人工审查。

解法是“策略注册”:新策略第一次使用前,用户在签名设备上注册它——软件钱包发起注册,设备在安全屏幕上展示策略,用户与可信来源(如纸质备份)比对后批准;有状态的设备把策略存入持久内存,无状态的设备返回一份“注册证明”(例如对策略哈希、名称等元数据做消息认证码)。此后生成地址、在屏幕上展示地址、签名并识别找零,都凭已注册的策略进行,无须每次重复昂贵的核对。本篇定的就是被注册的这份“策略”长什么样;注册流程的细节本身不在本篇范围内。

四、规则本身

4.1 总结构:模板 + 密钥信息表

一份钱包策略由两部分组成:

把冗长的 xpub 从模板里抽走、多处复用同一占位符,模板才短得可审查;把模板编译回描述符则是机械替换(见 4.4)。

4.2 模板中的密钥表达式

模板里的 KEY 由密钥占位符(KP)加上派生后缀构成,后缀永远是以下之一:

占位符(KP)或是一个密钥索引(KI):字符 @ 加一个无前导零的非负十进制数,如 @0、@1,@i 指密钥信息表中的第 i 项;或——仅在 tr() 内部——musig(KI_1,...,KI_n) 形式的聚合占位符(1.1.0 版加入)。

每个 KEY 表达式对应最终脚本里一把确定的公钥,因此 BIP-32 层级中的全部派生步都写在表达式里;而占位符本身只对应“该账户全部 UTXO 所用公钥的根”,占位符里不许再带派生步。

模板允许的脚本表达式包括 sh()、wsh()、pkh()、wpkh()、multi()、sortedmulti()、tr() 以及 wsh()/tr() 内的 Miniscript 模板,各自的位置限制与描述符一致。

4.3 附加规则

常见形态示例:单签账户 pkh(@0/**)、wpkh(@0/**)、sh(wpkh(@0/**))、tr(@0/**);多签如 wsh(multi(2,@0/**,@1/**));Taproot 密钥路径的 MuSig2 如 tr(musig(@0,@1)/**);更复杂的 Miniscript 与时间锁继承安排也可以写成模板。

4.4 从策略编译出描述符

由模板与密钥信息表得到对应的多路径描述符,只需两步替换:把每个占位符换成对应的密钥来源信息加 xpub;把每个 /** 换成 /<0;1>/*。反过来,把符合本篇模式的描述符拆回策略也容易,正因为这套语言刻意与描述符保持相似。原文提醒:实现可以只支持策略的一个子集,但限制应明确写清;另外,非标准单签、多签(尤其涉及外部共签人)场景下,种子本身已不足以重新发现有资金的策略,策略备份一旦丢失很可能永久丢币——备份策略与备份种子同样重要,而策略备份泄露只影响隐私、不直接丢币。

4.5 版本与实现

本文档版本 1.1.0(2024-11),该版为描述符模板加入了 musig 密钥占位符支持;1.0.0 于 2024-05-12 发布。原文列出的实现包括:Ledger 的比特币应用(2.1.0 起)、BitBox02 固件(v9.15.0 起)、Blockstream Jade(v1.0.24 起,经 libwally-core)、BTCPay Server(v2.1.1 起,仅支持单签与多签策略的有限子集)与 NBitcoin。采用完全自愿,软件钱包宜同时允许导出普通描述符,以便与不用钱包策略的软件互通。

五、谁必须动

普通持币人:使用硬件签名器时多了一步“注册策略并核对”:首次使用某账户前,在设备屏幕上逐项核对策略并与可信备份比对、批准注册;同时要像保管种子一样保管策略备份(两者缺一,复杂钱包可能无法恢复)。

钱包开发者(软件侧):要支持把账户表示为“模板 + 密钥信息表”、发起注册流程、按 4.4 编译出描述符,并为不用钱包策略的软件保留导出普通描述符的通道。

硬件签名设备开发者:要能解析这套受限语言、在小屏幕上紧凑展示、执行注册与注册证明校验,并凭已注册策略生成地址、识别找零、计算手续费;只能实现子集的,应明确声明范围。

全节点与矿工、共识层:无须改动。钱包策略展开后就是普通描述符与普通脚本,不涉及任何协议规则。

六、现在算不算数,以及一个常见误读

状态为 Complete(已完成):规范文本已经定稿,且原文列出了多个硬件与软件实现。它不改变任何共识或网络规则,“算数”体现在生态采用面上——签名设备与配套软件按同一格式注册、展示、校验策略,用户在不可信电脑前核对的那几行文本才有统一含义。

常见误读:

“钱包策略是一种新的脚本或新的地址类型。”

不对。它既不产生新脚本,也不产生新地址:策略只是把一整个账户的描述符换了一种紧凑表示——模板用 @i 占位、密钥信息外置成表。按 4.4 替换回去,得到的就是 BIP-389 意义下的普通多路径描述符,链上看到的输出与直接用描述符生成的毫无区别。

七、延伸

本页内容整理自 bitcoin/bips 仓库与 bips.dev,事实已与仓库核对;解读仅供学习参考。