1. 程式人生 > >以太坊《私有鏈和聯盟鏈的機會與挑戰》報告

以太坊《私有鏈和聯盟鏈的機會與挑戰》報告

以太坊平臺評估 私有鏈和聯盟鏈的機會與挑戰
作者:Vitalik Buterin 
翻譯:萬向區塊鏈實驗室/ChinaLedger 聯盟 
排版/校對:區塊鏈鉛筆(ChainB.com)
(注:本文屬於學習資料,請勿用於商業用途。轉載請註明作者與出處。)

以太坊平臺的構想最早是在 2013 年 11 月提出來的,當時的目標是建立一個 更通用的區塊鏈平臺——通過工作量證明機制(或最終轉換成權益證明機制)實 現了公共經濟共識的概念,並將其與狀態豐富的圖靈完備虛擬機器的抽象能力結合 起來,從而讓應用程式開發者更容易地建立區塊鏈上的應用程式,並能受益於區 塊鏈的去中心化和安全的特性,特別是避免了為每一個新的應用程式建立一個新 區塊鏈的麻煩。

而之前曾經出現過的區塊鏈協議可以視為是單一功能的工具,就如口袋中的 計算器,即使在好一點的情況下也就像瑞士軍刀這樣的多功能工具而已;以太坊 則是區塊鏈中的“智慧手機”:它是一個通用的平臺,你可以在上面搭建自己需 要實現的功能,就如搭建一個“APP”一樣,以太坊的使用者將會即時接觸到它能 提供的好處,而不需下載任何新的軟體。

雖然這個專案原本是作為“Mastercoin 功能升級提議”的一部分提出來的 (目的是為金融合約提供支援),後來專案的關注點擴充套件到了更廣泛的應用領域, 包括金融合約,下注,數字代幣(資產)發行,去中心化檔案儲存激勵機制,投 票,“去中心化自治組織”等。以太坊平臺開發的資金是通過在 2014 年 8 月的 一場眾籌活動籌集回來的。自從那時起,平臺上已經出現了超過 100 個應用程式, 範圍包括金融清算和結算,到保險,數字資產發行,甚至是非金融領域的應用(包 括投票和物聯網)。

基礎設計

有的區塊鏈都有一個“歷史”的概念——所有之前的交易、轉賬及其發生順 序的集合,以及“狀態”——決定某個給定交易是否有效以及在交易處理後狀態 將會如何改變的“當前相關的”資料。區塊鏈協議同時有一個“狀態轉換規則” 的概念:基於之前的狀態,以及一個給定的交易,(i)這個交易是有效的嗎? 還有,(ii)在交易發生後,狀態會是什麼?

我們可以用比特幣 1 給出一個例子。在比特幣中,狀態是賬戶餘額的集合(如 地址 39BaMQCphFXyYAvcoGpeKtnptLJ9v6cdFY 有 522.11790015 個比特幣,地址 375zAYokrLtBVv6bY47bf2YdJH1EYsgyNR 有 375 個比特幣......)。狀態轉換功能取得傳送者的地址、目標地址以及一個值,然後詢問:(i)這個交易已經由發 送者用密碼學的方式正確簽名了嗎?還有(ii)傳送者的賬戶裡面有足夠的位元 幣用於本次的傳送嗎?如果其中一個問題的答案是否定的,那麼交易就是無效的, 並且不能被包含到一個區塊裡面。如果一個區塊包含了當前狀態下的一個無效交 易,那麼這個區塊就會被網路忽略掉 2。如果兩個問題的答案都是正確的,那麼 交易的價值就會從傳送者的餘額中抽離出來,並新增到接收者的餘額中。

在以太坊中,相關的設計會更復雜一些。狀態可以被視為是所有賬戶的集合, 而每一個賬戶要不就是“外部擁有的賬戶”(EOA,externally owned account) 或一個合約(contract)。如果賬戶屬於 EOA,則狀態會簡單地儲存這個賬戶的 以太幣餘額(以太坊的內部加密代幣,其功能,類似比特幣或 XRP)以及一系列 用於防止重複支付攻擊的序列號。如果賬戶是一個合約,則狀態會儲存合約的代 碼,以及合約的儲存空間——一種鍵值資料庫(key-value database)。

在以太坊中一個交易會指定(跟其他的一些所需資訊一起,這會在後面會提 到)一個目標地址、用於交易的以太幣數量,以及一個理論上能儲存任何資訊的 “資料”域(另外,還有一個傳送人的地址,不過這在簽名裡已經指定了,因此 這裡沒有專門說明)。如果一個交易是對 EOA 或一個尚未存在的賬戶發出的,則 它除了簡單地作為傳送以太幣的手段外,並沒有其用途。如果一個交易被髮送到 一個合約裡,則會執行合約的程式碼。這個程式碼有能力實現:
 讀取交易資料。
 讀取交易中被髮送的以太幣餘額。
 讀取或寫入合約自己的儲存空間。
 讀取環境變數(如時間戳,區塊難度,前一個區塊的雜湊值)  向另一個合約傳送一個“內部交易”。

