Informational Final
BIP-386: Taproot 描述符
定義 tr() 描述符函數,用於表示 Taproot (SegWit v1) 輸出。
Pieter Wuille, Andrew Chow 2021年6月27日
BIP 編號
386
類型
Informational
狀態
Final
創建日期
2021-06-27
摘要
BIP-386 定義了 tr() 描述符函數,
用於表示 Taproot(SegWit v1)輸出。它支援 key path spending 和帶有腳本樹的 script path spending,
生成 bc1p 開頭的 Bech32m 地址。
基本格式
簡單 Key Path
語法:tr(KEY) 只有內部密鑰,沒有腳本樹: tr([d34db33f/86'/0'/0']xpub6ERApfZ.../0/*) 輸出腳本: OP_1 <32-byte-tweaked-pubkey> 其中: • OP_1 = 見證版本 1 • tweaked_pubkey = taproot_tweak(internal_pubkey, merkle_root=None) 地址:bc1p...(Bech32m 編碼)
帶腳本樹
語法:tr(KEY, TREE)
TREE 可以是:
• 單個腳本:tr(KEY, SCRIPT)
• 腳本對:tr(KEY, {SCRIPT_A, SCRIPT_B})
• 嵌套樹:tr(KEY, {SCRIPT_A, {SCRIPT_B, SCRIPT_C}})
範例:
tr(KEY_INTERNAL, {
pk(KEY_A),
{pk(KEY_B), pk(KEY_C)}
})
Merkle 樹結構:
[root]
/ \
pk(A) [branch]
/ \
pk(B) pk(C) x-only 公鑰
Taproot 使用 32 bytes 的 x-only 公鑰(省略 y 座標的符號位):
標準公鑰(33 bytes): 02 c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 │ └─────────────────────── x 座標(32 bytes)───────────────────────┘ └─ 前綴(02 或 03 表示 y 座標的奇偶) x-only 公鑰(32 bytes): c6047f9441ed7d6d3045406e95c07cd85c778e4b8cef3ca7abac09b95c709ee5 └─────────────────────── 只有 x 座標 ───────────────────────┘ 在 tr() 中,密鑰會自動轉換為 x-only 格式
腳本類型
Tapscript 函數
| 描述符 | 腳本 | 說明 |
|---|---|---|
| pk(KEY) | <xonly_key> OP_CHECKSIG | 單一密鑰簽章 |
| multi_a(k, K...) | <K1> CHECKSIG ... CHECKSIGADD ... k NUMEQUAL | k-of-n 多簽 |
| sortedmulti_a(k, K...) | (同上,密鑰排序) | 排序多簽 |
注意:multi_a vs multi
Tapscript 使用 multi_a() 而非 multi()。 這是因為 Tapscript 使用
OP_CHECKSIGADD 替代 OP_CHECKMULTISIG, 提供更好的批量驗證和更小的見證大小。
實際範例
BIP-86 錢包
標準 Taproot 單簽錢包: tr([d34db33f/86'/0'/0']xpub6ERApfZ.../0/*)#checksum 派生路徑:m/86'/0'/0'/0/* • 86' = BIP-86 用途(Taproot) • 0' = 比特幣主網 • 0' = 第一帳戶 • 0 = 接收鏈 • * = 地址索引 生成地址:bc1p...
2-of-3 Taproot 多簽
使用腳本路徑的 2-of-3: tr(KEY_INTERNAL, sortedmulti_a(2, [fp1/86'/0'/0']xpub1.../0/*, [fp2/86'/0'/0']xpub2.../0/*, [fp3/86'/0'/0']xpub3.../0/* )) 花費方式: • Key path: 用 KEY_INTERNAL 簽章(如果它是某個多簽的聚合密鑰) • Script path: 提供 2 個簽章 + Merkle proof
複雜腳本樹
混合花費條件:
tr(KEY_INTERNAL, {
pk(KEY_HOT), // 熱錢包快速花費
{
pk(KEY_COLD), // 冷錢包備份
multi_a(2, KEY_A, KEY_B, KEY_C) // 3 人中 2 人的恢復
}
})
樹結構:
[root]
/ \
pk(HOT) [branch]
/ \
pk(COLD) multi_a(2,A,B,C)
Merkle 深度影響見證大小:
• pk(HOT): 1 個哈希的 proof
• pk(COLD): 2 個哈希的 proof
• multi_a: 2 個哈希的 proof Key Path vs Script Path
Key Path
- • 只需 64 bytes Schnorr 簽章
- • 最小的見證大小
- • 最低的費用
- • 看起來像普通單簽
- • 最佳隱私
Script Path
- • 需要揭露腳本
- • 需要 Merkle proof
- • 見證較大
- • 揭露使用的條件
- • 支援任意條件
MuSig2 整合
對於多簽場景,可以結合 MuSig2 獲得最佳效率:
使用 MuSig2 聚合密鑰作為內部密鑰: tr(MUSIG_AGGREGATE_KEY) 其中 MUSIG_AGGREGATE_KEY 是多個參與者公鑰的聚合。 優點: • 看起來像單簽交易 • 最小的見證大小(64 bytes) • 最佳隱私 • 參與者數量不可見 缺點: • 需要交互式簽章協議 • 所有參與者必須在線
Bitcoin Core 範例
# 創建 Taproot 描述符錢包
$ bitcoin-cli createwallet "taproot_wallet" false false "" false true true
# 導入 tr() 描述符
$ bitcoin-cli -rpcwallet=taproot_wallet importdescriptors '[
{
"desc": "tr([d34db33f/86h/0h/0h]xpub.../0/*)#checksum",
"timestamp": "now",
"range": [0, 999],
"internal": false
},
{
"desc": "tr([d34db33f/86h/0h/0h]xpub.../1/*)#checksum",
"timestamp": "now",
"range": [0, 999],
"internal": true
}
]'
# 獲取 Taproot 地址
$ bitcoin-cli -rpcwallet=taproot_wallet getnewaddress "" "bech32m"
bc1p0xlxvlhemja6c4dqv22uapctqupfhlxm9h8z3k2e72q4k9hcz7vqzk5jj0 總結
BIP-386 定義的 tr() 函數是 Taproot 時代描述符的核心。 它支援從簡單的單簽到複雜的腳本樹,並生成 bc1p 開頭的 Bech32m 地址。 結合 MuSig2,Taproot 多簽可以達到與單簽相同的鏈上足跡,提供最佳的隱私和效率。
延伸閱讀: 查看 GitHub 上的完整 BIP-386 文件
已複製連結