如何使用 Taproot 的 Miniscript 將 Miniscript 樹變成 Taproot 樹?
如何使用 Taproot’d Miniscript 將 Miniscript“樹”變成 Taproot 樹?
(需要明確的是,與 Taproot 樹不同,Miniscript 樹可能不會出現在使用者面前。將 Miniscript 分解成樹狀結構是在程式碼中完成的,並於2022 年 5 月 18 日在比特幣核心公關評論俱樂部中進行了討論。 )
如何使用 Taproot’d Miniscript 將 Miniscript“樹”變成 Taproot 樹?
你不會 - 它們是無法從一個翻譯到另一個的無與倫比的東西。
Miniscript 是一種表示比特幣腳本的方法,以幫助對其進行推理。主根樹是有助於建構主根輸出的承諾結構,這些輸出可以通過滿足可能的多個腳本之一來使用。
主根腳本配置和迷你腳本表達式都可以被認為是樹,但它們獨立存在,存在於不同的級別。充其量您可以說主根輸出是一棵樹,其葉子是腳本,而這些腳本又可以表示為 miniscript 表達式樹 - 但這些樹的性質非常不同。
也許一個更有用的問題是:
既然主根允許使用多個腳本的分離而不是單個腳本來花費輸出,那麼如何將支出策略轉換為腳本樹?
最簡單的情況類似於策略“使用密鑰 K1 簽名或使用密鑰 K2 簽名”。它可以實現為:
單個腳本
<K1> OP_CHECKSIG OP_SWAP <K2> OP_CHECKSIG OP_BOOLOR
(miniscriptor_b(pk(K1),s:pk(K2))
)。兩個腳本的分離:
<K1> OP_CHECKSIG
(pk(K1)
)<K2> OP_CHECKSIG
(pk(K2)
)當我們談論更多涉及的政策時,情況會變得更加複雜:
“K1 必須簽名並且 K2 或 K3 必須簽名”可以使用以下方式實現:
單個腳本
<K1> OP_CHECKSIGVERIFY <K2> OP_CHECKSIG OP_SWAP <K3> OP_CHECKSIG OP_BOOLOR
(and_v(v:pk(K1),or_b(pk(K2),s:pk(K3)))
)。兩個腳本的分離:
<K1> OP_CHECKSIGVERIFY <K2> OP_CHECKSIG
(and_v(v:pk(K1),pk(K2))
)<K1> OP_CHECKSIGVERIFY <K3> OP_CHECKSIG
(and_v(v:pk(K1),pk(K3))
)“必須滿足這三個條件中的兩個:(1)K1 必須簽名(2)K2 必須簽名(3)K3 和 K4 都必須簽名”可以使用以下方式實現:
單個腳本
<K3> OP_CHECKSIG OP_SWAP <K4> OP_CHECKSIG OP_BOOLAND OP_SWAP <K1> OP_CHECKSIG OP_ADD OP_SWAP <K2> OP_CHECKSIG OP_ADD 2 OP_EQUAL
(thresh(2,and_b(pk(K3),s:pk(K4)),s:pk(K1),s:pk(K2))
)3個腳本的析取:
<K1> OP_CHECKSIGVERIFY <K2> OP_CHECKSIG
(and_v(v:pk(K1),pk(K2))
)<K1> OP_CHECKSIGVERIFY <K3> OP_CHECKSIGVERIFY <K4> OP_CHECKSIG
(and_v(v:pk(K1),and_v(v:pk(K3),pk(K4)))
)<K2> OP_CHECKSIGVERIFY <K3> OP_CHECKSIGVERIFY <K4> OP_CHECKSIG
(and_v(v:pk(K2),and_v(v:pk(K3),pk(K4)))
)這些選項中的哪一個是最佳的可能取決於具體情況:
- 使用更多的腳本葉子通常更私密,因為未使用的葉子(以及它們對應的支出條件)不會在花費時間向區塊鏈透露。
- 使用更多的腳本葉子可能會或可能不會更便宜。在簡單的析取情況下(其中策略是“A 或 B 或 C 或 …”),在單獨的腳本中拆分通常更便宜。當需要將策略轉化為使用單獨腳本的巨大組合爆炸時,單個腳本的花費可能會更便宜。
- 在單個腳本的情況下,多個簽名方需要合作時的協調可能會更容易,因為他們需要提前決定他們將為哪個腳本簽名(由於 BIP341 sighash 規則送出給實際使用的腳本)。
Taproot 樹是(Tap)腳本的 Merkle(二進制)樹。每個節點(將葉子雜湊到根的過程中的中間狀態)最多有 2 個子節點,並且每個葉子腳本(在樹的底部)在再次雜湊之前通過其雜湊和它的連接再次雜湊兄弟的雜湊。
Miniscript 樹不做任何散列,因為它只是將單個(可能非常大)腳本重組為片段。Miniscript 樹的根是整個表達式。每個子表達式都是樹中的一個節點。葉子是沒有子表達式的表達式,比如
pk()
orolder()
。樹上的一個節點可以有兩個以上的孩子。例如,Miniscript 樹的一個節點可能包含一個thresh()
包含超過 2 個子表達式的 a(例如,2-of-3 門檻值將包含三個子表達式)。一個節點也只能有 1 個子節點(例如,如果它包含 Miniscript 包裝器之一a:
,d:
或l:
)。Taproot 樹將在Policy級別而不是 Miniscript 級別建構,因為 Taproot 樹的葉子上的每個 (Tap) 腳本都可以表示為單獨的 Miniscript(Miniscript 僅編碼整個 Script 的子集)。但是,如果我們考慮如何建構策略樹的主根樹,如果策略樹的“根”(最高級別)包含 a
or(A,B,C)
,則很容易將其解構為具有葉 A、B 和 C 的主根樹。如果策略根包含一個整個策略and
可能需要進入一個單獨的葉子,但也有可能的例外(如果它下面有析取,例如and(or(A,B),C)
相當於or(and(A,C),and(B,C))``thresh``or()
3 2-of-2s,如本部落格文章中所解釋的 2-of-3 門檻值簽名。感謝個人回答我關於 IRC 的問題。任何錯誤都是我自己的。