本質上說,你可以將合約視為是儲存在以太坊的狀態裡的一類“虛擬物件”, 它可以包含自己內部的永久儲存空間,並有能力像外部使用者一個擁有對其他合約 的操作許可權和關係。內部交易是由合約建立的一種交易;就如普通的“外部”交 易一樣,它也包含了一個明確的傳送者、目標地址、以太幣數量以及資訊資料,如果一個內部交易被髮送到一個合約,則合約的程式碼就會執行起來;在合約執行 結束後,合約的程式碼將有能力返回 0 或更多位元組數的資料,可以讓內部交易用於 “詢問”其他合約去獲取特定的資訊。一個交易(transaction)可以建立一個 新的合約——通過將合約的程式碼放置在交易的資料中(目標地址不進行設定), 或通過 CREATE 這個操作程式碼(opcode)從合約的內部實現這個功能。

簡單地說,在以太坊的公有鏈上,合約機制是以如下的形式被使用的:
 作為一個追蹤使用者發行資產(issuer-backed assets)的資料庫;
 作為一個可控制其他資產的“智慧合約”(下面會詳細介紹這個概念), 並將根據特定的條件將這些資產傳送到特定的參與方;這通常會進一步分解 成幾個子類別,包括(i)金融合約(如差價合約,二元期權,衍生品), (ii)擔保交易(實施“無需信任的數字資產原子化互換”),(iii)多 方協議,如拍賣,保險合約,鼓勵披露特定資訊的經濟遊戲等;
 作為一個基於區塊鏈的域名系統的註冊記錄管理;
 作為一個代表使用者或機構的賬戶,不過擁有複雜的訪問許可權控制,如多 重簽名;
 作為“軟體庫”,讓程式碼可以寫入、釋出到區塊鏈上,並由其他的人使 用;

“智慧合約”的概念通常被簡單地定義為“一個直接控制數字資產的電腦程 序”3,這是特別重要的。合約有它們自己的地址,因此可以像使用者一樣作為數 字資產的持有者瞭如果一個合約真的“擁有”數字資產,這意味著(i)只有合 約自己的執行過程能夠向另一方傳送資產,還有(ii)每一個參與方在區塊鏈上 可以看到並檢驗這個資產真的在程式的控制下。

例如,你可以在無需信任的情況下實現資產 A 與資產 B 的交易——通過資產 A 的擁有者將資產傳送到一個程式裡,這個程式的程式碼定義了“如果我在 24 小 時內收到資產 B,則我會將資產 A 傳送到傳送人的地址裡,並將資產 B 發給我的 建立者,否則我將會把資產 A 傳送回我的建立者”。資產 B 的擁有者可以看到該 合約確實控制了資產 A,而且知道一旦他們將資產 B 傳送到合約的賬戶,合約將會進行一個公平、正確的交易。合約並沒有“擁有者”(owner)這個概念;當 資產 A 的原始擁有者把該資產傳送到合約裡,則他們就無法通過操縱這個合約把 資產拿回來,而是隻能等待交易成功完成並接收所交換到的資產 B,或者 24 小 時後,若交易還是沒有成功,則他們會自動地拿回資產 A。

以太坊區塊鏈在較高的層級上有點像比特幣的區塊鏈。最主要的也是最重的 ——區塊鏈由一系列的區塊所組成,每一個區塊包含指向前一個區塊的指標,以 及一個經過排序的交易列表。區塊是由工作量證明所維護的,“最長的鏈”(由 整體難度決定)定義了一系列經過確認的交易及其執行的順序。

為了到達以太坊區塊鏈上的“當前狀態”,節點可以從“初始狀態”開始(這 是一個內嵌在每一個以太坊客戶端裡的、所有人都認可的初始狀態),並處理每 一筆交易,並按順序執行由交易處理和程式碼執行過程所帶來的餘額/序列號/程式碼 /儲存的變化。比特幣裡面也有同樣的過程;雖然以太坊對交易執行過程“狀態 變化”模型的重視是獨特的(在比特幣中,交易通常被視為花費來自歷史上前一 個交易的“輸出項”,而不是狀態裡的某個物件)。但以太坊、比特幣和瑞波、 狗狗幣等協議裡,程式碼在這部分工作中的執行模式大體上是一樣的。

以太坊使用了記憶體需求較高的雜湊函式,uncle 激勵機制,難度調整演算法, gas 限制調整演算法等,這些都是以太坊的一些值得注意的不同之處,不過這些都 是優化工作,可以說在以太坊的本質中並不是處於中心的地位。

以太坊中另一個值得注意的特性(比特幣中沒有的)是 Merkle 樹的深度使 用,讓“輕客戶端”可以只下載和校驗區塊的頭資訊,同時也能在有需要的時候決定並安全地對區塊鏈狀態的任何特定部分進行校驗。而在比特幣中,一個區塊 頭只儲存包含交易的 Merkle 樹的根雜湊值(root hash),在以太坊中每一個區 塊投包含了一個“狀態根”(state root),實質上是包括了整個當前狀態(賬 戶餘額,序列號,程式碼和儲存)的密碼學雜湊樹的根雜湊值。

因此,輕客戶端通常可以只下載區塊頭(每 17 秒約 500 位元組),如果輕客 戶端需要了解狀態中的某個特定數值(如“賬戶 0x124b6f72 中的餘額是多少?” 或“賬戶儲存空間中鍵值為 178233 的記錄對應什麼資料?”),它就可以請求網 絡中的任何“完全節點”提供一個“分支”——這是(Merkle)樹結構中的資料 區塊構成的一系列雜湊值,指定了直到樹根部的特定資訊,而輕客戶端可以自己 驗證該分支的完整性。如果該分支是正確的,它就接納這個答案。“輕客戶端” 模式對那些使用智慧手機和物聯網/嵌入式裝置的以太坊使用者是很有用的,對那 些電腦效能較低、網路頻寬較差的使用者也是很有用的。

