關於比特幣、以太坊、libra,咱們知道他們是不一樣的區塊鏈應用,那麼他們的根本差異在哪裏呢。
其實,單從白皮書的標題,就能夠大概看出三個項目在設計目標上的差別。程序員
那麼,「可編程貨幣」、「可編程應用」、「可編程資源」,這三者到底有什麼不一樣呢?
既然都是 「可編程 XX」 句式,他們的主要區別就在於兩點:
對什麼編程;
如何編程。
對什麼編程?編程
對什麼編程,是指系統所描述或者抽象的,究竟是現實世界中的什麼東西。安全
比特幣系統抽象的是 「貨幣」,或者說是 「帳本」 的概念。貨幣能夠用一個數字來描述,也就是某一個帳戶的 「餘額」。用戶能夠經過 「交易」,把一部分錢轉給別人。當比特幣網絡接收到一筆交易的時候,每一個節點都會檢查交易是否合法,好比你花的是否是本身的錢,有沒有足夠的餘額(比特幣不容許透支)。當這些檢查都成功後,節點會作一個簡單的加減計算:在你的帳戶中扣減轉帳的數額,並在對方帳戶中加上一樣的數量。所以,比特幣惟一的功能就是記帳,保證在帳戶彼此轉帳的過程當中,貨幣的總量不會莫名其妙的增長或減小(不考慮挖礦獎勵和黑洞地址等特例)。網絡
以太坊系統抽象的是 「應用」,應用的種類一應俱全,好比遊戲、借貸系統、電商系統、交易所等,這些都是應用。理論上講,任何傳統的計算機程序均可以移植到以太坊上。所以,以太坊中記錄的是各類應用的內部數據(即 「合約狀態」),好比一個電商系統的庫存、訂單、結算信息等。這些信息沒法用一個簡單的數字來描述,必須容許用戶定義很是複雜的數據結構,而且容許用戶經過代碼(智能合約),來對這些數據進行任意所需的操做。固然,這些應用也包含了 「貨幣帳本」。事實上,目前在以太坊上應用最普遍的正是此類應用(稱爲 「ERC20 智能合約」)。因爲以太坊把這類應用看做是平臺所能支持的多種應用中的一種,與其餘類型的應用相比,並無什麼特別之處,因此也就沒有針對此類應用提供更多的安全保護,只提供了相似 ERC20 這樣的接口規範。一個在以太坊上新發行的 「貨幣」,其轉帳邏輯的正確性徹底由開發者負責。
在以太坊的存儲結構中,ERC20代幣 的帳本是 「二級對象」,和 ETH 原生代幣餘額存儲在不一樣的地方。例如上圖所示,0x0,0x1 和 0x2 是三個以太坊地址,其中,0x0 和 0x2 是普通帳戶地址(External accounts),而 0x1 是一個合約地址(Contract accounts)。咱們能夠看到,每一個帳戶都存儲了一個 ETH 的餘額,這個數據是頂級對象 (First-Class Object)。在合約地址 0x1 中,還存儲了一個智能合約代碼 MyCoin,它是一個 ERC20 代幣應用。而 MyCoin 這個代幣的整個帳本,都存儲在 0x1 的空間中,怎麼修改都由 0x1 中的合約代碼說了算。數據結構
不管是有意仍是無心,ERC20代幣 很是容易出現安全漏洞。也就是說,在以太坊系統中,原生代幣 ETH 和用戶發行的代幣並不享有一樣的安全級別。app
那麼,可否不那麼走極端,試圖去抽象一些比簡單數字更復雜的資產類型,而又不追求一應俱全的 「通用性」 呢?這正是 Libra 的出發點。Libra 能夠定義相似一籃子貨幣、金融衍生品等比貨幣更復雜的資產類型,以及如何對他們進行操做,這種資產被稱爲 「資源」。Move 經過限制對資源的操做來防止不恰當的修改,從而提升資產的安全性。不管資源的操做邏輯如何,都必須知足兩個約束條件:electron
這種資產的存儲方式並不是 Libra 首創,在此前的一些公鏈中已有應用,例如在 Vite 公鏈中,用戶發行的幣種餘額也是頂級對象。不過 Move 能夠支持更爲複雜的資產類型,並對其提供額外的保護,這是 Libra 的主要貢獻。編程語言
編者組: Vite 是本文做者建立的項目。區塊鏈
咱們再來看看三個項目如何經過編程來實現豐富的擴展性。ui
在比特幣中,定義了一種 「比特幣腳本」,用來描述花一筆錢的規則。比特幣是基於 UTXO 模型的,只有知足了預先定義的腳本規則,才能花費一筆 UTXO。經過比特幣腳本,能夠實現 「多重簽名」 之類的複雜邏輯。比特幣腳本是一種很是簡單的基於棧的字節碼,不支持循環之類的複雜結構,也不是圖靈完備的。雖然利用它能夠在比特幣網絡上發行新的貨幣(Colored Coins),但它的描述能力很是有限,對開發者也不友好,沒法應用到更復雜的場景中。
在以太坊中,定義了一種 Solidity 的編程語言,能夠用來開發 「智能合約」。智能合約代碼能夠編譯成一種基於棧的字節碼 ——EVM Code,在以太坊虛擬機 EVM 中執行。Solidity 是一種高級語言,參考了 C++、Python 和 Javascript 的語法,是一種靜態類型、圖靈完備的語言,支持繼承,容許用戶自定義複雜的類型。Solidity 更像是一種通用的編程語言,理論上能夠用來開發任何類型的程序,它沒有針對貨幣或者資產類型的數據,在語法和語義上作任何限制和保護。好比用它來開發一個新的代幣合約,代幣的餘額一般聲明爲 uint 類型,若是編碼時對餘額增減邏輯的處理不夠當心,就會使餘額變量發生溢出,形成超額鑄幣、隨意增發、下溢增持等嚴重錯誤, 如: BEC 智能合約的漏洞。
再來看 Libra,它定義了一種新的編程語言 Move,這種語言主要面向資產類數據,基於 Libra 所設定的 「頂級資源」 結構,主要設計目標是靈活性、安全性和可驗證性。目前,Move 高級語言的語法設計尚未完成,白皮書只給出了 Move 的中間語言(Move IR)和 Move 字節碼定義。所以咱們沒法評估最終 Move 語言對開發者是否友好,但從 Move IR 的設計中,能夠感覺到它在安全性和可驗證性方面的特色。
下面咱們來簡單介紹一下 Move 的語法。Move 的基本封裝單元是 「模塊」(Module),模塊有點相似於以太坊中的 「智能合約」,或者面嚮對象語言中的 「類」。模塊中能夠定義 「資源」(Resource)和 「過程」(Procedure),相似於類中的 「成員」(Member) 和 「方法」(Method)。
全部部署在 Libra 上的模塊都是全局的,經過相似於 Java 中的包名 + 類名的方式來引用,例如 0x001.MyModule,0x001 是一個 Libra 地址,MyModule 是一個模塊名。模塊中的過程有 public 和 private 兩種可見性,公有過程能夠被其餘模塊調用,私有過程只能被同模塊的過程調用。而模塊中的資源都是私有的,只有經過公有過程才能被其餘模塊訪問。並且,外部模塊或者過程對本模塊資源的修改受到嚴格的限制,惟一容許的操做就是 「移動」(Move),不能隨意對資源賦值。例如,Move 中是不容許出現一個相似於 MyCoin.setBalance() 這樣的接口,讓其餘用戶有機會隨意修改某個幣種餘額的。
除了受限的資源類型,Move 模塊中也容許定義非受限的成員,被稱爲非受限類型(Unrestricted Type),包括原生類型(boolean、uint6四、address、bytes)和非資源類的結構體(struct)。這些非受限類型就沒有那麼嚴格的訪問限制,能夠用來描述與資產無關的其餘應用類數據。從這個角度來講,Move 語言理論上應該具備和 Solidity 一樣的描述能力,但因爲實際的去中心化應用中,總會涉及到資產類的數據,而任何引用了資源類型的結構體也都是受限的,可以真正脫離 Move 語言嚴格限制的機會並很少。因此在實際使用 Move 語言開發的時候,程序員必定會有一種戴着鐐銬跳舞的感受,代碼出現編譯時和運行時失敗的可能也更大。
通俗的說,用 Move 寫代碼不會讓你感受 「很爽」,這就是安全性和可驗證性的代價。想一想你用 C 語言本身控制內存的分配和釋放時,雖然有一種 「我是上帝」 的感受,但也會時刻憂慮緩衝區溢出、內存泄露等潛在風險;而用 Java 語言開發,雖然你再也不可以隨心所欲的控制內存,但也不用擔憂這些內存安全性問題了。自由仍是安全,每每是不兼得的。
在一個 Libra 的交易(Transaction)中,也能夠嵌入一段 Move 代碼,被稱爲交易腳本(Transaction Script)。這段代碼不屬於任何模塊,是一次性執行的,不能再被其餘代碼調用。腳本中能夠包含多個過程,經過 main 過程做爲入口來執行,在其中也能夠調用其餘模塊中的過程。這個設計有點相似比特幣,而和以太坊徹底不一樣。在以太坊中,一個交易自己是不能包含一段可執行代碼的,只能部署新合約或者調用一個已部署的合約。我不太喜歡 Libra 的這個設計,因爲任何 Move 代碼都必須通過字節碼驗證器(Bytecode Verifier)的嚴格檢查才能發佈到鏈上,這種一次性代碼的邊際成本遠遠高於可複用的模塊,會拖慢交易被確認的速度,下降系統的吞吐量。交易腳本並非必須的,大部分現實場景均可以經過模塊來覆蓋,並且,它的存在還增長了 Libra 錢包的開發和使用難度,有機會的話我會向 Libra 的開發團隊提議取消這一設計。
本文內容首發於深刻淺出區塊鏈技術博客,點擊解讀 Libra Move:一種可編程資源語言看一下白皮書中的示例代碼片斷,直觀感覺Move 語言,進一步瞭解move虛擬機等。