Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions internal/api/lib_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ func TestInitCacheWorksForNonExistentDir(t *testing.T) {
func TestInitCacheErrorsForBrokenDir(t *testing.T) {
// Use colon to make this fail on Windows
// https://gist.github.com/doctaphred/d01d05291546186941e1b7ddc02034d3
// On Unix we should not have permission to create this.
cannotBeCreated := "/foo:bar"
// On Unix we should not have permission to create inside /sys
// which is mounted read-only in most environments.
cannotBeCreated := "/sys/foo:bar"
config := types.VMConfig{
Cache: types.CacheOptions{
BaseDir: cannotBeCreated,
Expand Down
152 changes: 148 additions & 4 deletions internal/wazeroimpl/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package wazeroimpl
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"runtime"
Expand Down Expand Up @@ -106,11 +107,70 @@ func (c *Cache) registerHost(ctx context.Context, store types.KVStore, apiImpl *
store.Delete(key)
}), []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}).Export("db_remove")

// query_external - simplified: returns 0 length
// query_external - calls into the Go querier
builder.NewFunctionBuilder().WithGoModuleFunction(api.GoModuleFunc(func(ctx context.Context, m api.Module, stack []uint64) {
resPtr := uint32(stack[2])
_ = m.Memory().WriteUint32Le(resPtr, 0)
}), []api.ValueType{api.ValueTypeI64, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}).Export("query_external")
gasLimit := uint64(stack[0])
reqPtr := uint32(stack[1])
reqLen := uint32(stack[2])
outPtr := uint32(stack[3])
mem := m.Memory()
req, _ := mem.Read(reqPtr, reqLen)
if q != nil {
res := types.RustQuery(*q, req, gasLimit)
bz, _ := json.Marshal(res)
_ = mem.WriteUint32Le(outPtr, uint32(len(bz)))
mem.Write(outPtr+4, bz)
} else {
_ = mem.WriteUint32Le(outPtr, 0)
}
}), []api.ValueType{api.ValueTypeI64, api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}).Export("query_external")

// humanize_address
builder.NewFunctionBuilder().WithGoModuleFunction(api.GoModuleFunc(func(ctx context.Context, m api.Module, stack []uint64) {
srcPtr := uint32(stack[0])
srcLen := uint32(stack[1])
outPtr := uint32(stack[2])
mem := m.Memory()
addr, _ := mem.Read(srcPtr, srcLen)
if apiImpl != nil {
res, _, err := apiImpl.HumanizeAddress(addr)
if err == nil {
_ = mem.WriteUint32Le(outPtr, uint32(len(res)))
mem.Write(outPtr+4, []byte(res))
return
}
}
_ = mem.WriteUint32Le(outPtr, 0)
}), []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}).Export("humanize_address")

// canonicalize_address
builder.NewFunctionBuilder().WithGoModuleFunction(api.GoModuleFunc(func(ctx context.Context, m api.Module, stack []uint64) {
srcPtr := uint32(stack[0])
srcLen := uint32(stack[1])
outPtr := uint32(stack[2])
mem := m.Memory()
addrBytes, _ := mem.Read(srcPtr, srcLen)
if apiImpl != nil {
res, _, err := apiImpl.CanonicalizeAddress(string(addrBytes))
if err == nil {
_ = mem.WriteUint32Le(outPtr, uint32(len(res)))
mem.Write(outPtr+4, res)
return
}
}
_ = mem.WriteUint32Le(outPtr, 0)
}), []api.ValueType{api.ValueTypeI32, api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}).Export("canonicalize_address")

// validate_address
builder.NewFunctionBuilder().WithGoModuleFunction(api.GoModuleFunc(func(ctx context.Context, m api.Module, stack []uint64) {
srcPtr := uint32(stack[0])
srcLen := uint32(stack[1])
mem := m.Memory()
addrBytes, _ := mem.Read(srcPtr, srcLen)
if apiImpl != nil {
_, _ = apiImpl.ValidateAddress(string(addrBytes))
}
}), []api.ValueType{api.ValueTypeI32, api.ValueTypeI32}, []api.ValueType{}).Export("validate_address")

return builder.Instantiate(ctx)
}
Expand Down Expand Up @@ -154,3 +214,87 @@ func (c *Cache) Execute(ctx context.Context, checksum types.Checksum, env, info,
}
return err
}

