以太坊是一个内置图灵完备编程语言的区块链平台,任何人都可以通过以太坊智能合约创建去中心化应用程序。
“以太坊虚拟机(EVM)是处理智能合约部署和执行的核心组件”(Antonopoulos and Wood,2018)。
EVM 采用基于堆栈的架构。部署智能合约前,所有高级智能合约代码需首先编译为机器可读的字节码。EVM 通过后进先出(LIFO)机制处理字节码中的操作码序列,其运行逻辑类似于 Java 虚拟机(JVM)——每条指令以单字节操作码起始,后接参数(若有),数值按大端序排列(Scott,2009)。
本文旨在解析以太坊基于堆栈的 EVM 内部运行机制。了解这些基础知识后,我们将进一步探讨以太坊如何通过过渡到 WebAssembly(Wasm)实现更广阔的发展前景。
什么是 WebAssembly(Wasm)?
WebAssembly(简称 Wasm)是一种可在现代浏览器中运行的新型代码格式,具有卓越的性能和跨平台能力。Wasm 被设计为 C、C++ 和 Rust 等低级语言的编译目标(MDN Web Docs,2019)。
以太坊与 WebAssembly:Ewasm 的诞生
以太坊 WebAssembly(Ewasm)是基于标准 Wasm 虚拟机构建的确定性智能合约执行引擎。作为替代 EVM 的主要候选方案,Ewasm 已被纳入以太坊 2.0 “Serenity” 的路线图,甚至有提案建议将其应用于以太坊主网(ewasm,2019)。
当前 EVM 架构是限制其性能的主要因素之一(GitHub EIP48,2019)。例如,虽然 256 位字长有助于原生哈希和椭圆曲线计算(Antonopoulos and Wood,2018),但也导致从 EVM 操作码到硬件指令的转换过程异常复杂。采用更接近硬件架构的设计将显著提升以太坊性能(GitHub EIP48,2019)。
Ewasm 的另一设计目标是支持多种智能合约开发语言和工具,包括 LLVM、C、C++、Rust 和 JavaScript。理论上,任何可编译为 Wasm 的语言都可编写智能合约,只需实现 Ewasm 合约接口(ECI)和 以太坊环境接口(EEI)(ewasm,2019)。
智能合约基础
智能合约在以太坊执行环境中充当“自治代理”,当被消息或交易触发时,执行预定义的代码段,并管理自身的以太币余额及持久化键值存储(Buterin,2013)。
诸如 Solidity、Vyper 和 Lity 等高级智能合约语言均配备独立编译器,可将源代码编译为多种输出格式,包括应用程序二进制接口(ABI)、字节码流和操作码。
智能合约编译流程
在本地安装编译器前,建议先使用基于 Web 的编译环境例如 BUIDL,以节省时间。
以 Simple Storage 合约为例,使用在线编译器可立即生成 ABI 和字节码。如需通过命令行完成相同操作,可参考文末附录 A。
字节码结构解析
以字节码的前几条指令为例:
60 80 60 40 5234
根据以太坊黄皮书,操作码 0x60 对应 PUSH1 指令,其作用是将一个字节的数据压入堆栈。例如:
- PUSH1 0x80:将 0x80 压入堆栈
- PUSH1 0x40:将 0x40 压入堆栈
随后,操作码 0x52 对应 MSTORE 指令。MSTORE 是内存操作指令,用于将一个 256 位字存入内存,其执行过程会消耗堆栈顶部的两个元素:第一个元素指定存储地址(如 0x40),第二个元素为待存储数据(如 0x80)。
EVM 的字长为 256 位(Antonopoulos and Wood,2018),此处的“字”可能代表账户地址或其他数据。
接下来,操作码 0x34 对应 CALLVALUE 指令,该指令从执行环境中获取交易转账的以太币数额,并将其压入堆栈。
部署字节码与运行时字节码
需注意区分部署字节码和运行时字节码:
- 部署字节码:包含仅在部署阶段执行的指令
- 运行时字节码:在合约调用阶段执行的指令,是部署字节码的子集
运行时字节码中的每个函数可通过 4 字节的函数签名识别。例如函数 set(uint256) 的签名可通过以下方式计算:
// web3.js 示例
var selectorHash = web3.sha3("set(uint256)").substring(0, 10);
// 返回 0x60fe47b1该签名可在字节码中直接定位。
Ewasm 实施方案
从高级智能合约代码到 Ewasm 的编译路径多样且复杂。Second State 团队开发的 Soll 编译器实现了从 Solidity 到 Ewasm 的转换。
在 Crosslink(台北)和 Devcon5(大阪)等重要会议上,Second State 展示了其在 Ewasm 领域的进展:
- Crosslink 2019:Second State 开发者 Hung-Ying Tai 因 Soll 项目获得以太基金会奖金
- Devcon5:团队演示了在 Ewasm 测试网部署 ERC20 合约的全过程
与 Solidity 团队 Christian Reitwiessner 的讨论进一步明确了未来发展方向:在完成 Solidity→LLVM→Ewasm 原型后,重点转向实现 Yul→LLVM→Ewasm 的编译路径。
Yul:以太坊中间语言
Yul 是以太坊特定的中间语言,未来将获得 Solidity 和 Vyper 编译器的全面支持。其设计兼容 EVM 1.0、EVM 1.5 和 Ewasm,核心特性包括函数、区块、变量、字面量、循环和条件语句等(Solidity-Yul,2019)。
“Yul 后端负责生成特定字节码,保留evm_和ewasm_前缀区分不同目标平台”(Solidity-Yul,2019)。
从 Solidity 到 Ewasm 的编译路径
编译 Solidity 为 Yul
使用 Solidity 编译器的 --ir 选项可生成 Yul 中间表示(IR):
solc --ir contract.sol编译 Yul 为 Ewasm
将 Yul 代码编译为 Ewasm 需完成以下步骤:
- 将 256 位变量拆分为 4 个 64 位变量
- 处理字节序转换(EVM 为大端序,Wasm 为小端序)
- 通过函数库实现每个 EVM 操作码的 Ewasm 等效功能
Christian Reitwiessner 在 Devcon5 演示的 代码示例 展示了 MSTORE 函数的 Ewasm 实现:
function mstore(x1, x2, x3, x4, y1, y2, y3, y4) {
let pos := u256_to_i32ptr(x1, x2, x3, x4)
i64.store(pos, endian_swap(x1))
i64.store(i64.add(pos, 8), endian_swap(x2))
i64.store(i64.add(pos, 16), endian_swap(x3))
i64.store(i64.add(pos, 24), endian_swap(x4))
}字节序处理
字节序转换至关重要:EVM 采用大端序,而 Wasm 规范要求小端序(webassembly.github.io,2019)。
未来发展与挑战
Ewasm 的实施仍面临多个待解决的问题:
- 与 EVM 1.x 的交互:Ewasm 如何访问合约存储、账户余额等状态数据仍在讨论中
- 确定性行为:需通过前哨合约拒绝具有非确定性特征的 Wasm 合约
- Gas 计量:正在研究基于静态分析的自动上限估计方案
常见问题
什么是 Ewasm?
Ewasm 是以太坊基于 WebAssembly 虚拟机构建的智能合约执行引擎,旨在提升性能并支持多语言开发,是以太坊 2.0 的重要组成部分。
Ewasm 如何提升以太坊性能?
Ewasm 采用更接近硬件架构的设计,简化指令转换过程,同时支持更多编程语言和优化工具链,显著提高执行效率和开发灵活性。
当前哪些语言支持 Ewasm 合约开发?
理论上任何可编译为 Wasm 的语言均可使用,包括 C、C++、Rust 和 JavaScript。通过实现 ECI 和 EEI 接口,可实现与以太坊环境的交互。
字节序转换为何重要?
因为 EVM 使用大端序而 Wasm 规范要求小端序,正确转换字节序是确保数据存储和检索正确的关键。
Ewasm 会完全取代 EVM 吗?
Ewasm 是目前替代 EVM 的主要候选方案,但具体实施路径和兼容性方案仍在讨论和完善中。
如何参与 Ewasm 开发?
开发者可通过贡献代码、测试网络、参加技术会议等方式参与生态建设,关注官方文档和 GitHub 仓库获取最新信息。
结论
智能合约编译到 Ewasm 的路径多样,Yul 中间语言的使用将为现有编译器提供统一目标,并为 LLVM→Ewasm 编译器提供入口。该路径不仅适用于 Solidity 和 Vyper,还为 Rust 等语言进入以太坊生态打开大门。
“使用 Yul 可重用大多数优化器组件,是重大进步”(Reitwiessner,2019)。
随着技术发展,Ewasm 有望为以太坊带来更高性能、更强兼容性和更丰富的开发环境。
附录 A:命令行编译示例
使用 Lity 编译器编译 Simple Storage 合约:
A.1 获取部署字节码
lityc --bin simple_storage.solA.2 获取运行时字节码
lityc --bin-runtime simple_storage.solA.3 获取操作码
lityc --opcodes simple_storage.solA.4 获取 ABI
lityc --abi simple_storage.sol附录 B:待讨论议题
- 与 EVM 1.x 状态交互:Ewasm 如何访问账户信息、区块数据等状态
- 确定性保证:通过前哨合约检测和拒绝非确定性代码
- Gas 计量机制:基于静态分析的自动上限估计方案
参考文献
- Antonopoulos, A. and Wood, G. (2018). 《精通以太坊》
- Ethereum Foundation. (2019). 以太坊 1.x 文档
- WebAssembly 官方规范
- Solidity 文档(Yul 部分)
- 各类会议演讲和技术报告