如何透過Qtum量子鏈賬戶抽象層打通比特幣和以太坊生態?

買賣虛擬貨幣

Qtum賬戶抽象層(AAL)實現簡析

Qtum設計上以比特幣UTXO為基礎賬戶模型,並實現了支援EVM規範的智慧合約,這是透過賬戶抽象層(Account Abstract Layer, AAL)來完成的。AAL對UTXO賬戶和EVM合約賬戶之間進行了適配,這樣透過AAL可以使用UTXO交易輸出實現在鏈上建立智慧合約,傳送交易到合約賬戶用於觸發合約的執行,完成執行後AAL最終對執行結果進行處理並適配至UTXO。由於採用了AAL,合約開發者不需關心對合約操作相關的UTXO轉換細節,即可使用EVM的特性進行開發而且相容現有以太坊的智慧合約。本文透過對從UTXO交易到智慧合約執行的實現程式碼進行解讀,初略分析了AAL的工作過程。

1.UTXO交易新增的指令碼操作碼

Qtum 針對UTXO交易指令碼新增了三個操作碼OP_CREATE,OP_CALL和OP_SPEND,目的是用於為UTXO和EVM賬戶模型之間的轉換提供操作支援。這些操作碼定義在opcodetype列舉型別中:

這個三個操作碼分別有以下作用

  • OP_CREATE用於智慧合約的建立;
  • OP_CALL用於合約的執行;
  • OP_SPEND用於合約餘額的花費。

為了在區塊生成過程中,識別並處理由這幾個操作碼控制的交易,在用於UTXO模型交易的類CTransaction中增加了HasCreateOrCall()和HasOpSpend()函式,用於新區塊中對mempool中的交易處理,並在指令碼操作碼解析的EvalScript()函式中增加了相應的處理。

2.UTXO交易到EVM模型交易的轉換

產生新的區塊時,除了對UTXO交易進行常規的引數合法性、共識規則、DDOS攻擊檢查等之外,還需要使用操作碼檢查函式HasCreateOrCall()判斷交易輸出是否包含OP_CREATE或OP_CALL,分別對應著EVM需要執行合約建立或合約呼叫。這部分有以下的處理過程:

2.1 進行EVM模型的賬號引數提取

合約在EVM的執行用到了data、gasPrice、gasLimit、VM version這幾個引數,這些引數是透過RPC呼叫sendtocontract 傳送的,sendtocontract會生成一個UTXO交易,並在交易輸出中使用了OP_CALL操作碼,之後交易會廣播到區塊鏈網路上。AAL中從UTXO到EVM的適配是透過QtumTxConverter類實現的,在這一步中該類的成員函式extractionQtumTransactions()和parseEthTXParams()完成對所有此類UTXO交易輸出的引數提取。程式碼片段如下:

以上程式碼首先判斷如果opcode 為OP_CALL,則說明地址為vecAddr的合約已經建立,因此直接轉換成EVM格式的地址receiveAddress,否則為OP_CREATE,對應合約的建立,沒有該欄位,所以不做提取。接下來依次完成了data、gasPrice、gasLimit、VM version的提取,這些都是EVM執行bytecode時必不可少的引數。

2.2 進行EVM賬戶模型的交易轉換

交易轉換是透過QtumTxConverter類的函式 createEthTX()完成,使用前面一步提取的引數和UTXO的交易輸出vout建立了QtumTransaction型別的交易。由於QtumTransaction派生自EVM中的dev::eth::Transaction類,因此和EVM執行相關的操作QtumTransaction類都支援。

首先程式碼etp.receiveAddress == dev::Address()判斷該合約是EVM狀態中沒有而需要新建立的還是EVM狀態已經包含的合約,差別只在於合約地址。然後,QtumTransaction()建構函式完成了部分的交易引數構造,接下來的語句提取交易的傳送者(sender),之後設定交易HASH。一個UTXO交易支援多個輸入和輸出,Qtum的AAL設計考慮到了這種情況,因此AAL支援一個交易輸出包含UTXO賬號和合約賬號,透過最後設定的nOut指示該交易的nOut輸出是傳送到智慧合約的,所以該輸出將觸發合約執行。這樣就按照EVM的賬號模型完成了交易的轉換。

3.合約執行及執行結果的UTXO轉換

合約的執行會改變狀態(由QtumState類的例項化物件globalState統一管理),對於合約的狀態,Qtum沿用了EVM定義,所以能相容所有的符合EVM規範的智慧合約。但是賬戶金額的轉移(transfer),Qtum做了UTXO的轉換,這意味著智慧合約和普通的UTXO模型賬號之間能完成互動,這是AAL實現UTXO支援智慧合約的重要的一環。下面簡要介紹一下合約執行和狀態結果的轉換過程。

3.1 合約執行環境構建及合約執行

合約的執行是對合約處理中很關鍵的一步,直接對合約的狀態產生影響。透過ByteCodeExec類實現了EVM對合約bytecode的執行,主要函式是performByteCode()。這一步的主要流程是使用上面提取的交易引數,來進行虛擬機器執行環境的構建,之後完成合約的執行,其程式碼如下:

首先是構建合約執行環境,由BuildEVMEnvironment()完成。可以看到這個執行環境是針對每個獨立交易進行的,這樣就最大限度的把不同交易的合約執行過程隔離開,避免合約執行過程中的交叉影響。然後構建一個新的sealEngine類,該類是EVM執行引擎,由createSealEngine()函式具體完成。中間對出現的可能狀態異常進行檢查,之後globalState->execute()完成合約的執行,這裡使用到了構建的執行環境envInfo和EVM執行引擎se。

3.2 合約執行結果的UTXO轉換

合約執行完成後的結果儲存在vector<ResultExecute> result,vector向量理記錄了每個合約執行產生的EVM賬戶間transfer關係,AAL透過把這些transfer轉換成UTXO交易,完成了從EVM賬戶模型到UTXO模型交易的轉換。這一處理是透過processingResults()函式實現的,以下是程式碼片段。

首先定義了ByteCodeExecResult型別的resultBCE變數,用於儲存轉換的結果。使用操作碼OP_SPEND,用於實現交易的花費,這是因為比特幣的UTXO透過私鑰簽名在交易輸入解鎖後來實現餘額花費的,而EVM執行涉及不同賬戶之間的transfer,所以需要透過OP_SPEND實現這些transfer到UTXO模型交易的轉換。如果execRes.excepted不為None,即合約執行異常,則將餘額返還給合約呼叫者。否則,如果沒有異常,則將扣除消耗的gas之後的剩餘gas返還給合約的呼叫者。對於合約執行中出現的transfer其UTXO交易儲存在result[i].tx中。因此,經過這一步處理合約執行產生的不同UTXO賬戶之間的交易就儲存在valueTransfers向量中了,最終這些交易會包含進新的區塊中。至此AAL模組就完成了從EVM交易到UTXO的轉換。

4.總結

AAL透過新增的UTXO指令碼操作碼,協助完成合約的建立、執行和花費。在合約建立和執行前,需要進行UTXO交易到EVM模型交易的轉換,之後使用構建的EVM執行環境和引擎,完成合約的執行。AAL最終對合約的執行結果進行處理並從EVM適配至UTXO,這樣就實現了基於UTXO的智慧合約。AAL使得Qtum相容符合EVM規範的智慧合約,為Dapp提供一個新的基礎平臺,同時UTXO的優點使得諸如並行處理、隱私性等優點能得以保留。

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;