// callFunc instantiates the module and executes the given exported function name.
func (c *Cache) callFunc(ctx context.Context, checksum types.Checksum, funcName string, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
compiled, ok := c.getModule(checksum)
if !ok {
return fmt.Errorf("module not found")
}
_, err := c.registerHost(ctx, store, apiImpl, q, gm)
if err != nil {
return err
}
mod, err := c.runtime.InstantiateModule(ctx, compiled, wazero.NewModuleConfig())
if err != nil {
return err
}
if fn := mod.ExportedFunction(funcName); fn != nil {
_, err = fn.Call(ctx)
}
return err
}

func (c *Cache) Query(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "query", store, apiImpl, q, gm)
}

func (c *Cache) Migrate(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "migrate", store, apiImpl, q, gm)
}

func (c *Cache) Sudo(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "sudo", store, apiImpl, q, gm)
}

func (c *Cache) Reply(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "reply", store, apiImpl, q, gm)
}

func (c *Cache) IBCChannelOpen(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "ibc_channel_open", store, apiImpl, q, gm)
}

func (c *Cache) IBCChannelConnect(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "ibc_channel_connect", store, apiImpl, q, gm)
}

func (c *Cache) IBCChannelClose(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "ibc_channel_close", store, apiImpl, q, gm)
}

func (c *Cache) IBCPacketReceive(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "ibc_packet_receive", store, apiImpl, q, gm)
}

func (c *Cache) IBCPacketAck(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "ibc_packet_ack", store, apiImpl, q, gm)
}

func (c *Cache) IBCPacketTimeout(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "ibc_packet_timeout", store, apiImpl, q, gm)
}

func (c *Cache) IBCSourceCallback(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "ibc_source_callback", store, apiImpl, q, gm)
}

func (c *Cache) IBCDestinationCallback(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "ibc_destination_callback", store, apiImpl, q, gm)
}

func (c *Cache) IBC2PacketReceive(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "ibc2_packet_receive", store, apiImpl, q, gm)
}

func (c *Cache) IBC2PacketAck(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "ibc2_packet_ack", store, apiImpl, q, gm)
}

func (c *Cache) IBC2PacketTimeout(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "ibc2_packet_timeout", store, apiImpl, q, gm)
}

func (c *Cache) IBC2PacketSend(ctx context.Context, checksum types.Checksum, store types.KVStore, apiImpl *types.GoAPI, q *types.Querier, gm types.GasMeter) error {
return c.callFunc(ctx, checksum, "ibc2_packet_send", store, apiImpl, q, gm)
}
86 changes: 69 additions & 17 deletions lib_libwasmvm_wazero.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,69 +122,121 @@ func (vm *VM) Execute(checksum Checksum, env types.Env, info types.MessageInfo,
}

