Output Descriptors
Output Descriptors 是一種標準化語言,用於描述如何從密鑰派生比特幣地址和腳本,解決了錢包備份和恢復的可移植性問題。
什麼是 Output Descriptors?
Output Descriptors(輸出描述符)是由 Pieter Wuille 提出的標準, 用於完整描述如何從密鑰材料生成比特幣輸出腳本。它解決了一個關鍵問題: 僅有種子詞是不夠的,還需要知道使用什麼腳本類型和派生路徑。
問題場景: Alice 有一個 12 詞助記詞。當她嘗試在新錢包恢復時, 發現餘額為零。原因是新錢包使用 P2WPKH,而原錢包使用 P2SH-P2WPKH。 Output Descriptors 通過明確指定腳本類型解決這個問題。
基本語法
Descriptor 由腳本函數和密鑰表達式組成:
# 基本格式
SCRIPT(KEY)#CHECKSUM
# 實際範例
wpkh([d34db33f/84'/0'/0']xpub.../0/*)#checksum
腳本類型
| Descriptor | 腳本類型 | 地址前綴 |
|---|---|---|
| pk(KEY) | P2PK(早期格式) | 無地址 |
| pkh(KEY) | P2PKH | 1... |
| wpkh(KEY) | P2WPKH (Native SegWit) | bc1q... |
| sh(wpkh(KEY)) | P2SH-P2WPKH | 3... |
| tr(KEY) | P2TR (Taproot) | bc1p... |
| wsh(SCRIPT) | P2WSH | bc1q...(較長) |
| sh(wsh(SCRIPT)) | P2SH-P2WSH | 3... |
密鑰表達式
單一公鑰
# 壓縮公鑰(33 bytes hex)
wpkh(02a1b2c3...)
# WIF 私鑰
wpkh(L1a2b3c4...)
擴展密鑰(xpub/xprv)
# xpub 帶派生路徑
wpkh(xpub661MyMwAq.../0/0)
# 帶來源資訊
wpkh([fingerprint/path]xpub.../0/0)
密鑰來源資訊
密鑰來源(Key Origin)記錄了密鑰的派生歷史:
[d34db33f/84'/0'/0']xpub6D4...
# d34db33f = 主密鑰指紋(前 4 bytes)
# 84'/0'/0' = 從主密鑰到此 xpub 的派生路徑
範圍與萬用字元
使用 * 表示地址範圍:
# 外部地址(接收)
wpkh([fp/84'/0'/0']xpub.../0/*)
# 內部地址(找零)
wpkh([fp/84'/0'/0']xpub.../1/*)
# * 代表 0, 1, 2, 3, ... 的索引
多簽 Descriptors
傳統多簽
# 2-of-3 P2WSH 多簽
wsh(multi(2,
[fp1/48'/0'/0'/2']xpub1.../0/*,
[fp2/48'/0'/0'/2']xpub2.../0/*,
[fp3/48'/0'/0'/2']xpub3.../0/*
))
排序多簽
# sortedmulti 按字典序排序公鑰
wsh(sortedmulti(2, xpub1..., xpub2..., xpub3...))
# 確保不同順序輸入產生相同地址
Taproot Descriptors
密鑰路徑
# 單純密鑰路徑花費
tr([fp/86'/0'/0']xpub.../0/*)
腳本路徑
# 密鑰路徑 + 腳本樹
tr(INTERNAL_KEY, SCRIPT_TREE)
# 帶備用腳本的 Taproot
tr(Alice, pk(Bob))
# Alice 是內部密鑰,Bob 的簽名可作為備用
複雜腳本樹
# 多個備用路徑
tr(Main, {
pk(Backup1),
{pk(Backup2), and_v(pk(Recovery), older(52560))}
})
Miniscript 整合
Descriptors 可以包含 Miniscript 表達式:
# P2WSH 包裝的 Miniscript
wsh(or_d(
multi(2, Alice, Bob),
and_v(pk(Recovery), older(4320))
))
# Taproot 腳本路徑的 Miniscript
tr(Internal, and_v(pk(External), after(1000000)))
校驗碼
每個 descriptor 都應附帶 8 字元的校驗碼,防止輸入錯誤:
wpkh([d34db33f/84'/0'/0']xpub6DJ2.../0/*)#abcd1234
# 校驗碼是根據整個 descriptor 計算的
Bitcoin Core 命令:
bitcoin-cli getdescriptorinfo "wpkh(xpub...)"
返回 descriptor 資訊和校驗碼
BIP 標準
| BIP | 內容 | 狀態 |
|---|---|---|
| BIP-380 | Output Descriptors 通用格式 | Draft |
| BIP-381 | 非 SegWit 腳本(pk, pkh, sh) | Draft |
| BIP-382 | SegWit 腳本(wpkh, wsh) | Draft |
| BIP-383 | 多簽(multi, sortedmulti) | Draft |
| BIP-384 | 組合腳本(sh(wsh(...))) | Draft |
| BIP-385 | 原始腳本(raw, addr) | Draft |
| BIP-386 | Taproot 腳本(tr) | Draft |
Bitcoin Core 使用
創建 Descriptor 錢包
# 創建新的 descriptor 錢包
bitcoin-cli createwallet "mywallet" false false "" false true
# 列出錢包 descriptors
bitcoin-cli listdescriptors
導入 Descriptors
# 導入 watch-only descriptor
bitcoin-cli importdescriptors '[{
"desc": "wpkh([fp/84h/0h/0h]xpub.../0/*)#checksum",
"timestamp": "now",
"range": [0, 999],
"watchonly": true
}]'
派生地址
# 從 descriptor 派生特定索引的地址
bitcoin-cli deriveaddresses "wpkh([fp]xpub.../0/*)#cs" "[0,5]"
# 返回索引 0-5 的地址列表
常見派生路徑
| BIP | 路徑 | 用途 |
|---|---|---|
| BIP-44 | m/44'/0'/0' | P2PKH (Legacy) |
| BIP-49 | m/49'/0'/0' | P2SH-P2WPKH |
| BIP-84 | m/84'/0'/0' | P2WPKH (Native SegWit) |
| BIP-86 | m/86'/0'/0' | P2TR (Taproot) |
| BIP-48 | m/48'/0'/0'/2' | 多簽 P2WSH |
完整備份範例
一個完整的錢包備份應包含所有相關 descriptors:
# 外部地址(接收)
wpkh([d34db33f/84'/0'/0']xpub6D.../0/*)#abc123
# 內部地址(找零)
wpkh([d34db33f/84'/0'/0']xpub6D.../1/*)#def456
最佳實踐: 備份時保存完整的 descriptor(包含密鑰來源和校驗碼), 而不僅僅是助記詞。這確保可以在任何支援 descriptor 的錢包中正確恢復。
錢包支援
相關資源
- * Miniscript 腳本語言
- * BIP-32:HD 錢包
- * BIP-44:多帳戶層次結構
- * BIP-84:Native SegWit 派生路徑
- * 多簽錢包入門
延伸閱讀: 查看 Bitcoin Core 官方文檔 了解完整的 descriptor 語法。