跳至主要內容
Informational Final

BIP-382: SegWit 描述符

定義 wpkh() 和 wsh() 描述符函數,用於原生隔離見證腳本類型。

Pieter Wuille, Andrew Chow 2021年6月27日
BIP 編號

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() 函數。

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