原文:《 Web3.0底層語言:Move彌補了Solidity哪些不足? 》
作者:宋嘉吉、任鶴義
摘要
為什麼基於Solidity 語言的以太坊生態如此龐大,市場依然對新公鏈有著新期待? Move 出自大廠(Meta),被行業普遍看好,前期一些基於Move 語言開發的公鏈得到了市場的青睞和資本的追捧。面向Web3 更為豐富的應用,底層語言的進化是基礎,Move 有哪些優勢,彌補了Solidity 哪些不足?基於這些特點,Move 生態有可能誕生新模式和新應用。
針對已有的編程語言如Solidity,Move 語言在很多細節設計考慮的比較周到,如將庫與應用邏輯分離開來;但最為突出的特點是資源類型方面,即面向資源的編程。在Dapp 應用支持方面,吸收了比特幣script 和以太坊的smart contract 的優點,因此行業普遍對該編程語言比較看好。而針對Solidity 被外界詬病的安全問題,move 也在嘗試解決。
Move 是面向資源(resources) 的編程語言,資源在Move 的世界裡是「第一等公民」(first-class resource),其關鍵特性是自定義資源類型:resources 永遠不能被複製或隱式丟棄,只能在程序存儲位置之間移動。 Solidity 並不是面向資源的,用戶的賬戶擁有某個Token 資產,只是該Token 合約分配給用戶的一個數值。而Move 創建的Token 賬戶資產是獨一無二的資源類型,比如賬戶A 中的資產是保存在A 賬戶中的,雖然也是數值,但不能複制、丟棄或重用,可以被安全地存儲和轉移。同時,賬戶資產只能由定義該資源的模塊進行創建和銷毀,這使得同質化的數值類型的資產可能產生的重入、類似雙花或者賬戶餘額出現不平衡的狀況得以避免。在這一點上,Move 賬戶資產有些類似比特幣的UTXO 機制,Token 不再是簡單的同質化數值,而是可區分的。
為了可以實現更靈活的業務,Move 另外定義了4 種權限屬性:可複制(copy)、可丟棄(drop)、可存儲(store)、可檢索(key)。這4 種屬性可以任意組合,來定義資源的屬性,方便用戶靈活操作。如drop+store+key 的組合,定義的資源是不可以復制的,可以避免複製引發的代幣增發以及雙花的問題,這一點類似NFT 以及比特幣的UTXO 機制。
對於模塊化和合約組合性方面,Moe 使用了模塊和腳本設計,通過傳遞資源實現合約交互。 Solidity(如以太坊)上面的Contract 合約通過library(相當於靜態庫)進行消息的傳遞,從而實現Contract 合約之間的調用、交互。而Move 語言使用了模塊(module) 和腳本(script) 的設計,前者類似於Contract 合約,Move 語言的合約組合性則是模塊之間的組合,通過傳遞資源(即前文提到的resources)。關於組合性方面,Solidity 和Move 的區別非常明顯。
在交易執行方面,Move 的並行處理相交Solidity 帶來區塊鏈性能的極大提升。並行執行(PE)通過識別獨立交易並同時執行,這極大提升了區塊鏈的擴展性。 Solidity 並不支持並行處理,如以太坊上的交易按順序執行,其他交易置於暫停(排序)狀態——因此產生了mempool(內存池)和MEV 市場。如基於Move 的公鏈Aptos,利用Block-STM(Software Transactional Memory)引擎實現並行處理,帶來性能的明顯提升。
1. 核心觀點
Move 出自大廠(Meta),被行業普遍看好,期間一些基於Move 語言開發的公鏈得到了市場的青睞和資本的追捧。為什麼基於Solidity 語言的以太坊生態如此龐大,市場依然對新公鏈有著新期待? Move 所擁有的優勢,彌補了Solidity 哪些不足?基於這些特點,Move 生態有可能誕生新模式和新應用。
本文對比Solidity 和EVM 存在的不足,分析了Move 的優勢與特點。
2. 為什麼發明Move:彌補Solidity(以太坊)的哪些問題?
Move 是Meta(原Facebook)公司為其Diem 項目(最初是全球穩定幣項目Libra)開發的一種安全可靠的智能合約語言,Aptos、Sui 等新公鏈使用的正是move 編程語言,這些公鏈正是看中了Move 的優勢及其並行處理特性,可拓展單片鏈的局限。 Move 是基於Rust 的編程語言,但是Move 專門針對智能合約進行開發優化,主要用於操作資源,因此入門門檻是低於rust 的。因為主要針對智能合約,因此砍掉了許多Rust 多餘的操作,更加簡潔。為了彌補Solidity 和EVM 出現的一些不足,Move 做了一些優化,使得基於Move 的Dapp 應用有著更多靈活玩法。
針對已有的編程語言如Solidity,Move 語言在很多細節設計考慮的比較周到,如將庫與應用邏輯分離開來;但最為突出的特點是資源類型方面,即面向資源的編程。在Dapp 應用支持方面,吸收了比特幣script 和以太坊的smart contract 的優點,因此行業普遍對該編程語言比較看好。而針對Solidity 被外界詬病的安全問題,move 也在嘗試解決。
2.1.一等資源與數字資產(first-class resource)
與其出現的背景相匹配,Move 是面向資源(resources) 的編程語言,資源在Move 的世界裡是「第一等公民」(first-class resource),其關鍵特性是自定義資源類型:resources 永遠不能被複製或隱式丟棄,只能在程序存儲位置之間移動。它可以像傳統的類型一樣,可以存儲在數據結構中,也可以作為參數傳遞。簡單的說,他就是傳統編程語言中一個不可隨意銷毀的新數據類型。對比Solidity 定義的資產,如以太坊上的某種Token 賬戶,資產只是一個數值,兩個賬戶之間發生轉賬後,賬戶資產數值相應的發生變化,不同賬戶資產的區別就是數值餘額,並無本質區別(也就是說資產是同質的)。同時需要注意,例如以太坊上ERC20 代幣TokenA,其是一個獨立的合約賬戶,這個合約為用戶(賬戶地址)分配一個數值,代表用戶擁有的Token A 的數量。從這一點可以看出,Solidity 並不是面向資源的,用戶的賬戶擁有某個Token 資產,只是該Token 合約分配給用戶的一個數值。
而Move 創建的Token 賬戶資產是獨一無二的資源類型,比如賬戶A 中的資產是保存在A 賬戶中的,雖然也是數值,但不能複制、丟棄或重用,可以被安全地存儲和轉移,用並不完全準確的比喻,可以認為A 賬戶中的資產與其他賬戶資產在某種意義上是不完全同質的。同時,賬戶資產只能由定義該資源的模塊進行創建和銷毀,這使得同質化的數值類型的資產可能產生的重入、類似雙花或者賬戶餘額出現不平衡的狀況得以避免。在這一點上,Move 賬戶資產有些類似比特幣的UTXO 機制,Token 不再是簡單的同質化數值,而是可區分的。為了可以實現更靈活的業務,Move 另外定義了4 種權限屬性:可複制(copy)、可丟棄(drop)、可存儲(store)、可檢索(key)。這4 種屬性可以任意組合,來定義資源的屬性,方便用戶靈活操作。如drop+store+key 的組合,定義的資源是不可以復制的,可以避免複製引發的代幣增發以及雙花的問題,這一點類似NFT 以及比特幣的UTXO 機制。
可以這樣理解,以太坊(Solidity)的資產是由相應的合約控制,如果把Token A 合約比喻為保險箱,保險箱會給所有用戶分配一個數值餘額,來表達用戶所有擁有的Token A 資產數量,但資產本身還是放在Token A 合約的保險箱內。而Move 用戶賬戶本身就是一個單獨的大保險箱,由用戶自己控制,所有的Token 資產都放在這個保險箱內。且這些Token 並不是以數字的形式存在,而是不可複制的、權限受用戶控制的資源(類型)。
Move 語言中的資源定義與權限是分離的,資源的權限屬於用戶。 Solidity 中賬戶資源權限歸屬於合約,比如以太坊上某個erc20 Token 屬於相應的合約,如用戶在DEX 如Uniswap 合約進行Token A(權限屬於Token A 的合約)兌換為Tokend B(權限屬於Token B 的合約)交易時,無法在Uniswap 合約裡直接提取自己的A 資產換為B 資產——因為Uniswap 裡資產的權限屬於其合約。實際的流程至少三步交易操作:i)首先對Uniswap 合約進行授權(approve),授權Uniswap 合約代用戶提取A 合約的資產;ii)進入Uniswap 合約進行兌換,提取A 後將B 存入賬戶;iii )取消授權(revoke)。但用戶一般不會在完成兌換後立刻取消授權(為後續可能還會進行兌換行為節省gas 費用),一旦Uniswap 合約受到攻擊或者出現漏洞,就為用的A Token 賬戶帶來風險。需要注意的是,授權/ 取消授權都需要在以太坊上執行合約操作,從而產生gas 費。從這裡我們可以清晰看到,Token A、Token B、Uniswap 裡的LP 資產權限分屬於各自的合約,用戶無法通過一個賬戶在三個合約之間自由切換。而Move 的資產大賬戶則不需要跨合約授權,權限是屬於用戶的,用戶直接在DEX 裡提取A、兌換為B 存儲到賬戶裡,這個過程可以在一個交易操作裡完成,無需授權/ 取消授權操作,一定程度上提高了安全性。
2.2. Move 語言的模塊化和靈活組合性
此前我們的深度報告《Web3.0 時代:開放、隱私、共建》中提出了Web3.0 與Web2.0 很大的區別在於開放性、可組合性。那麼這種開放調用從底層上是如何實現的呢? Move 語言又將提供哪些便利?
對於模塊化和合約組合性方面,Solidity(如以太坊)上面的Contract 合約通過library(相當於靜態庫)進行消息的傳遞,從而實現Contract 合約之間的調用、交互。而Move 語言使用了模塊(module) 和腳本(script) 的設計,前者類似於Contract 合約,Move 語言的合約組合性則是模塊之間的組合,通過傳遞資源(即前文提到的resources)。關於組合性方面,Solidity 和Move 的區別非常明顯。
以部署Token 合約為例,Solidity 的Token 作為一種服務存在,可以查詢餘額,而Move 的Token 則是一種資源,也就是上文提到的「永遠不能被複製或隱式丟棄,只能在程序存儲位置之間移動」。而這兩者之間的區別,可以這樣比喻:基於Solidiy 的合約之間調用是通過消息服務,如各類接口的調用,Solidity 上面的合約交互就好比是兩個原始部落之間的貿易交流,為了方便兩個部落之間的往來,需要統一生產工具和製作方法等標准信息——即兩合約之間的狀態同步,實現交互。 A 部落髮明了石斧頭,於是將這個石斧頭的用材標準、製作方法等信息告知B 部落,由B 部落自行生產(這就好比Token A 和Token B 分別由各自的合約控制)。注意這里為了安全,合約要保持隔離狀態,只能傳遞消息服務,但消息服務顯然是可以復製或被丟棄(將石刻信息擦除)。如果一個合約出現升級,如以太坊NFT 接口標準ERC 721、ERC 721A 和ERC4907 等系列優化升級,就好比A 部落髮明了鐵器,因此需要通過消息服務告知對方部落更新生產配置。一個合約的升級,需要調用過該合約的其他合約進行狀態同步,跟隨升級。這個工作流程無疑會增加複雜性,以太坊合約的升級迭代也是同樣複雜的,且會帶來EVM 的字節代碼膨脹。
Move 的世界,合約交互則更具備靈活組合性。還是上面的喻例,作為Move 的模塊(module) 之間交互(即部落之間的交易)是通過傳遞資源來實現的,這種優化相當於科技升級,A 部落並不是告知B 部落生產工具的配置信息,而是根據需求,將生產工具(無論是石斧頭還是升級後的鐵器工具)封裝在一輛型號合適的標準運輸車中,對方不必需升級生產配置,而是每次只需要接收車輛開走就行。換句話說,Move 的模塊之間交互傳遞的不是消息,而是乾脆傳遞了運輸車輛(這是一種資源,永遠不能被複製或隱式丟棄,只能在程序存儲位置之間移動的資源) 。無疑這種模式更具有靈活組合性,接收方收到車輛可以存儲,也可以轉移給其他方(其他合約),甚至可以將車輛貨物卸下來後分裝在不同的車輛裡。也就是說,一個Move 模塊的升級,其他使用過該模塊的合約自動會升級到最新狀態。
2.3.對Web3 安全性的改進
Move 語言帶來的安全改進是多方面的。
Move 語言的資源有四個屬性:可複制、可索引、可丟棄、可存儲,通過這四個屬性的不同組合,用戶可以方便的定義出任何類型的資源。 Solidity 的資產是由代幣合約賦予用戶賬戶的數值餘額,相比較,Move 無疑增加了資產的安全性。
Solidity 的資產是由相應的Token 合約賦予用戶的數值。而Move 規定資源會存儲在由所有者的帳戶控制的模塊裡,資源的所有者俱有最高決定權,只有所有者能夠決定資源(Resource)的存儲和轉移。操作權限分離,使得不同場景可以定義不同的權限,這也是安全的一面。
Move 資源的設計讓數字資產轉移不是賬戶間餘額數值的簡單加減,而是存儲位置間的移動(不可複制、不可丟棄),避免重入和雙花攻擊。重入指的是黑客抓住代碼漏洞,製造惡意合約,在用戶轉賬的同時再次調用轉賬函數(重入),在不改變賬戶餘額的情況下不斷提走資金。對於Solidity 語言Token 合約的賦值方案,重入攻擊和雙花的風險都很大。
另外,Move 的模塊工作模式也大大降低了系統風險——如前文所述,Solidity 合約升級需要其他合約作出相應的升級,否則將帶來安全隱患,而Move 的合約升級非常簡單,只需相應合約自身升級,並不需要其他合約作出更新,這在一定程度上規避了合約升級不及時帶來的安全風險。
2.4. Move 的並行處理帶來更高的擴展性
在交易執行方面,Move 的並行處理相交Solidity 帶來區塊鏈擴展性的極大提升。並行執行(PE)通過識別獨立交易並同時執行,這極大提升了區塊鏈的擴展性。 Solidity 並不支持並行處理,如以太坊上的交易按順序執行,其他交易置於暫停(排序)狀態——因此產生了mempool(內存池)和MEV 市場。對於兩個不關聯的交易,如果能夠並行處理,則高效且可擴展。
如基於Move 的公鏈Aptos,利用Block-STM(Software Transactional Memory)引擎實現並行處理,帶來性能的明顯提升。其工作理念類似以太坊二層網絡的Optimistic Rollup(樂觀匯總),交易在區塊內是預先排序的,先假設交易之間是沒有依賴關係,樂觀底執行並行交易。執行後驗證所有交易結果,如果發現一個交易訪問了由先前交易修改的內存位置,則該交易無效——因為很明顯兩個交易是相關的。刷新交易的結果,然後重新執行交易。重複該過程,直到區塊中的所有交易都被執行。 Block-STM 的特點是支持比較複雜的事物,適合多種應用負載工況。
如下圖,將Block-STM 與區塊按交易順序執行進行了比較。每個區塊包含一萬筆交易,賬戶數量決定了區塊處理的交易的競爭複雜程度。在低競爭和高競爭情況下,Block-STM 比順序執行的方案實現了8-16 倍的加速。當交易任務是順序的情況下,Block-STM 的消耗也更小。由此可見,Move 帶來的並發性能是非常突出的。
由此可見,在L2(二層網絡)之前,主鏈的並行處理能力亦是公鏈擴容積極考慮的方案。這為Move 生態帶來更多的可能性。