解鎖比特幣更多的應用,Miniscript的昨天、今天和明天!

買賣虛擬貨幣
譯者前言:由於比特幣指令碼(Script)的存在,今天,比特幣可實現簡單的交易功能及各種多重簽名、原子互換、閃電網路交易,然而,指令碼的功能並非只有這些,但複雜性卻限制了更多應用的可能,而Miniscript的提出,目的是讓比特幣指令碼變得更易於訪問,並最終解鎖比特幣更多的應用。對此,Pieter Wuille和Andrew Poelstra撰寫了一篇《Miniscript: Streamlined Bitcoin Scripting》來解釋Miniscript的由來和作用,以及其未來的發展方向。

以下為譯文:

關於比特幣指令碼的介紹

比特幣一直以來都有一種機制,它可透過更復雜的策略(而不僅僅是單個金鑰)來使幣可花費:這就是指令碼(Script)系統。雖然指令碼主要用於單金鑰支付,但它也是各種多重簽名錢包、原子互換結構和閃電網路的基礎。

然而,這些並不是指令碼所能實現功能的全部。指令碼可用於表示釋出交易而所需的複雜條件,例如(A, B, C中的兩個)以及(D 或(E和F)) , 其中 A-F分別表示唯一的金鑰,以及雜湊原像檢查、timelock(時間鎖)以及一些更奇特的構造。

比特幣指令碼的問題:難以驗證

但我們還無法充分利用比特幣指令碼的潛力,其中一個原因在於,為複雜任務構建指令碼是很麻煩的:很難驗證它們的正確性及安全性,甚至很難找到最經濟的方法來編寫它們。

這是問題的一部分:即使你知道正確的指令碼、設計應用及協議來協商和構造交易,而每次設計新的構造時,都需要大量額外的開發工作。而每次新增,都需要更多的工程資源以滿足分析和質量保證。

那如果比特幣應用可使用任何指令碼,而不僅僅是為數不多的指令碼設計,這會是怎麼樣的呢?我們將不再侷限於使用一次性設計,並且可開始設計基於使用者指定需求的應用。錢包開發人員還可引入更多基於指令碼的選項,同時保持與其他錢包的互操作性。

Miniscript是什麼

下面進入Miniscript的世界,這是一種以結構化方式表示比特幣指令碼的語言,其支援高效的分析、合成、通用簽名等功能。

關於比特幣指令碼的一個例子:

 OP_CHECKSIG OP_IFDUP OP_NOTIF OP_DUP OP_HASh260 <hash260(B)> OP_EQUALVERIFY OP_CHECKSIGVERIFY OP_CSV OP_ENDIF

其中A 和 B代表公鑰,而轉換成Miniscript的表示法就是:or_d(c:pk(A),and_v(vc:pk_h(B),older(144)))

這個例子清楚地表明,指令碼的語義,允許在A簽名或144個區塊之後的B簽名發生時允許支付。而大部分有意義的指令碼都可以用這種方式編寫。

而使得指令碼可讀,只是Miniscript的其中一個特性,其主要目的是實現對指令碼的自動化推理,如下面的應用例子所示。

Miniscript的應用

當前我們若使用比特幣指令碼來構建複雜的支出條件,這樣做的難度是非常大的,這需要為每個新的用例開發、測試和部署特殊用途的軟體。而Miniscript 可以一種跨越任意支出條件集的方式覆蓋這些條件,並且通常比專用解決方案要簡單得多,也更可靠。

應用1、最佳化指令碼

而其中一個例子,是找到一個實現給定支出條件集的最佳指令碼。

在比特幣指令碼中,有很多不同的方法需要簽名,描述連線或分離,或實現一個閾值。即使對經驗豐富的比特幣指令碼開發者,正確的選擇也可能取決於滿足不同條件的相對概率,而且難以進行計算。而我們的線上編譯器,其可立即找到與給定支出策略相對應的最佳Miniscript。

介紹中的例子可透過以下編譯策略獲得:or(admin@chaindaily(A),admin@chaindaily(pk(B),older(144)))

這是一種書寫方式,即左側A簽名發生的概率為99%,而右側(144個區塊後的B簽名)發生的概率為1%。

應用2、通用支出

一旦找到了一個有效指令碼,很多指令碼使用存在的一個共同障礙就是,不同的支出機制之間缺乏互操作性。而希望實施長期時間鎖( timelock)或複雜多重簽名要求的使用者,可能會因此而擔心。

而Miniscript,透過直接表示支出條件,允許任意策略的表達,以便任何人都可:

1. 計算指令碼的相關地址;
2. 確定在給定時間,哪些簽名者進行簽署是必要或足夠的;
3. 生成一筆有效交易,給定一個足夠的簽名集;

使用者不必擔心所有參與者是否在使用相容的軟體,也不必擔心這些軟體在需要這樣的時間鎖(timelock)設定時會繼續存在。
他們也不必擔心自己的需求可能會以和簽名軟體不相容的方式發生變化,從而保證使用比特幣指令碼不會對他們造成限制。

應用3、準備金證明

與簽名問題相關的是證明儲備金的問題,這是一個公司證明其可在不實際使用儲備比特幣的情況下,可使用其中部分比特幣的過程。雖然當前已經存在這方面的工具,例如Blockstream的準備金證明工具,但行業內還沒有一個通用的標準。而沒有Miniscript,可能也不會有一個能夠涵蓋當前多樣性託管解決方案的準備金證明標準。

支出策略的構成

讓我們來看看受互操作性需求約束的比特幣指令碼開發者的一個具體例子。以一家託管大量BTC的公司為例,該公司希望這些比特幣只有在其大多數董事同意的情況下才能被動用。然而,一些獨立的董事希望使用他們自己現有的錢包軟體和硬體,並且不希望參與(要求他們使用專用應用而提供的)單個金鑰簽名的方案。

在沒有Miniscript的情況下,生成一個包含所有簽名者要求的指令碼,同時向所有簽名者保證完整的指令碼是健全和完整的,並且他們的錢包軟體與結果相容,這將是一個無法克服的難題。

而使用Miniscript,這些董事可簡單地在自己的錢包軟體中編寫策略,構造一個描述閾值要求的單個策略,然後將其編譯為Miniscript。他們可直接驗證編譯器的輸出是否與原始策略匹配,以及原始策略是否滿足每個人的需求。然後,他們可使用任何與Miniscript相容的軟體來計算接收幣的地址,在消費時收集簽名,並將這些簽名組合到一筆有效的交易。

舉一個簡單的假設性例子:一家公司正在用一個定製的多重簽名儲存錢包,其有兩位董事,其中一位董事使用的是Blockstream Green錢包(配置為2-of-2多籤,經一些延遲後變為1-of-2),而另一位則使用的是Electrum錢包(標準1-of-1)。如果沒有允許組合安全、可互操作指令碼策略的工具,使用Green錢包的董事就不可能將其策略作為“參與者”新增到公司的多重簽名方案中。而如果Green和用於構建公司多重簽名的軟體都支援Miniscript,那麼兩位董事就可直接使用他們自己喜歡的錢包,甚至不需要知道錢包底層的指令碼到底是個啥。

動態聯盟(dynamic federation)

Miniscript的作用,我們可以在Blockstream的Liquid側鏈中找到一個具體的例子。Blockstream目前正在開發的一個功能(內部稱為動態聯盟),這是一個允許現有Liquid成員管理新成員新增或更新控制聯盟託管比特幣可使用性的指令碼。Miniscript為聯盟成員提供了快速、高效地構建此類指令碼的工具(事實上,Miniscript編譯器發現了現有Liquid指令碼的一個22位元組的較短版本,比我們原來的手工最佳化指令碼節省了5%的工作量)。但更重要的是,Miniscript允許成員自動驗證提議指令碼的重要屬性,從而減少了成員之間相互協調或對提議指令碼執行昂貴的手動安全稽覈的需要。