以太坊的私有鏈和公有鏈

需要注意到,雖然以太坊原來是以公有鏈的形式存在的,但以太坊的狀態轉 換規則(即協議中處理交易、執行合約程式碼等的部分)可以從以太坊的公有鏈共識演算法(如工作量證明)中抽離出來,因此完全可以建立執行以太坊程式碼的私有 鏈(在一個節點上執行,這個節點由一個公司控制)或聯盟鏈(由一系列預先指 定的節點執行)。4 以太坊技術自身因此可謂是與具體的應用場景不相關的—— 無論是用於公有鏈、聯盟鏈或私有鏈的模式,因此我們的目標是讓以太坊的多種 例項的互操作性實現最大化——如可以將為以太坊公有鏈書寫的合約和應用程 序匯入到以太坊的私有鏈中,反過來也一樣。

現在,在私有鏈的應用場景中已經有幾個版本的以太坊在進行開發了,如 Hydrachain。私有鏈版本的以太坊實施方案在理論上會一些可擴充套件性方面的提升, 但若這些特性要應用到公有鏈版本的以太坊上,還是需要完成不少的工作。

金融領域中的應用

雖然以太坊是一個高度通用化的平臺,其用途理論上是很廣泛的,但以太坊 上的主要應用專案還是具有某些金融特性。這些應用專案可以進一步分解成“純 金融性的”,即只進行有價金融資產管理、建立金融合約、擔保交易等;另一種 是“半金融性”的,將一些本身並非金融應用的服務與金融、支付用例結合起來。

後一個類別的例子由很多,從“去中心化的 Uber”平臺,到專注於機構服 務的貿易融資專案(如在 2016 年 1 月贏得上海區塊鏈黑客馬拉松大獎的 CargoChain),這些專案都利用了以太坊區塊鏈的數字資產管理和智慧合約功能 及其在金融應用領域之外的功能,將以太坊用作一個航運記錄跟蹤、聲譽和評價 資訊,以及為簽訂的法律合約提供存在性證明的資料庫。

在“純金融性應用”的方面,我們可以看到:
 基於區塊鏈的金融合約和衍生品處理平臺(如Clearmatics);
 在區塊鏈上實施的其他金融工具(如UBS的“智慧債券”平臺);
 從黃金(如DigixGlobal)到以法幣計價的“結算幣”這類對現實世界 資產進行數字化的應用,為金融交易和簡單的主流支付服務;
 使用區塊鏈實現差價合約(CFD),用智慧合約執行,並用無對手風險的 加密貨幣進行抵押品管理和結算工作,以建立對映現實世界資產的“映象資產”,在那些有足夠流動性和套利空間的市場中提供對底層資產的相同回報 率。
 基於區塊鏈或基於智慧合約的抵押品管理。

有一類非金融領域的區塊鏈應用所提供的服務本來在金融平臺上就是很有用的(無論是否基於區塊鏈技術);或許最佳的例子就是身份驗證系統。

為你的應用評估以太坊私有鏈或公有鏈的適用性

評估以太坊在這些應用上的適用性涉及兩個主要的步驟。第一步是去決定區 塊鏈是否真的適合做這個事情。區塊鏈的基本技術優勢包括可靠性,安全性,可 審計性以及去中心化,這些都是人們瞭解得比較多的,不過人們考慮得比較少的 則是這些特效能在什麼場所發揮作用。主流的支付系統需要依靠聯盟資料庫或公 共資料庫去實現密碼學意義上的可審計性及去中心化嗎?證券交易呢?航運或 航空票務市場呢?或檔案儲存、計算呢?商家的積分計劃呢?在非金融應用那邊, 若要對不同的現實世界資產或數字資產(如域名)的所有權進行追蹤呢?電子郵 件和社交網路應用呢?

這樣,我們就面臨一個選擇了——公有鏈和私有鏈哪種更合適?可以這麼說, 以太坊的優勢在公有鏈或聯盟鏈上是有所不同的。在公有鏈上,除了能夠實現程 序化的擔保交易和金融合約外,以太坊能提供的一個好處是協同性,正如一位以 太坊應用程式開發者最近描述過的那樣。以太坊中的合約可以滿足不同的功能, 而每一種建造在以太坊之上的應用程式在理論上可以利用其它應用程式提供的 功能。

例如,如果你希望用區塊鏈去管理公司股份的所有權,那麼從安全性和可校 驗的記錄管理角度來看,這個工具確實是很有用的,但另一個好處是讓股權眾籌 變得更簡單了:公司可以將股份轉移到一個智慧合約中,任何人若將 Y 個單位的 加密貨幣 Z 傳送到該合約,該合約就會自動往他的賬戶中返回 X 個單位的股份, 而合約中的這些錢若要提取出來,必須經過 5 個董事中的 3 個人的授權。如果公 司所在地有相應的監管要求,需要進行某種形式的 KYC(瞭解你的客戶)認證或 對投資者的身份進行限制,只要有人在以太坊上設計了一個基於區塊鏈的 KYC和認證平臺,前面提到過的這個股權眾籌平臺以及其他的股權眾籌平臺(也可以 是廣義的金融應用專案)可以立刻與該身份認證系統進行互動,並往合約中新增 相應的限制,要求只有經過授權的個人才能達成有效的股權購買行為。

