Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[x/programs] migrate wasm runtime to wasmtime and refactor for VM integration #477

Merged
merged 49 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
f23db1f
[x/programs] migrate to wasm runtime to wasmtime
hexfusion Sep 20, 2023
3ebbd38
Implement memory with tests
hexfusion Sep 20, 2023
8e01086
Add guest import examples
hexfusion Sep 20, 2023
7cec29b
Add vm/storage examples
hexfusion Sep 20, 2023
eb2c03f
Remove storage mocks
hexfusion Sep 20, 2023
8ed6774
Remove hard coded guest imports
hexfusion Sep 20, 2023
c7a8a34
Update token example to use new runtime
hexfusion Sep 20, 2023
c76d204
Implement guest export client
hexfusion Sep 20, 2023
2303f5c
Add config builder
hexfusion Sep 20, 2023
2b6ce89
React to new implementations
hexfusion Sep 20, 2023
7cf7f75
Implement meter
hexfusion Sep 20, 2023
fc80112
Remove failing tests/examples for now
hexfusion Sep 20, 2023
b79d4af
Fix lints
hexfusion Sep 20, 2023
dd620f3
Add Wasi mod as const
hexfusion Sep 20, 2023
3bf8905
Improve docs around host function imports
hexfusion Sep 20, 2023
d50618c
Add meter and runtime stop tests
hexfusion Sep 20, 2023
9f52536
Add licenses
hexfusion Sep 20, 2023
3de881a
Add precompile function
hexfusion Sep 20, 2023
61d8adb
Add precompile bench
hexfusion Sep 20, 2023
7d77550
Remove cache from precompiled bench
hexfusion Sep 20, 2023
2e68363
nit
hexfusion Sep 20, 2023
d2d2198
Add token program example
hexfusion Sep 20, 2023
579fce5
wip
hexfusion Sep 25, 2023
b14a5a5
remove wasi
hexfusion Oct 3, 2023
949a81d
wip
hexfusion Oct 3, 2023
36c7837
Add state import
hexfusion Oct 3, 2023
3d6fa55
Cleanup token
hexfusion Oct 3, 2023
81541cc
Recompile and update tests
hexfusion Oct 3, 2023
c15bba9
add optimizations that reduce binary size
hexfusion Oct 3, 2023
2691f72
Remove bulk memory from token tests
hexfusion Oct 3, 2023
b363a8b
Add runtime import factory
hexfusion Oct 4, 2023
45382ff
Rename state import module as pstate
hexfusion Oct 4, 2023
df816a7
Add counter program to program example
hexfusion Oct 4, 2023
98837de
Update runtime to use SupportedImports type
hexfusion Oct 4, 2023
cd4b1f0
Update token example
hexfusion Oct 4, 2023
149f568
Cleanup logging
hexfusion Oct 4, 2023
1290d2c
More log cleanup
hexfusion Oct 4, 2023
9aa4c77
Cargo fmt
hexfusion Oct 4, 2023
1b0d4be
Cleanup
hexfusion Oct 4, 2023
2b32009
Merge branch 'main' into wasmtime
hexfusion Oct 4, 2023
7ed5c49
Add RunShort benchmark for token
hexfusion Oct 5, 2023
7656d94
Add max wasm stack test
hexfusion Oct 5, 2023
61af5b1
Cleanup and nits
hexfusion Oct 5, 2023
fa1b0ac
Cleanup storage
hexfusion Oct 6, 2023
e045b56
Define defaults for all configs
hexfusion Oct 6, 2023
7fdaff5
Remove unused file
hexfusion Oct 6, 2023
8eb9122
Document opt-level flag for release profile
hexfusion Oct 6, 2023
574fbbd
Merge branch 'main' into wasmtime
hexfusion Oct 6, 2023
14857d7
Remove todo
hexfusion Oct 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ members = [
resolver = "2"

[profile.release]
opt-level = 3
opt-level = "s"
hexfusion marked this conversation as resolved.
Show resolved Hide resolved
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
hexfusion marked this conversation as resolved.
Show resolved Hide resolved
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
Loading