以太坊智慧合約中必須瞭解的概念

買賣虛擬貨幣


本篇文章讓你瞭解以太坊中的幾個重要概念,有助於您理解智慧合約,包括其執行過程,以及Solidity語言在開發智慧合約時的相關概念

以太坊虛擬機器(EVM)是以太坊中智慧合約的執行環境。它不僅被沙箱封裝起來,事實上它被完全隔離,也就是說執行在EVM內部的程式碼不能接觸到網路、檔案系統或者其它程序。甚至智慧合約與其它智慧合約只有有限的接觸。賬戶以太坊中有兩類賬戶,它們共用同一個地址空間。外部賬戶,該類賬戶被公鑰-私鑰對控制(人類)。合約賬戶,該類賬戶被儲存在賬戶中的程式碼控制。外部賬戶的地址是由公鑰決定的,合約賬戶的地址是在建立改合約時確定的(這個地址由合約建立者的地址和該地址發出過的交易數量計算得到,地址發出過的交易數量也被稱作"nonce")
合約賬戶儲存了程式碼,外部賬戶則沒有,除了這點以外,這兩類賬戶對於EVM來說是一樣的。每個賬戶有一個key-value形式的持久化儲存。其中key和value的長度都是256bit,名字叫做storage.另外,每個賬戶都有一個以太幣餘額(單位是“Wei"),該賬戶餘額可以透過向它傳送帶有以太幣的交易來改變。交易一筆交易是一條訊息,從一個賬戶傳送到另一個賬戶(可能是相同的賬戶或者零賬戶,見下文)。交易可以包含二進位制資料(payload)和以太幣。如果目標賬戶包含程式碼,該程式碼會執行,payload就是輸入資料。
如果目標賬戶是零賬戶(賬戶地址是0),交易將建立一個新合約。正如上文所講,這個合約地址不是零地址,而是由合約建立者的地址和該地址發出過的交易數量(被稱為nonce)計算得到。建立合約交易的payload被當作EVM位元組碼執行。執行的輸出做為合約程式碼被永久儲存。這意味著,為了建立一個合約,你不需要向合約傳送真正的合約程式碼,而是傳送能夠返回真正程式碼的程式碼。Gas以太坊上的每筆交易都會被收取一定數量的gas,gas的目的是限制執行交易所需的工作量,同時為執行支付費用。當EVM執行交易時,gas將按照特定規則被逐漸消耗。gas price(gas價格,以太幣計)是由交易建立者設定的,傳送賬戶需要預付的交易費用 = gas price * gas amount。 如果執行結束還有gas剩餘,這些gas將被返還給傳送賬戶。無論執行到什麼位置,一旦gas被耗盡(比如降為負值),將會觸發一個out-of-gas異常。當前呼叫幀所做的所有狀態修改都將被回滾。儲存,主存和棧
每個賬戶有一塊持久化記憶體區域被稱為儲存。其形式為key-value,key和value的長度均為256位元。在合約裡,不能遍歷賬戶的儲存。相對於另外兩種,儲存的讀操作相對來說開銷較大,修改儲存更甚。一個合約只能對它自己的儲存進行讀寫。第二個記憶體區被稱為主存。合約執行每次訊息呼叫時,都有一塊新的,被清除過的主存。主存可以以位元組粒度定址,但是讀寫粒度為32位元組(256位元)。操作主存的開銷隨著其增長而變大(平方級別)。EVM不是基於暫存器,而是基於棧的虛擬機器。因此所有的計算都在一個被稱為棧的區域執行。棧最大有1024個元素,每個元素256位元。對棧的訪問只限於其頂端,方式為:允許複製最頂端的16個元素中的一個到棧頂,或者是交換棧頂元素和下面16個元素中的一個。所有其他操作都只能取最頂的兩個(或一個,或更多,取決於具體的操作)元素,並把結果壓在棧頂。當然可以把棧上的元素放到儲存或者主存中。但是無法只訪問棧上指定深度的那個元素,在那之前必須要把指定深度之上的所有元素都從棧中移除才行。指令集EVM的指令集被刻意保持在最小規模,以儘可能避免可能導致共識問題的錯誤實現。所有的指令都是針對256位元這個基本的資料型別的操作。具備常用的算術,位,邏輯和比較操作。也可以做到條件和無條件跳轉。此外,合約可以訪問當前的相關屬性,比如它的編號和時間戳。訊息呼叫
合約可以透過訊息呼叫的方式來呼叫其它合約或者傳送以太幣到非合約賬戶。訊息呼叫和交易非常類似,它們都有一個源,一個目標,資料負載,以太幣,gas和返回資料。事實上每個交易都可以被認為是一個頂層訊息呼叫,這個訊息呼叫會依次產生更多的訊息呼叫。一個合約可以決定剩餘gas的分配。比如內部訊息呼叫時使用多少gas,或者期望保留多少gas。如果在內部訊息呼叫時發生了out-of-gas異常(或者其他異常),合約將會得到通知,一個錯誤碼被壓在棧上。這種情況只是內部訊息呼叫的gas耗盡。在solidity中,這種情況下發起呼叫的合約預設會觸發一個人工異常。這個異常會列印出呼叫棧。就像之前說過的,被呼叫的合約(發起呼叫的合約也一樣)會擁有嶄新的主存並能夠訪問呼叫的負載。呼叫負載被儲存在一個單獨的被稱為calldata的區域。呼叫執行結束後,返回資料將被存放在呼叫方預先分配好的一塊記憶體中。呼叫層數被限制為1024,因此對於更加複雜的操作,我們應該使用迴圈而不是遞迴。程式碼呼叫和庫存在一種特殊型別的訊息呼叫,被稱為callcode。它跟訊息呼叫幾乎完全一樣,只是載入自目標地址的程式碼將在發起呼叫的合約上下文中執行。
這意味著一個合約可以在執行時從另外一個地址動態載入程式碼。儲存,當前地址和餘額都指向發起呼叫的合約,只有程式碼是從被呼叫地址獲取的。這使得Solidity可以實現”庫“。可複用的庫程式碼可以應用在一個合約的儲存上,可以用來實現複雜的資料結構。日誌在區塊層面,可以用一種特殊的可索引的資料結構來儲存資料。這個特性被稱為日誌,Solidity用它來實現事件。合約建立之後就無法訪問日誌資料,但是這些資料可以從外高效的訪問。因為部分日誌資料被儲存在布隆過濾器(Bloom filter) 中,我們可以高效並且安全的搜尋日誌,所以那些沒有下載整個區塊鏈的網路節點(輕客戶端)也可以找到這些日誌。建立合約甚至可以透過一個特殊的指令來建立其他合約(不是簡單的向零地址發起呼叫)。建立合約的呼叫跟普通的訊息呼叫的區別在於,負載資料執行的結果被當作程式碼,呼叫者/建立者在棧上得到新合約的地址。
自毀只有在某個地址上的合約執行自毀操作時,合約程式碼才會從區塊鏈上移除。合約地址上剩餘的以太幣會傳送給指定的目標,然後其儲存和程式碼被移除。注意,即使一個合約的程式碼不包含自毀指令,依然可以透過程式碼呼叫(callcode)來執行這個操作。

來源:區塊鏈大師 微訊號DACMaster

免責聲明:

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

推荐阅读

;