前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >链上兼容EVM、Wasm虚拟机的实现思路

链上兼容EVM、Wasm虚拟机的实现思路

作者头像
路之遥
发布2022-09-26 17:00:43
5230
发布2022-09-26 17:00:43
举报
文章被收录于专栏:luzhiyaoluzhiyao

概述

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

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

  1. 将Solidity合约编译为Wasm字节码
    • 使用类似于SOLL的方案,将Solidity合约编译为等价的WebAssembly字节码,底层提供Wasm虚拟机来运行合约。
  2. 在Wasm上提供系统合约,来运行Solidity字节码的合约
    • 在Wasm虚拟机上构建EVM字节码器,来运行编译后的Solidity字节码。
  3. 提供两种虚拟机的实现,不同的字节码合约在不同的虚拟机上运行
    • 使用两种虚拟机,分别运行EVM字节码合约和WebAseembly字节码合约,同时在Wasm虚拟机上通过Host函数,提供Ethereum Semantic的实现,以便做到两种虚拟机合约之间的互相调用。

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

Wasm虚拟机实现Ethereum Semantic

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

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

示例如下:

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

代码语言:javascript
复制
// 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函数

代码语言:javascript
复制
//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语义的支持.

代码语言:javascript
复制
 +--------------+               +---------------+               +---------------+
 |              |   create VM   |               |       run     |               |
 |  Wasm        | ------------> |      VM       | ------------->|   host func   |
 |  ByteCode    |               |               |               |               | 
 +--------------+               +---------------+               +---------------+

EVM虚拟机集成

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

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

代码语言:javascript
复制
 +--------------+               +---------------+               +---------------+
 |              |   params      | contract code |       run     |               |
 |  Load EMV    | ------------> |     input     | ------------->|  HostContext  |
 |              |               |     ...       |               |               | 
 +--------------+               +---------------+               +---------------+

虚拟机间的兼容

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

  1. 在合约的元信息中增加标识,来表明合约字节码类型;
  2. 依据标识来创建指定类型的虚拟机;
  3. 通过引入中间层接口ContractExecutor,来屏蔽smart chain 在链上执行合约时,对两种虚拟机实现细节的关注.
  4. 在虚拟机执行时,通过使用ABI编码后的参数,来做到虚拟机之间的互相调用
代码语言:javascript
复制
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)
}
代码语言:javascript
复制
 +--------------+               +---------------+               +---------------+
 |              |  create vm    |               |    run        |               |
 |  Contract    | ------------> |   Contract    | ------------->|    Execute    |
 |  Info        |               |   Executor    |               |               | 
 +--------------+               +---------------+               +---------------+

总结

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

smart-architecture.jpg

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-10-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • Wasm虚拟机实现Ethereum Semantic
  • EVM虚拟机集成
  • 虚拟机间的兼容
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档