exec

package
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2019 License: BSD-3-Clause Imports: 18 Imported by: 3

Documentation

Overview

Package exec provides functions for executing WebAssembly bytecode.

Index

Examples

Constants

View Source
const (
	MinHeapMemorySize = 64 * 1024   //64k
	MaxHeapMemorySize = 1024 * 1024 //1M
)

Variables

View Source
var (
	// ErrSignatureMismatch is the error value used while trapping the VM when
	// a signature mismatch between the table entry and the type entry is found
	// in a call_indirect operation.
	ErrSignatureMismatch = errors.New("exec: signature mismatch in call_indirect")
	// ErrUndefinedElementIndex is the error value used while trapping the VM when
	// an invalid index to the module's table space is used as an operand to
	// call_indirect
	ErrUndefinedElementIndex = errors.New("exec: undefined element index")
)
View Source
var (
	// ErrMultipleLinearMemories is returned by (*VM).NewVM when the module
	// has more then one entries in the linear memory space.
	ErrMultipleLinearMemories = errors.New("exec: more than one linear memories in module")
	// ErrInvalidArgumentCount is returned by (*VM).ExecCode when an invalid
	// number of arguments to the WebAssembly function are passed to it.
	ErrInvalidArgumentCount = errors.New("exec: invalid number of arguments to function")
)
View Source
var ErrOutOfBoundsMemoryAccess = errors.New("exec: out of bounds memory access")

ErrOutOfBoundsMemoryAccess is the error value used while trapping the VM when it detects an out of bounds access to the linear memory.

View Source
var ErrUnreachable = errors.New("exec: reached unreachable")

ErrUnreachable is the error value used while trapping the VM when an unreachable operator is reached during execution.

View Source
var (
	InvalidMemIndex = errors.New("invalid memory index")
)

Functions

This section is empty.

Types

type ContractInvoker

type ContractInvoker interface {
	InvokeInternal(contractAddr string, ownerAddr string, callerAddr string, vmContext *VMContext, code []byte, contractName string, method string, params interface{}, rtnType string) (interface{}, error)
}

type InvalidFunctionIndexError

type InvalidFunctionIndexError int64

InvalidFunctionIndexError is returned by (*VM).ExecCode when the function index provided is invalid.

func (InvalidFunctionIndexError) Error

type InvalidReturnTypeError

type InvalidReturnTypeError int8

InvalidReturnTypeError is returned by (*VM).ExecCode when the module specifies an invalid return type value for the executed function.

func (InvalidReturnTypeError) Error

func (e InvalidReturnTypeError) Error() string

type NativeCompilationError

type NativeCompilationError struct {
	Start, End uint
	FuncIndex  int
	Err        error
}

NativeCompilationError represents a failure to compile a sequence of instructions to native code.

func (NativeCompilationError) Error

func (e NativeCompilationError) Error() string

type NativeCompileStats

type NativeCompileStats struct {
	Ops               map[byte]*OpStats
	NumCompiledBlocks int
}

NativeCompileStats encapsulates statistics about any native compilation performed on the VM.

type OpStats

type OpStats struct {
	Interpreted int
	Compiled    int
}

type Process

type Process struct {
	// contains filtered or unexported fields
}

Process is a proxy passed to host functions in order to access things such as memory and control.

func NewProcess

func NewProcess(vm *VM) *Process

NewProcess creates a VM interface object for host functions

func (*Process) MemSize

func (proc *Process) MemSize() int

MemSize returns the current allocated memory size in bytes.

func (*Process) ReadAt

func (proc *Process) ReadAt(p []byte, off int64) (int, error)

ReadAt implements the ReaderAt interface: it copies into p the content of memory at offset off.

func (*Process) ReadString

func (proc *Process) ReadString(off int64) (string, error)

func (*Process) Terminate

func (proc *Process) Terminate()

Terminate stops the execution of the current module.

func (*Process) VM

func (proc *Process) VM() *VM

func (*Process) VMContext

func (proc *Process) VMContext() *VMContext

func (*Process) WriteAt

func (proc *Process) WriteAt(p []byte, off int64) (int, error)

WriteAt implements the WriterAt interface: it writes the content of p into the VM memory at offset off.

type VM

