以太坊 EVM虚拟机框架分析
最近比较迷恋solidity和EVM,solidity研究了不少,发现还是需要结合EVM才能理解的比较透彻,最近准备详细研究一些EVM。研究了一下源码,发现EVM貌似会有新的版本,叫EWASM;不过现在貌似还没有应用,据说改动很大;笔者研究的还是EVM。之后会继续根据EWASM的进展。EVM模块支持合约的执行与调用,调用时根据合约地址获取到代码,生成环境后载入到EVM中运行。通...
最近比较迷恋solidity和EVM,solidity研究了不少,发现还是需要结合EVM才能理解的比较透彻,最近准备详细研究一些EVM。研究了一下源码,发现EVM貌似会有新的版本,叫EWASM;不过现在貌似还没有应用,据说改动很大;笔者研究的还是EVM。之后会继续根据EWASM的进展。
EVM模块支持合约的执行与调用,调用时根据合约地址获取到代码,生成环境后载入到EVM中运行。通常智能合约的开发流程是用solidlity编写逻辑代码,再通过编译器编译元数据,最后通过EVM解析之后,再发布到链上。
再来介绍一个几个关键的模块。
指令:文件opcodes.go中定义了所有的OpCode,该值是一个byte,合约编译出来的bytecode中,一个OpCode就是上面的一位。opcodes按功能分为9组(运算相关,块操作,加密相关等)。
指令函数集:jump.table.go中定义了四种指令集合,每个集合实质上是个256长度的数组,指令集分为了四种,分别是frontierInstructionSet、homesteadInstructionSet、byzantiumInstructionSet、constantinopleInstructionSet(荒地,农庄,拜占庭,君士坦丁堡);应该是对应了EVM的四个发展阶段。指令集向前兼容。
解释器:interpreter.go中有解释器的入口函数run,根据用户给定的输入数据,循环对智能合约中的代码进行解析,翻译成对应的指令函数集中的函数,并运行。
Gas计算:gas_table.go,gas.go,根据不同的运算,计算消耗的gas,具体的方法都定义在gas_table里面。
智能合约:contract.go,合约是EVM智能合约的存储单位也是解释器执行的基本单位,包含了代码,调用人,所有人,gas相关的信息。contracts.go ,包含了一些EVM预先编译好的一些合约,例如ecrecover、sha256hashripemd160hash。
memory:memory.go,内存用于一些内存操作(MLOAD,MSTORE,MSTORE8)及合约调用的参数拷贝(CALL,CALLCODE)。内存数据结构,维护了一个byte数组,MLOAD,MSTORE读取存入的时候都要指定位置及长度才能准确的读写。
stack:stack.go,EVM中栈用于保存操作数,每个操作数的类型是big.int.执行opcode的时候,从上往下弹出操作数,作为操作的参数。
statedb:go-ethereum/core/state/statedb.go,合约本身不保存数据,合约及其调用类似于数据库的日志,保存了合约定义以及对他的一系列操作,只要将这些操作执行一遍就能获取当前的结果,但是如果每次都要去执行就太慢了,因而这部分数据是会持久化到stateDb里面的。code中定义了两条指令SSTORE SLOAD用于从db中读写合约当前的状态。
log:logger.go,对evm运行过程,对memorty,stack,statedb,还有一些信息的记录。
需要注意的是在EVM中,栈是唯一免费的存放数据的区域,其他区域都需要支付gas。因此,这相当于鼓励尽量使用栈,但是栈的深度又有限制,可见写一个很棒的solidity是有难度的。
上图主要是对EVM的整个结构进行了一下总结,可能有不准确的地方,随着后续文章会慢慢改进;发现错误或者有建议的同学可以联系我。
更多推荐
所有评论(0)