跳至主要內容
高級

Output Descriptors

Output Descriptors 是一種標準化語言,用於描述如何從密鑰派生比特幣地址和腳本,解決了錢包備份和恢復的可移植性問題。

20 分鐘

什麼是 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 的錢包中正確恢復。

錢包支援

Bitcoin Core 完整支援
Sparrow 完整支援
Specter 完整支援
Electrum 部分支援
Liana 完整支援 + Miniscript

相關資源

延伸閱讀: 查看 Bitcoin Core 官方文檔 了解完整的 descriptor 語法。

已複製連結
已複製到剪貼簿