Output Descriptor 是一份文本描述,说明钱包应使用哪些密钥、遵循哪些规则来构造 Bitcoin 输出,也就是记录金额及其今后花费条件的数据。它有助于重建正确的地址并识别相关付款。它本身既不是交易,也不是完整备份;内容可能只有公开数据,也可能包含秘密密钥。
安娜想换一个应用来查看自己的硬件钱包。她希望把查看资金的功能迁过去,而不用在电脑上输入恢复词。这些恢复词称为 Seed Phrase,是一份可以用来恢复钱包密钥的备份。公开的 descriptor 会告诉新应用,该用哪些公钥,以及怎样生成相同的地址。可以把它理解为一份精确的地址构造说明,而不是又一个密码。对于常见钱包,软件往往能自行识别标准设置;但遇到特殊配置或 Multisig(使用多把签名密钥的钱包配置),就不能只靠猜测。Descriptor 不会转移资金,也不会改变已经收到的付款。它记录的是恢复时必须保留的规则。 [1] [8]
私钥可以生成授权花费资金的数字签名。公钥能验证这种签名,却不能生成它。公开的 descriptor 可能包含 xpub,也就是能够派生更多公钥、却不能用来签名的数据。它适用于 Watch-only Wallet:这种钱包可以查看付款,但不能自行发送。不过,为了保护隐私,你仍应妥善保管这份导出,因为它可能把许多地址及其历史联系起来。另一份 descriptor 则可能包含扩展私钥 xprv,或单个私钥的编码 WIF。这些就是秘密资料,可能让持有者在满足相应条件时花费资金。不要把它们提交到在线检查网站,也别当成无关紧要的笔记保存。公开配置不能替代签名所需的备份。 [1] [8]
导入后,安娜先将几个收款地址与原钱包进行比较。使用硬件钱包时,她按厂商的流程,在可信的设备屏幕上核对地址。她也检查找零分支的配置,即付款时接收未花完余额的那一部分。账户名称一样并不够。在依赖新备份之前,她按照自己钱包的流程验证完整恢复过程,同时避免不必要地暴露秘密密钥。如果应用不支持该 descriptor,或显示的地址不同,应先检查兼容性、网络和设置。凭感觉修改一个不熟悉的复杂表达式,不是安全的修复方法。 [5] [8]
对于需要三把密钥中两份签名的钱包,仅有两组恢复词,再记得“三把密钥中要有两把签名”,还不够。要重建正确的花费条件,需要全部三把密钥的公开数据、各自的派生规则,以及准确的脚本类型。脚本写明了花费资金必须满足的条件。技术表达式 multi(k,...) 使用所列的密钥顺序,k 是所需签名数量。sortedmulti(k,...) 则在构造每个脚本时,按字节顺序排列派生出的公钥。这是两套不同规则,不是可以互换的名称。因此,要保留完整的配置导出,并另行保护签名所需密钥的备份。只有设备名称清单是不够的。 [2] [8]
字符 # 后面可以跟八个字符,称为 BIP380 定义的 checksum,也就是校验和。软件用它发现许多复制错误。但它不是作者签名,不是加密,也不能证明 descriptor 属于你。故意换入自己密钥的人,同样能计算出一个新的正确校验和。因此,检查文本还要配合核对地址和配置来源。如果应用报告校验和错误,应该先重新取得原始导出。直接生成新校验和,可能只是让已经损坏的文本也能通过校验。 [1]
密钥前面可能有 [fingerprint/path],称为 key origin,即密钥来源信息。Fingerprint 是起始密钥的简短标识;path 记录后面那把密钥是沿什么路径派生的。这能帮助签名设备找到正确密钥。xpub 后面还可能有另一段路径,用于派生各个地址。这两部分用途不同,并不只是账户标签。不同密钥可能碰巧具有相同 fingerprint,所以它不能验证设备身份。公开导出也无法随意继续跨过 Hardened Derivation:这种派生步骤需要私有数据,因此导出应用必须选择合适的密钥层级。 [1]
/* 中的星号表示依次代入数字,例如 0、1、2。这种 ranged descriptor 描述的不只是一个地址;执行具体操作时,软件会确定要处理的索引范围。如果应用支持,BIP389 的 <0;1> 写法可以包含两个分支,通常用于收款与找零。不过,descriptor 本身不会维护已用地址清单,也不记录下一个空闲编号。Gap limit,也就是连续发现多少个从未使用的地址后停止查找,同样不会自动成为表达式的一部分。从未使用指没有交易历史:曾经收款、后来资金已被花完的地址,不属于未使用地址。因此,恢复时可能还要转移钱包状态,并扫描足够宽的范围。 [5] [6] [9]
交易输出包含 scriptPubKey,即规定今后如何花费该输出的脚本。Descriptor 告诉软件怎样构造它。wpkh(KEY) 描述单密钥的 Native SegWit;这里的 KEY 是占位符,不是真实密钥。如果外面包上 sh,写成 sh(wpkh(KEY)),即使密钥没变,输出格式和地址也会改变。还有 pk()、pkh()、wsh()、addr()、raw() 等表达式,但它们并非可以互换的选项。例如 addr() 描述一个已知地址,却不会自动补上花费其资金所缺少的信息。这一节是配置参考,并不是要求新手手写 descriptor。 [1] [8]
Taproot 输出可以通过密钥签名花费;如果包含脚本条件,也可以按这些条件花费。tr(KEY) 指定一个内部密钥,不含可用于花费的脚本分支;tr(KEY,TREE) 则加入脚本树。因此,需要保留的不只是密钥清单。脚本在树中如何分组也很重要:改变分组,可能改变它们汇总后的哈希 Merkle root,以及最终地址,即使各条条件都未改变。不过,并不是每次交换分支都会改变结果。Miniscript 帮助描述和分析条件,multi_a 则在 Taproot 的脚本语言 Tapscript 中表达多签名要求。两者本身都不能替代完整的配置导出。 [3] [8]
RPC 是一个接口,可让其他程序或命令行向软件发送指令。在 Bitcoin Core 29 中,RPC 命令 getdescriptorinfo 会解析描述,返回不含私钥的公开形式,以及 checksum、isrange、issolvable、hasprivatekeys 等字段。最后一项说明输入是否含有私钥;issolvable 并不表示你拥有签名所需的秘密密钥。deriveaddresses 可用于比较派生出的地址。导入时,importdescriptors 还接受 timestamp、active、internal、range、next_index,分别用于指定查找历史的起始时间、配置是否启用、是否为内部找零、索引范围及下一个地址编号。Rescan 指重新在链上查找交易。timestamp 设得太晚,可能漏掉早期付款;单纯改变 descriptor 不会把这些付款移走或删除。导入后需要重新备份钱包。这些命令应在你自己可信的安装环境中使用,而不是填进陌生网站的表单。 [5] [7] [8]
要获得更完整的理解,请将本词条与以下词条结合阅读: 钱包, Watch-only Wallet, Multisig, PSBT, Miniscript, Bitcoin. 反向关联还来自: Watch-only Wallet, Extended Public Key (xpub), PSBT, 自主托管.