挖礦之後,全面了解 EVM 源碼。

Milo Chen
6 min readAug 22, 2019

--

在 Post 此文章之前,我們曾經 post 過 帶你了解虛擬機 EVM 的源始碼 , 該篇文章是比較基本方式了解其開發。另外,在 Cypherpunks Taiwan 的演講主題「讓區塊鏈有價值的應用落地」中,也用最簡單的方式,以應用端的角度切入,帶你了解應用端如何發送信息(transaction)去啟動以太坊這個世界電腦 。

Client 端透過如 Wallet 或其它方法,以 private key 作完簽章並送 Transaction 至 任何 ethereum 的 node 之中。

在 eth/backend.go 中

func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {   eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock)}

它呼叫了 miner 的 New function

在 miner/miner.go 中

而 miner的 New 的建構之中又呼叫了 newWorker() 函數

func New(eth Backend, config *Config, chainConfig *params.ChainConfig, mux *event.TypeMux, engine consensus.Engine, isLocalBlock func(block *types.Block) bool) *Miner {   miner := &Miner{
eth: eth,
mux: mux,
engine: engine,
exitCh: make(chan struct{}),
worker: newWorker(config, chainConfig, engine, eth, mux, isLocalBlock),
canStart: 1,}go miner.update()return miner}

在 miner/worker.go 中

看見這個 newWorker 函數原始碼,最主要是啟動了一個

go worker.mainLoop()

而這個 mainLoop() 是一種 event looper 的 pattern ,它有一部份的主要功能是把 Transaction 交付於 EVM 中去執行。目前我們知道如下資訊:

— — — — — -

eth/backend.go 的建構子中呼叫了
miner/miner.go 的建構子,而該程式又呼叫了
miner/works.go 的建構子,並且啟動 mainLoop, 在當中對 commitTransaction 作 ApplyTransaction 的動作

— — — — — -

回到 miner/worker.go 的程式,
func (w *worker) mainLoop() {}
這個 mainLoop 是一種 event loop, 針對不同的 event ,持續作對應的處理,
其中一個event 為 txsCh , 在當中會呼叫 Worker 的 commitTransactions
這函數會一筆一筆的對每個transaction 作 commitTransaction()

在這個關鍵的 commitTransaction() 之中就會呼叫 core.ApplyTransaction()

在 core/state_processor.go 中的 ApplyTransaction()

在 core/state_processor.go 中

在當中會作兩件事,一個是 NewEVMContext, 以及 vm.NewEVM

context := NewEVMContext(msg, header, bc, author)// Create a new environment which holds all relevant information// about the transaction and calling mechanisms.vmenv := vm.NewEVM(context, statedb, config, cfg)

context 變數的設定

在 core/evm.go 中

它的 NewEVMContext() 會產生一個給EVM 使用的 執行脈落 Context ,該 context 是紀錄與 transaction 比較相關的資料

關於 vmevn 變數的設定

而vmenv 則是呼叫了

在 core/vm/evm.go 中

的 NewEVM () ,這個 NewEVM 程式內有個關鍵的東西叫

evm.interpreters = append(evm.interpreters, NewEVMInterpreter(evm, vmConfig))evm.interpreter = evm.interpreters[0]

(PS: 注意 core/vm/evm.go 與 core/evm.go 是不同隻的程式 )

為了看 NewEVMInterpreter 這程式

在 core/vm/interpreter.go 中

EVMInterpreter.Run

會有一有一個 Smart Contract with Program Counter (pc)

不斷從 Contract 取出 Op Code (GetOp)

contract.GetOp(pc), 也就是呼叫 contract.go 的 GetOp

在 core/vm/contract.go 中

res, err = operation.execute(&pc, in, contract, mem, stack)

這個 operation.execute 反應的是什麼呢 ?

它就會以 JumpTable 中的東西去執行,請見

在 core/vm/jump_table.go 中

func newFrontierInstructionSet() JumpTable {
return JumpTable{
STOP: {
...

各種 組語OpCode …

STOP, ADD, MUL, SUB, DIV, SDIV, MOD, SMOD, ADDMOD, EXP, …, CALLER, SHA3, BALANCE, SLOAD, SSTORE, JUMP, PC,

在 jump_table.go 中描述的是 怎麼解解析出來一組語,一行又一行的對應到 instructions.go 的程式碼。

如果你看 opJump, opPc 這兩個code 就很快猜的出來前面trace 程式的 source code 常用到的 intPool 的用途是怎麼一回事了。

對應 opStop opSstore 等 這些就是 intrstruction.go 下所實現的

現在我們已經有了大致概念,前面前先講到由 eth/backend.go miner 好資料後,如何去 ApplyTransaction, 接著依著 Smart Contract 的架構,讓 EVM 可以像是 program 一樣的被執行及一行一行運作。並且我們可以知道這些一行又一行運作的組語長在哪邊,程式碼在哪邊。也清楚知道一筆 transaction 的 Context 進來怎麼跟 EVM Instance 連接,然後完成 transaction 的執行內容。

--

--

Milo Chen
Milo Chen

Written by Milo Chen

Study in Law/CS/EE & Dev in blockchain, AI, IoT, mobile app. Good in almost programming language with github https://github.com/milochen0418. 永遠十八歲/對世界好奇/INFP型

No responses yet