感謝Mustafa Al-Bassam (musalbas)、James Prestwich (prestwich) 和Sam Wilson (SamWilsn) 的審閱。
HackMD 鏡像在此:https://hackmd.io/KOJdKANHSvaGC_8IugEAJA 20
時至今日,有關UTXO 模式的局限性,仍有許多誤解廣為流傳;人們聲稱,UTXO 是不可能實現以太坊那樣的智能合約的(或者即使能也非常難)。我們在此提供出一種基於UTXO 的執行模式,可以支持所有的以太坊智能合約功能模塊(取決於虛擬機的規範)。這些想法都不是全新的,只不過都散落在各種在線聊天裡。對於尚不熟悉這種模型的人來說,這篇文章可以作為介紹和討論這個模型的資源匯總。
背景
前置讀物
Bitcoin: A Peer-to-Peer Electronic Cash System, Nakamoto(Ethereum Design Rationale) Accounts and not UTXOs, Buterin(中文譯本)(Bitcoin Stack Exchange) UTXO model vs. account/balance model, WuilleThe Stateless Client Concept, Buterin(中文譯本)EIP-648: Easy parallelizability 25, ButerinPractical parallel transaction validation without state lookups using Merkle accumulators, AdlerIntro to CKB Script Programming 1: Validation Model, Xiao
額外讀物
State Provider Models in Ethereum 2.0 , Dietrichs et al.(中文譯本)Automated Detection of Dynamic State Access in Solidity, WilsonThe “Direct Push” model can't handle stale witnesses, CloutierOptimizing sparse Merkle trees, ButerinFraud and Data Availability Proofs: Maximising Light Client Security and Scaling Blockchains with Dishonest Majorities 33, Al-Bassam et al.Zexe: Enabling Decentralized Private Computation 4, Bowe et al.
在UTXO 模式中實現以太坊式的執行
數據模式
除了我們在傳統的基於UTXO 的系統裡面熟悉的 coin UTXO(原生貨幣UTXO)以外,我們定義一種新的UTXO 類型,contract UTXO(合約UTXO)。
Coin UTXO 有如下字段:
Coin 的數量使用腳本的哈希值(定義了該UTXO 的所有者)或者所有者
Contract UTXO 由以下字段組成:
Coin 的數量合約ID合約代碼哈希值存儲根
在實踐中,除了這些字段,肯定還會增添字段或優化這些字段,比如存儲代碼或腳本默克爾樹的樹根(BIP-016),而不是存儲哈希值。我們在這裡僅列舉最基礎的字段,以簡化分析、集中在所需的核心特徵上。
合約的代碼哈希值和存儲根只有使用無狀態執行模式才會用得上。在具有狀態的執行模式中可以省略,但因此需要一個專門用於存儲的UTXO 類型。
UTXO ID(即每個UTXO 的唯一標識符,可以在基於鍵值對的數據庫中用作key)是這個UTXO 的outpoint(生產該UTXO 的交易的ID 以及該UXTO 在輸出中的位置索引),或者某種變種(例如,outpoint 及其字段的哈希值)。
注意,在這個模式中,合約UXTO 沒有定義“所有者”(即對此UTXO 具有排他控制權的私鑰),就像以太坊當前的合約一樣。也就是說,合約的代碼要來定義其內部的所有權概念,例如 使用
onlyOwner()
方法。因此,合約UTXO 是 任何人都可以花費的。
執行模式
以太坊虛擬機(EVM)中的智能合約,有三大區別於比特幣腳本的本質特徵:
狀態元素可以定義自身的修改規則。這個區別是眾所周知的,只不過被不精確地表達為以太坊可以上傳持久的代碼,但這只是一個手段,而非目的。用戶可以與合約交互。這就意味著以太坊式的合約沒有固有的所有權概念。合約可以與其它合約交互。
那我們如何能在UTXO 模式上實現這些特徵呢?
第一點很簡單:我們可以使用covenants 來強制執行合約UTXO:當合約UXTO 在一筆交易中使用時,必須創建一個新的、帶有特定花費條件的UTXO(且只能創建一個);具體來說,就是合約代碼相同,但是狀態根更新了(取決於交易執行的結果)的UTXO。一個例外是合約的銷毀,如果需要這個功能的話。
用了covenants,用戶自然而然可以跟合約交互,因為合約UTXO 是人人可用的,任何用戶單獨與任意數量的合約交互。
然後,還得讓合約能夠跟其它合約交互(結果是,用戶可以同時與許多合約交互)。這個也簡單,只需讓多個合約的UTXO 都能在同一筆交易中使用,即可。從另一個角度看,交易聲明了自己將觸及哪些合約(且,在賬戶模型中,還可額外聲明將觸及哪些狀態對象)。這就是所謂的“嚴格訪問列表”。
最後,我們需要討論如何生成合約和更新合約。合約UTXO 可以使用一個操作碼來創建,創建時會確定性地分配一個密碼學上唯一的合約ID,例如類似於以太坊CREATE2 這樣的操作碼。作為一個合約UTXO,在使用和重生時,其合約ID 保持不變,但其UTXO ID 將變化,而且每次交易後都會不同,因為UTXO 的ID 是由outpoint 決定的。
交易格式
交易是一個包含下列內容的元組:
輸入:一些唯一標識符,表明要消耗哪些UTXO,並提供不可變形(non-malleable)的數據來解鎖coin 或者與合約交互。輸出:定義創建哪些UTXO。 Gas Price 和Gas Limit。 Witness:額外的元數據,包括賦予交易合法性的數字簽名以及無狀態的默克爾樹分支。
交易由自身的輸入和輸出來唯一標識,也即簽名的對象僅包括輸入和輸出。 Witness 數據是區塊生產者可以改變的。
要讓一個區塊裡面可以多次使用同一個合約,關鍵是合約UTXO 可以由其合約ID 來唯一標識(加上其UTXO ID),即在任何時候,使用某個ID 的合約都只有一個。因此,用戶只需提供自己的交易會訪問的所有合約的ID,而不需要提供UTXO ID。區塊組裝者會提供具體的UTXO ID,放在witness 中。 Coin UTXO 的花費則與我們今天的用法無二。
最後一件事
精明的讀者可能注意到了,在本文提供的方案中,某些只引用合約UTXO 作為輸出但不執行操作(也即不消耗gas)的交易,可能會遇到交易ID 重合問題。為了避免這一點,一筆交易至少要消耗一個coin UTXO。
更一般地來說,這個規則也可以放得寬鬆一些,只要求交易至少一個輸入需要用UTXO ID 來顯式地指定,這樣只提供合約UTXO 有時也行。這樣做就支持原生的賬戶抽象(EIP-2938)。
還有其它重要的理由支持實施這條規則,包括通過最基本的手續費來實現DoS 保護,並以動態比例的手續費燃燒的方式實現彈性的區塊大小(EIP-1559)。
UTXO 對比賬戶模式的好處
相比賬戶模式,使用UTXO 有許多好處,最主要的是通過並行化來創建更高吞吐量工程實現的潛能
交易指定了自己會觸及哪個合約,因此不相關的交易就可以並行執行(連生產區塊的節點都可以)。這個在賬戶數據模式下使用“嚴格訪問列表” 也可以實現。 UTXO 數據模式下的交易顯式地說明了其狀態轉換。因此,在非區塊生產者這邊,交易可以並行地驗證,即使它們讀取或者寫入了同一個合約。在本文提出的方案中,生產區塊的節點仍然需要用重疊的訪問列表,按順序地執行交易。 UTXO 數據模式的nonce(交易流水號)以outpoint 的形式呈現,所以無需顯式地跟踪零餘額地址的nonce,但當前的賬戶數據模式就需要。
直覺
我們注意到,UTXO 沒有提供任何本質上與賬戶不同的功能,也沒有缺失任何基礎功能。這一點可能並不讓人驚訝,因為它們都可以在一個統一的模式下得到描述。不過,UTXO 數據模式提供的內置訪問列表功能可以實現更大的可擴展性。
一個關鍵的直覺是,底層的數據模式與執行模式沒有絕對的關聯,執行模式既可以是具狀態的,也可以是無狀態的;跟合約是否能與另一個合約互動也沒有絕對的關聯。
結論
我們在此提出了一種用UTXO 數據模式實現通用的、以太坊式富狀態智能合約的方案。這是用covenants 以及允許合約彼此交互(在同一筆交易中聲明)來實現的。我們注意到,UTXO 數據模式和帶有嚴格訪問列表的賬戶數據模式是等價的。
(完)
(文內有許多超鏈接,可點擊左下”閱讀原文“ 從EthFans 網站上獲取)
原文鏈接:
https://forum.celestia.org/t/accounts-strict-access-lists-and-utxos/37
作者: John Adler
翻譯:
阿劍
你可能還喜歡:
觀點| 狀態膨脹和無狀態性
Echo | 以太坊的設計理念,Part-2
科普| 比特幣的UTXO 模型