-
Notifications
You must be signed in to change notification settings - Fork 118
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[x/programs] migrate to wasm runtime to wasmtime and refactor for VM …
…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
Showing
43 changed files
with
2,098 additions
and
1,122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.