type VM struct {

	// RecoverPanic controls whether the `ExecCode` method
	// recovers from a panic and returns it as an error
	// instead.
	// A panic can occur either when executing an invalid VM
	// or encountering an invalid instruction, e.g. `unreachable`.
	RecoverPanic bool
	// contains filtered or unexported fields
}

VM is the execution context for executing WebAssembly bytecode.

Example (Add)
package main

import (
	"bytes"
	"fmt"
	"io/ioutil"
	"log"
	"reflect"

	"github.com/Ankr-network/wagon/exec"
	"github.com/Ankr-network/wagon/wasm"
)

func main() {
	raw, err := compileWast2Wasm("testdata/add-ex-main.wast")
	if err != nil {
		log.Fatalf("could not compile wast file: %v", err)
	}

	m, err := wasm.ReadModule(bytes.NewReader(raw), func(name string) (*wasm.Module, error) {
		// ReadModule takes as a second argument an optional "importer" function
		// that is supposed to locate and import other modules when some module is
		// requested (by name.)
		// Theoretically, a general "importer" function not unlike the Python's 'import'
		// mechanism (that tries to locate and import modules from a $PYTHONPATH)
		// could be devised.
		switch name {
		case "add":
			raw, err := compileWast2Wasm("testdata/add-ex.wast")
			if err != nil {
				return nil, fmt.Errorf("could not compile wast file hosting %q: %v", name, err)
			}

			add, err := wasm.ReadModule(bytes.NewReader(raw), nil)
			if err != nil {
				return nil, fmt.Errorf("could not read wasm %q module: %v", name, err)
			}
			return add, nil
		case "go":
			// create a whole new module, called "go", from scratch.
			// this module will contain one exported function "print",
			// implemented itself in pure Go.
			print := func(proc *exec.Process, v int32) {
				fmt.Printf("result = %v\n", v)
			}

			m := wasm.NewModule()
			m.Types = &wasm.SectionTypes{
				Entries: []wasm.FunctionSig{
					{
						Form:       0, // value for the 'func' type constructor
						ParamTypes: []wasm.ValueType{wasm.ValueTypeI32},
					},
				},
			}
			m.FunctionIndexSpace = []wasm.Function{
				{
					Sig:  &m.Types.Entries[0],
					Host: reflect.ValueOf(print),
					Body: &wasm.FunctionBody{}, // create a dummy wasm body (the actual value will be taken from Host.)
				},
			}
			m.Export = &wasm.SectionExports{
				Entries: map[string]wasm.ExportEntry{
					"print": {
						FieldStr: "print",
						Kind:     wasm.ExternalFunction,
						Index:    0,
					},
				},
			}

			return m, nil
		}
		return nil, fmt.Errorf("module %q unknown", name)
	})
	if err != nil {
		log.Fatalf("could not read module: %v", err)
	}

	vm, err := exec.NewVM(m)
	if err != nil {
		log.Fatalf("could not create wagon vm: %v", err)
	}

	const fct1 = 2 // index of function fct1
	out, err := vm.ExecCode(fct1)
	if err != nil {
		log.Fatalf("could not execute fct1(): %v", err)
	}
	fmt.Printf("fct1() -> %v\n", out)

	const fct2 = 3 // index of function fct2
	out, err = vm.ExecCode(fct2, 40, 6)
	if err != nil {
		log.Fatalf("could not execute fct2(40, 6): %v", err)
	}
	fmt.Printf("fct2() -> %v\n", out)

	const fct3 = 4 // index of function fct3
	out, err = vm.ExecCode(fct3, 42, 42)
	if err != nil {
		log.Fatalf("could not execute fct3(42, 42): %v", err)
	}
	fmt.Printf("fct3() -> %v\n", out)

}

// compileWast2Wasm fakes a compilation pass from WAST to WASM.
//
// When wagon gets a WAST parser, this function will be running an actual compilation.
// See: https://github.com/Ankr-network/wagon/issues/34
func compileWast2Wasm(fname string) ([]byte, error) {
	switch fname {
	case "testdata/add-ex.wast":
		// obtained by running:
		//  $> wat2wasm -v -o add-ex.wasm add-ex.wast
		return ioutil.ReadFile("testdata/add-ex.wasm")
	case "testdata/add-ex-main.wast":
		// obtained by running:
		//  $> wat2wasm -v -o add-ex-main.wasm add-ex-main.wast
		return ioutil.ReadFile("testdata/add-ex-main.wasm")
	}
	return nil, fmt.Errorf("unknown wast test file %q", fname)
}
Output:

fct1() -> 42
fct2() -> 46
result = 84
fct3() -> <nil>

func NewVM

func NewVM(contractAddr string, ownerAddr string, callerAddr string, metric gas.GasMetric, publisher vmevent.Publisher, module *wasm.Module, opts ...VMOption) (*VM, error)

NewVM creates a new VM from a given module and options. If the module defines a start function, it will be executed.

func (*VM) CallerAddr

func (vm *VM) CallerAddr() string

func (*VM) Close

func (vm *VM) Close() error

Close frees any resources managed by the VM.

func (*VM) CompileStats

func (vm *VM) CompileStats() NativeCompileStats

CompileStats returns statistics about native compilation performed on the VM.

func (*VM) ContrInvoker

func (vm *VM) ContrInvoker() ContractInvoker

func (*VM) ContractAddr

func (vm *VM) ContractAddr() string

func (*VM) ExecCode

func (vm *VM) ExecCode(fnIndex int64, rtnType string, args ...uint64) (rtrn interface{}, err error)

ExecCode calls the function with the given index and arguments. fnIndex should be a valid index into the function index space of the VM's module.

func (*VM) Logger

func (vm *VM) Logger() log.Logger

func (*VM) Memory

func (vm *VM) Memory() []byte

Memory returns the linear memory space for the VM.

func (*VM) Module

func (vm *VM) Module() *wasm.Module

func (*VM) OwnerAddr

func (vm *VM) OwnerAddr() string

func (*VM) ReadAt

func (vm *VM) ReadAt(p []byte, off int64) (int, error)

ReadAt implements the ReaderAt interface: it copies into p the content of memory at offset off.

func (*VM) ReadString

func (vm *VM) ReadString(off int64) (string, error)

func (*VM) Restart

func (vm *VM) Restart()

Restart readies the VM for another run.

func (*VM) SetBytes

func (vm *VM) SetBytes(bytes []byte) (uint64, error)

func (*VM) SetContrInvoker

func (vm *VM) SetContrInvoker(contrInvoker ContractInvoker)

func (*VM) SetLogger

func (vm *VM) SetLogger(log log.Logger)

func (*VM) Strcmp

func (vm *VM) Strcmp(memIndex1 uint, memIndex2 uint) (int, error)

func (*VM) Strlen

func (vm *VM) Strlen(memIndex uint) (int, error)

type VMContext

type VMContext struct {
	JsonObjectCache []map[string]json.RawMessage
	// contains filtered or unexported fields
}

func NewVMContext

func NewVMContext() *VMContext

func (*VMContext) GasMetric

func (vmc *VMContext) GasMetric() gas.GasMetric

func (*VMContext) PopVM

func (vmc *VMContext) PopVM() (*VM, error)

func (*VMContext) Publisher

func (vmc *VMContext) Publisher() vmevent.Publisher

func (*VMContext) PushVM

func (vmc *VMContext) PushVM(vm *VM) (int, error)

func (*VMContext) RunningVM

func (vmc *VMContext) RunningVM() *VM

func (*VMContext) SetGasMetric

func (vmc *VMContext) SetGasMetric(metric gas.GasMetric)

func (*VMContext) SetPublisher

func (vmc *VMContext) SetPublisher(publisher vmevent.Publisher)

func (*VMContext) SetRunningVM

func (vmc *VMContext) SetRunningVM(vm *VM)

func (*VMContext) TopVM

func (vmc *VMContext) TopVM() (*VM, error)

type VMOption

type VMOption func(c *config)

VMOption describes a customization that can be applied to the VM.

func EnableAOT

func EnableAOT(v bool) VMOption

EnableAOT enables ahead-of-time compilation of supported opcodes into runs of native instructions, if wagon supports native compilation for the current architecture.

Directories

Path Synopsis
internal
compile
Package compile is used internally by wagon to convert standard structured WebAssembly bytecode into an unstructured form suitable for execution by it's VM.
Package compile is used internally by wagon to convert standard structured WebAssembly bytecode into an unstructured form suitable for execution by it's VM.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL