以太坊儲存機制
在EVM中允許執行智慧合約程式碼。合約狀態或記憶體儲存在智慧合約地址中。可以將這種儲存視為位於智慧合約地址的無限長度的資料結構陣列。儲存機制確儲存儲位置沒有衝突,並遵循一組規則。使用這些規則,我們可以解碼任何合約的狀態。解碼儲存在對映中的資料需要知道所使用的金鑰。合約資料的解碼使用RPC呼叫eth_getStorageAt進行。
插槽位置
變數在智慧合約的儲存陣列中的位置由程式碼中出現的順序以及變數的大小決定。此位置稱為插槽。如果一個變數小於256位,則EVM會嘗試在空間中容納一個以上的變數,因此一個以上的變數可能會佔用儲存陣列中單個插槽的空間。對映或陣列將始終佔據一個插槽。陣列和對映元素的位置遵循一組特殊的雜湊規則,本文將對此進行介紹,這些規則在以太坊文件中也有描述。下表(表1)提供了EVM遵循的分配規則的摘要。我們將看兩個智慧合約的示例,並使用表1中提供的規則對其進行解碼
256位變數的簡單示例首先讓我們看一個簡單示例,所有變數都是256bit(32位元組長)。這樣做使我們無需考慮可變變數即可檢視分配。請注意,當對數字應用keccack雜湊時,數字必須是0填充的64位值。所有解碼都是使用以太坊RPC呼叫eth_getStorageAt執行的,在本文中將其表示為GetStorageAt。可以使用任何語言打包程式(例如nethereum或web3j)來呼叫此RPC api。下圖(圖1)顯示瞭如何對智慧合約的地址和傳遞給它的位置值進行GetStorageAt呼叫。圖1左側的數字是變數的位置。對於基型別(uint、string等),可以將此位置傳遞到GetStorageAt以獲取變數值。對於陣列,位置將返回陣列的長度。透過將Keccack雜湊傳遞給索引為0的GetStorageAt來解碼陣列索引。陣列的每個後續索引位於與位置求和的雜湊值處。可以認為這是訪問陣列的指標並增加其位置以查詢每個元素,類似於C或C ++。傳遞給每個鍵的GetStoragetAt的位置值是鍵的keccack雜湊值和對映宣告的位置。對於多維對映,將金鑰和變數位置遞迴呼叫Keccack雜湊值。參見圖1中的示例進行說明。
接下來,我們來看一個發生變數打包的示例。打包要記住的是:
1. 它僅按出現順序適用於基本變數型別(uint128,string,int等)。EVM將按照程式碼中列出的順序在256位空間中打包儘可能多的變數。
2. 每個對映和陣列變數將佔用一個新的插槽。
3. 陣列變數對映將遵循打包規則。也就是說,如果一個元素小於256位,則陣列的多個索引將佔用儲存陣列中的單個插槽。圖2顯示並提供了發生的打包的說明。當型別的長度小於256位時,EVM嘗試將其他變數打包到插槽中。EVM按列出的順序選擇要打包的變數。對映和陣列始終出現在新位置。但是打包規則仍適用於解碼陣列索引,打包規則仍適用於儲存在對映中的結構。有關這種情況下如何儲存變數的說明,請參見圖2。
繼 承
關於繼承的說明。當智慧合約繼承其他智慧合約時,基本智慧合約的儲存變數將按繼承順序佔據儲存陣列的第一個插槽。子類的儲存變數將隨後出現。
結 論
如前所述,我們在本文介紹的規則來解碼以太坊智慧合約的儲存機制。在接下來的,第2部分將描述的智慧合約規則編寫的工具。相關文章閱讀:
區塊鏈研究實驗室|如何編寫智慧合約,最佳化以太坊gas的消耗
區塊鏈研究實驗室|減少智慧合約程式碼複雜性並提高可維護性
區塊鏈研究實驗室|如何使用Python為區塊鏈編寫智慧合約-第一部分
區塊鏈研究實驗室|如何使用Python為區塊鏈編寫智慧合約-第二部分