具體來說,我們可以認為協同性是以太坊和所謂的“雙層”區塊鏈智慧合約 系統(如現在已經停止了的 Codius 專案)的主要差別,後者將區塊鏈當成是一 個純粹用於追蹤資產所有權的層(甚至是更“傻瓜化”的純資料層),並要求每 一個應用程式通過多重簽名“公證人”或讓使用者獨自處理區塊鏈並“解讀”其結 果的方式單獨去處理智慧合約;協同性的設計目標是讓應用程式就智慧合約執行 結果正確性的來源達成共識(每一個人都同意這個來源是安全的),因此在協議 的層面引入這種機制將鼓勵其作為共識演算法的一部分從而實現公共利益,是有經 濟意義的。

在私有鏈中,論點就有所不同了。私有鏈通常是用作為特定產業建立結算平 臺的工具,通過構建一個實質上是唯一的、共同的資料庫,讓機構之間的交易處 理效率趕上機構內的交易處理效率。私有鏈的理想“使用者”實質上是一個在一定 程度上已經去中心化的產業,這產業裡面沒有一個公司擁有超過略高於兩位數的 市場份額,不幸的是,這種去中心化的狀態在當前的技術水平下明顯降低了效率: 如果一個公司的客戶希望與其他公司的另一個客戶進行某種互動(如傳送付款, 執行交易等),就需要一個繁瑣和笨重的機構間對賬和結算過程,這通常帶來了 明顯的費用以及延遲。使用區塊鏈的話,當前的“半去中心化”的產業“政治架 構”照樣可以儲存下來——並不需要說服所有的參與方進行合併或成為某個超級 公司的客戶,更不需要說服那些有反壟斷政策的監管者同意這種合併。同時,通 過技術上的簡單變革,得到了大規模的網路效應和高度的互操作性的好處。

另一個潛在的好處是通過“分離關注點”的做法提高金融產業的效率:銀行 並不需要親自對每一種類別的金融應用進行創新,而是可以將這個任務交給更靈 活的金融企業,這些企業正在往類似軟體提供商這種角色的方向發展,它們可以 幫助使用者在區塊鏈上傳送經過密碼學簽名的交易、執行交易、以及達成涉及有對 應背書資產的代幣相關的合約,而不需自己對實際的資產進行託管(因此降低了它們自身的監管負擔),而銀行還是會保留它們的核心業務——接收存款,以及 發放貸款。

在私有鏈的場景中,協同性就顯得沒那麼重要了,因為每一個私有鏈更有可 能被設計成專門針對某種特定應用。不過,還是有可能實現某種程度上的“私有 鏈間互動”或“公有鏈與私有鏈互動”這樣的協同模式。現在已經有一些針對跨 鏈資產交易這種特定用例的嘗試了,包括 TierNolan 的跨鏈互換協議,以及 Interledger 最近釋出的一些成果;然而,以太坊的策略更具雄心壯志,尋求創 造更通用的“搭橋”機制,讓從一個區塊鏈讀取另一個區塊鏈的內容成為可能(例 如,BTCrelay 是比特幣和以太坊之間的橋),長期的目標將會是整合一個通用 的非同步程式語言,讓應用程式可以跨越多個區塊鏈開展。若這是一個有較高需求 的特性,則計劃中的以太坊 2.0 的很多技術可以重點去達成這些目標;若這個功 能被認為重要性不高,則以太坊的功能就會受限在智慧合約和未來的可證明性上, 至於“傻瓜區塊鏈”和“智慧區塊鏈”之間的取捨及其效率與複雜性的平衡,這 是要由使用者去決定的。

當一個公司決定區塊鏈是可行的策略時,它就需要選擇具體的平臺。以太坊 的好處是可程式設計性,靈活性,協同性,模組性,以及容易使用的哲學思想——畢 竟,我們現在和未來五年內都不太可能完全分析清楚開發者們到底需要什麼樣的 特性。如果公司的法務研究工作決定某類特定的應用需要 KYC(瞭解你的客戶) 認證、登記限制或其他規則,那麼身份認證可以作為一個獨立的層進行搭建,並 可以書寫直接接入這個系統的合約。在一個股份可以被私下進行交易的公司裡, 你希望股份登記在區塊鏈上,而且希望增加一個限制,即只有經過 51%的現有股 東同意才能增加新的股東,這樣你還是可以在不改變基礎層或系統的其他部分就 可以實現這個目的。

即使是對如支付這樣簡單點的應用來說,剛開始時在以太坊之上搭建這種應 用,可以快速地在基礎的資產層上整合更高階的應用功能,如金融合約,抵押品 管理,無需信任的原子化互換等,這樣將來需要這些功能就可以輕易地新增上去。 以太坊未來的版本將會繼續這種“未來相容性”,甚至將其擴充套件到連密碼學的層 面——使用者甚至可以選擇用於保護其賬號的密碼學演算法。例如,如果你對量子計算機(譯者注:具有強大運算效能,對一些加密方法帶來威脅)感到擔憂,而且 想快速地升級到 Lamport 簽名機制,就可以如願以償,無需等待整個區塊鏈的協 議的進化。

自然而然地,有些人認為“如果能用一種簡單的工具去完成一項任務,就不 要用複雜的工具了”,隨之而來的還有認為以太坊的通用性或其實施的特定方式 帶來了特定的效率問題。前一種論點需要就具體的專案進行具體的分析,並與以 太坊的特性進行對比;後面的論點將會在接下來的以太坊路線圖中進行詳細討論。

以太坊開發路線圖概要