func (vm *VM) Query(checksum Checksum, env types.Env, queryMsg []byte, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.QueryResult, uint64, error) {
return nil, 0, fmt.Errorf("Query not supported in wazero VM")
if err := vm.cache.Query(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.QueryResult{}, 0, nil
}

func (vm *VM) Migrate(checksum Checksum, env types.Env, migrateMsg []byte, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.ContractResult, uint64, error) {
return nil, 0, fmt.Errorf("Migrate not supported in wazero VM")
if err := vm.cache.Migrate(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.ContractResult{}, 0, nil
}

func (vm *VM) MigrateWithInfo(checksum Checksum, env types.Env, migrateMsg []byte, migrateInfo types.MigrateInfo, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.ContractResult, uint64, error) {
return nil, 0, fmt.Errorf("MigrateWithInfo not supported in wazero VM")
// reuse migrate for now
if err := vm.cache.Migrate(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.ContractResult{}, 0, nil
}

func (vm *VM) Sudo(checksum Checksum, env types.Env, sudoMsg []byte, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.ContractResult, uint64, error) {
return nil, 0, fmt.Errorf("Sudo not supported in wazero VM")
if err := vm.cache.Sudo(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.ContractResult{}, 0, nil
}

func (vm *VM) Reply(checksum Checksum, env types.Env, reply types.Reply, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.ContractResult, uint64, error) {
return nil, 0, fmt.Errorf("Reply not supported in wazero VM")
if err := vm.cache.Reply(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.ContractResult{}, 0, nil
}

func (vm *VM) IBCChannelOpen(checksum Checksum, env types.Env, msg types.IBCChannelOpenMsg, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.IBCChannelOpenResult, uint64, error) {
return nil, 0, fmt.Errorf("IBCChannelOpen not supported in wazero VM")
if err := vm.cache.IBCChannelOpen(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.IBCChannelOpenResult{}, 0, nil
}

func (vm *VM) IBCChannelConnect(checksum Checksum, env types.Env, msg types.IBCChannelConnectMsg, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.IBCBasicResult, uint64, error) {
return nil, 0, fmt.Errorf("IBCChannelConnect not supported in wazero VM")
if err := vm.cache.IBCChannelConnect(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.IBCBasicResult{}, 0, nil
}

func (vm *VM) IBCChannelClose(checksum Checksum, env types.Env, msg types.IBCChannelCloseMsg, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.IBCBasicResult, uint64, error) {
return nil, 0, fmt.Errorf("IBCChannelClose not supported in wazero VM")
if err := vm.cache.IBCChannelClose(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.IBCBasicResult{}, 0, nil
}

func (vm *VM) IBCPacketReceive(checksum Checksum, env types.Env, msg types.IBCPacketReceiveMsg, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.IBCReceiveResult, uint64, error) {
return nil, 0, fmt.Errorf("IBCPacketReceive not supported in wazero VM")
if err := vm.cache.IBCPacketReceive(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.IBCReceiveResult{}, 0, nil
}

func (vm *VM) IBCPacketAck(checksum Checksum, env types.Env, msg types.IBCPacketAckMsg, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.IBCBasicResult, uint64, error) {
return nil, 0, fmt.Errorf("IBCPacketAck not supported in wazero VM")
if err := vm.cache.IBCPacketAck(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.IBCBasicResult{}, 0, nil
}

func (vm *VM) IBCPacketTimeout(checksum Checksum, env types.Env, msg types.IBCPacketTimeoutMsg, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.IBCBasicResult, uint64, error) {
return nil, 0, fmt.Errorf("IBCPacketTimeout not supported in wazero VM")
if err := vm.cache.IBCPacketTimeout(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.IBCBasicResult{}, 0, nil
}

func (vm *VM) IBCSourceCallback(checksum Checksum, env types.Env, msg types.IBCSourceCallbackMsg, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.IBCBasicResult, uint64, error) {
return nil, 0, fmt.Errorf("IBCSourceCallback not supported in wazero VM")
if err := vm.cache.IBCSourceCallback(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.IBCBasicResult{}, 0, nil
}

func (vm *VM) IBCDestinationCallback(checksum Checksum, env types.Env, msg types.IBCDestinationCallbackMsg, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.IBCBasicResult, uint64, error) {
return nil, 0, fmt.Errorf("IBCDestinationCallback not supported in wazero VM")
if err := vm.cache.IBCDestinationCallback(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.IBCBasicResult{}, 0, nil
}

func (vm *VM) IBC2PacketAck(checksum Checksum, env types.Env, msg types.IBC2AcknowledgeMsg, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.IBCBasicResult, uint64, error) {
return nil, 0, fmt.Errorf("IBC2PacketAck not supported in wazero VM")
if err := vm.cache.IBC2PacketAck(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.IBCBasicResult{}, 0, nil
}

func (vm *VM) IBC2PacketReceive(checksum Checksum, env types.Env, msg types.IBC2PacketReceiveMsg, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.IBCReceiveResult, uint64, error) {
return nil, 0, fmt.Errorf("IBC2PacketReceive not supported in wazero VM")
if err := vm.cache.IBC2PacketReceive(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.IBCReceiveResult{}, 0, nil
}

func (vm *VM) IBC2PacketTimeout(checksum Checksum, env types.Env, msg types.IBC2PacketTimeoutMsg, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.IBCBasicResult, uint64, error) {
return nil, 0, fmt.Errorf("IBC2PacketTimeout not supported in wazero VM")
if err := vm.cache.IBC2PacketTimeout(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.IBCBasicResult{}, 0, nil
}

func (vm *VM) IBC2PacketSend(checksum Checksum, env types.Env, msg types.IBC2PacketSendMsg, store KVStore, goapi GoAPI, querier Querier, gasMeter GasMeter, gasLimit uint64, deserCost types.UFraction) (*types.IBCBasicResult, uint64, error) {
return nil, 0, fmt.Errorf("IBC2PacketSend not supported in wazero VM")
if err := vm.cache.IBC2PacketSend(context.Background(), checksum, store, &goapi, &querier, gasMeter); err != nil {
return nil, 0, err
}
return &types.IBCBasicResult{}, 0, nil
}
Loading