待字閨中開發(fā)了一門區(qū)塊鏈方面的課程:《深入淺出ETH原理與智能合約開發(fā)》窘面,馬良老師講授。此簡書文集記錄我的學(xué)習(xí)筆記末早。
課程共8節(jié)課寨昙。其中,前四課講ETH原理午绳,后四課講智能合約。
第四課分為三部分:
- Ethash算法
- EVM框架
- Bloom Filter / Recipt
這篇文章是第四課第二部分的學(xué)習(xí)筆記:EVM框架。
這節(jié)課介紹的是以太坊虛擬機(jī)的設(shè)計框架杜跷。智能合約是以太坊的靈魂,而虛擬機(jī)是執(zhí)行合約的環(huán)境矫夷。
1葛闷、EVM的設(shè)計理念
以太坊虛擬機(jī)有一定的復(fù)雜性,其復(fù)雜性在于:需要考慮以太坊特殊的數(shù)據(jù)結(jié)構(gòu)双藕、區(qū)塊鏈的特點淑趾、Gas的計價策略,特定的密碼學(xué)操作蔓彩,等等治笨。
其設(shè)計理念如下:
- Stack/memory 模型。它是一個基于棧的虛擬機(jī)赤嚼。
- 32 Bytes的Word旷赖。棧中的每一個元素非常大,占32個字節(jié)更卒。因為過程中用到的很多數(shù)據(jù)都是32字節(jié)等孵。
- 調(diào)用深度上限為1024。
- 棧的大小無限制
- 臨時/永久存儲的區(qū)別蹂空。
- 完全可確定俯萌。每一步都是確定的,可以回滾上枕。
2咐熙、EVM的實現(xiàn)框架
虛擬機(jī)基本的執(zhí)行流程:
- 取指令
指令在哪兒?在以太坊虛擬機(jī)中辨萍,有一個叫做執(zhí)行環(huán)境的數(shù)據(jù)結(jié)構(gòu)棋恼,它就包括了合約的指令。而這些指令(圖右的 code )的 Hash 在全局狀態(tài)前綴樹中。在創(chuàng)建虛擬機(jī)實例后爪飘,這些代碼就拷貝到了執(zhí)行環(huán)境义起。這些指令是字節(jié)碼,如圖左上角师崎。
- 取操作數(shù)
根據(jù)合約編寫的內(nèi)容取操作數(shù)入棧默终。這些操作數(shù)可以是很多不同的內(nèi)容(圖左下角部分),如輸入數(shù)據(jù)的值(Input Data Value)犁罩,代碼的擁有者(Code Owner)齐蔽,區(qū)塊的頭部(Block Header),等昼汗。另外肴熏,執(zhí)行環(huán)境除了提供需要的數(shù)據(jù),還記錄了一些數(shù)據(jù)的狀態(tài)顷窒,如調(diào)用的深度(Message-Call Depth)蛙吏,日志(Log Series),返還Gas(Refund Balance)鞋吉,等鸦做。
- 檢查GAS策略
有的是根據(jù)操作的次數(shù),有的是根據(jù)輸入數(shù)據(jù)的長度谓着。
在虛擬機(jī)中泼诱,有一塊數(shù)據(jù)結(jié)構(gòu)是虛擬機(jī)狀態(tài),這里記錄了你還有多少GAS赊锚,臨時存儲的內(nèi)容治筒,記錄了多少Word(一個word是32字節(jié)), 最后是棧的內(nèi)容舷蒲。檢查內(nèi)容有耸袜,錢是不是夠,內(nèi)存是不是需要擴(kuò)張牲平,如果都滿足要求就會執(zhí)行合約堤框,出錯了就會回滾。
- 執(zhí)行指令
執(zhí)行后纵柿,一般會更新storage 的變量(如圖箭頭)
- 增加PC
移動指針蜈抓,執(zhí)行下一條。
3昂儒、EVM的常見指令
- 算術(shù)指令: ADD SUB MUL DIV MOD
- 比較指令: LT GT EQ AND OR
- SHA3: SHA3
實際是Keccek沟使,雖然名字寫的是SHA3。
- 執(zhí)行環(huán)境信息: ADDRESS ORIGIN CALLER
合約地址渊跋,發(fā)起者腊嗡,調(diào)用者
- 區(qū)塊信息: COINBASE DIFFICULTY NUMBER
挖礦受益人撤缴,區(qū)塊難度,區(qū)塊號
- 棧/存儲: POP PUSH DUP SWAP MLOAD/MSAVE SLOAD/SSTORE JUMP
- 系統(tǒng)操作: CREATE CALL CALLCODE RETURN SELFDESTRUCT INVALID
以上這些指令一般不會直接用到叽唱,平時用到的是腳本語言,再編譯出來微宝。但以下指令需要特別理解一下棺亭。
- CALLCODE/DELEGATECALL:用來使得合約以函數(shù)的形式調(diào)用其它合約的代碼。且棧和存儲空間利用當(dāng)前合約的資源蟋软,僅僅使用被調(diào)用合約的代碼镶摘。這樣便于合約代碼設(shè)計標(biāo)準(zhǔn)庫。
CALLCODE 的msg.sender 未能和庫調(diào)用邏輯一致岳守。 A-> B(callcode) ->C(lib)
DELEGATECALL的msg.sender 則和庫調(diào)用邏輯一致凄敢。 A-> B(delegatecall) ->C(lib)
所以,盡量使用 DELEGATECALL 指令湿痢。
SELFDESTRUCT:允許一個合約在必要的情境下刪除自己涝缝。實際上并不是立即執(zhí)行,而是在交易的最后被執(zhí)行譬重。這樣的話可以大大降低回滾已刪除合約這項功能在虛擬機(jī)中實現(xiàn)的復(fù)雜度拒逮。
SHA256,ECRECOVER和RIPEMD160不是作為操作碼而是包含在偽合約中臀规。
4滩援、GAS 計價策略
指令計價類型分為三種:單一計價類、按照數(shù)據(jù)長度計價塔嬉、返還類型玩徊。
比較昂貴的有圖右邊所示的幾種;其總體的邏輯是谨究,增加存儲負(fù)擔(dān)就貴恩袱,減輕了就便宜。
所以记盒,我們要盡量避免昂貴的操作憎蛤。
5、臨時/永久存儲的生命周期
以一個合約執(zhí)行過程說明一下纪吮。
- A調(diào)用B
- B執(zhí)行過程中俩檬,設(shè)置永久存儲的S值為5,臨時M值為9碾盟;
- B調(diào)用C
- C調(diào)用B棚辽,這時的B是一個新的實例,不是第2步中的B冰肴;
- 這時下面這個B中的S=5(永久)屈藐,M=0(臨時的榔组,不用上面的值);
- 在執(zhí)行B的過程中联逻,S變成了17搓扯,M變成了13;
- 返回到C包归,返回到B锨推,這時的S值為17,M還是之前的9公壤。
結(jié)論换可,永久存儲的可以跨越交易,跨越區(qū)塊厦幅;而臨時存儲的只限于一個實例沾鳄。
本節(jié)主要介紹了以太坊虛擬機(jī)的設(shè)計框架,不足之處确憨,請批評指正译荞。