Skip to content

Commit

Permalink
[x/programs] migrate to wasm runtime to wasmtime and refactor for VM …
Browse files Browse the repository at this point in the history
…integration (#477)

* [x/programs] migrate to wasm runtime to wasmtime

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Implement memory with tests

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add guest import examples

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add vm/storage examples

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Remove storage mocks

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Remove hard coded guest imports

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Update token example to use new runtime

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Implement guest export client

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add config builder

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* React to new implementations

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Implement meter

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Remove failing tests/examples for now

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Fix lints

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add Wasi mod as const

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Improve docs around host function imports

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add meter and runtime stop tests

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add licenses

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add precompile function

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add precompile bench

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Remove cache from precompiled bench

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* nit

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add token program example

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* wip

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* remove wasi

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* wip

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add state import

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Cleanup token

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Recompile and update tests

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* add optimizations that reduce binary size

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Remove bulk memory from token tests

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add runtime import factory

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Rename state import module as pstate

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add counter program to program example

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Update runtime to use SupportedImports type

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Update token example

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Cleanup logging

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* More log cleanup

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Cargo fmt

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Cleanup

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add RunShort benchmark for token

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Add max wasm stack test

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Cleanup and nits

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Cleanup storage

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Define defaults for all configs

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Remove unused file

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Document opt-level flag for release profile

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

* Remove todo

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>

---------

Signed-off-by: Sam Batschelet <sam.batschelet@avalabs.org>
  • Loading branch information
hexfusion authored Oct 6, 2023
1 parent 9b37f07 commit 8ecd682
Show file tree
Hide file tree
Showing 43 changed files with 2,098 additions and 1,122 deletions.
4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ members = [
resolver = "2"

[profile.release]
opt-level = 3
# https://rustwasm.github.io/docs/book/reference/code-size.html#tell-llvm-to-optimize-for-size-instead-of-speed
opt-level = "s"
lto = true
codegen-units = 1
overflow-checks = true
# https://doc.rust-lang.org/book/ch09-01-unrecoverable-errors-with-panic.html#unwinding-the-stack-or-aborting-in-response-to-a-panic
panic = 'abort'
strip = true
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ go 1.20

require (
github.com/NYTimes/gziphandler v1.1.1
github.com/ava-labs/avalanche-network-runner v1.7.2
github.com/ava-labs/avalanche-network-runner v1.7.2-0.20230825184751-fbe081616f02
github.com/ava-labs/avalanchego v1.10.10
github.com/bytecodealliance/wasmtime-go/v13 v13.0.0
github.com/cockroachdb/pebble v0.0.0-20230224221607-fccb83b60d5c
github.com/golang/mock v1.6.0
github.com/gorilla/mux v1.8.0
Expand All @@ -19,7 +20,6 @@ require (
github.com/prometheus/client_golang v1.16.0
github.com/rs/cors v1.7.0
github.com/stretchr/testify v1.8.3
github.com/tetratelabs/wazero v1.3.0
go.opentelemetry.io/otel v1.11.2
go.opentelemetry.io/otel/exporters/zipkin v1.11.2
go.opentelemetry.io/otel/sdk v1.11.2
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,12 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/ava-labs/avalanche-network-runner v1.7.2 h1:XFad/wZfYzDnqbLzPAPPRYU3a1Zc8QT8x5dtLTS3lUo=
github.com/ava-labs/avalanche-network-runner v1.7.2/go.mod h1:naLveusSrP7YgTAqRykD1SyLOAUilCp9jGjk3MDxoPI=
github.com/ava-labs/avalanche-network-runner v1.7.2-0.20230825184751-fbe081616f02 h1:VThDljvPfIWneBO6Y99Nboe3yrJwI8clhRiQ9zuHVB8=
github.com/ava-labs/avalanche-network-runner v1.7.2-0.20230825184751-fbe081616f02/go.mod h1:euKHwZ77sGvGfhVj4v9WPM4jD2b5N80ldE2XHqO7lwA=
github.com/ava-labs/avalanchego v1.10.10 h1:EYX4LVotcfdtIQ0nJSBTcoisubx/Bzk2tM1aP3yiYiw=
github.com/ava-labs/avalanchego v1.10.10/go.mod h1:6UA0nxxTvvpyuCbP2DSzx9+7uWQfQx9DPApK8JptLiE=
github.com/ava-labs/coreth v0.12.5-rc.6 h1:OajGUyKkO5Q82XSuMa8T5UD6QywtCHUiZ4Tv3RFmRBU=
github.com/ava-labs/coreth v0.12.5-rc.6/go.mod h1:s5wVyy+5UCCk2m0Tq3jVmy0UqOpKBDYqRE13gInCJVs=
github.com/ava-labs/wazero v0.0.2-hypersdk h1:zsl0saXFEU/dnZ7/cFVDXoSKeavzjrqv1PoR/vKaKmY=
github.com/ava-labs/wazero v0.0.2-hypersdk/go.mod h1:0U0G41+ochRKoPKCJlh0jMg1CHkyfK8kDqiirMmKY8A=
github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down Expand Up @@ -95,6 +93,8 @@ github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku
github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/bytecodealliance/wasmtime-go/v13 v13.0.0 h1:o2PsUgSu6vMKr5S0+mz8EL3mZGQ0M8gHwS8/R0wY/wY=
github.com/bytecodealliance/wasmtime-go/v13 v13.0.0/go.mod h1:KmsZLdjjzNH/E5wbfoRehqP70tHzKlfNOi730VCAR4E=
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
Expand Down
1 change: 0 additions & 1 deletion scripts/mocks.mockgen.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,3 @@ github.com/ava-labs/hypersdk/state=Mutable=state/mock_mutable.go
github.com/ava-labs/hypersdk/state=Immutable=state/mock_immutable.go
github.com/ava-labs/hypersdk/state=View=state/mock_view.go
github.com/ava-labs/hypersdk/vm=Controller=vm/mock_controller.go
github.com/ava-labs/hypersdk/x/programs/runtime=Storage=x/programs/runtime/mock_storage.go
197 changes: 197 additions & 0 deletions x/programs/examples/counter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package examples

import (
"context"

"go.uber.org/zap"

"github.com/ava-labs/avalanchego/ids"
"github.com/ava-labs/avalanchego/utils/logging"

"github.com/ava-labs/hypersdk/state"
"github.com/ava-labs/hypersdk/x/programs/examples/storage"
"github.com/ava-labs/hypersdk/x/programs/runtime"
)

func NewCounter(
log logging.Logger,
programBytes []byte,
db state.Mutable,
cfg *runtime.Config,
cfg2 *runtime.Config,
imports runtime.SupportedImports,
) *Counter {
return &Counter{
log: log,
programBytes: programBytes,
cfg: cfg,
cfg2: cfg2,
imports: imports,
db: db,
}
}

type Counter struct {
log logging.Logger
programBytes []byte
cfg *runtime.Config
cfg2 *runtime.Config
imports runtime.SupportedImports
db state.Mutable
}

func (c *Counter) Run(ctx context.Context) error {
rt := runtime.New(c.log, c.cfg, c.imports)
err := rt.Initialize(ctx, c.programBytes)
if err != nil {
return err
}

c.log.Debug("initial meter",
zap.Uint64("balance", rt.Meter().GetBalance()),
)

// simulate create program transaction
programID := ids.GenerateTestID()
err = storage.SetProgram(ctx, c.db, programID, c.programBytes)
if err != nil {
return err
}

programIDPtr, err := runtime.WriteBytes(rt.Memory(), programID[:])
if err != nil {
return err
}

c.log.Debug("new counter program created",
zap.String("id", programID.String()),
)

// generate alice keys
_, aliceKey, err := newKey()
if err != nil {
return err
}

// write alice's key to stack and get pointer
alicePtr, err := newKeyPtr(ctx, aliceKey, rt)
if err != nil {
return err
}

// create counter for alice on program 1
_, err = rt.Call(ctx, "initialize_address", programIDPtr, alicePtr)
if err != nil {
return err
}

result, err := rt.Call(ctx, "get_value", programIDPtr, alicePtr)
if err != nil {
return err
}
c.log.Debug("count",
zap.Uint64("alice", result[0]),
)

// initialize second runtime to create second counter program
rt2 := runtime.New(c.log, c.cfg2, c.imports)
err = rt2.Initialize(ctx, c.programBytes)
if err != nil {
return err
}

// simulate creating second program transaction
program2ID := ids.GenerateTestID()
err = storage.SetProgram(ctx, c.db, program2ID, c.programBytes)
if err != nil {
return err
}

programID2Ptr, err := runtime.WriteBytes(rt2.Memory(), program2ID[:])
if err != nil {
return err
}

c.log.Debug("new counter program created",
zap.String("id", program2ID.String()),
)

// write alice's key to stack and get pointer
alicePtr2, err := newKeyPtr(ctx, aliceKey, rt2)
if err != nil {
return err
}

_, err = rt2.Call(ctx, "initialize_address", programID2Ptr, alicePtr2)
if err != nil {
return err
}

// increment alice's counter on program 2 by 10
_, err = rt2.Call(ctx, "inc", programID2Ptr, alicePtr2, 10)
if err != nil {
return err
}

result, err = rt2.Call(ctx, "get_value", programID2Ptr, alicePtr2)
if err != nil {
return err
}

c.log.Debug("count program 2",
zap.Uint64("alice", result[0]),
)

// stop 2nd runtime as work is done
rt2.Stop()

// increment alice's counter on program 1
_, err = rt.Call(ctx, "inc", programIDPtr, alicePtr, 1)
if err != nil {
return err
}

result, err = rt.Call(ctx, "get_value", programIDPtr, alicePtr)
if err != nil {
return err
}

c.log.Debug("count program 1",
zap.Uint64("alice", result[0]),
)

// write program id 2 to stack of program 1
programID2Ptr, err = runtime.WriteBytes(rt.Memory(), program2ID[:])
if err != nil {
return err
}

// set the max units to the current balance
maxUnits := uint64(20000)
caller := programIDPtr
target := programID2Ptr

// increment alice's counter on program 2 by 5 from program 1
_, err = rt.Call(ctx, "inc_external", caller, target, maxUnits, alicePtr, 5)
if err != nil {
return err
}

result, err = rt.Call(ctx, "get_value_external", caller, target, maxUnits, alicePtr)
if err != nil {
return err
}

c.log.Debug("count from program 2",
zap.Uint64("alice", result[0]),
)

c.log.Debug("remaining balance",
zap.Uint64("unit", rt.Meter().GetBalance()),
)

return nil
}
50 changes: 50 additions & 0 deletions x/programs/examples/counter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (C) 2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package examples

import (
"context"
_ "embed"
"testing"

"github.com/stretchr/testify/require"

"github.com/ava-labs/hypersdk/x/programs/examples/imports/program"
"github.com/ava-labs/hypersdk/x/programs/examples/imports/pstate"
"github.com/ava-labs/hypersdk/x/programs/runtime"
"github.com/ava-labs/hypersdk/x/programs/utils"
)

//go:embed testdata/counter.wasm
var counterProgramBytes []byte

// go test -v -timeout 30s -run ^TestCounterProgram$ github.com/ava-labs/hypersdk/x/programs/examples
func TestCounterProgram(t *testing.T) {
require := require.New(t)
db := utils.NewTestDB()
maxUnits := uint64(50000)

// define supported imports
supported := runtime.NewSupportedImports()
supported.Register("state", func() runtime.Import {
return pstate.New(log, db)
})
supported.Register("program", func() runtime.Import {
return program.New(log, db)
})

cfg, err := runtime.NewConfigBuilder(maxUnits).
WithLimitMaxMemory(18 * runtime.MemoryPageSize). // 18 pages
Build()
require.NoError(err)

cfg2, err := runtime.NewConfigBuilder(maxUnits).
WithLimitMaxMemory(18 * runtime.MemoryPageSize). // 18 pages
Build()
require.NoError(err)

program := NewCounter(log, counterProgramBytes, db, cfg, cfg2, supported.Imports())
err = program.Run(context.Background())
require.NoError(err)
}
64 changes: 0 additions & 64 deletions x/programs/examples/examples.go

This file was deleted.

Loading

0 comments on commit 8ecd682

Please sign in to comment.