Giter Site home page Giter Site logo

perlin-network / life Goto Github PK

View Code? Open in Web Editor NEW
1.7K 56.0 122.0 4.04 MB

A secure WebAssembly VM catered for decentralized applications.

License: MIT License

Go 94.25% WebAssembly 0.83% Python 0.34% JavaScript 0.06% Shell 0.20% Rust 1.45% C 2.84% Makefile 0.03%

life's Introduction

Life

GoDoc Discord MIT licensed Build Status Go Report Card

life is a secure & fast WebAssembly VM built for decentralized applications, written in Go by Perlin Network.

Features

  • Fast - Includes a fast interpreter and an experimental AOT compilation engine.
  • Correct - Implements WebAssembly execution semantics and passes most of the official test suite (66/72 passed, none of the failures are related to the execution semantics).
  • Secure - User code executed is fully sandboxed. A WebAssembly module's access to resources (instruction cycles, memory usage) may easily be controlled to the very finest detail.
  • Pure - Does not rely on any native dependencies in interpreter-only mode, and may easily be cross-compiled for running WebAssembly modules on practically any platform (Windows/Linux/Mac/Android/iOS/etc).
  • Practical - Make full use of the minimal nature of WebAssembly to write code once and run anywhere. Completely customize how WebAssembly module imports are resolved and integrated, and have complete control over the execution lifecycle of your WebAssembly modules.

Getting Started

# enable go modules: https://github.com/golang/go/wiki/Modules
export GO111MODULE=on

# download the dependencies to vendor folder
go mod vendor

# build test suite runner
go build github.com/perlin-network/life/spec/test_runner

# run official test suite
python3 run_spec_tests.py /path/to/testsuite

# build main program
go build

# run your wasm program
# entry point is `app_main` by default if entry flag is omitted, array with 
# param in it is optional arguements for entrypoint. params should be converted into `int`.
./life -entry 'method' /path/to/your/wasm/program.wasm [param,...] 

# run your wasm program with the Polymerase AOT compilation engine enabled
./life -polymerase -entry 'method' /path/to/your/wasm/program.wasm [param,...]

Executing WebAssembly Modules

Suppose we have already loaded our *.wasm module's bytecode into the variable var input []byte.

Lets pass the bytecode into a newly instantiated virtual machine:

vm, err := exec.NewVirtualMachine(input, exec.VMConfig{}, &exec.NopResolver{}, nil)
if err != nil { // if the wasm bytecode is invalid
    panic(err)
}

Lookup the function ID to a desired entry-point function titled app_main:

entryID, ok := vm.GetFunctionExport("app_main") // can be changed to your own exported function
if !ok {
    panic("entry function not found")
}

And startup the VM; printing out the result of the entry-point function:

ret, err := vm.Run(entryID)
if err != nil {
    vm.PrintStackTrace()
    panic(err)
}
fmt.Printf("return value = %d\n", ret)

Interested to tinker with more options? Check out our fully-documented example here .

Import Resolvers

One extremely powerful feature is that you may completely customize how WebAssembly module import functions are resolved, executed, and defined.

With import resolvers, you may now securely call external code/functions inside your WebAssembly modules which are executed through life.

Take for example the following Rust module compiled down to a WebAssembly module:

extern "C" {
    fn __life_log(msg: *const u8, len: usize);
}

#[no_mangle]
pub extern "C" fn app_main() -> i32 {
    let message = "This is being called outside of WebAssembly!".as_bytes();

    unsafe {
        __life_log(message.as_ptr(), message.len());
    }

    return 0;
}

We can define an import resolver into our WebAssembly virtual machine that will let us define whatever code the function __life_log may execute in our host environment.

type Resolver struct{}

