1. 程式人生 > >以太坊虛擬機器(EVM) 區塊鏈技術分享

以太坊虛擬機器(EVM) 區塊鏈技術分享

以太坊是一個交易驅動的賬戶狀態機模型,所以咱們先從賬戶開始講的。

以太坊賬戶又分為外部擁有賬戶和合約賬戶,賬戶狀態含4個屬性:Nonce、 Balance、StorageRoot、CodeHash。

其中Nonce是序列號,表示這個賬戶發出了多少筆交易或建立了多少個合約,每交易或建立一次,序列化就加1,可以有效防止重放攻擊。

Balance就是賬戶有多少餘額。

StorageRoot和CodeHash只對合約賬戶有效,其中StorageRoot是一棵MPT樹的根雜湊,這棵樹將合約儲存的資料以樹型結構組織起來,便於存在性證明和定址。

CodeHash儲存的是合約的EVM(以太坊虛擬機器)程式碼的雜湊值。

除了CodeHash,其它我們都細講過了,所以本篇就講講CodeHash。根據定義,瞭解CodeHash主要就是要了解EVM(以太坊虛擬機器)。首先宣告一下,因為咱們目的不是程式設計,所以咱們對EVM的學習是淺嘗輒止(關鍵是我瞭解得也不深。。。)。

虛擬機器就是虛擬計算機,以太坊用軟體的形式實現了一個虛擬機器分佈在每個節點。每個節點上的虛擬機器都是一樣的,也就是說,相同的指令進入虛擬機器,出來的結果都是一樣的。所以可以說,以太坊是一臺用區塊鏈實現的世界計算機。

當然,為了安全起見,這臺虛擬機器在節點上是完全隔離的,它是一個完全獨立的“沙盒”。 虛擬機器的作用就是用來執行以太坊智慧合約,它是智慧合約執行的環境。

對於整個以太坊系統來說,EVM其實也就是一個函式。智慧合約的部署和呼叫都是由交易驅動,當有這類需求時,交易就會呼叫EVM這個函式,然後EVM一條條地執行相關指令。

EVM跟比特幣的腳本系統一樣,也是用堆疊方式實現的,關於堆疊可參考0627的文章。EVM的堆疊深度限制在1024層,也就是說最多往堆疊裡疊加1024個數據,而且每個堆疊項的資料長度是32位元組,與我們上篇說的合約賬戶的資料儲存長度對得上,所以,大家都把以太坊虛擬機器稱之為一個圖靈完備的256位虛擬機器。

EVM有自己的位元組碼,而且每個指令都是一個位元組。當然,我們編寫智慧合約的時候,不會直接使用位元組碼,因為對於人來說,太難讀了,我們通常使用類似於solidity的高階語言,然後再通過編譯器把高階語言轉換為EVM能讀懂的位元組碼。

最後我們一個最簡單的指令來看看EVM如何執行。

這個指令的高階語言形式是這樣的:
uint256 x = 1

這句指令的意思是定義一個uint256型別的資料x,並且給它賦值1,就是這麼簡單一件事。

但這條指令經過編譯後,到了EVM這裡就變成了一堆指令(方框內為註釋):

push(0x1)
將1壓入棧中,這個1就是要賦值的1

push(0x0)
將0壓入棧中,這個0是指x這個資料將要儲存到合約賬戶資料儲存(見上篇)的0號位置。這兩句執行完後,堆疊裡從頂往下,就有了0和1兩個資料

dup2
複製堆疊中從頂往下數的第二項,所以這時堆疊從頂往上就有了1、0、1三個資料

swap1
交換棧頂的兩項資料,這時堆疊從頂往下儲存的是0、1、1

sstore
從棧頂往下數,將第二項資料儲存到第一項標識的位置上,同時將這兩項彈出堆疊。這裡便是將資料1儲存到0號位置,前面因為已經將x與0號位置做了繫結,所以就完成了x=1的賦值。這時堆疊裡就只剩一層資料:1

pop
丟棄棧頂資料,這時堆疊變成空的了,等待下一條指令的執行

其實仔細看看,發現可以完全不要dup2,swap1,pop這三條指令,效果是一樣的。不清楚為什麼編譯後會用這種多餘的方式,可能也其他原因吧。