基于XuperChain提出的一種智能合約并行執(zhí)行區(qū)塊鏈結構解析
近年來,區(qū)塊鏈技術不僅僅在加密貨幣交易,而且在存證和商品溯源等領域發(fā)揮著重要而廣泛的作用。然而,許多現(xiàn)有的區(qū)塊鏈系統(tǒng)在執(zhí)行智能合約方面表現(xiàn)不佳,無法滿足業(yè)務需求,因為智能合約是串行執(zhí)行的。XuperChain是一個新的區(qū)塊鏈系統(tǒng),它能夠支持智能合約在交易粒度并行地執(zhí)行和驗證。
引言
2009年中本聰(Satoshi Nakamoto)發(fā)明了比特幣,這是區(qū)塊鏈技術首次大規(guī)模成功應用。2014年,Vitalik Buterin發(fā)明了以太坊。與比特幣相比,以太坊支持智能合約,允許開發(fā)者使用基于區(qū)塊鏈的Solidity語言開發(fā)應用程序。2015,Linux基金會推出了超級賬本,它允許開發(fā)人員使用流行的語言如GO開發(fā)智能合約。這些系統(tǒng)在實際使用時性能表現(xiàn)的一般。本質上,是由于智能合約是串行執(zhí)行和串行驗證的,也就是說,對于單個節(jié)點,只能使用一個CPU核。XuperChain提出了一種新的區(qū)塊鏈數(shù)據(jù)模型:XuperModel?;谶@樣的底層數(shù)據(jù)模型,XuperChain可以使用多核計算能力來同時執(zhí)行和驗證智能合約。
智能合約的性能問題
在以太坊中,礦工首先從交易池中提取一組有序事務,然后在一系列事務中執(zhí)行智能合約調用,最后將它們打包成塊。接收該區(qū)塊的驗證節(jié)點還需要根據(jù)區(qū)塊內(nèi)的交易順序逐一執(zhí)行智能合約,這與之前對礦工進行打包的順序相同,驗證節(jié)點和礦工執(zhí)行的結果應該相同。
顯然,智能合約的串行執(zhí)行模式限制了區(qū)塊鏈系統(tǒng)的性能提升,因為串行執(zhí)行模式不能充分利用多核的計算能力。
Hyperledger Fabric提出了一種方法,其中智能合約首先在多個背書節(jié)點上執(zhí)行,以獲得讀寫集和背書節(jié)點的簽名。然后,排序節(jié)點對事務進行排序,并將它們打包到鏈上。這種方法的優(yōu)點是,有些事務執(zhí)行可以完全并行,但也有一些局限性:未確認事務的輸出不立即可見,新事務的讀依賴性只能是BlockChain中的已確認事務。這使得合約從調用到數(shù)據(jù)變更生效有較大的延時。
XuperChain讓智能合約執(zhí)行并行化
1 架構概述
XuperChain 事務執(zhí)行架構主要由三個部分組成,分別為VM層、Bridge層和Model層。 VM層主要用于解釋用戶執(zhí)行合同的字節(jié)碼,目前主要支持的有wasm、native。Bridge 層用于隔離用戶態(tài)和內(nèi)核態(tài),為用戶提供系統(tǒng)調用的接口,如get、put、迭代器等。Model層用于數(shù)據(jù)的提交、回滾和查詢,其內(nèi)置的smart cache機制能支持事務的并發(fā)執(zhí)行。
整個過程是這樣的。階段1:首先,客戶端觸發(fā)智能合約的預執(zhí)行,智能合約的字節(jié)碼由虛擬機解析執(zhí)行,執(zhí)行過程中的get、put等系統(tǒng)調用被Bridge層截獲,Bridge層將記錄執(zhí)行過程中的讀寫集,最后返回給客戶端。階段2:客戶端使用讀寫集組裝事務,并附加其簽名,然后將其提交到Model層。Model層將驗證讀取集的有效性和正確性,最后將其寫入數(shù)據(jù)庫中。
2 XuperModel
為了描述讀寫集,XuperChain定義了一個名為XuperModel的新的事務模型。該模型是比特幣UTXO模型的一個演變。在比特幣的UTXO模型中,每個交易都需要在輸入字段中引用早期交易的輸出,以證明資金來源。同樣,在XuperModel中,每個事務讀取的數(shù)據(jù)需要引用早先的事務寫入的數(shù)據(jù)。在XuperModel中,事務的輸入表示在執(zhí)行智能合約期間讀取的數(shù)據(jù)源,即數(shù)據(jù)來自哪些事務的輸出。事務的輸出表示事務寫入狀態(tài)數(shù)據(jù)庫的數(shù)據(jù),而這些數(shù)據(jù)會被后續(xù)的合約調用所引用。
為了進一步說明XuperModel,考慮兩個事務:tx1和tx2,其中tx1給變量a賦值1,tx2給變量b賦值2。然后還有第三個事務tx3,它調用一個合約來交換兩個變量的值,最后它的輸出是a=2和b=1,交換兩個變量。因此,在tx3的輸入中,它將引用tx1和tx2,因為前面的值是由tx1和tx2所修改的,如下圖所示:
3 XuperModel 的智能緩存
為了在運行時獲取合約的讀寫集,在預執(zhí)行每個合約時為其分配一個智能緩存。該緩存對狀態(tài)數(shù)據(jù)庫是只讀的,它可以為合約的預執(zhí)行生成讀寫集和結果。同時,也可用于合約的驗證。該緩存由四部分組成:一個寫集合實例、一個讀集合實例、一個Model實例的引用和一個穿透的標志,標記查詢是否可以穿透到Model實例中。
在合約預執(zhí)行時,穿透標志設置為True,Bridge為合同獲取該Cache,通過緩存可以讀取到DB中的數(shù)據(jù),查詢到的數(shù)據(jù)將緩存在Cache的讀集中。此外,合約可以寫入數(shù)據(jù),寫入數(shù)據(jù)將在Cache的寫集中生效。在預執(zhí)行之后,讀寫集可以被提取到并且一起并返回給客戶端。
驗證合約時,是否穿透的標志為false,驗證節(jié)點根據(jù)提交的事務的讀寫集一個新的Cache實例,如果事務中所引用的版本已經(jīng)過期,則事務直接失敗。若版本都有效,節(jié)點將再次執(zhí)行合約,但此時合約只能從讀取集讀取數(shù)據(jù)。同樣,寫入數(shù)據(jù)也只會在寫入集中生效。
為了進一步說明該Cache,考慮一次合約調用。XuperChain通過發(fā)起事務來調用合同。在預執(zhí)行合約時,Cache是一個三級的存儲對象。假設合約調用get操作,則Cache將首先從寫集讀取最新數(shù)據(jù),如果未找到,則從讀集中讀取,如果未找到,則從DB讀取。在驗證合約時,Cache是兩級存儲對象。假設驗證get操作,Cache將首先從寫集讀取最新數(shù)據(jù),如果找不到,則從讀集合中讀取。
4 事務沖突處理
前面提到Cache可以提取智能合約預執(zhí)行生成的讀寫集,這是事務提交時重要的組成部分。在XuperChain中,讀寫集由讀集和寫集組成。其中,讀集由元組組成:變量名,數(shù)據(jù)版本,反映了合同運行時讀取的變量狀態(tài),寫集為元組:變量名,數(shù)據(jù)值,表示合同執(zhí)行后對狀態(tài)數(shù)據(jù)庫的更改。
數(shù)據(jù)版本是一個元組:{ref_txid,ref_offset},表示修改變量的最后一個事務的ID和事務的輸出偏移量。Hyperledger結構[3]中的數(shù)據(jù)版本也是一個元組,但其版本由{blockheight、txnumber}組成,因此無法支持未確認事務輸出的即時可用性。顯然,XuperChain的設計可以支持更低的延遲。
當節(jié)點接收到一個事務時,會首先構造一個臨時Cache,并用事務攜帶的讀寫集填充該緩存,執(zhí)行合約,驗證智能合約執(zhí)行的結果是否正確。通過此檢查后,將驗證讀寫集中變量的版本是否與本地狀態(tài)數(shù)據(jù)庫中記錄的版本一致,如果不一致,則拒絕事務。值得注意的是,XuperChain要求寫入集中存在的所有變量名必須在讀取集中給出相應的數(shù)據(jù)版本,如果變量之前沒有值,則版本字段應保留為空。此外,如果本地未確認事務池中的事務與塊中的已確認事務之間存在讀寫集沖突,則將回滾未確認事務?;貪L操作是將寫集中的變量還原到讀集中聲明的上一個版本。
5 智能合約的并行預執(zhí)行
通過上述所提到Model、智能緩存和數(shù)據(jù)版本。XuperChain可以做到并行地執(zhí)行智能合約。Bridge會為每一個合約調用生成一個Context,Context里有一個Cache實例對象,并且生命周期僅限于一次預執(zhí)行調用。預執(zhí)行中的讀寫操作將在此Cache中生效,因此預執(zhí)行過程相互獨立。由于合約的預執(zhí)行是一個互不影響的過程,所以合約的預執(zhí)行可以并行進行。
上圖說明了合約是如何并行預執(zhí)行的。假設Contract1、Contract2和Contract3同時啟動。通過XuperBridge,初始化了三個Cache實例。Cache記錄合約執(zhí)行期間的讀寫集,并將其返回給用戶。
6 智能合約的并行驗證
當合約已經(jīng)預執(zhí)行完畢后。XuperChain返回給用戶一個讀寫集。用戶將在本地組裝整個事務,并立即將其提交給XuperChain網(wǎng)絡。然后XuperChain中的其他驗證節(jié)點將驗證合約。驗證過程如下所述:
合約的驗證主要包括3個步驟:
Step 1: XuperBridge初始化一個新的Context,并根據(jù)提交的事務的讀取集在Context中填充Cache。如果找不到讀集中指定版本的數(shù)據(jù),則表示數(shù)據(jù)優(yōu)先被其他合約更改,則Cache初始化失敗,合約調用失敗。
Step 2: 節(jié)點驗證合約以驗證寫集是否與事務中提交過來的寫入集是否相同。
Step 3: 如果讀寫集驗證相同,交易驗證通過,驗證通過后會更新狀態(tài)數(shù)據(jù),否則返回執(zhí)行失敗。
由于每個合約的驗證都在緩存中運行,沖突的事務將在步驟1中失敗。因此,不同合約的驗證是相互獨立的,合約的正確性驗證可以在第2步中并行進行。在第3步中,我們還會再次檢查讀集合的版本是否仍然有效。
7 局限性
以上就是XuperChain 中XuperModel支持合約并行執(zhí)行的內(nèi)容。并且所述的并發(fā)粒度是事務粒度,事務執(zhí)行完后會狀態(tài)是unconfirm狀態(tài),但是已經(jīng)寫入到DB中,后續(xù)合約調用可以直接引用該版本。但是XuperModel還有些缺點,首先,在合約執(zhí)行期間對數(shù)據(jù)庫的每個訪問都將生成一個讀集記錄。因此,如果用戶在合約調用期間訪問過多的數(shù)據(jù),那么讀集將太大,甚至無法傳輸?shù)狡渌?jié)點。此外,該模型的存儲資源占用較大,有待進一步優(yōu)化。
總結
XuperChain提出了一種新的智能合約并行執(zhí)行區(qū)塊鏈結構,其特點是將智能合約的執(zhí)行分為兩個不同的階段:預執(zhí)行階段和提交階段,并通過XuperModel數(shù)據(jù)模型解決并行環(huán)境中的交易沖突問題。XuperModel模型是從utxo[1]模型發(fā)展而來的。目前,學術界對如何提高智能合約的性能有很多的研究。其中一些是從底層的存儲引擎[4]開始的,其中一些使用STM技術[5]并行執(zhí)行合約。XuperChain基于讀寫集的方法是確定性的,并且易于實現(xiàn)。在業(yè)界,Hyperledger Fabric[3]也提出了一種基于讀寫集的模型。Fabric模型的主要缺點是數(shù)據(jù)版本綁定到塊高度,因此無法立即使用未確認事務的輸出。綜上所述,我們認為XuperChain提出的體系結構對于業(yè)界探索智能合約的并行化具有重要意義。今后,超級鏈團隊將繼續(xù)解決這個模型的一些局限性,提高性能。





