菜单

以太坊虚拟机

相关源文件

以太坊虚拟机(EVM)是以太坊区块链上智能合约的执行环境。本页面重点介绍了 EVM 在 go-ethereum 客户端中的实现,并着重介绍了其架构、执行模型和关键组件。有关使用应用程序二进制接口(ABI)进行智能合约交互的信息,请参阅 ABI 和合约交互

概述

EVM 是一个基于堆栈的、隔离的运行时环境,智能合约代码在此环境中执行。它被设计为沙盒化的、完全确定性的,确保在无论底层硬件或操作系统如何的情况下,相同的输入始终产生相同的输出。

来源:[core/vm/evm.go], [core/vm/interpreter.go], [core/vm/instructions.go], [core/vm/jump_table.go]

架构

EVM 实现为一个基于堆栈的虚拟机,具有简单的指令集。它操作三个主要数据位置:

  1. 堆栈:在执行期间,临时值被压入或弹出堆栈。
  2. 内存:线性、字节可寻址、易失性内存,在每次交易之间重置。
  3. 存储:与每个合约账户关联的持久性键值存储。

来源:[core/vm/evm.go], [core/vm/interpreter.go], [core/state/statedb.go]

EVM 结构

核心 EVM 实现定义在 core/vm/evm.go82-128,其中 EVM 结构体包含执行上下文、状态数据库、解释器和其他设置。

解释器是实际执行合约代码的组件。

来源:[core/vm/evm.go], [core/vm/interpreter.go]

执行模型

合约执行

EVM 通过以下流程执行合约代码:

来源:core/vm/evm.go188-259 core/vm/interpreter.go156-322

指令处理

EVM 的核心是解释器中的指令处理循环。

来源:core/vm/interpreter.go226-315

Gas 机制

EVM 使用 Gas 来衡量计算资源。每个操作消耗一定量的 Gas,该 Gas 将从交易的 Gas 限额中扣除。

  • 操作既有固定成本,也有动态成本。
  • 内存扩展成本呈二次方增长。
  • 存储操作成本最高。
  • 对于某些操作(例如清除存储),Gas 会被退还。

Gas 表定义在 core/vm/gas_table.goparams/protocol_params.go

来源:[core/vm/gas_table.go], [params/protocol_params.go], core/vm/interpreter.go246-292

指令集

EVM 拥有丰富的指令集,分为几个类别:

类别描述示例
算术基本算术运算ADD, SUB, MUL, DIV
比较数值比较LT, GT, EQ, ISZERO
按位操作位运算AND, OR, XOR, NOT
内存内存操作MLOAD, MSTORE, MSTORE8
存储存储操作SLOAD, SLOAD
流量控制执行流程操作JUMP, JUMPI, JUMPDEST
环境类区块链信息访问TIMESTAMP, NUMBER, BALANCE
堆栈操作POP, PUSH1-PUSH32, DUP1-DUP16, SWAP1-SWAP16
日志记录事件日志LOG0, LOG1, LOG2, LOG3, LOG4
系统合约交互CALL, CALLCODE, DELEGATECALL, STATICCALL, CREATE, CREATE2, RETURN, REVERT

指令集会根据活动的硬分叉而有所不同,新的操作码通过以太坊改进提案(EIP)添加。

来源:[core/vm/instructions.go], [core/vm/jump_table.go], [core/vm/opcodes.go]

指令实现

每个操作码都实现为一个具有以下签名的函数:

例如,ADD 操作:

来源:core/vm/instructions.go30-34 core/vm/interpreter.go93-102

状态交互

EVM 通过 StateDB 接口与以太坊状态进行交互,该接口提供了以下方法:

  • 访问账户余额、nonce 和代码。
  • 读写合约存储。
  • 创建和自毁合约。
  • 修改账户状态。

来源:[core/state/statedb.go], [core/vm/evm.go], [core/vm/instructions.go]

预编译合约

EVM 包含几个内置合约,称为预编译合约,它们提供了常用加密操作的高效实现。

地址姓名描述
0x01ECRECOVER从签名中恢复公钥。
0x02SHA256计算 SHA-256 哈希。
0x03RIPEMD160计算 RIPEMD-160 哈希。
0x04IDENTITY内存复制操作。
0x05MODEXP模幂运算。
0x06ECADD椭圆曲线加法。
0x07ECMUL椭圆曲线标量乘法。
0x08ECPAIRING椭圆曲线配对校验。
0x09BLAKE2FBLAKE2b F 压缩函数。
0x0aKZG POINT EVALUATIONEIP-4844(Cancun)的多项式承诺验证。

预编译合约实现于 core/vm/contracts.go,并根据活跃的硬分叉进行选择。

来源:core/vm/contracts.go45-116

跳转表和硬分叉版本控制

EVM 使用跳转表来定义不同以太坊硬分叉可用的操作码。

EVM 根据链规则选择合适的跳转表,以确保在不同的网络升级中行为一致。

来源:core/vm/jump_table.go50-65 core/vm/interpreter.go104-154

智能合约调用和创建

EVM 提供了几种合约交互方法:

  1. Call:执行合约的标准方法。
  2. CallCode:以调用者作为上下文执行合约代码。
  3. DelegateCall:以调用者的上下文执行合约代码,并将调用者设置为调用者的调用者。
  4. StaticCall:执行合约,但不允许状态修改。
  5. Create:创建一个新合约。
  6. Create2:以确定性地址创建一个新合约。

来源:core/vm/evm.go188-737

内存和堆栈管理

EVM 通过专用数据结构管理内存和堆栈。

内存

内存实现为一个简单的字节数组,可以根据需要进行扩展。

内存操作包括:

  • Set:在特定偏移量存储字节。
  • Get:从特定偏移量检索字节。
  • Resize:将内存扩展到特定大小。

堆栈实现为一个 256 位无符号整数数组。

堆栈操作包括:

  • push:将项添加到堆栈顶部。
  • pop:移除并返回堆栈顶部的项。
  • peek:返回堆栈顶部的项而不移除它。
  • swap:交换不同位置的项。
  • dup:复制特定位置的项。

来源:[core/vm/memory.go], [core/vm/stack.go]

结论

以太坊虚拟机是一个定义明确、确定性的执行环境,是以太坊智能合约执行的基础。其在 go-ethereum 中的实现提供了一个完整、经过 Gas 计量、基于堆栈的虚拟机,支持从基本算术到复杂的加密原语的各种操作。

EVM 的设计确保智能合约在所有以太坊节点上执行得完全相同,提供了全球去中心化计算机所需的确定性。通过与以太坊状态的交互,EVM 实现了以太坊区别于简单区块链系统的丰富、可编程的功能。