func (r *Resolver) ResolveFunc(module, field string) exec.FunctionImport {
	switch module {
	case "env":
		switch field {
		case "__life_log":
			return func(vm *exec.VirtualMachine) int64 {
				ptr := int(uint32(vm.GetCurrentFrame().Locals[0]))
				msgLen := int(uint32(vm.GetCurrentFrame().Locals[1]))
				msg := vm.Memory[ptr : ptr+msgLen]
				fmt.Printf("[app] %s\n", string(msg))
				return 0
			}

		default:
			panic(fmt.Errorf("unknown import resolved: %s", field))
		}
	default:
		panic(fmt.Errorf("unknown module: %s", module))
	}
}

func (r *Resolver) ResolveGlobal(module, field string) int64 {
	panic("we're not resolving global variables for now")
}

We can then include the import resolver into our WebAssembly VM:

vm, err := exec.NewVirtualMachine(input, exec.VMConfig{}, new(Resolver), nil)
if err != nil {
    panic(err)
}

And have the VM run the entry-point function app_main to see the result:

[app] This is being called from outside WebAssembly!

Benchmarks

We benchmarked life alongside a couple of other WebAssembly implementations in different programming languages (go-interpreter/wagon, paritytech/wasmi).

Raw results are here.

Contributions

We at Perlin love reaching out to the open-source community and are open to accepting issues and pull-requests.

For all code contributions, please ensure they adhere as close as possible to the following guidelines:

  1. Strictly follows the formatting and styling rules denoted here.
  2. Commit messages are in the format module_name: Change typed down as a sentence. This allows our maintainers and everyone else to know what specific code changes you wish to address.
    • compiler/liveness: Implemented full liveness analysis.
    • exec/helpers: Added function to run the VM with time limit.
  3. Consider backwards compatibility. New methods are perfectly fine, though changing the existing public API should only be done should there be a good reason.

If you...

  1. love the work we are doing,
  2. want to work full-time with us,
  3. or are interested in getting paid for working on open-source projects

... we're hiring.

To grab our attention, just make a PR and start contributing.

life's People

Contributors

a-urth avatar cristaloleg avatar doug-perlin avatar hunjixin avatar iwasaki-kenta avatar jack0 avatar justinclift avatar losfair avatar mastersingh24 avatar ondrajz avatar radding avatar sbinet avatar singpolyma-shopify avatar xe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

life's Issues

Virtual Machine Snapshots

I want to take a snapshot of the full virtual machine state so that I can restore it possibly even on another machine (in an external function that was called during the .wasm execution).

It seems necessary to only serialize the VirtualMachine struct for this, is this correct?

Go 1.11 WebAssembly modules

Have you guys done any testing with modules created via Go 1.11? I assume it might likely be an issue with wagon?

Simple test.go:

package main

import (
	"fmt"
)

func main() {
	fmt.Println("Hello World")
}

Using Go 1.11rc1:
GOOS=js GOARCH=wasm go build -o test.wasm test.go
and then
./life -entry main /Users/gsingh/Projects/golang/src/webassembly/test.wasm
with result

panic: unexpected EOF

goroutine 1 [running]:
main.main()
	/Users/gsingh/tmp/life/main.go:81 +0x72c

Maybe related to go-interpreter/wagon#69 ?

Unknown wagon revision causing error loading module requirements

When using go mod vendor:
go: finding github.com/perlin-network/life latest
go: finding github.com/go-interpreter/wagon v0.0.0
go: github.com/go-interpreter/[email protected]: unknown revision v0.0.0
go: error loading module requirements

I'm on go version go1.11.5 linux/amd64. (This might be my fault- I've never used go modules before.)
Thanks for any help!

An error occurred at the beginning of the attempt.

I encountered an error while executing the go mod vendor download dependency. I tried Google and found no answer. Who can tell me how to solve this problem?

go: labix.org/v2/[email protected]: bzr pull --overwrite-tags in /Users/residuallaugh/go/pkg/mod/cache/vcs/ca61c737a32b1e09a0919e15375f9c2b6aa09860cc097f1333b3c3d29e040ea8: exit status 3: bzr: ERROR: Not a branch: "/Users/residuallaugh/go/pkg/mod/cache/vcs/ca61c737a32b1e09a0919e15375f9c2b6aa09860cc097f1333b3c3d29e040ea8/.bzr/branch/": location is a repository. go: finding launchpad.net/gocheck v0.0.0-20140225173054-000000000087 go: launchpad.net/[email protected]: bzr pull --overwrite-tags in /Users/residuallaugh/go/pkg/mod/cache/vcs/f46ce2ae80d31f9b0a29099baa203e3b6d269dace4e5357a2cf74bd109e13339: exit status 3: bzr: ERROR: Not a branch: "/Users/residuallaugh/go/pkg/mod/cache/vcs/f46ce2ae80d31f9b0a29099baa203e3b6d269dace4e5357a2cf74bd109e13339/.bzr/branch/": location is a repository. go: error loading module requirements

Execute never returns

// Execute starts the virtual machines main instruction processing loop.
// This function may return at any point and is guaranteed to return
// at least once every 10000 instructions. Caller is responsible for
// detecting VM status in a loop.

As far as I can tell, this is just not true. It only returns on exit/error or gas limit exceeded. And a trivial infinite loop (jmp over and over) never triggers the gas limit check. This means there is no way to prevent a VM from being tied up forever by an infinite loop.

can't use printf

I write a code that just printf some info. Then compile to wasm. But there is an error when run in life.
The c code:

#include <stdio.h>
int main(){
  printf("test mapData1~~~~~~~~~~\r\n");
  return 0;
}
The wasm
(module
  (type $t0 (func (param i32) (result i32)))
  (type $t1 (func (result i32)))
  (import "env" "puts" (func $env.puts (type $t0)))
  (func $main (export "main") (type $t1) (result i32)
    (drop
      (call $env.puts
        (i32.const 16)))
    (i32.const 0))
  (table $T0 0 anyfunc)
  (memory $memory (export "memory") 1)
  (data (i32.const 16) "test mapData1~~~~~~~~~~\0d\00"))

the run code is:

func TestOriginLifeMap(t *testing.T){
	fileCode, err := ioutil.ReadFile("./sample/test.wasm")
	assert.NoError(t, err)

	vm, err := exec.NewVirtualMachine(fileCode, exec.VMConfig{
		EnableJIT:          false,
		DefaultMemoryPages: 128,
		DefaultTableSize:   65536,
	}, nil, nil)
	assert.NoError(t,err)

	entryID, ok := vm.GetFunctionExport("main")
	assert.Equal(t,true,ok)

	data, err := vm.Run(entryID)
	assert.NoError(t,err)

	fmt.Printf("the data is: %d",data)
}

There is an error:
runtime error: index out of range

I found the wasm need call "puts", but there is't the import function in ResolveFunc.
https://github.com/perlin-network/life/blob/master/main.go#L20
so does it mean life can't run the related function in c standard library?
If not, why there is an error occurred?

How AddGas injected?

For Gas control flow life used AddGas instruction.
From source code it's not clear how it injected to Wasm instructions.

		case opcodes.AddGas:
			delta := LE.Uint64(frame.Code[frame.IP : frame.IP+8])

where delta are formed?

The root question from strange behavior:

#[no_mangle]
pub extern "C" fn sum(n: u64) -> u64 {
        let mut res = 0;
        for x in 0..n {
                res += x;
        }
        return res;
}

#[no_mangle]
pub extern "C" fn app_main() -> u64 {
        sum(1_000_000)
}

And after execution vm.Gas == 2. It's strange.

What's the status of Jit compiler?

Hey Perlin guys:

In "Features" section, I saw "JIT support for x86-64 and ARM is planned". But In "Benchmarks" section, I saw the test result of life(JIT). So what's the current status of life's jit compiler?

Thanks!

Problem sending string concatenated with variable

Hello all,

I am trying to run a ts (compiled with Assemblyscript) file that implements a simple function, it logs on the terminal a string concatenated with a variable (that is also a string). The code is imported through Perlin and runs in a Golang Vm.

Here is a Go code chunk that is handling the generated wasm,;-the string is reconstructed ffollowing AssemblyScript documentation on how strings are allocated in the memory(https://github.com/AssemblyScript/assemblyscript/wiki/Memory-Layout-&-Management):


ptr := int(uint32(vm.GetCurrentFrame().Locals[0]))
msgLen := int(uint32(vm.Memory[ptr]))
msg := vm.Memory[(ptr + 4):(ptr + 4 + 2*msgLen)]
fmt.Println(ptr)`

This is a ts code that when compiled works fine :

export function app_main():string{
	let a = "Hello";
	r.consoleLog(a);
	return '0';
}

Here is another ts code that also runs without any problem:

export function app_main():string{
		r.consoleLog('World');
		return '0';
}

But here is a code that not only does not work but also returns an error:

export function app_main():string{
		let a = 'World';
		r.consoleLog("Hello"+a);
		return '0';
}

And here is the error that Life returns:

Resolve func: env abort
panic: unknown field: abort

It is important to emphasize that this error does not appear in any other instances.

So, anyone has a workaround for this issue??

Failed to install and build Life

Hey perlin fellows,

I'm having a hard time installing your code into my machine.

I'm having this error:

λ ~/GoPath/src/github.com/perlin-network/life/ master vgo mod -vendor
go: finding github.com/losfair/wagon v0.0.0-20180807163237-f6497f251c75
go: github.com/losfair/[email protected]: unknown revision f6497f251c75d3d2ea31bdbc05b636f5d4d39221
go: error loading module requirements

Exported function Input parameters

I am still going through the code to see if I can answer this myself.

Do you currently support input parameters to exported wasm functions, If so do you have an example.

I am currently stepping through vm.Run and vm.Ignite.

Example for resource control and further questions

Can you provide an example of how to invoke a process in your VM with instruction step limits?
Can instruction steps and memory usage be limited separately?
What is the granularity of resource control (for time: the number of milliseconds or with Instruction steps: per instruction, per block, per function call; for memory: bytes, kilobytes, pages, etc.)?
Is it possible to refuel a process that ran out of gas?
Can a process within your VM create and sandbox another one? (Either by a custom VM instruction or providing an external function that the process can call)

panic: unknown module: go

osx high sierra, v10.13.6

A basic test of life and the output of the go11 wasm produces the error panic: unknown module: go.

jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ export PATH=/usr/local/go1.11.1/bin:$PATH
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ go version
go version go1.11.1 darwin/amd64
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ GOARCH=wasm GOOS=js go build -o lib.wasm m.go
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ ls -alFtr|tail
drwxrwxr-x   3 jaten  staff       96 Oct 22 22:39 spec/
drwxrwxr-x  14 jaten  staff      448 Oct 22 22:39 tests/
drwxrwxr-x   3 jaten  staff       96 Oct 22 22:39 utils/
drwxrwxr-x  13 jaten  staff      416 Oct 22 22:39 .git/
-rw-rw-r--   1 jaten  staff      350 Oct 22 22:40 go.sum
drwxrwxr-x   4 jaten  staff      128 Oct 22 22:40 vendor/
-rwxrwxr-x   1 jaten  staff  3496456 Oct 22 22:40 test_runner*
-rw-rw-r--   1 jaten  staff      177 Oct 22 22:44 m.go
-rwxrwxr-x   1 jaten  staff  2532371 Oct 22 22:44 lib.wasm*
drwxrwxr-x  22 jaten  staff      704 Oct 22 22:44 ./
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ life ./lib.wasm
Resolve func: go debug
panic: unknown module: go

goroutine 1 [running]:
main.main()
	/Users/jaten/go/src/github.com/perlin-network/life/main.go:78 +0x63d
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ cat m.go
package main

import (
	"fmt"
	"time"
)

func main() {
	t0 := time.Now()
	a := 0
	for i := 0; i < 10000000; i++ {
		a++
	}
	fmt.Printf("a = %v, elap=%v\n", a, time.Since(t0))
}
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ go run m.go # positive control
a = 10000000, elap=2.941357ms
jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ git log|head
commit 4e2637791edc5716293a29710531e36d39da4d5c
Merge: 1eb3d14 6525bd2
Author: Heyang Zhou <[email protected]>
Date:   Fri Oct 12 11:18:30 2018 +0800

    Merge pull request #38 from perlin-network/return-on-gas-limit
    
    Allow normal return instead of error when gas limit is exceeded.

jaten@jatens-MacBook-Pro ~/go/src/github.com/perlin-network/life (master) $ 

gomobile bind fails

gomobile bind -target=ios -o life.framework
gomobile: darwin-arm: go build -tags ios -buildmode=c-archive -o /var/folders/df/6z4dgq9d44l8164d2s4mb0r00000gn/T/gomobile-work-606257726/life-arm.a gobind failed: exit status 2
# github.com/perlin-network/life/exec
exec/vm_codegen.go:93:37: constant -9223372036854775808 overflows int

gomobile bind -target=android
gomobile: go build -buildmode=c-shared -o=/var/folders/df/6z4dgq9d44l8164d2s4mb0r00000gn/T/gomobile-work-891709332/android/src/main/jniLibs/armeabi-v7a/libgojni.so gobind failed: exit status 2
# github.com/perlin-network/life/exec
exec/vm_codegen.go:93:37: constant -9223372036854775808 overflows int

too many arguments in call to disasm.Disassemble

Hi,

I am facing this error while trying to call a wasm file from go code:

connecto/input/src/github.com/connecto/lifecontractone/vendor/github.com/perlin-network/life/compiler/module.go:147:31: too many arguments in call to disasm.Disassemble
	have (wasm.Function, *wasm.Module)
	want ([]byte)
connecto/input/src/github.com/connecto/lifecontractone/vendor/github.com/perlin-network/life/compiler/module.go:151:39: cannot use d (type []disasm.Instr) as type *disasm.Disassembly in argument to NewSSAFunctionCompiler
connecto/input/src/github.com/connecto/lifecontractone/vendor/github.com/perlin-network/life/compiler/module.go:223:31: too many arguments in call to disasm.Disassemble
	have (wasm.Function, *wasm.Module)
	want ([]byte)
connecto/input/src/github.com/connecto/lifecontractone/vendor/github.com/perlin-network/life/compiler/module.go:227:39: cannot use d (type []disasm.Instr) as type *disasm.Disassembly in argument to NewSSAFunctionCompiler

Snippet of go code:


// Resolver defines imports for WebAssembly modules ran in Life.
type Resolver struct {
	tempRet0 int64
}

// ResolveFunc defines a set of import functions that may be called within a WebAssembly module.
func (r *Resolver) ResolveFunc(module, field string) exec.FunctionImport {
	fmt.Printf("Resolve func: %s %s\n", module, field)
	switch module {
	case "env":
		switch field {
		case "__life_log":
			return func(vm *exec.VirtualMachine) int64 {
				ptr := int(uint32(vm.GetCurrentFrame().Locals[0]))
				msgLen := int(uint32(vm.GetCurrentFrame().Locals[1]))
				msg := vm.Memory[ptr : ptr+msgLen]
				fmt.Printf("[app] %s\n", string(msg))
				return 0
			}
		default:
			panic(fmt.Errorf("unknown field: %s", field))
		}
	default:
		panic(fmt.Errorf("unknown module: %s", module))
	}
}

// ResolveGlobal defines a set of global variables for use within a WebAssembly module.
func (r *Resolver) ResolveGlobal(module, field string) int64 {
	fmt.Printf("Resolve global: %s %s\n", module, field)
	switch module {
	case "env":
		switch field {
		case "__life_magic":
			return 424
		default:
			panic(fmt.Errorf("unknown field: %s", field))
		}
	default:
		panic(fmt.Errorf("unknown module: %s", module))
	}
}

// query callback representing the query of a chaincode
func main()  {

	wasmbytes, _ := getWasm(A)
	entryFunctionFlag := flag.String("entry", "funcToInvoke", "entry function name")
	noFloatingPointFlag := flag.Bool("no-fp", false, "disable floating point")
	flag.Parse()


	validator, err := wasm_validation.NewValidator()
	if err != nil {
		panic(err)
	}
	err = validator.ValidateWasm(Chaincodebytes)
	if err != nil {
		panic(err)
	}

	// Instantiate a new WebAssembly VM with a few resolved imports.
	vm, err := exec.NewVirtualMachine(Chaincodebytes, exec.VMConfig{
		DefaultMemoryPages:   128,
		DefaultTableSize:     65536,
		DisableFloatingPoint: *noFloatingPointFlag,
	}, new(Resolver), nil)

	if err != nil {
		panic(err)
	}

	// Get the function ID of the entry function to be executed.
	entryID, ok := vm.GetFunctionExport(*entryFunctionFlag)
	if !ok {
		fmt.Printf("Entry function %s not found; starting from 0.\n", *entryFunctionFlag)
		entryID = 0
	}

	start := time.Now()

	// Run the WebAssembly module's entry function.
	result, err := vm.Run(entryID)
	if err != nil {
		vm.PrintStackTrace()
		panic(err)
	}
	end := time.Now()

	fmt.Printf("return value = %d, duration = %v\n", result, end.Sub(start))

	fmt.Printf("Query Response:%s\n", result)
}

Any pointers on what might have gone wrong would be appreciated.

Thanks

Unable to import and use

This project looks great and I'd love to use it for an upcoming project.

Unfortunately, it just won't work:

➜  go get
go: finding github.com/perlin-network/life/exec latest
go: finding github.com/perlin-network/life latest
go: finding github.com/go-interpreter/wagon v0.0.0
go: github.com/go-interpreter/[email protected]: unknown revision v0.0.0
go: error loading module requirements

Is there a workaround or should I just wait for stability?

how to get GlobalExport ?

func GetExport(vm *exec.VirtualMachine,name string) int64{
	entryID, ok := vm.GetGlobalExport(name)
	if ok {
		fmt.Printf("Entry GlobalExport %s not found; starting from 0.\n", name)
		entryID = 0
	}
	ret, err := vm.Run(entryID)

	if err != nil {
		vm.PrintStackTrace()
		panic(err)
	}
	return ret
}

How to call back into WASM from ResolveFunc

I am trying to implement the invoke_ii helper for emscripten. The JS generated by emscripten is:

function invoke_ii(index,a1) {
  var sp = stackSave();
  try {
    return Module["dynCall_ii"](index,a1);
  } catch(e) {
    stackRestore(sp);
    if (typeof e !== 'number' && e !== 'longjmp') throw e;
    Module["setThrew"](1, 0);
  }
}

stackSave, stackRestore, and dynCall_ii all ultimately come from the WASM and the call here is just a shim (I assume to enable using JS exceptions for some handling here? Not 100% sure why emscripten needs this shim). When I try to just find dynCall_ii and use vm.Run however, I get call stack not empty; cannot ignite -- is it just not possible to call back into WASM from the go side at the moment, or am I missing some way to do this?

Error: "m.Customs undefined (type *wasm.Module has no field or method Customs)"

$ go get -u github.com/perlin-network/life/exec
go: finding github.com/perlin-network/life/exec latest
go: finding github.com/perlin-network/life latest
go: finding golang.org/x/tools latest
# github.com/perlin-network/life/compiler
../../../../../pkg/mod/github.com/perlin-network/[email protected]/compiler/module.go:46:23: m.Customs undefined (type *wasm.Module has no field or method Customs)

$ go version
go version go1.11 darwin/amd64

AOT

what is AOT shorted for?
does it necessary to compile .wasm(compile from C/rust) to in.c and out back?

Strange misbehaviour in life VM

https://0x0.st/zcgm.wasm

The above wasm works in nodejs and using wagon's wasm-run command, but running with life I get a different return value.

Calling the exported function run with no arguments should return 4 and in nodejs and wasm-run it does but running under life I get 0.

I know it's a big blob but I have not yet been able to get a smaller version that triggers the bug.

panic: input too large

I'm trying to run stuff from the benchmarks folder just to get a sense of how things work.

In the fib_recursive benchmark folder I ran cargo build --release. This produced a .wasm file in the target folder. I then tried to run it with life like this:

$ ./life bench/cases/fib_recursive/target/wasm32-unknown-unknown/release/fib_recursive.wasm 
panic: input too large

goroutine 1 [running]:
main.main()
        /Users/jehan/life/main.go:86 +0xc29

Cannot Run `go build`

after running go build i get:

build github.com/perlin-network/life: cannot find module for path bytes

Full Print:

matt@ubuntu:~/web/life$ go build
go: finding github.com/go-interpreter/wagon v0.0.0
build github.com/perlin-network/life: cannot find module for path bytes

latest Go version installed on Ubuntu 16.04

interop between WASM containers

this is the new docker in a way.
Is there an common interop between WASM containers yet ? Wondering if GRPC is the right way to go ?
I have not even tried but raising here as i expect the team there have thought about this.

There seems to be two fundamental approaches that i see so far:
1- Open a port on the VM host that lets the VM guest use anything it wants.
2- Integrate some sort of IO API at the host level that allows VMS to talk to each other using a formalised transport.

curious where you are heading on this.

What generates custom section with type id == 1?

In compiler/module.go, there seems to be an initial decoder for custom sections, with the current code looking for a type of 1:

if err != nil || ty != 1 {

Any idea what generates these sections?

Asking because I'm adding code in my fork to decode the (LLVM 8 generated) custom section containing the function names (type = 4).

It looks like the existing code is meant to do the same thing (extract function names). Not sure what is being used to generate it though, so an curious if maybe it was from an older LLVM release or similar?

creating vm based off docs dont work

Hello, I have my wasm module compiled (written in go) and I'm trying to load it up in the wasm vm, but following the example code doesn't work:

go: finding github.com/go-interpreter/wagon v0.0.0 # command-line-arguments ./test.go:16:35: not enough arguments in call to exec.NewVirtualMachine have ([]byte, exec.VMConfig, *exec.NopResolver) want ([]byte, exec.VMConfig, exec.ImportResolver, compiler.GasPolicy)

Any help would be appreciated.

Invalid assumption of stack pointer in compiled .wasm.

#include <stdio.h>
#include <string.h>
#include <cstdlib>
extern "C" {
extern void logi(int);
extern void logs(char *);
extern void logl(long);
}
int main() {
    int a[3];
    a[0]=134;
    a[1]=13;
    a[2]=52;
    for (const auto &item : a)
    {
        logi(item);
    }
    return 0;
}
(module
 (type $FUNCSIG$vi (func (param i32)))
 (import "env" "logi" (func $logi (param i32)))
 (table 0 anyfunc)
 (memory $0 1)
 (export "memory" (memory $0))
 (export "main" (func $main))
 (func $main (; 1 ;) (result i32)
  (local $0 i32)
  (local $1 i32)
  (local $2 i32)
  (i32.store offset=4
   (i32.const 0)
   (tee_local $2
    (i32.sub
     (i32.load offset=4
      (i32.const 0)
     )
     (i32.const 16)
    )
   )
  )
  (i32.store offset=12
   (get_local $2)
   (i32.const 52)
  )
  (i64.store offset=4 align=4
   (get_local $2)
   (i64.const 55834574982)
  )
  (call $logi
   (i32.const 134)
  )
  (set_local $0
   (i32.add
    (i32.add
     (get_local $2)
     (i32.const 4)
    )
    (i32.const 4)
   )
  )
  (set_local $1
   (i32.const 0)
  )
  (loop $label$0
   (call $logi
    (i32.load
     (i32.add
      (get_local $0)
      (get_local $1)
     )
    )
   )
   (br_if $label$0
    (i32.ne
     (tee_local $1
      (i32.add
       (get_local $1)
       (i32.const 4)
      )
     )
     (i32.const 8)
    )
   )
  )
  (i32.store offset=4
   (i32.const 0)
   (i32.add
    (get_local $2)
    (i32.const 16)
   )
  )
  (i32.const 0)
 )
)

i64.const 55834574982

=== RUN   TestWasmRun
--- Begin stack trace ---
<0> [1] 
--- End stack trace ---
--- FAIL: TestWasmRun (0.00s)
panic: runtime error: slice bounds out of range [recovered]
	panic: runtime error: slice bounds out of range

could GasPolicy have more detail abount op

could GasPolicy have more detail abount op like below

type GasPolicy interface {
	GetCost(key Instr) int64
}

some time more detail may be needed
eg:
GrowMemory op. i want to know how many pages to grow, op gas may be n* pageGas.

if think it ok. i can have a pr

Dockerfile

Will be nice to have a docker file to simplify testing of ./life binary.

Question: Is life available without Go modules?

As life uses replace section in its go.mod, I was wondering if life works when the user tries to go-get github.com/go-interpreter/wagon instead of github.com/perlin-network/wagon due to lack of Go modules.

provide an example for return string or[]byte

Current there is an example for read string in resolvefunction, how about return a string? In my mind, we need two methods return pointer and len respect, however how to combined these operation in two methods call?

Unable to Import/Compile Life

Been having some issue adding Life to a project. Here is my go.mod:

module github.com/ansermino/wasm-test

replace github.com/go-interpreter/wagon v0.0.0 => github.com/perlin-network/wagon v0.3.1-0.20180825141017-f8cb99b55a39

require (
	github.com/go-interpreter/wagon v0.4.0 // indirect
	github.com/perlin-network/life v0.0.0-20190402092845-c30697b41680
	google.golang.org/appengine v1.5.0 // indirect
)

When I run go run, go build I get:

# github.com/perlin-network/life/compiler
../../../../pkg/mod/github.com/perlin-network/[email protected]/compiler/module.go:147:31: too many arguments in call to disasm.Disassemble
        have (wasm.Function, *wasm.Module)
        want ([]byte)
../../../../pkg/mod/github.com/perlin-network/[email protected]/compiler/module.go:151:39: cannot use d (type []disasm.Instr) as type *disasm.Disassembly in argument to NewSSAFunctionCompiler
../../../../pkg/mod/github.com/perlin-network/[email protected]/compiler/module.go:223:31: too many arguments in call to disasm.Disassemble
        have (wasm.Function, *wasm.Module)
        want ([]byte)
../../../../pkg/mod/github.com/perlin-network/[email protected]/compiler/module.go:227:39: cannot use d (type []disasm.Instr) as type *disasm.Disassembly in argument to NewSSAFunctionCompiler

Benchmarks

Thanks for publishing those benchmarks! I was recently looking at wabt, which among other things contains a very neat interpreter. Have you excluded it from the benchmark list on purpose (maybe wabt is too slow), or was it more due to other reasons (e.g., limited time)?

CC: @binji

Interop with Strings

Hey Perlin fellows,

How are you doing?

I would like to know how your Strings support works (if you have it)!

SSA advantages

I would like to understand the benefit of transpiling WASM to an SSA-based IR
Is this solely based on the fact that register-based VM has better performance compared to a stack-based? If so, is there any benchmark showing the execution speed gain is worth the compilation overhead?

Incorrect switch statement execution in go

package main

func main() {
	s := "f64"
	switch s {
	case "i32":
	case "i64":
	case "f32":
	case "f64":
	default:
		panic(s)
	}
}

go version go1.11.1 darwin/amd64

The default branch is triggered, then panic.
It's ok in browser.

Update to latest version of wagon

wagon has added module support plus made a few mods in terms of parsing custom sections.
Makes sense to stay up to date with wagon.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.