在区块链上,用户通过运行部署在区块链上的合约,完成需要共识的操作。

以太坊虚拟机,是智能合约代码的执行器。

当智能合约被编译成二进制文件后,被部署到区块链上。

用户通过调用智能合约的接口,来触发智能合约的执行操作。

EVM执行智能合约的代码,修改当前区块链上的数据(状态)。

被修改的数据,会被共识,确保一致性。

EVMC – Ethereum Client-VM Connector API

新版本的以太坊将EVM从节点代码中剥离出来,形成一个独立的模块。EVM与节点的交互,抽象出EVMC接口标准。

通过EVMC,节点可以对接多种虚拟机,而不仅限于传统的基于solidity的虚拟机。

传统的solidity虚拟机,在以太坊中称为interpreter,下文主要解释interpreter的实现。

EVMC 接口

EVMC主要定义了两种调用的接口:

  • Instance接口:节点调用EVM的接口
  • Callback接口:EVM回调节点的接口

EVM本身不保存状态数据,节点通过instance接口操作EVM,EVM反过来,调Callback接口,对节点的状态进行操作。

Instance 接口

定义了节点对虚拟机的操作,包括创建,销毁,设置等。

接口定义在evmc_instance(evmc.h)中

  • abi_version
  • name
  • version
  • destroy
  • execute
  • set_tracer
  • set_option

Callback接口

定义了EVM对节点的操作,主要是对state读写、区块信息的读写等。

接口定义在evmc_context_fn_table(evmc.h)中。

  • evmc_account_exists_fn account_exists
  • evmc_get_storage_fn get_storage
  • evmc_set_storage_fn set_storage
  • evmc_get_balance_fn get_balance
  • evmc_get_code_size_fn get_code_size
  • evmc_get_code_hash_fn get_code_hash
  • evmc_copy_code_fn copy_code
  • evmc_selfdestruct_fn selfdestruct
  • evmc_call_fn call
  • evmc_get_tx_context_fn get_tx_context
  • evmc_get_block_hash_fn get_block_hash
  • evmc_emit_log_fn emit_log

EVM 执行

EVM 指令

solidity是合约的执行语言,solidity被solc编译后,变成类似于汇编的EVM指令。

Interpreter定义了一套完整的指令集。solidity被编译后,生成二进制文件,二进制文件就是EVM指令的集合,交易以二进制的形式发往节点,节点收到后,通过EVMC调用EVM执行这些指令。

在EVM中,用代码模拟实现了这些指令的逻辑。

Solidity是基于堆栈的语言,EVM在执行二进制时,也是以堆栈的方式进行调用。

算术指令举例

一条ADD指令,在EVM中的代码实现如下。

SP是堆栈的指针,从栈顶第一和第二个位置(SP[0]SP[1])拿出数据,进行加和后,写入结果堆栈SPP的顶端SPP[0]

CASE(ADD)
{ON_OP();updateIOGas();// pops two items and pushes their sum mod 2^256.m_SPP[0] = m_SP[0] + m_SP[1];
}

跳转指令举例

JUMP指令,实现了二进制代码间的跳转。首先从堆栈顶端SP[0]取出待跳转的地址,验证一下是否越界,放到程序计数器PC中,下一个指令,将从PC指向的位置开始执行。

CASE(JUMP)
{ON_OP();updateIOGas();m_PC = verifyJumpDest(m_SP[0]);
}

状态读指令举例

SLOAD可以查询状态数据。大致过程是,

  • 从堆栈顶端SP[0]取出要访问的key,
  • 把key作为参数,然后调evmc的callback函数get_storage() ,查询相应的key对应的value。
  • 之后将读到的value写到结果堆栈SPP的顶端SPP[0]
CASE(SLOAD)
{m_runGas = m_rev >= EVMC_TANGERINE_WHISTLE ? 200 : 50;ON_OP();updateIOGas();evmc_uint256be key = toEvmC(m_SP[0]);evmc_uint256be value;m_context->fn_table->get_storage(&value, m_context, &m_message->destination, &key);m_SPP[0] = fromEvmC(value);
}

状态写指令举例

SSTORE指令可以将数据写到节点的状态中,大致过程是,从栈顶第一和第二个位置(SP[0]SP[1])拿出key和value,把key和value作为参数,调用evmc的callback函数set_storage() ,写入节点的状态。

CASE(SSTORE)
{ON_OP();if (m_message->flags & EVMC_STATIC)throwDisallowedStateChange();static_assert(VMSchedule::sstoreResetGas <= VMSchedule::sstoreSetGas, "Wrong SSTORE gas costs");m_runGas = VMSchedule::sstoreResetGas;  // Charge the modification cost up front.updateIOGas();evmc_uint256be key = toEvmC(m_SP[0]);evmc_uint256be value = toEvmC(m_SP[1]);auto status =m_context->fn_table->set_storage(m_context, &m_message->destination, &key, &value);if (status == EVMC_STORAGE_ADDED){// Charge additional amount for added storage item.m_runGas = VMSchedule::sstoreSetGas - VMSchedule::sstoreResetGas;updateIOGas();}
}

合约调用指令举例

CALL指令能够根据地址调用另外一个合约。首先,EVM判断是CALL指令,调用caseCall()。

在caseCall()中,用caseCallSetup()从堆栈中拿出数据,封装成msg,作为参数,调用evmc的callback函数call。

Eth在被回调call()后,启动一个新的EVM,处理调用,之后将新的EVM的执行结果,通过call()```的参数返回给当前的EVM,当前的EVM将结果写入结果堆栈SSP中,调用结束。合约创建的逻辑与此逻辑类似。

CASE(CALL)
CASE(CALLCODE)
{ON_OP();if (m_OP == Instruction::DELEGATECALL && m_rev < EVMC_HOMESTEAD)throwBadInstruction();if (m_OP == Instruction::STATICCALL && m_rev < EVMC_BYZANTIUM)throwBadInstruction();if (m_OP == Instruction::CALL && m_message->flags & EVMC_STATIC && m_SP[2] != 0)throwDisallowedStateChange();m_bounce = &VM::caseCall;
}
BREAKvoid VM::caseCall()
{m_bounce = &VM::interpretCases;evmc_message msg = {};// Clear the return data buffer. This will not free the memory.m_returnData.clear();bytesRef output;if (caseCallSetup(msg, output)){evmc_result result;m_context->fn_table->call(&result, m_context, &msg);m_returnData.assign(result.output_data, result.output_data + result.output_size);bytesConstRef{&m_returnData}.copyTo(output);m_SPP[0] = result.status_code == EVMC_SUCCESS ? 1 : 0;m_io_gas += result.gas_left;if (result.release)result.release(&result);}else{m_SPP[0] = 0;m_io_gas += msg.gas;}++m_PC;
}

总结

EVM是一个状态执行的机器,输入是solidity编译后的二进制指令和节点的状态数据,输出是节点状态的改变。

以太坊通过EVMC实现了多种虚拟机的兼容。但截至目前,并未出现除开interpreter之外的,真正生产可用的虚拟机。也许要做到同一份代码在不同的虚拟机上跑出相同的结果,是一件很难的事情。

https://fisco-bcos-documentation.readthedocs.io/zh_CN/latest/docs/design/virtual_machine/evm.html?highlight=EVM

以太坊虚拟机 EVM(1)EVMC interpreter相关推荐

  1. 以太坊虚拟机EVM的缺陷与不足

    首先对作者做个简单的自我介绍,Jordan Earls是Qtum量子链的联合创始人之一,目前担任Qtum量子链全球首席工程师.Qtum目前采用了以太坊虚拟机(Ethereum Virtual Mach ...

  2. 以太坊虚拟机EVM究竟是个啥

    基本概念 EVM(ETHereum Virtual Machine)是「以太坊虚拟机」的缩写.如果你有一些软件开发的背景,一定听过java虚拟机.通俗的解释java虚拟机的就是: 我们写的java代码 ...

  3. 深入了解以太坊虚拟机

    本文由币乎社区(bihu.com)内容支持计划赞助. 译者说,深入了解以太坊虚拟机是一个系列的文章,一共5篇! 本文是第1篇,主要介绍的是以太坊虚拟机汇编代码基础.后续的4篇译文链接在本文的结尾处. ...

  4. 对于以太坊虚拟机 (EVM)及其相关知识的讲解

    以太坊虚拟机(EVM) EVM是智能合约的运行环境 作为区块验证协议的一部分,参与网络的每个节点都会运行EVM,审查节点会检查验证正在验证的区块中列出的交易,并运行EVM中交易触发的代码 EVM是沙盒 ...

  5. 深度剖析以太坊虚拟机(EVM)的未来:Ewasm

    以太坊是具有内置图灵完备编程语言的区块链.任何人都可以使用以太坊智能合约来创建去中心化应用程序."以太坊虚拟机(EVM)是以太坊处理智能合约部署和执行的一部分"(Antonopou ...

  6. 从比特币脚本引擎到以太坊虚拟机

    这个系列是目标受众是区块链开发者和有其他开发经验的CS专业学生 面对媒体对区块链相关技术的解读和吹捧,许多人一时不知所措.投资人.大公司都在FOMO(fear of missing out)的心理驱动 ...

  7. 写给开发者——从比特币脚本引擎到以太坊虚拟机

    这个系列的目标受众是区块链开发者和CS专业同学 面对媒体对区块链相关技术的解读和吹捧,许多人一时不知所措.投资人.大公司都在FOMO(fear of missing out)的心理驱动下,争相宣布al ...

  8. 以太坊源码深入分析(9)-- 以太坊通过EVM执行交易过程分析

    上一节分析了同步一个新的区块准备插入本地BlockChain之前需要重放并执行新区块的所有交易,并产生交易收据和日志.以太坊是如何执行这些交易呢?这就要请出大名鼎鼎的以太坊虚拟机. 以太坊虚拟机在执行 ...

  9. solidity智能合约[37]-以太坊虚拟机数据存储

    EVM 当调用solidity函数时,都会在以太坊虚拟机当中来执行.因此了解以太坊虚拟机的细节,了解其数据的存储机制变得尤为重要. 以太坊虚拟机中的空间分为3大部分.分别为storage.stack与 ...

  10. 深入了解以太坊虚拟机第4部分——ABI编码外部方法调用的方式

    本文由币乎社区(bihu.com)内容支持计划赞助. 在本系列的上一篇文章中我们看到了Solidity是如何在EVM存储器中表示复杂数据结构的.但是如果无法交互,数据就是没有意义的.智能合约就是数据和 ...

最新文章

  1. Machine Learning - Andrew Ng on Coursera (Week 5)
  2. oracle 重建em失败,11gr2 EM重建出现问题,求高人指点
  3. 把MySQL中的各种锁及其原理都画出来
  4. 如何双启动Linux和Windows
  5. ADMM算法求解二次项目标函数+l1正则项问题
  6. maven详解_本地仓库+远程仓库_体现maven用途
  7. FCM算法研究(一)
  8. 向死而生的微信视频号,逆风翻盘的2020
  9. 一个人是否靠谱,闭环很重要
  10. defy+me525+android2.3.6官方镜像包,摩托罗拉 DEFY+ 2.3.7 ROM刷机包MIUI版
  11. python按什么键停止运行_python如何停止运行
  12. 【10大基础算法】线性查找算法-NO5
  13. HDMI接口之HPD(热拔插)
  14. OpenCV开发笔记(七十一):红胖子8分钟带你深入级联分类器训练
  15. CSDN的密码修改流程比之前好多了
  16. 机器学习讲堂 ACF 聚合通道检测
  17. 数组排序sort()。升序还是降序
  18. python爬虫爬取的数据与浏览器获取的数据不一样 爬虫爬取到的数据一直不变
  19. pythonturtle是标准库_Python import载入turtle库详解
  20. 这群程序员中的「广告狂人」,把抖音广告做成了AR游戏

热门文章

  1. JAVAWeb开发之Servlet-19.Filter
  2. Delphi XE7下如何创建一个Android模拟器调试?
  3. 数据库操作之——约束
  4. Android调用默认浏览器打开指定url
  5. sqlserver2008的数据库自动备份方法(转载)
  6. 不足百行代码 实体数组转DataTable通用类
  7. 孙鑫VC学习笔记:第十四讲 (二) 网络编程
  8. python实现画板功能并操作数据库
  9. chapter 9 series
  10. 【Python】@ 操作符