在使用智能合約時節省資金

在使用智能合約時節省資金

摘要

作為一種利用區塊鏈來執行真實合同的新型軟件,由於許多優點,智能合約的需求量很大。 以太坊是最大的區塊鏈平臺之一,通過在虛擬機中運行智能合約來支持智能合約。 為確保智能合約最終終止並防止濫用資源,以太坊向合約創建者收取部署智能合約的費用並向用戶收取執行智能合約的費用。 雖然我們之前的工作表明,未充分優化的智能合約可能會花費超過必要的金額,但它只列出了7種反模式和3種反模式的檢測方法。 在本文中,我們對這種欠優化的智能合約進行了第一次深入調查。 我們首先從真實智能合約的執行軌跡中識別出24種反模式。 然後,我們設計和開發GasReducer,這是第一個從智能合約的字節碼中自動檢測所有這些反模式的工具,並通過字節碼到字節碼優化用高效代碼替換它們。 使用GasReducer分析所有智能合約及其執行軌跡,我們分別在部署和調用智能合約時檢測到9,490,768和557,565,754個反模式實例。

反模式

EVM的狀態被定義為元組σ = {g,pc,m,s,st},用於表示剩餘Gas,程序計數器,存儲器,運行時堆棧(EVM是基於堆棧的VM)和存儲。 存儲是一個永久性空間,如數據庫,用於存儲信息(例如,賬戶餘額,智能合約的字節碼)。 操作OP的執行可以被定義為將函數ξ應用於EVM狀態σ並將其轉移到另一狀態σ×。

在智能合約中,如果存在與OS1在語義上等效但消耗更少Gas的另一操作序列OS2,則操作序列OS1是反模式實例。

我們通過從部署的智能合約的執行軌跡中查找實例來識別反模式。 執行軌跡是執行的EVM操作的有序序列。 我們首先從軌跡中收集N個執行操作(默認情況下N = 10,000),然後使用滑動窗口生成操作序列。 在本研究中,窗口大小(即,窗口中的操作數)在1到5的範圍內。 因此,總共收集了286,647個不同的操作序列。 通過手動仔細檢查,我們發現了許多反模式的實例,並將它們推廣到24種反模式中。

下圖說明了如何從執行軌跡中提取反模式。 軌跡包含347個EVM操作,為了便於顯示,我們顯示了一個包含5個操作的片段。 '‘|’之前的內容表示EVM操作,'‘|’之後的數字是執行這些操作後可用的Gas。 因此,可以通過減法來計算用於執行操作的Gas。 下圖還顯示出了通過滑動窗口從執行軌跡中提取的操作序列。 不同的序列用';'分隔,並且我們通過手動檢查所有15個操作序列找到反模式的實例。

在使用智能合約時節省資金


GasReducer

我們開發GasReducer以自動檢測智能合約字節碼中的所有24種反模式,並通過用高效代碼替換耗費Gas的代碼來進行字節碼到字節碼優化。

GasReducer(下圖)接收智能合約的字節碼並輸出優化的字節碼。 更準確地說,GasReducer首先將字節碼反彙編成彙編代碼(例如,add),然後可以使用以太坊提供的disasm命令將其讀取(步驟1)。 然後,它對彙編代碼進行反模式檢測(步驟2)。 如果找到,將生成包含每個發現的反模式實例的位置的報告以及相應的有效代碼。 否則,彙編代碼將使用asm命令組裝成字節碼(步驟3)。 利用該報告,GasReducer用高效代碼替換反模式實例(步驟4),然後重建彙編代碼(步驟5,第3.2節)。 GasReducer迭代檢測和優化,直到在彙編代碼中找不到反模式。

在使用智能合約時節省資金


在用高效代碼替換耗費Gas的代碼之後,彙編代碼的結構可能會被破壞。 具體來說,以太坊的協議指定控制流轉移(例如,跳轉)的跳轉目標應該在編譯中確定,替換過程可能導致跳轉操作指向錯誤的位置,從而在執行優化的智能合約時導致運行時異常。

