Skip to content

Commit

Permalink
feat: wasm bindings for evm support (#477)
Browse files Browse the repository at this point in the history
  • Loading branch information
TheMarstonConnell authored Sep 12, 2024
2 parents 8ca23e1 + 70fca98 commit af32726
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# syntax=docker/dockerfile:1
FROM golang:1.21
FROM golang:1.22.2

# Update package list and install jq
RUN apt-get update && apt-get install -y jq
Expand Down
3 changes: 3 additions & 0 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ import (
wasmclient "github.com/CosmWasm/wasmd/x/wasm/client"
wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
wasmappparams "github.com/jackalLabs/canine-chain/v4/app/params"
owasm "github.com/jackalLabs/canine-chain/v4/wasmbinding"

mint "github.com/jackalLabs/canine-chain/v4/x/jklmint"
mintkeeper "github.com/jackalLabs/canine-chain/v4/x/jklmint/keeper"
Expand Down Expand Up @@ -574,6 +575,8 @@ func NewJackalApp(
// The last arguments can contain custom message handlers, and custom query handlers,
// if we want to allow any custom callbacks
supportedFeatures := "iterator,staking,stargate,cosmwasm_1_1,cosmwasm_1_2"

wasmOpts = append(owasm.RegisterCustomPlugins(&app.FileTreeKeeper, &app.StorageKeeper), wasmOpts...)
app.wasmKeeper = wasm.NewKeeper(
appCodec,
keys[wasm.StoreKey],
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.22.2

require (
github.com/CosmWasm/wasmd v0.32.0
github.com/CosmWasm/wasmvm v1.2.6 // indirect
github.com/CosmWasm/wasmvm v1.2.6
github.com/cosmos/cosmos-sdk v0.45.17
github.com/cosmos/ibc-go/v4 v4.6.0
github.com/ecies/go/v2 v2.0.6
Expand Down
8 changes: 8 additions & 0 deletions wasmbinding/bindings/msg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package bindings

import storagetypes "github.com/jackalLabs/canine-chain/v4/x/storage/types"

type JackalMsg struct {
/// Contracts can make Files
PostFile *storagetypes.MsgPostFile `json:"post_file,omitempty"`
}
92 changes: 92 additions & 0 deletions wasmbinding/message_plugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package wasmbinding

import (
"encoding/json"

wasmvmtypes "github.com/CosmWasm/wasmvm/types"
sdk "github.com/cosmos/cosmos-sdk/types"

wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
"github.com/jackalLabs/canine-chain/v4/wasmbinding/bindings"
filetreekeeper "github.com/jackalLabs/canine-chain/v4/x/filetree/keeper"

storagekeeper "github.com/jackalLabs/canine-chain/v4/x/storage/keeper"
storagetypes "github.com/jackalLabs/canine-chain/v4/x/storage/types"
)

// CustomMessageDecorator returns decorator for custom CosmWasm bindings messages
func CustomMessageDecorator(filetree *filetreekeeper.Keeper, storage *storagekeeper.Keeper) func(wasmkeeper.Messenger) wasmkeeper.Messenger {
return func(old wasmkeeper.Messenger) wasmkeeper.Messenger {
return &CustomMessenger{
wrapped: old,
filetree: filetree,
storage: storage,
}
}
}

type CustomMessenger struct {
wrapped wasmkeeper.Messenger
filetree *filetreekeeper.Keeper
storage *storagekeeper.Keeper
}

var _ wasmkeeper.Messenger = (*CustomMessenger)(nil)

// DispatchMsg executes on the contractMsg.
// NOTE: did we ever use the 'contractIBCPortID' before?
// If we can give each bindings contract--owned by a user--an IBC port ID, perhaps we can use that for authenticating the sender?

// NOTE: I think the CosmWasm bindings contract can call this multiple times in a single contract.execute()
// This would be great because we wouldn't need to change the chain code too much
func (m *CustomMessenger) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) ([]sdk.Event, [][]byte, error) {
// If the factory contract calls one of its 'child' bindings contracts, the 'sender' field will automatically be filled in with the factory contract's address

if msg.Custom != nil {
// only handle the happy path where this is really posting files
// leave everything else for the wrapped version

var contractMsg bindings.JackalMsg

if err := json.Unmarshal(msg.Custom, &contractMsg); err != nil {
return nil, nil, sdkerrors.Wrap(err, "Failed to unmarshal CosmosMsg enum variant 'Custom' into jackal msg")
}

if contractMsg.PostFile != nil {
return m.postFile(ctx, contractAddr, contractMsg.PostFile)
}
}
return m.wrapped.DispatchMsg(ctx, contractAddr, contractIBCPortID, msg)
}

// postFile posts a File to the storage module
func (m *CustomMessenger) postFile(ctx sdk.Context, contractAddr sdk.AccAddress, postFile *storagetypes.MsgPostFile) ([]sdk.Event, [][]byte, error) {
err := PerformPostFile(m.storage, ctx, contractAddr, postFile)
if err != nil {
return nil, nil, sdkerrors.Wrap(err, "perform post file")
}
return nil, nil, nil
}

func PerformPostFile(s *storagekeeper.Keeper, ctx sdk.Context, contractAddr sdk.AccAddress, postFile *storagetypes.MsgPostFile) error {
if postFile == nil {
return wasmvmtypes.InvalidRequest{Err: "post file null error"}
}

if postFile.Creator != contractAddr.String() {
return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "creator of bindings is not bindings contract address")
}

if err := postFile.ValidateBasic(); err != nil {
return err
}

msgServer := storagekeeper.NewMsgServerImpl(*s)
_, err := msgServer.PostFile(sdk.WrapSDKContext(ctx), postFile)
if err != nil {
return sdkerrors.Wrap(err, "post file error from message")
}

return nil
}
25 changes: 25 additions & 0 deletions wasmbinding/wasm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package wasmbinding

import (
"github.com/CosmWasm/wasmd/x/wasm"
wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
filetreekeeper "github.com/jackalLabs/canine-chain/v4/x/filetree/keeper"
storagekeeper "github.com/jackalLabs/canine-chain/v4/x/storage/keeper"
)

// WARNING: we're using wasmd from confio and not our fork atm
// wasmd sends custom CosmWasm messages WITHOUT ensuring that the broadcaster is in fact the 'sender' arg of the msg.

func RegisterCustomPlugins(
// We can add in more keepers kere if needed
filetree *filetreekeeper.Keeper,
storage *storagekeeper.Keeper,
) []wasmkeeper.Option {
messengerDecoratorOpt := wasmkeeper.WithMessageHandlerDecorator(
CustomMessageDecorator(filetree, storage),
)

return []wasm.Option{
messengerDecoratorOpt,
}
}

0 comments on commit af32726

Please sign in to comment.