原文标题:《解构 ETH2.0:EVM 和 eWASM》
原文来源:ETH中文网
以太坊 2.0 之 eWASM
eWASM 是以太坊迈向 2.0 时代的又一创新之举。主流看法是,eWASM 能够促进网络的速度、可扩展性和灵活性,也使得开发者能够基于以太坊 2.0 的协议构建更为复杂的智能合约。
除此之外,我们之前的文章还对 Eth 2.0 的许多不同方面进行了解释,如 Staking、Sharding、以太坊 Layer-2、zk- snark 等。在探讨 eWASM 之前,我们再过一遍以太坊 2.0 的基本路线。
什么是以太坊 2.0?
以太坊 2.0 包含一系列升级,将对协议进行颠覆性的改进,扩容以太坊网络,使其更加高效。其中的升级包括:使用 Casper 协议的 Proof of Stake (权益证明) 机制、分片、Raiden (雷电网络)、Plasma 以及 Rollups 等等。这些升级将会在以太坊不同的阶段中实现,以确保合理的部署和执行。
– 阶段 0:启动信标链,转向 PoS 权益证明机制
– 阶段 1:加入分片
– 阶段 2:使用以太坊 2.0 eWASM 替代现有的以太坊虚拟机 (EVM)
本文将主要探讨阶段 2,如果读者对以太坊 2.0 有一些了解,那么应该知道从 EVM 到 eWASM 的转变是非常宏大的工作。在我们进入 eWASM 之前,先来看看 EVM 到底是什么。
以太坊虚拟机是什么?
每条去中心化的区块链都需要一个虚拟机来处理并执行操作。比特币的虚拟机相对简单,因为它只需要处理交易。然而,由于以太坊支持图灵完备的智能合约,其复杂度也就更高。因此,我们需要思考另一个重要问题。
既然智能合约要满足不可篡改性,并且即使历经多个节点也能无损运行,那么以太坊虚拟机 (EVM) 需要拥有哪些主要特性?
– 确定性
– 可终止性
– 独立性
▼确定性
如果针对相同的一组输入,无论其执行了多少次代码,程序都给出相同的输出,那么就可以说是该程序具有确定性。确定性函数的一个完美示例就是数学运算。例如,假定所有数字都以 10 为底,则无论重复运算多少次,1 + 4 始终等于 5。
DApps 往往需要同时处理大量金额,所以用户需要清楚知道代码在每个执行阶段如何响应。
▼可终止性
我们需要谨记一点,以太坊智能合约是图灵完备的。如果有充足的时间和资源,那么理论上来说智能合约可以解决任何问题。然而,我们无法判断合约是否能在给定的时间限制内完成所有操作。这就是为什么智能合约需要有终止机制。以太坊智能合约借助「gas」来定义其使用期限。当合约达到 gas 上限,则无法继续进行操作。
▼独立性
最后,智能合约应该在一个完全独立的环境中运行。如果合约发生什么意外情况 (例如被攻击或是出现漏洞),那么其影响不应该波及到其他底层协议。
要满足以上三个特性,有两种系统可以供智能合约使用——虚拟机和 Docker 容器。由于 Docker 的合约默认设计不具备确定性,以太坊决定采用虚拟机。
以太坊虚拟机:如何运作?
当我们说到「虚拟机」(virtual machine) 的时候,到底是什么意思?
传统的操作系统 (Windows/iOS) 一次只需要在一个系统中运行。而虚拟机 (VM) 是基于本地操作系统所创建更高级抽象,可用于复制物理机的功能。
虚拟机使得用户能够在不同的硬件架构和操作系统中同时运行同一平台。这就是为什么虚拟机非常适合像以太坊这样的去中心化网络的原因。以太坊的主要目标是成为一台全球超级计算机,使得开发者能够借助其计算资源构建自己的智能合约和去中心化应用程序。以太坊虚拟机 (EVM) 的功能就类似世界计算机,遍布全球的节点都能进行访问。
▼堆栈和状态机
相较于普通的虚拟机,EVM 还具备两个额外特性。首先,作为状态机的 EVM 可以读取输入然后相应地更新其状态。其次,EVM 还是堆栈式,其内存结构能够以堆栈形式进行组织和访问。
如果读者熟悉数据结构,那么应该对堆栈并不陌生。堆栈是线性数据结构,其中的操作是通过 LIFO (后进先出) 来执行的。
下面举个例子:
在上图的堆栈中,第一条插入的数据是 Orange,最后一条数据是 Apple。根据 LIFO 的逻辑,我们取出的第一条数据应该是 Apple,最后才是 Orange。
现在我们再来看看堆栈操作:Push 和 Pop。
Push:向堆栈中加入数据
Pop:使用 LIFO 逻辑将数据从堆栈中移除
▼EVM 中的堆栈操作
在堆栈式虚拟机中,操作执行如下:
– 首先移除数据和操作数
– 相应操作被执行
– 执行结果被加入堆栈
参考以下图表:
– 我们首先移除两个数字:20 和 7
– 将这两个数字相加,我们得到 27
– 最后,结果被重新加入堆栈
EVM 堆栈式系统的优势
– 堆栈结构可确保 EVM 不需要获取操作数的确切地址。堆栈结构会始终且必然将 VM 指向下一个操作数。降低大量操作开销的同时提高了整体效率。
– EVM 拥有:世界状态 (world state)、机器状态 (machine state) 和虚拟 ROM。世界状态将所有帐户存储在网络中,机器状态包括程序计数器、可用 gas、堆栈和内存等数据。最后,虚拟 ROM 读取名为「EVM 字节码」的机器级代码。这是只有 EVM 才能理解的独特语言。
▼EVM – 读取字节码
编程语言分为高级和低级语言。低级语言 (如字节码) 能够轻松被机器读取,但人类却难以理解。这也是为什么大多数编程语言都是高级形式的原因。那么,在智能合约中程序是如何运作的呢?
– Solidity/Vyper 语言的智能合约被编译为字节码,使用到的编译器叫做「solc」
– 字节码由网络读取并处理
– 字节码是 Solidity 操作码的二进制形式。从 EVM 转向 eWASM 的过程中,编译器是非常重要的一个部分,因为 EVM 无法理解除了字节码之外的任何语言。
– 每个操作码在规范中都被赋予了易于理解的名称,并由数字代码表示。例如,数字 0X01 代表 ADD 操作码。
▼EVM 的功能性
– EVM 是以太坊网络中的去中心化处理单元。每笔交易、交互和智能合约执行只能通过 EVM 进行。
– 负责所有不同的数据结构,包括指令、操作数以及已经处理的数据。
– EVM 通过指令分配器获取并执行指令,对操作码进行解码。
– EVM 还会跟踪多个网络组件,例如世界状态、存储状态以及区块信息。
– 在以太坊网络中为智能合约创建一个运行时环境。该环境包含需要用以执行具体交易的信息,例如 gas 价格(最新 gas 价格)、代码大小、Caller (交易接收方地址) 以及 Origin (交易发送方地址)。
▼EVM 的缺点
虽然 EVM 具备许多优势,但也存在四个主要问题,导致网络的整体吞吐量受限:
– 由于 EVM 需要处理大量各种各样的操作,其速度便不尽人意。EVM 的操作码规范没有进行更新,也没有针对不同的硬件平台做出优化。
– 第一点提到由于 EVM 需要处理大量不同操作,就会容易成为运转瓶颈。其结果就是严重损害整个网络的效率。
– 自从发布初始规范以来,EVM 并没有进行太多优化,导致编写合约所需的工具和语言极大受限。
假如底层工作环境本身存在巨大缺陷,那么引入一系列新颖机制 (分片/rollups/Casper) 的意义何在?以太坊之所以寻求从 EVM 转向使用 eWASM,也出于对以上缺陷的衡量。
那么什么是 eWASM 呢?在此之前,我们需要先理解什么是 WebAssembly。
什么是 WebAssembly (WASM)?
WebAssembly 最近获得了许多关注。WebAssembly 是由 World Wide Web Consortium (W3C, 万维网联盟) 创造并定义的新代码类型,能够在现代浏览器中高效执行。
WebAssembly 凭什么独树一帜?
由于 WASM 具备基于堆栈的低级二进制格式,且在默认情况下很小,从而可以实现快速加载和执行。浏览器下载 WASM 代码后,便可以快速将其转换为任何计算机的程序集。
WebAssembly 的优势
受多个 JavaScript 引擎和运行时环境的支持,可以在大多数现代浏览器中执行。
Go/Rust/C/C++语言可以直接编译为 WASM
能够快速适应所有机器级架构,具备极高性能
附带与大多数现代硬件架构兼容的指令集
在大多数平台上趋近于本地运行速度
以太坊 2.0 eWASM
读到这里大家可能已经发现了,eWASM (Ethereum WebAssembly) 就是以太坊 2.0 版的 WebAssembly。
根据相关团队的说法:
eWASM = WASM – 非确定性 (浮点) + 计量 + EEI 路径 (用以与以太坊交互)
eWASM 团队已经给出其具体的设计目标:
构建 EVM 转译器,并且以 eWASM 合约形式添加计量注入器
发布明确详细的规范:以太坊接口、eWASM 合约语义以及细节
为 solc 编译器构建一个 eWASM 后端
提供 C 语言和 Rust 语言的相应指令和库,以支持智能合约编写
诸如 EOS、Tron 以及 Cardano 等项目已经或者准备采用 WASM,实现 eWASM 之后,以太坊也将成为其中之一。
eWASM vs EVM
EVM 的主要设计目标就是要保证正确性,即使可能会因此牺牲一定的效率。以太坊开发者 Lane Rettig 认为 EVM 是基于理论设计而非实用设计,因此可能无法完美支持现实应用。EVM 中的每个节点都必须完整正确地运行 EVM,而 WASM 是为现实应用而生的,能够翻译轻松实际的代码逻辑,因此在效率和速度上更具优势。
现在有了大概的认识,我将进一步对比 eWASM 和 EVM。
▼eWASM vs EVM #1: 速度
简单来说,EVM 可以看作是「万精油」,但没有达到理想效果。就拿代码编译来说吧。
EVM 经常无法有效编译大量代码。而浏览器的本地 JS 引擎通常需要大量工作来为某些操作的执行匹配最佳路径,而这对 EVM 的整体吞吐量来说会产生巨大影响。此外,EVM 只能处理 256 位的字节码,因此小于 256 位的字节码必须转换为 256 位格式。
EVM 的设计极大限制了以太坊的速度和可扩展性,使其每秒最多只能处理 25 笔交易。而这对于现实世界和现实需求来说是非常不切实际的。
eWASM 可以直接转换为编译代码,从而提高加载速度,并且大幅提升每个区块能够处理的交易量。除此之外,有了分片和 layer2 解决方案的加持,以太坊 2.0 的速度会显著提升。
▼eWASM vs EVM #2: 预编译
eWASM 还能消除以太坊对预编译的依赖。预编译是 EVM 字节码的特殊位,好处在于能够节省 gas 成本,进行高效的密码运算。大多数情况下,如果不进行预编译,那么几乎不可能将创建合约所需的 gas 控制在上限范围内。而 eWASM 的 gas 效率非常之高,以至于能够省去大部分甚至全部的预编译。
然而,预编译也有不足之处。引入新的预编译往往需要网络进行系统范围的硬分叉。根据历史经验,因为可能导致社区分裂,硬分叉多少具有争议性。
而这些意味着什么?
eWASM 能够帮助开发者又快又省地创建智能合约,并且没有硬分叉的顾虑。
▼eWASM vs EVM #3: 灵活性
最后,相较于标准的 EVM,eWASM 最显著的优势就是代码灵活性。要编写智能合约,以太坊开发者必须特地学习 Solidity 语言,而这就成为了开发者的知识瓶颈。
eWASM 能够与多种语言进行交互,并且拥有更为广泛的开发者工具集。eWASM 将支持 C/C++/Rust 语言。
eWASM 将获得所有主流 JavaScript 引擎的支持,例如:
– Microsoft 的 Chakra 引擎 (Microsoft Edge)
– Google 的 V8 engine (Node.js 及基于 Chromium 的浏览器)
– Mozilla 的 Spidermonkey 引擎 (Firefox 及 Thunderbird)
eWASM 还将获得以下非浏览器实现的支持:
– ml-proto (OCaml 引用解释器)
– wasm-jit-prototype (使用 LLVM 后端的独立虚拟机)
– wabt (基于堆栈的解释器)
EWASM 还具有以下的开创性优势,这些优势是之前的 EVM 不可能拥有的:
– 对于以太坊轻客户端,得到浏览器支持会更简单,因为 eWASM 是根据 W3C 标准架构的
– eWASM 有更多编译器和更多种类的开发者工具
– 由于大量的项目已经在使用 eWASM 了,它已聚集了一个健康、多元的开发者社区
结语:eWASM 能否助 Eth 2.0 更上一层楼?
关于 eWASM,以太坊社区感到非常兴奋。然而,相关讨论也总是伴随着天花乱坠的说法,我们还需要听到不同的声音。一位资深以太坊开发者 Greg Colvin 就对 eWASM 智能合约持疑,其主要观点是:
– eWASM 无法消除预编译
– eWASM 过渡依赖编译器,可能会导致单点故障
其实绝大多数以太坊开发者都相信 eWASM 将对协议的整体性能和吞吐量造成巨大影响。
结果究竟会如何呢?让我们拭目以待吧!