详解虚拟机EVM:以太坊运行的基石

 2023-09-11 22:25:56发布

以太坊虚拟机(Ethereum virtual machine,EVM)是一种介于代码与主机之间的虚拟机,是以太坊得以运行的基本保障。进一步来说,EVM是一个由所有运行着以太坊客户端的计算机共同维护的一个实体,并且规定了从一个区块计算得到下一个有效区块的规则。

EVM的运行原理

区别于比特币,以太坊不是一种分布式账本,而是一种分布式状态容器。从一个区块过渡到下一个区块,意味着状态的更新,包括账户的状态、链上数据的更新。而状态如何更新,则是由EVM根据合约的代码计算得到的。

EVM是基于栈的虚拟机,其所有的操作都是与操作数栈直接交互。当把智能合约编译为字节码后,EVM就会根据字节码来执行操作,包括从内存中取出变量到操作数栈、在操作数栈中对变量进行运算以及将变量再存储到内存中等一系列流程。

EVM的运行原理

EVM的运行原理

EVM的数据存储主要有两种:Memory和Storage。

  • Storage中的变量在合约执行完毕后会存储到以太坊链上
  • Memory中的变量只在EVM执行代码的过程中存在,并不会永久存储到链上

以太坊虚拟机的用处

以太坊致力成为“下一代智能合约和去中心化应用平台”,创始人 Vitalik 也将其构想为一个去中心化的“世界计算机”。

作为计算机,就需要有计算,存储,执行等功能。所以,以太坊在拥有比特币网络中基本的数据存储功能之外,还需要运行各种代码进行计算,由以太坊虚拟机(EVM)所编译和解释执行的软件或者应用就是“智能合约”。

当以太坊链上发生转账交易的时候,以太坊虚拟机(EVM)会进行以下一系列工作:

  1. 调取转账的数值,分析合约的指令。
  2. 计算Gas的消耗(手续费), 确保发出转账的地址有足够的Gas费。
  3. 执行合约,实现转账到对应的地址。

EVM对于以太坊的功能

便于测试

为了保证各种“智能合约”的顺利执行,我们需要给它们创建一个安全的运行环境,以太坊虚拟机就是一个代码的运行环境。

正如我们上文所说,在虚拟机里的各种操作不会影响主机一样,任何想要在以太坊虚拟机创建智能合约的开发者可以在虚拟机上测试各种应用而不占用主链资源也不受其他区块链的影响。

增加安全性

以太坊上承载着具有强大功能的各种应用,其逻辑也就更加复杂,开发者也越容易出现各种漏洞。而以太坊虚拟机是一个完全独立的沙盒,合约代码可对外完全隔离并在 EVM 内部运行。

不仅可以防止因为不法分子或者程序员的编程错误而影响整个主链,还可以防止运行智能合约的物理设备遭受攻击。

保障稳定性

由于以太坊虚拟机部署在以太坊网络的每个节点,整个以太坊网络的数据由众多节点共同维护和更新,这保持了整个区块链数据的一致性,这同样也使以太坊有极高的故障容错性,保证零停机。

EVM的核心要素

智能合约

智能合约是专门在EVM上运行的代码。智能合约是存储在以太坊上的、一旦部署则无法更改的代码片段。以太坊通过智能合约来定义、修改、存储状态,以实现去中心化的各种应用,而EVM充当的则是智能合约运行的载体,就像是高速公路与汽车的关系。

gas机制

EVM执行智能合约代码,需要耗费大量的计算机算力。因此,在EVM执行智能合约代码时,需要消耗一定的gas费,就像汽车在高速公路上驾驶需要缴纳通行费一样。

gas机制的存在,一方面可以用来激励来自世界各地的矿工加入并提供算力,以此实现以太坊的去中心化分布,另一方面也可以防止用户随意提交操作请求而造成以太坊主网拥堵,甚至防止恶意攻击而导致以太坊出现宕机的情形。

Solidity语言与Opcodes

以太坊上的智能合约通过Solidity语言进行编写,编译成Bytecode(字节码)后再由EVM执行。Bytecode中还包含Opcodes(操作代码),EVM中目前包含144个操作代码,可以执行不同的进程,因此EVM是图灵完备的,我们可以通过EVM完成几乎任何运算。正是通过Solidity语言和Opcodes,我们可以编写复杂的智能合约,并由EVM来实现合约中丰富的功能,为用户提供多种多样的去中心化应用。

EVM的典型特征

确定性

对于同一段代码,经由不同EVM执行之后输出的结果必然是相同的,这和代码的执行环境、执行次数无关。EVM的确定性保证了代码的可靠性,避免执行代码的过程中出现不可预知的后果,尤其是当用户在以太坊上进行大额交易时,用户需要EVM的这一特征来保障其利益。

