Skip to content

Commit

Permalink
feat(logic): handle wasm uri on consult/1 predicate
Browse files Browse the repository at this point in the history
  • Loading branch information
bdeneux committed Mar 8, 2023
1 parent 4eb6b47 commit bbc7aae
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 35 deletions.
37 changes: 6 additions & 31 deletions x/logic/interpreter/fs/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,21 @@ 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
ctx goctx.Context
parser Parser
}

// 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(ctx goctx.Context, keeper types.WasmKeeper) FileSystem {
func New(ctx goctx.Context, handlers []URIHandler) FileSystem {
return FileSystem{
ctx: ctx,
wasmKeeper: keeper,
ctx: ctx,
parser: Parser{handlers},
}
}

Expand All @@ -39,26 +33,7 @@ func (f FileSystem) Open(name string) (fs.File, error) {
// 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
return f.parser.Parse(f.ctx, name)
}

type Object []byte
Expand Down
35 changes: 35 additions & 0 deletions x/logic/interpreter/fs/parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package fs

import (
"context"
"fmt"
"net/url"
)

type URIHandler interface {
CanOpen(ctx context.Context, uri *url.URL) bool
Open(ctx context.Context, uri *url.URL) ([]byte, error)
}

type Parser struct {
Handlers []URIHandler
}

func (p *Parser) Parse(ctx context.Context, name string) ([]byte, error) {
uri, err := url.Parse(name)
if err != nil {
return nil, err
}

if uri.Scheme != "okp4" {
return nil, fmt.Errorf("incompatible schema '%s' for %s", uri.Scheme, name)
}

for _, handler := range p.Handlers {
if handler.CanOpen(ctx, uri) {
return handler.Open(ctx, uri)
}
}

return nil, fmt.Errorf("could not find handler for load %s file", name)
}
64 changes: 64 additions & 0 deletions x/logic/interpreter/fs/wasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package fs

import (
"context"
"encoding/base64"
"encoding/json"
"fmt"
"net/url"
"strings"

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

const queryKey = "query"
const hostName = "wasm"

type WasmFS struct {
wasmKeeper types.WasmKeeper
}

func NewWasmFS(keeper types.WasmKeeper) WasmFS {
return WasmFS{wasmKeeper: keeper}
}

func (w WasmFS) CanOpen(ctx context.Context, uri *url.URL) bool {
return uri.Host == hostName
}

func (w WasmFS) Open(ctx context.Context, uri *url.URL) ([]byte, error) {
sdkCtx := sdk.UnwrapSDKContext(ctx)

paths := strings.SplitAfter(uri.Path, "/")
if len(paths) != 2 {
return nil, fmt.Errorf("incorect path, should contains only contract address : '://wasm/{contractAddr}?query={query}'")
}

contractAddr, err := sdk.AccAddressFromBech32(paths[1])
if err != nil {
return nil, fmt.Errorf("failed convert path '%s' to contract address: %w", uri.Path, err)
}

if !uri.Query().Has(queryKey) {
return nil, fmt.Errorf("uri should contains query params")
}
query := uri.Query().Get(queryKey)

data, err := w.wasmKeeper.QuerySmart(sdkCtx, contractAddr, []byte(query))
if err != nil {
return nil, fmt.Errorf("failed query wasm keeper: %w", err)
}

var program string
err = json.Unmarshal(data, &program)
if err != nil {
return nil, fmt.Errorf("failed unmarshal json wasm response to string: %w", err)
}

decoded, err := base64.StdEncoding.DecodeString(program)
if err != nil {
return nil, fmt.Errorf("failed decode wasm base64 respone: %w", err)
}
return decoded, nil
}
5 changes: 2 additions & 3 deletions x/logic/interpreter/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ichiban/prolog"
"github.com/okp4/okp4d/x/logic/interpreter/fs"
"github.com/okp4/okp4d/x/logic/types"
)

// New creates a new prolog.Interpreter with:
Expand All @@ -22,10 +21,10 @@ func New(
predicates []string,
bootstrap string,
meter sdk.GasMeter,
wasmKeeper types.WasmKeeper,
uriHandlers []fs.URIHandler,
) (*prolog.Interpreter, error) {
var i prolog.Interpreter
i.FS = fs.New(ctx, wasmKeeper)
i.FS = fs.New(ctx, uriHandlers)

for _, o := range predicates {
if err := Register(&i, o, meter); err != nil {
Expand Down
5 changes: 4 additions & 1 deletion x/logic/keeper/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ichiban/prolog"
"github.com/okp4/okp4d/x/logic/interpreter"
"github.com/okp4/okp4d/x/logic/interpreter/fs"
"github.com/okp4/okp4d/x/logic/types"
"github.com/okp4/okp4d/x/logic/util"
)
Expand Down Expand Up @@ -97,12 +98,14 @@ func (k Keeper) newInterpreter(ctx goctx.Context) (*prolog.Interpreter, error) {

interpreterParams := params.GetInterpreter()

wasmHandler := fs.NewWasmFS(k.WasmKeeper)

interpreted, err := interpreter.New(
ctx,
util.NonZeroOrDefault(interpreterParams.GetRegisteredPredicates(), interpreter.RegistryNames),
util.NonZeroOrDefault(interpreterParams.GetBootstrap(), interpreter.Bootstrap()),
sdkctx.GasMeter(),
k.WasmKeeper,
[]fs.URIHandler{wasmHandler},
)

return interpreted, err
Expand Down

0 comments on commit bbc7aae

Please sign in to comment.