本文介绍了如何使用 Bitcoin Core 软件恢复和使用 Nunchuk 软件钱包创建的 Miniscript 钱包。文章详细说明了两种恢复方法:基于硬件签名器的恢复和基于种子词的恢复,并提供了详细的操作步骤和注意事项,包括 Bitcoin Core 的安装、钱包配置文件的处理、PSBT 交易的创建、签名和广播等。
作者:Nunchuk

Nunchuk 软件钱包建立在公开的标准和可以互操作的数据格式上,这意味着,你使用 Nunchuk 软件建立的钱包总是可以在其它开源的比特币工具上复原出来,也包括在 Bitcoin Core 软件上。本指南解释了如何在 Bitcoin Core 中(使用它的 “描述符” 和 “ PSBT ” 特性)复原和花费一个 Miniscript 钱包(译者注:指在建立过程中使用了 Miniscript 编程语言的钱包;在创建完成后,这样的钱包的描述符将带有 Miniscript 代码)。
Bitcoin Core 从 V24 开始就添加了基础的 Miniscript 支持,允许复原在 Nunchuk 中建立的高级钱包策略,比如多签名和时间锁脚本。V29 以及更高的版本提升了 Miniscript 处理和描述符钱包,所以,本指南更推荐使用 V29 以及更高版本。
取决于你选择如何签名自己的交易,这里有两种复原方法:
基于硬件签名器的复原(推荐):使用你的硬件签名器来复原和安全签名交易。私钥绝不离开你的设备。
基于种子词的复原(仅使用软件):在 Bitcoin Core 中直接使用你的钱包种子词或者密钥备份。这需要获得你的钱包中的密钥的 xprv(拓展私钥)、用它替换掉你的钱包描述符中对应密钥的 xpub(拓展公钥)字符。出于安全性, 请仅在断网和空气隔离(air-gapped)的设备上操作。
编者注:此处的 “空气隔离” 应指与无任何与联网设备的连接,不论有线或无线。
“拓展公钥” 和 “拓展私钥” 并不是指的某一个 公钥/私钥,它是一种格式,用于描述一棵 BIP32 层级式确定性派生密钥树上的一个密钥。拓展 公钥/私钥 包含了这个 公钥/私钥 的许多信息,比如,它是如何派生出来的(派生路径)、它从哪里派生而来(根源密钥指纹),以及如何用它派生子密钥。
Nunchuk 中获得的钱包配置文件(“ BSMS ” 格式的文件或者描述符文本)Bitcoin Core 24.0 以上的版本(推荐 29.0 以上的版本)HWI(硬件钱包接口):要求允许 Bitcoin Core 与硬件签名器通信。详见《 HWI 安装指南》。要求总结
| 钱包类型 | 需要的材料 |
|---|---|
| 单签名钱包 | 一个种子词或者签名器 |
| 多签名钱包 | 能够满足钱包阈值要求数量的 种子词/签名器(比如,若要复原 2-of-3 多签名钱包,任意两个不同密钥的 种子词/签名器 就可满足要求) |
| Miniscript | 满足 Miniscript 花费要求数量的 种子词/签名器 |
Bitcoin Core 并同步比特币区块链先安装 Bitcoin Core 并确保你的节点已经完全同步了区块链,然后才能继续。
bitcoind -daemon
编者注:此为安装好
Bitcoin Core之后,在命令行环境中启动Bitcoin Core并要求后台运行的命令。在 Windows 系统中,可通过Terminal(终端)进入这样的命令行环境;但是,较老版本的Bitcoin Core在 Windows 系统中可能无法后台运行,为此,可直接输入以下命令,按下回车执行:bitcoind如果你不习惯命令行环境,也可以运行
Bitcoin Core的图形界面。在图形界面中,也可以使用 “控制台” 菜单来输入指南中提到的命令(无需前面的bitcoin-cli)。
用以下命令检查同步状态:
bitcoin-cli getblockchaininfo
编者注:如果以非后台模式运行,这意味着你需要打开一个新的命令行环境窗口来输入以上命令。
等待出现 "initialblockdownload": false 这样的字样(表示同步完成)。
如果你准备使用硬件签名器复原方法(建议),请跳到 “步骤 3 ” 。
如果你要执行仅使用软件的复原方法,你必须先获得跟你的钱包有关的密钥的托管私钥(xprv)。这是必要的,因为 Bitcoin Core 的描述符钱包并不直接支持 BIP-39 种子词;它需要拓展密钥(xpub 或者 xprv)。
安全警告:本节所述的流程会导致你的私钥暴露。强烈建议在一台断网而且空气隔离的电脑上执行。绝对不要在任何联网的工具上输入你的种子词或者私钥!
这个过程需要使用一种断网的派生工具,比如 Ian Coleman 的 BIP39 工具。请确保你下载和使用的是离线版本。
首先,观察你的钱包配置文件,找出你需要复原的密钥的派生路径。或者,在描述符内寻找密钥的来源信息。
例如:
[a3b12f34/48h/0h/0h/2h]xpub6DT5...
这样的文字,就表明这个拓展公钥(xpub)是由指纹为 a3b12f34 的主公钥经过 m/48'/0'/0'/2' 的派生路径派生出来的。
注意,字符 h 或者 ' 表明它用到了 “硬化的派生路径”;Ian Coleman 的 BIP39 工具仅支持使用硬化派生路径。(编者注:在 BIP-32 层级式确定性密钥派生方法中,常规派生可以仅使用父公钥来派生子公钥;但硬化派生路径则必须有父私钥的参与,才能派生硬化的子公钥)。
这一步骤的具体操作取决于你的备份形式:
标准的 BIP39 种子词
如果你还持有 12 词或者 24 词的种子词,它就可以作为你的根源密钥材料。
TAPSIGNER 备份
“ Tapsigner ”不使用 BIP39 种子词。你必须从备份文件中抽取出根源主私钥 xprv。
xprv... 字符串。要了解解密 Tapsigner 备份文件的详细指令,请看《 Tapsigner 新手指南》。
现在,使用离线的派生工具(比如前述的 Ian Coleman 的 BIP39 工具)来计算钱包具体用到的 xprv 子私钥。
m/48'/0'/0'/2')输入 “ BIP32 Derivation Path ” 输入框中。

打开你的 Nunchuk 钱包配置文件并找出你想要复原的钱包的描述符。
对于 Miniscript 钱包,Nunchuk 使用了 “多路径的描述符”(以 /<0;1>/* 结尾),这也是 Bitcoin Core 直接支持的形式。在这种形式下,单个描述符就同时涵盖了收款地址(0)和找零地址(1)。
描述符案例:
wsh(and_v(v:pkh([a3b12f34/84h/1h/0h]xpub6DT5.../<0;1>/*),older(1000)))#checksum
取决于你使用的复原方法,你要准备不同的事项:
xpub(拓展公钥)替换成你在 “步骤 2 ” 中得到的对应密钥的 xprv(拓展私钥)。 确保钱包来源信息(方括号中的部分,比如 [a3b12f34/84h/1h/0h])保持不变。只要你修改了描述符(例如,将 xpub 替换成了对应的 xprv),那么最初的描述符的校验码(checksum)就失效了。而在导入描述符的时候,Bitcoin Core 要求描述符的校验码是有效的。
使用 Bitcoin Core 为修改后的描述符计算新的校验码(例如):
bitcoin-cli getdescriptorinfo "wsh(and_v(v:pkh([a3b12f34/84h/1h/0h]xprvA1amWrohy…/<0;1>/*),older(1000)))"
结果是:
{
"descriptor": "wsh...",
"checksum": "#NEW_CHECKSUM",
"isrange": true,
"issolvable": true,
"hasprivatekeys": true
}
输出的 "checksum" 字段就包含了新的校验码。将这个新的校验码替换到修改后的描述符中。
带有新的校验码的修改后的描述符:
"wsh(and_v(v:pkh([a3b12f34/84h/1h/0h]xprvA1amWrohy…/<0;1>/*),older(1000)))#NEW_CHECKSUM"
使用准备好的描述符,向 Bitcoin Core 创建和导入你的钱包。首先,创建一个空的、基于描述符的钱包。
disable_private_keys=true):bitcoin-cli createwallet "my_recovered_wallet" true true "" false true
disable_private_keys=false)bitcoin-cli createwallet "my_recovered_wallet" false true "" false true
编者注:命令中以双引号包起来的部分
"my_recovered_wallet"是给这个新钱包的命名,可以自由修改。
输出是:
{
"name": "my_recovered_wallet",
"warning": "Empty string given as passphrase, wallet will not be encrypted.\nWallet is an experimental descriptor wallet"
}
然后,就导入钱包描述符。因为我们使用了一个带有范围的描述符(/<0;1>/*),所以只需要导入一次就够了。
bitcoin-cli -rpcwallet=my_recovered_wallet importdescriptors "[{\"desc\":\"WALLET_DESCRIPTOR_WITH_CHECKSUM\", \"timestamp\":\"now\", \"active\":true}]"
编者注:
"WALLET_DESCRIPTOR_WITH_CHECKSUM\"部分要替换成你在 “步骤 3 ” 中最终得到的描述符。
输出:
[\
{\
"success": true,\
"warnings": [\
"Not all private keys provided. Some wallet functionality may return unexpected errors"\
]\
}\
]
注:如果你导入的描述符还带有 xpub,比如你使用的是硬件签名器复原法,则出现 “ Not all private keys provided (并未提供钱包内所有密钥的私钥)” 的警告是意料之中的;但如果你导入的描述符只有 xprv,则应该不会出现这样的警告。
验证你的钱包已经正确导入,而且软件所生成的地址与你预期的一致:
bitcoin-cli -rpcwallet=my_recovered_wallet listdescriptors
bitcoin-cli -rpcwallet=my_recovered_wallet getbalance
bitcoin-cli -rpcwallet=my_recovered_wallet getnewaddress
编者注:
-rpcwallet=后面应使用你给钱包的命名。第一条命令是列出该钱包的描述符;第二条命令是了解该钱包的余额;第三条命令则是生成一个新的地址。
现在,你的钱包激活了,你可以创建一笔交易来花费资金了。
编者注:在确保你的钱包已经正确导入之后,也可以通过图形界面来加载钱包和使用它,这样更加简单,也更不容易出错。
bitcoin-cli -rpcwallet=my_recovered_wallet walletcreatefundedpsbt '[]' \
'{"bc1qdestinationaddress...":0.001}' 0 '{"fee_rate":2.0}'
输出:
{
"psbt": "cHNidP8BAH0CAAAAA...",
"fee": 0.00000324,
"changepos": 1
}
这就创建好了可以签名的 PSBT(在 "psbt" 字段中出现的字符串就是)。
如果你的 Miniscript 花费策略包含了时间锁条件,比如 older(n) 或者 after(n),在创建交易时,你必须满足这些条件。
绝对时间锁 —— after(n)(BIP-65)
绝对时间锁会阻止在某个 区块高度/时间点 到来之前的花费动作。你必须将交易的 locktime 字段设置为大于等于 n 的数值。
n < 500,000,000 ,这个时间锁会被解释为由区块高度定义。
after(840000) 表明资金只能在高度 840000 及以后的区块中花费。n ≥ 500,000,000,这个数值会被解释为一个 Unix 时间戳。
after(1893456000) 表明资金只能在 2030 年 1 月 1 日之后花费。如果要从带有绝对时间锁的路径中花费(例如,将交易的 lncoktime 设置为 1893542400 —— 2023 年 1 月 2 日的 0 时 0 分 0 秒,GTM+0 时间):
bitcoin-cli -rpcwallet=my_recovered_wallet walletcreatefundedpsbt '[]' \
'{"bc1qdestinationaddress...":0.001}' 1893542400 '{"fee_rate":2.0}'
你可以这样检查区块高度:
bitcoin-cli getblockcount
相对时间锁 —— older(n)(BIP-68)
相对时间锁会限制一个 UTXO 在到达特定年龄之前被花掉。所需的 n 必须在输入的 sequence 字段编码。
n 的含义也取决于其数值大小:
n < 0x40000000(十进制下是 1073741824),那就解释为区块数量。每 1 数字单位 = 1 个区块(而一个区块的生产时间大概是 10 分钟)。
older(1000) 就表示,一个 UTXO 必须在其得到区块确认(生成)之后,经过 1000 个区块(大约 1 周),才能花费。n ≥ 0x40000000,那就解释为时间长度。每 1 数字单位 = 512 秒(大约是 8.5 分钟)。
older(1073741854) 意味着一个 UTXO 在其诞生的 30 个时间单位之后才能花费(30 * 512 秒 ~= 4 小时 15 分钟)。若要花费带有相对时间锁的路径:
确保 UTXO 的年龄已经满足要求。
在创建 PSBT 时,在具体输入的 sequence 字段包含所需的 n。这需要手动指定输入。
bitcoin-cli -rpcwallet=my_recovered_wallet walletcreatefundedpsbt \
'[{"txid":"<txid>","vout":0,"sequence":n}]' \
'{"bc1qdestinationaddress...":0.001}' 0 '{"fee_rate":2.0}'
如果你太早尝试花费,这笔交易会被网络拒绝,故障码是这样的:
non-BIP68-final (code 64)
注:使用时间锁分支是可选的。只有你的钱包脚本(或者说你的 Miniscript 花费策略)要求的时候,才需要在创建交易时包含这些参数。
取决于你的复原方法:
选项 1:使用硬件签名器签名(推荐)
确保已经安装好了 HWI 。连接你的硬件签名器到运行 Bitcoin Core 的电脑。如果你的设备有 PIN 码或者口令,你可能需要先解锁设备。使用下列命令来列出所有已经连接且解锁的硬件签名器:
hwi enumerate
输出:
[{"type": "coldcard", "model": "coldcard", "label": null, "path": "1-4:1.3", "needs_pin_sent": false, "needs_passphrase_sent": false}]
注意:HWI 主要支持带有 USB 连接的硬件签名器。Tapsigner 使用 NFC,所以无法连接到 HWI 。如果你的签名条件依赖于一个 Tapsigner ,你可以 将 Tapsigner 的私钥导入一个 Coldcard 签名器,然后使用 Coldcard 连接 HWI 来签名。
Miniscript 登记和固件
有些硬件签名器会要求先在设备中登记 Miniscript 钱包,然后才能用来签名交易。此外,你可能需要升级签名设备的固件到支持 Miniscript 的版本。看看硬件制造商的手册吧。
案例:在 Coldcard (Mk4 Q) 签名器中登记一个 Miniscript 钱包
.txt 文件,然后复制这个文件到 microSD 卡。Settings > Miniscript > Import 。签名交易
在已经连接电脑的设备上签名 PSBT 。将以下命令中的 <device_type>(设备类型)替换成你在上文的 hwi enumerate 命令中得到结果(例如 coldcard、jade、ledger),将 <psbt_string> 替换成你在前面步骤中生成的 PSBT 。
hwi --device-type <device_type> signtx <psbt_string>
结果:
{
"psbt": "cHNidP8BAH0CAAAAAT+..."
}
如果你使用的是多签名钱包,或者多密钥的 Miniscript 花费条件,你就要重复上述步骤,直到攒够签名数量:每使用一个签名器完成签名(生成一个新的 PSBT),就将这个新的 PSBT 传递给下一个签名器。
注意:如果你无法按顺序签名(也即,每一个签名器都独立签名原始的 PSBT,而不是经过上一个签名器签名的 PSBT ),你可以将包含不同签名的 PSBT 都收集起来,使用下列命令合并成一个最终的 PSBT :
bitcoin-cli combinepsbt '["psbt1","psbt2"]'
选项 2:使用 Bitcoin Core 来签名(基于种子词的方法)
如果你向 Bitcoin Core 直接导入了私钥(xprv)(将下列命令中的 <psbt_string> 替换成你在一开始创建的 PSBT):
bitcoin-cli -rpcwallet=my_recovered_wallet walletprocesspsbt "<psbt_string>"
输出:
{
"psbt": "cHNidP8BAH0CAAAAAT+...",
"complete": true
}
一旦你的 PSBT 到了完成阶段("complete" 字段的数值是 true),你就可以敲定它并抽取出交易的十六进制形式:
bitcoin-cli -rpcwallet=my_recovered_wallet finalizepsbt "<signed_psbt>"
结果:
{
"hex": "02000000000101...",
"complete": true
}
最后,广播这个十六进制形式的交易(即上面结果 "hex" 字段的数值)到网络中:
bitcoin-cli sendrawtransaction "<raw_transaction_hex>"
输出(交易 ID):
b91276af8b6f5ede632aadfb87bf8a9209a43d0a030396cd0c4629a1ec92b87a
在确认复原成功、钱包中的资金都已经成功转出之后,应该安全地删除你的临时钱包和文件,尤其是你使用了基于种子词的复原方法的话。
首先,在 Bitcoin Core 中卸载钱包:
bitcoin-cli -rpcwallet=my_recovered_wallet unloadwallet
然后,你可以移除这个钱包的目录:
rm -rf ~/.bitcoin/wallets/my_recovered_wallet
编者注:上面这条命令主要用于 Linux 系统。在 Windows 系统中,你可以找出钱包文件的目录并手动删除。
(完)
- 本文转载自: btcstudy.org/2025/11/18/... , 如有侵权请联系管理员删除。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!