以太坊專案當前預期的里程碑目標將會在下面的章節展開討論:
 Metropolis:Mist瀏覽器的釋出,預計在2016年的夏天或秋天;
 Serenity (“以太坊 1.5”):釋出區塊鏈的 PoS 股權證明(Casper)版本, 同時包含以太坊改善提議(EIPs)101 和 105。這計劃在 2017 年早期實現。  WebAssembly 釋出 (“以太坊 1.75”):更快的虛擬機器。預計在 2017 年 到來。
 以太坊2.0(尚未命名):初步可擴充套件性提升的版本。預期在2017年晚 期實現。
 以太坊3.0(尚未命名):“沒有限制的”可擴充套件性版本,預計在2018 年晚期實現。

這些名字在接下來的章節中將會被大量使用。

安全性

(以太坊)作為一個在大範圍內複製、共享賬本的圖靈完備狀態機,能讓世 界上任何能購買 0.3 美分價值以太幣的人上傳程式碼,然後網路中的每一個參與者 都必須在自己本地的機器上執行這段程式碼,這確實是會帶來一些明顯的與安全性 相關的憂慮。畢竟,其他的一些平臺也提供類似的功能,這包括了 Flash 和JavaScript——它們經常碰到“堆與緩衝區溢位攻擊”,沙盒逃逸攻擊以及大量的其他漏洞,讓攻擊者可以做任何事情,甚至包括控制你的整臺計算機。除此之 外,還會有拒絕服務攻擊(D.D.O.S.)——強迫虛擬機器去執行無限迴圈的程式碼。

為解決這些挑戰,以太坊專案引入了不少的策略。首先,以太坊的虛擬機器的 架構是高度簡化和受限的,之所以要從頭搭建一個全新的虛擬機器而不是用如 Java 這樣現有的虛擬機器,是為了實現虛擬機器的高度安全性。與訪問系統資源、 直接讀取記憶體或與檔案系統互動的操作程式碼(Op Codes)在 EVM 以太坊虛擬機器的 設計規格中是不存在的;與此相反,唯一存在的“系統”或“環境”操作程式碼是 與以太坊“狀態”裡定義的架構進行互動的:虛擬機器記憶體,堆疊,儲存空間,代 碼以及區塊鏈環境資訊(如時間戳)。

以太坊虛擬機器的大多數實施方案是解釋型的,不過有一個由 JIT 編譯的虛擬 機已經被開發出來了。以太坊虛擬機器(以及以太坊協議的其他部分)已經有 6 個實施版本了,也經歷了超過50000個單元測試,以確保完美的相容性和確定性 的執行結果。7 Go語言、C++和Python語言的實施版本在我們的安全審計機構 Deja Vu 的幫助下,已經進行了深度的安全性審計。在以太坊釋出後的幾個月時 間裡,發現過幾個需要修復的安全性漏洞,不過這種事發生的頻率已經大幅度降 低了:在本文行文前的兩個月,以太坊網路一直在正常執行,而沒有發現任何明 顯的安全性漏洞。

無限迴圈攻擊的解決方案是最複雜的。總體上說,任何圖靈完備的程式語言 在理論上都是會碰到“停機問題”的,即不可能預先確定給定程式在給定的輸入 值下進行執行是否會出現停機問題。其中一個例子就是考拉茲猜想(Collatz Conjecture)。假設有如下的程式:

該猜想認為,如果你使用任何輸入值去執行這個程式,這個程式最終會停止, 不過我們並不能證明這一點;若在找到一個反面例子的情況下我們就可以證明“並不是這樣的”,但現在人們已經嘗試過 1 萬億以上的輸入值了,也沒能找到 這樣的一個反面例子。因此,這帶來了一個憂慮——攻擊者可以建立一個合約, 裡面包含一些混淆的無限迴圈程式碼,然後往這個合約裡面傳送一筆交易,從而將 系統拖垮。

以太坊解決這個問題的概念是汽油(Gas):交易的傳送者定義他們授權代 碼執行所需的最大計算步數,然後為此支付相應比例的以太幣。在實際中,不同 的操作過程需要耗費不同的 Gas 數量,這些耗費的標準不僅是基於執行每一種操 作過程所需的運算時間,還包括如全節點儲存以及記憶體耗費等考量因素,所以 Gas 並不只是一個用於統計運算步數的標準,不過我們初步就理解成“Gas=計算 步數”吧,這對理解 Gas 的用途基本上足夠了。

若在執行交易的過程中“Gas”被耗盡了,如超出了其允許的最大計算步數所需的預算,則交易的執行會被回滾,但交易還是正確的(只是不再有效了),傳送者照樣要付相應的費用;因此,交易的傳送者必須在下面兩種策略之間進行取捨:設定一個更高的 Gas 限額,這可能會支付更高的交易費;或設定一個較低的 Gas 限額,這樣可能會創建出一個會被回滾的交易,就需要以一個更高的限額重新發送一遍了。資訊(譯者注:可用於合約間互動的一個特性)本身也可以設定 Gas 的限額,因此可能讓一個合約與其他合約進行互動,而無需擔心其他合約會無節制地消耗自己的合約裡的 Gas“預算”。這個機制已經被密碼學學者 Andrew Miller 及其他人審查過了,其結論是這個機制確實能實現逃過停機問題的目的,並以經濟學的方式分配運算能力,不過在某些邊緣案例中激勵機制可能不是一個 最優解 9。

