BIP-380: Output Descriptors 基礎
定義輸出腳本描述符的通用語法和語義,作為整個描述符系列的基礎規範。
380
Informational
Final
2021-06-27
摘要
BIP-380 定義了 Output Script Descriptors(輸出腳本描述符)的基礎框架。 描述符是一種用於完整描述如何從密鑰材料派生輸出腳本的語言, 解決了僅靠助記詞無法完整恢復錢包的問題。
動機
助記詞的不足
BIP-39 助記詞只編碼了熵(種子),但錢包恢復還需要知道:
缺失的資訊
- • 腳本類型:P2PKH? P2SH-P2WPKH? P2WPKH? P2TR?
- • 派生路徑:BIP-44? BIP-84? BIP-86? 自定義路徑?
- • 多簽配置:幾個密鑰?閾值是多少?密鑰順序?
- • 時間鎖:是否有額外的鎖定條件?
實際問題
用戶 Alice 在錢包 A 創建了 2-of-3 多簽錢包。當她嘗試在錢包 B 恢復時, 即使輸入了所有三個助記詞,錢包 B 也無法重建相同的地址, 因為它不知道這是多簽、閾值是多少、以及密鑰的正確順序。
描述符解決方案
完整性
描述符包含重建錢包所需的所有資訊:腳本類型、派生路徑、密鑰、條件等。
可移植性
標準化格式使不同錢包軟體可以正確解析和使用相同的描述符。
可擴展性
可以表達任意複雜的腳本,包括多簽、時間鎖、Taproot 等。
可驗證性
內建校驗和確保描述符在傳輸過程中沒有被修改或損壞。
基本語法
描述符結構
描述符基本結構: SCRIPT_EXPRESSION#CHECKSUM 組成部分: ┌─────────────────────────────────────────────────────────────┐ │ 腳本表達式(SCRIPT_EXPRESSION) │ │ 定義輸出腳本的結構和使用的密鑰 │ ├─────────────────────────────────────────────────────────────┤ │ # │ │ 分隔符 │ ├─────────────────────────────────────────────────────────────┤ │ 校驗和(CHECKSUM) │ │ 8 字符的錯誤檢測碼 │ └─────────────────────────────────────────────────────────────┘ 範例: wpkh([d34db33f/84'/0'/0']xpub6ERApfZ.../0/*)#checksum
腳本表達式
腳本表達式是一個函數調用,描述如何構建輸出腳本:
腳本表達式語法: FUNCTION(ARGUMENTS) 其中 ARGUMENTS 可以是: • 密鑰表達式(KEY) • 其他腳本表達式(嵌套) • 其他參數(如數字、哈希等) 範例: sh(wpkh(KEY)) // P2SH 包裝 P2WPKH wsh(multi(2,K1,K2,K3)) // P2WSH 包裝 2-of-3 多簽
密鑰表達式
密鑰類型
| 類型 | 格式 | 說明 |
|---|---|---|
| 公鑰(hex) | 02abc123... | 33 或 65 bytes 的壓縮/非壓縮公鑰 |
| WIF 私鑰 | L1a2b3c4... | Base58Check 編碼的私鑰 |
| xpub | xpub6ABC... | BIP-32 擴展公鑰 |
| xprv | xprv9ABC... | BIP-32 擴展私鑰 |
| x-only 公鑰 | abc123...(32 bytes) | Taproot 使用的 32 bytes 公鑰 |
來源資訊
密鑰可以包含來源資訊,描述其派生路徑:
來源資訊格式: [FINGERPRINT/PATH]KEY 組成部分: • FINGERPRINT: 主密鑰的 4 bytes 指紋(hex) • PATH: BIP-32 派生路徑 • KEY: 該路徑對應的密鑰 範例: [d34db33f/84'/0'/0']xpub6ERApfZ... 解讀: • d34db33f = 主密鑰指紋 • 84' = BIP-84 用途(原生 SegWit) • 0' = 比特幣主網 • 0' = 第一個帳戶 • xpub6ERApfZ... = 該路徑的擴展公鑰
派生路徑
從擴展密鑰派生子密鑰: xpub.../0/* // 從 xpub 派生接收地址 xpub.../1/* // 從 xpub 派生找零地址 路徑元素: • 數字:普通派生(如 0, 1, 2) • 數字':硬化派生(如 0', 44'), 只能用於私鑰 • *:萬用符,表示一系列索引 • <M;N;O>:多路徑,表示多個可能的索引 範例: xpub.../0/* // 索引 0, 1, 2, 3, ... xpub.../<0;1>/* // 接收(0)和找零(1)都包含
校驗和
描述符使用與 Bech32 類似的校驗和算法:
校驗和特性:
長度:8 字符
字符集:qpzry9x8gf2tvdw0s3jn54khce6mua7l(Bech32)
錯誤檢測能力:
• 最多 4 個字符錯誤
• 任何單個字符替換
• 任意兩個字符交換
計算方式:
1. 將描述符(不含 #)轉換為 5-bit 組
2. 應用多項式校驗
3. 輸出 8 個 5-bit 值
4. 轉換為 Bech32 字符
範例:
wpkh(02abc...)#abcd1234
^^^^^^^^
校驗和 描述符系列
BIP-380 是基礎規範,具體的腳本類型由後續 BIP 定義:
| BIP | 內容 | 描述符函數 |
|---|---|---|
| BIP-380 | 基礎框架 | 語法、密鑰表達式、校驗和 |
| BIP-381 | 非 SegWit 描述符 | pk(), pkh(), sh() |
| BIP-382 | SegWit 描述符 | wpkh(), wsh() |
| BIP-383 | 多簽描述符 | multi(), sortedmulti() |
| BIP-384 | 組合描述符 | combo() |
| BIP-385 | 原始描述符 | raw(), addr() |
| BIP-386 | Taproot 描述符 | tr() |
實際範例
單簽錢包
P2WPKH(Native SegWit,bc1q... 地址): wpkh([d34db33f/84'/0'/0']xpub6ERApfZwUNrhL.../0/*)#checksum 解讀: • wpkh() = P2WPKH 腳本類型 • [d34db33f/84'/0'/0'] = 來源資訊 • xpub6ERApfZ... = 帳戶級別的擴展公鑰 • /0/* = 接收地址鏈,索引從 0 開始 • #checksum = 校驗和
多簽錢包
2-of-3 多簽(P2WSH): wsh(sortedmulti(2, [aabbccdd/48'/0'/0'/2']xpub1.../0/*, [11223344/48'/0'/0'/2']xpub2.../0/*, [55667788/48'/0'/0'/2']xpub3.../0/* ))#checksum 解讀: • wsh() = P2WSH 包裝 • sortedmulti() = 排序的多簽(密鑰按字典序排列) • 2 = 閾值(需要 2 個簽章) • 3 個 xpub = 3 個參與者的公鑰
Taproot 錢包
簡單 Taproot(bc1p... 地址):
tr([d34db33f/86'/0'/0']xpub6ERApfZ.../0/*)#checksum
帶腳本樹的 Taproot:
tr(KEY_INTERNAL,{
pk(KEY_A),
{pk(KEY_B),pk(KEY_C)}
})#checksum
[Internal Key]
│
┌────┴────┐
pk(A) ┌───┴───┐
pk(B) pk(C) 工具支援
總結
BIP-380 建立了 Output Script Descriptors 的基礎框架,定義了語法結構、密鑰表達式和校驗和算法。 這個標準使錢包備份和恢復變得完整和可靠,特別是對於複雜的多簽和 Taproot 設置。 後續的 BIP-381 到 BIP-386 則定義了具體的腳本類型函數。
延伸閱讀: 查看 GitHub 上的完整 BIP-380 文件