From 0df98bf44a8294fd20830471897a7f77f2aaf750 Mon Sep 17 00:00:00 2001 From: BiPhan4 Date: Fri, 26 Jul 2024 20:28:35 -0400 Subject: [PATCH 01/13] directly import wasmvm --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 9772ebbc..ddbf6d62 100644 --- a/go.mod +++ b/go.mod @@ -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 From bad26a1b6f5284c2398fe0074638ba13a5bbf73d Mon Sep 17 00:00:00 2001 From: BiPhan4 Date: Fri, 26 Jul 2024 20:35:11 -0400 Subject: [PATCH 02/13] docker file uses correct go version --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0f9d5a67..6dceadbc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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 From 804e257943e36a5faeb46f5ae96a8ac3a690b9e9 Mon Sep 17 00:00:00 2001 From: BiPhan4 Date: Wed, 31 Jul 2024 17:41:57 -0400 Subject: [PATCH 03/13] add wasm bindings --- app/app.go | 3 ++ wasmbinding/bindings/msg.go | 16 ++++++ wasmbinding/message_plugin.go | 98 +++++++++++++++++++++++++++++++++++ wasmbinding/wasm.go | 34 ++++++++++++ 4 files changed, 151 insertions(+) create mode 100644 wasmbinding/bindings/msg.go create mode 100644 wasmbinding/message_plugin.go create mode 100644 wasmbinding/wasm.go diff --git a/app/app.go b/app/app.go index 48890290..3237982e 100644 --- a/app/app.go +++ b/app/app.go @@ -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" @@ -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], diff --git a/wasmbinding/bindings/msg.go b/wasmbinding/bindings/msg.go new file mode 100644 index 00000000..e89d1bd4 --- /dev/null +++ b/wasmbinding/bindings/msg.go @@ -0,0 +1,16 @@ +package bindings + +type JackalMsg struct { + /// Contracts can create files + /// will they be namespaced under the contract's address? + /// A contract may create any number of independent files. + PostKey *PostKey `json:"post_key,omitempty"` +} + +// WARNING DANGER +// NOTE: Sender can currently be spoofed +// We have notes everywhere to flesh out different authentication methods +type PostKey struct { + Sender string `json:"sender"` + Key string `json:"key"` +} diff --git a/wasmbinding/message_plugin.go b/wasmbinding/message_plugin.go new file mode 100644 index 00000000..823565d3 --- /dev/null +++ b/wasmbinding/message_plugin.go @@ -0,0 +1,98 @@ +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" + filetreetypes "github.com/jackalLabs/canine-chain/v4/x/filetree/types" + + storagekeeper "github.com/jackalLabs/canine-chain/v4/x/storage/keeper" +) + +// 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: The last arg--'sender' string--was something we could use when running our fork of wasmd because we added it to wasmd's Messenger +// interface + +// 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 /*sender string*/) ([]sdk.Event, [][]byte, error) { + if msg.Custom != nil { + // only handle the happy path where this is really posting files + // leave everything else for the wrapped version + + // TODO: retrieve the tx signer from the ctx and authenticate it against the 'sender' param of the CosmosMsg above + 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.PostKey != nil { + return m.postKey(ctx, contractAddr, contractMsg.PostKey, contractMsg.PostKey.Sender) + + } + } + return m.wrapped.DispatchMsg(ctx, contractAddr, contractIBCPortID, msg) + +} + +// postKey posts a user's public key on chain for the encryption scheme +func (m *CustomMessenger) postKey(ctx sdk.Context, contractAddr sdk.AccAddress, postKey *bindings.PostKey, sender string) ([]sdk.Event, [][]byte, error) { + err := PerformPostKey(m.filetree, ctx, contractAddr, postKey, sender) + if err != nil { + return nil, nil, sdkerrors.Wrap(err, "perform post key") + } + return nil, nil, nil +} + +func PerformPostKey(f *filetreekeeper.Keeper, ctx sdk.Context, contractAddr sdk.AccAddress, postKey *bindings.PostKey, sender string) error { + if postKey == nil { + return wasmvmtypes.InvalidRequest{Err: "post key null error"} + } + + sdkMsg := filetreetypes.NewMsgPostKey( + sender, + postKey.Key, + ) + + if err := sdkMsg.ValidateBasic(); err != nil { + return err + } + + msgServer := filetreekeeper.NewMsgServerImpl(*f) + _, err := msgServer.PostKey(sdk.WrapSDKContext(ctx), sdkMsg) + if err != nil { + return sdkerrors.Wrap(err, "post key error from message") + } + + return nil +} diff --git a/wasmbinding/wasm.go b/wasmbinding/wasm.go new file mode 100644 index 00000000..0c1fbe12 --- /dev/null +++ b/wasmbinding/wasm.go @@ -0,0 +1,34 @@ +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 { + // NOTE: can we add this in later so we have less code to manage? + + // wasmQueryPlugin := NewQueryPlugin(filetree) + + // queryPluginOpt := wasmkeeper.WithQueryPlugins(&wasmkeeper.QueryPlugins{ + // Custom: CustomQuerier(wasmQueryPlugin), + // }) + + messengerDecoratorOpt := wasmkeeper.WithMessageHandlerDecorator( + CustomMessageDecorator(filetree, storage), + ) + + return []wasm.Option{ + messengerDecoratorOpt, + } + +} From c60a6b10a481b85750e909813307b674235d0416 Mon Sep 17 00:00:00 2001 From: BiPhan4 Date: Thu, 29 Aug 2024 11:48:54 -0400 Subject: [PATCH 04/13] remove sender --- wasmbinding/message_plugin.go | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/wasmbinding/message_plugin.go b/wasmbinding/message_plugin.go index 823565d3..13f06fac 100644 --- a/wasmbinding/message_plugin.go +++ b/wasmbinding/message_plugin.go @@ -44,7 +44,15 @@ var _ wasmkeeper.Messenger = (*CustomMessenger)(nil) // 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 /*sender string*/) ([]sdk.Event, [][]byte, error) { +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 + // NOTE: retrieve public key/signature of braodcaster and compare it to the 'sender' field + + // Idea: Use the contractAddr for the creator of the postKey + // If factory contract calls its child bindings contract + // Yes, the sender of the cross-contract call will be the factory address + // But the child bindings contractAddr will still get propagated to this DispatchMsg function if msg.Custom != nil { // only handle the happy path where this is really posting files // leave everything else for the wrapped version @@ -66,21 +74,24 @@ func (m *CustomMessenger) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddre } // postKey posts a user's public key on chain for the encryption scheme -func (m *CustomMessenger) postKey(ctx sdk.Context, contractAddr sdk.AccAddress, postKey *bindings.PostKey, sender string) ([]sdk.Event, [][]byte, error) { - err := PerformPostKey(m.filetree, ctx, contractAddr, postKey, sender) +func (m *CustomMessenger) postKey(ctx sdk.Context, contractAddr sdk.AccAddress, postKey *bindings.PostKey) ([]sdk.Event, [][]byte, error) { + err := PerformPostKey(m.filetree, ctx, contractAddr, postKey) if err != nil { return nil, nil, sdkerrors.Wrap(err, "perform post key") } return nil, nil, nil } -func PerformPostKey(f *filetreekeeper.Keeper, ctx sdk.Context, contractAddr sdk.AccAddress, postKey *bindings.PostKey, sender string) error { +func PerformPostKey(f *filetreekeeper.Keeper, ctx sdk.Context, contractAddr sdk.AccAddress, postKey *bindings.PostKey) error { + // Use The contractAddr as the sender? + // Can't make CosmWasm permissioned, otherwise devs can't use it + // if postKey == nil { return wasmvmtypes.InvalidRequest{Err: "post key null error"} } sdkMsg := filetreetypes.NewMsgPostKey( - sender, + "sender", postKey.Key, ) From 6c790ce73f78721cd5e306d2af890cd3c9103c37 Mon Sep 17 00:00:00 2001 From: BiPhan4 Date: Thu, 29 Aug 2024 11:54:36 -0400 Subject: [PATCH 05/13] use contract address for creator field --- wasmbinding/message_plugin.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wasmbinding/message_plugin.go b/wasmbinding/message_plugin.go index 13f06fac..503e0c26 100644 --- a/wasmbinding/message_plugin.go +++ b/wasmbinding/message_plugin.go @@ -65,7 +65,7 @@ func (m *CustomMessenger) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddre } if contractMsg.PostKey != nil { - return m.postKey(ctx, contractAddr, contractMsg.PostKey, contractMsg.PostKey.Sender) + return m.postKey(ctx, contractAddr, contractMsg.PostKey) } } @@ -91,7 +91,7 @@ func PerformPostKey(f *filetreekeeper.Keeper, ctx sdk.Context, contractAddr sdk. } sdkMsg := filetreetypes.NewMsgPostKey( - "sender", + contractAddr.String(), postKey.Key, ) From d2560922c283a7ccd32349aa5948396959e775d8 Mon Sep 17 00:00:00 2001 From: BiPhan4 Date: Mon, 9 Sep 2024 20:40:43 -0400 Subject: [PATCH 06/13] add postFile bindings --- wasmbinding/bindings/msg.go | 24 +++++++++++------ wasmbinding/message_plugin.go | 50 +++++++++++++++++++++++++++++------ wasmbinding/wasm.go | 2 +- 3 files changed, 59 insertions(+), 17 deletions(-) diff --git a/wasmbinding/bindings/msg.go b/wasmbinding/bindings/msg.go index e89d1bd4..df13ab7c 100644 --- a/wasmbinding/bindings/msg.go +++ b/wasmbinding/bindings/msg.go @@ -1,16 +1,24 @@ package bindings type JackalMsg struct { - /// Contracts can create files - /// will they be namespaced under the contract's address? - /// A contract may create any number of independent files. + /// Contracts can have a PubKey PostKey *PostKey `json:"post_key,omitempty"` + /// Contracts can make Files + PostFile *PostFile `json:"post_file,omitempty"` } -// WARNING DANGER -// NOTE: Sender can currently be spoofed -// We have notes everywhere to flesh out different authentication methods +// NOTE: Creator field is automatically the contract address type PostKey struct { - Sender string `json:"sender"` - Key string `json:"key"` + Key string `json:"key"` +} + +// NOTE: Creator field is automatically the contract address +type PostFile struct { + Merkle []byte `json:"merkle"` + FileSize int64 `json:"file_size"` + ProofInterval int64 `json:"proof_interval"` + ProofType int64 `json:"proof_type"` + MaxProofs int64 `json:"max_proofs"` + Expires int64 `json:"expires"` + Note string `json:"note"` } diff --git a/wasmbinding/message_plugin.go b/wasmbinding/message_plugin.go index 503e0c26..46405474 100644 --- a/wasmbinding/message_plugin.go +++ b/wasmbinding/message_plugin.go @@ -13,6 +13,7 @@ import ( filetreetypes "github.com/jackalLabs/canine-chain/v4/x/filetree/types" 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 @@ -39,20 +40,12 @@ var _ wasmkeeper.Messenger = (*CustomMessenger)(nil) // 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: The last arg--'sender' string--was something we could use when running our fork of wasmd because we added it to wasmd's Messenger -// interface - // 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 - // NOTE: retrieve public key/signature of braodcaster and compare it to the 'sender' field - // Idea: Use the contractAddr for the creator of the postKey - // If factory contract calls its child bindings contract - // Yes, the sender of the cross-contract call will be the factory address - // But the child bindings contractAddr will still get propagated to this DispatchMsg function if msg.Custom != nil { // only handle the happy path where this is really posting files // leave everything else for the wrapped version @@ -66,7 +59,10 @@ func (m *CustomMessenger) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddre if contractMsg.PostKey != nil { return m.postKey(ctx, contractAddr, contractMsg.PostKey) + } + if contractMsg.PostFile != nil { + return m.postFile(ctx, contractAddr, contractMsg.PostFile) } } return m.wrapped.DispatchMsg(ctx, contractAddr, contractIBCPortID, msg) @@ -107,3 +103,41 @@ func PerformPostKey(f *filetreekeeper.Keeper, ctx sdk.Context, contractAddr sdk. return nil } + +// postFile posts a File to the storage module +func (m *CustomMessenger) postFile(ctx sdk.Context, contractAddr sdk.AccAddress, postFile *bindings.PostFile) ([]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 *bindings.PostFile) error { + + if PostFile == nil { + return wasmvmtypes.InvalidRequest{Err: "post file null error"} + } + + sdkMsg := storagetypes.NewMsgPostFile( + contractAddr.String(), + PostFile.Merkle, + PostFile.FileSize, + PostFile.ProofInterval, + PostFile.ProofType, + PostFile.MaxProofs, + PostFile.Note, + ) + + if err := sdkMsg.ValidateBasic(); err != nil { + return err + } + + msgServer := storagekeeper.NewMsgServerImpl(*s) + _, err := msgServer.PostFile(sdk.WrapSDKContext(ctx), sdkMsg) + if err != nil { + return sdkerrors.Wrap(err, "post file error from message") + } + + return nil +} diff --git a/wasmbinding/wasm.go b/wasmbinding/wasm.go index 0c1fbe12..cd664ad5 100644 --- a/wasmbinding/wasm.go +++ b/wasmbinding/wasm.go @@ -15,7 +15,7 @@ func RegisterCustomPlugins( filetree *filetreekeeper.Keeper, storage *storagekeeper.Keeper, ) []wasmkeeper.Option { - // NOTE: can we add this in later so we have less code to manage? + // NOTE: can add the query in later if needed, but I don't think it's needed. // wasmQueryPlugin := NewQueryPlugin(filetree) From 8695a3e74df08559516f450e625f1a09d277b17c Mon Sep 17 00:00:00 2001 From: BiPhan4 Date: Tue, 10 Sep 2024 11:59:00 -0400 Subject: [PATCH 07/13] temporarily replace merkle with string for debugging --- wasmbinding/bindings/msg.go | 2 +- wasmbinding/message_plugin.go | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/wasmbinding/bindings/msg.go b/wasmbinding/bindings/msg.go index df13ab7c..d641800a 100644 --- a/wasmbinding/bindings/msg.go +++ b/wasmbinding/bindings/msg.go @@ -14,7 +14,7 @@ type PostKey struct { // NOTE: Creator field is automatically the contract address type PostFile struct { - Merkle []byte `json:"merkle"` + Merkle string `json:"merkle"` FileSize int64 `json:"file_size"` ProofInterval int64 `json:"proof_interval"` ProofType int64 `json:"proof_type"` diff --git a/wasmbinding/message_plugin.go b/wasmbinding/message_plugin.go index 46405474..cd37da31 100644 --- a/wasmbinding/message_plugin.go +++ b/wasmbinding/message_plugin.go @@ -119,9 +119,11 @@ func PerformPostFile(s *storagekeeper.Keeper, ctx sdk.Context, contractAddr sdk. return wasmvmtypes.InvalidRequest{Err: "post file null error"} } + placeholderByteArray := []byte{0x01, 0x02, 0xAB, 0xFF, 0x10} + sdkMsg := storagetypes.NewMsgPostFile( contractAddr.String(), - PostFile.Merkle, + placeholderByteArray, PostFile.FileSize, PostFile.ProofInterval, PostFile.ProofType, From 648099be389f42229c941088b9a9b125ac2d280f Mon Sep 17 00:00:00 2001 From: BiPhan4 Date: Tue, 10 Sep 2024 13:19:28 -0400 Subject: [PATCH 08/13] add buy storage bindings --- wasmbinding/bindings/msg.go | 10 +++++++++ wasmbinding/message_plugin.go | 41 ++++++++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/wasmbinding/bindings/msg.go b/wasmbinding/bindings/msg.go index d641800a..ff8bfb8d 100644 --- a/wasmbinding/bindings/msg.go +++ b/wasmbinding/bindings/msg.go @@ -5,6 +5,8 @@ type JackalMsg struct { PostKey *PostKey `json:"post_key,omitempty"` /// Contracts can make Files PostFile *PostFile `json:"post_file,omitempty"` + /// Contracts can buy storage + BuyStorage *BuyStorage `json:"buy_storage,omitempty"` } // NOTE: Creator field is automatically the contract address @@ -22,3 +24,11 @@ type PostFile struct { Expires int64 `json:"expires"` Note string `json:"note"` } + +// NOTE: Creator field is automatically the contract address +type BuyStorage struct { + ForAddress string `json:"for_address"` + DurationDays int64 `json:"duration_days"` + Bytes int64 `json:"bytes"` + PaymentDenom string `json:"payment_denom"` +} diff --git a/wasmbinding/message_plugin.go b/wasmbinding/message_plugin.go index cd37da31..6e4fd38a 100644 --- a/wasmbinding/message_plugin.go +++ b/wasmbinding/message_plugin.go @@ -64,9 +64,12 @@ func (m *CustomMessenger) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddre if contractMsg.PostFile != nil { return m.postFile(ctx, contractAddr, contractMsg.PostFile) } + + if contractMsg.BuyStorage != nil { + return m.buyStorage(ctx, contractAddr, contractMsg.BuyStorage) + } } return m.wrapped.DispatchMsg(ctx, contractAddr, contractIBCPortID, msg) - } // postKey posts a user's public key on chain for the encryption scheme @@ -143,3 +146,39 @@ func PerformPostFile(s *storagekeeper.Keeper, ctx sdk.Context, contractAddr sdk. return nil } + +// buyStorage buys storage +func (m *CustomMessenger) buyStorage(ctx sdk.Context, contractAddr sdk.AccAddress, buyStorage *bindings.BuyStorage) ([]sdk.Event, [][]byte, error) { + err := PerformBuyStorage(m.storage, ctx, contractAddr, buyStorage) + if err != nil { + return nil, nil, sdkerrors.Wrap(err, "perform buy storage") + } + return nil, nil, nil +} + +func PerformBuyStorage(s *storagekeeper.Keeper, ctx sdk.Context, contractAddr sdk.AccAddress, buyStorage *bindings.BuyStorage) error { + + if buyStorage == nil { + return wasmvmtypes.InvalidRequest{Err: "buy storage null error"} + } + + sdkMsg := storagetypes.NewMsgBuyStorage( + contractAddr.String(), + buyStorage.ForAddress, + buyStorage.DurationDays, + buyStorage.Bytes, + buyStorage.PaymentDenom, + ) + + if err := sdkMsg.ValidateBasic(); err != nil { + return err + } + + msgServer := storagekeeper.NewMsgServerImpl(*s) + _, err := msgServer.BuyStorage(sdk.WrapSDKContext(ctx), sdkMsg) + if err != nil { + return sdkerrors.Wrap(err, "post file error from message") + } + + return nil +} From cd77c66dc56f598a1a32764d6d6c5255e8ef8d7a Mon Sep 17 00:00:00 2001 From: BiPhan4 Date: Tue, 10 Sep 2024 13:20:36 -0400 Subject: [PATCH 09/13] fix: set 'expires' field --- wasmbinding/message_plugin.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wasmbinding/message_plugin.go b/wasmbinding/message_plugin.go index 6e4fd38a..7134e898 100644 --- a/wasmbinding/message_plugin.go +++ b/wasmbinding/message_plugin.go @@ -134,6 +134,8 @@ func PerformPostFile(s *storagekeeper.Keeper, ctx sdk.Context, contractAddr sdk. PostFile.Note, ) + sdkMsg.Expires = PostFile.Expires + if err := sdkMsg.ValidateBasic(); err != nil { return err } From 538140767177bf8570ca77f01e658647a7b0758e Mon Sep 17 00:00:00 2001 From: BiPhan4 Date: Wed, 11 Sep 2024 17:01:40 -0400 Subject: [PATCH 10/13] remove query plugin --- wasmbinding/wasm.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/wasmbinding/wasm.go b/wasmbinding/wasm.go index cd664ad5..fc937cb5 100644 --- a/wasmbinding/wasm.go +++ b/wasmbinding/wasm.go @@ -15,13 +15,6 @@ func RegisterCustomPlugins( filetree *filetreekeeper.Keeper, storage *storagekeeper.Keeper, ) []wasmkeeper.Option { - // NOTE: can add the query in later if needed, but I don't think it's needed. - - // wasmQueryPlugin := NewQueryPlugin(filetree) - - // queryPluginOpt := wasmkeeper.WithQueryPlugins(&wasmkeeper.QueryPlugins{ - // Custom: CustomQuerier(wasmQueryPlugin), - // }) messengerDecoratorOpt := wasmkeeper.WithMessageHandlerDecorator( CustomMessageDecorator(filetree, storage), From f4c8dab7e099408aa7374fa6212af0c35a841109 Mon Sep 17 00:00:00 2001 From: BiPhan4 Date: Wed, 11 Sep 2024 17:01:55 -0400 Subject: [PATCH 11/13] keep only post file bindings --- wasmbinding/bindings/msg.go | 19 +------- wasmbinding/message_plugin.go | 86 +---------------------------------- 2 files changed, 2 insertions(+), 103 deletions(-) diff --git a/wasmbinding/bindings/msg.go b/wasmbinding/bindings/msg.go index ff8bfb8d..38bf039f 100644 --- a/wasmbinding/bindings/msg.go +++ b/wasmbinding/bindings/msg.go @@ -1,22 +1,13 @@ package bindings type JackalMsg struct { - /// Contracts can have a PubKey - PostKey *PostKey `json:"post_key,omitempty"` /// Contracts can make Files PostFile *PostFile `json:"post_file,omitempty"` - /// Contracts can buy storage - BuyStorage *BuyStorage `json:"buy_storage,omitempty"` -} - -// NOTE: Creator field is automatically the contract address -type PostKey struct { - Key string `json:"key"` } // NOTE: Creator field is automatically the contract address type PostFile struct { - Merkle string `json:"merkle"` + Merkle []byte `json:"merkle"` FileSize int64 `json:"file_size"` ProofInterval int64 `json:"proof_interval"` ProofType int64 `json:"proof_type"` @@ -24,11 +15,3 @@ type PostFile struct { Expires int64 `json:"expires"` Note string `json:"note"` } - -// NOTE: Creator field is automatically the contract address -type BuyStorage struct { - ForAddress string `json:"for_address"` - DurationDays int64 `json:"duration_days"` - Bytes int64 `json:"bytes"` - PaymentDenom string `json:"payment_denom"` -} diff --git a/wasmbinding/message_plugin.go b/wasmbinding/message_plugin.go index 7134e898..bffd3a64 100644 --- a/wasmbinding/message_plugin.go +++ b/wasmbinding/message_plugin.go @@ -10,14 +10,12 @@ import ( 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" - filetreetypes "github.com/jackalLabs/canine-chain/v4/x/filetree/types" 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{ @@ -50,63 +48,19 @@ func (m *CustomMessenger) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddre // only handle the happy path where this is really posting files // leave everything else for the wrapped version - // TODO: retrieve the tx signer from the ctx and authenticate it against the 'sender' param of the CosmosMsg above 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.PostKey != nil { - return m.postKey(ctx, contractAddr, contractMsg.PostKey) - } - if contractMsg.PostFile != nil { return m.postFile(ctx, contractAddr, contractMsg.PostFile) } - - if contractMsg.BuyStorage != nil { - return m.buyStorage(ctx, contractAddr, contractMsg.BuyStorage) - } } return m.wrapped.DispatchMsg(ctx, contractAddr, contractIBCPortID, msg) } -// postKey posts a user's public key on chain for the encryption scheme -func (m *CustomMessenger) postKey(ctx sdk.Context, contractAddr sdk.AccAddress, postKey *bindings.PostKey) ([]sdk.Event, [][]byte, error) { - err := PerformPostKey(m.filetree, ctx, contractAddr, postKey) - if err != nil { - return nil, nil, sdkerrors.Wrap(err, "perform post key") - } - return nil, nil, nil -} - -func PerformPostKey(f *filetreekeeper.Keeper, ctx sdk.Context, contractAddr sdk.AccAddress, postKey *bindings.PostKey) error { - // Use The contractAddr as the sender? - // Can't make CosmWasm permissioned, otherwise devs can't use it - // - if postKey == nil { - return wasmvmtypes.InvalidRequest{Err: "post key null error"} - } - - sdkMsg := filetreetypes.NewMsgPostKey( - contractAddr.String(), - postKey.Key, - ) - - if err := sdkMsg.ValidateBasic(); err != nil { - return err - } - - msgServer := filetreekeeper.NewMsgServerImpl(*f) - _, err := msgServer.PostKey(sdk.WrapSDKContext(ctx), sdkMsg) - if err != nil { - return sdkerrors.Wrap(err, "post key error from message") - } - - return nil -} - // postFile posts a File to the storage module func (m *CustomMessenger) postFile(ctx sdk.Context, contractAddr sdk.AccAddress, postFile *bindings.PostFile) ([]sdk.Event, [][]byte, error) { err := PerformPostFile(m.storage, ctx, contractAddr, postFile) @@ -122,11 +76,9 @@ func PerformPostFile(s *storagekeeper.Keeper, ctx sdk.Context, contractAddr sdk. return wasmvmtypes.InvalidRequest{Err: "post file null error"} } - placeholderByteArray := []byte{0x01, 0x02, 0xAB, 0xFF, 0x10} - sdkMsg := storagetypes.NewMsgPostFile( contractAddr.String(), - placeholderByteArray, + PostFile.Merkle, PostFile.FileSize, PostFile.ProofInterval, PostFile.ProofType, @@ -148,39 +100,3 @@ func PerformPostFile(s *storagekeeper.Keeper, ctx sdk.Context, contractAddr sdk. return nil } - -// buyStorage buys storage -func (m *CustomMessenger) buyStorage(ctx sdk.Context, contractAddr sdk.AccAddress, buyStorage *bindings.BuyStorage) ([]sdk.Event, [][]byte, error) { - err := PerformBuyStorage(m.storage, ctx, contractAddr, buyStorage) - if err != nil { - return nil, nil, sdkerrors.Wrap(err, "perform buy storage") - } - return nil, nil, nil -} - -func PerformBuyStorage(s *storagekeeper.Keeper, ctx sdk.Context, contractAddr sdk.AccAddress, buyStorage *bindings.BuyStorage) error { - - if buyStorage == nil { - return wasmvmtypes.InvalidRequest{Err: "buy storage null error"} - } - - sdkMsg := storagetypes.NewMsgBuyStorage( - contractAddr.String(), - buyStorage.ForAddress, - buyStorage.DurationDays, - buyStorage.Bytes, - buyStorage.PaymentDenom, - ) - - if err := sdkMsg.ValidateBasic(); err != nil { - return err - } - - msgServer := storagekeeper.NewMsgServerImpl(*s) - _, err := msgServer.BuyStorage(sdk.WrapSDKContext(ctx), sdkMsg) - if err != nil { - return sdkerrors.Wrap(err, "post file error from message") - } - - return nil -} From 8a74d957f3294057e5f6047af8552e6da6c552a6 Mon Sep 17 00:00:00 2001 From: marston Date: Wed, 11 Sep 2024 21:12:47 -0400 Subject: [PATCH 12/13] linting --- wasmbinding/message_plugin.go | 20 +++++++++----------- wasmbinding/wasm.go | 2 -- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/wasmbinding/message_plugin.go b/wasmbinding/message_plugin.go index bffd3a64..ff115e68 100644 --- a/wasmbinding/message_plugin.go +++ b/wasmbinding/message_plugin.go @@ -41,7 +41,6 @@ var _ wasmkeeper.Messenger = (*CustomMessenger)(nil) // 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 { @@ -70,23 +69,22 @@ func (m *CustomMessenger) postFile(ctx sdk.Context, contractAddr sdk.AccAddress, return nil, nil, nil } -func PerformPostFile(s *storagekeeper.Keeper, ctx sdk.Context, contractAddr sdk.AccAddress, PostFile *bindings.PostFile) error { - - if PostFile == nil { +func PerformPostFile(s *storagekeeper.Keeper, ctx sdk.Context, contractAddr sdk.AccAddress, postFile *bindings.PostFile) error { + if postFile == nil { return wasmvmtypes.InvalidRequest{Err: "post file null error"} } sdkMsg := storagetypes.NewMsgPostFile( contractAddr.String(), - PostFile.Merkle, - PostFile.FileSize, - PostFile.ProofInterval, - PostFile.ProofType, - PostFile.MaxProofs, - PostFile.Note, + postFile.Merkle, + postFile.FileSize, + postFile.ProofInterval, + postFile.ProofType, + postFile.MaxProofs, + postFile.Note, ) - sdkMsg.Expires = PostFile.Expires + sdkMsg.Expires = postFile.Expires if err := sdkMsg.ValidateBasic(); err != nil { return err diff --git a/wasmbinding/wasm.go b/wasmbinding/wasm.go index fc937cb5..8b486e82 100644 --- a/wasmbinding/wasm.go +++ b/wasmbinding/wasm.go @@ -15,7 +15,6 @@ func RegisterCustomPlugins( filetree *filetreekeeper.Keeper, storage *storagekeeper.Keeper, ) []wasmkeeper.Option { - messengerDecoratorOpt := wasmkeeper.WithMessageHandlerDecorator( CustomMessageDecorator(filetree, storage), ) @@ -23,5 +22,4 @@ func RegisterCustomPlugins( return []wasm.Option{ messengerDecoratorOpt, } - } From 70fca98daa812b3998993f013babc64b5512867d Mon Sep 17 00:00:00 2001 From: BiPhan4 Date: Thu, 12 Sep 2024 14:44:36 -0400 Subject: [PATCH 13/13] take post file protobuf type --- wasmbinding/bindings/msg.go | 15 +++------------ wasmbinding/message_plugin.go | 22 +++++++--------------- 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/wasmbinding/bindings/msg.go b/wasmbinding/bindings/msg.go index 38bf039f..fad3b9ac 100644 --- a/wasmbinding/bindings/msg.go +++ b/wasmbinding/bindings/msg.go @@ -1,17 +1,8 @@ package bindings +import storagetypes "github.com/jackalLabs/canine-chain/v4/x/storage/types" + type JackalMsg struct { /// Contracts can make Files - PostFile *PostFile `json:"post_file,omitempty"` -} - -// NOTE: Creator field is automatically the contract address -type PostFile struct { - Merkle []byte `json:"merkle"` - FileSize int64 `json:"file_size"` - ProofInterval int64 `json:"proof_interval"` - ProofType int64 `json:"proof_type"` - MaxProofs int64 `json:"max_proofs"` - Expires int64 `json:"expires"` - Note string `json:"note"` + PostFile *storagetypes.MsgPostFile `json:"post_file,omitempty"` } diff --git a/wasmbinding/message_plugin.go b/wasmbinding/message_plugin.go index ff115e68..8921ce5c 100644 --- a/wasmbinding/message_plugin.go +++ b/wasmbinding/message_plugin.go @@ -61,7 +61,7 @@ func (m *CustomMessenger) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddre } // postFile posts a File to the storage module -func (m *CustomMessenger) postFile(ctx sdk.Context, contractAddr sdk.AccAddress, postFile *bindings.PostFile) ([]sdk.Event, [][]byte, error) { +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") @@ -69,29 +69,21 @@ func (m *CustomMessenger) postFile(ctx sdk.Context, contractAddr sdk.AccAddress, return nil, nil, nil } -func PerformPostFile(s *storagekeeper.Keeper, ctx sdk.Context, contractAddr sdk.AccAddress, postFile *bindings.PostFile) error { +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"} } - sdkMsg := storagetypes.NewMsgPostFile( - contractAddr.String(), - postFile.Merkle, - postFile.FileSize, - postFile.ProofInterval, - postFile.ProofType, - postFile.MaxProofs, - postFile.Note, - ) - - sdkMsg.Expires = postFile.Expires + if postFile.Creator != contractAddr.String() { + return sdkerrors.Wrap(sdkerrors.ErrInvalidAddress, "creator of bindings is not bindings contract address") + } - if err := sdkMsg.ValidateBasic(); err != nil { + if err := postFile.ValidateBasic(); err != nil { return err } msgServer := storagekeeper.NewMsgServerImpl(*s) - _, err := msgServer.PostFile(sdk.WrapSDKContext(ctx), sdkMsg) + _, err := msgServer.PostFile(sdk.WrapSDKContext(ctx), postFile) if err != nil { return sdkerrors.Wrap(err, "post file error from message") }