BIP-382: SegWit 描述符
定義 wpkh() 和 wsh() 描述符函數,用於原生隔離見證腳本類型。
382
Informational
Final
2021-06-27
摘要
BIP-382 定義了兩個描述符函數,用於表達原生隔離見證(Native SegWit)腳本:
wpkh()(Pay-to-Witness-PubKey-Hash)和
wsh()(Pay-to-Witness-Script-Hash)。 這些對應 SegWit v0 見證程序,使用 Bech32 地址格式。
wpkh() — Pay-to-Witness-PubKey-Hash
格式
語法:wpkh(KEY) 輸出腳本(見證程序 v0): OP_0 <20-byte-pubkey-hash> 範例: wpkh([d34db33f/84'/0'/0']xpub6ERApfZ.../0/*) 生成的腳本: 00 14 <20-byte-hash> │ │ └─ 公鑰的 HASH160 │ └─ OP_PUSHBYTES_20 └─ OP_0(見證版本 0) 對應地址:bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
見證結構
花費 P2WPKH 輸出時: scriptSig: (空) witness: <signature> // DER 編碼簽章 + SIGHASH 標記 <pubkey> // 33 bytes 壓縮公鑰 驗證邏輯: 1. 檢查見證程序長度 = 20 bytes 2. 驗證 HASH160(pubkey) = 見證程序 3. 驗證簽章對應公鑰
BIP-84 錢包
標準 Native SegWit 錢包
wpkh([d34db33f/84'/0'/0']xpub6CUGRUonZSQ4TWtTMmz.../0/*)#checksum 派生路徑解析: m/84'/0'/0'/0/* │ │ │ │ └─ 地址索引 │ │ │ └─ 接收鏈(0=接收,1=找零) │ │ └─ 帳戶索引 │ └─ 幣種(0=BTC) └─ BIP-84 用途(Native SegWit)
BIP-84 是 Native SegWit 錢包的標準派生路徑。
地址格式
主網
bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4
前綴:bc1q(q 表示版本 0 + 長度 20)
測試網
tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx
前綴:tb1q
wsh() — Pay-to-Witness-Script-Hash
格式
語法:wsh(SCRIPT) 輸出腳本(見證程序 v0): OP_0 <32-byte-script-hash> 範例: wsh(multi(2, KEY1, KEY2, KEY3)) 生成的腳本: 00 20 <32-byte-hash> │ │ └─ 見證腳本的 SHA256 │ └─ OP_PUSHBYTES_32 └─ OP_0(見證版本 0) 對應地址:bc1q...(42 字符,比 P2WPKH 長)
見證結構
花費 P2WSH 輸出時(以 2-of-3 多簽為例): scriptSig: (空) witness: OP_0 // 多簽 bug 的空佔位符 <sig1> // 第一個簽章 <sig2> // 第二個簽章 <witnessScript> // 完整的多簽腳本 witnessScript: OP_2 <pubkey1> <pubkey2> <pubkey3> OP_3 OP_CHECKMULTISIG 驗證邏輯: 1. 檢查見證程序長度 = 32 bytes 2. 驗證 SHA256(witnessScript) = 見證程序 3. 執行 witnessScript 驗證簽章
可包裝的腳本
| 描述符 | 用途 |
|---|---|
| wsh(multi(k, K1, ..., Kn)) | k-of-n 多簽 |
| wsh(sortedmulti(k, K1, ..., Kn)) | 排序多簽(確定性) |
| wsh(pk(KEY)) | 單密鑰(少見) |
| wsh(pkh(KEY)) | 公鑰哈希(少見) |
SegWit 優勢
費用節省
見證資料只計算 1/4 權重,降低交易費用約 30-40%。
修復延展性
簽章不再影響 txid,解決第三方延展性問題。
錯誤檢測
Bech32 地址有強大的錯誤檢測能力。
腳本版本控制
見證版本允許未來腳本升級(如 Taproot)。
wpkh vs wsh 比較
| 特性 | wpkh() | wsh() |
|---|---|---|
| 見證程序長度 | 20 bytes | 32 bytes |
| 地址長度 | 42 字符 | 62 字符 |
| 哈希算法 | HASH160 | SHA256 |
| 用途 | 單簽 | 複雜腳本 |
| 典型見證大小 | ~107 bytes | 取決於腳本 |
包裝在 sh() 中
為了與不支援原生 SegWit 的錢包相容,可以將 SegWit 描述符包裝在 sh() 中:
相容性包裝: sh(wpkh(KEY)) → P2SH-P2WPKH(BIP-49,地址以 "3" 開頭) sh(wsh(...)) → P2SH-P2WSH(複雜腳本的相容模式) 範例: sh(wpkh([d34db33f/49'/0'/0']xpub.../0/*)) 結構: ┌─────────────────────────────────────────┐ │ P2SH 輸出 │ │ OP_HASH160 <script-hash> OP_EQUAL │ ├─────────────────────────────────────────┤ │ redeemScript(P2WPKH 見證程序) │ │ OP_0 <20-byte-pubkey-hash> │ ├─────────────────────────────────────────┤ │ witness │ │ [signature, pubkey] │ └─────────────────────────────────────────┘
密鑰限制
壓縮公鑰要求
SegWit 描述符要求使用壓縮公鑰(33 bytes)。非壓縮公鑰(65 bytes)不被接受:
有效:wpkh(02c6047f9441ed7d6d...) // 33 bytes 壓縮公鑰 無效:wpkh(04c6047f9441ed7d6d...) // 65 bytes 非壓縮公鑰
Bitcoin Core 範例
# 創建原生 SegWit 錢包
$ bitcoin-cli createwallet "segwit_wallet" false false "" false true
# 導入 wpkh 描述符
$ bitcoin-cli -rpcwallet=segwit_wallet importdescriptors '[
{
"desc": "wpkh([d34db33f/84h/0h/0h]xpub.../0/*)#checksum",
"timestamp": "now",
"range": [0, 999],
"internal": false
},
{
"desc": "wpkh([d34db33f/84h/0h/0h]xpub.../1/*)#checksum",
"timestamp": "now",
"range": [0, 999],
"internal": true
}
]'
# 獲取新地址
$ bitcoin-cli -rpcwallet=segwit_wallet getnewaddress "" "bech32"
bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4 總結
BIP-382 定義了原生 SegWit 的描述符函數。wpkh() 適用於單簽錢包, 而 wsh() 支援多簽等複雜腳本。這些描述符生成 bc1q 開頭的 Bech32 地址, 提供更低的交易費用和更好的錯誤檢測。對於 Taproot,請參考 BIP-386 的 tr() 函數。
延伸閱讀: 查看 GitHub 上的完整 BIP-382 文件