走近BTC:理解BitVM所需的背景知識

新手7/11/2024, 2:55:14 PM
本文深入解釋比特幣二層技術(如BitVM)的背景和核心概念,幫助讀者理解這些前沿技術及其應用,特別是對於比特幣生態系統有濃厚興趣的人。

摘要:近期Delphi Digital發布了題爲《The Dawn of Bitcoin Programmability: Paving the Way for Rollups 》的比特幣二層相關技術研報,系統的梳理了和比特幣Rollup有關的核心概念,如BitVM全家桶、OP_CAT和Covenant限制條款、比特幣生態DA層、橋以及Bitlayer、Citrea、Yona、Bob等四大採用BitVM的比特幣二層。

該研報雖然大體展示了比特幣二層技術的大致圖景,但整體比較泛泛而缺乏細節描述,讓人似懂非懂。極客web3在Delphi研報基礎上進行了展開式的深入挖掘,嘗試讓更多人系統的理解BitVM等技術。

我們將與Bitlayer研究團隊及BitVM中文社區共同開展一個名爲“走近BTC”的系列專欄,長期圍繞BitVM、OP_CAT和比特幣跨鏈橋等重點話題進行科普,致力於爲更多人祛魅比特幣二層相關技術,幫更多愛好者鋪平道路。

正文:幾個月前,ZeroSync負責人Robin Linus發布了名爲《BitVM: Compute Anything on Bitcoin》的文章,正式提出了BitVM的概念,推動了比特幣二層技術的進展。可以說這是比特幣生態最具革命性的創新之一,引爆了整個比特幣二層生態,吸引了如Bitlayer、Citrea、BOB等明星項目的參與,爲整個市場帶來了生機。

之後,更多研究人員參與改進了BitVM,先後推出了BitVM1、BitVM2、BitVMX、BitSNARK等不同的迭代版本。其大致情況如下所示:

  1. Robin Linus於去年最先提出的BitVM實現白皮書,就是基於虛構邏輯門電路的BitVM實現方案,被稱爲BitVM0;

  2. Robin Linus在後面幾次演講和採訪中,又非正式的介紹了基於虛構CPU的BitVM方案(稱爲BitVM1),類似於Optimism的欺詐證明系統Cannon,可以用比特幣腳本在鏈下模擬出一個通用CPU的效果。

  3. Robin Linus還提出了BitVM2,一個Permissionless的單步非交互式欺詐證明協議。

  4. Rootstock Labs和Fairgate Labs的成員發布了BitVMX白皮書,與BitVM1類似,他們希望通過比特幣腳本模擬出通用CPU的效果(在鏈下)。

目前BitVM相關開發者生態的建設日漸明朗,週邊工具的迭代完善也已肉眼可見,相比於去年,如今的BitVM生態已經從最初的“空中樓閣”變得“依稀可見”,這也吸引了越來越多的開發者和VC爭相湧入比特幣生態。

但對於大多數人而言,要理解BitVM和比特幣二層相關的技術名詞絕非易事,因爲你要先對其週邊的基礎知識有系統性的理解,尤其是比特幣腳本和Taproot等背景知識。目前網上已有的參考資料要麼篇幅太長廢話連篇,要麼解釋的不夠透徹讓人似懂非懂。我們致力於解決上述問題,力求以盡可能清晰的語言,幫助更多人理解比特幣二層的週邊知識,對BitVM體系建立起系統性認知。

MATT和承諾:BitVM的基礎思想

首先我們要強調,BitVM的基礎思想是MATT,含義是Merkleize All The Things,主要指通過Merkle Tree這種樹狀的數據存儲結構來展示復雜的程序執行過程,設法讓比特幣Native的驗證欺詐證明。

MATT雖然可以表達出一段復雜程序及其數據處理痕跡,但不會直接在BTC鏈上發布這些數據,因爲這些數據的總體規模非常龐大。採用MATT的方案只在鏈下的Merkle樹中存儲數據,只把Merkle樹最頂部的摘要(Merkle Root)發布到鏈上。這棵Merkle樹主要包含三大核心內容:

· 智能合約腳本代碼

· 合約所需的數據

· 合約執行中留下的痕跡(智能合約在EVM等虛擬機中執行時對內存、CPU寄存器產生的變更記錄)

(一個簡單的Merkle Tree默克爾樹示意圖 其Merkle Root是由圖中底部的8個數據片段經過多層hash計算得到的)

MATT方案下,只有尺寸極小的Merkle Root存儲在鏈上,Merkle Tree包含的完整數據集存儲在鏈下,這用到了一種被稱爲“承諾”的思路。這裏解釋下什麼是“承諾”(Commitment)。

承諾類似於一種簡潔化的聲明,我們可以把它理解爲一大批數據壓縮後得到的“指紋”。一般而言,在鏈上發布“承諾”的人會聲稱,某些存放在鏈下的數據是準確無誤的,這些鏈下數據要對應一個簡潔化的聲明,這個聲明就是“承諾”。

在某些時候,數據的hash可以作爲對數據本身的“承諾”,其他的承諾方案還有KZG承諾或Merkle Tree等。在Layer2慣用的欺詐證明協議中,數據發布者會在鏈下發布完整數據集,在鏈上發布數據集的承諾。如果有人發現鏈下的數據集中存在無效數據,就會針對鏈上的數據承諾進行挑戰。

通過承諾(Commitment),二層能夠把大量數據壓縮處理,只在比特幣鏈上發布其“承諾”。當然,還要保證發布在鏈下的完整數據集可以被外界觀測到。

目前幾大BitVM方案如BitVM0、BitVM1、BitVM2和BitVMX,基本都採用了類似的抽象結構:

1.程序分解和承諾:首先將復雜的程序分解爲大量的、較基礎的操作碼(編譯),然後把這些操作碼在具體執行時產生的痕跡記錄下來(說白了就是一段程序跑在CPU和內存中時,整個的狀態變化記錄,稱爲Trace)。之後,我們對包括Trace和操作碼在內的所有數據進行整理,組織成一個數據集,然後生成該數據集的承諾。

具體的承諾方案可以有多種形式,如:Merkle樹、PIOPs(各種ZK算法)、哈希函數

2.資產質押和預籤名:數據發布者和驗證者需要通過預籤名的形式,把一定金額的資產鎖定在鏈上,並且會有限制條件。這些條件會針對未來可能發生的情況而針對性的觸發,如果數據發布者作惡,驗證者可以提交證明把數據發布者的資產拿走

3.數據和承諾發布:數據發布者在鏈上發布承諾,鏈下發布完整的數據集,驗證者檢索數據集並檢查是否有任何錯誤。鏈下數據集中的每個部分都與鏈上的承諾有關聯性。

4.挑戰和懲罰:一旦驗證者發現數據發布者提供的數據有錯誤,它會把這部分數據拿到鏈上去直接驗證(要先把這部分數據切的特別細),這就是欺詐證明的邏輯。如果驗證結果顯示,數據發布者的確在鏈下提供了無效數據,它的資產就會被挑戰他的驗證者拿走。

總結下就是,數據發布者Alice在鏈下公開二層交易執行過程中產生的所有痕跡,把對應的承諾發布到鏈上。如果你要證明某部分數據有誤,先向比特幣節點證明這部分數據和鏈上的承諾相關聯,也就是證明這些數據是Alice本人對外公開的,然後讓比特幣節點確定這部分數據有錯誤。

現在我們大致理解了BitVM的整體思路,所有的BitVM變體基本都脫離不了上述範式。那麼接下來,讓我們開始學習和理解上述流程中用到的一些重要技術,先從最基礎的比特幣腳本和Taproot以及預籤名開始。

什麼是Bitcoin Script腳本

比特幣相關的知識要比以太坊的更難理解,就連最基礎的轉帳行爲都涉及到一系列概念,包括UTXO(未花費的交易輸出)、鎖定腳本(也稱爲ScriptPubKey)和解鎖腳本(也稱爲ScriptSig)。我們先對這幾個主要概念進行講解。

(一段比特幣腳本代碼的示例 由比高級語言更底層的操作碼組成 )

以太坊的資產表達方式,更像支付寶或者微信,每次轉帳只是對不同帳戶的餘額做加減法,這種方法是以帳戶爲核心,資產餘額只是帳戶名下的一個數字;比特幣的資產表達形式更像黃金,每塊黃金(UTXO)都會標記出主人,轉帳實際上是把舊的UTXO銷毀,把新的UTXO產生(主人會變更)。

比特幣UTXO包含兩個關鍵字段:

數額,以“聰(satoshi)”爲單位(一億聰爲一BTC);

鎖定腳本,也稱 “腳本公鑰(ScriptPubKey)”,會定義UTXO的解鎖條件。

需要注意的是,比特幣UTXO的所有權是通過鎖定腳本來表達的,如果你要把自己的UTXO轉讓給Sam,可以發起交易銷毀自己的某個UTXO,把新生成的UTXO的解鎖條件寫爲“只有Sam可解鎖”。

之後,Sam如果要使用這些比特幣,需要提交一個解鎖腳本(ScriptSig),在這個解鎖腳本中Sam要出示自己的數字籤名,證明自己是Sam本人。如果解鎖腳本和前述鎖定腳本相匹配,Sam就可以解鎖並把這些比特幣再轉給別人。

(解鎖腳本要和鎖定腳本相匹配才行)

從表現形式的角度看,比特幣鏈上的每筆交易都對應着多個Input和Output,每個Input中要聲明自己想解鎖的某個UTXO,並提交解鎖腳本,解鎖並銷毀該UTXO;Output中會展示新生成的UTXO信息,對外公示鎖定腳本的內容。

比如,在一筆交易的Input中,你證明自己是Sam,把別人給你的多個UTXO解鎖,統一銷毀,再生成多個新的UTXO並聲明讓xxx在未來去解鎖。

具體而言,在交易的Input數據中,你要聲明自己要解鎖哪些UTXO,並指出這些UTXO數據的“存儲位置”。這裏要注意,比特幣和以太坊截然不同,以太坊提供了合約帳戶和EOA帳戶兩種帳戶來存儲數據, 資產餘額作爲數字,記錄在合約帳戶或EOA帳戶名下,統一放置在名爲“世界狀態”的數據庫中,轉帳時直接從“世界狀態”中對特定帳戶進行修改,便於定位到數據的存儲位置;