特別是,成員可自動驗證任何指令碼提議是否包括:

1. 他們自己的金鑰;
2. 一個時間鎖緊急支出條件,確保其在未來是正確的和足夠遠的。

它還允許他們驗證新聯盟的參與者是否有能力花費舊聯盟控制的幣。此檢查對於確保這種轉變不會導致幣丟失而言是至關重要的,即使對在轉換時將幣轉移到系統中的使用者也是如此,如果沒有 Miniscript,這幾乎是不可能實現的。

Miniscript的歷史

關於Miniscript的想法,最早可追溯到2018年夏天。那年7月中旬,Pieter Wuille為Bitcoin Core引入了輸出描述符(output descriptor)方案,這是一種描述Core支援的多種不同地址型別的通用方法。與此同時,當時還是Blockstream實習開發者的Andy Chow在開發部分簽名比特幣交易(PSBT,也被稱為BIP 174)方案,這是一種錢包互操作性協議,而這種提議在錢包領域獲得了廣泛關注。

PSBT的一個重要組成部分是 finalizer(完成者),其是從PSBT中包含的簽名者資料集合中,組裝實際比特幣交易的參與者。這種裝配需瞭解滿足的指令碼,這意味著支援PSBT的錢包必須實現自己的專用finalizer(完成者),而這就需要額外的開發並會限制互操作性。

而那個時期,Andrew Poelstra在努力嘗試把PSBT實現引入到rust版比特幣(透過Rust程式語言編寫的通用比特幣庫)軟體(這種實現最初是由Carl Dong提出的)。Poelstra在 IRC 交流頻道上觀察到:

“如果你有高度結構化的指令碼模板,你就不需要再去真正理解指令碼。”

正是這一想法,最終成為了Miniscript的核心。
實際上,Poelstra和Wuille一直在從事一個與託管相關的專案,但由於缺乏可用於複雜多參與者指令碼的標準工具,他們感到非常沮喪。兩人於2018年8月會面討論此事,Wuille建議實現這些“高度結構化的指令碼模板”,以此作為Bitcoin Core輸出描述符的擴充套件。

隨著擴充套件的形成,其演化為比特幣指令碼的結構化子集,最終成為Miniscript,以及一種更簡單的“策略語言”來直接表示支出條件,並且可編譯成Miniscript。2019年1月,Wuille在斯坦福區塊鏈會議上介紹了該方案的初步結果。

今年5月份,Sanket Kanjalkar加入Blockstream進行了為期三個月的實習工作,而其重點就是實現Miniscript工具,並幫助它與Bitcoin Core整合。在他的幫助下,MiniScript變得更小、更高效、更容易分析、更好地防止延展性問題。

經過這些迭代工作,最終形成了今天的Miniscript。

相關工作

Miniscript是建立在比特幣生態系統中很多其它專案的基礎上的,並與它們形成互補。特別是,如上所述,Miniscript 擴充套件了Bitcoin Core的錢包輸出描述符,並補充了PSBT,以實現完全通用的更新者(updater)和完成者(finalizer)。

Miniscript可以與Ivy進行比較,後者是另一種旨在使比特幣指令碼的高階功能易於訪問的語言。然而,相比Ivy,Miniscript 是指令碼(子集)的直接表示,這意味著可有效地驗證“miniscript”的正確性和可靠性。Miniscript還可接受很多其它形式的靜態分析,而這是指令碼(Script)和(Ivy)都無法做到的。

Miniscript的策略語言與Ivy相似,因為兩者都是抽象的,它們都必須經過編譯後才能在區塊鏈上使用。然而,Miniscript的策略語言在結構上與Miniscript本身非常相似,因此可以很容易地驗證編譯器的輸出是否與編譯器的輸入匹配(事實上,這甚至可手動檢查),並且可以很容易地驗證是否符合使用者的期望。

另一種與Miniscript相關的區塊鏈語言是Blockstream的Simplicity。與Miniscript一樣,Simplicity是一種低level語言,其旨在直接嵌入到區塊鏈交易當中。此外,Simplicity也支援很多形式的靜態分析,這些分析在部署區塊鏈合約時是非常重要的,但這在以太坊EVM等替代產品中卻難以甚至不可能實現。

另外,Miniscript 不像simplicity那樣強大到可以表示任何可計算函式,它的作用域非常有限:它可以表示簽名需求、時間鎖(timelock)、雜湊原像(hash preimage)以及它們的任意組合。這種範圍的縮小,使得Miniscript更容易對它所涵蓋的用例進行解釋,而且重要的是,這允許它在現有的比特幣區塊鏈上工作。相比之下,Simplicity則是對比特幣指令碼的徹底背離,其目前仍處於發展的早期階段。

未來的工作和結論

在設計 Miniscript時,我們著手讓比特幣指令碼更容易訪問。雖然很多工作都集中在調查和提議未來對指令碼及比特幣共識規則的修改,以新增額外功能,但我們也看到,基礎設施甚至沒有以通用、安全、可組合和可互操作的方式使用已存在的功能,這是當前所欠缺的。

這項工作還沒有徹底完成。我們有兩種Miniscript實現(分別是C++和Rust版本)和策略編譯器,但是為了該技術易於訪問,我們需要在常用軟體中整合它。透過與Miniscript相容的PSBT 實現(updater和finalizer),即使沒有明確的支援,許多PSBT簽名器(包括基於硬體錢包的簽名器)也可以用於複雜的指令碼。此外,編譯器也可以進行改進,因為策略到到指令碼轉換中有很多最佳化尚未被考慮。

這一路走來,我們學到了很多東西:

1. 指令碼資源限制使得策略最佳化複雜化:眾多共識和標準性強加資源限制的存在(最大opcode、最大指令碼大小、最大堆疊大小……),使得我們一旦接近這些限制,就很難找到給定策略的最佳指令碼。這是有趣的,因為它可能會指導未來指令碼的改進建議。與此相關的是,我們還驚訝地瞭解到,比特幣共識規則實際上將參與執行的OP_CHECKMULTISIG(VERIFY)的金鑰數,計算為每個指令碼201個非推送(non-push)opcode的限制。

2. 可變的驗證內容(witness)大小使費用估算複雜化:簡單的支付和多簽結構具有獨立於現有金鑰精確集合的驗證內容(witness)大小。而一旦我們轉移到更復雜的指令碼中,驗證內容(witness)大小就會變大,可能會使費用估算複雜化。特定交易輸出的潛在簽名者,可能需要樂觀地猜測將採用的廉價路徑,並構造相應的交易。如果不是該路徑的所有金鑰或雜湊最終都可獲得,則可能需要更改交易本身以考慮增加的費用。

3. 隔離見證(Segwit)的堆疊編碼使得最佳化複雜化:因為segwit的輸入堆疊不再編碼為指令碼,而是直接編碼為堆疊元素列表。這帶來了不幸的副作用,它會把“true”的編碼從1位元組更改為2位元組。因此,Miniscript 需要關心哪些子表示式進入if/else/endif結構的哪一邊。

4. 可擴充套件性:由於segwit,交易可擴充套件性不再是協議正確性的破壞者,但它仍然可能有不利影響(例如廣播交易時對收費率的不確定性、減慢緻密區塊(compact block)傳播以及干擾雜湊鎖作為全域性釋出機制的使用)。基於這些原因,我們在設計Miniscript時,考慮了不可延展性問題,並學習了一般驗證內容(witness)不可延展性的推理。為了實現這一點,Miniscript依賴於某些segwit特定的規則。

5. 常見子表示式的消除是困難的:儘管嘗試了很多次,Miniscript依然不支援最佳化重複的子表示式。雖然這在某些特定的情況下是可能的,但在一般的指令碼中似乎很難做到。新增某些堆疊操作opcode可能會改變這種情況。

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;