一把钥匙四种地址:combo() 描述符为什么是扫描老钱包的默认答案 图 1
一把钥匙四种地址:combo() 描述符为什么是扫描老钱包的默认答案 · 图 1

描述符钱包时代的第一个实际问题是:比特币地址格式换过三代(裸公钥、传统哈希、隔离见证包裹与原生隔离见证),一把老钥匙历史上同时在四种格式下收过款,一条描述符表达式怎么把这四种历史一次说全?答案就是 BIP-384 定义的 combo()——名字直译是”组合”,作用是一行表达式顶四行。它状态 Deployed(已部署),Bitcoin Core 从 0.17 起支持。想先补描述符基础,读 ‘比特币钱包描述符是什么?’ 与语法篇 ‘BIP380输出描述符语法怎么读?‘。

产出规则:两样必出,两样看钥匙

combo 接收一个键表达式,只允许出现在顶层。它无条件产出两种脚本:把钥匙装进裸公钥脚本(P2PK)与装进公钥哈希脚本(P2PKH)——这等价于把同一个键分别写进 pk() 与 pkh() 两个表达式。接着看这把钥匙有没有压缩形式的公钥:有,就追加产出 P2WPKH 与 P2SH 包裹版(等价 wpkh() 与 sh(wpkh())),一共四种;只有非压缩公钥,就只出前两种。所以”一把钥匙四种地址”要说得严谨:取决于密钥形式,是二或四。

为什么它专门解决”老钱包搬家”

在钱包数据库换引擎、从密钥型钱包升级到描述符型钱包的那些年里,迁移工具最头疼的就是历史地址覆盖:只写 wpkh() 会漏掉十年前的 P2PKH 收款,只写 pkh() 看不见后来的隔离见证收款。combo 的存在让”导入一把不知道收过什么款的钥匙”有了偷懒但正确的写法——四种格式全扫一遍,宁多勿漏。Core 的扫描与恢复类命令接受 combo 作参数,正是为这个场景准备的。补新地址类型到现有钱包的增量做法见 ‘老钱包想收新地址:createwalletdescriptor 给现有钱包补一种地址类型’,与 combo 的全量思路正好互补。

读一条 combo 表达式的三个核对点

第一,顶层限制:combo 只能整条使用,不能套在 sh() 或 wsh() 里面,看到嵌套写法直接判定非法。第二,数量账:展开后每种脚本对应一整条独立地址链,扫描成本是单一格式的四倍——它用时间换完整性,适合盘点与恢复,不适合高频逐块查询的生产环境。第三,版本账:0.17 起就支持,但各家第三方钱包对 combo 的支持参差不齐,能否解析以本机工具的实际返回为准,不要按”Core 支持”推断所有软件支持。

一条常见误读:combo 不是”地址类型选择器”

有人把 combo 理解成”钱包设置里那四种地址类型的开关”,这是错的。combo 不出现在收款界面,也不决定钱包”下一把收什么地址”——它是描述符表达式层的产物,用途是穷举描述一把钥匙可能对应的脚本,主要服务于导入与扫描。钱包日常给你哪类地址,由钱包自己的策略决定。理解这条边界,才能明白为什么”用 combo 导入”和”以后一直用旧格式收款”是两件毫不相干的事:前者是历史检索,后者是未来的地址策略,前者做对与否不改变后者。

与 miniscript、multi_a 等表达式的分工

描述符家族里各表达式各管一段:combo 管”一把钥匙的全格式”,多签写法管”多把钥匙的策略”,miniscript 管”更复杂的条件”。combo 内部不含任何策略逻辑——它就是一条表达式四种壳。因此”用 combo 表达 2/3 多签”是不可能的任务,需要多签请走对应的多签表达式族。把表达式当句子读:函数名是动词,键表达式是宾语,嵌套是语法层级,combo 的语法身份是”句子的完整形态”,不是”可以嵌进句中的从句”。

实操场景示范

一个典型的用法序列:拿到一段十年前的 xpub 做资产盘点。第一步,用 combo 包上 xpub 加派生路径写成一条表达式;第二步,用本机描述符解析命令确认它能被拆成预期的四种脚本;第三步,交给扫描命令检索历史。盘点类命令与参数另文详述,本文只定 combo 的概念位置。收尾仍然要强调:表达式解析成功不代表地址找全了,扫描窗口设置不足导致的漏账是另一种独立故障,排查思路见 ‘钱包恢复时少了一串地址:派生路径、扫描窗口与找零导致的两种看不见’。两种故障叠加时,先修表达式再修窗口,顺序不要颠倒。