Libra區塊鏈
白皮書作者:Zachary Amsden, Ramnik Arora, Shehar Bano, Mathieu Baudet, Sam Blackshear, Abhay Bothra, George Cabrera,Christian Catalini, Konstantinos Chalkias, Evan Cheng, Avery Ching, Andrey Chursin, George Danezis,Gerardo Di Giacomo, David L. Dill, Hui Ding, Nick Doudchenko, Victor Gao, Zhenhuan Gao, François Garillot,Michael Gorven, Philip Hayes, J. Mark Hou,Yuxuan Hu, Kevin Hurley, Kevin Lewi, Chunqi Li, Zekun Li, Dahlia Malkhi,Sonia Margulis, Ben Maurer, Payman Mohassel, Ladi de Naurois, Valeria Nikolaenko, Todd Nowacki, Oleksandr Orlov,Dmitri Perelman, Alistair Pott, Brett Proctor, Shaz Qadeer, Rain, Dario Russi, Bryan Schwab,Stephane Sezer,Alberto Sonnino, Herman Venter, Lei Wei, Nils Wernerfelt, Brandon Williams, Qinfan Wu, Xifan Yan, Tim Zakian,Runtian Zhou*
翻譯:巴位元資訊 (灑脫喜,Kyle)
摘要
Libra區塊鏈是一個去中心化、可程式設計的資料庫,其旨在支援一個低波動性的加密貨幣,能夠作為服務全世界數十億人的有效交易媒介。我們提出了一個關於Libra協議的提議,它會實現Libra區塊鏈,旨在建立一個可促進創新、降低進入壁壘,並改善訪問金融服務機會的金融基礎設施。為了驗證Libra協議的設計,我們已構建了一個開源原型實現 —— Libra Core ,並在全球範圍內共同推進這一新生態系統。
Libra協議允許來自不同實體的一組副本(稱為驗證者)共同維護一個可程式設計資源的資料庫。這些資源由經過公鑰加密驗證的不同使用者帳戶擁有,並遵守這些資源開發者指定的自定義規則。驗證者處理事務(transaction)並相互作用,就資料庫的狀態達成共識。事務是基於預定義的,在未來的版本中,使用者自定義的智慧合約會使用一種稱為Move的新程式語言編寫。
我們使用Move語言定義區塊鏈的核心機制,例如貨幣和驗證者會員。這些核心機制能夠建立一個獨特的治理機制,其建立在現有專案早期已建立的穩定基礎之上,但Libra系統會隨著時間的推移,完全開放。
(圖片來自: Libra.org)
一、引言
網際網路的普及以及由此產生的產品和服務的數字化,提高了效率,降低了進入壁壘,降低了大多數行業的成本。這種連通性已透過讓更多的人進入金融生態系統,而驅動了經濟賦權。儘管如此,對於那些最需要金融服務的人來說,獲得金融服務的機會仍然有限,這是由成本、可靠性以及無縫傳送資金的能力影響的。
這篇技術論文為Libra協議提出了一個提議,旨在支援這個新生的 Libra生態系統,並解決這些挑戰,擴大資本准入,並作為創新金融服務的一個平臺。這個生態系統將提供一種新的全球貨幣 —— Libra幣,它將由優質的中央銀行一籃子銀行存款和國債充分支撐。
這些基準貨幣都經歷了相對較低的通貨膨脹,因此,Libra穩定幣繼承了這一屬性,且其還擁有在地理上呈現多樣化的組合優勢。Libra協議必須擴充套件,以支援其貨幣成長為一個全球金融基礎設施,提供以實施經濟和治理的靈活性,支援其操作策略。Libra協議的設計從一開始就以整體解決這些需求,它建立在現有專案以及研究的基礎之上。Libra結合了新穎的方法以及已被廣泛理解的技術。
金融服務業健康競爭和創新的一個關鍵前提,是依靠處理事務、維護賬戶以及確保跨服務和組織的互操作性公共基礎設施。透過降低進入壁壘和轉換成本,Libra協議將使初創企業和現有大型企業能夠在公平競爭的環境中競爭,並試驗新的商業模式和金融應用。區塊鏈技術能夠很好地解決這些問題,因為它可以用於確保沒有單個實體能夠控制生態系統或可單方塑造其進化優勢[2]。
Libra區塊鏈將是去中心化的,它由一組共同工作的驗證者組成,用於處理事務並維護區塊鏈的狀態。這些驗證者也構成了Libra協會的成員,這將為網路的管理以及支援貨幣的儲備提供一個框架。最初,該協會(驗證者)將由一組地理分佈廣泛的創始成員組成。這些成員是根據客觀參與標準選擇出來的,包括它們在引導Libra生態系統和為其成功而投入的權益。隨著時間的推移,成員資格將轉變為完全開放,只基於Libra的持有量。Libra協會已發表了報告,概述了其願景[1]、提議的結構[3]、貨幣的經濟學[4]以及向無許可系統轉變的路線圖[5]。
而本文,則是構建支援Libra生態系統的技術基礎設施的第一步。
我們釋出這份早期報告,是為了徵求社羣對Libra的初步設計、系統的發展計劃以及當前未解決的研究挑戰的反饋意見。因此,協會建立了一個開放原始碼社羣[6]以供大家討論以及支援專案的開發。
Libra協議。Libra區塊鏈是使用Libra協議進行維護的密碼學證明資料庫 [7, 8, 9]。該資料庫儲存了一個可程式設計資源(例如Libra幣)的賬本。資源(resource)遵循其宣告模組指定的自定義規則,該模組還儲存在資料庫中。資源由使用密碼學公鑰進行驗證的帳戶擁有。帳戶可代表系統的直接終端使用者以及實體(例如託管錢包),代表他們的使用者。帳戶的所有者可簽署對帳戶內的資源進行操作的事務(transaction)。
圖1顯示了使用Libra協議進行互動的兩種型別的實體:(1)驗證者,其負責維護資料庫,(2)客戶端,它們對資料庫執行查詢,並提交事務以修改它。
圖1:Libra協議的縱覽圖
驗證者維護這個資料庫,並處理由包含在資料庫:
(1)的客戶端提交的事務(transaction)。驗證者使用一個分散式共識協議來商定不斷增長的,已提交到資料庫的事務列表,以及執行這些事務的結果。即使少數驗證者存在惡意或錯誤,此共識協議也必須是可靠的。驗證者輪流驅動接受事務的過程。當驗證者充當領導者時,它會向其他驗證者
(2)提出客戶端直接提交給它的事務,以及透過其他驗證者間接提交的事務。所有驗證者執行事
(3)並形成一個經驗證的資料結構,其中包含新賬本歷史記錄。作為共識協議
(4)的一部分,驗證者對該資料結構的確認者進行投票。作為在版本i提交一個事務ti的一部分,共識協議在版本i輸出資料庫完整狀態的簽名(包括整個歷史),以確認對來自客戶端
(5)查詢的響應。
客戶端可以向驗證者發出查詢,以從資料庫中讀取資料。由於資料庫是經驗證的,因此可保證客戶端對其查詢的響應的準確性。作為對讀取查詢的響應的一部分,驗證者返回驗證者已知資料庫最新版本i的簽名驗證器。
此外,客戶端還可以選擇透過與驗證者同步事務歷史,來建立整個資料庫的副本。在建立副本時,客戶端可檢查驗證者是否正確執行了事務,從而改善了系統的問責制和透明度。其他客戶端可以從儲存副本的客戶端讀取副本,這和從驗證者處讀取副本以驗證響應真實性的方式相同。
為了簡單起見,本文的其餘部分假設客戶端直接查詢一個驗證者,而不是副本。
組成(Organization)。本文討論了Libra協議的組成部分:
邏輯資料模型 :(第2節)描述了邏輯資料模型,該模型組織了對驗證者和客戶端可見的去中心化資料庫。
執行事務:(第3節)描述了Move [10]程式語言的使用,這是一種用於定義和執行資料庫事務的新程式語言。
經驗證的資料結構和儲存:(第4節)描述了基於Merkle樹的邏輯模型到經驗證資料結構的對映[11]。
拜占庭容錯共識:(第5節)描述了HotStuff協議[13]的變體LibraBFT [12],允許具有潛在惡意驗證者的網路,透過執行Move語言事務,並在使用經驗證的資料結構執行事務時達成一致,來維護一個單一的、一致的資料庫。
網路:(第6節)描述了使驗證者能根據協商一致的需要,安全地相互通訊的協議。
而在之後,我們展示了開源的Libra Core原型[6]。第7節內容則討論了Libra Core如何結合了Libra協議的元件來處理事務。
第8節內容則探討了效能考慮。
最後,我們將解釋如何使用該協議來支援Libra生態系統政策的經濟穩定和治理。
第9節內容展示了我們如何使用Move語言來實現低波動性、儲備支撐的Libra貨幣,以及反映 Libra協會治理的驗證者管理系統。
第10節內容,討論了有關Libra生態系統的未來計劃,及其當前正面臨的挑戰,這也將是這篇文章的結尾。
二、邏輯資料模型
Libra區塊鏈中的所有資料都儲存在單一版本的資料庫當中[14, 15]。版本號是與系統已執行的事務數相對應的無符號64位整數。在每個版本i中,資料庫都包含一個元組 (Ti, Oi, Si) ,它們分別表示事務 (Ti),事務輸出(Oi)以及賬本狀態 (Si)。給定一個確定性執行函式Apply,這個元組的含義是:對賬本狀態Si−1執行事務Ti會產生輸出Oi以及新賬本狀態Si,即Apply(Si−1, Ti) → ⟨Oi, Si⟩。
Libra協議使用Move語言來實現確定性執行函式(請參見第3節內容)。在本節內容中,我們將重點介紹版本化資料庫,它允許驗證者:
根據最新版本的賬本狀態執行事務;
響應客戶端有關當前和以前版本的賬本歷史記錄的查詢;
我們首先解釋儲存在單個版本中的賬本狀態的結構,然後討論版本化賬本歷史檢視(History view)的目的。
2.1 賬本狀態
賬本狀態代表了有關Libra生態系統的基本事實,包括每個使用者在給定版本中持有的Libra幣的數量。每個驗證者必須知道最新版本的賬本狀態,以便執行新的事務。
Libra協議使用基於帳戶的資料模型[16]對賬本狀態進行編碼。狀態被構造為一個鍵值儲存,它將帳戶地址鍵對映到帳戶值。賬本狀態下的賬戶值是已釋出Move資源和模組的集合。這個 Move資源儲存資料值,而模組則儲存程式碼。初始帳戶集及其狀態在創始賬本狀態中指定(見第3.1節)。
帳戶地址:帳戶地址是一個256位的值。要建立新帳戶,使用者首先為簽名方案生成一個新的驗證/簽名金鑰對 (vk, sk),並使用公共驗證金鑰vk的加密雜湊作為帳戶地址a = H(vk)。當從現有賬戶傳送的事務呼叫這個create_account(a) Move指令時,則這個新賬戶就會在賬本狀態中建立。這通常發生在一筆事務嘗試將Libra傳送到尚未建立的地址a的帳戶時。
在地址a中建立新帳戶後,使用者可使用私人簽名金鑰sk,簽署要從該帳戶傳送的事務。該使用者還可以在不更改其地址的情況下,更改用於簽署交易的金鑰(例如,主動更改金鑰或響應金鑰可能被盜的情況)。
Libra協議不會將帳戶連結到使用者的真實身份(即沒有KYC)。使用者可透過生成多個金鑰對來自由建立多個帳戶。由同一使用者控制的帳戶沒有固有的相互聯絡。該方案參照了比特幣和以太坊,為使用者提供了假名性 (又稱半匿名)[19]。
資源值:所謂資源值或資源,是將命名欄位繫結到簡單值(例如整數或複雜值)的記錄。
(腳註1: 具體地說,我們使用SHA3-256 [17]例項化雜湊函式,並使用edwards25519曲線[18]實現EdDSA數字簽名)
圖2:具有四個帳戶的賬本狀態示例。
在這個圖中,橢圓表示資源,矩形表示模組。從資源到模組的定向邊,意味著該模組宣告瞭資源的型別。地址為0x12的帳戶,包含由貨幣模組宣告的Currency.T資源。該貨幣模組的程式碼儲存在地址0x56。地址0x34處的帳戶,同時包含了一個Currency.T資源以及StateChannel.T資源,這是由儲存在地址0x78的模組宣告的。
每個資源都有一個由模組宣告的型別。資源型別是名義型別[20] ,其由型別的名稱和資源的宣告模組的名稱和地址組成。例如,圖2中的 Currency.T資源的型別是0x56.Currency.T.這裡,0x56是儲存貨幣模組的地址,Currency是模組的名稱,而Currency.T則是資源的名稱。
要在帳戶地址0x12取回資源0x56.Currency.T,客戶端將請求0x12/resources/0x56.Currency.T.
這種設計的目的,是讓模組為頂級帳戶值定義一個可預測的模式——也就是說,每個帳戶都將其0x56.Currency.T資源儲存在同一路徑下。因此,每個帳戶最多可儲存一個給定型別的資源。但是,這一限制是沒有約束的,因為程式設計師可定義包裝器(wrapper)資源,以自定義的方式組織資源。(例如,resource TwoCoin { c1: 0x56.Currency.T, c2: 0x56.Currency.T })。
用於改變、刪除和釋出資源的規則,編碼在建立資源並宣告其型別的模組當中。
Move的安全和驗證規則,會阻止其他程式碼對資源進行修改。
模組值:所謂模組值或模組,包含宣告資源型別和程式的Move位元組碼(更多細節見第3.4節)。與資源型別一樣,模組由宣告模組的帳戶地址識別。例如,圖2中Currency模組的識別符號是0x56.Currency。
模組必須在一個帳戶中唯一命名,每個帳戶最多隻能宣告一個具有給定名稱的模組。例如,圖2中地址0x56處的帳戶無法宣告另一個名為Currency的模組。另一方面,地址為0x34的帳戶可以宣告Currency的模組。此模組的識別符號將為0x34.Currency。注意,0x56.Currency.T和0x34.Currency.T 是不同的型別,它們彼此不能互換使用。
在當前版本的Libra協議中,模組是不可變的。一旦在帳戶地址下宣告模組,就不能修改或刪除它,除非透過硬分叉的方式。我們正研究在未來的版本中啟用安全模組更新的方案選項。
2、2事務(Transactions)
Libra區塊鏈的客戶端是透過提交事務來更新賬本狀態的。從高維度來講,事務由事務指令碼(以Move位元組碼編寫)和事務指令碼的引數(例如,接收方帳戶地址或要傳送的Libra幣數量)組成。驗證者透過執行指令碼及其引數和當前賬本狀態作為輸入來執行事務,以生成完全確定的事務輸出。在共識(第5節)期間,透過同意對事務輸出的約束性承諾(第4節),在事務被承諾之前,賬本狀態不會改變。
我們將在第3節中更詳細地討論事務的結構和執行。
事務輸出:執行一個事務Ti將生成新的賬本狀態Si以及執行狀態程式碼、gas使用量以及事件列表(彙總在輸出Oi中)。執行狀態程式碼記錄了執行一個事務的結果(例如,成功、因錯誤e退出、gas耗盡等)。
gas使用,記錄了執行事務時使用的gas單位數量(有關如何使用gas,來管理與事務處理相關費用的詳細資訊,請參見第3.1節)。
事件(Events):事件列表,是由執行事務時產生的一組副作用(2)。Move程式碼可透過一個事件結構觸發事件。每個事件都與一個唯一的key相關聯,它標識事件發出的結構,以及提供活動詳細資訊的有效載荷。一旦按照共識協議提交了事務,事務生成的事件將新增到商定的賬本歷史記錄中,並提供成功執行事務導致特定效果的證據。例如,一筆付款交易會發出一個事件,允許接收方確認已收到付款並確認付款金額。
乍一看,事件似乎是多餘的。相比透過一筆事務Ti查詢事件,客戶端可詢問事務Ti是否包含在區塊鏈中。但是,這很容易出錯,因為包含Ti並不意味著成功執行(例如,gas用完後可能會中斷)。在事務可能失敗的系統中,事件不僅提供了特定事務已執行的證據,而且還提供了它已以預期效果成功完成的證據。
事務只能生成事件-它們不能讀取事件。這種設計允許事務執行僅為當前狀態的函式,而不是歷史資訊(例如以前生成的事件)。
2、3 賬本歷史
賬本歷史記錄儲存已提交和已執行事務的序列,以及它們發出的關聯事件。賬本歷史的目的,是為了記錄最近的賬本狀態是如何被計算的。
賬本歷史中不存在一組事務的概念(3)。共識協議將事務批處理至區塊,作為最佳化並驅動這一共識協議(有關共識的詳細資訊,請參閱第5節內容)。然而,在邏輯資料模型中,事務按順序發生,而不會區分哪個區塊包含每個事務。
(腳註2: 事件的作用,類似於以太坊中的日誌和事件概念 [16],然而,Libra協議中的事件機制是完全不同的。
腳註3:這與比特幣和以太坊相反,在比特幣和以太坊中,區塊和區塊最大值的概念扮演著重要的角色。 )
儘管驗證者不需要知道賬本歷史就可以執行新的事務,但是客戶端可以對賬本歷史記錄執行經驗證的查詢,並使用賬本歷史來稽覈事務執行。
響應客戶端查詢:驗證者可使用賬本歷史來回答客戶端關於以前賬本狀態、事務和輸出的查詢。例如,客戶端可能會詢問有關特定版本的賬本狀態(例如,在第30個版本的地址x的帳戶餘額是多少?),或者特定型別事件的歷史(例如,Y地址的賬戶在最後20分鐘收到了哪些付款?)。
稽覈事務執行:客戶端可透過重新執行歷史記錄中的每個事務Ti,並將計算的賬本狀態與版本資料庫中相應的賬本狀態Si和事務輸出Oi進行比較,來檢查賬本狀態是否正確。
此機制允許客戶端審計驗證者,以確保正確執行事務。
三、執行事務
在Libra區塊鏈中,更改區塊鏈狀態的唯一方法是執行一個事務。
本節內容概述了事務執行的要求,定義了事務的結構,解釋Move虛擬機器(VM)如何執行一個事務,以及描述Move語言的關鍵概念。
在最初版本的Libra協議中,只有有限的Move功能子集可提供給客戶端。雖然Move是用於定義核心系統概念,如 Libra貨幣,但使用者無法釋出宣告自己資源型別的自定義模組。這種方法允許Move語言和工具鏈在暴露給使用者之前能夠變成熟。這種方法還推遲了事務執行和資料儲存中的可擴充套件性挑戰,而它們正是通用智慧合約平臺所固有的問題。
正如我們在第10節中所討論的,我們致力於透過Move語言來展示全面的可程式設計性。
3、1 執行要求
已知初始狀態:所有驗證者必須同意系統的初始或創始賬本狀態。
因為Libra區塊鏈的核心元件(比如賬戶邏輯、事務驗證,驗證者選擇以及Libra幣)是由Move模組定義的,創始狀態必須定義這些模組。創始狀態還必須具有這些核心元件的足夠例項化,以便事務可被處理(例如,至少有一個帳戶必須能支付第一個事務;必須定義驗證器集,以便集的法定數量的團體可對致力於第一個事務的確認者進行簽名)。
為了簡化系統的設計,系統的初始狀態表示為空狀態。然後透過定義特定模組的特殊事務T0建立創始狀態,該事務定義要建立的特定模組和資源,而不是透過正常事務過程。客戶端和驗證者被配置為只接受以特定T0開頭的賬本歷史記錄,該T0是由其加密雜湊標識的。
這些特殊事務不能透過共識協議新增到賬本歷史中,只能透過配置。(4)
確定性:事務執行必須具有確定性和密封性。這意味著事務執行的輸出是完全可預測的,並且僅基於事務和當前賬本狀態中包含的資訊。事務執行並不具有外部效應(例如與網路互動)。確定性和封閉性執行可確保多個驗證者可以就同一事務序列產生的狀態達成一致,即使事務是由每個驗證者獨立執行的。
這也意味著區塊鏈的事務歷史可從創始區塊重新執行,以生成當前的賬本狀態(見第2.3節)。
計量:為了管理對計算能力的需求,Libra協議收取以 Libra幣計價的交易費用(5)。這參照了以太坊普及的gas模型 [16]。
我們採用的方法,是選擇具有足夠容量的驗證者來滿足Libra生態系統的需求(見第8節內容)。這項費用的唯一目的,是在系統負載高於系統所提供承載能力時(例如,在遭到拒絕服務攻擊)減少需求,系統的設計是,當其處於正常執行期間,當有足夠的容量可用時,費用會是較低的。
這種方法不同於一些現有的區塊鏈,這些區塊鏈有時處理事務的需求會大於吞吐量。在這些系統中,費用會在出現高需求時激增,這是驗證者的收入來源,但給使用者造成了成本方面的問題。
費用的大小由兩個因素決定:gas價格和gas消耗。每個事務都規定了提交者願意支付的每單位gas的價格(以Libra為單位)。事務的執行動態地說明了它以gas消耗的計算能力。當系統發生堵塞時,驗證者會優先執行gas價格更高的事務,並可能放棄價格較低的事務。這就減少了在系統高負荷狀態下,事務的發起需求。
此外,一筆事務還包含了一個最大gas量,它指定了提交者願意以規定價格支付的最大gas單位數量。在執行期間,虛擬機器會跟蹤使用的gas單位數量。如果在執行完成前達到最大gas限制,虛擬機器將立即停止。這種事務所導致的部分更改都不會提交給狀態。但是,事務仍會出現在事務歷史記錄中,而傳送者的賬戶仍然是要為使用的gas付費的。
正如我們在本節中討論的,Libra區塊鏈核心邏輯的很多部分,是使用Move定義的,這包括gas費用的扣除。為了避免迴圈,虛擬機器在執行這些核心元件期間禁用gas計量。這些核心元件必須在創始狀態下定義。必須以防禦性的方式編寫,以防止惡意事務觸發執行計算代價很高的程式碼。執行此邏輯的成本,可包括在為事務收取的基本費用中。
資產語義:正如我們在第2.1節中所解釋的,賬本狀態直接對具有實際價值的數字資產進行編碼。事務執行必須確保,在未經授權的情況下,不得複製、丟失或轉讓Libra幣等資產。Libra協議使用Move虛擬機器(第3.4節)安全地執行事務以及具有這些屬性的自定義資產。
(腳註4:我們正在探索使用這種形式的特殊事務,來清晰地定義硬分叉的想法。客戶端可指定 一種首選配置,宣告類似的特殊事務(它對標準交易處理規則之外的模組和資源進行了特定的更改),應在第i版附加到賬本歷史當中。由於Libra協議的很多部分是使用Move語言表示的,所以這個型別的更新是可以表示出來的,但只需要對客戶端軟體進行配置更改。
腳註5:在第4.4節中,我們討論了管理儲存容量需求的方法。 )
3、2 事務結構
所謂一筆事務,是指包含以下資料的簽名訊息:
傳送方地址:即事務傳送者的賬戶地址。虛擬機器會讀取序列編號、身份驗證金鑰以及儲存在地址的LibraAccount.T 資源的餘額;
傳送方公鑰:與用於簽署事務的私鑰相對應的公鑰。此公鑰的雜湊必須與傳送方的LibraAccount.T資源儲存的身份驗證金鑰匹配。
程式:要執行的Move位元組碼事務指令碼、指令碼輸入的可選列表以及要釋出的Move位元組碼模組的可選列表。
Gas價格:傳送方願意支付每單位gas的數量,以便執行此事務。
最大Gas量:事務中止前允許消耗的最大Gas單位數量。
序列號:一個無符號整數,必須等於傳送方LibraAccount.T資源中的序列號。執行此事務後,序列號會增加1。由於對於給定的序列號只能提交一個事務,因此無法重放事務。
3、3 執行事務
執行事務,是透過在虛擬機器內執行六個步驟來實現的。執行獨立於賬本狀態的更新。首先,執行一個事務,是試圖就其順序達成共識嘗試的一部分。由於執行是封閉的,因此它不會造成外部副作用。隨後,如果達成共識,則將其輸出寫入賬本歷史。
執行一個事務,會執行以下這6個步驟:
1、核對簽名:事務上的簽名必須與傳送方的公鑰和事務資料匹配。此步驟只是事務本身的一個作用,它不需要讀取來自傳送方帳戶的任何資料。
2、執行prologue:prologue對事務傳送方進行身份驗證,確保傳送方有足夠的Libra幣支付交易中規定的最大數量的gas單位,並確保該事務不是前一個事務的重播。所有這些檢查,都是透過LibraAccount模組的prologue過程在Move語言中實現的。在prologue執行期間,Gas計量是被禁用的。具體來說,這個prologue會做如下這些工作:
(1)檢查傳送方公鑰的雜湊是否等於傳送方帳戶下儲存的身份驗證金鑰:如果沒有這個檢查,虛擬機器將錯誤地接受具有密碼學有效簽名的事務,即使沒有與帳戶相關聯金鑰的通訊。
(2)檢查gas_price * max_gas_amount <= sender_account_balance :如果不進行此檢查,虛擬機器將執行可能在epilogue中失敗的事務,因為它們將無法支付gas費用。
(3)確保事務序列號等於儲存在使用者帳戶下的序列號:如果沒有這項檢查,惡意方可重放舊的事務(例如,Bob可以重放Alice支付給他的10個Libra幣的這筆交易)。
3、驗證事務指令碼和模組:一旦事務prologue成功完成任務,虛擬機器將使用Move位元組碼驗證器對事務指令碼和模組執行良構的檢查。在實際執行或釋出任何Move程式碼之前,這個位元組碼驗證器檢查諸如型別安全(type-safety)、引用安全(reference-safety,即沒有懸空引用)和資源安全(resource-safety,即資源不會被複制、重複使用或意外銷燬)等關鍵屬性。
4、釋出模組:事務的程式欄位中的每個模組,都在事務傳送方的帳戶下發布。重複的模組名稱是被禁止的,例如,如果事務嘗試將名為M的模組釋出到已包含模組名為M的賬戶中,則該步驟將會失敗;
5、執行事務指令碼:虛擬機器將事務引數繫結到形式引數並執行事務指令碼。如果此指令碼執行成功完成,則指令碼執行的寫入操作和指令碼發出的事件將提交給全域性狀態。如果指令碼執行失敗(例如,由於gas耗盡或runtime執行失敗),則指令碼中的任何更改都不會提交到全域性狀態。
6、執行epilogue:最後,虛擬機器執行事務epilogue,向使用者收取所用gas的費用,並增加傳送方帳號序列號。就像prologue一樣,這個事務epilogue 是Move LibraAccount模組的一個過程,且其是在禁用gas計量的情況下執行的。如果執行躍了步驟(2),包括步驟(3)、(4)或(5)失敗,這一epilogue步驟也會始終執行。這個prologue步驟和epilogue步驟會一起工作,以確保在賬本歷史中的所有事務都是透過付費gas完成的。而不超過步驟(2) 的事務,不會被附加到賬本歷史。如果一筆事務超過了步驟(2),這個prologue步驟會確保賬戶擁有足夠的Libra幣以支付事務允許的最大gas單位數量。 即使事務用光了gas,epilogue步驟也可以按這個最大金額收取費用。
3、4 Move程式語言
正如我們所看到的,一筆事務是圍繞一個Move位元組碼程式,經證實的包裝器(wrapper)。
Move [10]是我們在設計Libra協議期間建立的一種新的程式語言,它在系統中扮演了三個重要的角色:
透過事務指令碼啟用靈活的事務;
允許使用者定義的程式碼和資料型別,包括透過模組的“智慧合約”;
支援Libra協議的配置和可擴充套件性(見第9節);
Move語言的關鍵特點是能夠定義自定義資源型別,這些型別是受線性邏輯[21]啟發的。用於編碼可程式設計資產的資源型別,其表現類似於普通程式值:
資源可以儲存在資料結構中,作為引數傳遞給過程,等等。然而,這個Move型別系統為資源提供了特殊的安全保障。資源無法被複制,只能移動。此外,資源型別只能由宣告該型別的模組建立或銷燬。這些保證,都是透過Move虛擬機器靜態地強制執行的。這使我們能夠在Move語言中將Libra幣表示為一種資源型別(這與以太幣和比特幣是不同的,它們在各自的語言中具有特殊的地位)。
我們已釋出了一份關於Move [10]設計的更為詳細的文章。在本節的其餘部分內容中,我們簡要地概述了用於事務執行的關鍵Move概念:開發Move事務指令碼和模組,並使用虛擬機器執行Move位元組碼。
編寫Move程式。Move程式有三種不同的表示形式:原始碼、最佳化中間程式碼 (IR)以及位元組碼。我們目前正在設計Move源語言,這將是一種符合人體工程學的語言,旨在使編寫和驗證安全程式碼變得容易。同時,程式設計師可以在Move IR中開發模組和事務指令碼。Move IR足以用於編寫人類可讀的程式碼,它也可直接轉換為Move位元組碼。未來的Move源語言和Move IR都可以編譯成Move位元組碼,而後者是Libra協議所使用的格式。
我們使用可驗證的位元組碼作為Move的可執行表示,原因有兩個:
上述安全保證必須適用於所有Move程式。執行這些編譯器中的保證是不夠的。惡意方總是可選擇透過直接使用位元組碼編寫惡意程式碼來繞過編譯器(作為事務執行的一部分,執行編譯器會使執行速度變慢和更復雜,並且需要驗證者信任完整編譯器程式碼庫的正確性),因此,該協議透過位元組碼驗證(型別安全、引用安全和資源安全)來強制Move的所有安全保證,從而避免了對編譯器的信任。
與高階源語言相比, Move基於棧的位元組碼指令更少。此外,每個指令都有簡單的語義,可以透過更小的原子步驟來表示。這減少了Libra協議的規範足跡,並使得開發者更容易發現實現錯誤。
事務指令碼:事務指令碼是Libra協議的主要程式。事務指令碼負責啟用靈活的事務,因為指令碼是一個任意的Move位元組碼程式。指令碼可使用條件邏輯,以及執行本地計算,呼叫在賬本狀態下發布的模組的多個程式,這意味著指令碼可執行富有表現力的一次性操作,例如為特定的一組接收者支付。
我們期望大多數事務指令碼將執行一個包含通用函式的程式呼叫。例如,LibraAccount.pay_from_sender(recipient_address, amount) 程式封裝了執行一筆對等式支付的邏輯。以recipient_address(接收方地址)和amount(金額)為引數並呼叫此過程的事務指令碼與以太坊中的以太幣傳輸事務相同[16]。
模組:模組是釋出在賬本狀態中的程式碼單元。模組負責宣告結構型別和程式。結構值包含可儲存基元值的資料欄位,例如整數或其他結構值。
每個結構必須標記為資源或不受限制(即非資源)。不受限制結構不受上述複製和銷燬限制。但是,不受限制結構不能包含資源結構(直接或傳遞),並且不能在賬本狀態下的賬戶釋出。
從高維度來說,模組/結構/程式的關係,類似於物件導向程式設計中的類/物件/方法的關係。但是,這裡有一些重要的區別。一個模組可以宣告多個結構型別(或零個結構型別)。在其宣告模組之外不能訪問任何資料欄位(即,沒有公共欄位)。模組的過程是靜態過程,而不是例項方法;過程中沒有this或self的概念。Move模組類似於沒有高階函式的有限版本的ML樣式模組 [22]。Move模組與以太坊和其它區塊鏈平臺的“智慧合約”概念相關,但也有不同。一個以太坊智慧合約包含了賬本狀態下發布的程式碼以及資料。而在Libra,模組包含程式碼值,資源包含資料值。在物件導向術語中,以太坊智慧合約就像是在單個帳戶地址下發布的單例物件。模組是建立資源的方法,它可以建立任意數量的資源,這些資源可以在不同的帳戶地址下發布。
Move虛擬機器:Move虛擬機器為Move位元組碼實現驗證程式和解釋程式任務。位元組碼以基於棧的虛擬機器為目標,使用過程本地運算元棧和暫存器。非結構化控制流透過goto和標籤(label)進行編碼。
開發人員在Move IR中編寫事務指令碼或模組,然後將其編譯成Move位元組碼。編譯將結構化控制流構造(例如,條件、迴圈)轉換為非結構化控制流,並將複雜表示式轉換為少量的位元組碼指令,以控制一個運算元棧。這個Move虛擬機器透過驗證然後執行這個位元組碼來執行一筆事務。
這個Move虛擬機器支援少量型別和值:布林運算(booleans)、無符號64位整數,256位地址、固定大小位元組陣列、結構(包括資源)和引用。結構欄位不能是引用型別,這將阻止在賬本狀態中儲存引用。
這個Move虛擬機器並沒有堆(heap):本地資料在棧(stack)上分配,並在分配程式返回時釋放。所有永續性資料必須儲存在賬本狀態中。
四、經驗證的資料結構和儲存
在執行事務之後,驗證者將對邏輯資料模型的更改,轉換為用於表示資料庫的已驗證資料結構[7、8、9]的新版本。此資料結構的簡短驗證器是對賬本歷史的約束性承諾,其中包括新執行的事務。與事務執行一樣,此資料結構的生成也是確定性的。
共識協議使用這個驗證器來同意事務的順序及其結果的執行(我們將在第5節內容詳細討論共識)。作為提交事務區塊的一部分,驗證者將短驗證器集體簽名至結果資料庫的新版本。
使用這種集體簽名,客戶端可信任資料庫版本代表資料庫賬本歷史的完整、有效和不可逆狀態。
客戶端可查詢任意驗證者(或資料庫的第三方副本)來讀取特定的資料庫值,並使用驗證器以及簡短的證明來驗證結果。
因此,客戶端不需要信任執行查詢的一方,以確保結果讀取的正確性。
Libra協議中的資料結構基於Merkle樹,並受到其他區塊鏈的啟發;但是,在某些情況下,我們做出了一些稍微不同的決定,下面我們會進行強調。首先,我們簡要討論建立驗證器的Merkle樹方法。然後我們描述經驗證的資料結構,從資料結構的根開始,然後我們討論其中的子結構。圖3描述了資料結構,並提供了本節內容的視覺化指南。
圖片3: (1)賬本歷史結構的根雜湊是系統完整狀態的驗證器,即(2)由法定人數驗證者簽署。當事務新增到資料庫時,提交到賬本歷史的驗證器(第4.2節)將增長(用虛線箭頭表示)。賬本歷史的每個子葉都提交至一個(3)TransactionInfo結構。此結構承諾(4)簽署的事務(Ti),(5)該事務(Ei,第4.5節)期間產生的事件列表,以及(6)該事務 (Si, 第4.3節)執行後的狀態。該狀態是一顆稀疏Merkle二叉樹,其中每個子葉上都有一個 (7)帳戶斑點。
4、1 認證資料結構的背景
認證資料結構允許驗證者V控制一個簡短的驗證器a,它對更大的資料結構D形成了約束承諾。一個不受信任的證明者P,其控制了資料結構D,計算f(D) → r並向驗證者返回r (資料結構D上某些函式f的計算結果)以及π(正確計算結果的證明)。驗證者V可以執行Verify(a, f, r, π),當且僅當 f(D) = r時返回真(true)值。在Libra區塊鏈的背景中,證明者通常是驗證者,而驗證者是執行讀取查詢的客戶端。但是,客戶端(即使只有部分資料庫副本的客戶端)也可以充當驗證者,併為其他客戶端執行經驗證的讀取查詢。
圖片4:一顆儲存D = {0 : s0, . . .}的 Merkle樹。如果f是獲取第三項(用虛線顯示)的函式,則 r = s2 ,π = [h3, h4] (這些節點用虛線顯示)。Verify(a, f, r, π) 會驗證 a ? = H(h4∥H(H(2∥r)∥h3)).
Merkle樹[11]是一種常見的認證資料結構形式,其用於儲存整數和字串之間的對映。在一顆大小為2^k的Merkle樹中,結構D將每一個整數鍵i ∈ [0, 2^k)對映到一個字串值si。
驗證器由字串建立的完整二叉樹的根組成,將子葉標記為 H(i||si),將內部節點標記為H(left||right),其中H是一個加密雜湊函式(我們稱之為雜湊)(6)。證明者希望驗證的函式f,是一個包含鍵值對 (k, v)在對映D中的證明。
P透過返回由節點i的每個祖先的兄弟姐妹的標籤組成的證明π,來驗證對D中專案i的查詢。圖4顯示了對大小為4的Merkle樹中專案3的查詢。專案3的節點用虛線表示,π中包含的節點用虛線表示。
(腳註6: 安全Merkle樹必須使用不同的雜湊函式,雜湊子葉和內部節點,以避免兩種型別的節點混淆。為了簡單起見,我們在示例中省略了這個細節,而Libra協議使用了一種獨特的雜湊函式,用於區分不同的雜湊函式型別,以避免基於型別混淆的攻擊[23]。)
4、2 賬本歷史
從比特幣 [24]開始的大多數區塊鏈,用一個包含單個祖先雜湊的區塊,維護一個共識一致的每個交易區塊的連結列表。
這一結構就導致了客戶端效率低下。例如,信任某區塊B並希望驗證祖先塊B'中的資訊的客戶端,需要獲取和處理所有的中間祖先區塊。
Libra協議使用單個Merkle樹,為賬本歷史提供一個經驗證的資料結構。圖3解釋了支援Libra資料庫的完整資料結構,包括包含事務的賬本歷史,這些記錄依次包含有關資料庫狀態、事件和帳戶的資訊。賬本歷史表示為一顆Merkle樹,它將順序資料庫版本號i對映到一個TransactionInfoi結構。每個TransactionInfoi結構都包含一個已簽名的事務 (Ti), 執行Ti(Si,在第4.3節中討論)後的狀態驗證器,以及 Ti(Ei,在第4.5節中討論)生成的事件驗證器。
與其他Merkle樹一樣,這個賬本歷史支援O(log n)大小的證明(其中n是已處理的事務總數),以驗證一個特定TransactionInfoi的查詢。 當客戶端希望查詢版本I的狀態,或查詢在版本I中生成的事件時,它將使用包含的狀態或事件列表驗證器對TransactionInfoi 執行已驗證的查詢。
具體來說,賬本歷史使用Merkle樹累加器[25,26]方法來形成Merkle樹,其還提供有效的附加操作。此操作很有用,因為可以透過將新事務附加到舊賬本歷史來進行遞增計算。Merkle樹累加器還可以生成一個有效的證明,證明在給定驗證器a提交到事務I之前的賬本資訊時,驗證器a′提交到賬本資訊最多 j > i具有與事務i相同的歷史。換句話說,這證明了a是a′的字首。這些證明可有效地驗證一個賬本歷史承諾是另一個承諾的延續。
修剪儲存:賬本歷史Merkle累加器的根雜湊,是系統完整狀態的驗證器。它在系統的每個現有版本、傳送的每個事務以及生成的每個事件上提交狀態。雖然第4.3節中描述的狀態儲存允許有效地儲存賬本狀態的多個版本,但驗證者可能希望減少以前版本佔用的空間。驗證者可自由地刪除舊狀態,因為它們不是處理新事務所必需的。Merkle樹累加器支援修剪歷史資料,其只需要O(log n)大小的儲存來附加新記錄[25]。
系統的任何副本都可以自由保留整個狀態,並可以將其資料的真實性跟蹤到由共識協議簽名的根雜湊。副本比驗證者更易於擴充套件。副本不需要得到保護,因為它們不參與共識,可建立多個副本來並行處理讀取查詢操作。
4、3 賬本狀態
一個賬本狀態Si表示版本i中所有賬戶的狀態,作為鍵值對的對映。金鑰基於256位帳戶地址,它們的對應值是賬戶確認者(在第4.4節中討論)(7)。使用類似於圖4的表示法,將對映表示為大小為2^256 的一棵Merkle樹,雖然一棵大小為2^256的樹是一種難以處理的表示,但可以應用最佳化來形成一棵稀疏Merkle樹。圖5顯示了兩種用於將簡單實現(1)轉換為有效實現的最佳化方法。首先,完全由空節點組成的子葉將替換為證書透明度系統(certificate transparency system) [27]中使用的佔位符值 ( 2 ) 。
這種最佳化建立了一個可跟蹤大小的表示,而沒有實質性地改變Merkle樹的證明生成。然而,子葉總是儲存在二叉樹的底層,這意味著結構需要在每次子葉修改時計算256個雜湊。第二種最佳化,用單個節點( 3 )替換由一個子葉組成的子樹。預期中,任何給定項的深度都是O(log n),其中n是二叉樹中專案數。這種最佳化減少了在對映上執行操作時要計算的雜湊數。
(腳註7: 地址的雜湊作為金鑰。即使地址是作為公鑰的雜湊,惡意方也可以在與真實地址幾乎衝突的地址建立一個新帳戶。雖然無法從此帳戶傳送任何事務,因為與該帳戶地址對應的私鑰未知,但樹中存在此近似衝突,會增加鄰近地址的證明長度。在將地址用作金鑰之前對其進行雜湊處理,可減少此類攻擊的影響。)
圖5 : 一棵稀疏Merkle樹儲存D = {01002 : A, 10002 : B, 10112 : C}的三個版本 有效實現,如Libra Core,可以最佳化它們的磁碟佈局和節點的批處理層,以避免在查詢過程中的請求。(8)
(腳註8: 這種最佳化使磁碟效能與以太坊中使用的16元帕特里夏Merkle樹方法相似,但其證明時間更短。)
當稀疏Merkle樹在執行事務後更新時,新的樹將重用上一版本的未更改部分,形成一個持久的資料結構[28,29]。如果一個事務修改了系統中n個帳戶中的m個帳戶,則在與以前版本不同的新賬本狀態樹中平均建立了O(m · log n) 個新分支和子葉。這種方法允許驗證者有效地儲存賬本狀態的多個版本。此功能還允許在處理事務後高效地重計算賬本狀態驗證器。
我們考慮過基於AVL樹結構,它比稀疏Merkle二叉樹結構提供了更優的最壞情況證明長度[30]。然而,稀疏Merkle樹方法允許實現者進行最佳化,例如跨伺服器共享儲存以及並行根雜湊計算。
4、4 賬戶
從邏輯層來講,帳戶是儲存在帳戶地址下的資源與模組的集合。從物理層來講,帳戶被視為位元組陣列值訪問路徑的有序對映。訪問路徑是一個分隔字串,類似於檔案系統中的路徑。
在協議的第一次迭代中,我們將一個帳戶序列化(serialize)為按訪問路徑排序的訪問路徑和值列表。帳戶的驗證器是此序列化表示的雜湊。注意,此表示要求在對帳戶進行任何修改之後,對整個帳戶重新計算驗證器。這個操作的開銷是O(n),其中n是完整帳戶的位元組表示長度。此外,從客戶端讀取,需要完整的帳戶資訊來驗證其中的任何特定值。
我們在賬戶中儲存資料的策略與其他系統(如以太坊)不同(9)。我們的方法允許Move語言透過將帳戶表示為訪問值路徑的有序對映,以提供更好的程式設計抽象。這種表示允許Move透過虛擬機器有效地管理資源的保護。Move鼓勵每個使用者在他們自己的賬戶當中持有資源。在最初發布的Libra當中,我們針對小客戶進行了最佳化。而在未來的版本中,我們可能會考慮支援更高效的結構來代表更大的賬戶,比如說Merkle AVL二叉樹結構 [30]。
(腳註9: 相反,以太坊[16]使用Merkle樹將資料儲存為稀疏memory對映,該二叉樹表示256位key到256位值的無序對映。這種方法使以太坊能夠有效地處理大的賬戶。)
賬戶收回和重加工:我們預計,隨著系統的使用,最終與帳戶相關的儲存增長可能會成為一個問題。正如gas鼓勵負責任地使用計算資源(見第3.1節),我們預計儲存可能需要一種租賃機制。我們正在評估最適合生態系統的租賃機制。我們討論了一個可應用於任何確定過期時間的策略選項,在時間到期之後,資料就可以被收回。
在每個影響賬戶的事務執行之後,虛擬機器計算邏輯過期時間,在該時間內,為帳戶分配的儲存可被釋放。虛擬機器可自由地應用任何確定性方法來確定到期時間。這種政策的一個例子是收取以Libra幣計價的費用,該費用是基於賬戶的儲存時間及其大小確定的。
帳戶的驗證器表示為H(H(AccountBlob)||(ExpirationTime),它對帳戶的過期時間進行編碼。到期後,虛擬機器拒絕訪問帳戶,從而引發一個錯誤。由於AccountBlob是不可訪問的,因此在ExpirationTime之後,驗證者可以自由刪除此資料。然而,驗證者允許事務在過期後透過重新計算其內容來重新啟用帳戶。該事務必須包含AccountBlob的預對映(preimage),並具有包含進一步儲存成本的關聯交易費用。透過重新計算和檢查與帳戶關聯的雜湊值(不刪除)來確保重新獲取內容的真實性。這種租賃實現方法是對現有帳戶收回方案的改進,而現有方法要求第三方傳送一個事務來刪除帳戶的儲存。
4、5 事件
Ei 是Ti執行期間發出的事件列表,每一個事件都以一個子葉儲存在Merkle樹中,該二叉樹Ei形成一個驗證器。事件被序列化為 form (A, p, c)的一個元組,它表示發出事件(A)、資料有效負載(p)以及計數器值(c)的事件結構訪問路徑。這些元組按Ti執行期間發出的事件順序j進行索引。根據慣例,我們把事件j→(a,p,c)包含在Ei中,表示為 (j,(A, p, c)) ∈ Ei。Ei的驗證器包含在TransactionInfoi中,因此,驗證者可構造一個包含證明,證明在第i個事務中,第j個事件是 (A, p, c)。
包含在每個事件中計數器c,在允許客戶端檢索給定訪問路徑A的事件列表方面發揮了特殊作用。客戶端也可以確保列表是完整的。在Move語言中,表示具有訪問路徑A的事件的事件結構,為其已發出的事件總數維護一個計數器C。
此計數器儲存在賬本狀態中,並在每次事務執行,在訪問路徑A上發出事件後進行遞增。
客戶端可獲取最近賬本狀態的驗證器,查詢與事件結構關聯的計數器以獲取訪問路徑A,並檢索事件總數C。
然後,客戶端可以查詢不受信任的服務,以獲取訪問路徑A上的事件列表。查詢響應由一組元組(i, j, A, p, c)組成,每個元組對應一個事件,其中i是發出事件的事務序列號,j是此事務中事件發出的順序。可以為每個事件提供 (j,(A, p, c)) ∈ Ei的關聯包含證明。由於客戶端知道訪問路徑A發出的事件總數,因此它們可確保不受信任的服務提供了此數量的不同事件,並按其序列號0 ≤ c < C對其進行排序。這使客戶端確信為A返回的事件列表是完整的。
此方案允許客戶端儲存對訪問路徑A上事件的已驗證訂閱。客戶端可定期為事件訪問路徑A觸發總計數器C,以確定訂閱是否是最新的。例如,客戶端可使用它在監視的地址上維護對傳入付款事務的訂閱。不受信任的第三方服務可為按訪問路徑索引的事件提供源,而客戶端可有效地驗證返回的結果。
五、拜占庭容錯共識
拜占庭容錯共識協議允許一組驗證者建立單個資料庫的邏輯層次。這種共識協議在驗證者之間複製提交的事務,對當前資料庫執行潛在的事務,然後就事務順序和結果執行的繫結承諾達成一致。因此,所有驗證者都可以按照狀態機器複製正規化[31]為給定的版本號維護相同的資料庫。
Libra 區塊鏈使用了一種HotStuff [13]共識協議的變體,叫做LibraBFT協議。在傳統的DLS[32]和PBF[33]以及更新的Casper[34]和Tendermint[35]的部分同步模型中,它提供了安全性和活力。本節概述LibraBFT共識機制中的關鍵決策。LibraBFT的完整報告[12]中包含了更詳細的分析,包括安全性和活性的證明。
即使存在拜占庭錯誤[36],驗證者之間也必須就資料庫狀態達成一致。拜占庭錯誤模型允許一些驗證者不受約束地任意偏離協議,除了在計算上的界限(因此不能破壞密碼學假設)。拜占庭錯誤是最壞的情況下的錯誤,在這種情況下,驗證者串通一氣,惡意破壞系統。一種可以容忍由惡意或被駭客攻擊的驗證者引起的拜占庭錯誤的共識協議,也可以減輕任意的硬體和軟體故障。
LibraBFT假設一組3f + 1的投票分佈在一組驗證者中,這些驗證者可能是誠實的,也可能是拜占庭式的。當最多f票由拜占庭驗證者控制時,LibraBFT仍然是安全的,它可以防止雙重支出和分叉等攻擊。LibraBFT保持活性——向客戶端提交事務,只要存在一個全球穩定時間(GST)之後,誠實的驗證者之間的所有訊息將在一個最大的網路延遲δ(這是引入的部分同步模型[32]傳送到其他誠實的驗證者。
除了傳統的保證之外,LibraBFT還在驗證者崩潰和重啟時維護安全性——即使所有驗證者同時重啟。
LibraBFT的概述:驗證者接收來自客戶端的交易,並透過一個共享的mempool協議來彼此共享這些事務。然後LibraBFT協議按順序進行。在每輪中,都有一個驗證者會扮演領導者(leader)的角色,並提出一個事務區塊來擴充套件一個包含完整的以前事務歷史的經認證的區塊序列(請參閱下面的法定人數證書quorum certificate)。
驗證者接收提議的區塊並檢查其投票規則,以確定是否應投票支援對該區塊進行驗證。這些簡單的規則確保LibraBFT的安全性——它們的實現可以被清晰地分離和審計。如果驗證者打算為這個區塊投票,它將執行該區塊的事務,而不受外部影響。這將導致驗證器對資料庫的計算,從而促成了區塊的執行。
這個驗證者然後傳送一個為這個區塊和資料庫驗證人進行的投票給這個leader。leader收集這些投票,形成一個法定人數證書(quorum certificate(QC)),它為這個區塊提供2f +1票的證據,並將該QC廣播給所有驗證者。
當滿足連續的3-chain提交規則時,區塊就會被提交。如果在第k輪有QC,並且在第k + 1輪和第k + 2輪有兩個區塊和QC確認,則區塊被提交。提交規則最終允許誠實的驗證者提交一個區塊。LibraBFT保證所有誠實的驗證者最終都將提交該區塊(以及從它連結的區塊的序列)。一旦提交了一個區塊序列,執行事務所產生的狀態就可以持續下去並形成一個複製的資料庫。
HotStuff範例的優點:我們針對驗證者的效能、可靠性、安全性、健壯實現的易用性和運營開銷等方面評估了幾個基於BFT的協議。我們的目標是選擇一種協議,該協議最初將支援至少100個驗證者,並且能夠隨著時間的推移發展到支援500 - 1000個驗證者。選擇HotStuff協議作為LibraBFT的基礎有三個原因:(1)安全性引數的簡單性和模組化;(2)容易將共識與執行相結合;(3)早期實驗中的效能表現良好。
這個HotStuff協議分解為安全模組(投票和提交規則)以及活性模組(pacemaker)。這種解耦提供了獨立開發和並行測試不同模組的能力。由於投票和提交規則簡單,協議安全性易於實現和驗證。將執行作為共識的一部分進行整合是很簡單的,以避免在基於領導者的協議中由非確定性執行引起的分叉問題。
最後,我們的早期原型證實了HotStuff中獨立測量的高吞吐量和低事務延遲[13]。我們沒有考慮基於工作量證明(PoW)的協議,因為它們的效能差,能源(和環境)成本高[24]。
HotStuff擴充套件及修改:在LibraBFT中,為了更好地支援Libra生態系統的目標,我們擴充套件和調整了核心HotStuff協議,並以多種方式進行實現。
重要的是,我們重新制定了安全條件,並提供安全、活力和樂觀反應的擴充套件證明。我們還實現了一些附加功能。首先,我們讓驗證者集體簽署區塊的結果狀態,而不僅僅是事務序列,從而使協議更能抵抗不確定性錯誤。這還允許客戶端使用QC來驗證從資料庫中讀取的內容。第二,我們設計了一個傳出明確超時的pacemaker資源管理器,驗證者依賴於這些pacemaker中的法定數量來進入下一輪,而不需要同步時鐘。第三,我們設計了一個不可預測的leader選舉機制,其中一輪的leader由最新提交區塊的提議者使用可驗證隨機函式(VRF) [37]確定。
這種機制限制了惡意方對leader發起有效拒絕服務攻擊的時間視窗。第四,我們使用聚合簽名[38]來保留簽署QC的身份驗證者。這使我們能夠向有助於QC的驗證者提供激勵(詳見9.3節內容)。它也不需要複雜的閾值金鑰設定[39]。
驗證者管理:Libra協議使用了一個Move模組管理一組驗證者。這在共識系統和定義可信驗證者集的密碼學經濟系統之間建立了一個清晰的分離。我們將在第9.2節中討論Libra區塊鏈對該合約的實施。以這種方式抽象驗證者管理,是透過定義Move中的核心區塊鏈原語而獲得的靈活性的一個例子。
對驗證者組的每次更改,都定義了一個新的epoch期。如果一個事務導致驗證者管理模組更改驗證者集,該事務將是當前epoch期提交的最後一個事務。該區塊或該epoch期以後的區塊中的任何後續事務,都將被忽略。一旦事務被提交,新的驗證者集就可開啟共識協議的下一個epoch期。
在一個epoch期內,客戶端不需要同步每個QC。由於已提交的QC包含對所有以前狀態的繫結承諾,客戶端只需要同步到當前epoch期的最新可用QC。如果此QC是其epoch期的最後一個,則客戶端可以看到新的一組驗證者,更新其epoch,然後再次同步到最新的QC。如果驗證者選擇按照第4.2節的描述刪減歷史記錄,那麼它需要保留至少足夠的資料,以向客戶端提供驗證者集更改的證明。
驗證者管理合約,必須提供滿足由共識協議要求的安全屬性的驗證者集。拜占庭驗證者不能控制超過 f的投票權。投票權必須在epoch期間以及epoch之後的一段時間內保持誠實,以允許客戶端與新配置同步。離線時間超過此時間段的客戶端需要使用一些外部真實性源重新同步,,以獲取他們信任的檢查點(例如,從其用於接收更新軟體的源重新同步)。此外,驗證者集不能過於頻繁地轉動,以致於破壞系統的效能,或者導致客戶端為過多數量的epoch期下載QC。我們計劃研究最佳的epoch期長度,預計這個時間會小於1天。
六、網路設計
Libra協議,與其他去中心化系統一樣,需要一個網路基層來支援其成員之間的通訊。驗證者之間的共識和共享的mempool協議都需要透過網際網路進行通訊,如第5節和第7節所述。
這個網路層在設計上是通用的,靈感來自libp2p [40]專案。它目前提供了兩個主要介面:(1)遠端過程呼叫(RPC)和(2)DirectSend,實現了向單個接收方傳送“即發即棄”(fire-and-forget)型別訊息。
驗證者之間的網路實現為一種點對點系統,使用了Multiaddr [41]方案進行對等(peer)定址,使用TCP用於可靠傳輸,Noise[42]用於身份驗證和完整的端到端加密,Yamux[43]用於在單個連線上的多路複用子流,push式gossip用於對等節點發現。每個新的子流都被分配了一個由傳送方和接收方都支援的協議。每個RPC和DirectSend型別都對應一個這樣的協議。
這個網路系統使用與共識系統相同的驗證者集管理智慧合約,作為當前驗證者集的一個真實性來源。這種合約持有每個驗證者的網路公鑰和共識公鑰。一個驗證者透過監視這個智慧合約中的更改來檢測驗證者集中的更改。
要加入這個驗證者間網路,一個驗證者必須使用這個合約定義的最新驗證者集中的網路公鑰進行身份驗證。啟動一個驗證者則需要一組種子對等節點(peers),首先對要加入的驗證者進行身份驗證,使其成為驗證者間網路的合格成員,然後與這個新對等節點共享它們的狀態。
Libra協議中的每個驗證者都維護著系統的完全成員關係檢視,並直接連線到需要與之通訊的任何驗證者。不能直接連線的驗證者則被假定為屬於系統拜占庭錯誤的範圍。
圖6:寫入事務透過Libra Core內部元件的流程
每個驗證者的健康資訊,使用週期性活性試樣來確定,不會在各驗證者之間進行共享;相反,每個驗證者直接監視它的對等節點驗證者的活動。我們期望這種方法在需要部分成員檢視、複雜的故障檢測器或通訊中繼之前,可以擴充套件到幾百個驗證者。
七、Libra Core實現
為了驗證Libra協議,我們構建了一個開源的原型實現 Libra Core[6]。這個實現是用Rust語言編寫的, 我們選擇Rust是因為這種語言專注於實現安全的編碼實踐,及其對系統程式設計的支援和高效能屬性。我們將系統的內部元件拆分為gRPC [44]服務。模組化允許更好的安全性;例如,共識安全元件可以在單獨的程序中執行,甚至可以在不同的機器上執行。
Libra 區塊鏈的安全性取決於驗證者、Move程式和Move 虛擬機器的正確實現。目前,我們正在解決Libra Core存在的這些問題。這包括隔離程式碼中有助於一個驗證者在共識期間簽署一個事務區塊的部分,並應用措施來增強這些元件正確性的保證(例如,廣泛的測試、正式規範和正式驗證)。高保證性方面的工作,還包括確保程式碼依賴項的安全性(例如,程式碼評審過程、原始碼控制、開源庫依賴項、構建系統和版本釋出管理)。
7.1 寫入請求生命週期
圖6展示了Libra Core中支援對去中心化資料庫進行寫入操作的事務的生命週期。本節深入研究事務如何透過驗證者的內部元件進行流動。
當客戶端希望向資料庫提交事務時,就會發起一個請求(request)。我們目前假設客戶端有一個帶外機制來查詢要提交事務的驗證者地址——這一機制的最終版本尚未設計出來。
准入控制(Admission control)。在接收一筆事務時,一個驗證者的准入控制元件會執行初始語法檢查(1)拋棄那些永遠不會被執行的畸形事務。儘早進行這些檢查可避免把資源用在垃圾事務上。准入控制可能訪問VM(2),VM使用儲存元件執行檢查,如確保賬戶有足夠的餘額支付事務所需的gas。接納控制元件設計,元件的驗證器可以執行多個例項。這種設計允許驗證者處理規模的事務和減輕拒絕服務攻擊。這個准入控制元件的設計,可以使一個驗證者執行多個元件例項。這種設計允許驗證者擴充套件傳入事務的處理,並減少拒絕服務攻擊。
Mempool。透過准入控制元件的檢查的事務將被送入驗證者的Mempool,Mempool容納著等待在記憶體緩衝區被執行的事務(3)。Mempool中可能容納著來自同一個地址的多筆事務。因為Mempool可以一次處理多筆事務,它能執行檢查,比如驗證同一地址上的一系列操作是否都能夠支付准入控制系統無法支付的gas。使用這個共享Mempool協議(4),一個驗證者可以在自己的Mempool中與其他驗證者共享事務,將從其他驗證者接收的事務放到自己的Mempool中。
共識。驗證者透過從其Mempool中選擇一系列事務來建立區塊。當驗證者充當共識協議的領導者(leader)時,它從其Mempool(5)中組成一個事務區塊。它將此事務區塊作為一個提議傳送給其他驗證者(6)。共識元件負責協調所有驗證器之間關於這些事務區塊的順序及其使用LibraBFT協議的執行結果的協議(第5節)。
事務執行。作為達成協議的一部分,事務區塊被傳遞給執行器元件(7),負責管理VM(8)中事務(第3節)的執行。這種執行發生在事務達成協議之前。這種早期執行是安全的,因為事務是具有確定性的,並且沒有外部影響。在執行區塊中事務之後,執行元件會構建一個這些事務的賬本歷史(第4.2節)。這個賬本歷史驗證者將返回到共識元件(9)。
這個leader然後將嘗試組成一個法定數量證書鏈(第5節)來就這個賬本驗證者達成共識,其中每一個證書都由一組驗證者來進行簽名,至少獲得2f+1個投票。
提交一個區塊。一旦共識演算法達成一致,任何誠實的驗證者都能確保所有其他誠實的驗證者最終將提交一個一致的賬本歷史。驗證者可以從執行元件的快取中讀取區塊執行的結果並更新其本地資料庫儲存(10)。
7.2 讀取請求生命週期
客戶端還可以提交讀取請求,為去中心化資料庫中帳戶的內容查詢驗證者。讀取請求不會改變狀態,可以在本地處理,而不需要經過共識。讀取請求被提交到驗證者的准入控制元件。准入控制元件執行初步檢查,從儲存中讀取資料,然後將結果傳送回客戶端。這個響應附帶一個法定數量證書(如第5節中描述),其中包含一個根雜湊(如第4節中描述)。
QC允許客戶端對查詢的響應進行身份驗證。這個客戶端使用與虛擬機器相同的技術,使用邏輯資料模型(第2節)來解釋帳戶的原始位元組。例如,要讀取地址a 的賬戶餘額,客戶端需要解碼嵌入到該帳戶的原始位元組中的LibraCoin.T資源。
八、 效能
Libra協議的使命是支援一個全球金融基礎設施。效能是實現這一目標的一個組成部分。我們將討論區塊鏈效能的三個組成部分:
吞吐量:區塊鏈每秒可處理的事務數;
延遲:客戶端向區塊鏈提交事務與另一方看到這筆事務之間的時間;
容量:區塊鏈儲存大量帳戶數的能力;
Libra協議還處於原型階段,因此我們還沒有具體的效能指標,但我們預計Libra協議在最初發布時可支援每秒1000筆支付事務,事務提交到確認的最終時間為10秒。隨著時間的推移,我們希望能夠增加系統的吞吐量,以滿足網路的需求。我們預計,許多支付事務將發生在鏈下進行,例如,在託管錢包內或透過使用支付通道[45]。因此,我們認為鏈上每秒支援1000筆事務,將滿足生態系統的初始需求。Libra協議旨在透過以下幾種方式來實現這些目標:
協議設計:Libra協議的很多元素都是基於效能挑選的。例如,LibraBFT演算法在三輪網路通訊中獲得共識結果,不需要任何實時延遲就區塊進行提議或投票。這使得提交延遲只受驗證者之間的網路延遲的限制。
我們還考慮採用並行化和分片(sharding)來選擇協議的元素。計算驗證者的稀疏Merkle樹方法允許跨多臺機器對資料庫進行分片((這增加了容量)或並行處理更新(這增加了吞吐量)。初始事務驗證(包括計算昂貴的簽名驗證)也可以實現並行化。
驗證者挑選:與大多數服務一樣,Libra區塊鏈的效能取決於操作它的底層驗證器的效能。去中心化與效能之間存在著一種妥協。對資源非常充足的驗證者需要,限制了可執行該角色實體的數量。然而,資源極度不足的驗證者的存在,將限制整個系統的效能。
我們傾向於採取一種平衡的方法,將目標鎖定在可以在商用硬體上執行的節點,許多實體都能買到這些硬體。但是,我們假設了這些節點執行在伺服器級別硬體上,並且與資料中心能夠連線良好。
根據我們進行的一次近似分析顯示,該系統很可能能滿足每秒1000筆事務的需求。
頻寬:如果我們假設每筆事務需要5 KB的流量——包括透過mempool接收事務、重播事務、接收來自leader的區塊以及複製到客戶端的成本——那麼驗證者需要40 Mbps的網路連線來支援每秒1000筆事務。這種級別的頻寬還是能夠廣泛獲得的。
CPU:簽名驗證是與支付轉換操作相關的重要計算成本。我們設計了允許並行驗證事務簽名的協議。採用Modern簽名方案,一個普通商用CPU就可以支援每秒1000多個事務驗證。
磁碟:從大型伺服器供應商那裡,我們可以獲得16TB SSD儲存的伺服器。由於當前狀態是驗證者處理事務所需的惟一資訊,所以我們估計,如果帳戶大小約為4 KB(包括所有形式的開銷),那麼這將使得驗證者可儲存40億個帳戶。我們預計,磁碟儲存的發展、驗證器向多個分片的擴充套件,以及經濟激勵措施將允許商用系統保持使用這個系統。
歷史資料的增長可能會超出單個伺服器所能處理的數量。驗證者可隨意丟棄那些在處理新事務的過程中所不需要的歷史資料(參見第4.2節);但是,那些希望查詢來自過去事務事件的客戶端可能對這些資料感興趣。由於驗證者簽署了對該資料的繫結承諾,客戶端可自由地使用任何系統訪問資料,而不必信任交付資料的系統。我們希望這種型別的讀取流量能夠很容易地透過並行進行擴充套件。
九、 用Move來實施Libra的生態系統政策
Libra 區塊鏈是一個獨特的系統,它平衡了傳統金融網路的穩定性和由加密經濟手段管理的系統所提供的開放性。正如我們在第1節中討論的,Libra協議旨在支援Libra生態系統實現新的經濟[4]和治理[3]策略。該協議指定了一個靈活的框架,該框架在關鍵系統元件(如本地貨幣、驗證者管理和事務驗證)中是引數化的。在本節中,我們將討論Libra 區塊鏈如何使用Move程式語言定製這些元件。我們的討論集中在協調網路參與者和驗證者激勵的挑戰,以及支援Libra生態系統的執行、治理和演化的挑戰。
9.1 Libra幣
許多加密貨幣沒有真實世界資產的支援。因此,投資和投機一直是這些加密貨幣主要用例。投資者購買這些貨幣時,往往認為它們會大幅升值,然後可以以更高的價格賣出。對這些貨幣長期價值的信念波動,導致了相應的價格波動,有時會導致價值的大幅波動。
為了推動廣泛採用,Libra被設計成一種貨幣,任何使用者都會知道,Libra今天的價值與明天甚至更遠未來的價值都是接近的。儲備是實現價值保值的關鍵機制。透過儲備,每枚幣都有一套穩定的流動資產作為後盾。有了與儲備掛鉤的一群具有競爭力的流動性提供者的存在,使用者就可以放心,他們所持有的任何一枚幣都可以以高於或低於底層資產價值的狹窄價差,以法定貨幣出售。這從一開始就賦予了Libra內在價值,並有助於防範現有加密貨幣所經歷的投機性波動。
Libra的儲備資產是一個低波動性資產的集合,包括來自穩定且聲譽良好的國家央行發行的法幣和政府證券。由於Libra的價值實際上與一籃子法定貨幣掛鉤,從任何特定貨幣的角度來看,Libra的價值都會有波動。儲備金的組成旨在減輕這些波動的可能性和嚴重性,特別是在負面方向(例如,經濟危機中)。為此,該貨幣籃子的結構考慮到了資本保值和流動性。
該儲備由Libra協會管理(見第9.2節),該協會發布了一份關於該儲備執行的詳細報告[4]。使用者不直接與儲備介面。相反,為了支援更高的效率,會有一些授權轉售商,他們是由Libra協會唯一授權的實體,來處理大量的法定貨幣和Libra在儲備中的流入和流出。這些授權轉售商與事務所和其他買賣加密貨幣的機構相結合,為那些希望將現金與Libra進行來回兌換的使用者提供流動性。
為了實施這一計劃,Libra的合約允許Libra 協會在需求增加時鑄造新的Libra幣,以及在需求減少時銷燬它們。該協會不制定貨幣政策。它只能根據授權經銷商的要求鑄造和銷燬幣。使用者不必擔心這種關聯會導致通脹或貨幣貶值:要鑄造新硬幣,必須有相應的法定存款準備金。
使用Move自定義Libra合約的能力,允許在不修改底層協議或實現該協議的軟體的情況下定義此計劃。此外,還可以建立其他功能,比如需要多個簽名來鑄造貨幣和建立有限數量的金鑰來提高安全性。
9.2 驗證者管理和治理
共識演算法依賴於驗證者集管理Move模組來維護當前的驗證者集,並管理驗證者之間的投票分配。這種合約負責維護一個驗證者集,其中3f + 1的總投票中最多有f票由拜占庭驗證者控制。
最初,Libra區塊鏈只向創始成員(Founding Members)授予投票權,這些實體:(1)滿足一組預定義的創始成員資格標準[46],(2)擁有Libra投資代幣(Libra Investment Tokens)。這些規則有助於確保對擁有一個安全且活動的驗證者集的安全性需求。使用創始成員資格標準確保了創始成員都是已建立起聲譽的組織,使其不太可能出現惡意行為,並暗示他們將勤奮地捍衛自己的驗證者來抵禦外部攻擊。Libra投資代幣代表對準備金利息回報的預期,進一步激勵驗證者去維持系統的執行。由於儲備中的資產風險低、收益低,只有當網路成功、儲備規模大幅增長時,早期投資者才能獲得超額回報。
雖然這種評估驗證者資格的方法是對傳統許可區塊鏈(通常形成一組封閉的業務關係)的改進,但我們希望Libra 區塊鏈完全沒有許可。為此,我們計劃逐步過渡到權益證明(PoS)[47]系統,在該系統中,驗證者的投票權與他們所持有的Libra幣數量成正比。這將把生態系統的治理移交給它的使用者,同時透過要求驗證者持有稀缺資源並將它們的動機與健康系統操作結合起來,以防止Sybil攻擊[48]。這種過渡需要(1)生態系統足夠大,以防止單個壞行為者造成破壞;(2)為不想成為驗證者的使用者提供一個具有競爭性和可靠的委託市場;(3)解決Libra在Staking過程中面臨的技術和可用性挑戰。
Libra生態系統治理的另一個獨特點是驗證者形成了一個真實世界的實體,即非盈利的Libra協會,由一個驗證者委員會管理。該協會的每一個理事會成員代表著每個驗證者。理事會中成員的投票權重與共識協議中驗證者的投票權重相同。協會執行的任務包括管理儲備、評估驗證者資格標準以及指導Libra協議的開源開發。
Move使將驗證器管理和治理規則編碼為一個模組成為可能。Libra投資代幣可以使用Move資源來實現。Move透過將投資代幣或Libra幣包裝在資源中,從而防止獲得底層資產,從而允許對它們進行抵押。已抵押的資源可用於計算驗證者的投票權。這個合約可以配置變更生效的時間間隔,以減少驗證者集的變動。
Libra 協會的運作也得到了Move的幫助。由於該協會是儲備的運營商,它可以建立Move模組,將Libra的鑄造和銷燬權力委託給與授權經銷商進行互動的操作部門。該業務部門還可以評估潛在創始成員是否符合資格標準。Move允許靈活的治理機制,比如允許理事會行使其權力,透過投票收回其授權。
該協會發布了一份詳細的檔案,概述了其擬議的結構[3]。協會中的所有治理都源於驗證者理事會——該理事會擁有最終的權利來維護提供給協會的任何授權。因此,隨著驗證者集從最初的創始成員集更改為基於PoS的集,整個Libra生態系統的治理也在不斷髮展。
9.3 驗證者的安全與激勵
在初始設定中,使用創始成員作為驗證者,我們認為每個驗證者的機構聲譽和經濟激勵足以確保拜占庭驗證器控制的投票不超過f。然而,在未來,一個以幣所有權為代表的開放系統將需要一個完全不同的市場設計。我們已開始瞭解基於利益相關者和消費者對錢包和其他代表的信心的區塊鏈系統的治理和均衡結構。在這個過程中,我們在Libra方法和更成熟的方法(如工作量證明(PoW))之間確定了新的市場設計妥協。
然而,要確定如何在確保網路安全和效率的同時,還能最好地保持生態系統中的長期競爭,這需要更多的研究。此外,由於基於份額(stake)的治理引入了對影響力的路徑依賴,因此有必要探索保護較小利益相關者和服務提供者的機制。
Move允許靈活界定相關激勵計劃,如gas定價或staking。例如,通常討論的stake slashing機制可以在Move中實現,方法是鎖定stake一段時間,如果驗證者違反LibraBFT演算法的規則,影響安全性,則自動懲罰驗證器。
類似地,當驗證者在LibraBFT演算法中投票時,這些投票可以記錄在資料庫中。該記錄允許Move模組基於演算法中的參與度來分發獎勵,從而激勵驗證者保持活動。Libra儲備的利息和gas支付也可以作為激勵的來源。這兩個來源都由Move模組管理,這增加了它們分配的靈活性。雖然需要更多的研究來設計一種方法來支援Libra生態系統的進化,但Move的靈活性確保了所需的方法可以在對Libra協議進行很少(如果有的話)更改的情況下實現。
十、 Libra接下來要做什麼?
我們為Libra協議提出了一個提案,允許一組驗證者提供一個去中心化資料庫來跟蹤可程式設計資源。我們討論了Libra協議的一個開源原型——Libra Core,並展示了為智慧合約引入的Move程式語言如何允許Libra協議實現Libra生態系統的獨特設計。
本文描述的協議和實現目前都處於原型階段。我們希望從新成立的Libra協會和更廣泛的社羣收集反饋,把這些想法變成一個開放的金融基礎設施。我們目前正在執行一個測試網路,以允許社羣對這個系統進行試驗。
我們正致力於這個系統的首次啟動,為了將其保持在可管理的範圍內,我們計劃在第一個版本中進行幾個簡化。在系統的早期,使用一組外部認可的創始成員減少了對共識激勵系統的需求,並允許更快的更新速度。我們預計只對系統定義的模組使用Move語言,而不是讓使用者定義自己的模組,這將使Libra生態系統能夠在完全形成Move語言之前啟動。這還允許在不損害使用Move定義核心系統行為所帶來的靈活性的情況下中斷所做的更改。然而,我們打算在Libra協議的未來版本中提供對Move語言的開放使用。
最後,我們目前正在Libra協會的框架內工作,以啟動這個新生態系統背後的技術基礎設施。我們釋出了一個路線圖[50]的工作,我們計劃為支援這個啟動做出貢獻。Libra協會的首要目標之一是將Libra的生態系統遷移到一個沒有許可的系統中。我們已經記錄了[5]在進行此遷移時所面臨的技術挑戰。該協會的開源社羣[6]提供了有關如何開始使用Libra測試網、試用Move語言和為Libra生態系統做出貢獻的資訊。
致謝
感謝以下人士對本文的討論和反饋:
Adrien Auclert,Morgan Beller,Tarun Chitra,James Everingham,Maurice Herlihy,Ravi Jagadeesan,Archana Jayaswal,Scott Duke Kominers,John Mitchell,Rajesh Nishtala, Roberto Rigobon,Jared Saia,Christina Smedley,Catherine Tucker, Kevin Weil,David Wong,Howard Wu,Nina Yiamsamatha,和Kevin Zhang。
﹏