plainchant
  • Welcome PCT‘s Blog
  • Golang
    • golang基础
      • Go 语言 select 的实现原理
      • golang数字最大值
      • go-defer
      • Channel实现
      • go逃逸分析
      • Golang调度
  • Linux
  • Linux开发
    • 查看磁盘的UUID并挂载
    • Linux内核开发示例
    • 误删Linux内核后修复系统
    • linux补丁的创建和应用
    • Git常用命令
    • SystemV消息队列使用范例
    • ubuntu搭建全局代理
    • linux安装和配置
  • 嵌入式
    • 计算机为什么存在补码
    • 一种可靠串口协议
    • CRC校验算法
    • RasperryPi3 Ros系统安装(Debian)
  • 套接字编程
    • TCP建立连接过程分析
    • 线程的分发
    • TCP的并发处理epoll
    • TCP的并发处理select
    • 非阻塞TCP示例
    • 阻塞TCP示例
    • UDP组播
    • UDP广播
    • 非阻塞UDP示例(fcntl方式)
    • 非阻塞UDP示例
    • 局域网发现协议
    • socket通信机制浅析-前言
  • 交友网站
  • 区块链
    • Wasm虚拟机
      • wagon外部参数和内部参数的统一
      • Wagon实现log函数的第二种方法
      • Wagon实现一个log函数
      • go版本wasm解析器分析
      • 解析wasm二进制文件
      • ONT实现API的流程
      • Wasm工具安装使用
    • BCH
      • SLP代币协议
    • Cosmos
      • 区块链共识进化史
      • Tendermint 的区块构成
      • CoinEx 链 Gas 费指南
      • CoinEx交易类型收集
      • Cosmos简介和环境搭建
    • ETH
      • Geth命令详解
    • BTC
      • 助记词到地址
  • 算法
    • 动态规划
  • HTTP
    • URL 在浏览器被被输入到页面展现的过程中发生了什么
  • 运维后台
    • Docker学习笔记
  • 数据型应用系统设计
    • 数据密集型应用系统设计读书笔记
    • 数据编码与演化
      • Kafka配置
      • protobuf简介
    • MySQL
      • mysql安装和数据目录变更
      • 深入理解事务
      • MySQL事务问题验证
    • Redis
      • Redis缓存实现
      • Redis基本概念
由 GitBook 提供支持
在本页

这有帮助吗?

  1. 区块链
  2. Wasm虚拟机

ONT实现API的流程

[TOC]

实现方式

本体是在原有VM的基础上添加了memory部分,实现wasm虚拟机的堆栈处理部分。 在调用合约时会执行下面函数:

func (this *WasmVmService) Invoke() (interface{}, error) {


    stateMachine := NewWasmStateMachine()



    //register the "CallContract" function



    stateMachine.Register("ONT_CallContract", this.callContract)



    stateMachine.Register("ONT_MarshalNativeParams", this.marshalNativeParams)



    stateMachine.Register("ONT_MarshalNeoParams", this.marshalNeoParams)

这里注册了ONT的API,注册函数将函数执行和名称存在一个map里:

func (i *WasmStateReader) Register(name string, handler func(*exec.ExecutionEngine) (bool, error)) bool {


    if _, ok := i.serviceMap[name]; ok {



        return false



    }



    i.serviceMap[name] = handler



    return true



}

等待执行时取出,实现体内部则是调用自己实现的memory:

func (this *WasmVmService) runtimeLog(engine *exec.ExecutionEngine) (bool, error) {


    vm := engine.GetVM()



    envCall := vm.GetEnvCall()



    params := envCall.GetParams()



    if len(params) != 1 {



        return false, errors.NewErr("[RuntimeLog]parameter count error ")



    }



    item, err := vm.GetPointerMemory(params[0])



    if err != nil {



        return false, err



    }



    context := this.ContextRef.CurrentContext()



    txHash := this.Tx.Hash()



    event.PushSmartCodeEvent(txHash, 0, event.EVENT_LOG, &event.LogEventArgs{TxHash: txHash, ContractAddress: context.ContractAddress, Message: string(item)})



    vm.RestoreCtx()



    return true, nil



}

将获取的结果存入堆栈中,并返回指针。 在执行代码时,首先解析module部分,然后创建新的VM:

func (e *ExecutionEngine) call(caller common.Address,


    code []byte,



    input []byte,



    actionName string,



    ver byte) (returnbytes []byte, er error) {



    if ver > 0 { //production contract version



        methodName := CONTRACT_METHOD_NAME //fix to "invoke"



        //1. read code



        bf := bytes.NewBuffer(code)



        //2. read module



        m, err := wasm.ReadModule(bf, importer)



        if err != nil {



            return nil, errors.NewErr("[Call]Verify wasm failed!" + err.Error())



        }



        //3. verify the module



        //already verified in step 2



        //4. check the export



        //every wasm should have at least 1 export



        if m.Export == nil {



            return nil, errors.NewErr("[Call]No export in wasm!")



        }



        vm, err := NewVM(m)

load部分就是将解析出的module加载到虚拟机,这个过程会调用vm.newFuncTable()来生成函数列表:

func (vm *VM) newFuncTable() {


    vm.funcTable[ops.I32Clz] = vm.i32Clz



    vm.funcTable[ops.I32Ctz] = vm.i32Ctz



    vm.funcTable[ops.I32Popcnt] = vm.i32Popcnt



    vm.funcTable[ops.I32Add] = vm.i32Add



    vm.funcTable[ops.I32Sub] = vm.i32Sub


    vm.funcTable[ops.Call] = vm.call


    vm.funcTable[ops.CallIndirect] = vm.callIndirect

vm.call里面就实现了我们上面定义的API:

func (vm *VM) call() {


    index := vm.fetchUint32()



    vm.doCall(vm.compiledFuncs[index], int64(index))



}
func (vm *VM) doCall(compiled compiledFunction, index int64) {


        vm.envCall.envPreCtx = prevCtxt



        v, ok := vm.Services[compiled.name]



        if ok {



            rtn, err := v(vm.Engine)

这里还有一个问题存疑,就是在解析wasm文件时,调用的ONT API是作为外部函数的,解析时会找不到,这个是通过编译器解决的还是其他方式还未看懂。

上一页解析wasm二进制文件下一页Wasm工具安装使用

最后更新于4年前

这有帮助吗?