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

BIP-384 combo() 输出脚本描述符

定义 combo() 输出脚本描述符表达式,用一个密钥一次生成 P2PK 与 P2PKH 脚本,钥匙带压缩公钥时再同时生成 P2WPKH 与 P2SH-P2WPKH 脚本。本 BIP 目前处于已部署状态。

一、档案卡

档案卡
编号BIP-384
标题combo() Output Script Descriptors
作者Pieter Wuille <[email protected]>, Ava Chow <[email protected]>
指定日期2021-06-27
层级Applications(应用)
类型Specification(规范类)
状态Deployed(已部署)
依赖BIP-380
阅读版https://bips.dev/384
官方原文https://github.com/bitcoin/bips/blob/master/bip-0384.mediawiki

二、放在哪一族

输出脚本描述符族中的“打包”一员。通用语法、校验和与密钥表达式都在 BIP-380,本 BIP 在档案上依赖它,只新增一个顶层表达式。

它不定义任何新脚本,而是把同族其他篇的表达式按一把钥匙打包:

BIP-381:pk() 给出 P2PK,pkh() 给出 P2PKH

BIP-382:wpkh() 给出 P2WPKH,sh(wpkh()) 组合给出 P2SH-P2WPKH

BIP-384(本篇):combo(KEY) 一次把上面两到四种脚本全部生成,省去逐个写的四行描述符

与它相邻的是 BIP-385 的 raw() 与 addr()——同样是顶层表达式,但那两个面向原始脚本与既有地址,与本篇的“一钥多格式”用途不同。

三、它要解决什么

原文的动机很明确:为了让传统“以钥匙为中心”的钱包更容易过渡到以描述符为中心的钱包,最好能拿一把钥匙,直接生成传统钱包软件过去通常会生成的那一整套脚本。

传统钱包的逻辑是先有一把钥匙,再由软件决定用它做几种地址。描述符的逻辑正相反:先写明脚本表达式,钥匙只是参数。两边在迁移时对不上——用户手里只有钥匙与旧地址,却不知该写哪几行描述符,才能让新钱包监视到旧钱包用过的全部输出。

combo() 就是这座桥:把一把钥匙放进去,传统上会由它派生的几种脚本一次性全列出来。新钱包导入这一个描述符,就能同时认出这把钥匙名下的老格式与 SegWit 格式输出,不必逐种猜测、逐行补写。

四、规则本身

4.1 定义与位置

新增一个顶层脚本表达式 combo(KEY)。它只能作顶层表达式使用,不能放进 sh()、wsh() 等其他表达式里;它的参数只能是一个密钥表达式(写法见 BIP-380),不能放脚本表达式。原文把 sh(combo(...))、wsh(combo(...)) 与 combo(pkh(...)) 都列为无效描述符。

与族内其他表达式“一式一脚本”不同,combo() 是“一式多脚本”:一个描述符对应两到四个输出脚本,钱包要把它们全部纳入监视范围。

4.2 生成哪几个脚本

规则分两档,取决于钥匙是否带压缩公钥:

因此:压缩公钥的钥匙得四个脚本,非压缩公钥的钥匙只得前两个。原因与 BIP-382 的限制同源——SegWit 的 wpkh() 只接受压缩公钥,非压缩钥匙在那一档下无脚本可生成,combo() 只能跳过,而不是报错。

4.3 与扩展钥匙配合

参数可以是带派生路径的扩展钥匙。此时每个子索引都按上述规则成套生成:原文测试向量中,带 /* 的扩展私钥在子索引 0 与 1 下,各生成 P2PK、P2PKH、P2WPKH、P2SH-P2WPKH 四个脚本。钱包据此按索引成批监视,而不是只盯住某一个地址。

五、谁必须动

普通持币人:无直接变化。把老钱包的钥匙迁入支持描述符的钱包时,一个 combo() 描述符即可覆盖旧软件用过的几种收款格式,减少漏监视的风险。

钱包开发者:实现描述符时需支持 combo() 这一顶层表达式,展开为两到四个脚本并全部纳入监视;须按钥匙是否带压缩公钥决定是否生成 SegWit 两项,不得对非压缩钥匙强行生成 wpkh() 类脚本;并拒绝把 combo() 嵌进其他表达式的写法。

全节点与矿工:无须改动。它生成的每一种脚本都是既有的标准脚本,共识规则不变。

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

状态为 Deployed(已部署)。原文记载:combo() 描述符自 Bitcoin Core 0.17 起已有实现。它采用 BIP-380 的格式与通用操作;原文称其为全新描述符、与此前任何实现并不兼容,但生成的脚本都是标准脚本,既有软件对这些脚本本身并不陌生。

它的定位是过渡工具:新设计的钱包通常应直接用 pk()、pkh()、wpkh() 等表达式写明自己真正要用的那一种格式;combo() 的价值在导入与兼容——把历史上一把钥匙撒出去的几种格式一次收齐。

常见误读:

“combo() 对任何钥匙都固定生成四个脚本。”

不对。原文写明生成的是 2 个或 4 个,取决于钥匙:P2PK 与 P2PKH 始终有;只有钥匙是或带有压缩公钥时,才再加 P2WPKH 与 P2SH-P2WPKH。拿非压缩公钥去核对,只找到两个脚本不是实现出错,而是规范本身如此。

七、延伸

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