1. 程式人生 > >以太坊智慧合約的奇幻漂流

以太坊智慧合約的奇幻漂流

“A smart contract is a computer program executed in a secure
environment that directly controls digital assets.”
– Vitalik Buterin

在這裡插入圖片描述
作為以太坊的標誌性技術, 網路上已經有非常多的文章對智慧合約進行了介紹。今天Cindy將主要帶領大家經歷一場以太坊上智慧合約的生命週期之旅, 一起經歷合約儲存、建立、部署、執行、升級與銷燬的過程。
一起出發吧!

第一站: 合約儲存

以太坊上兩種賬戶型別: a) 個人賬戶 b)合約賬戶

首先, 以太坊智慧合約有兩種型別的賬戶: 外部個人賬戶和合約賬戶。這兩種型別賬戶的功能和特點都不一樣。

其次, 合約在部署時, 就會建立一個合約賬戶, 合約程式碼的可執行位元組碼(Bytecode)儲存在合約賬戶(CA)中。具體來說就是存在賬戶codehash指向的儲存區域; codeHash是程式碼的hash值,建立後不可更改。

再次, 資料主要儲存在賬戶storageRoot指向的儲存區域; storageRoot對應合約儲存結構的MPT樹根節點hash值,通過它能夠在資料庫中檢索到合約的變數資訊。
最後, 所有的基礎儲存目前都基於leveldb, 一種kv資料庫。

第二站: 合約建立

這裡我們用使用者A的例子做說明。
在這裡插入圖片描述

  1. 使用者A使用solidity等語言建立一份合約程式碼。
  2. A在IDE/錢包/其他客戶端,按一定的格式(from,data,value,Gas,GasPrice…)填寫data,然後確認(即發起一次transaction)
  3. 客戶端會填補 account nonce(tx計數器)、compile solidity、簽名
    等操作,並將to欄位置零(代表合約建立)。
  4. 該tx廣播到網路上,B節點收到該tx。
  5. B節點檢查TX是否有效、格式是否正確,驗證交易簽名是否合法。如果符合要求,計算可能的最大交易費用,確定傳送者的地址,並在本地的區塊鏈上檢視傳送者的餘額,如果賬戶餘額不足以支付最大的交易費用,則返回錯誤。
  6. 對於符合要求的交易請求,B將其放在交易儲存池中,並向其他節點轉發(比如轉發給了C)。C收到交易請求的節點重複使用者B的處理過程。

第三站: 合約部署

我們加入礦工B和C。
部署與挖礦過程

  1. B和C各自從本地的交易儲存池中拿到一批TX,然後打包進行hash計算(挖礦)。
  2. 假設B挖礦成功(獲得了記賬權),B會根據A提供的交易費用和合約程式碼,建立合約賬戶,並在賬戶空間中部署合約。合約賬戶地址在建立合約的TX確認後返回給A。
  3. B打包好的區塊(包含A建立的智慧合約)傳送至對等節點,並在全網傳播。
  4. C接收到該區塊,驗證區塊,如果區塊通過驗證:
    (1)C從記憶體池中刪除A建立的智慧合約交易請求。
    (2)C將區塊連結到本地最長鏈上(同步區塊)。
    (3)C將A的智慧合約部署在本地區塊鏈中。

區塊驗證過程

第四站: 合約執行

合約執行過程

  1. 使用者A按照一定格式在網路中發起一個TX請求;該請求被網路中節點B收到:

(1)如果符合要求,計算可能的最大交易費用(最大交易費用=Gas Limit×GasPrice),確定傳送方的地址,並在本地的區塊鏈上從傳送方賬戶中減去相應費用。
(2)如果賬戶餘額不足,則返回錯誤,這條交易被直接丟棄。

  1. B 同步到此交易,檢查交易是否有效、格式是否正確。
  2. 符合要求的交易請求,使用者B將其放在交易儲存池中,並向其他節點轉發. 其他節點執行和B同樣的操作過程。
  3. B挖礦成功。
    (1)對於轉賬交易,B將該交易和其他交易一起打包到區塊。
    (2)對於合約呼叫交易,B將該交易和其他交易一起打包到區塊中,並在本地的EVM上執行合約程式碼:
    (a)如果程式碼並未結束而Gas已經用完,那麼因程式碼執行而改變的狀態回滾到程式碼執行之前,但是已經支付的交易費用不可收回,交易費用由B獲得。
    (b)如果程式碼執行結束Gas還有剩餘,那麼B只會獲得消耗的Gas×GasPrice作為手續費,不會收取剩餘Gas對應的手續費。
    (3)B將包含A交易請求的區塊傳播到對等節點,在網路中廣播。
  4. C節點收到該區塊後:
    (1)驗證區塊(使用者A的交易的合法性也被再次驗證)。
    (a)驗證通過,C將記憶體池中A的交易請求刪掉,同時將B的區塊新增到本地的區塊鏈中。
    (b)驗證不通過,C丟棄該區塊。
    (2)執行區塊中的智慧合約交易
    (a)C在本地的EVM上執行該智慧合約,並與B的執行結果互相驗證。
  5. 網路上其他礦工節點重複C的執行過程:通過EVM在本地計算機上執行智慧合約,作為他們參與挖礦程序的一部分,然後得出一個結果並進行驗證。
    (1)理論上,如果沒有人惡意操作,每個計算機程式碼執行的結果都是相同的,因為它們執行著提供了相同資訊的相同合約程式碼。

在這裡插入圖片描述

第五站: 合約升級

  1. 部署在以太坊區塊鏈上的程式碼是不可改變的,即無法重新部署一個新的合約到相同的地址上。
  2. 智慧合約升級較為困難, 務必需要一次性將合約寫"完美"(測試/驗證要求極高)。
  3. hacking辦法:
    (1)部署一個擁有呼叫轉發功能的智慧合約
    (2)將收到的呼叫轉發到另外一個包含邏輯功能的合約地址
    (3)當進行合約升級時,只需要部署一個新的合約並修改轉發的目標地址,以指向新的合約。

第六站: 合約銷燬

合約發起者可以呼叫selfdestruct()方法即可銷燬合約。舉例:
在這裡插入圖片描述

終點站

好啦, 看完了以太坊智慧合約的6個生命週期過程, 各位是否在寫程式碼的時候更有深入的體會了呢?

歡迎大家留言,並加入本期**免費公開課《以太坊智慧合約開發與安全實踐》**學習,繼續以太坊上的奇幻之旅吧!
在這裡插入圖片描述
參考材料:
https://blog.ethereum.org/2016/06/02/go-ethereums-jit-evm/
https://github.com/ethereum/go-ethereum/blob/master/core/vm/evm.go
以太坊技術詳解與實戰. 閆鶯;鄭凱;郭眾鑫 編著 出版日期: 2018年06月

本文為Codefine原創文章。Codefine是領先的區塊鏈安全服務提供商,提供多種平臺上的智慧合約開發和安全解決方案,並以此連線全球範圍內區塊鏈的創新者和開發者。