科普 | 以太坊智慧合約的生命週期
編者注:本文轉載自“Codefine好碼安全”公眾號,講述了以太坊上的合約從部署到呼叫的完整過程。值得指出的是,因為與合約相關的交易被打包進區塊並得到計算的過程與普通交易是即為相似的,因此讀者也可藉此一窺以太坊這個計算機系統是如何執行的。
"A smart contract is a computer program executed in a secure environment that directly controls digital assets ."
-- Vitalik Buterin
作為以太坊的標誌性技術, 網路上已經有非常多的文章對智慧合約進行了介紹。今天Cindy將主要帶領大家經歷一場以太坊上智慧合約的生命週期之旅, 一起經歷合約儲存、建立、部署、執行、升級與銷燬的過程。
一起出發吧!
第一站:合約儲存
首先,以太坊智慧合約有兩種型別的賬戶:外部個人賬戶和合約賬戶。這兩種型別賬戶的功能和特點都不一樣。
其次,合約在部署時, 就會建立一個合約賬戶, 合約程式碼的可執行位元組碼(Bytecode)儲存在合約賬戶(CA)中。具體來說就是存在賬戶 codehash 指向的儲存區域;codeHash 是程式碼的 hash 值,建立後不可更改。
再次, 資料主要儲存在賬戶 storageRoot 指向的儲存區域;storageRoot 對應合約儲存結構的MPT樹根節點hash值,通過它能夠在資料庫中檢索到合約的變數資訊。
最後, 所有的基礎儲存目前都基於 leveldb, 一種 kv 資料庫。
第二站:合約建立
這裡我們用使用者 A 的例子做說明。
- 使用者 A 使用 solidity 等語言建立一份合約程式碼
- A 在 IDE/錢包/其他客戶端,按一定的格式(from,data,value,Gas,GasPrice....)填寫 data,然後確認(即發起一次transaction)
- 客戶端會填補 account nonce(tx計數器)、compile solidity、簽名 等操作,並將 to 欄位置零(代表合約建立)。
- 該 tx 廣播到網路上,B 節點收到該 tx。
- B 節點檢查 tx 是否有效、格式是否正確,驗證交易簽名是否合法。如果符合要求,計算可能的最大交易費用,確定傳送者的地址,並在本地的區塊鏈上檢視傳送者的餘額,如果賬戶餘額不足以支付最大的交易費用,則返回錯誤。
- 對於符合要求的交易請求,B 將其放在交易儲存池中,並向其他節點轉發(比如轉發給了C)。C 收到交易請求的節點重複使用者 B 的處理過程。
第三站:合約部署
我們加入礦工B和C。
-
B 和 C 各自從本地的交易儲存池中拿到一批 TX,然後打包進行 hash 計算(挖礦)。
-
假設 B 挖礦成功(獲得了記賬權),B 會根據 A 提供的交易費用和合約程式碼,建立合約賬戶,並在賬戶空間中部署合約。合約賬戶地址在建立合約的 tx 確認後返回給 A
-
B 打包好的區塊(包含 A 建立的智慧合約)傳送至對等節點,並在全網傳播。
-
C 接收到該區塊,驗證區塊,如果區塊通過驗證:
a. C 從記憶體池中刪除 A 建立的智慧合約交易請求
b. C 將區塊連結到本地最長鏈上(同步區塊)
c. C 將 A 的智慧合約部署在本地區塊鏈中。
第四站:合約執行
- 使用者 A 按照一定格式在網路中發起一個 tx 請求;該請求被網路中節點 B 收到: i. 如果符合要求,計算可能的最大交易費用(最大交易費用=Gas Limit×GasPrice),確定傳送方的地址,並在本地的區塊鏈上從傳送方賬戶中減去相應費用 ii. 如果賬戶餘額不足,則返回錯誤,這條交易被直接丟棄。
- B 同步到此交易,檢查交易是否有效、格式是否正確。
- 符合要求的交易請求,使用者 B 將其放在交易儲存池中,並向其他節點轉發. 其他節點執行和B同樣的操作過程.
- B 挖礦成功。 a. 對於轉賬交易,B 將該交易和其他交易一起打包到區塊。 b. 對於合約呼叫交易,B 將該交易和其他交易一起打包到區塊中,並在本地的 EVM 上執行合約程式碼: i. 如果程式碼並未結束而 Gas 已經用完,那麼因程式碼執行而改變的狀態回滾到程式碼執行之前,但是已經支付的交易費用不可收回,交易費用由B獲得。 ii. 如果程式碼執行結束 Gas 還有剩餘,那麼B只會獲得消耗 的Gas×GasPrice 作為手續費,不會收取剩餘 Gas 對應的手續費。 c. B 將包含 A 交易請求的區塊傳播到對等節點,在網路中廣播。
- C 節點收到該區塊後: a. 驗證區塊(使用者A的交易的合法性也被再次驗證) i. 驗證通過,C 將記憶體池中 A 的交易請求刪掉,同時將B的區塊新增到本地的區塊鏈中 ii. 驗證不通過,C 丟棄該區塊。 b. 執行區塊中的智慧合約交易 i. C 在本地的 EVM 上執行該智慧合約,並與 B 的執行結果互相驗證。
- 網路上其他礦工節點重複 C 的執行過程:通過 EVM 在本地計算機上執行智慧合約,作為他們參與挖礦程序的一部分,然後得出一個結果並進行驗證。 a. 理論上,如果沒有人惡意操作,每個計算機程式碼執行的結果都是相同的,因為它們執行著提供了相同資訊的相同合約程式碼。
第五站:合約升級
- 部署在以太坊區塊鏈上的程式碼是不可改變的,即無法重新部署一個新的合約到相同的地址上。(編者注:實際上是可以改變的。但需要)
- 智慧合約升級較為困難,務必需要一次性將合約寫"完美"(測試/驗證要求極高)。
- hacking 辦法: a. 部署一個擁有呼叫轉發功能的智慧合約 b. 將收到的呼叫轉發到另外一個包含邏輯功能的合約地址 c. 當進行合約升級時,只需要部署一個新的合約並修改轉發的目標地址,以指向新的合約。
第六站:合約銷燬
合約發起者可以呼叫 selfdestruct()
方法即可銷燬合約。舉例:
參考材料:
- ofollow,noindex" target="_blank">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 原創文章,ETHFANS 經授權轉發。Codefine 是領先的區塊鏈安全服務提供商,提供多種平臺上的智慧合約開發和安全解決方案, 並以此連線全球範圍內區塊鏈的創新者和開發者。