比特幣沒有世界狀態的設計,資產數據分散存儲在過往的區塊中(就是未解鎖的UTXO數據,在每筆交易的OutPut中單獨存放)。

如果你想解鎖某個UTXO,要說明該UTXO信息存在於過去哪筆交易的Output中,出示這筆交易的ID(就是其hash),讓比特幣節點去歷史記錄中尋找。如果要查詢某個地址的比特幣餘額,需要從頭遍歷所有區塊,找出和xx地址關聯的未解鎖UTXO。

平時用比特幣錢包時,可以快速檢查某地址擁有的比特幣餘額,很多時候是因爲錢包服務自身通過掃描區塊,對所有地址建立了索引,方便我們快速查詢。

(當你生成一筆交易聲明把自己的UTXO送給別人時,要根據這些UTXO所屬的交易hash/ID來標記出該UTXO在比特幣歷史記錄中的位置)

有意思的是,比特幣交易的結果是在鏈下計算完成的,用戶在本地設備上生成交易時,就要直接把Input和Output全部創建好,相當於把交易的輸出結果計算完了。交易在廣播到比特幣網路中,被節點驗證後才上鏈。這種“鏈下計算—鏈上驗證”的模式與以太坊是完全不同的,在以太坊上,你只需要提供交易輸入參數,交易結果由以太坊節點計算並輸出。

此外,UTXO的鎖定腳本(Locking Script)是可以自定義的,你可以把UTXO設定爲“某個比特幣地址的主人可解鎖”,該地址的主人需要提供數字籤名和公鑰(P2PKH)。而在Pay-to-Script-Hash(P2SH)交易類型中,你可以在UTXO鎖定腳本中添加一個Script Hash,誰能提交這個Hash對應的腳本原像,並滿足該腳本原像中預設的條件,就可以解鎖UTXO。BitVM所依賴的Taproot腳本,用到了類似於P2SH的特性。

比特幣腳本怎麼觸發

這裏我們先以P2PKH爲案例介紹比特幣腳本的觸發方式,只有理解了其觸發方式才能理解更爲復雜的Taproot和BitVM。P2PKH全稱“Pay to Public Key Hash”,在這種方案下,UTXO的鎖定腳本中會設置一個公鑰hash,解鎖時需要提交對應該hash的公鑰,這和常規的比特幣轉帳思路基本一致。

此時,比特幣節點要確定解鎖腳本中的公鑰,和鎖定腳本中指定的公鑰hash能對上號,也就是說,要確定解鎖人提交的“鑰匙”和UTXO預設的“鎖”彼此匹配。

進一步說,P2PKH方案下,比特幣節點收到交易後,會將用戶給出的解鎖腳本ScriptSig,與要解鎖的UTXO的鎖定腳本ScriptPubkey拼接到一起,放在BTC腳本的執行環境內執行。下圖給出執行前的拼接結果:

可能讀者並不了解BTC的腳本執行環境,此處我們進行簡單介紹。首先,BTC腳本包含兩種元素:

數據和操作碼。這些數據和操作碼會按照從左到右的順序,依次壓入棧內按照指定邏輯來執行,得到最終結果(關於什麼是棧 此處不展開詳述 讀者可以自行Chatgpt)。

以上圖爲例,左側是某人上傳的解鎖腳本ScriptSig,包含他的數字籤名和公鑰,而右側的鎖定腳本ScriptPubkey中,包含UTXO創建者生成該UTXO時設置的一段操作碼和數據(此處我們不需要了解每個操作碼的含義,理解個大概即可)。

上圖中右側的鎖定腳本中的DUP、HASH160、EQUALVERIFY等操作碼,負責把左側的解鎖腳本中攜帶的Public key取哈希,和鎖定腳本中預設的Public key hash做對比,若兩者相等,說明解鎖腳本中上傳的公鑰,和鎖定腳本中預設的公鑰哈希相匹配,這就通過了第一道驗證。

但是,有個問題,UTXO鎖定腳本的內容其實是在鏈上公開的,任何人都能觀測到其中包含的公鑰哈希,誰都可以上傳對應的公鑰,謊稱自己是那個被“欽定”的人。所以在驗證完公鑰和公鑰hash後,還要驗證交易發起人是否真是該公鑰的實際控制者,這就要對數字籤名進行核驗。鎖定腳本中的CHECKSIG操作碼,就是負責驗證數字籤名的。

總結一下,P2PKH方案下,交易發起人提交的解鎖腳本中,包含公鑰和數字籤名,該公鑰要和鎖定腳本中指定的公鑰哈希匹配,且交易的數字籤名正確,滿足這些條件才能順利解鎖UTXO。