GasReducer通過三個步驟重建彙編代碼。 首先,它根據報告通過搜索跳轉來計算優化後彙編代碼中每個跳轉的位置。 之後,GasReducer將跳躍操作(例如,jumpi)與其相應的跳躍關聯起來。 在大多數情況下,跳轉操作緊接著是一個push操作,其操作數是jumpdest的位置。 可以通過將push的操作數與jumpdest的位置進行匹配來識別關聯。 但是,匹配方法並不總是有效,因為跳轉目標可以通過一系列操作來計算。

為了解決這個問題,我們的方法使用模擬執行來查找關聯。 具體來說,我們在模擬環境中執行EVM操作直到跳轉操作,然後在堆棧上獲取跳轉目標的位置,因為在執行跳轉之前,其跳轉目標的位置應該存儲在堆棧中。 注意,僅模擬所有堆棧操作(例如,push1),算術操作(例如,添加),按位操作(例如,和)和比較操作(例如,iszero)就足夠了。

實驗

我們進行實驗來回答三個研究問題。 Q1:部署智能合約浪費了多少Gas? Q2:使用智能合約浪費了多少Gas? Q3:現有的編譯器優化能否消除所有反模式?

為了研究部署中浪費的Gas,我們需要獲得智能合約的字節碼。 由於所有智能合約都存儲在區塊鏈中,而以太坊提供API(即getCode())來下載字節碼,因此截至2017年6月10日,我們使用此API下載所有(即599,959)部署的智能合約。其中145,907智能合同沒有代碼(即,他們已從區塊鏈中刪除),GasReducer處理剩餘的454,052個智能合約。 為了檢查使用智能合約浪費的Gas,我們需要在智能合約的歷史執行中識別反模式實例。 獲得歷史執行並非易事,因為它們不存儲在區塊鏈中。 我們通過檢測EVM來記錄所有執行軌跡來解決這個問題。 因此,我們獲得從以太坊啟動到2017年6月10日的所有(即9,250,400份)執行軌跡,並調整GasReducer進行分析。

下圖顯示了每週執行軌跡中檢測到的浪費的Gas。 隨著時間的推移,我們觀察到一個穩定增長的趨勢(y軸是對數刻度),表明隨著以太坊的日益普及,用戶浪費了更多的Gas。 通過檢查異常連續四周的執行軌跡,GasReducer發現了8,207,970個{extcodesize,pop}序列和93,637,713個{balance,pop}序列。 這些序列與P3匹配,可以用一個pop替換。 事實證明,我們的分析結果與關於DoS攻擊的報告一致,目的是通過重複執行extcodesize,balance等來耗盡以太坊節點的計算資源。 更準確地說,攻擊者利用這兩個操作耗費資源但消耗Gas少的事實來對以太坊進行攻擊。 有趣的是,我們的字節碼到字節碼優化可以通過用廉價的pop替換那些耗費資源的序列來防止DoS攻擊。

在使用智能合約時節省資金


我們進一步研究了最新的和推薦的編譯器(即Solidity 0.4.17)對於消除反模式實例的智能合約的優化效果。 我們從Etherscan(https://etherscan.io/)下載智能合約的源代碼,並使用Solidity 0.4.17進行編譯,並打開優化。 通過將GasReducer應用於編譯的智能合約,我們發現515個已編譯的智能合約中的506個仍然有15,205個反模式實例。 在GasReducer處理後,節省了1,688,560單位的Gas。 下圖中的每個點(x,y)表示存在包含不多於x個反模式實例的y個智能合約。 因此,Q3的答案是:現有的編譯器優化無法消除所有反模式。

在使用智能合約時節省資金

本文主要貢獻

(1) 我們確定了24種反模式,即在部署和調用智能合約時浪費Gas的模式,並確定用於替換反模式實例的相應有效代碼。

(2) 我們設計和開發GasReducer,這是第一個從智能合約的字節碼中自動檢測這些反模式並用高效代碼替換它們的工具。 GasReducer將在論文發表後發佈。

(3) 我們對所有已部署的智能合約及其執行跟蹤進行實驗,並檢測大量用於部署和調用智能合約的反模式實例。

致謝

本文由南京大學軟件學院2019級碩士李紫欣翻譯轉述


分享到:


相關文章: