go-ethereum/core/vm/ewasm_linker.go
Guillaume Ballet 9927596822 core/vm: Add wagon/wasm as an interpreter
* Implement the ewasm module and the EEI.
 * Add an ewasm standalone binary to test standalone files
 * use reflection to declare EEI module exports
 * check the module name when importing EEI functions
 * make eeiFuncs a function to avoid an init loop issue in call
 * Add a reference to the ewasm tests
 * wagon implementation of the Interpreter interface
 * update to wagon's PR #59 and uses the Process structure
 * Adapt to endianness change
 * All tests but 1 passing
 * CanRun only checks for the header
 * Add a "debug" module to support "printHex" in contracts

Notes:
  * There are very little checks, e.g. of
     the call depths and so on.
2018-10-05 15:15:41 +02:00

119 lines
2.9 KiB
Go

// Copyright 2018 The go-ethereum Authors
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package vm
import (
"fmt"
"github.com/go-interpreter/wagon/wasm"
)
var eeiFunctionList = []string{
"useGas",
"getAddress",
"getExternalBalance",
"getBlockHash",
"call",
"callDataCopy",
"getCallDataSize",
"callCode",
"callDelegate",
"callStatic",
"storageStore",
"storageLoad",
"getCaller",
"getCallValue",
"codeCopy",
"getCodeSize",
"getBlockCoinbase",
"create",
"getBlockDifficulty",
"externalCodeCopy",
"getExternalCodeSize",
"getGasLeft",
"getBlockGasLimit",
"getTxGasPrice",
"log",
"getBlockNumber",
"getTxOrigin",
"finish",
"revert",
"getReturnDataSize",
"returnDataCopy",
"selfDestruct",
"getBlockTimestamp",
}
var debugFunctionList = []string{
"printMemHex",
"printStorageHex",
}
// ModuleResolver matches all EEI functions to native go functions
func ModuleResolver(interpreter *InterpreterEWASM, name string) (*wasm.Module, error) {
if name == "debug" {
debugModule := wasm.NewModule()
debugModule.Types = eeiTypes
debugModule.FunctionIndexSpace = getDebugFuncs(interpreter)
entries := make(map[string]wasm.ExportEntry)
for idx, name := range debugFunctionList {
entries[name] = wasm.ExportEntry{
FieldStr: name,
Kind: wasm.ExternalFunction,
Index: uint32(idx),
}
}
debugModule.Export = &wasm.SectionExports{
Entries: entries,
}
return debugModule, nil
}
if name != "env" && name != "ethereum" {
return nil, fmt.Errorf("Unknown module name: %s", name)
}
m := wasm.NewModule()
m.Types = eeiTypes
m.FunctionIndexSpace = eeiFuncs(interpreter)
entries := make(map[string]wasm.ExportEntry)
for idx, name := range eeiFunctionList {
entries[name] = wasm.ExportEntry{
FieldStr: name,
Kind: wasm.ExternalFunction,
Index: uint32(idx),
}
}
m.Export = &wasm.SectionExports{
Entries: entries,
}
return m, nil
}
// WrappedModuleResolver returns a module resolver function that whose
// EEI functions are closure-bound to a given interpreter.
// This is the first step to closure hell, the plan is to improve PR #59
// in wagon to be able to pass some context.
func WrappedModuleResolver(in *InterpreterEWASM) wasm.ResolveFunc {
return func(name string) (*wasm.Module, error) {
return ModuleResolver(in, name)
}
}