(這個圖是動態的:P2PKH方案下比特幣解鎖腳本示意圖

來源:https://learnmeabitcoin.com/technical/script

當然,比特幣網路中支持多種交易類型,不只有Pay to public key/public key hash,還有P2SH(Pay to Script hash)等,一切取決於UTXO創建時自定義的鎖定腳本被設置成什麼樣。

這裏需要注意的是,P2SH方案下,鎖定腳本中可以預設一個Script Hash,而解鎖腳本需要把Script Hash對應的腳本內容完整提交上來。比特幣節點可以執行這段腳本,如果這段腳本裏定義了多籤驗證的邏輯,就可以在比特幣鏈上實現多簽錢包的效果。

當然,P2SH方案下,UTXO創建者要讓未來解鎖UTXO的人事先知道Script Hash對應的腳本內容,只要雙方都知道這段Script的內容,那麼我們就可以實現比多籤更復雜的業務邏輯。

這裏要說明一點,比特幣鏈上(區塊)並不直接記錄哪些UTXO和哪些地址關聯,它只記錄UTXO可以被哪個公鑰哈希/哪個腳本哈希解鎖,但我們根據公鑰hash/腳本hash可以快速算出對應的地址(錢包界面顯示的那一段像亂碼的東西)。

我們之所以能在區塊瀏覽器和錢包界面看到xx地址下有xx數額的比特幣,是因爲區塊瀏覽器和錢包項目方幫你解析了這些數據,會掃描所有區塊並根據鎖定腳本中聲明的公鑰hash/腳本hash,計算出對應的“地址”,然後顯示出xx地址名下有多少比特幣。

隔離見證與Witness

當我們理解了P2SH的思路後,便和BitVM所依賴的Taproot更近一步了。但在此之前,我們要了解一個重要的概念:Witness和隔離見證。

復盤前面講到的解鎖腳本和鎖定腳本,以及UTXO解鎖流程,會發現一個問題:交易的數字籤名包含在解鎖腳本中,生成籤名時不能把解鎖腳本覆蓋進去(生成籤名用到的參數不能包含籤名本身),所以數字籤名只能覆蓋解鎖腳本之外的部分,也就是只能與交易數據的主幹部分建立關聯,不能完整的覆蓋交易數據。

這樣一來,就算交易的解鎖腳本被中間人稍做手腳,也不會影響到驗籤結果。比如說,比特幣節點或礦池可以在交易的解鎖腳本中,塞入其他數據,在不影響驗籤和交易結果的前提下,使得交易數據發生細微變化,最後算出的交易hash/交易ID也會改變。這被稱爲交易延展性問題。

這帶來的壞處是,如果你打算連續發起多筆交易,並且有次序上的依賴關係(比如,交易3引用了交易2的輸出,交易2引用了交易1的輸出),那麼排後面的交易必然要引用前面交易的ID(hash),礦池或比特幣節點等任意中間人可以微調解鎖腳本中的內容,使交易上鏈後的hash與你預期的不一致,那麼你預先創建好的多筆有次序關聯的交易會失效。

實際上,在DLC橋和BitVM2的方案中,會批量構建有先後次序關聯性的交易,所以前面提到的場景並不少見。

簡單來說,交易延展性問題是因爲,交易的ID/hash在計算時,會把解鎖腳本的數據包含進去,而比特幣節點等中間人可以微調解鎖腳本中的內容, 導致交易ID與用戶預期的不符合。其實這是比特幣在早期設計時考慮不周留下的歷史包袱。

後來推出的隔離見證/SegWit升級,其實就是把交易ID和解鎖腳本徹底解耦,計算交易hash時不需要把解鎖腳本數據包含進去。遵循SegWit升級的UTXO鎖定腳本,會默認在首位設置一個叫“OP_0”的操作碼,充當標記;而對應的解鎖腳本,從SigScript更名爲了Witness(見證)。

遵循隔離見證規則後,交易延展性問題會被妥善解決,你不需要擔心發送給比特幣節點的交易數據被微調。當然我們不需要想的太復雜,P2WSH的功能和前面談到的P2SH並無本質差異,你可以在UTXO鎖定腳本中預設一個腳本哈希,等解鎖腳本的提交者把hash對應的腳本內容提交到鏈上並執行。

但如果你要實現的腳本內容特別龐大,包含特別多的代碼,通過常規的方法無法把完整的腳本提交到比特幣鏈上(每個區塊有大小限制)。那怎麼辦?這就需要借助Taproot,針對上鏈的腳本內容進行精簡化處理,而BitVM正是基於Taproot構建出的復雜方案。

在“走近BTC”的下一篇文章中,我們將對Taproot、預籤名等和BitVM相關的其他更復雜的技術進行詳細科普,大家敬請期待!

聲明:

  1. 本文轉載自[極客web3],著作權歸屬原作者[Nickqiao & Faust & Shew Wang],如對轉載有異議,請聯系 Gate Learn團隊,團隊會根據相關流程盡速處理。

  2. 免責聲明:本文所表達的觀點和意見僅代表作者個人觀點,不構成任何投資建議。

  3. 文章其他語言版本由Gate Learn團隊翻譯, 在未提及Gate.io的情況下不得復制、傳播或抄襲經翻譯文章。

走近BTC:理解BitVM所需的背景知識

新手7/11/2024, 2:55:14 PM
本文深入解釋比特幣二層技術(如BitVM)的背景和核心概念,幫助讀者理解這些前沿技術及其應用,特別是對於比特幣生態系統有濃厚興趣的人。

摘要:近期Delphi Digital發布了題爲《The Dawn of Bitcoin Programmability: Paving the Way for Rollups 》的比特幣二層相關技術研報,系統的梳理了和比特幣Rollup有關的核心概念,如BitVM全家桶、OP_CAT和Covenant限制條款、比特幣生態DA層、橋以及Bitlayer、Citrea、Yona、Bob等四大採用BitVM的比特幣二層。

該研報雖然大體展示了比特幣二層技術的大致圖景,但整體比較泛泛而缺乏細節描述,讓人似懂非懂。極客web3在Delphi研報基礎上進行了展開式的深入挖掘,嘗試讓更多人系統的理解BitVM等技術。

我們將與Bitlayer研究團隊及BitVM中文社區共同開展一個名爲“走近BTC”的系列專欄,長期圍繞BitVM、OP_CAT和比特幣跨鏈橋等重點話題進行科普,致力於爲更多人祛魅比特幣二層相關技術,幫更多愛好者鋪平道路。

正文:幾個月前,ZeroSync負責人Robin Linus發布了名爲《BitVM: Compute Anything on Bitcoin》的文章,正式提出了BitVM的概念,推動了比特幣二層技術的進展。可以說這是比特幣生態最具革命性的創新之一,引爆了整個比特幣二層生態,吸引了如Bitlayer、Citrea、BOB等明星項目的參與,爲整個市場帶來了生機。

之後,更多研究人員參與改進了BitVM,先後推出了BitVM1、BitVM2、BitVMX、BitSNARK等不同的迭代版本。其大致情況如下所示:

  1. Robin Linus於去年最先提出的BitVM實現白皮書,就是基於虛構邏輯門電路的BitVM實現方案,被稱爲BitVM0;

  2. Robin Linus在後面幾次演講和採訪中,又非正式的介紹了基於虛構CPU的BitVM方案(稱爲BitVM1),類似於Optimism的欺詐證明系統Cannon,可以用比特幣腳本在鏈下模擬出一個通用CPU的效果。

  3. Robin Linus還提出了BitVM2,一個Permissionless的單步非交互式欺詐證明協議。

  4. Rootstock Labs和Fairgate Labs的成員發布了BitVMX白皮書,與BitVM1類似,他們希望通過比特幣腳本模擬出通用CPU的效果(在鏈下)。

目前BitVM相關開發者生態的建設日漸明朗,週邊工具的迭代完善也已肉眼可見,相比於去年,如今的BitVM生態已經從最初的“空中樓閣”變得“依稀可見”,這也吸引了越來越多的開發者和VC爭相湧入比特幣生態。

但對於大多數人而言,要理解BitVM和比特幣二層相關的技術名詞絕非易事,因爲你要先對其週邊的基礎知識有系統性的理解,尤其是比特幣腳本和Taproot等背景知識。目前網上已有的參考資料要麼篇幅太長廢話連篇,要麼解釋的不夠透徹讓人似懂非懂。我們致力於解決上述問題,力求以盡可能清晰的語言,幫助更多人理解比特幣二層的週邊知識,對BitVM體系建立起系統性認知。

MATT和承諾:BitVM的基礎思想

首先我們要強調,BitVM的基礎思想是MATT,含義是Merkleize All The Things,主要指通過Merkle Tree這種樹狀的數據存儲結構來展示復雜的程序執行過程,設法讓比特幣Native的驗證欺詐證明。

MATT雖然可以表達出一段復雜程序及其數據處理痕跡,但不會直接在BTC鏈上發布這些數據,因爲這些數據的總體規模非常龐大。採用MATT的方案只在鏈下的Merkle樹中存儲數據,只把Merkle樹最頂部的摘要(Merkle Root)發布到鏈上。這棵Merkle樹主要包含三大核心內容:

· 智能合約腳本代碼

· 合約所需的數據

· 合約執行中留下的痕跡(智能合約在EVM等虛擬機中執行時對內存、CPU寄存器產生的變更記錄)

(一個簡單的Merkle Tree默克爾樹示意圖 其Merkle Root是由圖中底部的8個數據片段經過多層hash計算得到的)

MATT方案下,只有尺寸極小的Merkle Root存儲在鏈上,Merkle Tree包含的完整數據集存儲在鏈下,這用到了一種被稱爲“承諾”的思路。這裏解釋下什麼是“承諾”(Commitment)。

承諾類似於一種簡潔化的聲明,我們可以把它理解爲一大批數據壓縮後得到的“指紋”。一般而言,在鏈上發布“承諾”的人會聲稱,某些存放在鏈下的數據是準確無誤的,這些鏈下數據要對應一個簡潔化的聲明,這個聲明就是“承諾”。

在某些時候,數據的hash可以作爲對數據本身的“承諾”,其他的承諾方案還有KZG承諾或Merkle Tree等。在Layer2慣用的欺詐證明協議中,數據發布者會在鏈下發布完整數據集,在鏈上發布數據集的承諾。如果有人發現鏈下的數據集中存在無效數據,就會針對鏈上的數據承諾進行挑戰。

通過承諾(Commitment),二層能夠把大量數據壓縮處理,只在比特幣鏈上發布其“承諾”。當然,還要保證發布在鏈下的完整數據集可以被外界觀測到。

目前幾大BitVM方案如BitVM0、BitVM1、BitVM2和BitVMX,基本都採用了類似的抽象結構:

1.程序分解和承諾:首先將復雜的程序分解爲大量的、較基礎的操作碼(編譯),然後把這些操作碼在具體執行時產生的痕跡記錄下來(說白了就是一段程序跑在CPU和內存中時,整個的狀態變化記錄,稱爲Trace)。之後,我們對包括Trace和操作碼在內的所有數據進行整理,組織成一個數據集,然後生成該數據集的承諾。

具體的承諾方案可以有多種形式,如:Merkle樹、PIOPs(各種ZK算法)、哈希函數

2.資產質押和預籤名:數據發布者和驗證者需要通過預籤名的形式,把一定金額的資產鎖定在鏈上,並且會有限制條件。這些條件會針對未來可能發生的情況而針對性的觸發,如果數據發布者作惡,驗證者可以提交證明把數據發布者的資產拿走

3.數據和承諾發布:數據發布者在鏈上發布承諾,鏈下發布完整的數據集,驗證者檢索數據集並檢查是否有任何錯誤。鏈下數據集中的每個部分都與鏈上的承諾有關聯性。

4.挑戰和懲罰:一旦驗證者發現數據發布者提供的數據有錯誤,它會把這部分數據拿到鏈上去直接驗證(要先把這部分數據切的特別細),這就是欺詐證明的邏輯。如果驗證結果顯示,數據發布者的確在鏈下提供了無效數據,它的資產就會被挑戰他的驗證者拿走。

總結下就是,數據發布者Alice在鏈下公開二層交易執行過程中產生的所有痕跡,把對應的承諾發布到鏈上。如果你要證明某部分數據有誤,先向比特幣節點證明這部分數據和鏈上的承諾相關聯,也就是證明這些數據是Alice本人對外公開的,然後讓比特幣節點確定這部分數據有錯誤。

現在我們大致理解了BitVM的整體思路,所有的BitVM變體基本都脫離不了上述範式。那麼接下來,讓我們開始學習和理解上述流程中用到的一些重要技術,先從最基礎的比特幣腳本和Taproot以及預籤名開始。

什麼是Bitcoin Script腳本

比特幣相關的知識要比以太坊的更難理解,就連最基礎的轉帳行爲都涉及到一系列概念,包括UTXO(未花費的交易輸出)、鎖定腳本(也稱爲ScriptPubKey)和解鎖腳本(也稱爲ScriptSig)。我們先對這幾個主要概念進行講解。

(一段比特幣腳本代碼的示例 由比高級語言更底層的操作碼組成 )

以太坊的資產表達方式,更像支付寶或者微信,每次轉帳只是對不同帳戶的餘額做加減法,這種方法是以帳戶爲核心,資產餘額只是帳戶名下的一個數字;比特幣的資產表達形式更像黃金,每塊黃金(UTXO)都會標記出主人,轉帳實際上是把舊的UTXO銷毀,把新的UTXO產生(主人會變更)。

比特幣UTXO包含兩個關鍵字段:

數額,以“聰(satoshi)”爲單位(一億聰爲一BTC);

鎖定腳本,也稱 “腳本公鑰(ScriptPubKey)”,會定義UTXO的解鎖條件。

需要注意的是,比特幣UTXO的所有權是通過鎖定腳本來表達的,如果你要把自己的UTXO轉讓給Sam,可以發起交易銷毀自己的某個UTXO,把新生成的UTXO的解鎖條件寫爲“只有Sam可解鎖”。

之後,Sam如果要使用這些比特幣,需要提交一個解鎖腳本(ScriptSig),在這個解鎖腳本中Sam要出示自己的數字籤名,證明自己是Sam本人。如果解鎖腳本和前述鎖定腳本相匹配,Sam就可以解鎖並把這些比特幣再轉給別人。

(解鎖腳本要和鎖定腳本相匹配才行)

從表現形式的角度看,比特幣鏈上的每筆交易都對應着多個Input和Output,每個Input中要聲明自己想解鎖的某個UTXO,並提交解鎖腳本,解鎖並銷毀該UTXO;Output中會展示新生成的UTXO信息,對外公示鎖定腳本的內容。

比如,在一筆交易的Input中,你證明自己是Sam,把別人給你的多個UTXO解鎖,統一銷毀,再生成多個新的UTXO並聲明讓xxx在未來去解鎖。

具體而言,在交易的Input數據中,你要聲明自己要解鎖哪些UTXO,並指出這些UTXO數據的“存儲位置”。這裏要注意,比特幣和以太坊截然不同,以太坊提供了合約帳戶和EOA帳戶兩種帳戶來存儲數據, 資產餘額作爲數字,記錄在合約帳戶或EOA帳戶名下,統一放置在名爲“世界狀態”的數據庫中,轉帳時直接從“世界狀態”中對特定帳戶進行修改,便於定位到數據的存儲位置;

比特幣沒有世界狀態的設計,資產數據分散存儲在過往的區塊中(就是未解鎖的UTXO數據,在每筆交易的OutPut中單獨存放)。

如果你想解鎖某個UTXO,要說明該UTXO信息存在於過去哪筆交易的Output中,出示這筆交易的ID(就是其hash),讓比特幣節點去歷史記錄中尋找。如果要查詢某個地址的比特幣餘額,需要從頭遍歷所有區塊,找出和xx地址關聯的未解鎖UTXO。

平時用比特幣錢包時,可以快速檢查某地址擁有的比特幣餘額,很多時候是因爲錢包服務自身通過掃描區塊,對所有地址建立了索引,方便我們快速查詢。

(當你生成一筆交易聲明把自己的UTXO送給別人時,要根據這些UTXO所屬的交易hash/ID來標記出該UTXO在比特幣歷史記錄中的位置)

有意思的是,比特幣交易的結果是在鏈下計算完成的,用戶在本地設備上生成交易時,就要直接把Input和Output全部創建好,相當於把交易的輸出結果計算完了。交易在廣播到比特幣網路中,被節點驗證後才上鏈。這種“鏈下計算—鏈上驗證”的模式與以太坊是完全不同的,在以太坊上,你只需要提供交易輸入參數,交易結果由以太坊節點計算並輸出。

此外,UTXO的鎖定腳本(Locking Script)是可以自定義的,你可以把UTXO設定爲“某個比特幣地址的主人可解鎖”,該地址的主人需要提供數字籤名和公鑰(P2PKH)。而在Pay-to-Script-Hash(P2SH)交易類型中,你可以在UTXO鎖定腳本中添加一個Script Hash,誰能提交這個Hash對應的腳本原像,並滿足該腳本原像中預設的條件,就可以解鎖UTXO。BitVM所依賴的Taproot腳本,用到了類似於P2SH的特性。

比特幣腳本怎麼觸發

這裏我們先以P2PKH爲案例介紹比特幣腳本的觸發方式,只有理解了其觸發方式才能理解更爲復雜的Taproot和BitVM。P2PKH全稱“Pay to Public Key Hash”,在這種方案下,UTXO的鎖定腳本中會設置一個公鑰hash,解鎖時需要提交對應該hash的公鑰,這和常規的比特幣轉帳思路基本一致。

此時,比特幣節點要確定解鎖腳本中的公鑰,和鎖定腳本中指定的公鑰hash能對上號,也就是說,要確定解鎖人提交的“鑰匙”和UTXO預設的“鎖”彼此匹配。

進一步說,P2PKH方案下,比特幣節點收到交易後,會將用戶給出的解鎖腳本ScriptSig,與要解鎖的UTXO的鎖定腳本ScriptPubkey拼接到一起,放在BTC腳本的執行環境內執行。下圖給出執行前的拼接結果:

可能讀者並不了解BTC的腳本執行環境,此處我們進行簡單介紹。首先,BTC腳本包含兩種元素:

數據和操作碼。這些數據和操作碼會按照從左到右的順序,依次壓入棧內按照指定邏輯來執行,得到最終結果(關於什麼是棧 此處不展開詳述 讀者可以自行Chatgpt)。

以上圖爲例,左側是某人上傳的解鎖腳本ScriptSig,包含他的數字籤名和公鑰,而右側的鎖定腳本ScriptPubkey中,包含UTXO創建者生成該UTXO時設置的一段操作碼和數據(此處我們不需要了解每個操作碼的含義,理解個大概即可)。

上圖中右側的鎖定腳本中的DUP、HASH160、EQUALVERIFY等操作碼,負責把左側的解鎖腳本中攜帶的Public key取哈希,和鎖定腳本中預設的Public key hash做對比,若兩者相等,說明解鎖腳本中上傳的公鑰,和鎖定腳本中預設的公鑰哈希相匹配,這就通過了第一道驗證。

但是,有個問題,UTXO鎖定腳本的內容其實是在鏈上公開的,任何人都能觀測到其中包含的公鑰哈希,誰都可以上傳對應的公鑰,謊稱自己是那個被“欽定”的人。所以在驗證完公鑰和公鑰hash後,還要驗證交易發起人是否真是該公鑰的實際控制者,這就要對數字籤名進行核驗。鎖定腳本中的CHECKSIG操作碼,就是負責驗證數字籤名的。

總結一下,P2PKH方案下,交易發起人提交的解鎖腳本中,包含公鑰和數字籤名,該公鑰要和鎖定腳本中指定的公鑰哈希匹配,且交易的數字籤名正確,滿足這些條件才能順利解鎖UTXO。

(這個圖是動態的:P2PKH方案下比特幣解鎖腳本示意圖

來源:https://learnmeabitcoin.com/technical/script

當然,比特幣網路中支持多種交易類型,不只有Pay to public key/public key hash,還有P2SH(Pay to Script hash)等,一切取決於UTXO創建時自定義的鎖定腳本被設置成什麼樣。

這裏需要注意的是,P2SH方案下,鎖定腳本中可以預設一個Script Hash,而解鎖腳本需要把Script Hash對應的腳本內容完整提交上來。比特幣節點可以執行這段腳本,如果這段腳本裏定義了多籤驗證的邏輯,就可以在比特幣鏈上實現多簽錢包的效果。

當然,P2SH方案下,UTXO創建者要讓未來解鎖UTXO的人事先知道Script Hash對應的腳本內容,只要雙方都知道這段Script的內容,那麼我們就可以實現比多籤更復雜的業務邏輯。

這裏要說明一點,比特幣鏈上(區塊)並不直接記錄哪些UTXO和哪些地址關聯,它只記錄UTXO可以被哪個公鑰哈希/哪個腳本哈希解鎖,但我們根據公鑰hash/腳本hash可以快速算出對應的地址(錢包界面顯示的那一段像亂碼的東西)。

我們之所以能在區塊瀏覽器和錢包界面看到xx地址下有xx數額的比特幣,是因爲區塊瀏覽器和錢包項目方幫你解析了這些數據,會掃描所有區塊並根據鎖定腳本中聲明的公鑰hash/腳本hash,計算出對應的“地址”,然後顯示出xx地址名下有多少比特幣。

隔離見證與Witness

當我們理解了P2SH的思路後,便和BitVM所依賴的Taproot更近一步了。但在此之前,我們要了解一個重要的概念:Witness和隔離見證。

復盤前面講到的解鎖腳本和鎖定腳本,以及UTXO解鎖流程,會發現一個問題:交易的數字籤名包含在解鎖腳本中,生成籤名時不能把解鎖腳本覆蓋進去(生成籤名用到的參數不能包含籤名本身),所以數字籤名只能覆蓋解鎖腳本之外的部分,也就是只能與交易數據的主幹部分建立關聯,不能完整的覆蓋交易數據。

這樣一來,就算交易的解鎖腳本被中間人稍做手腳,也不會影響到驗籤結果。比如說,比特幣節點或礦池可以在交易的解鎖腳本中,塞入其他數據,在不影響驗籤和交易結果的前提下,使得交易數據發生細微變化,最後算出的交易hash/交易ID也會改變。這被稱爲交易延展性問題。

這帶來的壞處是,如果你打算連續發起多筆交易,並且有次序上的依賴關係(比如,交易3引用了交易2的輸出,交易2引用了交易1的輸出),那麼排後面的交易必然要引用前面交易的ID(hash),礦池或比特幣節點等任意中間人可以微調解鎖腳本中的內容,使交易上鏈後的hash與你預期的不一致,那麼你預先創建好的多筆有次序關聯的交易會失效。

實際上,在DLC橋和BitVM2的方案中,會批量構建有先後次序關聯性的交易,所以前面提到的場景並不少見。

簡單來說,交易延展性問題是因爲,交易的ID/hash在計算時,會把解鎖腳本的數據包含進去,而比特幣節點等中間人可以微調解鎖腳本中的內容, 導致交易ID與用戶預期的不符合。其實這是比特幣在早期設計時考慮不周留下的歷史包袱。

後來推出的隔離見證/SegWit升級,其實就是把交易ID和解鎖腳本徹底解耦,計算交易hash時不需要把解鎖腳本數據包含進去。遵循SegWit升級的UTXO鎖定腳本,會默認在首位設置一個叫“OP_0”的操作碼,充當標記;而對應的解鎖腳本,從SigScript更名爲了Witness(見證)。

遵循隔離見證規則後,交易延展性問題會被妥善解決,你不需要擔心發送給比特幣節點的交易數據被微調。當然我們不需要想的太復雜,P2WSH的功能和前面談到的P2SH並無本質差異,你可以在UTXO鎖定腳本中預設一個腳本哈希,等解鎖腳本的提交者把hash對應的腳本內容提交到鏈上並執行。

但如果你要實現的腳本內容特別龐大,包含特別多的代碼,通過常規的方法無法把完整的腳本提交到比特幣鏈上(每個區塊有大小限制)。那怎麼辦?這就需要借助Taproot,針對上鏈的腳本內容進行精簡化處理,而BitVM正是基於Taproot構建出的復雜方案。

在“走近BTC”的下一篇文章中,我們將對Taproot、預籤名等和BitVM相關的其他更復雜的技術進行詳細科普,大家敬請期待!

聲明:

  1. 本文轉載自[極客web3],著作權歸屬原作者[Nickqiao & Faust & Shew Wang],如對轉載有異議,請聯系 Gate Learn團隊,團隊會根據相關流程盡速處理。

  2. 免責聲明:本文所表達的觀點和意見僅代表作者個人觀點,不構成任何投資建議。

  3. 文章其他語言版本由Gate Learn團隊翻譯, 在未提及Gate.io的情況下不得復制、傳播或抄襲經翻譯文章。

即刻開始交易
註冊並交易即可獲得
$100
和價值
$5500
理財體驗金獎勵!
It seems that you are attempting to access our services from a Restricted Location where Gate is unable to provide services. We apologize for any inconvenience this may cause. Currently, the Restricted Locations include but not limited to: the United States of America, Canada, Cambodia, Thailand, Cuba, Iran, North Korea and so on. For more information regarding the Restricted Locations, please refer to the User Agreement. Should you have any other questions, please contact our Customer Support Team.