关于以太坊虚拟机 EVM
一、什么是EVM
EVM是以太坊協(xié)議的一部分,它用來處理智能合約的部署和執(zhí)行。除了在EOA(由用戶私鑰控制的所謂“外部賬戶”)之間的簡單轉(zhuǎn)賬交易以外,其他所有涉及狀態(tài)更新的操作都是通過EVM來計(jì)算的。從高層抽象的角度,運(yùn)行在以太坊區(qū)塊鏈上的EVM可以想象成一個包含了數(shù)百萬可執(zhí)行對象的全球化去中心化計(jì)算機(jī),這些可執(zhí)行對象都擁有它們各自的永久數(shù)據(jù)存儲。
EVM是一個“準(zhǔn)”圖靈完備的狀態(tài)機(jī),因?yàn)樵谄渲羞M(jìn)行的任意智能合約的執(zhí)行都必須限定在一個由可用的gas總量所限制的、有限的計(jì)算步驟數(shù)量之內(nèi)。
EVM是一個基于棧的架構(gòu),在一個棧中保存了所有的內(nèi)存數(shù)值。EVM的數(shù)據(jù)處理單位被定義為256位的“字”,并且它還有以下數(shù)據(jù)組件:
一個不可變的程序代碼存儲區(qū)ROM,加載了要執(zhí)行的智能合約字節(jié)碼。
一個內(nèi)容可變的內(nèi)存,它被嚴(yán)格初始化為全0的數(shù)值。
一個永久存儲,它是作為以太坊狀態(tài)的一部分而存在的,也會被初始化為0
二、與現(xiàn)有技術(shù)的比較
所謂“虛擬機(jī)”的概念通常用于對真實(shí)計(jì)算機(jī)的虛擬化,一般是通過一個像virtualbox或者QEMU這樣的“管理程序”,或者像Linux上的KVM這樣的完整操作系統(tǒng)實(shí)例來實(shí)現(xiàn)的。這些方案中都必須分別對實(shí)際的硬件、系統(tǒng)調(diào)用和其他內(nèi)核功能提供一個軟件抽象。
而EVM則運(yùn)行在一個更局限的領(lǐng)域,它僅僅是一個計(jì)算引擎,僅僅提供對計(jì)算和存儲的抽象。
就像Java虛擬機(jī)(JVM)那樣。從高級視角來看,JVM的設(shè)計(jì)提供了一個無須知曉底層宿主OS或硬件的運(yùn)行環(huán)境,從而提供了跨不同系統(tǒng)平臺的兼容性。像Java、Scala(基于JVM)或者C#(基于.NET)這樣的高級程序設(shè)計(jì)語言會被編譯為與它們對應(yīng)的虛擬機(jī)字節(jié)碼指令集。 同樣的,像LLL、SerPent、Mutan或solidity這樣的高級智能合約開發(fā)語言,也會被編譯為由EVM執(zhí)行的字節(jié)碼指令集
EVM沒有可調(diào)度性,因?yàn)閳?zhí)行順序是由外部所組織好的,也就是由以太坊客戶端通過驗(yàn)證區(qū)塊中的交易來決定哪些智能合約應(yīng)該運(yùn)行,以及他們的執(zhí)行順序應(yīng)該是什么。從這個角度講,以太坊世界計(jì)算機(jī)就像JavaScript引擎那樣是“單線程”的。EVM既沒有任何"系統(tǒng)接口”,也沒有“硬件支持”,因?yàn)椴]有任何物理機(jī)器需要與之交互。以太坊世界計(jì)算機(jī)是完全虛擬化的。
EVM指令集(字節(jié)碼)
EVM指令有很多標(biāo)準(zhǔn)機(jī)器碼指令組成,包含:算術(shù)和位運(yùn)算邏輯操作;執(zhí)行上下文查詢;棧、內(nèi)存和存儲訪問;處理流程操作;日志、跳轉(zhuǎn)和其他操作
三、以太坊的狀態(tài)
EVM的任務(wù)是基于以太坊協(xié)議、根據(jù)智能合約的代碼的執(zhí)行來計(jì)算合法的狀態(tài)轉(zhuǎn)換,用以更新以太坊的狀態(tài)。
這也就是將以太坊作為基于交易的狀態(tài)機(jī)所描述的層面,同時也是外部用戶(即賬戶持有人和礦工)通過創(chuàng)建、接受交易和對交易進(jìn)行排序打包來引發(fā)狀態(tài)轉(zhuǎn)換所反映的層面。
在最高級,我們有以太坊世界狀態(tài)的概念。世界狀態(tài)是一個以太坊地址到賬戶數(shù)據(jù)的映射。
具體來說,每個以太坊賬戶地址所對應(yīng)的賬戶數(shù)據(jù)都由以下幾個部分組成:一個以太幣余額,一個nonce, 賬戶的存儲(僅供智能合約使用的永久數(shù)據(jù)存儲)以及賬戶的程序代碼(如果賬戶是智能合約賬戶),一個EOA永遠(yuǎn)不會有代碼,且只有全空的存儲。
當(dāng)一個交易最終反映為一次智能合約代碼的執(zhí)行時,一個EVM實(shí)例會基于當(dāng)前正在創(chuàng)建的區(qū)塊信息和這個交易的信息被初始化出來。具體的說,就是會將調(diào)用的合約賬戶所對應(yīng)的代碼加載到EVM的ROM中,程序計(jì)數(shù)器置0,從調(diào)用的合約賬戶所對應(yīng)的存儲中加載存儲數(shù)據(jù),將內(nèi)存清零并將于區(qū)塊和其他環(huán)境變量相關(guān)的信息設(shè)置好。這個執(zhí)行中的關(guān)鍵變量就是提供給這次執(zhí)行的gas,這個gas被設(shè)定為原始交易開始時交易發(fā)送者支付的gas總量。在執(zhí)行的過程中,gas的供給會基于操作執(zhí)行的消耗相應(yīng)減少。
無論何時,只要gas的供給減小到0,我們就會得到一個“out of gas”的異常,執(zhí)行會立即終止,相應(yīng)的交易也即失敗。
把EVM的運(yùn)行想象為將以太坊世界狀態(tài)復(fù)制到一個沙盒中,如果執(zhí)行因?yàn)槿魏卧驔]有完成,那么這個沙盒中的狀態(tài)就會被丟棄。不過,如果執(zhí)行成功結(jié)束,那么真正的世界狀態(tài)就會被更新為這個沙盒的狀態(tài),包含所有對調(diào)用過的合約的存儲數(shù)據(jù)的修改、新創(chuàng)建的合約以及其間所有以太幣余額的轉(zhuǎn)移。
請注意,因?yàn)橹悄芎霞s可以自己產(chǎn)生交易,所以代碼執(zhí)行時一個遞歸的過程。一個合約可以調(diào)用其他合約,每個調(diào)用都會最終都會反映為另一個基于新目標(biāo)的EVM執(zhí)行。
每次EVM的實(shí)例化都會基于之前的EVM沙盒來構(gòu)造。每次實(shí)例化也會獲得一個指定數(shù)量的gas供給,它自己可能因?yàn)楂@得的gas過少而無法完成它的執(zhí)行。在這種情況下,沙盒的狀態(tài)就會被丟棄,執(zhí)行會返回到上一層調(diào)用。
四、合約部署代碼
我們創(chuàng)建和部署一個新合約到以太坊平臺上所使用的代碼和合約代碼本身有一個很重要但又很微妙的區(qū)別。
為了創(chuàng)建一個新合約,我們需要一個特殊的交易,其目標(biāo)地址to字段需要被指定為0x0,并且它的data字段需要被設(shè)置為合約的初始化代碼。
當(dāng)這樣一個合約創(chuàng)建交易被處理的時候,新合約賬戶的代碼其實(shí)并不是交易數(shù)據(jù)的data字段所附帶的代碼。一個EVM實(shí)例會將這個交易所附帶的data字段作為程序代碼加載到其ROM中,并將這個部署代碼的執(zhí)行輸出結(jié)果作為新合約賬戶的關(guān)聯(lián)代碼,通過這樣的方式,新合約就可以使用部署時的以太坊世界狀態(tài),以編程方式被初始化,并更改合約的存儲數(shù)據(jù)甚至發(fā)送以太幣或者創(chuàng)建更多的新合約。
當(dāng)我們編譯一個合約,比如在命令行使用solc,就會獲得部署字節(jié)碼,也會獲得運(yùn)行時字節(jié)碼。
使用部署字節(jié)碼來執(zhí)行初始化新合約賬戶的所有操作,包含實(shí)際交易調(diào)用這個新合約時需要執(zhí)行的字節(jié)碼(即運(yùn)行時字節(jié)碼)以及在合約的構(gòu)造函數(shù)中進(jìn)行初始化處理的代碼。
換句話說,運(yùn)行時字節(jié)碼就是當(dāng)新合約被調(diào)用時,所執(zhí)行的所有字節(jié)碼,僅此而已,其中并不包含需要在部署中使用的用來初始化合約的字節(jié)碼。
五、圖靈完備和gas
用簡單的術(shù)語來解釋,如果一個系統(tǒng)或者編程語言能夠解決你交給它的所有問題,它就是圖靈完備的。然而這種能力伴隨著一個非常重要的警示:有些問題需要無限的資源去解決。
由于停機(jī)問題,以太坊世界計(jì)算機(jī)就有了一個被程序要求永遠(yuǎn)執(zhí)行下去的風(fēng)險。這可能是由于某些意外情況或者惡意的目的。我們曾討論過以太坊就像是一個單線程的計(jì)算機(jī),沒有調(diào)度程序,所以它會被無限循環(huán)卡住,而這將會使得它變得不可用。
在有了gas之后,也就有了一個解決方案:如果在一個預(yù)先指定的最大計(jì)算量被用盡的時候計(jì)算還沒有結(jié)束,那么所有的處理都會無條件地停止。這就使得EVM成為一個準(zhǔn)圖靈完備的機(jī)器:它可以解決你交給它的所有問題,但前提是這個問題可以在一定量的計(jì)算量內(nèi)被解決。
六、區(qū)塊的gas限制
區(qū)塊的gas限制指的是一個區(qū)塊中的所有交易總共能消耗的最大gas數(shù)量,它也限定了一個區(qū)塊中能包含多少交易。
例如,我們假定有5個交易,它們的gas上限分別為30000、30000、40000、50000和50000。如果區(qū)塊的gas限制是180000,那么任意四個交易都可以包含到一個區(qū)塊中,第5個區(qū)塊則需要等待后續(xù)的區(qū)塊。如果是一個礦工嘗試包含一個gas消耗超過區(qū)塊gas限制的交易,那么這個區(qū)塊將會被網(wǎng)絡(luò)解決。
總結(jié)
以上是生活随笔為你收集整理的关于以太坊虚拟机 EVM的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: go视频提取音频
- 下一篇: 「已解答」沈阳米旗蛋糕店所有店址