第三個安全性問題在較高的層面展現出來:若我看到某人提供的一個智慧合 約,上面寫著它是一個二元期權合約,需要收取 10 美元的費用,而且若 3 月 30 日的金價超過 1100 美元時則會向你支付 20 美元——我如何知道這是真的呢?如 果這是一個合約,用於管理整個市場內的二元期權合約,讓使用者可以出價、投標、 完成交易,我如何知道這個合約沒有能讓作者拿著所有的錢跑路的後門呢?一個 更好的問題是,假設這個合約的作者程式設計水平有限,他們如何知道自己寫出的程 序程式碼沒有漏洞,讓大家永遠都沒法將錢從合約中拿走呢?

上述的兩個問題——程式設計師作惡和程式設計師出錯——是獨立的問題,而解決問 題也有所不同,但兩者之間還是有共同點的。以太坊裡面臨的挑戰對應兩類解決 方案,分別是低科技的和高科技的解決方案。高科技解決方案在理論上能提供更 好的希望,不過會帶來整合的難度,以及更依賴於複雜的工具。而針對作惡問題 的低科技解決方案有兩個層面。第一,在以太坊裡,我們明確以下兩者的區別, 即應用程式的核心(純粹由智慧合約的集合構成)以及介面(HTML 和 Javascript 程式碼通過讀取區塊鏈及傳送交易的方式與核心通訊)。

這是一個為擔保交易 Dapp 應用而設的簡單、美觀的使用者介面。不過你怎麼 知道點選“移除”按鈕時並不是將你的全部錢傳送給開發者呢?

我們的目標是讓核心變得可信,若要實現這點,核心就必須儘量精簡,並且 經過深入的審計和審查;而使用者介面可能包括大量的程式碼,可以無需這麼信任; 我們的一箇中期的設計目標是讓以太坊使用者介面去保護使用者,以免他們受到來自 作惡的交易介面的損害,如通過強制性的彈出一個“你是否想將帶有這些資料的 一個交易傳送到這個合約裡?”對話方塊(或其他形式的通知方法)。我們希望會 呈現出一些專業事務所的市場空間,就如今天律師事務所建立標準化法律合約那 樣,這些專業事務所會為不同的用例建立標準化的合約,並讓這些合約接受來自 第三方審計人員的深入檢查。

審計和標準化可以減少程式碼錯誤帶來的損害,不過在錯誤的特例裡,已經有 人進行了數十年的研究,引入了一種強型別要求的程式語言,專門用於避免錯誤; 這類語言讓你可以更豐富地指定每一種資料的含義,並自動防止資料被以明顯錯 誤的方式組合起來(如時間戳加上了一個貨幣價值,或由區塊雜湊值分割的地址)。

更高階的解決方案集合依賴於名為形式化驗證(Formal Verification)的 技術。簡單地說,形式化驗證就是使用計算機程式自動地在數學的層面上證明關 於其他計算機程式的語句。其中一個簡單的例子就是證明一個排序演算法的正確性: 給定一段程式碼,它以一個數組作為輸入項,並提供一個數組作為輸出項,你可以 插入一個“定理”,如for x ε I: x ε O; j > i => O[j] >= Oi。形式 化驗證者將會處理這個程式碼,構造出肯定或否定這個定理的數學證明,或放棄處 理(在考拉茲猜想的例子裡有可能會這樣)。Aesthetic Integration 公司的 Imandra 產品甚至可以自動找出錯誤定理的反面例子。

現在,以太坊的高階程式語言 Solidity(編譯到以太坊的 bytecode)的主 導開發者 Christian Reitwiessner 正在將形式化證明引擎 Why3 整合到 Solidity 裡面,讓使用者可以在 Solidity 程式裡面插入與某種數學論點有關的證據,並在 編譯的時候進行驗證;還有一個專案在將 lmandra 整合到以太坊虛擬機器的程式碼裡。


通過 why3 引擎實現 Solidity 的形式化證明

形式化證明是一項強大的技術;不過,它無法解決這樣的一個問題:有一些 事情,可能連我們自己都不知道應該要去證明。人類對公平和正確性的定義往往 是非常複雜的,而由此帶來的複雜影響往往是難以檢測的。市場的訂單本(譯者 注:Order Book,即撮合交易引擎常見的買賣單系統)通常需要有一些基礎的正 確性規則(你要不就以所出的價格得到你需要的東西,要不繫統就把錢返還給你), 順序的不變性(為了防止 front-running,即所謂的提前交易或搶單),確保每 一個買家和賣家都能與最佳的對手單匹配上,以及其他等等;不幸的是,我們並 不能簡單地將所有的情況都列舉出來,也無法確保我們沒有任何遺漏的事項。現 在看來,對我們來說選擇什麼東西進行驗證會是繼續是一項藝術(難題),不過 形式化證明技術肯定會降低攻擊者們進行攻擊的自由度,讓對程式碼進行審計的人 員降低負擔。

關鍵建議

金融機構應該考慮使用以太坊的公有鏈或私有鏈版本,或者使用一個基於 EVM(以太坊虛擬機器引擎)的系統,畢竟這個虛擬機器是以完美的確定性和安全性 的出發點去設計和測試的,這些兩個目標對分散式賬本的用例是很有用的。(譯 者注:基於 EVM 的系統,並不一定指以太坊,而是指 EVM 這個虛擬機器引擎的設計 能夠即使是與其他的系統結合起來,例如非區塊鏈技術的系統,也能發揮強大的 功能)。具體來說,除了 EVM 之外,當前並沒有其他主流的虛擬機器引擎包含了 Gas 計數器這個概念,而這個機制對以下的目標是必須的:(i)避免無限迴圈攻 擊,(ii)避免在某些邊緣案例裡的具備不確定性的行為。在一個私有鏈的例項裡 面,並不一定要用以太幣去支付 Gas(或者其他密碼學代幣);你可以直接給用 戶分配“Gas 資源“,有點像亞馬遜雲伺服器給客服分配“CPU 時間”一樣,你 也可以簡單地要求所有的交易都包含一個給定的最大限制(如每個交易的 gas 上限是 100 萬),(譯者注:這樣即使有人發動無限迴圈攻擊,他也只能最多執 行 100 萬 Gas 允許執行的計算步數,無法導致系統長期的死迴圈)。

不過,除了虛擬機器的安全性外我們還有其他需要考慮的事情:在以太坊平臺 上,使用者若要與一個智慧合約進行互動,必須確定他們面對的程式是以他們想象 中的執行方式去執行(譯者注:例如,一個旨在進行遺產分配的智慧合約,使用者 必須確定當自己的財產劃撥進這個智慧合約後,這個智慧合約在日後真的會自動 地按照設定的規則去分配遺產)。區塊鏈是一個提供了密碼學擔保的平臺,具有 一定的便利性,畢竟程式碼是儲存在區塊鏈上的,所有與合約相關的參與者都能查 看此程式碼,使用者也能確定程式碼真的會被執行,不過若要確保不存在任何形式的作 惡行為和意外的漏洞,這依然具有挑戰性(可參考 Underhanded Contest,這是 一個所謂的“卑鄙 C 程式大賽”,專門編寫一些“說是一套,做是另一套”的程 序,裡面的一些例子具有相當的代表性)。我們推薦使用者去探索形式化驗證技術, 在他們與程式碼互動的過程中進行自動化的驗證,在金融行業的用例裡面,涉及的 經濟利益較大,這樣的技術可能是很有用的。

效率

效率問題是人們對以太坊平臺的主要憂慮之一。具體來說,一些人認為以太 坊平臺太通用了,因此可能會成為“什麼都能做,但什麼都不精通”的例子。由 位元股團隊(BitShares team)及其他人提出來的一類觀點就是虛擬機器內執行的 程式碼必然會比原生的程式碼慢,相比之下,那種支援很多“預編譯”操作程式碼的平 臺顯然會更高效。Gideon Greenspan(MultiChain 平臺所屬公司的 CEO)也提出 了與併發性有關的論點,不過平行化和計算效率是不同的概念,所以將會在下文 與可擴充套件性相關的段落敘述這個問題。第三個擔憂是以太坊區塊鏈裡進行的一些 操作指令,特別是 Merkle 雜湊過程,帶來了不必要的緩慢,因此可以將它移除 以實現更高的效率(而且,在私有鏈的場合,可能不太需要這個了)。

EVM 以太坊虛擬機器

或許可以說,虛擬機器的問題是目前最複雜的。區塊鏈最早的指令碼語言——比 特幣指令碼,是一個模仿 Forth 語言搭建的基於堆疊的程式語言,它的基礎演算法帶 有無大小限制的整數,字串操作,以及一系列的高階密碼學原語。其執行引擎 的效率還是比較低的,顯然不適合在指令碼的層面建立任何形式的複雜應用。不過, 因為 UTXO 模型固有的“無狀態”的特性,在比特幣之上搭建高階應用一直是不 太可能的,因此在比特幣之上的指令碼執行效率一直沒有受到太多的關注(這個情 況在最近出現了變化:在一篇近期的部落格文章裡面,比特幣的核心開發團隊反對 區塊大小從 1MB 擴充套件到 2 MB,認為這樣的話一個體積最大的交易可能需要十分 鍾才能校驗完畢)。

以太坊原來的程式語言有意做得像比特幣指令碼那樣,除了帶有一個狀態豐富 的執行環境,而不是比特幣指令碼那種無狀態的。對 256 位整數的限制被新增進去 了(比特幣腳本里還是禁止了這個限制),是為了防止整數乘法成為一種拒絕服 務攻擊的載體。它也曾經考慮過加入基於整數大小的動態 Gas 消耗機制,不過基 於效率的考慮最終還是剔除了。256 位被視為一個最佳的尺寸上限,因為它執行 和計算起來還是相對較快的,而且也具有足夠的資源去處理橢圓曲線加密演算法(使用 256 位數)和雜湊(大多數主流的雜湊演算法會提供一個 256 位的輸出值)。 它裡面帶有專為雜湊和橢圓曲線操作的操作程式碼(opcodes)。

那時候的用意是為了支援簡單的金融指令碼、if-then 條件語句以及其他的應 用程式,這些場景裡 256 位的虛擬機器可能會存在一定的效率問題,但相對於在交 易中校驗橢圓曲線簽名涉及的耗費,這些效率問題還是可以忽略不計的(這有點 像比特幣的指令碼)。在大多數的案例中,以下的描述是成立的:對一個簽名進行 校驗需要處理超過一千個模組化的乘法運算操作,而執行實際的虛擬機器程式碼只需 要簡單地處理一些條件語句及變數的變化。因此,那種認為“只”校驗簽名和運 行“完整”的程式之間存在巨大成本差別的看法,在很大程度上是錯誤的:不管 虛擬機器的效能如何,時間瓶頸在於密碼學校驗,而不是在於處理一些 if-then 條件語句。

足夠的極限

不過,在一些場景中還是存在非常明顯的整體開銷的。第一個是在涉及較多 的狀態改變的操作過程中。當前,每一個狀態的改變是以對 Merkle 樹進行修改 的形式實現的,這會觸發 5-20 次反序列化操作,雜湊和重新序列號操作,以及 資料庫的更新。就如之前描述的那樣,Merkle 樹若從輕客戶端的友好性來說是 協議的重要組成部分,若要在跨鏈運作中處理“收據”的話就更為重要了;不過, Merkle 樹相關操作對效率的影響還是非常明顯的——基準測試顯示,在某些合 約中,Merkle 樹的更新會耗費很多的時間,若要驗證簽名的話花費的時間就更 多了。

若要緩和這個影響,有兩個途徑。第一個解決方案是位元股團隊推薦的,即 完全去除 Merkle 樹,簡單地在 leveldb 資料庫裡儲存狀態。這對狀態更新的效 率大約會提升 5-20 倍左右,不過這是會對輕客戶端的友好性帶來影響的。對很 多私有鏈的應用來說, 這或許是一個合適的做法。第二個方法,也是以太坊團 隊最可能在 1.1 版本的 Serenity 釋出時跟進的辦法,是一個折中的策略:目前 Merkle 樹裡允許 32 位元組的鍵值對(key/value pairs),在將來會允許無限制大小的值,讓應用程式開發者可以在一個地方儲存資料架構並對其進行頻繁更新, 這樣就能夠減少實際上更新 Merkle 樹的次數。10

在以太坊虛擬機器內使用高階的數學和密碼學演算法可能是第二個弱點。目前, 在以太坊虛擬機器內進行開發的可選方案有環簽名,zk-SNARKs 零知識證明協議, RSA 式公鑰加密演算法,奇異值分解(singular value decomposition),甚至是 一些對記憶體需求較高的雜湊函式,如 scrypt。若要引入這些功能,以太坊虛擬 機的效能在實際使用中可能較低:
 用原生Python語言進行的橢圓曲線簽名校驗需要0.017秒;在Python 版本的以太坊虛擬機器中需要 0.57 秒
 用原生Python語言進行的五把鑰匙的環簽名校驗需要0.119秒;在 Python 版本的以太坊虛擬機器裡需要 3.68 秒
 g用Python實施對記憶體需求較高的scrypt雜湊函式的運算,會小於一 秒;在 Python 版本的以太坊虛擬機器裡這個操作的過程實在是太長了,甚至 需要分解到 118 個區塊裡才能執行這些交易。

這些情況是由兩個方面的原因所導致的。第一,現有的虛擬機器方案已經經歷 了幾十年的開發,有不少優化的 JIT(just-in-time,即時技術)方案,而以太 坊只有相對簡單的 JIT 方案。若要讓以太坊趕上現有的虛擬機器的效能,可能需要 幾年的時間。其次,256 位整數的需求讓虛擬機器的速度大幅度降低,畢竟其底層 的機器使用的是 64 位的架構,而這些演算法的大部分程式碼只處理那些小於 64 位的 整數,並不需要在每一個加法和乘法運算中使用整個 256 位的運算器及由此帶來 的整體開銷。

在短期內,我們的解決方案一直是“預先編譯的合約”。本質上說,如果應 用過程中對某種特定的密碼學功能有較高的需求(如 SHA3,SHA256,橢圓曲線 簽名校驗等),我們就給每一種功能分配一個地址(當前我們用較低的地址,如 1,2,3 等),並增加一個協議上的規則,即進入這個地址的一個交易(或內部 交易)消耗低額 Gas(有相應的標準),並輸出一個與輸入值相應的結果。這個 功能並不是整合在以太坊虛擬機器裡;相反,它是以原生程式碼的形式整合到每一個以太坊的客戶端,讓其執行成本更低及擁有原生程式碼的速度。這實質上是一個“急 救繃帶式的修復方案”,專門為特定的用例解決需求。不過,它顯然不是最優的: 這意味著對某類智慧合約來說——那些帶有稀奇古怪的、對運算資源需求較多的 密碼學演算法的智慧合約,其“無需許可的創新”可能就會受限於這個設計,它們 無法像普通的智慧合約那樣享受任意的靈活性——普通的合約可以在不對協議 層面進行更改的情況下書寫任意的新功能。

WebAssembly ——“EVM 2.0”

基於這個原因,我們的一個研究者 Martin Becze,正在探索用 WebAssembly 作為實現更快的虛擬機器的途徑,以提供一個長期的可行解決方案。這個專案有兩 個步驟。第一步是書寫一個 JIT 編譯器,目標是將 EVM 的程式碼編譯成 WebAssembly 的程式碼,這樣能實現更快的 EVM 實施方案。第二步是使用 WebAssembly 去建立一 個“以太坊虛擬機器 2.0”,其對 WebAssembly 增加的功能只有一個,就是一個代 碼翻譯器,可用於(i)插入 gas 計數操作,和(ii)禁止如下的一些操作程式碼 (opcode)——那些被認為不太明確的、沒有確定性的、或訪問以太坊虛擬機器本 來就不應該訪問的資訊的。(如執行緒,浮點運算)。

基於幾種原因,WebAssembly 被視為是一個理想的方案,這與 WebAssembly 和以太坊共享著相似的設計目標是有關聯的。
 WebAssembly致力於為小型的應用程式提供非常小的程式碼體積。一些更 傳統的技術方案(如由 C++生成的位元組碼)及其預設