EVM源码分析(一)
author:Thomas_Xu
源码结构
源码地址:https://github.com/ethereum/go-ethereum
EVM的核心代码在core/vm下,而在进入到EVM之前的处理,我们会在第二章讲到,我们这里只分析EVM的层次结构。
以下为vm的目录结构:
runtime 包下的文件在实际运行的geth客户端中并没有被调用到,只是作为开发人员测试使用。
core/vm/runtime/env.go
设置evm运行环境,并返回新的evm对象core/vm/runtime/fuzz.go
fuzz使得开发者可以随机测试evm代码,详见go-fuzz
工具core/vm/runtime/runtime.go
设置evm运行环境,并执行相应的evm代码
下面的文件为实际的使用到的evm的代码文件
core/vm/analysis.go
分析指令跳转目标core/vm/common.go
存放常用工具方法core/vm/contract.go
合约数据结构core/vm/contracts.go
存放预编译好的合约core/vm/errors.go
定义一些常见错误core/vm/evm.go
evm对于解释器提供的一些操作接口core/vm/gas.go
计算一级指令耗费gascore/vm/gas_table.go
各种操作的gas消耗计算表core/vm/gen_structlog.go
生成structlog的 序列化json和反序列化方法core/vm/instructions.go
所有指令集的实现函数core/vm/interface.go
定义常用操作接口core/vm/interpreter.go
evm 指令解释器core/vm/intpool.go
常量池core/vm/jump_table.go
指令跳转表core/vm/logger.go
状态日志core/vm/logger_json.go
json形式日志core/vm/memory.go
evm 可操作内存core/vm/memory_table.go
evm内存操作表,衡量一些操作耗费内存大小core/vm/opcodes.go
定义操作码的名称和编号core/vm/stacks.go
evm栈操作core/vm/stack_table.go
evm栈验证函数
contract.go
结构
1 | // 对合约支持对象的引用 |
构造
1 | // NewContract 表示状态数据库中的以太坊合约。它包含合约代码,调用参数。合约实现 ContractRef |
AsDelegate将合约设置为委托调用并返回当前合同(用于链式调用)
1 | // AsDelegate sets the contract to be a delegate call and returns the current |
GetOp 用来获取下一跳指令
1 | // GetOp returns the n'th element in the contract's byte array |
UseGas使用Gas。
1 | // UseGas attempts the use gas and subtracts it and returns true on success |
SetCode ,SetCallCode 设置代码。
1 | // SetCode sets the code to the contract |
EVM.go
结构
1 | // 上下文为EVM提供辅助信息。 一旦提供,不应该修改。 |
构造函数
1 | // NewEVM retutrns a new EVM . The returned EVM is not thread safe and should |
合约创建 Create 会创建一个新的合约。
1 | // create creates a new contract using code as deployment code. |
Call方法, 无论我们转账或者是执行合约代码都会调用到这里, 同时合约里面的call指令也会执行到这里。
1 | // Call executes the contract associated with the addr with the given input as |
剩下的三个函数 CallCode, DelegateCall, 和 StaticCall,这三个函数不能由外部调用,只能由Opcode触发。
CallCode
1 | // CallCode differs from Call in the sense that it executes the given address' |
DelegateCall
1 | // DelegateCall differs from CallCode in the sense that it executes the given address' |
true
...
...
00:00
00:00
This is copyright.