赞
踩
EVM有一个基于栈的架构,在一个栈中保存了所有内存数值。EVM的数据处理单位被定义为256位的“字”(这主要是为了方便处理哈希运算和椭圆曲线运算操作)
这里所说的内存数值是指那些EVM字节码运行所需要的输入、输出参数数据和智能合约程序运行中所需要的局部变量等数据,而不是指下文中所提到的“内存”数据;下文中的“内存”是一个与栈共同存在的、独立的临时存储空间。
以太坊EVM的架构和执行上下文
目前市面上比较主流的是BTC脚本引擎和以太坊虚拟机(Ethereum Virtual Machine, EVM)。
图灵完备的计算环境——以太坊虚拟机(EVM)。这就意味着在EVM上可以做所有的能想得到计算,包括无限循环。EVM指令包括一个JUMP的跳转指令,可让程序跳回前面的程序代码,也可以像条件判断语句那样做条件跳转,当满足一定条件时将程序跳转到另一个地方执行。另外,一个合约可以调用其他合约,这提供了潜在的递归调用的功能。
EVM模块主要分为三大模块:编译合约模块、Ledger模块和EVM执行模块。
EVM指令由很多标准机器码指令组成,包含:
EVM执行事务的流程如图所示
(1) EVM接收到Transaction信息,然后判断Transaction类型是部署合约还是执行合约。如果是部署合约,执行指令集,来存储合约地址和编译后的代码;如果是执行合约或是调用合约,则使用EVM来执行输入指令集。
(2) 执行上一条指令集之后,判断EVM是否停机,如果停机则判断是否正常停机,正常停机则更新合约状态到区块链,否则回滚合约状态。如果不停机则回到上一步(1)进行判断。
(3) 执行完的合约会返回一个执行结果,EVM会将结果存储在Receipt回执中,调用者可以通过Transaction的哈希来查询结果。
每轮执行时,通过调出代码的第pc(程序计数器)个字节,每个指令如何影响元组都有定义。例如,ADD将两个元素出栈并将它们的和入栈,将Gas减1并将pc加1; stack将顶部的两个元素出栈,并将第2个元素插入由第1个元素定义的合约存储位置,同样减少最多200的Gas值,并将pc加1。虽然有许多方法通过即时编译去优化以太坊,但以太坊的基础性的实施可以用几百行代码实现。
以太坊合约的代码是使用低级的基于堆栈的字节码的语言写成的,被称为“以太坊虚拟机代码”或者“EVM代码”。代码由一系列字节构成,每一个字节代表一种操作。一般而言,代码执行是无限循环,程序计数器每增加一(初始值为零)就执行一次操作,直到代码执行完毕或者遇到错误、STOP或者RETURN指令。
EVM不是基于寄存器的,而是基于栈的虚拟机。因此所有的计算都在一个称为栈的区域内执行。栈最大有1024个元素,每个元素有256位。对栈的访问只限于其顶端,允许复制最顶端的16个元素中的一个到栈顶,或者是交换栈顶元素和下面16个元素中的一个。所有其他操作都只能取最顶的一个或几个元素,并把结果压在栈顶。当然可以把栈里的元素放到存储或者主存中。但是无法只访问栈里指定深度的那个元素,在那之前必须把指定深度之上的所有元素都从栈中移除才行。
EVM的指令集被刻意保持在最小规模,以尽可能避免可能导致共识问题的错误。所有的指令都是针对256位这个基本的数据单位进行的操作,具备常用的算术、位、逻辑和比较操作,也可以进行条件和无条件跳转。
虚拟机(EVM)执行指令部分的Gas计算是最为复杂的。虚拟机(EVM)事务执行期间的所有操作,包括数据库读写、消息发送以及虚拟机采取的每个计算步骤都要消耗一定量的燃料,并且在不同参数和缓存影响的情况下都会对应有不同的燃料标价。图2-15是取自以太坊官方黄皮书中的非指令部分的燃料标价示例图。
黄皮书链接:https://ethereum.github.io/yellowpaper/paper.pdf
以太坊的高级语言最后会编译成在EVM中执行的EVM字节码(bytecode),部署在以太坊区块链上。以太坊提供3种编程语言:Solidity、Serpent和LLL。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。