其他分享
首页 > 其他分享> > EVM、Wasm虚拟机原理和设计思路

EVM、Wasm虚拟机原理和设计思路

作者:互联网

EVM和WASM(EOS虚拟机)基本原理

EVM是以太坊图灵完备的虚拟机(Ethereum Virtual Machine), 简称EVM

比特币的程序非常简单,由解锁脚本和锁定脚本构成。以太坊有智能合约,有图灵完备的虚拟机EVM,但是指令也相对简单,且自成一套。这两种程序本质上都是脚本程序,即由程序翻译指令并执行,而不是由本地机器CPU读取指令并执行,效率不高。但选择解释性语言有它的合理性,就是他的高度兼容性,它对智能合约的执行设备(矿机)没有限制。

WASM是EOS的智能合约标准Web Assembly,简称WASM

WASM

它是谷歌、苹果、微软三大竞争公司同时支持的一种中间代码(字节码), 是浏览器都支持的一种代码。

WASM

基于EOS.IO的区块链使用Web Assembly(WASM)执行开发者提供的应用代码。WASM是一个已崭露头角的web标准,受到Google, Microsoft, Apple及其他大公司的广泛支持。目前为止,最成熟的用于构建应用及WASM代码编译的工具链是clang/LLVM及其C/C++编译器。希望C++ 将成为开发高性能及安全智能合约的最佳语言

LLVM的命名最早来源于底层语言虚拟机(Low Level Virtual Machine)的缩写。它是一个用于建立编译器的基础框架,以C++编写。创建此工程的目的是对于任意的编程语言,利用该基础框架,构建一个包括编译时、链接时、执行时等的语言执行器。目前官方的LLVM只支持处理C/C++,Objective-C三种语言,当然也有一些非官方的扩展,使其支持ActionScript、Ada、D语言、Fortran、GLSL、Haskell、Java bytecode、Objective-C、Python、Ruby、Rust、Scala以及C#。

以太坊支持WASM吗?

EWASM

eWASM将允许以太坊开发人员能够使用多种编程语言来编写代码——而不仅仅目前所使用的以太坊专用的语言Solidity——据说eWASM还会带来大量的性能增强。

Ewasm (Web Assembly for Ethereum) 并不是一个智能合约语言,而是一个编译器目标,它将允许以太坊程序员用其他语言编程(如Rust,C ++,也许某一天是智能合约特定语言,如 Simplicity),并编译成以太坊风格的 WebAssembly。Ewasm 是 WebAssembly 的一个更安全的子集,它是 Web 平台相对较新的低级编译目标。方便的是,wasm(以及 ewasm)模块可以在任何 JavaScript 项目中使用。对于大多数区块链代码,通常超过 75% 的代码根本不在智能合约中 — 它在 JavaScript 中必须与智能合约进行通信。Ewasm 和 JavaScript 共享绑定和模块支持的共同基础。

 实现思路

Cosmos-SDK实现的Ethereum 的智能合约链,底层提供了EVM、Wasm两种虚拟机来运行智能合约。开发者可以使用传统的Solidity语言编写合约、或其它可以编译为WebAssembly高级语言(如:Rust/C++/AssemblyScript)编写合约,将编译后的合约字节码上传至 Chain上运行;并且两种类型的字节码合约之间可以互相进行调用。

基于上述这种开发理念,引申出一个问题:如何在Wasm上实现实现Ethereum . 对此初步提供了三种方案:

  1. 将Solidity合约编译为Wasm字节码

    • 使用类似于SOLL的方案,将Solidity合约编译为等价的WebAssembly字节码,底层提供Wasm虚拟机来运行合约。
  2. 在Wasm上提供系统合约,来运行Solidity字节码的合约

    • 在Wasm虚拟机上构建EVM字节码器,来运行编译后的Solidity字节码。
  3. 提供两种虚拟机的实现,不同的字节码合约在不同的虚拟机上运行

    • 使用两种虚拟机,分别运行EVM字节码合约和WebAseembly字节码合约,同时在Wasm虚拟机上通过Host函数,提供Ethereum 的实现,以便做到两种虚拟机合约之间的互相调用。

基于技术实现难度、运行性能等方面的考虑,采用了第三种方案。下面将详细介绍该方案的实现思路

Wasm虚拟机实现Ethereum 

在Wasm虚拟机中运行合约时,除了虚拟机自身之外,还需要依赖一些外部Host函数的支持,通过在Host中,提供EEI实现,以便在Wasm虚拟机中提供 Ethereum 

Chain提供了便于合约导入的SDK,以便在用高级语言(Rust/AssemblyScript/)写Wasm合约时,可以调用这些外部Host函数;将合约编译为Wasm字节码时,SDK中声明的所有export函数,都将由Chain客户端提供实现。

示例如下:

在smart-sdk-as项目中,提供了as项目使用的sdk.

// cesi.ts
export declare function getCallDataSize(): u32
export declare function callDataCopy(bufOut: Uint8Array, offset: u32, length: u32): void
export declare function getCodeSize(): u32

// lib_contract.ts
export namespace contract {
    export function getCodeSize(): u32 {
    return cesi.getCodeSize();
  }
  ....
}

// index_test.ts
export function testCoreAPI(): void {
    var codeSize = contract.getCodeSize(); 
}  

在smart chain链的客户端中,实现了这些Host函数

//export cesiGetCallDataSize
func cesiGetCallDataSize(context unsafe.Pointer) int32 {
    return convertContext(context).getCallDataSize()
}
//export cesiCallDataCopy
func cesiCallDataCopy(context unsafe.Pointer, resultOffset int32, dataOffset, length int32) {
    convertContext(context).callDataCopy(resultOffset, dataOffset, length)
}
//export cesiGetCodeSize
func cesiGetCodeSize(context unsafe.Pointer) int32 {
    return convertContext(context).getCodeSize()
}

将用高级语言(Rust/AssemblyScript)编写的Wasm合约编译为字节码(WebAssembly ByteCode),上传至链,创建Wasm虚拟机后,进行运行,并由Host函数提供EEI语义的支持.


 +--------------+               +---------------+               +---------------+
 |              |   create VM   |               |       run     |               |
 |  Wasm        | ------------> |      VM       | ------------->|   host func   |
 |  ByteCode    |               |               |               |               | 
 +--------------+               +---------------+               +---------------+

EVM虚拟机集成

在chain中,使用了[ethereum/evmone]作为以太坊虚拟机的实现,该项目内部实现了以太坊的所有指令;同时,提供了一个接口HostContext,负责与区块链进行数据交互;在smart chain 客户端中通过实现该接口,为evm虚拟机提供数据支持;

通过调用evmc提供的接口,从evmone的动态库中创建evm虚拟机;然后通过虚拟机提供的接口Execute,传入合约code,用户输入等一系列参数信息,运行合约。

 +--------------+               +---------------+               +---------------+
 |              |   params      | contract code |       run     |               |
 |  Load EMV    | ------------> |     input     | ------------->|  HostContext  |
 |              |               |     ...       |               |               | 
 +--------------+               +---------------+               +---------------+

虚拟机间的兼容

为了使smart chain在执行合约时,不用关注虚拟机的实现细节,增加了中间层,来兼容两种虚拟机的创建、执行;

  1. 在合约的元信息中增加标识,来表明合约字节码类型;
  2. 依据标识来创建指定类型的虚拟机;
  3. 通过引入中间层接口ContractExecutor,来屏蔽smart chain 在链上执行合约时,对两种虚拟机实现细节的关注.
  4. 在虚拟机执行时,通过使用ABI编码后的参数,来做到虚拟机之间的互相调用

type ContractInfo struct {
        ContractType uint8
}

func CreateVM(cfg Config) (ContractExecutor, error) {
    switch cfg.Flag {
    case EVM:
      return evm.NewVmEvmc()
    case Wasm:
      return wasm.NewWasmer(cfg.Ctx, cfg.Keeper, cfg.ContractAddr, cfg.Code, cfg.CodeHash, cfg.Ims)
    }
    return nil, types.ErrVMUnsupported
}

type ContractExecutor interface {
    Execute(ctx interface{}, rev evm.Revision,
      kind evm.CallKind, static bool, depth int, gas int64,
      destination sdk.AccAddress, sender sdk.AccAddress, input []byte, value int64,
      code []byte, create2Salt []byte) (output []byte, gasLeft int64, err error)
}

 +--------------+               +---------------+               +---------------+
 |              |  create vm    |               |    run        |               |
 |  Contract    | ------------> |   Contract    | ------------->|    Execute    |
 |  Info        |               |   Executor    |               |               | 
 +--------------+               +---------------+               +---------------+

总结

至此,我们完整介绍了方案三(提供两种虚拟机)的实现思路;通过在链上支持两种虚拟机,来使以太坊APP的开发者可以几乎无成本的进行生态迁移。



 

标签:EVM,虚拟机,+---------------+,Wasm,合约,字节
来源: https://blog.csdn.net/shangsongwww/article/details/92794878