隔离性

EVM像一个具有隔离性的沙盒,代码在其中运行,运行的过程不会对计算机的软/硬件产生潜在的危害,也不会对以太坊的底层协议产生影响。EVM的隔离性杜绝了黑客对运行EVM的机器进行攻击的可能性,也保护了以太坊的底层协议不被篡改,是以太坊安全运行的基本保障。

可终止性

EVM执行代码的过程是可以被中断的。如果用户运行了错误的代码,如一段陷入无限循环的代码,那么为了避免这样的代码无限制地占用算力资源,EVM通过gas机制赋予了代码执行过程的可终止性。用户在将代码传入EVM中执行时,需要预先设定gas的上限,当gas耗尽,代码便终止运行,并且回滚状态,不会在链上进行任何状态的更新。

EVM兼容性情况

随着以太坊主网的用户越来越多,其网络拥堵、gas费用高昂的缺点也逐渐暴露出来。受限于以太坊的早期设计,这些缺点并不能得到根本性的解决。

近年来涌现出一批gas费用低、网络快的公链以及为以太坊扩容的Layer2链,这些链宣称具有更优秀的底层设计,并且都属于智能合约链,可以打造各种各样的Dapp。

一方面,这些链承接了以太坊生态过剩的需求,另一方面,对以太坊的传统地位提出了挑战。作为一个以太坊的竞争对手链,到底要不要兼容以太坊的EVM?围绕这个分歧,这些链分为了两派:一派兼容EVM,一派不兼容EVM。

公链对EVM兼容

Layer1层面的公链层出不穷。脱离以太坊重新构建一个链上生态,虽然可以针对以太坊现存的缺点进行改进,但是从无到有建立一个完整的生态以及开发Dapp需要大量的人力资源投入。

开发人员储备不足成为制约新公链生态发展壮大的主要因素,一个生态不健全的公链短期内难以吸引到大批量原以太坊的用户。

一些公链采取了EVM兼容的策略,原先在以太坊上运行的Dapp只需要对源代码进行细微的修改,就可以完整地移植到EVM兼容的公链上。

这样一来,不仅大大节省了开发资源,还能为用户提供更好的使用体验,缓解从以太坊迁移到新的公链导致的不适感。

但是,兼容EVM也带来一些缺点。

在EVM的规则框架下,如何实现有效的创新而不至于同质化,是众多EVM兼容链面对的难题。非EVM兼容链,可以打破这些规则,从无到有开发一套新的规则,从根本上实现创新。

目前,对EVM进行兼容的主流公链达到了70%以上,如BSC、Avalanche、Fantom、Tron、Celo等。这些公链上的开发者不需要花费太大的学习成本就可以顺利地开发Dapp,或是将一些原本要部署到以太坊的应用部署在这些公链上以谋求更高的性能与更低的gas费用,进而改善用户的使用体验。

也有一些公链不支持EVM,而是开发了自己的虚拟机,如Sol、Terra等。虽然不兼容EVM,但是这些公链凭借其创新的设计理念与优秀的链上表现同样吸引了一批忠实的用户以及机构的青睐。

不过,EVM兼容和非EVM兼容并不是水火不容的,已经有一些非EVM兼容链也逐渐开始支持EVM,虽然这一改动可能会给代码带来非常大的复杂性。

Layer2对EVM兼容

Layer2作为以太坊扩容的解决方案,与以太坊完全互补,基本不存在竞争关系。所以Layer2的链都是EVM兼容的。不过,作为以太坊的“嫡系”,其EVM兼容性肯定要比其他Layer1的公链要更进一步。

因此,Layer2对EVM的兼容度分为两个等级:“EVM兼容”和“EVM等效”。

早期Layer2的解决方案采用的都是EVM兼容的方式,和Layer1公链的EVM兼容性类似,对以太坊Layer1上的智能合约进行一些调整,即可将其部署在Layer2的链上运行。

比如Optimism推出的Unipig,就是对Uniswap的代码进行了完全的重构,号称Layer2上的Uniswap。

EVM兼容性也存在一些局限性。开发者在一个EVM兼容的链上开发智能合约时,出现一些基于EVM的开发工具和框架不能使用的情况。

另外,对于原先布置在Layer1的智能合约,开发者还需要进行或多或少的调整,才能使智能合约能够顺利地运行在EVM兼容的区块链上。

EVM等效性致力于让开发者在开发Layer2上的智能合约时获得与在以太坊Layer1上开发智能合约时完全相同的体验。

这为Layer2的开发者带来了便利,并在EVM兼容的基础上进一步大大提升了开发效率、节省了开发成本。同时,EVM等效也显著降低了代码维护的成本。

推荐阅读