Skip to content

Commit

Permalink
feat(logic): call wasm contract from fileSystem
Browse files Browse the repository at this point in the history
  • Loading branch information
bdeneux committed Mar 6, 2023
1 parent b9cd4fb commit 4eb6b47
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 8 deletions.
3 changes: 1 addition & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ func New(
wasmOpts = append(wasmOpts, wasmkeeper.WithVMCacheMetrics(prometheus.DefaultRegisterer))
}

wasmOpts = append(wasmOpts, wasmkeeper.WithQueryPlugins(okp4wasm.CustomQueryPlugins(app.LogicKeeper)))
wasmOpts = append(wasmOpts, wasmkeeper.WithQueryPlugins(okp4wasm.CustomQueryPlugins(&app.LogicKeeper)))

// The last arguments can contain custom message handlers, and custom query handlers,
// if we want to allow any custom callbacks
Expand All @@ -591,7 +591,6 @@ func New(
availableCapabilities,
wasmOpts...,
)

app.LogicKeeper.WasmKeeper = app.WasmKeeper

govRouter := govv1beta1.NewRouter()
Expand Down
2 changes: 1 addition & 1 deletion app/wasm/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type customQuery struct {

// CustomQueryPlugins creates a wasm QueryPlugins containing the custom querier managing wasm contracts queries to the
// logic module.
func CustomQueryPlugins(logicKeeper logickeeper.Keeper) *wasmkeeper.QueryPlugins {
func CustomQueryPlugins(logicKeeper *logickeeper.Keeper) *wasmkeeper.QueryPlugins {
return &wasmkeeper.QueryPlugins{
Custom: makeCustomQuerier(
logicwasm.MakeLogicQuerier(logicKeeper),
Expand Down
93 changes: 91 additions & 2 deletions x/logic/interpreter/fs/fs.go
Original file line number Diff line number Diff line change
@@ -1,24 +1,113 @@
package fs

import (
goctx "context"
"encoding/base64"
"encoding/json"
"fmt"
"io/fs"
"time"

sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/okp4/okp4d/x/logic/types"
)

type FileSystem struct {
ctx goctx.Context
wasmKeeper types.WasmKeeper
}

// New return a new FileSystem object that will handle all virtual file on the interpreter.
// File can be provided from different sources like CosmWasm cw-storage smart contract.
func New(keeper types.WasmKeeper) FileSystem {
func New(ctx goctx.Context, keeper types.WasmKeeper) FileSystem {
return FileSystem{
ctx: ctx,
wasmKeeper: keeper,
}
}

func (f FileSystem) Open(name string) (fs.File, error) {
return nil, fmt.Errorf("not implemented")
data, err := f.ReadFile(name)
return Object(data), err
}

// ReadFile reads the named file and returns its contents.
// A successful call returns a nil error, not io.EOF.
// (Because ReadFi le reads the whole file, the expected EOF
// from the final Read is not treated as an error to be reported.)
//
// The caller is permitted to modify the returned byte slice.
// This method should return a copy of the underlying data.
func (f FileSystem) ReadFile(name string) ([]byte, error) {
sdkCtx := sdk.UnwrapSDKContext(f.ctx)

req := []byte(fmt.Sprintf("{\"object_data\":{\"id\": \"%s\"}}", name))
contractAddr, err := sdk.AccAddressFromBech32("okp415ekvz3qdter33mdnk98v8whv5qdr53yusksnfgc08xd26fpdn3ts8gddht")
if err != nil {
return nil, err
}

data, err := f.wasmKeeper.QuerySmart(sdkCtx, contractAddr, req)
if err != nil {
return nil, err
}
var program string
err = json.Unmarshal(data, &program)
if err != nil {
return nil, err
}

decoded, err := base64.StdEncoding.DecodeString(program)
return decoded, err
}

type Object []byte

type ObjectInfo struct {
name string
size int64
}

func From(object Object) ObjectInfo {
return ObjectInfo{
name: "contract",
size: int64(len(object)),
}
}

func (o ObjectInfo) Name() string {
return o.name
}

func (o ObjectInfo) Size() int64 {
return o.size
}

func (o ObjectInfo) Mode() fs.FileMode {
return fs.ModeIrregular
}

func (o ObjectInfo) ModTime() time.Time {
return time.Now()
}

func (o ObjectInfo) IsDir() bool {
return false
}

func (o ObjectInfo) Sys() any {
return nil
}

func (o Object) Stat() (fs.FileInfo, error) {
return From(o), nil
}

func (o Object) Read(bytes []byte) (int, error) {
//TODO implement me
panic("implement me")
}

func (o Object) Close() error {
return nil
}
2 changes: 1 addition & 1 deletion x/logic/interpreter/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func New(
wasmKeeper types.WasmKeeper,
) (*prolog.Interpreter, error) {
var i prolog.Interpreter
i.FS = fs.New(wasmKeeper)
i.FS = fs.New(ctx, wasmKeeper)

for _, o := range predicates {
if err := Register(&i, o, meter); err != nil {
Expand Down
2 changes: 2 additions & 0 deletions x/logic/keeper/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ func (k Keeper) enhanceContext(ctx goctx.Context) goctx.Context {
sdkCtx = sdkCtx.WithValue(types.AuthKeeperContextKey, k.authKeeper)
sdkCtx = sdkCtx.WithValue(types.BankKeeperContextKey, k.bankKeeper)

sdkCtx = sdkCtx.WithValue(types.WasmKeeperContextKey, k.WasmKeeper)

return sdkCtx
}

Expand Down
36 changes: 36 additions & 0 deletions x/logic/predicate/wasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package predicate

import (
"context"
"encoding/json"
"fmt"

"github.com/ichiban/prolog/engine"
"github.com/okp4/okp4d/x/logic/types"
"github.com/okp4/okp4d/x/logic/util"
)

func QueryWasm(vm *engine.VM, contractAddr engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
return engine.Delay(func(ctx context.Context) *engine.Promise {
sdkContext, err := util.UnwrapSDKContext(ctx)
if err != nil {
return engine.Error(fmt.Errorf("query_wasm/1: %w", err))
}
wasmKeeper := sdkContext.Value(types.WasmKeeperContextKey).(types.WasmKeeper)
addr, err := getBech32(env, contractAddr)
if err != nil {
return engine.Error(fmt.Errorf("query_wasm/1: %w", err))
}

req := []byte("{\"ask\":{\"query\": \"query_wasm('okp410gnd30r45k9658jm7hzxvp8ehz4ptf33tqjnaepwkunev6kax5ks3mnvmf').\"}}")
if !json.Valid(req) {
return engine.Error(fmt.Errorf("query_wasm/1: wasm query must be a valid json"))
}
res, err := wasmKeeper.QuerySmart(sdkContext, addr, req)
if err != nil {
return engine.Error(fmt.Errorf("query_wasm/1: %w", err))
}
fmt.Printf("result %w", string(res))
return engine.Unify(vm, contractAddr, engine.Integer(sdkContext.BlockHeight()), cont, env)
})
}
2 changes: 2 additions & 0 deletions x/logic/types/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ const (
AuthKeeperContextKey = ContextKey("authKeeper")
// BankKeeperContextKey is the context key for the bank keeper.
BankKeeperContextKey = ContextKey("bankKeeper")
// WasmKeeperContextKey is the context key for the wasm keeper.
WasmKeeperContextKey = ContextKey("wasmKeeper")
)
4 changes: 2 additions & 2 deletions x/logic/wasm/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import (
// LogicQuerier ease the bridge between the logic module with the wasm CustomQuerier to allow wasm contracts to query
// the logic module.
type LogicQuerier struct {
k keeper.Keeper
k *keeper.Keeper
}

// MakeLogicQuerier creates a new LogicQuerier based on the logic keeper.
func MakeLogicQuerier(keeper keeper.Keeper) LogicQuerier {
func MakeLogicQuerier(keeper *keeper.Keeper) LogicQuerier {
return LogicQuerier{
k: keeper,
}
Expand Down

0 comments on commit 4eb6b47

Please sign in to comment.