From d715ff8cfbb72a58d93db58207bf27c08170379e Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Thu, 23 May 2024 00:12:21 +0800 Subject: [PATCH 01/15] onion bootstrap --- app/app.go | 40 ++ app/prepare_proposal.go | 39 ++ go.mod | 2 +- proto/kujira/onion/genesis.proto | 10 + proto/kujira/onion/params.proto | 13 + proto/kujira/onion/tx.proto | 25 ++ x/onion/client/cli/query.go | 77 ++++ x/onion/hooks.go | 145 ++++++ x/onion/ibc_module.go | 261 +++++++++++ x/onion/ibcutils.go | 78 ++++ x/onion/ics4_middleware.go | 85 ++++ x/onion/keeper/ibcutils.go | 33 ++ x/onion/keeper/keeper.go | 279 ++++++++++++ x/onion/keeper/msg_server.go | 41 ++ x/onion/sdkmodule.go | 139 ++++++ x/onion/types/codec.go | 38 ++ x/onion/types/errors.go | 21 + x/onion/types/expected_keepers.go | 16 + x/onion/types/genesis.go | 16 + x/onion/types/genesis.pb.go | 321 +++++++++++++ x/onion/types/keys.go | 17 + x/onion/types/msgs.go | 32 ++ x/onion/types/params.go | 62 +++ x/onion/types/params.pb.go | 327 ++++++++++++++ x/onion/types/tx.pb.go | 724 ++++++++++++++++++++++++++++++ x/onion/types/types.go | 85 ++++ x/onion/wasm_hook.go | 381 ++++++++++++++++ 27 files changed, 3306 insertions(+), 1 deletion(-) create mode 100644 app/prepare_proposal.go create mode 100644 proto/kujira/onion/genesis.proto create mode 100644 proto/kujira/onion/params.proto create mode 100644 proto/kujira/onion/tx.proto create mode 100644 x/onion/client/cli/query.go create mode 100644 x/onion/hooks.go create mode 100644 x/onion/ibc_module.go create mode 100644 x/onion/ibcutils.go create mode 100644 x/onion/ics4_middleware.go create mode 100644 x/onion/keeper/ibcutils.go create mode 100644 x/onion/keeper/keeper.go create mode 100644 x/onion/keeper/msg_server.go create mode 100644 x/onion/sdkmodule.go create mode 100644 x/onion/types/codec.go create mode 100644 x/onion/types/errors.go create mode 100644 x/onion/types/expected_keepers.go create mode 100644 x/onion/types/genesis.go create mode 100644 x/onion/types/genesis.pb.go create mode 100644 x/onion/types/keys.go create mode 100644 x/onion/types/msgs.go create mode 100644 x/onion/types/params.go create mode 100644 x/onion/types/params.pb.go create mode 100644 x/onion/types/tx.pb.go create mode 100644 x/onion/types/types.go create mode 100644 x/onion/wasm_hook.go diff --git a/app/app.go b/app/app.go index 834d1c0f..cd6d1448 100644 --- a/app/app.go +++ b/app/app.go @@ -87,6 +87,9 @@ import ( upgradekeeper "github.com/cosmos/cosmos-sdk/x/upgrade/keeper" upgradetypes "github.com/cosmos/cosmos-sdk/x/upgrade/types" + onion "github.com/Team-Kujira/core/x/onion" + onionkeeper "github.com/Team-Kujira/core/x/onion/keeper" + oniontypes "github.com/Team-Kujira/core/x/onion/types" ibcwasm "github.com/cosmos/ibc-go/modules/light-clients/08-wasm" ibcwasmkeeper "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/keeper" ibcwasmtypes "github.com/cosmos/ibc-go/modules/light-clients/08-wasm/types" @@ -295,6 +298,9 @@ type App struct { ConsensusParamsKeeper consensusparamkeeper.Keeper ParamsKeeper paramskeeper.Keeper IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly + OnionKeeper *onionkeeper.Keeper + Ics20WasmHooks *onion.WasmHooks + HooksICS4Wrapper onion.ICS4Middleware IBCFeeKeeper ibcfeekeeper.Keeper ICAControllerKeeper icacontrollerkeeper.Keeper ICAHostKeeper icahostkeeper.Keeper @@ -383,6 +389,7 @@ func New( batchtypes.StoreKey, AllianceStoreKey, cwicatypes.StoreKey, + oniontypes.StoreKey, ) tkeys := sdk.NewTransientStoreKeys(paramstypes.TStoreKey) @@ -546,6 +553,17 @@ func New( scopedIBCKeeper, ) + // Configure the hooks keeper + hooksKeeper := onionkeeper.NewKeeper( + keys[oniontypes.StoreKey], + app.GetSubspace(oniontypes.ModuleName), + app.IBCKeeper.ChannelKeeper, + nil, + ) + app.OnionKeeper = hooksKeeper + + app.WireICS20PreWasmKeeper(appCodec, bApp, app.OnionKeeper) + // IBC Fee Module keeper app.IBCFeeKeeper = ibcfeekeeper.NewKeeper( @@ -704,6 +722,10 @@ func New( wasmOpts..., ) + // Pass the contract keeper to all the structs (generally ICS4Wrappers for ibc middlewares) that need it + app.Ics20WasmHooks.ContractKeeper = &app.WasmKeeper + app.OnionKeeper.ContractKeeper = wasmkeeper.NewDefaultPermissionKeeper(app.WasmKeeper) + // Register the proposal types // Deprecated: Avoid adding new handlers, instead use the new proposal flow // by granting the governance module the right to execute the message. @@ -758,6 +780,7 @@ func New( var transferStack ibcporttypes.IBCModule transferStack = transfer.NewIBCModule(app.TransferKeeper) transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper) + transferStack = onion.NewIBCMiddleware(transferStack, &app.HooksICS4Wrapper) // Create Interchain Accounts Stack // SendPacket, since it is originating from the application to core IBC: @@ -1176,6 +1199,22 @@ func New( return app } +// WireICS20PreWasmKeeper Create the IBC Transfer Stack from bottom to top: +func (app *App) WireICS20PreWasmKeeper( + appCodec codec.Codec, + bApp *baseapp.BaseApp, + hooksKeeper *onionkeeper.Keeper, +) { + // Setup the ICS4Wrapper used by the hooks middleware + addrPrefix := sdk.GetConfig().GetBech32AccountAddrPrefix() + wasmHooks := onion.NewWasmHooks(hooksKeeper, nil, addrPrefix) // The contract keeper needs to be set later + app.Ics20WasmHooks = &wasmHooks + app.HooksICS4Wrapper = onion.NewICS4Middleware( + app.IBCKeeper.ChannelKeeper, + app.Ics20WasmHooks, + ) +} + func (app *App) setPostHandler() { postHandler, err := posthandler.NewPostHandler( posthandler.HandlerOptions{}, @@ -1324,6 +1363,7 @@ func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino paramsKeeper.Subspace(oracletypes.ModuleName) paramsKeeper.Subspace(batchtypes.ModuleName) paramsKeeper.Subspace(alliancemoduletypes.ModuleName) + paramsKeeper.Subspace(oniontypes.ModuleName) return paramsKeeper } diff --git a/app/prepare_proposal.go b/app/prepare_proposal.go new file mode 100644 index 00000000..4e5bba3f --- /dev/null +++ b/app/prepare_proposal.go @@ -0,0 +1,39 @@ +package app + +import ( + "encoding/base64" + + abci "github.com/cometbft/cometbft/abci/types" + ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" +) + +func (app *App) PrepareProposal(req abci.RequestPrepareProposal) abci.ResponsePrepareProposal { + newTxs := [][]byte{} + for _, rawTx := range req.Txs { + tx, err := app.txConfig.TxDecoder()(rawTx) + if err != nil { + continue + } + msgs := tx.GetMsgs() + for _, msg := range msgs { + switch msg := msg.(type) { + case *ibctransfertypes.MsgTransfer: + if msg.Memo != "" { + newRawTx, err := base64.StdEncoding.DecodeString(msg.Memo) + if err != nil { + continue + } + _, err = app.txConfig.TxDecoder()(newRawTx) + if err != nil { + continue + } + newTxs = append(newTxs, newRawTx) + } + } + } + } + txs := append(req.Txs, newTxs...) + return abci.ResponsePrepareProposal{ + Txs: txs, + } +} diff --git a/go.mod b/go.mod index 39a9c8f9..e9d8b041 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( github.com/terra-money/alliance v0.3.5 google.golang.org/genproto/googleapis/api v0.0.0-20231212172506-995d672761c0 google.golang.org/grpc v1.60.1 + google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -181,7 +182,6 @@ require ( google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240108191215-35c7eff3a6b1 // indirect - google.golang.org/protobuf v1.32.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect nhooyr.io/websocket v1.8.6 // indirect diff --git a/proto/kujira/onion/genesis.proto b/proto/kujira/onion/genesis.proto new file mode 100644 index 00000000..f2caa86d --- /dev/null +++ b/proto/kujira/onion/genesis.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; +package kujira.onion; + +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "kujira/onion/params.proto"; + +option go_package = "github.com/Team-Kujira/core/x/onion/types"; + +message GenesisState { Params params = 1 [ (gogoproto.nullable) = false ]; } diff --git a/proto/kujira/onion/params.proto b/proto/kujira/onion/params.proto new file mode 100644 index 00000000..9bbd27d5 --- /dev/null +++ b/proto/kujira/onion/params.proto @@ -0,0 +1,13 @@ +syntax = "proto3"; +package kujira.onion; + +import "gogoproto/gogo.proto"; +import "cosmos_proto/cosmos.proto"; +import "google/protobuf/duration.proto"; + +option go_package = "github.com/Team-Kujira/core/x/onion/types"; + +message Params { + repeated string allowed_async_ack_contracts = 1 + [ (gogoproto.moretags) = "yaml:\"allowed_async_ack_contracts\"" ]; +} diff --git a/proto/kujira/onion/tx.proto b/proto/kujira/onion/tx.proto new file mode 100644 index 00000000..5f8b85e0 --- /dev/null +++ b/proto/kujira/onion/tx.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; +package kujira.onion; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/Team-Kujira/core/x/onion/types"; + +// Msg defines the Msg service. +service Msg { + // EmitIBCAck checks the sender can emit the ack and writes the IBC + // acknowledgement + rpc EmitIBCAck(MsgEmitIBCAck) returns (MsgEmitIBCAckResponse); +} + +message MsgEmitIBCAck { + string sender = 1 [ (gogoproto.moretags) = "yaml:\"sender\"" ]; + uint64 packet_sequence = 2 + [ (gogoproto.moretags) = "yaml:\"packet_sequence\"" ]; + string channel = 3 [ (gogoproto.moretags) = "yaml:\"channel\"" ]; +} +message MsgEmitIBCAckResponse { + string contract_result = 1 + [ (gogoproto.moretags) = "yaml:\"contract_result\"" ]; + string ibc_ack = 2 [ (gogoproto.moretags) = "yaml:\"ibc_ack\"" ]; +} diff --git a/x/onion/client/cli/query.go b/x/onion/client/cli/query.go new file mode 100644 index 00000000..bc3641be --- /dev/null +++ b/x/onion/client/cli/query.go @@ -0,0 +1,77 @@ +package cli + +import ( + "fmt" + "strings" + + "github.com/cosmos/cosmos-sdk/client/flags" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + "github.com/spf13/cobra" + + "github.com/Team-Kujira/core/x/onion/keeper" + + "github.com/Team-Kujira/core/x/onion/types" +) + +func indexRunCmd(cmd *cobra.Command, args []string) error { + usageTemplate := `Usage:{{if .HasAvailableSubCommands}} + {{.CommandPath}} [command]{{end}} + +{{if .HasAvailableSubCommands}}Available Commands:{{range .Commands}}{{if .IsAvailableCommand}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}} + +Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}} +` + cmd.SetUsageTemplate(usageTemplate) + return cmd.Help() +} + +// GetQueryCmd returns the cli query commands for this module. +func GetQueryCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: types.ModuleName, + Short: fmt.Sprintf("Querying commands for the %s module", types.ModuleName), + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: indexRunCmd, + } + + cmd.AddCommand( + GetCmdWasmSender(), + ) + return cmd +} + +// GetCmdPoolParams return pool params. +func GetCmdWasmSender() *cobra.Command { + cmd := &cobra.Command{ + Use: "wasm-sender ", + Short: "Generate the local address for a wasm hooks sender", + Long: strings.TrimSpace( + fmt.Sprintf(`Generate the local address for a wasm hooks sender. +Example: +$ %s query ibc-hooks wasm-hooks-sender channel-42 juno12smx2wdlyttvyzvzg54y2vnqwq2qjatezqwqxu +`, + version.AppName, + ), + ), + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + channelID := args[0] + originalSender := args[1] + // ToDo: Make this flexible as an arg + prefix := sdk.GetConfig().GetBech32AccountAddrPrefix() + senderBech32, err := keeper.DeriveIntermediateSender(channelID, originalSender, prefix) + if err != nil { + return err + } + fmt.Println(senderBech32) + return nil + }, + } + + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/x/onion/hooks.go b/x/onion/hooks.go new file mode 100644 index 00000000..aacadf95 --- /dev/null +++ b/x/onion/hooks.go @@ -0,0 +1,145 @@ +package onion + +import ( + // external libraries + sdk "github.com/cosmos/cosmos-sdk/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + + // ibc-go + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" +) + +type Hooks interface{} + +type OnChanOpenInitOverrideHooks interface { + OnChanOpenInitOverride(im IBCMiddleware, ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string) (string, error) +} +type OnChanOpenInitBeforeHooks interface { + OnChanOpenInitBeforeHook(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string) +} +type OnChanOpenInitAfterHooks interface { + OnChanOpenInitAfterHook(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string, finalVersion string, err error) +} + +// OnChanOpenTry Hooks +type OnChanOpenTryOverrideHooks interface { + OnChanOpenTryOverride(im IBCMiddleware, ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, counterpartyVersion string) (string, error) +} +type OnChanOpenTryBeforeHooks interface { + OnChanOpenTryBeforeHook(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, counterpartyVersion string) +} +type OnChanOpenTryAfterHooks interface { + OnChanOpenTryAfterHook(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, counterpartyVersion string, version string, err error) +} + +// OnChanOpenAck Hooks +type OnChanOpenAckOverrideHooks interface { + OnChanOpenAckOverride(im IBCMiddleware, ctx sdk.Context, portID, channelID string, counterpartyChannelID string, counterpartyVersion string) error +} +type OnChanOpenAckBeforeHooks interface { + OnChanOpenAckBeforeHook(ctx sdk.Context, portID, channelID string, counterpartyChannelID string, counterpartyVersion string) +} +type OnChanOpenAckAfterHooks interface { + OnChanOpenAckAfterHook(ctx sdk.Context, portID, channelID string, counterpartyChannelID string, counterpartyVersion string, err error) +} + +// OnChanOpenConfirm Hooks +type OnChanOpenConfirmOverrideHooks interface { + OnChanOpenConfirmOverride(im IBCMiddleware, ctx sdk.Context, portID, channelID string) error +} +type OnChanOpenConfirmBeforeHooks interface { + OnChanOpenConfirmBeforeHook(ctx sdk.Context, portID, channelID string) +} +type OnChanOpenConfirmAfterHooks interface { + OnChanOpenConfirmAfterHook(ctx sdk.Context, portID, channelID string, err error) +} + +// OnChanCloseInit Hooks +type OnChanCloseInitOverrideHooks interface { + OnChanCloseInitOverride(im IBCMiddleware, ctx sdk.Context, portID, channelID string) error +} +type OnChanCloseInitBeforeHooks interface { + OnChanCloseInitBeforeHook(ctx sdk.Context, portID, channelID string) +} +type OnChanCloseInitAfterHooks interface { + OnChanCloseInitAfterHook(ctx sdk.Context, portID, channelID string, err error) +} + +// OnChanCloseConfirm Hooks +type OnChanCloseConfirmOverrideHooks interface { + OnChanCloseConfirmOverride(im IBCMiddleware, ctx sdk.Context, portID, channelID string) error +} +type OnChanCloseConfirmBeforeHooks interface { + OnChanCloseConfirmBeforeHook(ctx sdk.Context, portID, channelID string) +} +type OnChanCloseConfirmAfterHooks interface { + OnChanCloseConfirmAfterHook(ctx sdk.Context, portID, channelID string, err error) +} + +// OnRecvPacket Hooks +type OnRecvPacketOverrideHooks interface { + OnRecvPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) ibcexported.Acknowledgement +} +type OnRecvPacketBeforeHooks interface { + OnRecvPacketBeforeHook(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) +} +type OnRecvPacketAfterHooks interface { + OnRecvPacketAfterHook(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, ack ibcexported.Acknowledgement) +} + +// OnAcknowledgementPacket Hooks +type OnAcknowledgementPacketOverrideHooks interface { + OnAcknowledgementPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) error +} +type OnAcknowledgementPacketBeforeHooks interface { + OnAcknowledgementPacketBeforeHook(ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) +} +type OnAcknowledgementPacketAfterHooks interface { + OnAcknowledgementPacketAfterHook(ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress, err error) +} + +// OnTimeoutPacket Hooks +type OnTimeoutPacketOverrideHooks interface { + OnTimeoutPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) error +} +type OnTimeoutPacketBeforeHooks interface { + OnTimeoutPacketBeforeHook(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) +} +type OnTimeoutPacketAfterHooks interface { + OnTimeoutPacketAfterHook(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, err error) +} + +// SendPacket Hooks +type SendPacketOverrideHooks interface { + SendPacketOverride(i ICS4Middleware, ctx sdk.Context, chanCap *capabilitytypes.Capability, sourcePort string, sourceChannel string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, data []byte) (uint64, error) +} +type SendPacketBeforeHooks interface { + SendPacketBeforeHook(ctx sdk.Context, chanCap *capabilitytypes.Capability, sourcePort string, sourceChannel string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, data []byte) +} +type SendPacketAfterHooks interface { + SendPacketAfterHook(cctx sdk.Context, chanCap *capabilitytypes.Capability, sourcePort string, sourceChannel string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, data []byte, err error) +} + +// WriteAcknowledgement Hooks +type WriteAcknowledgementOverrideHooks interface { + WriteAcknowledgementOverride(i ICS4Middleware, ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, ack ibcexported.Acknowledgement) error +} +type WriteAcknowledgementBeforeHooks interface { + WriteAcknowledgementBeforeHook(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, ack ibcexported.Acknowledgement) +} +type WriteAcknowledgementAfterHooks interface { + WriteAcknowledgementAfterHook(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, ack ibcexported.Acknowledgement, err error) +} + +// GetAppVersion Hooks +type GetAppVersionOverrideHooks interface { + GetAppVersionOverride(i ICS4Middleware, ctx sdk.Context, portID, channelID string) (string, bool) +} +type GetAppVersionBeforeHooks interface { + GetAppVersionBeforeHook(ctx sdk.Context, portID, channelID string) +} +type GetAppVersionAfterHooks interface { + GetAppVersionAfterHook(ctx sdk.Context, portID, channelID string, result string, success bool) +} diff --git a/x/onion/ibc_module.go b/x/onion/ibc_module.go new file mode 100644 index 00000000..edaba2e7 --- /dev/null +++ b/x/onion/ibc_module.go @@ -0,0 +1,261 @@ +package onion + +import ( + // external libraries + sdk "github.com/cosmos/cosmos-sdk/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + + // ibc-go + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" +) + +var _ porttypes.Middleware = &IBCMiddleware{} + +type IBCMiddleware struct { + App porttypes.IBCModule + ICS4Middleware *ICS4Middleware +} + +func NewIBCMiddleware(app porttypes.IBCModule, ics4 *ICS4Middleware) IBCMiddleware { + return IBCMiddleware{ + App: app, + ICS4Middleware: ics4, + } +} + +// OnChanOpenInit implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanOpenInit( + ctx sdk.Context, + order channeltypes.Order, + connectionHops []string, + portID string, + channelID string, + channelCap *capabilitytypes.Capability, + counterparty channeltypes.Counterparty, + version string, +) (string, error) { + if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenInitOverrideHooks); ok { + return hook.OnChanOpenInitOverride(im, ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version) + } + + if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenInitBeforeHooks); ok { + hook.OnChanOpenInitBeforeHook(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version) + } + + finalVersion, err := im.App.OnChanOpenInit(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version) + + if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenInitAfterHooks); ok { + hook.OnChanOpenInitAfterHook(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version, finalVersion, err) + } + return version, err +} + +// OnChanOpenTry implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanOpenTry( + ctx sdk.Context, + order channeltypes.Order, + connectionHops []string, + portID, + channelID string, + channelCap *capabilitytypes.Capability, + counterparty channeltypes.Counterparty, + counterpartyVersion string, +) (string, error) { + if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenTryOverrideHooks); ok { + return hook.OnChanOpenTryOverride(im, ctx, order, connectionHops, portID, channelID, channelCap, counterparty, counterpartyVersion) + } + + if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenTryBeforeHooks); ok { + hook.OnChanOpenTryBeforeHook(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, counterpartyVersion) + } + + version, err := im.App.OnChanOpenTry(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, counterpartyVersion) + + if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenTryAfterHooks); ok { + hook.OnChanOpenTryAfterHook(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, counterpartyVersion, version, err) + } + return version, err +} + +// OnChanOpenAck implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanOpenAck( + ctx sdk.Context, + portID, + channelID string, + counterpartyChannelID string, + counterpartyVersion string, +) error { + if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenAckOverrideHooks); ok { + return hook.OnChanOpenAckOverride(im, ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) + } + + if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenAckBeforeHooks); ok { + hook.OnChanOpenAckBeforeHook(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) + } + err := im.App.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) + if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenAckAfterHooks); ok { + hook.OnChanOpenAckAfterHook(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion, err) + } + + return err +} + +// OnChanOpenConfirm implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanOpenConfirm( + ctx sdk.Context, + portID, + channelID string, +) error { + if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenConfirmOverrideHooks); ok { + return hook.OnChanOpenConfirmOverride(im, ctx, portID, channelID) + } + + if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenConfirmBeforeHooks); ok { + hook.OnChanOpenConfirmBeforeHook(ctx, portID, channelID) + } + err := im.App.OnChanOpenConfirm(ctx, portID, channelID) + if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenConfirmAfterHooks); ok { + hook.OnChanOpenConfirmAfterHook(ctx, portID, channelID, err) + } + return err +} + +// OnChanCloseInit implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanCloseInit( + ctx sdk.Context, + portID, + channelID string, +) error { + // Here we can remove the limits when a new channel is closed. For now, they can remove them manually on the contract + if hook, ok := im.ICS4Middleware.Hooks.(OnChanCloseInitOverrideHooks); ok { + return hook.OnChanCloseInitOverride(im, ctx, portID, channelID) + } + + if hook, ok := im.ICS4Middleware.Hooks.(OnChanCloseInitBeforeHooks); ok { + hook.OnChanCloseInitBeforeHook(ctx, portID, channelID) + } + err := im.App.OnChanCloseInit(ctx, portID, channelID) + if hook, ok := im.ICS4Middleware.Hooks.(OnChanCloseInitAfterHooks); ok { + hook.OnChanCloseInitAfterHook(ctx, portID, channelID, err) + } + + return err +} + +// OnChanCloseConfirm implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanCloseConfirm( + ctx sdk.Context, + portID, + channelID string, +) error { + // Here we can remove the limits when a new channel is closed. For now, they can remove them manually on the contract + if hook, ok := im.ICS4Middleware.Hooks.(OnChanCloseConfirmOverrideHooks); ok { + return hook.OnChanCloseConfirmOverride(im, ctx, portID, channelID) + } + + if hook, ok := im.ICS4Middleware.Hooks.(OnChanCloseConfirmBeforeHooks); ok { + hook.OnChanCloseConfirmBeforeHook(ctx, portID, channelID) + } + err := im.App.OnChanCloseConfirm(ctx, portID, channelID) + if hook, ok := im.ICS4Middleware.Hooks.(OnChanCloseConfirmAfterHooks); ok { + hook.OnChanCloseConfirmAfterHook(ctx, portID, channelID, err) + } + + return err +} + +// OnRecvPacket implements the IBCMiddleware interface +func (im IBCMiddleware) OnRecvPacket( + ctx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, +) ibcexported.Acknowledgement { + if hook, ok := im.ICS4Middleware.Hooks.(OnRecvPacketOverrideHooks); ok { + return hook.OnRecvPacketOverride(im, ctx, packet, relayer) + } + + if hook, ok := im.ICS4Middleware.Hooks.(OnRecvPacketBeforeHooks); ok { + hook.OnRecvPacketBeforeHook(ctx, packet, relayer) + } + + ack := im.App.OnRecvPacket(ctx, packet, relayer) + + if hook, ok := im.ICS4Middleware.Hooks.(OnRecvPacketAfterHooks); ok { + hook.OnRecvPacketAfterHook(ctx, packet, relayer, ack) + } + + return ack +} + +// OnAcknowledgementPacket implements the IBCMiddleware interface +func (im IBCMiddleware) OnAcknowledgementPacket( + ctx sdk.Context, + packet channeltypes.Packet, + acknowledgement []byte, + relayer sdk.AccAddress, +) error { + if hook, ok := im.ICS4Middleware.Hooks.(OnAcknowledgementPacketOverrideHooks); ok { + return hook.OnAcknowledgementPacketOverride(im, ctx, packet, acknowledgement, relayer) + } + if hook, ok := im.ICS4Middleware.Hooks.(OnAcknowledgementPacketBeforeHooks); ok { + hook.OnAcknowledgementPacketBeforeHook(ctx, packet, acknowledgement, relayer) + } + + err := im.App.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer) + + if hook, ok := im.ICS4Middleware.Hooks.(OnAcknowledgementPacketAfterHooks); ok { + hook.OnAcknowledgementPacketAfterHook(ctx, packet, acknowledgement, relayer, err) + } + + return err +} + +// OnTimeoutPacket implements the IBCMiddleware interface +func (im IBCMiddleware) OnTimeoutPacket( + ctx sdk.Context, + packet channeltypes.Packet, + relayer sdk.AccAddress, +) error { + if hook, ok := im.ICS4Middleware.Hooks.(OnTimeoutPacketOverrideHooks); ok { + return hook.OnTimeoutPacketOverride(im, ctx, packet, relayer) + } + + if hook, ok := im.ICS4Middleware.Hooks.(OnTimeoutPacketBeforeHooks); ok { + hook.OnTimeoutPacketBeforeHook(ctx, packet, relayer) + } + err := im.App.OnTimeoutPacket(ctx, packet, relayer) + if hook, ok := im.ICS4Middleware.Hooks.(OnTimeoutPacketAfterHooks); ok { + hook.OnTimeoutPacketAfterHook(ctx, packet, relayer, err) + } + + return err +} + +// SendPacket implements the ICS4 Wrapper interface +func (im IBCMiddleware) SendPacket( + ctx sdk.Context, + chanCap *capabilitytypes.Capability, + sourcePort string, sourceChannel string, + timeoutHeight clienttypes.Height, + timeoutTimestamp uint64, + data []byte, +) (sequence uint64, err error) { + return im.ICS4Middleware.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data) +} + +// WriteAcknowledgement implements the ICS4 Wrapper interface +func (im IBCMiddleware) WriteAcknowledgement( + ctx sdk.Context, + chanCap *capabilitytypes.Capability, + packet ibcexported.PacketI, + ack ibcexported.Acknowledgement, +) error { + return im.ICS4Middleware.WriteAcknowledgement(ctx, chanCap, packet, ack) +} + +func (im IBCMiddleware) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { + return im.ICS4Middleware.GetAppVersion(ctx, portID, channelID) +} diff --git a/x/onion/ibcutils.go b/x/onion/ibcutils.go new file mode 100644 index 00000000..a94871de --- /dev/null +++ b/x/onion/ibcutils.go @@ -0,0 +1,78 @@ +package onion + +import ( + "encoding/json" + + sdk "github.com/cosmos/cosmos-sdk/types" + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" +) + +const IbcAcknowledgementErrorType = "ibc-acknowledgement-error" + +// NewEmitErrorAcknowledgement creates a new error acknowledgement after having emitted an event with the +// details of the error. +func NewEmitErrorAcknowledgement(ctx sdk.Context, err error, errorContexts ...string) channeltypes.Acknowledgement { + EmitIBCErrorEvents(ctx, err, errorContexts) + + return channeltypes.NewErrorAcknowledgement(err) +} + +// EmitIBCErrorEvents Emit and Log errors +func EmitIBCErrorEvents(ctx sdk.Context, err error, errorContexts []string) { + attributes := make([]sdk.Attribute, len(errorContexts)+1) + attributes[0] = sdk.NewAttribute("error", err.Error()) + for i, s := range errorContexts { + attributes[i+1] = sdk.NewAttribute("error-context", s) + } + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + IbcAcknowledgementErrorType, + attributes..., + ), + }) +} + +// MustExtractDenomFromPacketOnRecv takes a packet with a valid ICS20 token data in the Data field and returns the +// denom as represented in the local chain. +// If the data cannot be unmarshalled this function will panic +func MustExtractDenomFromPacketOnRecv(packet ibcexported.PacketI) string { + var data transfertypes.FungibleTokenPacketData + if err := json.Unmarshal(packet.GetData(), &data); err != nil { + panic("unable to unmarshal ICS20 packet data") + } + + var denom string + if transfertypes.ReceiverChainIsSource(packet.GetSourcePort(), packet.GetSourceChannel(), data.Denom) { + // remove prefix added by sender chain + voucherPrefix := transfertypes.GetDenomPrefix(packet.GetSourcePort(), packet.GetSourceChannel()) + + unprefixedDenom := data.Denom[len(voucherPrefix):] + + // coin denomination used in sending from the escrow address + denom = unprefixedDenom + + // The denomination used to send the coins is either the native denom or the hash of the path + // if the denomination is not native. + denomTrace := transfertypes.ParseDenomTrace(unprefixedDenom) + if denomTrace.Path != "" { + denom = denomTrace.IBCDenom() + } + } else { + prefixedDenom := transfertypes.GetDenomPrefix(packet.GetDestPort(), packet.GetDestChannel()) + data.Denom + denom = transfertypes.ParseDenomTrace(prefixedDenom).IBCDenom() + } + return denom +} + +// IsAckError checks an IBC acknowledgement to see if it's an error. +// This is a replacement for ack.Success() which is currently not working on some circumstances +func IsAckError(acknowledgement []byte) bool { + var ackErr channeltypes.Acknowledgement_Error + if err := json.Unmarshal(acknowledgement, &ackErr); err == nil && len(ackErr.Error) > 0 { + return true + } + return false +} diff --git a/x/onion/ics4_middleware.go b/x/onion/ics4_middleware.go new file mode 100644 index 00000000..06897f41 --- /dev/null +++ b/x/onion/ics4_middleware.go @@ -0,0 +1,85 @@ +package onion + +import ( + // external libraries + sdk "github.com/cosmos/cosmos-sdk/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + + // ibc-go + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" + porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" +) + +var _ porttypes.ICS4Wrapper = &ICS4Middleware{} + +type ICS4Middleware struct { + channel porttypes.ICS4Wrapper + + // Hooks + Hooks Hooks +} + +func NewICS4Middleware(channel porttypes.ICS4Wrapper, hooks Hooks) ICS4Middleware { + return ICS4Middleware{ + channel: channel, + Hooks: hooks, + } +} + +func (i ICS4Middleware) SendPacket( + ctx sdk.Context, + chanCap *capabilitytypes.Capability, + sourcePort string, sourceChannel string, + timeoutHeight clienttypes.Height, + timeoutTimestamp uint64, + data []byte, +) (sequence uint64, err error) { + if hook, ok := i.Hooks.(SendPacketOverrideHooks); ok { + return hook.SendPacketOverride(i, ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data) + } + + if hook, ok := i.Hooks.(SendPacketBeforeHooks); ok { + hook.SendPacketBeforeHook(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data) + } + + seq, err := i.channel.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data) + + if hook, ok := i.Hooks.(SendPacketAfterHooks); ok { + hook.SendPacketAfterHook(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data, err) + } + + return seq, err +} + +func (i ICS4Middleware) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, ack ibcexported.Acknowledgement) error { + if hook, ok := i.Hooks.(WriteAcknowledgementOverrideHooks); ok { + return hook.WriteAcknowledgementOverride(i, ctx, chanCap, packet, ack) + } + + if hook, ok := i.Hooks.(WriteAcknowledgementBeforeHooks); ok { + hook.WriteAcknowledgementBeforeHook(ctx, chanCap, packet, ack) + } + err := i.channel.WriteAcknowledgement(ctx, chanCap, packet, ack) + if hook, ok := i.Hooks.(WriteAcknowledgementAfterHooks); ok { + hook.WriteAcknowledgementAfterHook(ctx, chanCap, packet, ack, err) + } + + return err +} + +func (i ICS4Middleware) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { + if hook, ok := i.Hooks.(GetAppVersionOverrideHooks); ok { + return hook.GetAppVersionOverride(i, ctx, portID, channelID) + } + + if hook, ok := i.Hooks.(GetAppVersionBeforeHooks); ok { + hook.GetAppVersionBeforeHook(ctx, portID, channelID) + } + version, err := i.channel.GetAppVersion(ctx, portID, channelID) + if hook, ok := i.Hooks.(GetAppVersionAfterHooks); ok { + hook.GetAppVersionAfterHook(ctx, portID, channelID, version, err) + } + + return version, err +} diff --git a/x/onion/keeper/ibcutils.go b/x/onion/keeper/ibcutils.go new file mode 100644 index 00000000..60fd0f6c --- /dev/null +++ b/x/onion/keeper/ibcutils.go @@ -0,0 +1,33 @@ +package keeper + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" +) + +const IbcAcknowledgementErrorType = "ibc-acknowledgement-error" + +// NewSuccessAckRepresentingAnError creates a new success acknowledgement that represents an error. +// This is useful for notifying the sender that an error has occurred in a way that does not allow +// the received tokens to be reverted (which means they shouldn't be released by the sender's ics20 escrow) +func NewSuccessAckRepresentingAnError(ctx sdk.Context, err error, errorContent []byte, errorContexts ...string) channeltypes.Acknowledgement { + EmitIBCErrorEvents(ctx, err, errorContexts) + + return channeltypes.NewResultAcknowledgement(errorContent) +} + +// EmitIBCErrorEvents Emit and Log errors +func EmitIBCErrorEvents(ctx sdk.Context, err error, errorContexts []string) { + attributes := make([]sdk.Attribute, len(errorContexts)+1) + attributes[0] = sdk.NewAttribute("error", err.Error()) + for i, s := range errorContexts { + attributes[i+1] = sdk.NewAttribute("error-context", s) + } + + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + IbcAcknowledgementErrorType, + attributes..., + ), + }) +} diff --git a/x/onion/keeper/keeper.go b/x/onion/keeper/keeper.go new file mode 100644 index 00000000..a0793bf1 --- /dev/null +++ b/x/onion/keeper/keeper.go @@ -0,0 +1,279 @@ +package keeper + +import ( + "encoding/hex" + "encoding/json" + "fmt" + "strings" + + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + "github.com/cometbft/cometbft/crypto/tmhash" + "github.com/cometbft/cometbft/libs/log" + "github.com/cosmos/cosmos-sdk/types/address" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + + "github.com/Team-Kujira/core/x/onion/types" + + sdk "github.com/cosmos/cosmos-sdk/types" + + storetypes "github.com/cosmos/cosmos-sdk/store/types" +) + +type ( + Keeper struct { + storeKey storetypes.StoreKey + paramSpace paramtypes.Subspace + + channelKeeper types.ChannelKeeper + ContractKeeper *wasmkeeper.PermissionedKeeper + } +) + +// NewKeeper returns a new instance of the x/ibchooks keeper +func NewKeeper( + storeKey storetypes.StoreKey, + paramSpace paramtypes.Subspace, + channelKeeper types.ChannelKeeper, + contractKeeper *wasmkeeper.PermissionedKeeper, +) *Keeper { + if !paramSpace.HasKeyTable() { + paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable()) + } + return &Keeper{ + storeKey: storeKey, + paramSpace: paramSpace, + channelKeeper: channelKeeper, + ContractKeeper: contractKeeper, + } +} + +// Logger returns a logger for the x/tokenfactory module +func (k Keeper) Logger(ctx sdk.Context) log.Logger { + return ctx.Logger().With("module", fmt.Sprintf("x/%s", types.ModuleName)) +} + +// GetParams returns the total set of the module's parameters. +func (k Keeper) GetParams(ctx sdk.Context) (params types.Params) { + k.paramSpace.GetParamSet(ctx, ¶ms) + return params +} + +// SetParams sets the module's parameters with the provided parameters. +func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { + k.paramSpace.SetParamSet(ctx, ¶ms) +} + +// SetParam sets a specific ibc-hooks module's parameter with the provided parameter. +func (k Keeper) SetParam(ctx sdk.Context, key []byte, value interface{}) { + k.paramSpace.Set(ctx, key, value) +} + +func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) { + k.SetParams(ctx, genState.Params) +} + +func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { + return &types.GenesisState{ + Params: k.GetParams(ctx), + } +} + +func GetPacketCallbackKey(channel string, packetSequence uint64) []byte { + return []byte(fmt.Sprintf("%s::%d", channel, packetSequence)) +} + +func GetPacketAckKey(channel string, packetSequence uint64) []byte { + return []byte(fmt.Sprintf("%s::%d::ack", channel, packetSequence)) +} + +func GeneratePacketAckValue(packet channeltypes.Packet, contract string) ([]byte, error) { + if _, err := sdk.AccAddressFromBech32(contract); err != nil { + return nil, sdkerrors.Wrap(types.ErrInvalidContractAddr, contract) + } + + packetHash, err := hashPacket(packet) + if err != nil { + return nil, sdkerrors.Wrap(err, "could not hash packet") + } + + return []byte(fmt.Sprintf("%s::%s", contract, packetHash)), nil +} + +// StorePacketCallback stores which contract will be listening for the ack or timeout of a packet +func (k Keeper) StorePacketCallback(ctx sdk.Context, channel string, packetSequence uint64, contract string) { + store := ctx.KVStore(k.storeKey) + store.Set(GetPacketCallbackKey(channel, packetSequence), []byte(contract)) +} + +// GetPacketCallback returns the bech32 addr of the contract that is expecting a callback from a packet +func (k Keeper) GetPacketCallback(ctx sdk.Context, channel string, packetSequence uint64) string { + store := ctx.KVStore(k.storeKey) + return string(store.Get(GetPacketCallbackKey(channel, packetSequence))) +} + +// IsInAllowList checks the params to see if the contract is in the KeyAsyncAckAllowList param +func (k Keeper) IsInAllowList(ctx sdk.Context, contract string) bool { + var allowList []string + k.paramSpace.GetIfExists(ctx, types.KeyAsyncAckAllowList, &allowList) + for _, addr := range allowList { + if addr == contract { + return true + } + } + return false +} + +// DeletePacketCallback deletes the callback from storage once it has been processed +func (k Keeper) DeletePacketCallback(ctx sdk.Context, channel string, packetSequence uint64) { + store := ctx.KVStore(k.storeKey) + store.Delete(GetPacketCallbackKey(channel, packetSequence)) +} + +// StorePacketAckActor stores which contract is allowed to send an ack for the packet +func (k Keeper) StorePacketAckActor(ctx sdk.Context, packet channeltypes.Packet, contract string) { + store := ctx.KVStore(k.storeKey) + channel := packet.GetSourceChannel() + packetSequence := packet.GetSequence() + + val, err := GeneratePacketAckValue(packet, contract) + if err != nil { + panic(err) + } + store.Set(GetPacketAckKey(channel, packetSequence), val) +} + +// GetPacketAckActor returns the bech32 addr of the contract that is allowed to send an ack for the packet and the packet hash +func (k Keeper) GetPacketAckActor(ctx sdk.Context, channel string, packetSequence uint64) (string, string) { + store := ctx.KVStore(k.storeKey) + rawData := store.Get(GetPacketAckKey(channel, packetSequence)) + if rawData == nil { + return "", "" + } + data := strings.Split(string(rawData), "::") + if len(data) != 2 { + return "", "" + } + // validate that the contract is a valid bech32 addr + if _, err := sdk.AccAddressFromBech32(data[0]); err != nil { + return "", "" + } + // validate that the hash is a valid sha256sum hash + if _, err := hex.DecodeString(data[1]); err != nil { + return "", "" + } + + return data[0], data[1] +} + +// DeletePacketAckActor deletes the ack actor from storage once it has been used +func (k Keeper) DeletePacketAckActor(ctx sdk.Context, channel string, packetSequence uint64) { + store := ctx.KVStore(k.storeKey) + store.Delete(GetPacketAckKey(channel, packetSequence)) +} + +// DeriveIntermediateSender derives the sender address to be used when calling wasm hooks +func DeriveIntermediateSender(channel, originalSender, bech32Prefix string) (string, error) { + senderStr := fmt.Sprintf("%s/%s", channel, originalSender) + senderHash32 := address.Hash(types.SenderPrefix, []byte(senderStr)) + sender := sdk.AccAddress(senderHash32[:]) + return sdk.Bech32ifyAddressBytes(bech32Prefix, sender) +} + +// EmitIBCAck emits an event that the IBC packet has been acknowledged +func (k Keeper) EmitIBCAck(ctx sdk.Context, sender, channel string, packetSequence uint64) ([]byte, error) { + contract, packetHash := k.GetPacketAckActor(ctx, channel, packetSequence) + if contract == "" { + return nil, fmt.Errorf("no ack actor set for channel %s packet %d", channel, packetSequence) + } + // Only the contract itself can request for the ack to be emitted. This will generally happen as a callback + // when the result of other IBC actions has finished, but it could be exposed directly by the contract if the + // proper checks are made + if sender != contract { + return nil, fmt.Errorf("sender %s is not allowed to send an ack for channel %s packet %d", sender, channel, packetSequence) + } + + // Write the acknowledgement + _, cap, err := k.channelKeeper.LookupModuleByChannel(ctx, "transfer", channel) + if err != nil { + return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") + } + + // Calling the contract. This could be made generic by using an interface if we want + // to support other types of AckActors, but keeping it here for now for simplicity. + contractAddr, err := sdk.AccAddressFromBech32(contract) + if err != nil { + return nil, sdkerrors.Wrap(err, "could not parse contract address") + } + + msg := types.IBCAsync{ + RequestAck: types.RequestAck{RequestAckI: types.RequestAckI{ + PacketSequence: packetSequence, + SourceChannel: channel, + }}, + } + msgBytes, err := json.Marshal(msg) + if err != nil { + return nil, sdkerrors.Wrap(err, "could not marshal message") + } + bz, err := k.ContractKeeper.Sudo(ctx, contractAddr, msgBytes) + if err != nil { + return nil, sdkerrors.Wrap(err, "could not execute contract") + } + + ack, err := types.UnmarshalIBCAck(bz) + if err != nil { + return nil, sdkerrors.Wrap(err, "could not unmarshal into IBCAckResponse or IBCAckError") + + } + var newAck channeltypes.Acknowledgement + var packet channeltypes.Packet + + switch ack.Type { + case "ack_response": + jsonAck, err := json.Marshal(ack.AckResponse.ContractAck) + if err != nil { + return nil, sdkerrors.Wrap(err, "could not marshal acknowledgement") + } + packet = ack.AckResponse.Packet + newAck = channeltypes.NewResultAcknowledgement(jsonAck) + case "ack_error": + packet = ack.AckError.Packet + newAck = NewSuccessAckRepresentingAnError(ctx, types.ErrAckFromContract, []byte(ack.AckError.ErrorResponse), ack.AckError.ErrorDescription) + default: + return nil, sdkerrors.Wrap(err, "could not unmarshal into IBCAckResponse or IBCAckError") + } + + // Validate that the packet returned by the contract matches the one we stored when sending + receivedPacketHash, err := hashPacket(packet) + if err != nil { + return nil, sdkerrors.Wrap(err, "could not hash packet") + } + if receivedPacketHash != packetHash { + return nil, sdkerrors.Wrap(types.ErrAckPacketMismatch, fmt.Sprintf("packet hash mismatch. Expected %s, got %s", packetHash, receivedPacketHash)) + } + + // Now we can write the acknowledgement + err = k.channelKeeper.WriteAcknowledgement(ctx, cap, packet, newAck) + if err != nil { + return nil, sdkerrors.Wrap(err, "could not write acknowledgement") + } + + response, err := json.Marshal(newAck) + if err != nil { + return nil, sdkerrors.Wrap(err, "could not marshal acknowledgement") + } + return response, nil +} + +func hashPacket(packet channeltypes.Packet) (string, error) { + // ignore the data here. We only care about the channel information + packet.Data = nil + bz, err := json.Marshal(packet) + if err != nil { + return "", sdkerrors.Wrap(err, "could not marshal packet") + } + packetHash := tmhash.Sum(bz) + return hex.EncodeToString(packetHash), nil +} diff --git a/x/onion/keeper/msg_server.go b/x/onion/keeper/msg_server.go new file mode 100644 index 00000000..18c2fa48 --- /dev/null +++ b/x/onion/keeper/msg_server.go @@ -0,0 +1,41 @@ +package keeper + +import ( + "context" + "strconv" + + "github.com/Team-Kujira/core/x/onion/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +type msgServer struct { + Keeper +} + +// NewMsgServerImpl returns an implementation of the MsgServer interface +// for the provided Keeper. +func NewMsgServerImpl(keeper Keeper) types.MsgServer { + return &msgServer{Keeper: keeper} +} + +var _ types.MsgServer = msgServer{} + +func (m msgServer) EmitIBCAck(goCtx context.Context, msg *types.MsgEmitIBCAck) (*types.MsgEmitIBCAckResponse, error) { + ctx := sdk.UnwrapSDKContext(goCtx) + + ctx.EventManager().EmitEvent( + sdk.NewEvent( + types.MsgEmitAckKey, + sdk.NewAttribute(types.AttributeSender, msg.Sender), + sdk.NewAttribute(types.AttributeChannel, msg.Channel), + sdk.NewAttribute(types.AttributePacketSequence, strconv.FormatUint(msg.PacketSequence, 10)), + ), + ) + + ack, err := m.Keeper.EmitIBCAck(ctx, msg.Sender, msg.Channel, msg.PacketSequence) + if err != nil { + return nil, err + } + + return &types.MsgEmitIBCAckResponse{ContractResult: string(ack), IbcAck: string(ack)}, nil +} diff --git a/x/onion/sdkmodule.go b/x/onion/sdkmodule.go new file mode 100644 index 00000000..89199854 --- /dev/null +++ b/x/onion/sdkmodule.go @@ -0,0 +1,139 @@ +package onion + +import ( + "encoding/json" + "fmt" + + "github.com/Team-Kujira/core/x/onion/keeper" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/types/module" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/spf13/cobra" + + "github.com/Team-Kujira/core/x/onion/client/cli" + "github.com/Team-Kujira/core/x/onion/types" + + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + + abci "github.com/cometbft/cometbft/abci/types" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +var ( + _ module.AppModule = AppModule{} + _ module.AppModuleBasic = AppModuleBasic{} +) + +// AppModuleBasic defines the basic application module used by the ibc-hooks module. +type AppModuleBasic struct{} + +var _ module.AppModuleBasic = AppModuleBasic{} + +// Name returns the ibc-hooks module's name. +func (AppModuleBasic) Name() string { + return types.ModuleName +} + +// RegisterLegacyAminoCodec registers the ibc-hooks module's types on the given LegacyAmino codec. +func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { + types.RegisterCodec(cdc) +} + +// RegisterInterfaces registers the module's interface types +func (a AppModuleBasic) RegisterInterfaces(reg cdctypes.InterfaceRegistry) { + types.RegisterInterfaces(reg) +} + +// DefaultGenesis returns default genesis state as raw bytes for the +// module. +func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { + return cdc.MustMarshalJSON(types.DefaultGenesis()) +} + +// ValidateGenesis performs genesis state validation for the ibc-hooks module. +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { + var genState types.GenesisState + if err := cdc.UnmarshalJSON(bz, &genState); err != nil { + return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) + } + return genState.Validate() +} + +// RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the ibc-hooks module. +func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {} + +// GetTxCmd returns no root tx command for the ibc-hooks module. +func (AppModuleBasic) GetTxCmd() *cobra.Command { return nil } + +// GetQueryCmd returns the root query command for the ibc-hooks module. +func (AppModuleBasic) GetQueryCmd() *cobra.Command { + return cli.GetQueryCmd() +} + +// ___________________________________________________________________________ + +// AppModule implements an application module for the ibc-hooks module. +type AppModule struct { + AppModuleBasic + + keeper keeper.Keeper +} + +// NewAppModule creates a new AppModule object. +func NewAppModule(keeper keeper.Keeper) AppModule { + return AppModule{ + AppModuleBasic: AppModuleBasic{}, + keeper: keeper, + } +} + +// Name returns the ibc-hooks module's name. +func (AppModule) Name() string { + return types.ModuleName +} + +// RegisterInvariants registers the ibc-hooks module invariants. +func (am AppModule) RegisterInvariants(_ sdk.InvariantRegistry) {} + +// QuerierRoute returns the module's querier route name. +func (AppModule) QuerierRoute() string { + return "" +} + +// RegisterServices registers a gRPC query service to respond to the +// module-specific gRPC queries. +func (am AppModule) RegisterServices(cfg module.Configurator) { + types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) +} + +// InitGenesis performs genesis initialization for the ibc-hooks module. It returns +// no validator updates. +func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, data json.RawMessage) []abci.ValidatorUpdate { + var genState types.GenesisState + // Initialize global index to index in genesis state + cdc.MustUnmarshalJSON(data, &genState) + + am.keeper.InitGenesis(ctx, genState) + + return []abci.ValidatorUpdate{} +} + +func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { + genState := am.keeper.ExportGenesis(ctx) + return cdc.MustMarshalJSON(genState) +} + +// BeginBlock returns the begin blocker for the ibc-hooks module. +func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { +} + +// EndBlock returns the end blocker for the ibc-hooks module. It returns no validator +// updates. +func (AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.ValidatorUpdate { + return []abci.ValidatorUpdate{} +} + +// ConsensusVersion implements AppModule/ConsensusVersion. +func (AppModule) ConsensusVersion() uint64 { return 1 } diff --git a/x/onion/types/codec.go b/x/onion/types/codec.go new file mode 100644 index 00000000..5cd725f9 --- /dev/null +++ b/x/onion/types/codec.go @@ -0,0 +1,38 @@ +package types + +import ( + "github.com/cosmos/cosmos-sdk/codec" + cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + authzcodec "github.com/cosmos/cosmos-sdk/x/authz/codec" + + // this line is used by starport scaffolding # 1 + "github.com/cosmos/cosmos-sdk/types/msgservice" +) + +func RegisterCodec(cdc *codec.LegacyAmino) { + cdc.RegisterConcrete(&MsgEmitIBCAck{}, "kujira/ibc-hooks/emit-ibc-ack", nil) +} + +func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { + registry.RegisterImplementations( + (*sdk.Msg)(nil), + &MsgEmitIBCAck{}, + ) + msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) +} + +var ( + amino = codec.NewLegacyAmino() + ModuleCdc = codec.NewProtoCodec(cdctypes.NewInterfaceRegistry()) +) + +func init() { + RegisterCodec(amino) + // Register all Amino interfaces and concrete types on the authz Amino codec so that this can later be + // used to properly serialize MsgGrant and MsgExec instances + sdk.RegisterLegacyAminoCodec(amino) + RegisterCodec(authzcodec.Amino) + + amino.Seal() +} diff --git a/x/onion/types/errors.go b/x/onion/types/errors.go new file mode 100644 index 00000000..31722619 --- /dev/null +++ b/x/onion/types/errors.go @@ -0,0 +1,21 @@ +package types + +import ( + errorsmod "cosmossdk.io/errors" +) + +var ( + ErrBadMetadataFormatMsg = "wasm metadata not properly formatted for: '%v'. %s" + ErrBadExecutionMsg = "cannot execute contract: %v" + + ErrMsgValidation = errorsmod.Register("wasm-hooks", 2, "error in wasmhook message validation") + ErrMarshaling = errorsmod.Register("wasm-hooks", 3, "cannot marshal the ICS20 packet") + ErrInvalidPacket = errorsmod.Register("wasm-hooks", 4, "invalid packet data") + ErrBadResponse = errorsmod.Register("wasm-hooks", 5, "cannot create response") + ErrWasmError = errorsmod.Register("wasm-hooks", 6, "wasm error") + ErrBadSender = errorsmod.Register("wasm-hooks", 7, "bad sender") + ErrAckFromContract = errorsmod.Register("wasm-hooks", 8, "contract returned error ack") + ErrAsyncAckNotAllowed = errorsmod.Register("wasm-hooks", 9, "contract not allowed to send async acks") + ErrAckPacketMismatch = errorsmod.Register("wasm-hooks", 10, "packet does not match the expected packet") + ErrInvalidContractAddr = errorsmod.Register("wasm-hooks", 11, "invalid contract address") +) diff --git a/x/onion/types/expected_keepers.go b/x/onion/types/expected_keepers.go new file mode 100644 index 00000000..59761e41 --- /dev/null +++ b/x/onion/types/expected_keepers.go @@ -0,0 +1,16 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + "github.com/cosmos/ibc-go/v7/modules/core/exported" +) + +type ChannelKeeper interface { + GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) + GetPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64) []byte + GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) + LookupModuleByChannel(ctx sdk.Context, portID, channelID string) (string, *capabilitytypes.Capability, error) + WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet exported.PacketI, acknowledgement exported.Acknowledgement) error +} diff --git a/x/onion/types/genesis.go b/x/onion/types/genesis.go new file mode 100644 index 00000000..dd111be6 --- /dev/null +++ b/x/onion/types/genesis.go @@ -0,0 +1,16 @@ +package types + +// DefaultGenesis returns the default GenesisState for the concentrated-liquidity module. +func DefaultGenesis() *GenesisState { + return &GenesisState{ + Params: DefaultParams(), + } +} + +// Validate performs basic genesis state validation returning an error upon any failure. +func (gs GenesisState) Validate() error { + if err := gs.Params.Validate(); err != nil { + return err + } + return nil +} diff --git a/x/onion/types/genesis.pb.go b/x/onion/types/genesis.pb.go new file mode 100644 index 00000000..70bef3cd --- /dev/null +++ b/x/onion/types/genesis.pb.go @@ -0,0 +1,321 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: kujira/onion/genesis.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type GenesisState struct { + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` +} + +func (m *GenesisState) Reset() { *m = GenesisState{} } +func (m *GenesisState) String() string { return proto.CompactTextString(m) } +func (*GenesisState) ProtoMessage() {} +func (*GenesisState) Descriptor() ([]byte, []int) { + return fileDescriptor_e5d80ee52a36c767, []int{0} +} +func (m *GenesisState) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *GenesisState) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_GenesisState.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *GenesisState) XXX_Merge(src proto.Message) { + xxx_messageInfo_GenesisState.Merge(m, src) +} +func (m *GenesisState) XXX_Size() int { + return m.Size() +} +func (m *GenesisState) XXX_DiscardUnknown() { + xxx_messageInfo_GenesisState.DiscardUnknown(m) +} + +var xxx_messageInfo_GenesisState proto.InternalMessageInfo + +func (m *GenesisState) GetParams() Params { + if m != nil { + return m.Params + } + return Params{} +} + +func init() { + proto.RegisterType((*GenesisState)(nil), "kujira.onion.GenesisState") +} + +func init() { proto.RegisterFile("kujira/onion/genesis.proto", fileDescriptor_e5d80ee52a36c767) } + +var fileDescriptor_e5d80ee52a36c767 = []byte{ + // 205 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xca, 0x2e, 0xcd, 0xca, + 0x2c, 0x4a, 0xd4, 0xcf, 0xcf, 0xcb, 0xcc, 0xcf, 0xd3, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, + 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x81, 0xc8, 0xe9, 0x81, 0xe5, 0xa4, 0x44, 0xd2, + 0xf3, 0xd3, 0xf3, 0xc1, 0x12, 0xfa, 0x20, 0x16, 0x44, 0x8d, 0x94, 0x64, 0x72, 0x7e, 0x71, 0x6e, + 0x7e, 0x71, 0x3c, 0x44, 0x02, 0xc2, 0x81, 0x49, 0xa1, 0x18, 0x5d, 0x90, 0x58, 0x94, 0x98, 0x0b, + 0x95, 0x52, 0x72, 0xe2, 0xe2, 0x71, 0x87, 0x58, 0x15, 0x5c, 0x92, 0x58, 0x92, 0x2a, 0x64, 0xc4, + 0xc5, 0x06, 0x91, 0x97, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x36, 0x12, 0xd1, 0x43, 0xb6, 0x5a, 0x2f, + 0x00, 0x2c, 0xe7, 0xc4, 0x72, 0xe2, 0x9e, 0x3c, 0x43, 0x10, 0x54, 0xa5, 0x93, 0xf3, 0x89, 0x47, + 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, + 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, + 0x25, 0xe7, 0xe7, 0xea, 0x87, 0xa4, 0x26, 0xe6, 0xea, 0x7a, 0x43, 0x1c, 0x92, 0x9c, 0x5f, 0x94, + 0xaa, 0x5f, 0x01, 0x75, 0x4f, 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0xd8, 0x3d, 0xc6, 0x80, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xbe, 0x59, 0x14, 0x16, 0x07, 0x01, 0x00, 0x00, +} + +func (m *GenesisState) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *GenesisState) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { + offset -= sovGenesis(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *GenesisState) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Params.Size() + n += 1 + l + sovGenesis(uint64(l)) + return n +} + +func sovGenesis(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozGenesis(x uint64) (n int) { + return sovGenesis(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *GenesisState) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: GenesisState: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: GenesisState: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Params.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipGenesis(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowGenesis + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthGenesis + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupGenesis + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthGenesis + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthGenesis = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowGenesis = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupGenesis = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/onion/types/keys.go b/x/onion/types/keys.go new file mode 100644 index 00000000..db7527bd --- /dev/null +++ b/x/onion/types/keys.go @@ -0,0 +1,17 @@ +package types + +const ( + ModuleName = "ibchooks" + RouterKey = ModuleName + StoreKey = "hooks-for-ibc" // not using the module name because of collisions with key "ibc" + + IBCCallbackKey = "ibc_callback" + IBCAsyncAckKey = "ibc_async_ack" + + MsgEmitAckKey = "emit_ack" + AttributeSender = "sender" + AttributeChannel = "channel" + AttributePacketSequence = "sequence" + + SenderPrefix = "ibc-wasm-hook-intermediary" +) diff --git a/x/onion/types/msgs.go b/x/onion/types/msgs.go new file mode 100644 index 00000000..85ccb3b8 --- /dev/null +++ b/x/onion/types/msgs.go @@ -0,0 +1,32 @@ +package types + +import ( + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" +) + +// constants. +const ( + TypeMsgEmitIBCAck = "emit-ibc-ack" +) + +var _ sdk.Msg = &MsgEmitIBCAck{} + +func (m MsgEmitIBCAck) Route() string { return RouterKey } +func (m MsgEmitIBCAck) Type() string { return TypeMsgEmitIBCAck } +func (m MsgEmitIBCAck) ValidateBasic() error { + _, err := sdk.AccAddressFromBech32(m.Sender) + if err != nil { + return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid sender address (%s)", err) + } + return nil +} + +func (m MsgEmitIBCAck) GetSignBytes() []byte { + return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) +} + +func (m MsgEmitIBCAck) GetSigners() []sdk.AccAddress { + sender, _ := sdk.AccAddressFromBech32(m.Sender) + return []sdk.AccAddress{sender} +} diff --git a/x/onion/types/params.go b/x/onion/types/params.go new file mode 100644 index 00000000..091fbb14 --- /dev/null +++ b/x/onion/types/params.go @@ -0,0 +1,62 @@ +package types + +import ( + "fmt" + sdk "github.com/cosmos/cosmos-sdk/types" + paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" +) + +// Parameter store keys. +var ( + KeyAsyncAckAllowList = []byte("AsyncAckAllowList") + + _ paramtypes.ParamSet = &Params{} +) + +func ParamKeyTable() paramtypes.KeyTable { + return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) +} + +func NewParams(allowedAsyncAckContracts []string) Params { + return Params{ + AllowedAsyncAckContracts: allowedAsyncAckContracts, + } +} + +// DefaultParams returns default concentrated-liquidity module parameters. +func DefaultParams() Params { + return Params{ + AllowedAsyncAckContracts: []string{}, + } +} + +// ParamSetPairs implements params.ParamSet. +func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { + return paramtypes.ParamSetPairs{ + paramtypes.NewParamSetPair(KeyAsyncAckAllowList, &p.AllowedAsyncAckContracts, validateAsyncAckAllowList), + } +} + +// Validate params. +func (p Params) Validate() error { + if err := validateAsyncAckAllowList(p.AllowedAsyncAckContracts); err != nil { + return err + } + return nil +} + +func validateAsyncAckAllowList(i interface{}) error { + allowedContracts, ok := i.([]string) + + if !ok { + return fmt.Errorf("invalid parameter type: %T", i) + } + + for _, contract := range allowedContracts { + if _, err := sdk.AccAddressFromBech32(contract); err != nil { + return err + } + } + + return nil +} diff --git a/x/onion/types/params.pb.go b/x/onion/types/params.pb.go new file mode 100644 index 00000000..3146401e --- /dev/null +++ b/x/onion/types/params.pb.go @@ -0,0 +1,327 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: kujira/onion/params.proto + +package types + +import ( + fmt "fmt" + _ "github.com/cosmos/cosmos-proto" + _ "github.com/cosmos/gogoproto/gogoproto" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/protobuf/types/known/durationpb" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type Params struct { + AllowedAsyncAckContracts []string `protobuf:"bytes,1,rep,name=allowed_async_ack_contracts,json=allowedAsyncAckContracts,proto3" json:"allowed_async_ack_contracts,omitempty" yaml:"allowed_async_ack_contracts"` +} + +func (m *Params) Reset() { *m = Params{} } +func (m *Params) String() string { return proto.CompactTextString(m) } +func (*Params) ProtoMessage() {} +func (*Params) Descriptor() ([]byte, []int) { + return fileDescriptor_c9158e41ac96e8e0, []int{0} +} +func (m *Params) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *Params) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_Params.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *Params) XXX_Merge(src proto.Message) { + xxx_messageInfo_Params.Merge(m, src) +} +func (m *Params) XXX_Size() int { + return m.Size() +} +func (m *Params) XXX_DiscardUnknown() { + xxx_messageInfo_Params.DiscardUnknown(m) +} + +var xxx_messageInfo_Params proto.InternalMessageInfo + +func (m *Params) GetAllowedAsyncAckContracts() []string { + if m != nil { + return m.AllowedAsyncAckContracts + } + return nil +} + +func init() { + proto.RegisterType((*Params)(nil), "kujira.onion.Params") +} + +func init() { proto.RegisterFile("kujira/onion/params.proto", fileDescriptor_c9158e41ac96e8e0) } + +var fileDescriptor_c9158e41ac96e8e0 = []byte{ + // 248 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcc, 0x2e, 0xcd, 0xca, + 0x2c, 0x4a, 0xd4, 0xcf, 0xcf, 0xcb, 0xcc, 0xcf, 0xd3, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x81, 0x48, 0xe9, 0x81, 0xa5, 0xa4, 0x44, 0xd2, 0xf3, + 0xd3, 0xf3, 0xc1, 0x12, 0xfa, 0x20, 0x16, 0x44, 0x8d, 0x94, 0x64, 0x72, 0x7e, 0x71, 0x6e, 0x7e, + 0x71, 0x3c, 0x44, 0x02, 0xc2, 0x81, 0x4a, 0xc9, 0xa5, 0xe7, 0xe7, 0xa7, 0xe7, 0xa4, 0xea, 0x83, + 0x79, 0x49, 0xa5, 0x69, 0xfa, 0x29, 0xa5, 0x45, 0x89, 0x25, 0x99, 0xf9, 0x79, 0x10, 0x79, 0xa5, + 0x7c, 0x2e, 0xb6, 0x00, 0xb0, 0x75, 0x42, 0xa9, 0x5c, 0xd2, 0x89, 0x39, 0x39, 0xf9, 0xe5, 0xa9, + 0x29, 0xf1, 0x89, 0xc5, 0x95, 0x79, 0xc9, 0xf1, 0x89, 0xc9, 0xd9, 0xf1, 0xc9, 0xf9, 0x79, 0x25, + 0x45, 0x89, 0xc9, 0x25, 0xc5, 0x12, 0x8c, 0x0a, 0xcc, 0x1a, 0x9c, 0x4e, 0x6a, 0x9f, 0xee, 0xc9, + 0x2b, 0x55, 0x26, 0xe6, 0xe6, 0x58, 0x29, 0xe1, 0x51, 0xac, 0x14, 0x24, 0x01, 0x95, 0x75, 0x04, + 0x49, 0x3a, 0x26, 0x67, 0x3b, 0xc3, 0xa4, 0x9c, 0x9c, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, + 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, + 0x58, 0x8e, 0x21, 0x4a, 0x33, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x3f, + 0x24, 0x35, 0x31, 0x57, 0xd7, 0x1b, 0x12, 0x28, 0xc9, 0xf9, 0x45, 0xa9, 0xfa, 0x15, 0xd0, 0xb0, + 0x29, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0x3b, 0xde, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, + 0x5b, 0x3f, 0x21, 0xa2, 0x38, 0x01, 0x00, 0x00, +} + +func (m *Params) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Params) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.AllowedAsyncAckContracts) > 0 { + for iNdEx := len(m.AllowedAsyncAckContracts) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.AllowedAsyncAckContracts[iNdEx]) + copy(dAtA[i:], m.AllowedAsyncAckContracts[iNdEx]) + i = encodeVarintParams(dAtA, i, uint64(len(m.AllowedAsyncAckContracts[iNdEx]))) + i-- + dAtA[i] = 0xa + } + } + return len(dAtA) - i, nil +} + +func encodeVarintParams(dAtA []byte, offset int, v uint64) int { + offset -= sovParams(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *Params) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if len(m.AllowedAsyncAckContracts) > 0 { + for _, s := range m.AllowedAsyncAckContracts { + l = len(s) + n += 1 + l + sovParams(uint64(l)) + } + } + return n +} + +func sovParams(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozParams(x uint64) (n int) { + return sovParams(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *Params) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: Params: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field AllowedAsyncAckContracts", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowParams + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthParams + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthParams + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.AllowedAsyncAckContracts = append(m.AllowedAsyncAckContracts, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipParams(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthParams + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipParams(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowParams + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthParams + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupParams + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthParams + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthParams = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowParams = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupParams = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/onion/types/tx.pb.go b/x/onion/types/tx.pb.go new file mode 100644 index 00000000..f4eda7a8 --- /dev/null +++ b/x/onion/types/tx.pb.go @@ -0,0 +1,724 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: kujira/onion/tx.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type MsgEmitIBCAck struct { + Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty" yaml:"sender"` + PacketSequence uint64 `protobuf:"varint,2,opt,name=packet_sequence,json=packetSequence,proto3" json:"packet_sequence,omitempty" yaml:"packet_sequence"` + Channel string `protobuf:"bytes,3,opt,name=channel,proto3" json:"channel,omitempty" yaml:"channel"` +} + +func (m *MsgEmitIBCAck) Reset() { *m = MsgEmitIBCAck{} } +func (m *MsgEmitIBCAck) String() string { return proto.CompactTextString(m) } +func (*MsgEmitIBCAck) ProtoMessage() {} +func (*MsgEmitIBCAck) Descriptor() ([]byte, []int) { + return fileDescriptor_788539ffbe617633, []int{0} +} +func (m *MsgEmitIBCAck) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgEmitIBCAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgEmitIBCAck.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgEmitIBCAck) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgEmitIBCAck.Merge(m, src) +} +func (m *MsgEmitIBCAck) XXX_Size() int { + return m.Size() +} +func (m *MsgEmitIBCAck) XXX_DiscardUnknown() { + xxx_messageInfo_MsgEmitIBCAck.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgEmitIBCAck proto.InternalMessageInfo + +func (m *MsgEmitIBCAck) GetSender() string { + if m != nil { + return m.Sender + } + return "" +} + +func (m *MsgEmitIBCAck) GetPacketSequence() uint64 { + if m != nil { + return m.PacketSequence + } + return 0 +} + +func (m *MsgEmitIBCAck) GetChannel() string { + if m != nil { + return m.Channel + } + return "" +} + +type MsgEmitIBCAckResponse struct { + ContractResult string `protobuf:"bytes,1,opt,name=contract_result,json=contractResult,proto3" json:"contract_result,omitempty" yaml:"contract_result"` + IbcAck string `protobuf:"bytes,2,opt,name=ibc_ack,json=ibcAck,proto3" json:"ibc_ack,omitempty" yaml:"ibc_ack"` +} + +func (m *MsgEmitIBCAckResponse) Reset() { *m = MsgEmitIBCAckResponse{} } +func (m *MsgEmitIBCAckResponse) String() string { return proto.CompactTextString(m) } +func (*MsgEmitIBCAckResponse) ProtoMessage() {} +func (*MsgEmitIBCAckResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_788539ffbe617633, []int{1} +} +func (m *MsgEmitIBCAckResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *MsgEmitIBCAckResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_MsgEmitIBCAckResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *MsgEmitIBCAckResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_MsgEmitIBCAckResponse.Merge(m, src) +} +func (m *MsgEmitIBCAckResponse) XXX_Size() int { + return m.Size() +} +func (m *MsgEmitIBCAckResponse) XXX_DiscardUnknown() { + xxx_messageInfo_MsgEmitIBCAckResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_MsgEmitIBCAckResponse proto.InternalMessageInfo + +func (m *MsgEmitIBCAckResponse) GetContractResult() string { + if m != nil { + return m.ContractResult + } + return "" +} + +func (m *MsgEmitIBCAckResponse) GetIbcAck() string { + if m != nil { + return m.IbcAck + } + return "" +} + +func init() { + proto.RegisterType((*MsgEmitIBCAck)(nil), "kujira.onion.MsgEmitIBCAck") + proto.RegisterType((*MsgEmitIBCAckResponse)(nil), "kujira.onion.MsgEmitIBCAckResponse") +} + +func init() { proto.RegisterFile("kujira/onion/tx.proto", fileDescriptor_788539ffbe617633) } + +var fileDescriptor_788539ffbe617633 = []byte{ + // 357 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0xc1, 0x4e, 0xea, 0x40, + 0x18, 0x85, 0x99, 0xcb, 0x0d, 0xe4, 0x4e, 0x2e, 0xdc, 0xdc, 0x89, 0x18, 0x82, 0x49, 0x21, 0xe3, + 0x06, 0xa2, 0xb6, 0x89, 0xee, 0xdc, 0x51, 0xe2, 0xc2, 0x18, 0x5c, 0x8c, 0xba, 0x71, 0x43, 0xa6, + 0xe3, 0xa4, 0xd4, 0xd2, 0x99, 0xda, 0x99, 0x26, 0xf0, 0x08, 0xee, 0x7c, 0x11, 0xdf, 0xc3, 0x25, + 0x4b, 0x57, 0xc4, 0xc0, 0x1b, 0xf0, 0x04, 0x86, 0x4e, 0x9b, 0x00, 0x0b, 0x77, 0x93, 0xef, 0x9c, + 0x3f, 0x73, 0xfe, 0xff, 0xc0, 0x46, 0x98, 0x3e, 0x07, 0x09, 0x75, 0xa4, 0x08, 0xa4, 0x70, 0xf4, + 0xd4, 0x8e, 0x13, 0xa9, 0x25, 0xfa, 0x6b, 0xb0, 0x9d, 0xe1, 0xd6, 0x81, 0x2f, 0x7d, 0x99, 0x09, + 0xce, 0xe6, 0x65, 0x3c, 0xf8, 0x1d, 0xc0, 0xda, 0x50, 0xf9, 0x57, 0x51, 0xa0, 0xaf, 0xdd, 0x41, + 0x9f, 0x85, 0xa8, 0x07, 0x2b, 0x8a, 0x8b, 0x27, 0x9e, 0x34, 0x41, 0x07, 0x74, 0xff, 0xb8, 0xff, + 0xd7, 0x8b, 0x76, 0x6d, 0x46, 0xa3, 0xc9, 0x25, 0x36, 0x1c, 0x93, 0xdc, 0x80, 0x06, 0xf0, 0x5f, + 0x4c, 0x59, 0xc8, 0xf5, 0x48, 0xf1, 0x97, 0x94, 0x0b, 0xc6, 0x9b, 0xbf, 0x3a, 0xa0, 0xfb, 0xdb, + 0x6d, 0xad, 0x17, 0xed, 0x43, 0x33, 0xb3, 0x67, 0xc0, 0xa4, 0x6e, 0xc8, 0x5d, 0x0e, 0xd0, 0x29, + 0xac, 0xb2, 0x31, 0x15, 0x82, 0x4f, 0x9a, 0xe5, 0xec, 0x43, 0xb4, 0x5e, 0xb4, 0xeb, 0x66, 0x38, + 0x17, 0x30, 0x29, 0x2c, 0xf8, 0x15, 0xc0, 0xc6, 0x4e, 0x5e, 0xc2, 0x55, 0x2c, 0x85, 0xe2, 0x9b, + 0x30, 0x4c, 0x0a, 0x9d, 0x50, 0xa6, 0x47, 0x09, 0x57, 0xe9, 0x44, 0xe7, 0x0b, 0x6c, 0x85, 0xd9, + 0x33, 0x60, 0x52, 0x2f, 0x08, 0xc9, 0x00, 0x3a, 0x81, 0xd5, 0xc0, 0x63, 0x23, 0xca, 0xc2, 0x6c, + 0x93, 0x9d, 0x30, 0xb9, 0x80, 0x49, 0x25, 0xf0, 0x58, 0x9f, 0x85, 0xe7, 0x0f, 0xb0, 0x3c, 0x54, + 0x3e, 0xba, 0x85, 0x70, 0xeb, 0x7c, 0x47, 0xf6, 0xf6, 0xd5, 0xed, 0x9d, 0xac, 0xad, 0xe3, 0x1f, + 0xc4, 0x62, 0x11, 0x77, 0xf0, 0xb1, 0xb4, 0xc0, 0x7c, 0x69, 0x81, 0xaf, 0xa5, 0x05, 0xde, 0x56, + 0x56, 0x69, 0xbe, 0xb2, 0x4a, 0x9f, 0x2b, 0xab, 0xf4, 0xd8, 0xf3, 0x03, 0x3d, 0x4e, 0x3d, 0x9b, + 0xc9, 0xc8, 0xb9, 0xe7, 0x34, 0x3a, 0xbb, 0x31, 0xbd, 0x33, 0x99, 0x70, 0x67, 0x5a, 0xd4, 0x3f, + 0x8b, 0xb9, 0xf2, 0x2a, 0x59, 0xbd, 0x17, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb4, 0xc3, 0xf3, + 0x4c, 0x1b, 0x02, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// MsgClient is the client API for Msg service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type MsgClient interface { + // EmitIBCAck checks the sender can emit the ack and writes the IBC + // acknowledgement + EmitIBCAck(ctx context.Context, in *MsgEmitIBCAck, opts ...grpc.CallOption) (*MsgEmitIBCAckResponse, error) +} + +type msgClient struct { + cc grpc1.ClientConn +} + +func NewMsgClient(cc grpc1.ClientConn) MsgClient { + return &msgClient{cc} +} + +func (c *msgClient) EmitIBCAck(ctx context.Context, in *MsgEmitIBCAck, opts ...grpc.CallOption) (*MsgEmitIBCAckResponse, error) { + out := new(MsgEmitIBCAckResponse) + err := c.cc.Invoke(ctx, "/kujira.onion.Msg/EmitIBCAck", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// MsgServer is the server API for Msg service. +type MsgServer interface { + // EmitIBCAck checks the sender can emit the ack and writes the IBC + // acknowledgement + EmitIBCAck(context.Context, *MsgEmitIBCAck) (*MsgEmitIBCAckResponse, error) +} + +// UnimplementedMsgServer can be embedded to have forward compatible implementations. +type UnimplementedMsgServer struct { +} + +func (*UnimplementedMsgServer) EmitIBCAck(ctx context.Context, req *MsgEmitIBCAck) (*MsgEmitIBCAckResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method EmitIBCAck not implemented") +} + +func RegisterMsgServer(s grpc1.Server, srv MsgServer) { + s.RegisterService(&_Msg_serviceDesc, srv) +} + +func _Msg_EmitIBCAck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(MsgEmitIBCAck) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MsgServer).EmitIBCAck(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/kujira.onion.Msg/EmitIBCAck", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MsgServer).EmitIBCAck(ctx, req.(*MsgEmitIBCAck)) + } + return interceptor(ctx, in, info, handler) +} + +var _Msg_serviceDesc = grpc.ServiceDesc{ + ServiceName: "kujira.onion.Msg", + HandlerType: (*MsgServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "EmitIBCAck", + Handler: _Msg_EmitIBCAck_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "kujira/onion/tx.proto", +} + +func (m *MsgEmitIBCAck) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgEmitIBCAck) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgEmitIBCAck) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Channel) > 0 { + i -= len(m.Channel) + copy(dAtA[i:], m.Channel) + i = encodeVarintTx(dAtA, i, uint64(len(m.Channel))) + i-- + dAtA[i] = 0x1a + } + if m.PacketSequence != 0 { + i = encodeVarintTx(dAtA, i, uint64(m.PacketSequence)) + i-- + dAtA[i] = 0x10 + } + if len(m.Sender) > 0 { + i -= len(m.Sender) + copy(dAtA[i:], m.Sender) + i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *MsgEmitIBCAckResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *MsgEmitIBCAckResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *MsgEmitIBCAckResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.IbcAck) > 0 { + i -= len(m.IbcAck) + copy(dAtA[i:], m.IbcAck) + i = encodeVarintTx(dAtA, i, uint64(len(m.IbcAck))) + i-- + dAtA[i] = 0x12 + } + if len(m.ContractResult) > 0 { + i -= len(m.ContractResult) + copy(dAtA[i:], m.ContractResult) + i = encodeVarintTx(dAtA, i, uint64(len(m.ContractResult))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarintTx(dAtA []byte, offset int, v uint64) int { + offset -= sovTx(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *MsgEmitIBCAck) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sender) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + if m.PacketSequence != 0 { + n += 1 + sovTx(uint64(m.PacketSequence)) + } + l = len(m.Channel) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func (m *MsgEmitIBCAckResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.ContractResult) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + l = len(m.IbcAck) + if l > 0 { + n += 1 + l + sovTx(uint64(l)) + } + return n +} + +func sovTx(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozTx(x uint64) (n int) { + return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *MsgEmitIBCAck) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgEmitIBCAck: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgEmitIBCAck: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sender = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field PacketSequence", wireType) + } + m.PacketSequence = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.PacketSequence |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Channel", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Channel = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *MsgEmitIBCAckResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: MsgEmitIBCAckResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: MsgEmitIBCAckResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field ContractResult", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.ContractResult = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field IbcAck", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowTx + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthTx + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthTx + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.IbcAck = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipTx(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthTx + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipTx(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowTx + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthTx + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupTx + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthTx + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/onion/types/types.go b/x/onion/types/types.go new file mode 100644 index 00000000..d3caffa6 --- /dev/null +++ b/x/onion/types/types.go @@ -0,0 +1,85 @@ +package types + +import ( + "encoding/json" + + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" +) + +// Async: The following types represent the response sent by a contract on OnRecvPacket when it wants the ack to be async + +// OnRecvPacketAsyncAckResponse the response a contract sends to instruct the module to make the ack async +type OnRecvPacketAsyncAckResponse struct { + IsAsyncAck bool `json:"is_async_ack"` +} + +// Async The following types are used to ask a contract that has sent a packet to generate an ack for it + +// RequestAckI internals of IBCAsync +type RequestAckI struct { + PacketSequence uint64 `json:"packet_sequence"` + SourceChannel string `json:"source_channel"` +} + +// RequestAck internals of IBCAsync +type RequestAck struct { + RequestAckI `json:"request_ack"` +} + +// IBCAsync is the sudo message to be sent to the contract for it to generate an ack for a sent packet +type IBCAsync struct { + RequestAck `json:"ibc_async"` +} + +// General + +// ContractAck is the response to be stored when a wasm hook is executed +type ContractAck struct { + ContractResult []byte `json:"contract_result"` + IbcAck []byte `json:"ibc_ack"` +} + +// IBCAckResponse is the response that a contract returns from the sudo() call on OnRecvPacket or RequestAck +type IBCAckResponse struct { + Packet channeltypes.Packet `json:"packet"` + ContractAck ContractAck `json:"contract_ack"` +} + +// IBCAckError is the error that a contract returns from the sudo() call on RequestAck +type IBCAckError struct { + Packet channeltypes.Packet `json:"packet"` + ErrorDescription string `json:"error_description"` + ErrorResponse string `json:"error_response"` +} + +type IBCAck struct { + Type string `json:"type"` + Content json.RawMessage `json:"content"` + // Note: These two fields have to be pointers so that they can be null + // If they are not pointers, they will be empty structs when null, + // which will cause issues with json.Unmarshal. + AckResponse *IBCAckResponse `json:"response,omitempty"` + AckError *IBCAckError `json:"error,omitempty"` +} + +func UnmarshalIBCAck(bz []byte) (*IBCAck, error) { + var ack IBCAck + if err := json.Unmarshal(bz, &ack); err != nil { + return nil, err + } + + switch ack.Type { + case "ack_response": + ack.AckResponse = &IBCAckResponse{} + if err := json.Unmarshal(ack.Content, ack.AckResponse); err != nil { + return nil, err + } + case "ack_error": + ack.AckError = &IBCAckError{} + if err := json.Unmarshal(ack.Content, ack.AckError); err != nil { + return nil, err + } + } + + return &ack, nil +} diff --git a/x/onion/wasm_hook.go b/x/onion/wasm_hook.go new file mode 100644 index 00000000..cca116ae --- /dev/null +++ b/x/onion/wasm_hook.go @@ -0,0 +1,381 @@ +package onion + +import ( + "encoding/json" + "fmt" + + sdk "github.com/cosmos/cosmos-sdk/types" + capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + + errorsmod "cosmossdk.io/errors" + "cosmossdk.io/math" + wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" + + "github.com/Team-Kujira/core/x/onion/keeper" + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" + ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" + + "github.com/Team-Kujira/core/x/onion/types" +) + +type WasmHooks struct { + ContractKeeper *wasmkeeper.Keeper + ibcHooksKeeper *keeper.Keeper + bech32PrefixAccAddr string +} + +func NewWasmHooks(ibcHooksKeeper *keeper.Keeper, contractKeeper *wasmkeeper.Keeper, bech32PrefixAccAddr string) WasmHooks { + return WasmHooks{ + ContractKeeper: contractKeeper, + ibcHooksKeeper: ibcHooksKeeper, + bech32PrefixAccAddr: bech32PrefixAccAddr, + } +} + +func (h WasmHooks) ProperlyConfigured() bool { + return h.ContractKeeper != nil && h.ibcHooksKeeper != nil +} + +func (h WasmHooks) OnRecvPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) ibcexported.Acknowledgement { + if !h.ProperlyConfigured() { + // Not configured + return im.App.OnRecvPacket(ctx, packet, relayer) + } + isIcs20, data := isIcs20Packet(packet.GetData()) + if !isIcs20 { + return im.App.OnRecvPacket(ctx, packet, relayer) + } + + // Validate the memo + isWasmRouted, contractAddr, msgBytes, err := ValidateAndParseMemo(data.GetMemo(), data.Receiver) + if !isWasmRouted { + return im.App.OnRecvPacket(ctx, packet, relayer) + } + if err != nil { + return NewEmitErrorAcknowledgement(ctx, types.ErrMsgValidation, err.Error()) + } + if msgBytes == nil || contractAddr == nil { // This should never happen + return NewEmitErrorAcknowledgement(ctx, types.ErrMsgValidation) + } + + // Calculate the receiver / contract caller based on the packet's channel and sender + channel := packet.GetDestChannel() + sender := data.GetSender() + senderBech32, err := keeper.DeriveIntermediateSender(channel, sender, h.bech32PrefixAccAddr) + if err != nil { + return NewEmitErrorAcknowledgement(ctx, types.ErrBadSender, fmt.Sprintf("cannot convert sender address %s/%s to bech32: %s", channel, sender, err.Error())) + } + + // The funds sent on this packet need to be transferred to the intermediary account for the sender. + // For this, we override the ICS20 packet's Receiver (essentially hijacking the funds to this new address) + // and execute the underlying OnRecvPacket() call (which should eventually land on the transfer app's + // relay.go and send the sunds to the intermediary account. + // + // If that succeeds, we make the contract call + data.Receiver = senderBech32 + bz, err := json.Marshal(data) + if err != nil { + return NewEmitErrorAcknowledgement(ctx, types.ErrMarshaling, err.Error()) + } + packet.Data = bz + + // Execute the receive + ack := im.App.OnRecvPacket(ctx, packet, relayer) + if !ack.Success() { + return ack + } + + amount, ok := math.NewIntFromString(data.GetAmount()) + if !ok { + // This should never happen, as it should've been caught in the underlying call to OnRecvPacket, + // but returning here for completeness + return NewEmitErrorAcknowledgement(ctx, types.ErrInvalidPacket, "Amount is not an int") + } + + // The packet's denom is the denom in the sender chain. This needs to be converted to the local denom. + denom := MustExtractDenomFromPacketOnRecv(packet) + funds := sdk.NewCoins(sdk.NewCoin(denom, amount)) + + // Execute the contract + execMsg := wasmtypes.MsgExecuteContract{ + Sender: senderBech32, + Contract: contractAddr.String(), + Msg: msgBytes, + Funds: funds, + } + response, err := h.execWasmMsg(ctx, &execMsg) + if err != nil { + return NewEmitErrorAcknowledgement(ctx, types.ErrWasmError, err.Error()) + } + + // Check if the contract is requesting for the ack to be async. + var asyncAckRequest types.OnRecvPacketAsyncAckResponse + err = json.Unmarshal(response.Data, &asyncAckRequest) + if err == nil { + // If unmarshalling succeeds, the contract is requesting for the ack to be async. + if asyncAckRequest.IsAsyncAck { // in which case IsAsyncAck is expected to be set to true + if !h.ibcHooksKeeper.IsInAllowList(ctx, contractAddr.String()) { + // Only allowed contracts can send async acks + return NewEmitErrorAcknowledgement(ctx, types.ErrAsyncAckNotAllowed) + } + // Store the contract as the packet's ack actor and return nil + h.ibcHooksKeeper.StorePacketAckActor(ctx, packet, contractAddr.String()) + return nil + } + } + + // If the ack is not async, we continue generating the ack and return it + fullAck := types.ContractAck{ContractResult: response.Data, IbcAck: ack.Acknowledgement()} + bz, err = json.Marshal(fullAck) + if err != nil { + return NewEmitErrorAcknowledgement(ctx, types.ErrBadResponse, err.Error()) + } + + return channeltypes.NewResultAcknowledgement(bz) +} + +func (h WasmHooks) execWasmMsg(ctx sdk.Context, execMsg *wasmtypes.MsgExecuteContract) (*wasmtypes.MsgExecuteContractResponse, error) { + if err := execMsg.ValidateBasic(); err != nil { + return nil, fmt.Errorf(types.ErrBadExecutionMsg, err.Error()) + } + wasmMsgServer := wasmkeeper.NewMsgServerImpl(h.ContractKeeper) + return wasmMsgServer.ExecuteContract(sdk.WrapSDKContext(ctx), execMsg) +} + +func isIcs20Packet(data []byte) (isIcs20 bool, ics20data transfertypes.FungibleTokenPacketData) { + var packetdata transfertypes.FungibleTokenPacketData + if err := json.Unmarshal(data, &packetdata); err != nil { + return false, packetdata + } + return true, packetdata +} + +// jsonStringHasKey parses the memo as a json object and checks if it contains the key. +func jsonStringHasKey(memo, key string) (found bool, jsonObject map[string]interface{}) { + jsonObject = make(map[string]interface{}) + + // If there is no memo, the packet was either sent with an earlier version of IBC, or the memo was + // intentionally left blank. Nothing to do here. Ignore the packet and pass it down the stack. + if len(memo) == 0 { + return false, jsonObject + } + + // the jsonObject must be a valid JSON object + err := json.Unmarshal([]byte(memo), &jsonObject) + if err != nil { + return false, jsonObject + } + + // If the key doesn't exist, there's nothing to do on this hook. Continue by passing the packet + // down the stack + _, ok := jsonObject[key] + if !ok { + return false, jsonObject + } + + return true, jsonObject +} + +func ValidateAndParseMemo(memo string, receiver string) (isWasmRouted bool, contractAddr sdk.AccAddress, msgBytes []byte, err error) { + isWasmRouted, metadata := jsonStringHasKey(memo, "wasm") + if !isWasmRouted { + return isWasmRouted, sdk.AccAddress{}, nil, nil + } + + wasmRaw := metadata["wasm"] + + // Make sure the wasm key is a map. If it isn't, ignore this packet + wasm, ok := wasmRaw.(map[string]interface{}) + if !ok { + return isWasmRouted, sdk.AccAddress{}, nil, + fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, "wasm metadata is not a valid JSON map object") + } + + // Get the contract + contract, ok := wasm["contract"].(string) + if !ok { + // The tokens will be returned + return isWasmRouted, sdk.AccAddress{}, nil, + fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, `Could not find key wasm["contract"]`) + } + + contractAddr, err = sdk.AccAddressFromBech32(contract) + if err != nil { + return isWasmRouted, sdk.AccAddress{}, nil, + fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, `wasm["contract"] is not a valid bech32 address`) + } + + // The contract and the receiver should be the same for the packet to be valid + if contract != receiver { + return isWasmRouted, sdk.AccAddress{}, nil, + fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, `wasm["contract"] should be the same as the receiver of the packet`) + } + + // Ensure the message key is provided + if wasm["msg"] == nil { + return isWasmRouted, sdk.AccAddress{}, nil, + fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, `Could not find key wasm["msg"]`) + } + + // Make sure the msg key is a map. If it isn't, return an error + _, ok = wasm["msg"].(map[string]interface{}) + if !ok { + return isWasmRouted, sdk.AccAddress{}, nil, + fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, `wasm["msg"] is not a map object`) + } + + // Get the message string by serializing the map + msgBytes, err = json.Marshal(wasm["msg"]) + if err != nil { + // The tokens will be returned + return isWasmRouted, sdk.AccAddress{}, nil, + fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, err.Error()) + } + + return isWasmRouted, contractAddr, msgBytes, nil +} + +func (h WasmHooks) SendPacketOverride(i ICS4Middleware, ctx sdk.Context, chanCap *capabilitytypes.Capability, sourcePort string, sourceChannel string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, data []byte) (uint64, error) { + isIcs20, ics20data := isIcs20Packet(data) + if !isIcs20 { + return i.channel.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data) // continue + } + + isCallbackRouted, metadata := jsonStringHasKey(ics20data.GetMemo(), types.IBCCallbackKey) + if !isCallbackRouted { + return i.channel.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data) // continue + } + + // We remove the callback metadata from the memo as it has already been processed. + + // If the only available key in the memo is the callback, we should remove the memo + // from the data completely so the packet is sent without it. + // This way receiver chains that are on old versions of IBC will be able to process the packet + callbackRaw := metadata[types.IBCCallbackKey] // This will be used later. + delete(metadata, types.IBCCallbackKey) + bzMetadata, err := json.Marshal(metadata) + if err != nil { + return 0, errorsmod.Wrap(err, "Send packet with callback error") + } + stringMetadata := string(bzMetadata) + if stringMetadata == "{}" { + ics20data.Memo = "" + } else { + ics20data.Memo = stringMetadata + } + dataBytes, err := json.Marshal(ics20data) + if err != nil { + return 0, errorsmod.Wrap(err, "Send packet with callback error") + } + + seq, err := i.channel.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, dataBytes) + if err != nil { + return 0, err + } + + // Make sure the callback contract is a string and a valid bech32 addr. If it isn't, ignore this packet + contract, ok := callbackRaw.(string) + if !ok { + return 0, nil + } + _, err = sdk.AccAddressFromBech32(contract) + if err != nil { + return 0, nil + } + + h.ibcHooksKeeper.StorePacketCallback(ctx, sourceChannel, seq, contract) + return seq, nil +} + +func (h WasmHooks) OnAcknowledgementPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) error { + err := im.App.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer) + if err != nil { + return err + } + + if !h.ProperlyConfigured() { + // Not configured. Return from the underlying implementation + return nil + } + + contract := h.ibcHooksKeeper.GetPacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) + if contract == "" { + // No callback configured + return nil + } + + contractAddr, err := sdk.AccAddressFromBech32(contract) + if err != nil { + return errorsmod.Wrap(err, "Ack callback error") // The callback configured is not a bech32. Error out + } + + success := "false" + if !IsAckError(acknowledgement) { + success = "true" + } + + // Notify the sender that the ack has been received + ackAsJson, err := json.Marshal(acknowledgement) + if err != nil { + // If the ack is not a json object, error + return err + } + + sudoMsg := []byte(fmt.Sprintf( + `{"ibc_lifecycle_complete": {"ibc_ack": {"channel": "%s", "sequence": %d, "ack": %s, "success": %s}}}`, + packet.SourceChannel, packet.Sequence, ackAsJson, success)) + _, err = h.ContractKeeper.Sudo(ctx, contractAddr, sudoMsg) + if err != nil { + // error processing the callback + // ToDo: Open Question: Should we also delete the callback here? + return errorsmod.Wrap(err, "Ack callback error") + } + h.ibcHooksKeeper.DeletePacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) + return nil +} + +func (h WasmHooks) OnTimeoutPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) error { + err := im.App.OnTimeoutPacket(ctx, packet, relayer) + if err != nil { + return err + } + + if !h.ProperlyConfigured() { + // Not configured. Return from the underlying implementation + return nil + } + + contract := h.ibcHooksKeeper.GetPacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) + if contract == "" { + // No callback configured + return nil + } + + contractAddr, err := sdk.AccAddressFromBech32(contract) + if err != nil { + return errorsmod.Wrap(err, "Timeout callback error") // The callback configured is not a bech32. Error out + } + + sudoMsg := []byte(fmt.Sprintf( + `{"ibc_lifecycle_complete": {"ibc_timeout": {"channel": "%s", "sequence": %d}}}`, + packet.SourceChannel, packet.Sequence)) + _, err = h.ContractKeeper.Sudo(ctx, contractAddr, sudoMsg) + if err != nil { + // error processing the callback. This could be because the contract doesn't implement the message type to + // process the callback. Retrying this will not help, so we can delete the callback from storage. + // Since the packet has timed out, we don't expect any other responses that may trigger the callback. + ctx.EventManager().EmitEvents(sdk.Events{ + sdk.NewEvent( + "ibc-timeout-callback-error", + sdk.NewAttribute("contract", contractAddr.String()), + sdk.NewAttribute("message", string(sudoMsg)), + sdk.NewAttribute("error", err.Error()), + ), + }) + } + h.ibcHooksKeeper.DeletePacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) + return nil +} From 3f3ec55c200acba41bc7b61370f80fbd99660ffa Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 4 Jun 2024 00:13:01 +0800 Subject: [PATCH 02/15] MsgRecvPacket parser for transaction acknowledgement --- app/app.go | 6 ++ app/prepare_proposal.go | 24 +++++++- app/process_proposal.go | 11 ++++ x/onion/client/cli/tx.go | 119 +++++++++++++++++++++++++++++++++++++++ x/onion/sdkmodule.go | 4 +- x/onion/types/keys.go | 2 +- 6 files changed, 162 insertions(+), 4 deletions(-) create mode 100644 app/process_proposal.go create mode 100644 x/onion/client/cli/tx.go diff --git a/app/app.go b/app/app.go index cd6d1448..0b4f0c13 100644 --- a/app/app.go +++ b/app/app.go @@ -229,6 +229,7 @@ var ( oracle.AppModuleBasic{}, alliancemodule.AppModuleBasic{}, cwica.AppModuleBasic{}, + onion.AppModuleBasic{}, ) // module account permissions @@ -984,6 +985,8 @@ func New( ), ibcwasm.NewAppModule(app.WasmClientKeeper), + + onion.NewAppModule(*app.OnionKeeper), ) // During begin block slashing happens after distr.BeginBlocker so that @@ -1021,6 +1024,7 @@ func New( alliancemoduletypes.ModuleName, cwicatypes.ModuleName, ibcwasmtypes.ModuleName, + oniontypes.ModuleName, ) app.ModuleManager.SetOrderEndBlockers( @@ -1054,6 +1058,7 @@ func New( alliancemoduletypes.ModuleName, cwicatypes.ModuleName, ibcwasmtypes.ModuleName, + oniontypes.ModuleName, ) // NOTE: The genutils module must occur after staking so that pools are @@ -1094,6 +1099,7 @@ func New( alliancemoduletypes.ModuleName, wasmtypes.ModuleName, cwicatypes.ModuleName, + oniontypes.ModuleName, ) app.ModuleManager.RegisterInvariants(app.CrisisKeeper) diff --git a/app/prepare_proposal.go b/app/prepare_proposal.go index 4e5bba3f..921aaf20 100644 --- a/app/prepare_proposal.go +++ b/app/prepare_proposal.go @@ -4,7 +4,9 @@ import ( "encoding/base64" abci "github.com/cometbft/cometbft/abci/types" - ibctransfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" + channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" ) func (app *App) PrepareProposal(req abci.RequestPrepareProposal) abci.ResponsePrepareProposal { @@ -17,7 +19,8 @@ func (app *App) PrepareProposal(req abci.RequestPrepareProposal) abci.ResponsePr msgs := tx.GetMsgs() for _, msg := range msgs { switch msg := msg.(type) { - case *ibctransfertypes.MsgTransfer: + case *banktypes.MsgSend: + case *transfertypes.MsgTransfer: if msg.Memo != "" { newRawTx, err := base64.StdEncoding.DecodeString(msg.Memo) if err != nil { @@ -29,6 +32,23 @@ func (app *App) PrepareProposal(req abci.RequestPrepareProposal) abci.ResponsePr } newTxs = append(newTxs, newRawTx) } + case *channeltypes.MsgRecvPacket: + packet := msg.Packet + var data transfertypes.FungibleTokenPacketData + if err := transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { + continue + } + if data.Memo != "" { + newRawTx, err := base64.StdEncoding.DecodeString(data.Memo) + if err != nil { + continue + } + _, err = app.txConfig.TxDecoder()(newRawTx) + if err != nil { + continue + } + newTxs = append(newTxs, newRawTx) + } } } } diff --git a/app/process_proposal.go b/app/process_proposal.go new file mode 100644 index 00000000..5e93e3cb --- /dev/null +++ b/app/process_proposal.go @@ -0,0 +1,11 @@ +package app + +import ( + abci "github.com/cometbft/cometbft/abci/types" +) + +func (app *App) ProcessProposal(req abci.RequestProcessProposal) (resp abci.ResponseProcessProposal) { + return abci.ResponseProcessProposal{ + Status: abci.ResponseProcessProposal_ACCEPT, + } +} diff --git a/x/onion/client/cli/tx.go b/x/onion/client/cli/tx.go new file mode 100644 index 00000000..dd35cfc4 --- /dev/null +++ b/x/onion/client/cli/tx.go @@ -0,0 +1,119 @@ +package cli + +import ( + "encoding/base64" + "errors" + "fmt" + "os" + + "github.com/spf13/cobra" + "github.com/spf13/pflag" + + "github.com/Team-Kujira/core/x/onion/types" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + sdktx "github.com/cosmos/cosmos-sdk/client/tx" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +var FlagSplit = "split" + +// NewTxCmd returns a root CLI command handler for all x/bank transaction commands. +func NewTxCmd() *cobra.Command { + txCmd := &cobra.Command{ + Use: types.ModuleName, + Short: "Onion transaction subcommands", + DisableFlagParsing: true, + SuggestionsMinimumDistance: 2, + RunE: client.ValidateCmd, + } + + txCmd.AddCommand( + NewSendTxCmd(), + ) + + return txCmd +} + +// NewSendTxCmd returns a CLI command handler for creating a MsgSend transaction. +func NewSendTxCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "send [from_key_or_address] [to_address] [amount]", + Short: "Send funds from one account to another.", + Long: `Send funds from one account to another. +Note, the '--from' flag is ignored as it is implied from [from_key_or_address]. +When using '--dry-run' a key name cannot be used, only a bech32 address. +`, + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + cmd.Flags().Set(flags.FlagFrom, args[0]) + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + toAddr, err := sdk.AccAddressFromBech32(args[1]) + if err != nil { + return err + } + + coins, err := sdk.ParseCoinsNormalized(args[2]) + if err != nil { + return err + } + + msg := banktypes.NewMsgSend(clientCtx.GetFromAddress(), toAddr, coins) + + return WriteBase64Tx(clientCtx, cmd.Flags(), msg) + }, + } + + flags.AddTxFlagsToCmd(cmd) + + return cmd +} + +func WriteBase64Tx(clientCtx client.Context, flagSet *pflag.FlagSet, msgs ...sdk.Msg) error { + txf, err := sdktx.NewFactoryCLI(clientCtx, flagSet) + if err != nil { + return err + } + + if txf.SimulateAndExecute() || clientCtx.Simulate { + if clientCtx.Offline { + return errors.New("cannot estimate gas in offline mode") + } + + _, adjusted, err := sdktx.CalculateGas(clientCtx, txf, msgs...) + if err != nil { + return err + } + + txf = txf.WithGas(adjusted) + _, _ = fmt.Fprintf(os.Stderr, "%s\n", sdktx.GasEstimateResponse{GasEstimate: txf.Gas()}) + } + + if clientCtx.Simulate { + return nil + } + + tx, err := txf.BuildUnsignedTx(msgs...) + if err != nil { + return err + } + + err = sdktx.Sign(txf, clientCtx.GetFromName(), tx, true) + if err != nil { + return err + } + + txBytes, err := clientCtx.TxConfig.TxEncoder()(tx.GetTx()) + if err != nil { + return err + } + + txBase64Encoding := base64.StdEncoding.EncodeToString(txBytes) + fmt.Println(txBase64Encoding) + return nil +} diff --git a/x/onion/sdkmodule.go b/x/onion/sdkmodule.go index 89199854..6637675f 100644 --- a/x/onion/sdkmodule.go +++ b/x/onion/sdkmodule.go @@ -65,7 +65,9 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {} // GetTxCmd returns no root tx command for the ibc-hooks module. -func (AppModuleBasic) GetTxCmd() *cobra.Command { return nil } +func (AppModuleBasic) GetTxCmd() *cobra.Command { + return cli.NewTxCmd() +} // GetQueryCmd returns the root query command for the ibc-hooks module. func (AppModuleBasic) GetQueryCmd() *cobra.Command { diff --git a/x/onion/types/keys.go b/x/onion/types/keys.go index db7527bd..df5740ed 100644 --- a/x/onion/types/keys.go +++ b/x/onion/types/keys.go @@ -1,7 +1,7 @@ package types const ( - ModuleName = "ibchooks" + ModuleName = "onion" RouterKey = ModuleName StoreKey = "hooks-for-ibc" // not using the module name because of collisions with key "ibc" From 875ef24205d61af5624e6b5a2bb831c40024dbd3 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Thu, 6 Jun 2024 21:04:02 +0800 Subject: [PATCH 03/15] execute memo tx in ibc middleware --- app/app.go | 3 +- app/prepare_proposal.go | 110 +++++++++++++++++++------------------- app/process_proposal.go | 16 +++--- x/onion/ibc_module.go | 41 ++++++++++++-- x/onion/keeper/execute.go | 31 +++++++++++ x/onion/keeper/keeper.go | 5 ++ 6 files changed, 137 insertions(+), 69 deletions(-) create mode 100644 x/onion/keeper/execute.go diff --git a/app/app.go b/app/app.go index 0b4f0c13..65e9fabe 100644 --- a/app/app.go +++ b/app/app.go @@ -560,6 +560,7 @@ func New( app.GetSubspace(oniontypes.ModuleName), app.IBCKeeper.ChannelKeeper, nil, + app.MsgServiceRouter(), ) app.OnionKeeper = hooksKeeper @@ -781,7 +782,7 @@ func New( var transferStack ibcporttypes.IBCModule transferStack = transfer.NewIBCModule(app.TransferKeeper) transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper) - transferStack = onion.NewIBCMiddleware(transferStack, &app.HooksICS4Wrapper) + transferStack = onion.NewIBCMiddleware(transferStack, &app.HooksICS4Wrapper, app.OnionKeeper, encodingConfig.TxConfig) // Create Interchain Accounts Stack // SendPacket, since it is originating from the application to core IBC: diff --git a/app/prepare_proposal.go b/app/prepare_proposal.go index 921aaf20..ccb62f19 100644 --- a/app/prepare_proposal.go +++ b/app/prepare_proposal.go @@ -1,59 +1,59 @@ package app -import ( - "encoding/base64" +// import ( +// "encoding/base64" - abci "github.com/cometbft/cometbft/abci/types" - banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" - transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" -) +// abci "github.com/cometbft/cometbft/abci/types" +// banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +// transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" +// channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" +// ) -func (app *App) PrepareProposal(req abci.RequestPrepareProposal) abci.ResponsePrepareProposal { - newTxs := [][]byte{} - for _, rawTx := range req.Txs { - tx, err := app.txConfig.TxDecoder()(rawTx) - if err != nil { - continue - } - msgs := tx.GetMsgs() - for _, msg := range msgs { - switch msg := msg.(type) { - case *banktypes.MsgSend: - case *transfertypes.MsgTransfer: - if msg.Memo != "" { - newRawTx, err := base64.StdEncoding.DecodeString(msg.Memo) - if err != nil { - continue - } - _, err = app.txConfig.TxDecoder()(newRawTx) - if err != nil { - continue - } - newTxs = append(newTxs, newRawTx) - } - case *channeltypes.MsgRecvPacket: - packet := msg.Packet - var data transfertypes.FungibleTokenPacketData - if err := transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { - continue - } - if data.Memo != "" { - newRawTx, err := base64.StdEncoding.DecodeString(data.Memo) - if err != nil { - continue - } - _, err = app.txConfig.TxDecoder()(newRawTx) - if err != nil { - continue - } - newTxs = append(newTxs, newRawTx) - } - } - } - } - txs := append(req.Txs, newTxs...) - return abci.ResponsePrepareProposal{ - Txs: txs, - } -} +// func (app *App) PrepareProposal(req abci.RequestPrepareProposal) abci.ResponsePrepareProposal { +// newTxs := [][]byte{} +// for _, rawTx := range req.Txs { +// tx, err := app.txConfig.TxDecoder()(rawTx) +// if err != nil { +// continue +// } +// msgs := tx.GetMsgs() +// for _, msg := range msgs { +// switch msg := msg.(type) { +// case *banktypes.MsgSend: +// case *transfertypes.MsgTransfer: +// if msg.Memo != "" { +// newRawTx, err := base64.StdEncoding.DecodeString(msg.Memo) +// if err != nil { +// continue +// } +// _, err = app.txConfig.TxDecoder()(newRawTx) +// if err != nil { +// continue +// } +// newTxs = append(newTxs, newRawTx) +// } +// case *channeltypes.MsgRecvPacket: +// packet := msg.Packet +// var data transfertypes.FungibleTokenPacketData +// if err := transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { +// continue +// } +// if data.Memo != "" { +// newRawTx, err := base64.StdEncoding.DecodeString(data.Memo) +// if err != nil { +// continue +// } +// _, err = app.txConfig.TxDecoder()(newRawTx) +// if err != nil { +// continue +// } +// newTxs = append(newTxs, newRawTx) +// } +// } +// } +// } +// txs := append(req.Txs, newTxs...) +// return abci.ResponsePrepareProposal{ +// Txs: txs, +// } +// } diff --git a/app/process_proposal.go b/app/process_proposal.go index 5e93e3cb..247dff9f 100644 --- a/app/process_proposal.go +++ b/app/process_proposal.go @@ -1,11 +1,11 @@ package app -import ( - abci "github.com/cometbft/cometbft/abci/types" -) +// import ( +// abci "github.com/cometbft/cometbft/abci/types" +// ) -func (app *App) ProcessProposal(req abci.RequestProcessProposal) (resp abci.ResponseProcessProposal) { - return abci.ResponseProcessProposal{ - Status: abci.ResponseProcessProposal_ACCEPT, - } -} +// func (app *App) ProcessProposal(req abci.RequestProcessProposal) (resp abci.ResponseProcessProposal) { +// return abci.ResponseProcessProposal{ +// Status: abci.ResponseProcessProposal_ACCEPT, +// } +// } diff --git a/x/onion/ibc_module.go b/x/onion/ibc_module.go index edaba2e7..a6eb91f4 100644 --- a/x/onion/ibc_module.go +++ b/x/onion/ibc_module.go @@ -2,10 +2,15 @@ package onion import ( // external libraries + "encoding/base64" + sdk "github.com/cosmos/cosmos-sdk/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" // ibc-go + "github.com/Team-Kujira/core/x/onion/keeper" + "github.com/cosmos/cosmos-sdk/client" clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" @@ -15,14 +20,23 @@ import ( var _ porttypes.Middleware = &IBCMiddleware{} type IBCMiddleware struct { - App porttypes.IBCModule - ICS4Middleware *ICS4Middleware + App porttypes.IBCModule + ICS4Middleware *ICS4Middleware + Keeper *keeper.Keeper + txEncodingConfig client.TxEncodingConfig } -func NewIBCMiddleware(app porttypes.IBCModule, ics4 *ICS4Middleware) IBCMiddleware { +func NewIBCMiddleware( + app porttypes.IBCModule, + ics4 *ICS4Middleware, + Keeper *keeper.Keeper, + txEncodingConfig client.TxEncodingConfig, +) IBCMiddleware { return IBCMiddleware{ - App: app, - ICS4Middleware: ics4, + App: app, + ICS4Middleware: ics4, + Keeper: Keeper, + txEncodingConfig: txEncodingConfig, } } @@ -173,6 +187,23 @@ func (im IBCMiddleware) OnRecvPacket( packet channeltypes.Packet, relayer sdk.AccAddress, ) ibcexported.Acknowledgement { + var data transfertypes.FungibleTokenPacketData + if err := transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err == nil { + if data.Memo != "" { + newRawTx, err := base64.StdEncoding.DecodeString(data.Memo) + if err == nil { + tx, err := im.txEncodingConfig.TxDecoder()(newRawTx) + if err == nil { + cacheCtx, write := ctx.CacheContext() + _, err = im.Keeper.ExecuteTxMsgs(cacheCtx, tx) + if err == nil { + write() + } + } + } + } + } + if hook, ok := im.ICS4Middleware.Hooks.(OnRecvPacketOverrideHooks); ok { return hook.OnRecvPacketOverride(im, ctx, packet, relayer) } diff --git a/x/onion/keeper/execute.go b/x/onion/keeper/execute.go new file mode 100644 index 00000000..125424ca --- /dev/null +++ b/x/onion/keeper/execute.go @@ -0,0 +1,31 @@ +package keeper + +import ( + "fmt" + + errorsmod "cosmossdk.io/errors" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/x/group/errors" +) + +func (k Keeper) ExecuteTxMsgs(ctx sdk.Context, tx sdk.Tx) ([]sdk.Result, error) { + msgs := tx.GetMsgs() + results := make([]sdk.Result, len(msgs)) + for i, msg := range msgs { + handler := k.router.Handler(msg) + if handler == nil { + return nil, errorsmod.Wrapf(errors.ErrInvalid, "no message handler found for %q", sdk.MsgTypeURL(msg)) + } + r, err := handler(ctx, msg) + if err != nil { + return nil, errorsmod.Wrapf(err, "message %s at position %d", sdk.MsgTypeURL(msg), i) + } + // Handler should always return non-nil sdk.Result. + if r == nil { + return nil, fmt.Errorf("got nil sdk.Result for message %q at position %d", msg, i) + } + + results[i] = *r + } + return results, nil +} diff --git a/x/onion/keeper/keeper.go b/x/onion/keeper/keeper.go index a0793bf1..44cf1395 100644 --- a/x/onion/keeper/keeper.go +++ b/x/onion/keeper/keeper.go @@ -18,6 +18,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/baseapp" storetypes "github.com/cosmos/cosmos-sdk/store/types" ) @@ -28,6 +29,8 @@ type ( channelKeeper types.ChannelKeeper ContractKeeper *wasmkeeper.PermissionedKeeper + + router *baseapp.MsgServiceRouter } ) @@ -37,6 +40,7 @@ func NewKeeper( paramSpace paramtypes.Subspace, channelKeeper types.ChannelKeeper, contractKeeper *wasmkeeper.PermissionedKeeper, + router *baseapp.MsgServiceRouter, ) *Keeper { if !paramSpace.HasKeyTable() { paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable()) @@ -46,6 +50,7 @@ func NewKeeper( paramSpace: paramSpace, channelKeeper: channelKeeper, ContractKeeper: contractKeeper, + router: router, } } From af7c7485fee91ed9b14a4b49ea25eab7393b007f Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 11 Jun 2024 01:15:04 +0800 Subject: [PATCH 04/15] add signature verification in onion memo tx --- app/app.go | 2 + x/onion/client/cli/tx.go | 5 + x/onion/ibc_module.go | 7 +- x/onion/keeper/execute.go | 173 ++++++++++++++++++++++++++++++ x/onion/keeper/keeper.go | 30 +++--- x/onion/types/expected_keepers.go | 8 ++ 6 files changed, 210 insertions(+), 15 deletions(-) diff --git a/app/app.go b/app/app.go index 65e9fabe..cfb2fc44 100644 --- a/app/app.go +++ b/app/app.go @@ -561,6 +561,8 @@ func New( app.IBCKeeper.ChannelKeeper, nil, app.MsgServiceRouter(), + app.AccountKeeper, + txConfig.SignModeHandler(), ) app.OnionKeeper = hooksKeeper diff --git a/x/onion/client/cli/tx.go b/x/onion/client/cli/tx.go index dd35cfc4..79a33872 100644 --- a/x/onion/client/cli/tx.go +++ b/x/onion/client/cli/tx.go @@ -80,6 +80,11 @@ func WriteBase64Tx(clientCtx client.Context, flagSet *pflag.FlagSet, msgs ...sdk return err } + txf, err = txf.Prepare(clientCtx) + if err != nil { + return err + } + if txf.SimulateAndExecute() || clientCtx.Simulate { if clientCtx.Offline { return errors.New("cannot estimate gas in offline mode") diff --git a/x/onion/ibc_module.go b/x/onion/ibc_module.go index a6eb91f4..8c836e8b 100644 --- a/x/onion/ibc_module.go +++ b/x/onion/ibc_module.go @@ -195,9 +195,12 @@ func (im IBCMiddleware) OnRecvPacket( tx, err := im.txEncodingConfig.TxDecoder()(newRawTx) if err == nil { cacheCtx, write := ctx.CacheContext() - _, err = im.Keeper.ExecuteTxMsgs(cacheCtx, tx) + err = im.Keeper.ExecuteAnte(cacheCtx, tx) if err == nil { - write() + _, err = im.Keeper.ExecuteTxMsgs(cacheCtx, tx) + if err == nil { + write() + } } } } diff --git a/x/onion/keeper/execute.go b/x/onion/keeper/execute.go index 125424ca..0adf95f3 100644 --- a/x/onion/keeper/execute.go +++ b/x/onion/keeper/execute.go @@ -1,13 +1,186 @@ package keeper import ( + "bytes" "fmt" errorsmod "cosmossdk.io/errors" + "github.com/Team-Kujira/core/x/onion/types" + kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + txsigning "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/group/errors" ) +func GetSignerAcc(ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress) (authtypes.AccountI, error) { + if acc := ak.GetAccount(ctx, addr); acc != nil { + return acc, nil + } + + return nil, errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr) +} + +// CountSubKeys counts the total number of keys for a multi-sig public key. +func CountSubKeys(pub cryptotypes.PubKey) int { + v, ok := pub.(*kmultisig.LegacyAminoPubKey) + if !ok { + return 1 + } + + numKeys := 0 + for _, subkey := range v.GetPubKeys() { + numKeys += CountSubKeys(subkey) + } + + return numKeys +} + +func OnlyLegacyAminoSigners(sigData txsigning.SignatureData) bool { + switch v := sigData.(type) { + case *txsigning.SingleSignatureData: + return v.SignMode == txsigning.SignMode_SIGN_MODE_LEGACY_AMINO_JSON + case *txsigning.MultiSignatureData: + for _, s := range v.Signatures { + if !OnlyLegacyAminoSigners(s) { + return false + } + } + return true + default: + return false + } +} + +func (k Keeper) ExecuteAnte(ctx sdk.Context, tx sdk.Tx) error { + // ValidateBasicDecorator + if err := tx.ValidateBasic(); err != nil { + return err + } + + // SetPubKeyDecorator + sigTx, ok := tx.(authsigning.SigVerifiableTx) + if !ok { + return errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid tx type") + } + + pubkeys, err := sigTx.GetPubKeys() + if err != nil { + return err + } + signers := sigTx.GetSigners() + + for i, pk := range pubkeys { + if pk == nil { + continue + } + if !bytes.Equal(pk.Address(), signers[i]) { + return errorsmod.Wrapf(sdkerrors.ErrInvalidPubKey, + "pubKey does not match signer address %s with signer index: %d", signers[i], i) + } + + acc, err := GetSignerAcc(ctx, k.accountKeeper, signers[i]) + if err != nil { + return err + } + if acc.GetPubKey() != nil { + continue + } + err = acc.SetPubKey(pk) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, err.Error()) + } + k.accountKeeper.SetAccount(ctx, acc) + } + + // ValidateSigCountDecorator + params := k.accountKeeper.GetParams(ctx) + pubKeys, err := sigTx.GetPubKeys() + if err != nil { + return err + } + + sigCount := 0 + for _, pk := range pubKeys { + sigCount += CountSubKeys(pk) + if uint64(sigCount) > params.TxSigLimit { + return errorsmod.Wrapf(sdkerrors.ErrTooManySignatures, + "signatures: %d, limit: %d", sigCount, params.TxSigLimit) + } + } + + // SigVerificationDecorator + sigs, err := sigTx.GetSignaturesV2() + if err != nil { + return err + } + + signerAddrs := sigTx.GetSigners() + + if len(sigs) != len(signerAddrs) { + return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs)) + } + + for i, sig := range sigs { + acc, err := GetSignerAcc(ctx, k.accountKeeper, signerAddrs[i]) + if err != nil { + return err + } + + pubKey := acc.GetPubKey() + if pubKey == nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set") + } + + if sig.Sequence != acc.GetSequence() { + return errorsmod.Wrapf( + sdkerrors.ErrWrongSequence, + "account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence, + ) + } + + genesis := ctx.BlockHeight() == 0 + chainID := ctx.ChainID() + var accNum uint64 + if !genesis { + accNum = acc.GetAccountNumber() + } + signerData := authsigning.SignerData{ + Address: acc.GetAddress().String(), + ChainID: chainID, + AccountNumber: accNum, + Sequence: acc.GetSequence(), + PubKey: pubKey, + } + + err = authsigning.VerifySignature(pubKey, signerData, sig.Data, k.signModeHandler, tx) + if err != nil { + var errMsg string + if OnlyLegacyAminoSigners(sig.Data) { + errMsg = fmt.Sprintf("signature verification failed; please verify account number (%d), sequence (%d) and chain-id (%s)", accNum, acc.GetSequence(), chainID) + } else { + errMsg = fmt.Sprintf("signature verification failed; please verify account number (%d) and chain-id (%s)", accNum, chainID) + } + return errorsmod.Wrap(sdkerrors.ErrUnauthorized, errMsg) + } + } + + // IncrementSequenceDecorator + for _, addr := range sigTx.GetSigners() { + acc := k.accountKeeper.GetAccount(ctx, addr) + if err := acc.SetSequence(acc.GetSequence() + 1); err != nil { + panic(err) + } + + k.accountKeeper.SetAccount(ctx, acc) + } + + return nil +} + func (k Keeper) ExecuteTxMsgs(ctx sdk.Context, tx sdk.Tx) ([]sdk.Result, error) { msgs := tx.GetMsgs() results := make([]sdk.Result, len(msgs)) diff --git a/x/onion/keeper/keeper.go b/x/onion/keeper/keeper.go index 44cf1395..9adbcf2e 100644 --- a/x/onion/keeper/keeper.go +++ b/x/onion/keeper/keeper.go @@ -7,19 +7,17 @@ import ( "strings" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" + "github.com/Team-Kujira/core/x/onion/types" "github.com/cometbft/cometbft/crypto/tmhash" "github.com/cometbft/cometbft/libs/log" + "github.com/cosmos/cosmos-sdk/baseapp" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/address" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - - "github.com/Team-Kujira/core/x/onion/types" - - sdk "github.com/cosmos/cosmos-sdk/types" - - "github.com/cosmos/cosmos-sdk/baseapp" - storetypes "github.com/cosmos/cosmos-sdk/store/types" ) type ( @@ -29,8 +27,10 @@ type ( channelKeeper types.ChannelKeeper ContractKeeper *wasmkeeper.PermissionedKeeper + accountKeeper types.AccountKeeper - router *baseapp.MsgServiceRouter + router *baseapp.MsgServiceRouter + signModeHandler authsigning.SignModeHandler } ) @@ -41,16 +41,20 @@ func NewKeeper( channelKeeper types.ChannelKeeper, contractKeeper *wasmkeeper.PermissionedKeeper, router *baseapp.MsgServiceRouter, + accountKeeper types.AccountKeeper, + signModeHandler authsigning.SignModeHandler, ) *Keeper { if !paramSpace.HasKeyTable() { paramSpace = paramSpace.WithKeyTable(types.ParamKeyTable()) } return &Keeper{ - storeKey: storeKey, - paramSpace: paramSpace, - channelKeeper: channelKeeper, - ContractKeeper: contractKeeper, - router: router, + storeKey: storeKey, + paramSpace: paramSpace, + channelKeeper: channelKeeper, + ContractKeeper: contractKeeper, + router: router, + accountKeeper: accountKeeper, + signModeHandler: signModeHandler, } } diff --git a/x/onion/types/expected_keepers.go b/x/onion/types/expected_keepers.go index 59761e41..bb12dc77 100644 --- a/x/onion/types/expected_keepers.go +++ b/x/onion/types/expected_keepers.go @@ -2,6 +2,7 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" "github.com/cosmos/ibc-go/v7/modules/core/exported" @@ -14,3 +15,10 @@ type ChannelKeeper interface { LookupModuleByChannel(ctx sdk.Context, portID, channelID string) (string, *capabilitytypes.Capability, error) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet exported.PacketI, acknowledgement exported.Acknowledgement) error } + +type AccountKeeper interface { + GetParams(ctx sdk.Context) (params authtypes.Params) + GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI + SetAccount(ctx sdk.Context, acc authtypes.AccountI) + GetModuleAddress(moduleName string) sdk.AccAddress +} From 9d31ece71dcaa6fcd31f3a7d032939943985ac98 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Wed, 12 Jun 2024 01:10:16 +0800 Subject: [PATCH 05/15] use onion sequence in signature verification and onion sing --- app/app.go | 3 +- proto/kujira/onion/genesis.proto | 10 +- proto/kujira/onion/query.proto | 20 ++ x/onion/client/cli/query.go | 30 ++ x/onion/client/cli/tx.go | 11 + x/onion/keeper/execute.go | 27 +- x/onion/keeper/keeper.go | 6 +- x/onion/keeper/query.go | 20 ++ x/onion/keeper/sequence.go | 59 ++++ x/onion/sdkmodule.go | 1 + x/onion/types/genesis.pb.go | 292 +++++++++++++++- x/onion/types/keys.go | 2 + x/onion/types/query.pb.go | 582 +++++++++++++++++++++++++++++++ x/onion/types/query.pb.gw.go | 184 ++++++++++ 14 files changed, 1226 insertions(+), 21 deletions(-) create mode 100644 proto/kujira/onion/query.proto create mode 100644 x/onion/keeper/query.go create mode 100644 x/onion/keeper/sequence.go create mode 100644 x/onion/types/query.pb.go create mode 100644 x/onion/types/query.pb.gw.go diff --git a/app/app.go b/app/app.go index cfb2fc44..04e0c779 100644 --- a/app/app.go +++ b/app/app.go @@ -555,7 +555,7 @@ func New( ) // Configure the hooks keeper - hooksKeeper := onionkeeper.NewKeeper( + app.OnionKeeper = onionkeeper.NewKeeper( keys[oniontypes.StoreKey], app.GetSubspace(oniontypes.ModuleName), app.IBCKeeper.ChannelKeeper, @@ -564,7 +564,6 @@ func New( app.AccountKeeper, txConfig.SignModeHandler(), ) - app.OnionKeeper = hooksKeeper app.WireICS20PreWasmKeeper(appCodec, bApp, app.OnionKeeper) diff --git a/proto/kujira/onion/genesis.proto b/proto/kujira/onion/genesis.proto index f2caa86d..b6734487 100644 --- a/proto/kujira/onion/genesis.proto +++ b/proto/kujira/onion/genesis.proto @@ -7,4 +7,12 @@ import "kujira/onion/params.proto"; option go_package = "github.com/Team-Kujira/core/x/onion/types"; -message GenesisState { Params params = 1 [ (gogoproto.nullable) = false ]; } +message GenesisState { + Params params = 1 [ (gogoproto.nullable) = false ]; + repeated OnionSequence sequences = 2 [ (gogoproto.nullable) = false ]; +} + +message OnionSequence { + string address = 1; + uint64 sequence = 2; +} \ No newline at end of file diff --git a/proto/kujira/onion/query.proto b/proto/kujira/onion/query.proto new file mode 100644 index 00000000..a4f3afb8 --- /dev/null +++ b/proto/kujira/onion/query.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; +package kujira.onion; + +import "gogoproto/gogo.proto"; +import "google/api/annotations.proto"; +import "kujira/onion/genesis.proto"; + +option go_package = "github.com/Team-Kujira/core/x/onion/types"; + +// Query defines the gRPC querier service. +service Query { + rpc Sequence(QuerySequenceRequest) returns (QuerySequenceResponse) { + option (google.api.http).get = "/kujira/onion/sequence/{address}"; + } +} + +message QuerySequenceRequest { string address = 1; } +message QuerySequenceResponse { + OnionSequence seq = 1 [ (gogoproto.nullable) = false ]; +} diff --git a/x/onion/client/cli/query.go b/x/onion/client/cli/query.go index bc3641be..3ca04fb8 100644 --- a/x/onion/client/cli/query.go +++ b/x/onion/client/cli/query.go @@ -1,9 +1,11 @@ package cli import ( + "context" "fmt" "strings" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/version" @@ -39,6 +41,7 @@ func GetQueryCmd() *cobra.Command { cmd.AddCommand( GetCmdWasmSender(), + GetCmdQuerySequence(), ) return cmd } @@ -75,3 +78,30 @@ $ %s query ibc-hooks wasm-hooks-sender channel-42 juno12smx2wdlyttvyzvzg54y2vnqw return cmd } + +// GetCmdQuerySequence implements the query sequence command. +func GetCmdQuerySequence() *cobra.Command { + cmd := &cobra.Command{ + Use: "sequence [address]", + Args: cobra.ExactArgs(1), + Short: "Query the onion sequence of an address", + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientQueryContext(cmd) + if err != nil { + return err + } + queryClient := types.NewQueryClient(clientCtx) + res, err := queryClient.Sequence(context.Background(), &types.QuerySequenceRequest{ + Address: args[0], + }) + if err != nil { + return err + } + + return clientCtx.PrintProto(res) + }, + } + + flags.AddQueryFlagsToCmd(cmd) + return cmd +} diff --git a/x/onion/client/cli/tx.go b/x/onion/client/cli/tx.go index 79a33872..604066fe 100644 --- a/x/onion/client/cli/tx.go +++ b/x/onion/client/cli/tx.go @@ -1,6 +1,7 @@ package cli import ( + "context" "encoding/base64" "errors" "fmt" @@ -85,6 +86,16 @@ func WriteBase64Tx(clientCtx client.Context, flagSet *pflag.FlagSet, msgs ...sdk return err } + queryClient := types.NewQueryClient(clientCtx) + newSeq := uint64(0) + res, err := queryClient.Sequence(context.Background(), &types.QuerySequenceRequest{ + Address: clientCtx.GetFromAddress().String(), + }) + if err == nil { + newSeq = res.Seq.Sequence + } + txf = txf.WithSequence(newSeq) + if txf.SimulateAndExecute() || clientCtx.Simulate { if clientCtx.Offline { return errors.New("cannot estimate gas in offline mode") diff --git a/x/onion/keeper/execute.go b/x/onion/keeper/execute.go index 0adf95f3..3069dcef 100644 --- a/x/onion/keeper/execute.go +++ b/x/onion/keeper/execute.go @@ -135,10 +135,16 @@ func (k Keeper) ExecuteAnte(ctx sdk.Context, tx sdk.Tx) error { return errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set") } - if sig.Sequence != acc.GetSequence() { + onionSeq := uint64(0) + seq, err := k.GetSequence(ctx, acc.GetAddress().String()) + if err == nil { + onionSeq = seq.Sequence + } + + if sig.Sequence != onionSeq { return errorsmod.Wrapf( sdkerrors.ErrWrongSequence, - "account sequence mismatch, expected %d, got %d", acc.GetSequence(), sig.Sequence, + "onion sequence mismatch, expected %d, got %d", onionSeq, sig.Sequence, ) } @@ -152,7 +158,7 @@ func (k Keeper) ExecuteAnte(ctx sdk.Context, tx sdk.Tx) error { Address: acc.GetAddress().String(), ChainID: chainID, AccountNumber: accNum, - Sequence: acc.GetSequence(), + Sequence: onionSeq, PubKey: pubKey, } @@ -170,12 +176,19 @@ func (k Keeper) ExecuteAnte(ctx sdk.Context, tx sdk.Tx) error { // IncrementSequenceDecorator for _, addr := range sigTx.GetSigners() { - acc := k.accountKeeper.GetAccount(ctx, addr) - if err := acc.SetSequence(acc.GetSequence() + 1); err != nil { - panic(err) + seq, err := k.GetSequence(ctx, addr.String()) + if err != nil { + seq = types.OnionSequence{ + Address: addr.String(), + Sequence: 0, + } } - k.accountKeeper.SetAccount(ctx, acc) + seq.Sequence++ + err = k.SetSequence(ctx, seq) + if err != nil { + return err + } } return nil diff --git a/x/onion/keeper/keeper.go b/x/onion/keeper/keeper.go index 9adbcf2e..c9ccfbef 100644 --- a/x/onion/keeper/keeper.go +++ b/x/onion/keeper/keeper.go @@ -81,11 +81,15 @@ func (k Keeper) SetParam(ctx sdk.Context, key []byte, value interface{}) { func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) { k.SetParams(ctx, genState.Params) + for _, seq := range genState.Sequences { + k.SetSequence(ctx, seq) + } } func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { return &types.GenesisState{ - Params: k.GetParams(ctx), + Params: k.GetParams(ctx), + Sequences: k.GetAllSequences(ctx), } } diff --git a/x/onion/keeper/query.go b/x/onion/keeper/query.go new file mode 100644 index 00000000..373afe8a --- /dev/null +++ b/x/onion/keeper/query.go @@ -0,0 +1,20 @@ +package keeper + +import ( + "context" + + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/Team-Kujira/core/x/onion/types" +) + +var _ types.QueryServer = Keeper{} + +func (k Keeper) Sequence(c context.Context, req *types.QuerySequenceRequest) (*types.QuerySequenceResponse, error) { + ctx := sdk.UnwrapSDKContext(c) + seq, err := k.GetSequence(ctx, req.Address) + if err != nil { + return nil, err + } + return &types.QuerySequenceResponse{Seq: seq}, nil +} diff --git a/x/onion/keeper/sequence.go b/x/onion/keeper/sequence.go new file mode 100644 index 00000000..a5efde6a --- /dev/null +++ b/x/onion/keeper/sequence.go @@ -0,0 +1,59 @@ +package keeper + +import ( + "github.com/cosmos/cosmos-sdk/store/prefix" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" + + "github.com/Team-Kujira/core/x/onion/types" +) + +// GetAuthorityMetadata returns the authority metadata for a specific denom +func (k Keeper) GetSequence(ctx sdk.Context, address string) (types.OnionSequence, error) { + store := ctx.KVStore(k.storeKey) + prefixStore := prefix.NewStore(store, []byte(types.OnionSequencePrefix)) + bz := prefixStore.Get([]byte(address)) + if bz == nil { + return types.OnionSequence{ + Address: address, + Sequence: 0, + }, nil + } + sequence := types.OnionSequence{} + err := proto.Unmarshal(bz, &sequence) + if err != nil { + return types.OnionSequence{}, err + } + return sequence, nil +} + +// SetAuthorityMetadata stores authority metadata for a specific denom +func (k Keeper) SetSequence(ctx sdk.Context, sequence types.OnionSequence) error { + store := ctx.KVStore(k.storeKey) + prefixStore := prefix.NewStore(store, []byte(types.OnionSequencePrefix)) + + bz, err := proto.Marshal(&sequence) + if err != nil { + return err + } + + prefixStore.Set([]byte(sequence.Address), bz) + return nil +} + +func (k Keeper) GetAllSequences(ctx sdk.Context) []types.OnionSequence { + store := ctx.KVStore(k.storeKey) + iterator := sdk.KVStorePrefixIterator(store, []byte{}) + defer iterator.Close() + + sequences := []types.OnionSequence{} + for ; iterator.Valid(); iterator.Next() { + sequence := types.OnionSequence{} + err := proto.Unmarshal(iterator.Value(), &sequence) + if err != nil { + panic(err) + } + sequences = append(sequences, sequence) + } + return sequences +} diff --git a/x/onion/sdkmodule.go b/x/onion/sdkmodule.go index 6637675f..91a1d15d 100644 --- a/x/onion/sdkmodule.go +++ b/x/onion/sdkmodule.go @@ -108,6 +108,7 @@ func (AppModule) QuerierRoute() string { // module-specific gRPC queries. func (am AppModule) RegisterServices(cfg module.Configurator) { types.RegisterMsgServer(cfg.MsgServer(), keeper.NewMsgServerImpl(am.keeper)) + types.RegisterQueryServer(cfg.QueryServer(), am.keeper) } // InitGenesis performs genesis initialization for the ibc-hooks module. It returns diff --git a/x/onion/types/genesis.pb.go b/x/onion/types/genesis.pb.go index 70bef3cd..f85d2aaa 100644 --- a/x/onion/types/genesis.pb.go +++ b/x/onion/types/genesis.pb.go @@ -25,7 +25,8 @@ var _ = math.Inf const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type GenesisState struct { - Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + Params Params `protobuf:"bytes,1,opt,name=params,proto3" json:"params"` + Sequences []OnionSequence `protobuf:"bytes,2,rep,name=sequences,proto3" json:"sequences"` } func (m *GenesisState) Reset() { *m = GenesisState{} } @@ -68,27 +69,92 @@ func (m *GenesisState) GetParams() Params { return Params{} } +func (m *GenesisState) GetSequences() []OnionSequence { + if m != nil { + return m.Sequences + } + return nil +} + +type OnionSequence struct { + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` + Sequence uint64 `protobuf:"varint,2,opt,name=sequence,proto3" json:"sequence,omitempty"` +} + +func (m *OnionSequence) Reset() { *m = OnionSequence{} } +func (m *OnionSequence) String() string { return proto.CompactTextString(m) } +func (*OnionSequence) ProtoMessage() {} +func (*OnionSequence) Descriptor() ([]byte, []int) { + return fileDescriptor_e5d80ee52a36c767, []int{1} +} +func (m *OnionSequence) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *OnionSequence) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_OnionSequence.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *OnionSequence) XXX_Merge(src proto.Message) { + xxx_messageInfo_OnionSequence.Merge(m, src) +} +func (m *OnionSequence) XXX_Size() int { + return m.Size() +} +func (m *OnionSequence) XXX_DiscardUnknown() { + xxx_messageInfo_OnionSequence.DiscardUnknown(m) +} + +var xxx_messageInfo_OnionSequence proto.InternalMessageInfo + +func (m *OnionSequence) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +func (m *OnionSequence) GetSequence() uint64 { + if m != nil { + return m.Sequence + } + return 0 +} + func init() { proto.RegisterType((*GenesisState)(nil), "kujira.onion.GenesisState") + proto.RegisterType((*OnionSequence)(nil), "kujira.onion.OnionSequence") } func init() { proto.RegisterFile("kujira/onion/genesis.proto", fileDescriptor_e5d80ee52a36c767) } var fileDescriptor_e5d80ee52a36c767 = []byte{ - // 205 bytes of a gzipped FileDescriptorProto + // 276 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xca, 0x2e, 0xcd, 0xca, 0x2c, 0x4a, 0xd4, 0xcf, 0xcf, 0xcb, 0xcc, 0xcf, 0xd3, 0x4f, 0x4f, 0xcd, 0x4b, 0x2d, 0xce, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x81, 0xc8, 0xe9, 0x81, 0xe5, 0xa4, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x12, 0xfa, 0x20, 0x16, 0x44, 0x8d, 0x94, 0x64, 0x72, 0x7e, 0x71, 0x6e, 0x7e, 0x71, 0x3c, 0x44, 0x02, 0xc2, 0x81, 0x49, 0xa1, 0x18, 0x5d, 0x90, 0x58, 0x94, 0x98, 0x0b, - 0x95, 0x52, 0x72, 0xe2, 0xe2, 0x71, 0x87, 0x58, 0x15, 0x5c, 0x92, 0x58, 0x92, 0x2a, 0x64, 0xc4, - 0xc5, 0x06, 0x91, 0x97, 0x60, 0x54, 0x60, 0xd4, 0xe0, 0x36, 0x12, 0xd1, 0x43, 0xb6, 0x5a, 0x2f, - 0x00, 0x2c, 0xe7, 0xc4, 0x72, 0xe2, 0x9e, 0x3c, 0x43, 0x10, 0x54, 0xa5, 0x93, 0xf3, 0x89, 0x47, - 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, - 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, - 0x25, 0xe7, 0xe7, 0xea, 0x87, 0xa4, 0x26, 0xe6, 0xea, 0x7a, 0x43, 0x1c, 0x92, 0x9c, 0x5f, 0x94, - 0xaa, 0x5f, 0x01, 0x75, 0x4f, 0x49, 0x65, 0x41, 0x6a, 0x71, 0x12, 0x1b, 0xd8, 0x3d, 0xc6, 0x80, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xbe, 0x59, 0x14, 0x16, 0x07, 0x01, 0x00, 0x00, + 0x95, 0x52, 0x6a, 0x66, 0xe4, 0xe2, 0x71, 0x87, 0xd8, 0x15, 0x5c, 0x92, 0x58, 0x92, 0x2a, 0x64, + 0xc4, 0xc5, 0x06, 0x51, 0x20, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0x6d, 0x24, 0xa2, 0x87, 0x6c, 0xb7, + 0x5e, 0x00, 0x58, 0xce, 0x89, 0xe5, 0xc4, 0x3d, 0x79, 0x86, 0x20, 0xa8, 0x4a, 0x21, 0x7b, 0x2e, + 0xce, 0xe2, 0xd4, 0xc2, 0xd2, 0xd4, 0xbc, 0xe4, 0xd4, 0x62, 0x09, 0x26, 0x05, 0x66, 0x0d, 0x6e, + 0x23, 0x69, 0x54, 0x6d, 0xfe, 0x20, 0x32, 0x18, 0xaa, 0x06, 0xaa, 0x1b, 0xa1, 0x47, 0xc9, 0x95, + 0x8b, 0x17, 0x45, 0x85, 0x90, 0x04, 0x17, 0x7b, 0x62, 0x4a, 0x4a, 0x51, 0x6a, 0x31, 0xc4, 0x19, + 0x9c, 0x41, 0x30, 0xae, 0x90, 0x14, 0x17, 0x07, 0x4c, 0x9f, 0x04, 0x93, 0x02, 0xa3, 0x06, 0x4b, + 0x10, 0x9c, 0xef, 0xe4, 0x7c, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, + 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x9a, + 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x21, 0xa9, 0x89, 0xb9, 0xba, + 0xde, 0x90, 0x10, 0x49, 0xce, 0x2f, 0x4a, 0xd5, 0xaf, 0x80, 0x06, 0x4c, 0x49, 0x65, 0x41, 0x6a, + 0x71, 0x12, 0x1b, 0x38, 0x60, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xbf, 0xac, 0xe9, 0x22, + 0x90, 0x01, 0x00, 0x00, } func (m *GenesisState) Marshal() (dAtA []byte, err error) { @@ -111,6 +177,20 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l + if len(m.Sequences) > 0 { + for iNdEx := len(m.Sequences) - 1; iNdEx >= 0; iNdEx-- { + { + size, err := m.Sequences[iNdEx].MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintGenesis(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0x12 + } + } { size, err := m.Params.MarshalToSizedBuffer(dAtA[:i]) if err != nil { @@ -124,6 +204,41 @@ func (m *GenesisState) MarshalToSizedBuffer(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *OnionSequence) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *OnionSequence) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *OnionSequence) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.Sequence != 0 { + i = encodeVarintGenesis(dAtA, i, uint64(m.Sequence)) + i-- + dAtA[i] = 0x10 + } + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintGenesis(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func encodeVarintGenesis(dAtA []byte, offset int, v uint64) int { offset -= sovGenesis(v) base := offset @@ -143,6 +258,28 @@ func (m *GenesisState) Size() (n int) { _ = l l = m.Params.Size() n += 1 + l + sovGenesis(uint64(l)) + if len(m.Sequences) > 0 { + for _, e := range m.Sequences { + l = e.Size() + n += 1 + l + sovGenesis(uint64(l)) + } + } + return n +} + +func (m *OnionSequence) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovGenesis(uint64(l)) + } + if m.Sequence != 0 { + n += 1 + sovGenesis(uint64(m.Sequence)) + } return n } @@ -214,6 +351,141 @@ func (m *GenesisState) Unmarshal(dAtA []byte) error { return err } iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sequences", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sequences = append(m.Sequences, OnionSequence{}) + if err := m.Sequences[len(m.Sequences)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipGenesis(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthGenesis + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *OnionSequence) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: OnionSequence: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: OnionSequence: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthGenesis + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthGenesis + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Sequence", wireType) + } + m.Sequence = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowGenesis + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Sequence |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } default: iNdEx = preIndex skippy, err := skipGenesis(dAtA[iNdEx:]) diff --git a/x/onion/types/keys.go b/x/onion/types/keys.go index df5740ed..e42b2409 100644 --- a/x/onion/types/keys.go +++ b/x/onion/types/keys.go @@ -14,4 +14,6 @@ const ( AttributePacketSequence = "sequence" SenderPrefix = "ibc-wasm-hook-intermediary" + + OnionSequencePrefix = "onion-sequence" ) diff --git a/x/onion/types/query.pb.go b/x/onion/types/query.pb.go new file mode 100644 index 00000000..0d9756e9 --- /dev/null +++ b/x/onion/types/query.pb.go @@ -0,0 +1,582 @@ +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: kujira/onion/query.proto + +package types + +import ( + context "context" + fmt "fmt" + _ "github.com/cosmos/gogoproto/gogoproto" + grpc1 "github.com/cosmos/gogoproto/grpc" + proto "github.com/cosmos/gogoproto/proto" + _ "google.golang.org/genproto/googleapis/api/annotations" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" + io "io" + math "math" + math_bits "math/bits" +) + +// Reference imports to suppress errors if they are not otherwise used. +var _ = proto.Marshal +var _ = fmt.Errorf +var _ = math.Inf + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the proto package it is being compiled against. +// A compilation error at this line likely means your copy of the +// proto package needs to be updated. +const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package + +type QuerySequenceRequest struct { + Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` +} + +func (m *QuerySequenceRequest) Reset() { *m = QuerySequenceRequest{} } +func (m *QuerySequenceRequest) String() string { return proto.CompactTextString(m) } +func (*QuerySequenceRequest) ProtoMessage() {} +func (*QuerySequenceRequest) Descriptor() ([]byte, []int) { + return fileDescriptor_d450ac6fbe173c50, []int{0} +} +func (m *QuerySequenceRequest) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QuerySequenceRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QuerySequenceRequest.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QuerySequenceRequest) XXX_Merge(src proto.Message) { + xxx_messageInfo_QuerySequenceRequest.Merge(m, src) +} +func (m *QuerySequenceRequest) XXX_Size() int { + return m.Size() +} +func (m *QuerySequenceRequest) XXX_DiscardUnknown() { + xxx_messageInfo_QuerySequenceRequest.DiscardUnknown(m) +} + +var xxx_messageInfo_QuerySequenceRequest proto.InternalMessageInfo + +func (m *QuerySequenceRequest) GetAddress() string { + if m != nil { + return m.Address + } + return "" +} + +type QuerySequenceResponse struct { + Seq OnionSequence `protobuf:"bytes,1,opt,name=seq,proto3" json:"seq"` +} + +func (m *QuerySequenceResponse) Reset() { *m = QuerySequenceResponse{} } +func (m *QuerySequenceResponse) String() string { return proto.CompactTextString(m) } +func (*QuerySequenceResponse) ProtoMessage() {} +func (*QuerySequenceResponse) Descriptor() ([]byte, []int) { + return fileDescriptor_d450ac6fbe173c50, []int{1} +} +func (m *QuerySequenceResponse) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *QuerySequenceResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_QuerySequenceResponse.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *QuerySequenceResponse) XXX_Merge(src proto.Message) { + xxx_messageInfo_QuerySequenceResponse.Merge(m, src) +} +func (m *QuerySequenceResponse) XXX_Size() int { + return m.Size() +} +func (m *QuerySequenceResponse) XXX_DiscardUnknown() { + xxx_messageInfo_QuerySequenceResponse.DiscardUnknown(m) +} + +var xxx_messageInfo_QuerySequenceResponse proto.InternalMessageInfo + +func (m *QuerySequenceResponse) GetSeq() OnionSequence { + if m != nil { + return m.Seq + } + return OnionSequence{} +} + +func init() { + proto.RegisterType((*QuerySequenceRequest)(nil), "kujira.onion.QuerySequenceRequest") + proto.RegisterType((*QuerySequenceResponse)(nil), "kujira.onion.QuerySequenceResponse") +} + +func init() { proto.RegisterFile("kujira/onion/query.proto", fileDescriptor_d450ac6fbe173c50) } + +var fileDescriptor_d450ac6fbe173c50 = []byte{ + // 304 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0xcb, 0x4a, 0x03, 0x31, + 0x18, 0x85, 0x27, 0xde, 0x8d, 0xae, 0x42, 0x85, 0x32, 0x4a, 0x2c, 0xe3, 0xa6, 0x2e, 0x9c, 0x48, + 0xfb, 0x06, 0x75, 0xa9, 0x20, 0x56, 0x57, 0xee, 0xd2, 0xf6, 0x27, 0x46, 0x6d, 0xfe, 0xe9, 0x24, + 0x03, 0x16, 0xe9, 0xc6, 0x85, 0x6b, 0xc1, 0x97, 0xea, 0xb2, 0xe0, 0xc6, 0x95, 0x48, 0xeb, 0x83, + 0xc8, 0xdc, 0xc0, 0x11, 0x71, 0x93, 0x0b, 0xe7, 0x3b, 0x27, 0x27, 0x3f, 0xad, 0xdf, 0x25, 0xb7, + 0x3a, 0x96, 0x02, 0x8d, 0x46, 0x23, 0x46, 0x09, 0xc4, 0xe3, 0x30, 0x8a, 0xd1, 0x21, 0xdb, 0xce, + 0x95, 0x30, 0x53, 0xfc, 0x9a, 0x42, 0x85, 0x99, 0x20, 0xd2, 0x53, 0xce, 0xf8, 0x7b, 0x0a, 0x51, + 0xdd, 0x83, 0x90, 0x91, 0x16, 0xd2, 0x18, 0x74, 0xd2, 0x69, 0x34, 0xb6, 0x50, 0xfd, 0x4a, 0xb6, + 0x02, 0x03, 0x56, 0x17, 0x5a, 0x70, 0x4c, 0x6b, 0x17, 0xe9, 0x63, 0x97, 0x30, 0x4a, 0xc0, 0xf4, + 0xa1, 0x9b, 0xee, 0xd6, 0xb1, 0x3a, 0x5d, 0x97, 0x83, 0x41, 0x0c, 0xd6, 0xd6, 0x49, 0x83, 0x34, + 0x37, 0xbb, 0xe5, 0x35, 0x38, 0xa3, 0x3b, 0xbf, 0x1c, 0x36, 0x42, 0x63, 0x81, 0xb5, 0xe9, 0xb2, + 0x85, 0x51, 0x86, 0x6f, 0xb5, 0x76, 0xc3, 0x9f, 0xb5, 0xc3, 0xf3, 0x74, 0x2d, 0x1d, 0x9d, 0x95, + 0xe9, 0xc7, 0xbe, 0xd7, 0x4d, 0xe9, 0xd6, 0x33, 0xa1, 0xab, 0x59, 0x1c, 0x9b, 0xd0, 0x8d, 0x12, + 0x60, 0x41, 0xd5, 0xfd, 0x57, 0x43, 0xff, 0xe0, 0x5f, 0x26, 0xef, 0x14, 0x34, 0x9f, 0xde, 0xbe, + 0x5e, 0x97, 0x02, 0xd6, 0x10, 0x95, 0x19, 0xd8, 0x82, 0x13, 0x8f, 0xc5, 0xaf, 0x26, 0x9d, 0x93, + 0xe9, 0x9c, 0x93, 0xd9, 0x9c, 0x93, 0xcf, 0x39, 0x27, 0x2f, 0x0b, 0xee, 0xcd, 0x16, 0xdc, 0x7b, + 0x5f, 0x70, 0xef, 0xfa, 0x50, 0x69, 0x77, 0x93, 0xf4, 0xc2, 0x3e, 0x0e, 0xc5, 0x15, 0xc8, 0xe1, + 0xd1, 0x69, 0x1e, 0xd5, 0xc7, 0x18, 0xc4, 0x43, 0x91, 0xe8, 0xc6, 0x11, 0xd8, 0xde, 0x5a, 0x36, + 0xd4, 0xf6, 0x77, 0x00, 0x00, 0x00, 0xff, 0xff, 0x5f, 0x6b, 0x98, 0x59, 0xce, 0x01, 0x00, 0x00, +} + +// Reference imports to suppress errors if they are not otherwise used. +var _ context.Context +var _ grpc.ClientConn + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +const _ = grpc.SupportPackageIsVersion4 + +// QueryClient is the client API for Query service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. +type QueryClient interface { + Sequence(ctx context.Context, in *QuerySequenceRequest, opts ...grpc.CallOption) (*QuerySequenceResponse, error) +} + +type queryClient struct { + cc grpc1.ClientConn +} + +func NewQueryClient(cc grpc1.ClientConn) QueryClient { + return &queryClient{cc} +} + +func (c *queryClient) Sequence(ctx context.Context, in *QuerySequenceRequest, opts ...grpc.CallOption) (*QuerySequenceResponse, error) { + out := new(QuerySequenceResponse) + err := c.cc.Invoke(ctx, "/kujira.onion.Query/Sequence", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +// QueryServer is the server API for Query service. +type QueryServer interface { + Sequence(context.Context, *QuerySequenceRequest) (*QuerySequenceResponse, error) +} + +// UnimplementedQueryServer can be embedded to have forward compatible implementations. +type UnimplementedQueryServer struct { +} + +func (*UnimplementedQueryServer) Sequence(ctx context.Context, req *QuerySequenceRequest) (*QuerySequenceResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Sequence not implemented") +} + +func RegisterQueryServer(s grpc1.Server, srv QueryServer) { + s.RegisterService(&_Query_serviceDesc, srv) +} + +func _Query_Sequence_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(QuerySequenceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(QueryServer).Sequence(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/kujira.onion.Query/Sequence", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(QueryServer).Sequence(ctx, req.(*QuerySequenceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +var _Query_serviceDesc = grpc.ServiceDesc{ + ServiceName: "kujira.onion.Query", + HandlerType: (*QueryServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "Sequence", + Handler: _Query_Sequence_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "kujira/onion/query.proto", +} + +func (m *QuerySequenceRequest) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QuerySequenceRequest) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QuerySequenceRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if len(m.Address) > 0 { + i -= len(m.Address) + copy(dAtA[i:], m.Address) + i = encodeVarintQuery(dAtA, i, uint64(len(m.Address))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *QuerySequenceResponse) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *QuerySequenceResponse) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *QuerySequenceResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + { + size, err := m.Seq.MarshalToSizedBuffer(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarintQuery(dAtA, i, uint64(size)) + } + i-- + dAtA[i] = 0xa + return len(dAtA) - i, nil +} + +func encodeVarintQuery(dAtA []byte, offset int, v uint64) int { + offset -= sovQuery(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *QuerySequenceRequest) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Address) + if l > 0 { + n += 1 + l + sovQuery(uint64(l)) + } + return n +} + +func (m *QuerySequenceResponse) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = m.Seq.Size() + n += 1 + l + sovQuery(uint64(l)) + return n +} + +func sovQuery(x uint64) (n int) { + return (math_bits.Len64(x|1) + 6) / 7 +} +func sozQuery(x uint64) (n int) { + return sovQuery(uint64((x << 1) ^ uint64((int64(x) >> 63)))) +} +func (m *QuerySequenceRequest) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QuerySequenceRequest: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QuerySequenceRequest: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Address", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Address = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *QuerySequenceResponse) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: QuerySequenceResponse: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: QuerySequenceResponse: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Seq", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowQuery + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLengthQuery + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLengthQuery + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if err := m.Seq.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skipQuery(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthQuery + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func skipQuery(dAtA []byte) (n int, err error) { + l := len(dAtA) + iNdEx := 0 + depth := 0 + for iNdEx < l { + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= (uint64(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + wireType := int(wire & 0x7) + switch wireType { + case 0: + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + iNdEx++ + if dAtA[iNdEx-1] < 0x80 { + break + } + } + case 1: + iNdEx += 8 + case 2: + var length int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return 0, ErrIntOverflowQuery + } + if iNdEx >= l { + return 0, io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + length |= (int(b) & 0x7F) << shift + if b < 0x80 { + break + } + } + if length < 0 { + return 0, ErrInvalidLengthQuery + } + iNdEx += length + case 3: + depth++ + case 4: + if depth == 0 { + return 0, ErrUnexpectedEndOfGroupQuery + } + depth-- + case 5: + iNdEx += 4 + default: + return 0, fmt.Errorf("proto: illegal wireType %d", wireType) + } + if iNdEx < 0 { + return 0, ErrInvalidLengthQuery + } + if depth == 0 { + return iNdEx, nil + } + } + return 0, io.ErrUnexpectedEOF +} + +var ( + ErrInvalidLengthQuery = fmt.Errorf("proto: negative length found during unmarshaling") + ErrIntOverflowQuery = fmt.Errorf("proto: integer overflow") + ErrUnexpectedEndOfGroupQuery = fmt.Errorf("proto: unexpected end of group") +) diff --git a/x/onion/types/query.pb.gw.go b/x/onion/types/query.pb.gw.go new file mode 100644 index 00000000..e02cfdb3 --- /dev/null +++ b/x/onion/types/query.pb.gw.go @@ -0,0 +1,184 @@ +// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT. +// source: kujira/onion/query.proto + +/* +Package types is a reverse proxy. + +It translates gRPC into RESTful JSON APIs. +*/ +package types + +import ( + "context" + "io" + "net/http" + + "github.com/golang/protobuf/descriptor" + "github.com/golang/protobuf/proto" + "github.com/grpc-ecosystem/grpc-gateway/runtime" + "github.com/grpc-ecosystem/grpc-gateway/utilities" + "google.golang.org/grpc" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/grpclog" + "google.golang.org/grpc/status" +) + +// Suppress "imported and not used" errors +var _ codes.Code +var _ io.Reader +var _ status.Status +var _ = runtime.String +var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage + +func request_Query_Sequence_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySequenceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + msg, err := client.Sequence(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_Query_Sequence_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq QuerySequenceRequest + var metadata runtime.ServerMetadata + + var ( + val string + ok bool + err error + _ = err + ) + + val, ok = pathParams["address"] + if !ok { + return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "address") + } + + protoReq.Address, err = runtime.String(val) + + if err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "address", err) + } + + msg, err := server.Sequence(ctx, &protoReq) + return msg, metadata, err + +} + +// RegisterQueryHandlerServer registers the http handlers for service Query to "mux". +// UnaryRPC :call QueryServer directly. +// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906. +// Note that using this registration option will cause many gRPC library features (such as grpc.SendHeader, etc) to stop working. Consider using RegisterQueryHandlerFromEndpoint instead. +func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, server QueryServer) error { + + mux.Handle("GET", pattern_Query_Sequence_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_Query_Sequence_0(rctx, inboundMarshaler, server, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Sequence_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +// RegisterQueryHandlerFromEndpoint is same as RegisterQueryHandler but +// automatically dials to "endpoint" and closes the connection when "ctx" gets done. +func RegisterQueryHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { + conn, err := grpc.Dial(endpoint, opts...) + if err != nil { + return err + } + defer func() { + if err != nil { + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + return + } + go func() { + <-ctx.Done() + if cerr := conn.Close(); cerr != nil { + grpclog.Infof("Failed to close conn to %s: %v", endpoint, cerr) + } + }() + }() + + return RegisterQueryHandler(ctx, mux, conn) +} + +// RegisterQueryHandler registers the http handlers for service Query to "mux". +// The handlers forward requests to the grpc endpoint over "conn". +func RegisterQueryHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error { + return RegisterQueryHandlerClient(ctx, mux, NewQueryClient(conn)) +} + +// RegisterQueryHandlerClient registers the http handlers for service Query +// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "QueryClient". +// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "QueryClient" +// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in +// "QueryClient" to call the correct interceptors. +func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, client QueryClient) error { + + mux.Handle("GET", pattern_Query_Sequence_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + rctx, err := runtime.AnnotateContext(ctx, mux, req) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_Query_Sequence_0(rctx, inboundMarshaler, client, req, pathParams) + ctx = runtime.NewServerMetadataContext(ctx, md) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + + forward_Query_Sequence_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + +var ( + pattern_Query_Sequence_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"kujira", "onion", "sequence", "address"}, "", runtime.AssumeColonVerbOpt(true))) +) + +var ( + forward_Query_Sequence_0 = runtime.ForwardResponseMessage +) From 3bd55077367fa2d7813588f1ee98f8adbfe4738e Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Wed, 26 Jun 2024 20:46:04 +0800 Subject: [PATCH 06/15] Remove unused wasm hooks and channel keeper --- app/app.go | 27 +- proto/kujira/onion/params.proto | 2 - proto/kujira/onion/tx.proto | 15 - x/onion/client/cli/query.go | 39 -- x/onion/hooks.go | 145 ------- x/onion/ibc_module.go | 208 ++-------- x/onion/ibcutils.go | 78 ---- x/onion/ics4_middleware.go | 85 ---- x/onion/keeper/ibcutils.go | 33 -- x/onion/keeper/keeper.go | 217 +--------- x/onion/keeper/msg_server.go | 24 -- x/onion/types/codec.go | 2 - x/onion/types/expected_keepers.go | 11 - x/onion/types/msgs.go | 31 -- x/onion/types/params.go | 39 +- x/onion/types/params.pb.go | 75 +--- x/onion/types/tx.pb.go | 668 +----------------------------- x/onion/types/types.go | 84 ---- x/onion/wasm_hook.go | 381 ----------------- 19 files changed, 60 insertions(+), 2104 deletions(-) delete mode 100644 x/onion/hooks.go delete mode 100644 x/onion/ibcutils.go delete mode 100644 x/onion/ics4_middleware.go delete mode 100644 x/onion/keeper/ibcutils.go delete mode 100644 x/onion/wasm_hook.go diff --git a/app/app.go b/app/app.go index 04e0c779..5c98f4aa 100644 --- a/app/app.go +++ b/app/app.go @@ -300,8 +300,6 @@ type App struct { ParamsKeeper paramskeeper.Keeper IBCKeeper *ibckeeper.Keeper // IBC Keeper must be a pointer in the app, so we can SetRouter on it correctly OnionKeeper *onionkeeper.Keeper - Ics20WasmHooks *onion.WasmHooks - HooksICS4Wrapper onion.ICS4Middleware IBCFeeKeeper ibcfeekeeper.Keeper ICAControllerKeeper icacontrollerkeeper.Keeper ICAHostKeeper icahostkeeper.Keeper @@ -558,15 +556,12 @@ func New( app.OnionKeeper = onionkeeper.NewKeeper( keys[oniontypes.StoreKey], app.GetSubspace(oniontypes.ModuleName), - app.IBCKeeper.ChannelKeeper, nil, app.MsgServiceRouter(), app.AccountKeeper, txConfig.SignModeHandler(), ) - app.WireICS20PreWasmKeeper(appCodec, bApp, app.OnionKeeper) - // IBC Fee Module keeper app.IBCFeeKeeper = ibcfeekeeper.NewKeeper( @@ -725,10 +720,6 @@ func New( wasmOpts..., ) - // Pass the contract keeper to all the structs (generally ICS4Wrappers for ibc middlewares) that need it - app.Ics20WasmHooks.ContractKeeper = &app.WasmKeeper - app.OnionKeeper.ContractKeeper = wasmkeeper.NewDefaultPermissionKeeper(app.WasmKeeper) - // Register the proposal types // Deprecated: Avoid adding new handlers, instead use the new proposal flow // by granting the governance module the right to execute the message. @@ -783,7 +774,7 @@ func New( var transferStack ibcporttypes.IBCModule transferStack = transfer.NewIBCModule(app.TransferKeeper) transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper) - transferStack = onion.NewIBCMiddleware(transferStack, &app.HooksICS4Wrapper, app.OnionKeeper, encodingConfig.TxConfig) + transferStack = onion.NewIBCModule(transferStack, app.OnionKeeper, encodingConfig.TxConfig) // Create Interchain Accounts Stack // SendPacket, since it is originating from the application to core IBC: @@ -1207,22 +1198,6 @@ func New( return app } -// WireICS20PreWasmKeeper Create the IBC Transfer Stack from bottom to top: -func (app *App) WireICS20PreWasmKeeper( - appCodec codec.Codec, - bApp *baseapp.BaseApp, - hooksKeeper *onionkeeper.Keeper, -) { - // Setup the ICS4Wrapper used by the hooks middleware - addrPrefix := sdk.GetConfig().GetBech32AccountAddrPrefix() - wasmHooks := onion.NewWasmHooks(hooksKeeper, nil, addrPrefix) // The contract keeper needs to be set later - app.Ics20WasmHooks = &wasmHooks - app.HooksICS4Wrapper = onion.NewICS4Middleware( - app.IBCKeeper.ChannelKeeper, - app.Ics20WasmHooks, - ) -} - func (app *App) setPostHandler() { postHandler, err := posthandler.NewPostHandler( posthandler.HandlerOptions{}, diff --git a/proto/kujira/onion/params.proto b/proto/kujira/onion/params.proto index 9bbd27d5..9faa6c9b 100644 --- a/proto/kujira/onion/params.proto +++ b/proto/kujira/onion/params.proto @@ -8,6 +8,4 @@ import "google/protobuf/duration.proto"; option go_package = "github.com/Team-Kujira/core/x/onion/types"; message Params { - repeated string allowed_async_ack_contracts = 1 - [ (gogoproto.moretags) = "yaml:\"allowed_async_ack_contracts\"" ]; } diff --git a/proto/kujira/onion/tx.proto b/proto/kujira/onion/tx.proto index 5f8b85e0..145d3b7f 100644 --- a/proto/kujira/onion/tx.proto +++ b/proto/kujira/onion/tx.proto @@ -7,19 +7,4 @@ option go_package = "github.com/Team-Kujira/core/x/onion/types"; // Msg defines the Msg service. service Msg { - // EmitIBCAck checks the sender can emit the ack and writes the IBC - // acknowledgement - rpc EmitIBCAck(MsgEmitIBCAck) returns (MsgEmitIBCAckResponse); -} - -message MsgEmitIBCAck { - string sender = 1 [ (gogoproto.moretags) = "yaml:\"sender\"" ]; - uint64 packet_sequence = 2 - [ (gogoproto.moretags) = "yaml:\"packet_sequence\"" ]; - string channel = 3 [ (gogoproto.moretags) = "yaml:\"channel\"" ]; -} -message MsgEmitIBCAckResponse { - string contract_result = 1 - [ (gogoproto.moretags) = "yaml:\"contract_result\"" ]; - string ibc_ack = 2 [ (gogoproto.moretags) = "yaml:\"ibc_ack\"" ]; } diff --git a/x/onion/client/cli/query.go b/x/onion/client/cli/query.go index 3ca04fb8..bc1991bf 100644 --- a/x/onion/client/cli/query.go +++ b/x/onion/client/cli/query.go @@ -3,16 +3,11 @@ package cli import ( "context" "fmt" - "strings" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/version" "github.com/spf13/cobra" - "github.com/Team-Kujira/core/x/onion/keeper" - "github.com/Team-Kujira/core/x/onion/types" ) @@ -40,45 +35,11 @@ func GetQueryCmd() *cobra.Command { } cmd.AddCommand( - GetCmdWasmSender(), GetCmdQuerySequence(), ) return cmd } -// GetCmdPoolParams return pool params. -func GetCmdWasmSender() *cobra.Command { - cmd := &cobra.Command{ - Use: "wasm-sender ", - Short: "Generate the local address for a wasm hooks sender", - Long: strings.TrimSpace( - fmt.Sprintf(`Generate the local address for a wasm hooks sender. -Example: -$ %s query ibc-hooks wasm-hooks-sender channel-42 juno12smx2wdlyttvyzvzg54y2vnqwq2qjatezqwqxu -`, - version.AppName, - ), - ), - Args: cobra.ExactArgs(2), - RunE: func(cmd *cobra.Command, args []string) error { - channelID := args[0] - originalSender := args[1] - // ToDo: Make this flexible as an arg - prefix := sdk.GetConfig().GetBech32AccountAddrPrefix() - senderBech32, err := keeper.DeriveIntermediateSender(channelID, originalSender, prefix) - if err != nil { - return err - } - fmt.Println(senderBech32) - return nil - }, - } - - flags.AddQueryFlagsToCmd(cmd) - - return cmd -} - // GetCmdQuerySequence implements the query sequence command. func GetCmdQuerySequence() *cobra.Command { cmd := &cobra.Command{ diff --git a/x/onion/hooks.go b/x/onion/hooks.go deleted file mode 100644 index aacadf95..00000000 --- a/x/onion/hooks.go +++ /dev/null @@ -1,145 +0,0 @@ -package onion - -import ( - // external libraries - sdk "github.com/cosmos/cosmos-sdk/types" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - - // ibc-go - clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" -) - -type Hooks interface{} - -type OnChanOpenInitOverrideHooks interface { - OnChanOpenInitOverride(im IBCMiddleware, ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string) (string, error) -} -type OnChanOpenInitBeforeHooks interface { - OnChanOpenInitBeforeHook(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string) -} -type OnChanOpenInitAfterHooks interface { - OnChanOpenInitAfterHook(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID string, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, version string, finalVersion string, err error) -} - -// OnChanOpenTry Hooks -type OnChanOpenTryOverrideHooks interface { - OnChanOpenTryOverride(im IBCMiddleware, ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, counterpartyVersion string) (string, error) -} -type OnChanOpenTryBeforeHooks interface { - OnChanOpenTryBeforeHook(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, counterpartyVersion string) -} -type OnChanOpenTryAfterHooks interface { - OnChanOpenTryAfterHook(ctx sdk.Context, order channeltypes.Order, connectionHops []string, portID, channelID string, channelCap *capabilitytypes.Capability, counterparty channeltypes.Counterparty, counterpartyVersion string, version string, err error) -} - -// OnChanOpenAck Hooks -type OnChanOpenAckOverrideHooks interface { - OnChanOpenAckOverride(im IBCMiddleware, ctx sdk.Context, portID, channelID string, counterpartyChannelID string, counterpartyVersion string) error -} -type OnChanOpenAckBeforeHooks interface { - OnChanOpenAckBeforeHook(ctx sdk.Context, portID, channelID string, counterpartyChannelID string, counterpartyVersion string) -} -type OnChanOpenAckAfterHooks interface { - OnChanOpenAckAfterHook(ctx sdk.Context, portID, channelID string, counterpartyChannelID string, counterpartyVersion string, err error) -} - -// OnChanOpenConfirm Hooks -type OnChanOpenConfirmOverrideHooks interface { - OnChanOpenConfirmOverride(im IBCMiddleware, ctx sdk.Context, portID, channelID string) error -} -type OnChanOpenConfirmBeforeHooks interface { - OnChanOpenConfirmBeforeHook(ctx sdk.Context, portID, channelID string) -} -type OnChanOpenConfirmAfterHooks interface { - OnChanOpenConfirmAfterHook(ctx sdk.Context, portID, channelID string, err error) -} - -// OnChanCloseInit Hooks -type OnChanCloseInitOverrideHooks interface { - OnChanCloseInitOverride(im IBCMiddleware, ctx sdk.Context, portID, channelID string) error -} -type OnChanCloseInitBeforeHooks interface { - OnChanCloseInitBeforeHook(ctx sdk.Context, portID, channelID string) -} -type OnChanCloseInitAfterHooks interface { - OnChanCloseInitAfterHook(ctx sdk.Context, portID, channelID string, err error) -} - -// OnChanCloseConfirm Hooks -type OnChanCloseConfirmOverrideHooks interface { - OnChanCloseConfirmOverride(im IBCMiddleware, ctx sdk.Context, portID, channelID string) error -} -type OnChanCloseConfirmBeforeHooks interface { - OnChanCloseConfirmBeforeHook(ctx sdk.Context, portID, channelID string) -} -type OnChanCloseConfirmAfterHooks interface { - OnChanCloseConfirmAfterHook(ctx sdk.Context, portID, channelID string, err error) -} - -// OnRecvPacket Hooks -type OnRecvPacketOverrideHooks interface { - OnRecvPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) ibcexported.Acknowledgement -} -type OnRecvPacketBeforeHooks interface { - OnRecvPacketBeforeHook(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) -} -type OnRecvPacketAfterHooks interface { - OnRecvPacketAfterHook(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, ack ibcexported.Acknowledgement) -} - -// OnAcknowledgementPacket Hooks -type OnAcknowledgementPacketOverrideHooks interface { - OnAcknowledgementPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) error -} -type OnAcknowledgementPacketBeforeHooks interface { - OnAcknowledgementPacketBeforeHook(ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) -} -type OnAcknowledgementPacketAfterHooks interface { - OnAcknowledgementPacketAfterHook(ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress, err error) -} - -// OnTimeoutPacket Hooks -type OnTimeoutPacketOverrideHooks interface { - OnTimeoutPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) error -} -type OnTimeoutPacketBeforeHooks interface { - OnTimeoutPacketBeforeHook(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) -} -type OnTimeoutPacketAfterHooks interface { - OnTimeoutPacketAfterHook(ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, err error) -} - -// SendPacket Hooks -type SendPacketOverrideHooks interface { - SendPacketOverride(i ICS4Middleware, ctx sdk.Context, chanCap *capabilitytypes.Capability, sourcePort string, sourceChannel string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, data []byte) (uint64, error) -} -type SendPacketBeforeHooks interface { - SendPacketBeforeHook(ctx sdk.Context, chanCap *capabilitytypes.Capability, sourcePort string, sourceChannel string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, data []byte) -} -type SendPacketAfterHooks interface { - SendPacketAfterHook(cctx sdk.Context, chanCap *capabilitytypes.Capability, sourcePort string, sourceChannel string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, data []byte, err error) -} - -// WriteAcknowledgement Hooks -type WriteAcknowledgementOverrideHooks interface { - WriteAcknowledgementOverride(i ICS4Middleware, ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, ack ibcexported.Acknowledgement) error -} -type WriteAcknowledgementBeforeHooks interface { - WriteAcknowledgementBeforeHook(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, ack ibcexported.Acknowledgement) -} -type WriteAcknowledgementAfterHooks interface { - WriteAcknowledgementAfterHook(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, ack ibcexported.Acknowledgement, err error) -} - -// GetAppVersion Hooks -type GetAppVersionOverrideHooks interface { - GetAppVersionOverride(i ICS4Middleware, ctx sdk.Context, portID, channelID string) (string, bool) -} -type GetAppVersionBeforeHooks interface { - GetAppVersionBeforeHook(ctx sdk.Context, portID, channelID string) -} -type GetAppVersionAfterHooks interface { - GetAppVersionAfterHook(ctx sdk.Context, portID, channelID string, result string, success bool) -} diff --git a/x/onion/ibc_module.go b/x/onion/ibc_module.go index 8c836e8b..f3b626c6 100644 --- a/x/onion/ibc_module.go +++ b/x/onion/ibc_module.go @@ -11,37 +11,33 @@ import ( // ibc-go "github.com/Team-Kujira/core/x/onion/keeper" "github.com/cosmos/cosmos-sdk/client" - clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" ) -var _ porttypes.Middleware = &IBCMiddleware{} +var _ porttypes.IBCModule = IBCModule{} -type IBCMiddleware struct { +type IBCModule struct { App porttypes.IBCModule - ICS4Middleware *ICS4Middleware Keeper *keeper.Keeper txEncodingConfig client.TxEncodingConfig } -func NewIBCMiddleware( +func NewIBCModule( app porttypes.IBCModule, - ics4 *ICS4Middleware, Keeper *keeper.Keeper, txEncodingConfig client.TxEncodingConfig, -) IBCMiddleware { - return IBCMiddleware{ +) IBCModule { + return IBCModule{ App: app, - ICS4Middleware: ics4, Keeper: Keeper, txEncodingConfig: txEncodingConfig, } } -// OnChanOpenInit implements the IBCMiddleware interface -func (im IBCMiddleware) OnChanOpenInit( +// OnChanOpenInit implements the IBCModule interface +func (im IBCModule) OnChanOpenInit( ctx sdk.Context, order channeltypes.Order, connectionHops []string, @@ -51,24 +47,11 @@ func (im IBCMiddleware) OnChanOpenInit( counterparty channeltypes.Counterparty, version string, ) (string, error) { - if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenInitOverrideHooks); ok { - return hook.OnChanOpenInitOverride(im, ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version) - } - - if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenInitBeforeHooks); ok { - hook.OnChanOpenInitBeforeHook(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version) - } - - finalVersion, err := im.App.OnChanOpenInit(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version) - - if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenInitAfterHooks); ok { - hook.OnChanOpenInitAfterHook(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version, finalVersion, err) - } - return version, err + return im.App.OnChanOpenInit(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, version) } -// OnChanOpenTry implements the IBCMiddleware interface -func (im IBCMiddleware) OnChanOpenTry( +// OnChanOpenTry implements the IBCModule interface +func (im IBCModule) OnChanOpenTry( ctx sdk.Context, order channeltypes.Order, connectionHops []string, @@ -78,111 +61,49 @@ func (im IBCMiddleware) OnChanOpenTry( counterparty channeltypes.Counterparty, counterpartyVersion string, ) (string, error) { - if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenTryOverrideHooks); ok { - return hook.OnChanOpenTryOverride(im, ctx, order, connectionHops, portID, channelID, channelCap, counterparty, counterpartyVersion) - } - - if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenTryBeforeHooks); ok { - hook.OnChanOpenTryBeforeHook(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, counterpartyVersion) - } - - version, err := im.App.OnChanOpenTry(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, counterpartyVersion) - - if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenTryAfterHooks); ok { - hook.OnChanOpenTryAfterHook(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, counterpartyVersion, version, err) - } - return version, err + return im.App.OnChanOpenTry(ctx, order, connectionHops, portID, channelID, channelCap, counterparty, counterpartyVersion) } -// OnChanOpenAck implements the IBCMiddleware interface -func (im IBCMiddleware) OnChanOpenAck( +// OnChanOpenAck implements the IBCModule interface +func (im IBCModule) OnChanOpenAck( ctx sdk.Context, portID, channelID string, counterpartyChannelID string, counterpartyVersion string, ) error { - if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenAckOverrideHooks); ok { - return hook.OnChanOpenAckOverride(im, ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) - } - - if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenAckBeforeHooks); ok { - hook.OnChanOpenAckBeforeHook(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) - } - err := im.App.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) - if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenAckAfterHooks); ok { - hook.OnChanOpenAckAfterHook(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion, err) - } - - return err + return im.App.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) } -// OnChanOpenConfirm implements the IBCMiddleware interface -func (im IBCMiddleware) OnChanOpenConfirm( +// OnChanOpenConfirm implements the IBCModule interface +func (im IBCModule) OnChanOpenConfirm( ctx sdk.Context, portID, channelID string, ) error { - if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenConfirmOverrideHooks); ok { - return hook.OnChanOpenConfirmOverride(im, ctx, portID, channelID) - } - - if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenConfirmBeforeHooks); ok { - hook.OnChanOpenConfirmBeforeHook(ctx, portID, channelID) - } - err := im.App.OnChanOpenConfirm(ctx, portID, channelID) - if hook, ok := im.ICS4Middleware.Hooks.(OnChanOpenConfirmAfterHooks); ok { - hook.OnChanOpenConfirmAfterHook(ctx, portID, channelID, err) - } - return err + return im.App.OnChanOpenConfirm(ctx, portID, channelID) } -// OnChanCloseInit implements the IBCMiddleware interface -func (im IBCMiddleware) OnChanCloseInit( +// OnChanCloseInit implements the IBCModule interface +func (im IBCModule) OnChanCloseInit( ctx sdk.Context, portID, channelID string, ) error { - // Here we can remove the limits when a new channel is closed. For now, they can remove them manually on the contract - if hook, ok := im.ICS4Middleware.Hooks.(OnChanCloseInitOverrideHooks); ok { - return hook.OnChanCloseInitOverride(im, ctx, portID, channelID) - } - - if hook, ok := im.ICS4Middleware.Hooks.(OnChanCloseInitBeforeHooks); ok { - hook.OnChanCloseInitBeforeHook(ctx, portID, channelID) - } - err := im.App.OnChanCloseInit(ctx, portID, channelID) - if hook, ok := im.ICS4Middleware.Hooks.(OnChanCloseInitAfterHooks); ok { - hook.OnChanCloseInitAfterHook(ctx, portID, channelID, err) - } - - return err + return im.App.OnChanCloseInit(ctx, portID, channelID) } -// OnChanCloseConfirm implements the IBCMiddleware interface -func (im IBCMiddleware) OnChanCloseConfirm( +// OnChanCloseConfirm implements the IBCModule interface +func (im IBCModule) OnChanCloseConfirm( ctx sdk.Context, portID, channelID string, ) error { - // Here we can remove the limits when a new channel is closed. For now, they can remove them manually on the contract - if hook, ok := im.ICS4Middleware.Hooks.(OnChanCloseConfirmOverrideHooks); ok { - return hook.OnChanCloseConfirmOverride(im, ctx, portID, channelID) - } - - if hook, ok := im.ICS4Middleware.Hooks.(OnChanCloseConfirmBeforeHooks); ok { - hook.OnChanCloseConfirmBeforeHook(ctx, portID, channelID) - } - err := im.App.OnChanCloseConfirm(ctx, portID, channelID) - if hook, ok := im.ICS4Middleware.Hooks.(OnChanCloseConfirmAfterHooks); ok { - hook.OnChanCloseConfirmAfterHook(ctx, portID, channelID, err) - } - - return err + return im.App.OnChanCloseConfirm(ctx, portID, channelID) } -// OnRecvPacket implements the IBCMiddleware interface -func (im IBCMiddleware) OnRecvPacket( +// OnRecvPacket implements the IBCModule interface +func (im IBCModule) OnRecvPacket( ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, @@ -207,89 +128,24 @@ func (im IBCMiddleware) OnRecvPacket( } } - if hook, ok := im.ICS4Middleware.Hooks.(OnRecvPacketOverrideHooks); ok { - return hook.OnRecvPacketOverride(im, ctx, packet, relayer) - } - - if hook, ok := im.ICS4Middleware.Hooks.(OnRecvPacketBeforeHooks); ok { - hook.OnRecvPacketBeforeHook(ctx, packet, relayer) - } - - ack := im.App.OnRecvPacket(ctx, packet, relayer) - - if hook, ok := im.ICS4Middleware.Hooks.(OnRecvPacketAfterHooks); ok { - hook.OnRecvPacketAfterHook(ctx, packet, relayer, ack) - } - - return ack + return im.App.OnRecvPacket(ctx, packet, relayer) } -// OnAcknowledgementPacket implements the IBCMiddleware interface -func (im IBCMiddleware) OnAcknowledgementPacket( +// OnAcknowledgementPacket implements the IBCModule interface +func (im IBCModule) OnAcknowledgementPacket( ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress, ) error { - if hook, ok := im.ICS4Middleware.Hooks.(OnAcknowledgementPacketOverrideHooks); ok { - return hook.OnAcknowledgementPacketOverride(im, ctx, packet, acknowledgement, relayer) - } - if hook, ok := im.ICS4Middleware.Hooks.(OnAcknowledgementPacketBeforeHooks); ok { - hook.OnAcknowledgementPacketBeforeHook(ctx, packet, acknowledgement, relayer) - } - - err := im.App.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer) - - if hook, ok := im.ICS4Middleware.Hooks.(OnAcknowledgementPacketAfterHooks); ok { - hook.OnAcknowledgementPacketAfterHook(ctx, packet, acknowledgement, relayer, err) - } - - return err + return im.App.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer) } -// OnTimeoutPacket implements the IBCMiddleware interface -func (im IBCMiddleware) OnTimeoutPacket( +// OnTimeoutPacket implements the IBCModule interface +func (im IBCModule) OnTimeoutPacket( ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, ) error { - if hook, ok := im.ICS4Middleware.Hooks.(OnTimeoutPacketOverrideHooks); ok { - return hook.OnTimeoutPacketOverride(im, ctx, packet, relayer) - } - - if hook, ok := im.ICS4Middleware.Hooks.(OnTimeoutPacketBeforeHooks); ok { - hook.OnTimeoutPacketBeforeHook(ctx, packet, relayer) - } - err := im.App.OnTimeoutPacket(ctx, packet, relayer) - if hook, ok := im.ICS4Middleware.Hooks.(OnTimeoutPacketAfterHooks); ok { - hook.OnTimeoutPacketAfterHook(ctx, packet, relayer, err) - } - - return err -} - -// SendPacket implements the ICS4 Wrapper interface -func (im IBCMiddleware) SendPacket( - ctx sdk.Context, - chanCap *capabilitytypes.Capability, - sourcePort string, sourceChannel string, - timeoutHeight clienttypes.Height, - timeoutTimestamp uint64, - data []byte, -) (sequence uint64, err error) { - return im.ICS4Middleware.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data) -} - -// WriteAcknowledgement implements the ICS4 Wrapper interface -func (im IBCMiddleware) WriteAcknowledgement( - ctx sdk.Context, - chanCap *capabilitytypes.Capability, - packet ibcexported.PacketI, - ack ibcexported.Acknowledgement, -) error { - return im.ICS4Middleware.WriteAcknowledgement(ctx, chanCap, packet, ack) -} - -func (im IBCMiddleware) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { - return im.ICS4Middleware.GetAppVersion(ctx, portID, channelID) + return im.App.OnTimeoutPacket(ctx, packet, relayer) } diff --git a/x/onion/ibcutils.go b/x/onion/ibcutils.go deleted file mode 100644 index a94871de..00000000 --- a/x/onion/ibcutils.go +++ /dev/null @@ -1,78 +0,0 @@ -package onion - -import ( - "encoding/json" - - sdk "github.com/cosmos/cosmos-sdk/types" - transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" -) - -const IbcAcknowledgementErrorType = "ibc-acknowledgement-error" - -// NewEmitErrorAcknowledgement creates a new error acknowledgement after having emitted an event with the -// details of the error. -func NewEmitErrorAcknowledgement(ctx sdk.Context, err error, errorContexts ...string) channeltypes.Acknowledgement { - EmitIBCErrorEvents(ctx, err, errorContexts) - - return channeltypes.NewErrorAcknowledgement(err) -} - -// EmitIBCErrorEvents Emit and Log errors -func EmitIBCErrorEvents(ctx sdk.Context, err error, errorContexts []string) { - attributes := make([]sdk.Attribute, len(errorContexts)+1) - attributes[0] = sdk.NewAttribute("error", err.Error()) - for i, s := range errorContexts { - attributes[i+1] = sdk.NewAttribute("error-context", s) - } - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - IbcAcknowledgementErrorType, - attributes..., - ), - }) -} - -// MustExtractDenomFromPacketOnRecv takes a packet with a valid ICS20 token data in the Data field and returns the -// denom as represented in the local chain. -// If the data cannot be unmarshalled this function will panic -func MustExtractDenomFromPacketOnRecv(packet ibcexported.PacketI) string { - var data transfertypes.FungibleTokenPacketData - if err := json.Unmarshal(packet.GetData(), &data); err != nil { - panic("unable to unmarshal ICS20 packet data") - } - - var denom string - if transfertypes.ReceiverChainIsSource(packet.GetSourcePort(), packet.GetSourceChannel(), data.Denom) { - // remove prefix added by sender chain - voucherPrefix := transfertypes.GetDenomPrefix(packet.GetSourcePort(), packet.GetSourceChannel()) - - unprefixedDenom := data.Denom[len(voucherPrefix):] - - // coin denomination used in sending from the escrow address - denom = unprefixedDenom - - // The denomination used to send the coins is either the native denom or the hash of the path - // if the denomination is not native. - denomTrace := transfertypes.ParseDenomTrace(unprefixedDenom) - if denomTrace.Path != "" { - denom = denomTrace.IBCDenom() - } - } else { - prefixedDenom := transfertypes.GetDenomPrefix(packet.GetDestPort(), packet.GetDestChannel()) + data.Denom - denom = transfertypes.ParseDenomTrace(prefixedDenom).IBCDenom() - } - return denom -} - -// IsAckError checks an IBC acknowledgement to see if it's an error. -// This is a replacement for ack.Success() which is currently not working on some circumstances -func IsAckError(acknowledgement []byte) bool { - var ackErr channeltypes.Acknowledgement_Error - if err := json.Unmarshal(acknowledgement, &ackErr); err == nil && len(ackErr.Error) > 0 { - return true - } - return false -} diff --git a/x/onion/ics4_middleware.go b/x/onion/ics4_middleware.go deleted file mode 100644 index 06897f41..00000000 --- a/x/onion/ics4_middleware.go +++ /dev/null @@ -1,85 +0,0 @@ -package onion - -import ( - // external libraries - sdk "github.com/cosmos/cosmos-sdk/types" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - - // ibc-go - clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" - porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" - ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" -) - -var _ porttypes.ICS4Wrapper = &ICS4Middleware{} - -type ICS4Middleware struct { - channel porttypes.ICS4Wrapper - - // Hooks - Hooks Hooks -} - -func NewICS4Middleware(channel porttypes.ICS4Wrapper, hooks Hooks) ICS4Middleware { - return ICS4Middleware{ - channel: channel, - Hooks: hooks, - } -} - -func (i ICS4Middleware) SendPacket( - ctx sdk.Context, - chanCap *capabilitytypes.Capability, - sourcePort string, sourceChannel string, - timeoutHeight clienttypes.Height, - timeoutTimestamp uint64, - data []byte, -) (sequence uint64, err error) { - if hook, ok := i.Hooks.(SendPacketOverrideHooks); ok { - return hook.SendPacketOverride(i, ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data) - } - - if hook, ok := i.Hooks.(SendPacketBeforeHooks); ok { - hook.SendPacketBeforeHook(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data) - } - - seq, err := i.channel.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data) - - if hook, ok := i.Hooks.(SendPacketAfterHooks); ok { - hook.SendPacketAfterHook(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data, err) - } - - return seq, err -} - -func (i ICS4Middleware) WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet ibcexported.PacketI, ack ibcexported.Acknowledgement) error { - if hook, ok := i.Hooks.(WriteAcknowledgementOverrideHooks); ok { - return hook.WriteAcknowledgementOverride(i, ctx, chanCap, packet, ack) - } - - if hook, ok := i.Hooks.(WriteAcknowledgementBeforeHooks); ok { - hook.WriteAcknowledgementBeforeHook(ctx, chanCap, packet, ack) - } - err := i.channel.WriteAcknowledgement(ctx, chanCap, packet, ack) - if hook, ok := i.Hooks.(WriteAcknowledgementAfterHooks); ok { - hook.WriteAcknowledgementAfterHook(ctx, chanCap, packet, ack, err) - } - - return err -} - -func (i ICS4Middleware) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { - if hook, ok := i.Hooks.(GetAppVersionOverrideHooks); ok { - return hook.GetAppVersionOverride(i, ctx, portID, channelID) - } - - if hook, ok := i.Hooks.(GetAppVersionBeforeHooks); ok { - hook.GetAppVersionBeforeHook(ctx, portID, channelID) - } - version, err := i.channel.GetAppVersion(ctx, portID, channelID) - if hook, ok := i.Hooks.(GetAppVersionAfterHooks); ok { - hook.GetAppVersionAfterHook(ctx, portID, channelID, version, err) - } - - return version, err -} diff --git a/x/onion/keeper/ibcutils.go b/x/onion/keeper/ibcutils.go deleted file mode 100644 index 60fd0f6c..00000000 --- a/x/onion/keeper/ibcutils.go +++ /dev/null @@ -1,33 +0,0 @@ -package keeper - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" -) - -const IbcAcknowledgementErrorType = "ibc-acknowledgement-error" - -// NewSuccessAckRepresentingAnError creates a new success acknowledgement that represents an error. -// This is useful for notifying the sender that an error has occurred in a way that does not allow -// the received tokens to be reverted (which means they shouldn't be released by the sender's ics20 escrow) -func NewSuccessAckRepresentingAnError(ctx sdk.Context, err error, errorContent []byte, errorContexts ...string) channeltypes.Acknowledgement { - EmitIBCErrorEvents(ctx, err, errorContexts) - - return channeltypes.NewResultAcknowledgement(errorContent) -} - -// EmitIBCErrorEvents Emit and Log errors -func EmitIBCErrorEvents(ctx sdk.Context, err error, errorContexts []string) { - attributes := make([]sdk.Attribute, len(errorContexts)+1) - attributes[0] = sdk.NewAttribute("error", err.Error()) - for i, s := range errorContexts { - attributes[i+1] = sdk.NewAttribute("error-context", s) - } - - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - IbcAcknowledgementErrorType, - attributes..., - ), - }) -} diff --git a/x/onion/keeper/keeper.go b/x/onion/keeper/keeper.go index c9ccfbef..3d9d664b 100644 --- a/x/onion/keeper/keeper.go +++ b/x/onion/keeper/keeper.go @@ -1,23 +1,16 @@ package keeper import ( - "encoding/hex" - "encoding/json" "fmt" - "strings" wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" "github.com/Team-Kujira/core/x/onion/types" - "github.com/cometbft/cometbft/crypto/tmhash" "github.com/cometbft/cometbft/libs/log" "github.com/cosmos/cosmos-sdk/baseapp" storetypes "github.com/cosmos/cosmos-sdk/store/types" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/address" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" ) type ( @@ -25,9 +18,7 @@ type ( storeKey storetypes.StoreKey paramSpace paramtypes.Subspace - channelKeeper types.ChannelKeeper - ContractKeeper *wasmkeeper.PermissionedKeeper - accountKeeper types.AccountKeeper + accountKeeper types.AccountKeeper router *baseapp.MsgServiceRouter signModeHandler authsigning.SignModeHandler @@ -38,7 +29,6 @@ type ( func NewKeeper( storeKey storetypes.StoreKey, paramSpace paramtypes.Subspace, - channelKeeper types.ChannelKeeper, contractKeeper *wasmkeeper.PermissionedKeeper, router *baseapp.MsgServiceRouter, accountKeeper types.AccountKeeper, @@ -50,8 +40,6 @@ func NewKeeper( return &Keeper{ storeKey: storeKey, paramSpace: paramSpace, - channelKeeper: channelKeeper, - ContractKeeper: contractKeeper, router: router, accountKeeper: accountKeeper, signModeHandler: signModeHandler, @@ -74,11 +62,6 @@ func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { k.paramSpace.SetParamSet(ctx, ¶ms) } -// SetParam sets a specific ibc-hooks module's parameter with the provided parameter. -func (k Keeper) SetParam(ctx sdk.Context, key []byte, value interface{}) { - k.paramSpace.Set(ctx, key, value) -} - func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) { k.SetParams(ctx, genState.Params) for _, seq := range genState.Sequences { @@ -92,201 +75,3 @@ func (k Keeper) ExportGenesis(ctx sdk.Context) *types.GenesisState { Sequences: k.GetAllSequences(ctx), } } - -func GetPacketCallbackKey(channel string, packetSequence uint64) []byte { - return []byte(fmt.Sprintf("%s::%d", channel, packetSequence)) -} - -func GetPacketAckKey(channel string, packetSequence uint64) []byte { - return []byte(fmt.Sprintf("%s::%d::ack", channel, packetSequence)) -} - -func GeneratePacketAckValue(packet channeltypes.Packet, contract string) ([]byte, error) { - if _, err := sdk.AccAddressFromBech32(contract); err != nil { - return nil, sdkerrors.Wrap(types.ErrInvalidContractAddr, contract) - } - - packetHash, err := hashPacket(packet) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not hash packet") - } - - return []byte(fmt.Sprintf("%s::%s", contract, packetHash)), nil -} - -// StorePacketCallback stores which contract will be listening for the ack or timeout of a packet -func (k Keeper) StorePacketCallback(ctx sdk.Context, channel string, packetSequence uint64, contract string) { - store := ctx.KVStore(k.storeKey) - store.Set(GetPacketCallbackKey(channel, packetSequence), []byte(contract)) -} - -// GetPacketCallback returns the bech32 addr of the contract that is expecting a callback from a packet -func (k Keeper) GetPacketCallback(ctx sdk.Context, channel string, packetSequence uint64) string { - store := ctx.KVStore(k.storeKey) - return string(store.Get(GetPacketCallbackKey(channel, packetSequence))) -} - -// IsInAllowList checks the params to see if the contract is in the KeyAsyncAckAllowList param -func (k Keeper) IsInAllowList(ctx sdk.Context, contract string) bool { - var allowList []string - k.paramSpace.GetIfExists(ctx, types.KeyAsyncAckAllowList, &allowList) - for _, addr := range allowList { - if addr == contract { - return true - } - } - return false -} - -// DeletePacketCallback deletes the callback from storage once it has been processed -func (k Keeper) DeletePacketCallback(ctx sdk.Context, channel string, packetSequence uint64) { - store := ctx.KVStore(k.storeKey) - store.Delete(GetPacketCallbackKey(channel, packetSequence)) -} - -// StorePacketAckActor stores which contract is allowed to send an ack for the packet -func (k Keeper) StorePacketAckActor(ctx sdk.Context, packet channeltypes.Packet, contract string) { - store := ctx.KVStore(k.storeKey) - channel := packet.GetSourceChannel() - packetSequence := packet.GetSequence() - - val, err := GeneratePacketAckValue(packet, contract) - if err != nil { - panic(err) - } - store.Set(GetPacketAckKey(channel, packetSequence), val) -} - -// GetPacketAckActor returns the bech32 addr of the contract that is allowed to send an ack for the packet and the packet hash -func (k Keeper) GetPacketAckActor(ctx sdk.Context, channel string, packetSequence uint64) (string, string) { - store := ctx.KVStore(k.storeKey) - rawData := store.Get(GetPacketAckKey(channel, packetSequence)) - if rawData == nil { - return "", "" - } - data := strings.Split(string(rawData), "::") - if len(data) != 2 { - return "", "" - } - // validate that the contract is a valid bech32 addr - if _, err := sdk.AccAddressFromBech32(data[0]); err != nil { - return "", "" - } - // validate that the hash is a valid sha256sum hash - if _, err := hex.DecodeString(data[1]); err != nil { - return "", "" - } - - return data[0], data[1] -} - -// DeletePacketAckActor deletes the ack actor from storage once it has been used -func (k Keeper) DeletePacketAckActor(ctx sdk.Context, channel string, packetSequence uint64) { - store := ctx.KVStore(k.storeKey) - store.Delete(GetPacketAckKey(channel, packetSequence)) -} - -// DeriveIntermediateSender derives the sender address to be used when calling wasm hooks -func DeriveIntermediateSender(channel, originalSender, bech32Prefix string) (string, error) { - senderStr := fmt.Sprintf("%s/%s", channel, originalSender) - senderHash32 := address.Hash(types.SenderPrefix, []byte(senderStr)) - sender := sdk.AccAddress(senderHash32[:]) - return sdk.Bech32ifyAddressBytes(bech32Prefix, sender) -} - -// EmitIBCAck emits an event that the IBC packet has been acknowledged -func (k Keeper) EmitIBCAck(ctx sdk.Context, sender, channel string, packetSequence uint64) ([]byte, error) { - contract, packetHash := k.GetPacketAckActor(ctx, channel, packetSequence) - if contract == "" { - return nil, fmt.Errorf("no ack actor set for channel %s packet %d", channel, packetSequence) - } - // Only the contract itself can request for the ack to be emitted. This will generally happen as a callback - // when the result of other IBC actions has finished, but it could be exposed directly by the contract if the - // proper checks are made - if sender != contract { - return nil, fmt.Errorf("sender %s is not allowed to send an ack for channel %s packet %d", sender, channel, packetSequence) - } - - // Write the acknowledgement - _, cap, err := k.channelKeeper.LookupModuleByChannel(ctx, "transfer", channel) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id") - } - - // Calling the contract. This could be made generic by using an interface if we want - // to support other types of AckActors, but keeping it here for now for simplicity. - contractAddr, err := sdk.AccAddressFromBech32(contract) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not parse contract address") - } - - msg := types.IBCAsync{ - RequestAck: types.RequestAck{RequestAckI: types.RequestAckI{ - PacketSequence: packetSequence, - SourceChannel: channel, - }}, - } - msgBytes, err := json.Marshal(msg) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not marshal message") - } - bz, err := k.ContractKeeper.Sudo(ctx, contractAddr, msgBytes) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not execute contract") - } - - ack, err := types.UnmarshalIBCAck(bz) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not unmarshal into IBCAckResponse or IBCAckError") - - } - var newAck channeltypes.Acknowledgement - var packet channeltypes.Packet - - switch ack.Type { - case "ack_response": - jsonAck, err := json.Marshal(ack.AckResponse.ContractAck) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not marshal acknowledgement") - } - packet = ack.AckResponse.Packet - newAck = channeltypes.NewResultAcknowledgement(jsonAck) - case "ack_error": - packet = ack.AckError.Packet - newAck = NewSuccessAckRepresentingAnError(ctx, types.ErrAckFromContract, []byte(ack.AckError.ErrorResponse), ack.AckError.ErrorDescription) - default: - return nil, sdkerrors.Wrap(err, "could not unmarshal into IBCAckResponse or IBCAckError") - } - - // Validate that the packet returned by the contract matches the one we stored when sending - receivedPacketHash, err := hashPacket(packet) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not hash packet") - } - if receivedPacketHash != packetHash { - return nil, sdkerrors.Wrap(types.ErrAckPacketMismatch, fmt.Sprintf("packet hash mismatch. Expected %s, got %s", packetHash, receivedPacketHash)) - } - - // Now we can write the acknowledgement - err = k.channelKeeper.WriteAcknowledgement(ctx, cap, packet, newAck) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not write acknowledgement") - } - - response, err := json.Marshal(newAck) - if err != nil { - return nil, sdkerrors.Wrap(err, "could not marshal acknowledgement") - } - return response, nil -} - -func hashPacket(packet channeltypes.Packet) (string, error) { - // ignore the data here. We only care about the channel information - packet.Data = nil - bz, err := json.Marshal(packet) - if err != nil { - return "", sdkerrors.Wrap(err, "could not marshal packet") - } - packetHash := tmhash.Sum(bz) - return hex.EncodeToString(packetHash), nil -} diff --git a/x/onion/keeper/msg_server.go b/x/onion/keeper/msg_server.go index 18c2fa48..2749b4f2 100644 --- a/x/onion/keeper/msg_server.go +++ b/x/onion/keeper/msg_server.go @@ -1,11 +1,7 @@ package keeper import ( - "context" - "strconv" - "github.com/Team-Kujira/core/x/onion/types" - sdk "github.com/cosmos/cosmos-sdk/types" ) type msgServer struct { @@ -19,23 +15,3 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer { } var _ types.MsgServer = msgServer{} - -func (m msgServer) EmitIBCAck(goCtx context.Context, msg *types.MsgEmitIBCAck) (*types.MsgEmitIBCAckResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - - ctx.EventManager().EmitEvent( - sdk.NewEvent( - types.MsgEmitAckKey, - sdk.NewAttribute(types.AttributeSender, msg.Sender), - sdk.NewAttribute(types.AttributeChannel, msg.Channel), - sdk.NewAttribute(types.AttributePacketSequence, strconv.FormatUint(msg.PacketSequence, 10)), - ), - ) - - ack, err := m.Keeper.EmitIBCAck(ctx, msg.Sender, msg.Channel, msg.PacketSequence) - if err != nil { - return nil, err - } - - return &types.MsgEmitIBCAckResponse{ContractResult: string(ack), IbcAck: string(ack)}, nil -} diff --git a/x/onion/types/codec.go b/x/onion/types/codec.go index 5cd725f9..e98cf34b 100644 --- a/x/onion/types/codec.go +++ b/x/onion/types/codec.go @@ -11,13 +11,11 @@ import ( ) func RegisterCodec(cdc *codec.LegacyAmino) { - cdc.RegisterConcrete(&MsgEmitIBCAck{}, "kujira/ibc-hooks/emit-ibc-ack", nil) } func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { registry.RegisterImplementations( (*sdk.Msg)(nil), - &MsgEmitIBCAck{}, ) msgservice.RegisterMsgServiceDesc(registry, &_Msg_serviceDesc) } diff --git a/x/onion/types/expected_keepers.go b/x/onion/types/expected_keepers.go index bb12dc77..81b72b12 100644 --- a/x/onion/types/expected_keepers.go +++ b/x/onion/types/expected_keepers.go @@ -3,19 +3,8 @@ package types import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - "github.com/cosmos/ibc-go/v7/modules/core/exported" ) -type ChannelKeeper interface { - GetChannel(ctx sdk.Context, srcPort, srcChan string) (channel channeltypes.Channel, found bool) - GetPacketCommitment(ctx sdk.Context, portID, channelID string, sequence uint64) []byte - GetNextSequenceSend(ctx sdk.Context, portID, channelID string) (uint64, bool) - LookupModuleByChannel(ctx sdk.Context, portID, channelID string) (string, *capabilitytypes.Capability, error) - WriteAcknowledgement(ctx sdk.Context, chanCap *capabilitytypes.Capability, packet exported.PacketI, acknowledgement exported.Acknowledgement) error -} - type AccountKeeper interface { GetParams(ctx sdk.Context) (params authtypes.Params) GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI diff --git a/x/onion/types/msgs.go b/x/onion/types/msgs.go index 85ccb3b8..ab1254f4 100644 --- a/x/onion/types/msgs.go +++ b/x/onion/types/msgs.go @@ -1,32 +1 @@ package types - -import ( - sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" -) - -// constants. -const ( - TypeMsgEmitIBCAck = "emit-ibc-ack" -) - -var _ sdk.Msg = &MsgEmitIBCAck{} - -func (m MsgEmitIBCAck) Route() string { return RouterKey } -func (m MsgEmitIBCAck) Type() string { return TypeMsgEmitIBCAck } -func (m MsgEmitIBCAck) ValidateBasic() error { - _, err := sdk.AccAddressFromBech32(m.Sender) - if err != nil { - return sdkerrors.Wrapf(sdkerrors.ErrInvalidAddress, "Invalid sender address (%s)", err) - } - return nil -} - -func (m MsgEmitIBCAck) GetSignBytes() []byte { - return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&m)) -} - -func (m MsgEmitIBCAck) GetSigners() []sdk.AccAddress { - sender, _ := sdk.AccAddressFromBech32(m.Sender) - return []sdk.AccAddress{sender} -} diff --git a/x/onion/types/params.go b/x/onion/types/params.go index 091fbb14..a7db94df 100644 --- a/x/onion/types/params.go +++ b/x/onion/types/params.go @@ -1,62 +1,33 @@ package types import ( - "fmt" - sdk "github.com/cosmos/cosmos-sdk/types" paramtypes "github.com/cosmos/cosmos-sdk/x/params/types" ) // Parameter store keys. var ( - KeyAsyncAckAllowList = []byte("AsyncAckAllowList") - _ paramtypes.ParamSet = &Params{} ) func ParamKeyTable() paramtypes.KeyTable { - return paramtypes.NewKeyTable().RegisterParamSet(&Params{}) + return paramtypes.NewKeyTable() } -func NewParams(allowedAsyncAckContracts []string) Params { - return Params{ - AllowedAsyncAckContracts: allowedAsyncAckContracts, - } +func NewParams() Params { + return Params{} } // DefaultParams returns default concentrated-liquidity module parameters. func DefaultParams() Params { - return Params{ - AllowedAsyncAckContracts: []string{}, - } + return Params{} } // ParamSetPairs implements params.ParamSet. func (p *Params) ParamSetPairs() paramtypes.ParamSetPairs { - return paramtypes.ParamSetPairs{ - paramtypes.NewParamSetPair(KeyAsyncAckAllowList, &p.AllowedAsyncAckContracts, validateAsyncAckAllowList), - } + return paramtypes.ParamSetPairs{} } // Validate params. func (p Params) Validate() error { - if err := validateAsyncAckAllowList(p.AllowedAsyncAckContracts); err != nil { - return err - } - return nil -} - -func validateAsyncAckAllowList(i interface{}) error { - allowedContracts, ok := i.([]string) - - if !ok { - return fmt.Errorf("invalid parameter type: %T", i) - } - - for _, contract := range allowedContracts { - if _, err := sdk.AccAddressFromBech32(contract); err != nil { - return err - } - } - return nil } diff --git a/x/onion/types/params.pb.go b/x/onion/types/params.pb.go index 3146401e..5dd3232d 100644 --- a/x/onion/types/params.pb.go +++ b/x/onion/types/params.pb.go @@ -26,7 +26,6 @@ var _ = math.Inf const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package type Params struct { - AllowedAsyncAckContracts []string `protobuf:"bytes,1,rep,name=allowed_async_ack_contracts,json=allowedAsyncAckContracts,proto3" json:"allowed_async_ack_contracts,omitempty" yaml:"allowed_async_ack_contracts"` } func (m *Params) Reset() { *m = Params{} } @@ -62,13 +61,6 @@ func (m *Params) XXX_DiscardUnknown() { var xxx_messageInfo_Params proto.InternalMessageInfo -func (m *Params) GetAllowedAsyncAckContracts() []string { - if m != nil { - return m.AllowedAsyncAckContracts - } - return nil -} - func init() { proto.RegisterType((*Params)(nil), "kujira.onion.Params") } @@ -76,23 +68,19 @@ func init() { func init() { proto.RegisterFile("kujira/onion/params.proto", fileDescriptor_c9158e41ac96e8e0) } var fileDescriptor_c9158e41ac96e8e0 = []byte{ - // 248 bytes of a gzipped FileDescriptorProto + // 183 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0xcc, 0x2e, 0xcd, 0xca, 0x2c, 0x4a, 0xd4, 0xcf, 0xcf, 0xcb, 0xcc, 0xcf, 0xd3, 0x2f, 0x48, 0x2c, 0x4a, 0xcc, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x81, 0x48, 0xe9, 0x81, 0xa5, 0xa4, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x12, 0xfa, 0x20, 0x16, 0x44, 0x8d, 0x94, 0x64, 0x72, 0x7e, 0x71, 0x6e, 0x7e, 0x71, 0x3c, 0x44, 0x02, 0xc2, 0x81, 0x4a, 0xc9, 0xa5, 0xe7, 0xe7, 0xa7, 0xe7, 0xa4, 0xea, 0x83, - 0x79, 0x49, 0xa5, 0x69, 0xfa, 0x29, 0xa5, 0x45, 0x89, 0x25, 0x99, 0xf9, 0x79, 0x10, 0x79, 0xa5, - 0x7c, 0x2e, 0xb6, 0x00, 0xb0, 0x75, 0x42, 0xa9, 0x5c, 0xd2, 0x89, 0x39, 0x39, 0xf9, 0xe5, 0xa9, - 0x29, 0xf1, 0x89, 0xc5, 0x95, 0x79, 0xc9, 0xf1, 0x89, 0xc9, 0xd9, 0xf1, 0xc9, 0xf9, 0x79, 0x25, - 0x45, 0x89, 0xc9, 0x25, 0xc5, 0x12, 0x8c, 0x0a, 0xcc, 0x1a, 0x9c, 0x4e, 0x6a, 0x9f, 0xee, 0xc9, - 0x2b, 0x55, 0x26, 0xe6, 0xe6, 0x58, 0x29, 0xe1, 0x51, 0xac, 0x14, 0x24, 0x01, 0x95, 0x75, 0x04, - 0x49, 0x3a, 0x26, 0x67, 0x3b, 0xc3, 0xa4, 0x9c, 0x9c, 0x4f, 0x3c, 0x92, 0x63, 0xbc, 0xf0, 0x48, - 0x8e, 0xf1, 0xc1, 0x23, 0x39, 0xc6, 0x09, 0x8f, 0xe5, 0x18, 0x2e, 0x3c, 0x96, 0x63, 0xb8, 0xf1, - 0x58, 0x8e, 0x21, 0x4a, 0x33, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0x3f, - 0x24, 0x35, 0x31, 0x57, 0xd7, 0x1b, 0x12, 0x28, 0xc9, 0xf9, 0x45, 0xa9, 0xfa, 0x15, 0xd0, 0xb0, - 0x29, 0xa9, 0x2c, 0x48, 0x2d, 0x4e, 0x62, 0x03, 0x3b, 0xde, 0x18, 0x10, 0x00, 0x00, 0xff, 0xff, - 0x5b, 0x3f, 0x21, 0xa2, 0x38, 0x01, 0x00, 0x00, + 0x79, 0x49, 0xa5, 0x69, 0xfa, 0x29, 0xa5, 0x45, 0x89, 0x25, 0x99, 0xf9, 0x79, 0x10, 0x79, 0x25, + 0x0e, 0x2e, 0xb6, 0x00, 0xb0, 0x75, 0x4e, 0xce, 0x27, 0x1e, 0xc9, 0x31, 0x5e, 0x78, 0x24, 0xc7, + 0xf8, 0xe0, 0x91, 0x1c, 0xe3, 0x84, 0xc7, 0x72, 0x0c, 0x17, 0x1e, 0xcb, 0x31, 0xdc, 0x78, 0x2c, + 0xc7, 0x10, 0xa5, 0x99, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97, 0x9c, 0x9f, 0xab, 0x1f, 0x92, + 0x9a, 0x98, 0xab, 0xeb, 0x0d, 0x71, 0x6d, 0x72, 0x7e, 0x51, 0xaa, 0x7e, 0x05, 0xd4, 0xd1, 0x25, + 0x95, 0x05, 0xa9, 0xc5, 0x49, 0x6c, 0x60, 0x53, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x42, + 0xa0, 0x06, 0x6b, 0xd1, 0x00, 0x00, 0x00, } func (m *Params) Marshal() (dAtA []byte, err error) { @@ -115,15 +103,6 @@ func (m *Params) MarshalToSizedBuffer(dAtA []byte) (int, error) { _ = i var l int _ = l - if len(m.AllowedAsyncAckContracts) > 0 { - for iNdEx := len(m.AllowedAsyncAckContracts) - 1; iNdEx >= 0; iNdEx-- { - i -= len(m.AllowedAsyncAckContracts[iNdEx]) - copy(dAtA[i:], m.AllowedAsyncAckContracts[iNdEx]) - i = encodeVarintParams(dAtA, i, uint64(len(m.AllowedAsyncAckContracts[iNdEx]))) - i-- - dAtA[i] = 0xa - } - } return len(dAtA) - i, nil } @@ -144,12 +123,6 @@ func (m *Params) Size() (n int) { } var l int _ = l - if len(m.AllowedAsyncAckContracts) > 0 { - for _, s := range m.AllowedAsyncAckContracts { - l = len(s) - n += 1 + l + sovParams(uint64(l)) - } - } return n } @@ -188,38 +161,6 @@ func (m *Params) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: Params: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field AllowedAsyncAckContracts", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowParams - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthParams - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthParams - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.AllowedAsyncAckContracts = append(m.AllowedAsyncAckContracts, string(dAtA[iNdEx:postIndex])) - iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipParams(dAtA[iNdEx:]) diff --git a/x/onion/types/tx.pb.go b/x/onion/types/tx.pb.go index f4eda7a8..cdd9e7a3 100644 --- a/x/onion/types/tx.pb.go +++ b/x/onion/types/tx.pb.go @@ -10,11 +10,7 @@ import ( grpc1 "github.com/cosmos/gogoproto/grpc" proto "github.com/cosmos/gogoproto/proto" grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" - io "io" math "math" - math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. @@ -28,150 +24,19 @@ var _ = math.Inf // proto package needs to be updated. const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package -type MsgEmitIBCAck struct { - Sender string `protobuf:"bytes,1,opt,name=sender,proto3" json:"sender,omitempty" yaml:"sender"` - PacketSequence uint64 `protobuf:"varint,2,opt,name=packet_sequence,json=packetSequence,proto3" json:"packet_sequence,omitempty" yaml:"packet_sequence"` - Channel string `protobuf:"bytes,3,opt,name=channel,proto3" json:"channel,omitempty" yaml:"channel"` -} - -func (m *MsgEmitIBCAck) Reset() { *m = MsgEmitIBCAck{} } -func (m *MsgEmitIBCAck) String() string { return proto.CompactTextString(m) } -func (*MsgEmitIBCAck) ProtoMessage() {} -func (*MsgEmitIBCAck) Descriptor() ([]byte, []int) { - return fileDescriptor_788539ffbe617633, []int{0} -} -func (m *MsgEmitIBCAck) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgEmitIBCAck) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgEmitIBCAck.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *MsgEmitIBCAck) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgEmitIBCAck.Merge(m, src) -} -func (m *MsgEmitIBCAck) XXX_Size() int { - return m.Size() -} -func (m *MsgEmitIBCAck) XXX_DiscardUnknown() { - xxx_messageInfo_MsgEmitIBCAck.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgEmitIBCAck proto.InternalMessageInfo - -func (m *MsgEmitIBCAck) GetSender() string { - if m != nil { - return m.Sender - } - return "" -} - -func (m *MsgEmitIBCAck) GetPacketSequence() uint64 { - if m != nil { - return m.PacketSequence - } - return 0 -} - -func (m *MsgEmitIBCAck) GetChannel() string { - if m != nil { - return m.Channel - } - return "" -} - -type MsgEmitIBCAckResponse struct { - ContractResult string `protobuf:"bytes,1,opt,name=contract_result,json=contractResult,proto3" json:"contract_result,omitempty" yaml:"contract_result"` - IbcAck string `protobuf:"bytes,2,opt,name=ibc_ack,json=ibcAck,proto3" json:"ibc_ack,omitempty" yaml:"ibc_ack"` -} - -func (m *MsgEmitIBCAckResponse) Reset() { *m = MsgEmitIBCAckResponse{} } -func (m *MsgEmitIBCAckResponse) String() string { return proto.CompactTextString(m) } -func (*MsgEmitIBCAckResponse) ProtoMessage() {} -func (*MsgEmitIBCAckResponse) Descriptor() ([]byte, []int) { - return fileDescriptor_788539ffbe617633, []int{1} -} -func (m *MsgEmitIBCAckResponse) XXX_Unmarshal(b []byte) error { - return m.Unmarshal(b) -} -func (m *MsgEmitIBCAckResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - if deterministic { - return xxx_messageInfo_MsgEmitIBCAckResponse.Marshal(b, m, deterministic) - } else { - b = b[:cap(b)] - n, err := m.MarshalToSizedBuffer(b) - if err != nil { - return nil, err - } - return b[:n], nil - } -} -func (m *MsgEmitIBCAckResponse) XXX_Merge(src proto.Message) { - xxx_messageInfo_MsgEmitIBCAckResponse.Merge(m, src) -} -func (m *MsgEmitIBCAckResponse) XXX_Size() int { - return m.Size() -} -func (m *MsgEmitIBCAckResponse) XXX_DiscardUnknown() { - xxx_messageInfo_MsgEmitIBCAckResponse.DiscardUnknown(m) -} - -var xxx_messageInfo_MsgEmitIBCAckResponse proto.InternalMessageInfo - -func (m *MsgEmitIBCAckResponse) GetContractResult() string { - if m != nil { - return m.ContractResult - } - return "" -} - -func (m *MsgEmitIBCAckResponse) GetIbcAck() string { - if m != nil { - return m.IbcAck - } - return "" -} - -func init() { - proto.RegisterType((*MsgEmitIBCAck)(nil), "kujira.onion.MsgEmitIBCAck") - proto.RegisterType((*MsgEmitIBCAckResponse)(nil), "kujira.onion.MsgEmitIBCAckResponse") -} - func init() { proto.RegisterFile("kujira/onion/tx.proto", fileDescriptor_788539ffbe617633) } var fileDescriptor_788539ffbe617633 = []byte{ - // 357 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x91, 0xc1, 0x4e, 0xea, 0x40, - 0x18, 0x85, 0x99, 0xcb, 0x0d, 0xe4, 0x4e, 0x2e, 0xdc, 0xdc, 0x89, 0x18, 0x82, 0x49, 0x21, 0xe3, - 0x06, 0xa2, 0xb6, 0x89, 0xee, 0xdc, 0x51, 0xe2, 0xc2, 0x18, 0x5c, 0x8c, 0xba, 0x71, 0x43, 0xa6, - 0xe3, 0xa4, 0xd4, 0xd2, 0x99, 0xda, 0x99, 0x26, 0xf0, 0x08, 0xee, 0x7c, 0x11, 0xdf, 0xc3, 0x25, - 0x4b, 0x57, 0xc4, 0xc0, 0x1b, 0xf0, 0x04, 0x86, 0x4e, 0x9b, 0x00, 0x0b, 0x77, 0x93, 0xef, 0x9c, - 0x3f, 0x73, 0xfe, 0xff, 0xc0, 0x46, 0x98, 0x3e, 0x07, 0x09, 0x75, 0xa4, 0x08, 0xa4, 0x70, 0xf4, - 0xd4, 0x8e, 0x13, 0xa9, 0x25, 0xfa, 0x6b, 0xb0, 0x9d, 0xe1, 0xd6, 0x81, 0x2f, 0x7d, 0x99, 0x09, - 0xce, 0xe6, 0x65, 0x3c, 0xf8, 0x1d, 0xc0, 0xda, 0x50, 0xf9, 0x57, 0x51, 0xa0, 0xaf, 0xdd, 0x41, - 0x9f, 0x85, 0xa8, 0x07, 0x2b, 0x8a, 0x8b, 0x27, 0x9e, 0x34, 0x41, 0x07, 0x74, 0xff, 0xb8, 0xff, - 0xd7, 0x8b, 0x76, 0x6d, 0x46, 0xa3, 0xc9, 0x25, 0x36, 0x1c, 0x93, 0xdc, 0x80, 0x06, 0xf0, 0x5f, - 0x4c, 0x59, 0xc8, 0xf5, 0x48, 0xf1, 0x97, 0x94, 0x0b, 0xc6, 0x9b, 0xbf, 0x3a, 0xa0, 0xfb, 0xdb, - 0x6d, 0xad, 0x17, 0xed, 0x43, 0x33, 0xb3, 0x67, 0xc0, 0xa4, 0x6e, 0xc8, 0x5d, 0x0e, 0xd0, 0x29, - 0xac, 0xb2, 0x31, 0x15, 0x82, 0x4f, 0x9a, 0xe5, 0xec, 0x43, 0xb4, 0x5e, 0xb4, 0xeb, 0x66, 0x38, - 0x17, 0x30, 0x29, 0x2c, 0xf8, 0x15, 0xc0, 0xc6, 0x4e, 0x5e, 0xc2, 0x55, 0x2c, 0x85, 0xe2, 0x9b, - 0x30, 0x4c, 0x0a, 0x9d, 0x50, 0xa6, 0x47, 0x09, 0x57, 0xe9, 0x44, 0xe7, 0x0b, 0x6c, 0x85, 0xd9, - 0x33, 0x60, 0x52, 0x2f, 0x08, 0xc9, 0x00, 0x3a, 0x81, 0xd5, 0xc0, 0x63, 0x23, 0xca, 0xc2, 0x6c, - 0x93, 0x9d, 0x30, 0xb9, 0x80, 0x49, 0x25, 0xf0, 0x58, 0x9f, 0x85, 0xe7, 0x0f, 0xb0, 0x3c, 0x54, - 0x3e, 0xba, 0x85, 0x70, 0xeb, 0x7c, 0x47, 0xf6, 0xf6, 0xd5, 0xed, 0x9d, 0xac, 0xad, 0xe3, 0x1f, - 0xc4, 0x62, 0x11, 0x77, 0xf0, 0xb1, 0xb4, 0xc0, 0x7c, 0x69, 0x81, 0xaf, 0xa5, 0x05, 0xde, 0x56, - 0x56, 0x69, 0xbe, 0xb2, 0x4a, 0x9f, 0x2b, 0xab, 0xf4, 0xd8, 0xf3, 0x03, 0x3d, 0x4e, 0x3d, 0x9b, - 0xc9, 0xc8, 0xb9, 0xe7, 0x34, 0x3a, 0xbb, 0x31, 0xbd, 0x33, 0x99, 0x70, 0x67, 0x5a, 0xd4, 0x3f, - 0x8b, 0xb9, 0xf2, 0x2a, 0x59, 0xbd, 0x17, 0xdf, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb4, 0xc3, 0xf3, - 0x4c, 0x1b, 0x02, 0x00, 0x00, + // 139 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcd, 0x2e, 0xcd, 0xca, + 0x2c, 0x4a, 0xd4, 0xcf, 0xcf, 0xcb, 0xcc, 0xcf, 0xd3, 0x2f, 0xa9, 0xd0, 0x2b, 0x28, 0xca, 0x2f, + 0xc9, 0x17, 0xe2, 0x81, 0x08, 0xeb, 0x81, 0x85, 0xa5, 0x44, 0xd2, 0xf3, 0xd3, 0xf3, 0xc1, 0x12, + 0xfa, 0x20, 0x16, 0x44, 0x8d, 0x11, 0x2b, 0x17, 0xb3, 0x6f, 0x71, 0xba, 0x93, 0xf3, 0x89, 0x47, + 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x85, + 0xc7, 0x72, 0x0c, 0x37, 0x1e, 0xcb, 0x31, 0x44, 0x69, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, + 0x25, 0xe7, 0xe7, 0xea, 0x87, 0xa4, 0x26, 0xe6, 0xea, 0x7a, 0x43, 0xec, 0x4a, 0xce, 0x2f, 0x4a, + 0xd5, 0xaf, 0x80, 0x59, 0x59, 0x59, 0x90, 0x5a, 0x9c, 0xc4, 0x06, 0x36, 0xd2, 0x18, 0x10, 0x00, + 0x00, 0xff, 0xff, 0x22, 0x53, 0x0d, 0xef, 0x8f, 0x00, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -186,9 +51,6 @@ const _ = grpc.SupportPackageIsVersion4 // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type MsgClient interface { - // EmitIBCAck checks the sender can emit the ack and writes the IBC - // acknowledgement - EmitIBCAck(ctx context.Context, in *MsgEmitIBCAck, opts ...grpc.CallOption) (*MsgEmitIBCAckResponse, error) } type msgClient struct { @@ -199,526 +61,22 @@ func NewMsgClient(cc grpc1.ClientConn) MsgClient { return &msgClient{cc} } -func (c *msgClient) EmitIBCAck(ctx context.Context, in *MsgEmitIBCAck, opts ...grpc.CallOption) (*MsgEmitIBCAckResponse, error) { - out := new(MsgEmitIBCAckResponse) - err := c.cc.Invoke(ctx, "/kujira.onion.Msg/EmitIBCAck", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - // MsgServer is the server API for Msg service. type MsgServer interface { - // EmitIBCAck checks the sender can emit the ack and writes the IBC - // acknowledgement - EmitIBCAck(context.Context, *MsgEmitIBCAck) (*MsgEmitIBCAckResponse, error) } // UnimplementedMsgServer can be embedded to have forward compatible implementations. type UnimplementedMsgServer struct { } -func (*UnimplementedMsgServer) EmitIBCAck(ctx context.Context, req *MsgEmitIBCAck) (*MsgEmitIBCAckResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method EmitIBCAck not implemented") -} - func RegisterMsgServer(s grpc1.Server, srv MsgServer) { s.RegisterService(&_Msg_serviceDesc, srv) } -func _Msg_EmitIBCAck_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(MsgEmitIBCAck) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(MsgServer).EmitIBCAck(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/kujira.onion.Msg/EmitIBCAck", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(MsgServer).EmitIBCAck(ctx, req.(*MsgEmitIBCAck)) - } - return interceptor(ctx, in, info, handler) -} - var _Msg_serviceDesc = grpc.ServiceDesc{ ServiceName: "kujira.onion.Msg", HandlerType: (*MsgServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "EmitIBCAck", - Handler: _Msg_EmitIBCAck_Handler, - }, - }, - Streams: []grpc.StreamDesc{}, - Metadata: "kujira/onion/tx.proto", -} - -func (m *MsgEmitIBCAck) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgEmitIBCAck) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgEmitIBCAck) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.Channel) > 0 { - i -= len(m.Channel) - copy(dAtA[i:], m.Channel) - i = encodeVarintTx(dAtA, i, uint64(len(m.Channel))) - i-- - dAtA[i] = 0x1a - } - if m.PacketSequence != 0 { - i = encodeVarintTx(dAtA, i, uint64(m.PacketSequence)) - i-- - dAtA[i] = 0x10 - } - if len(m.Sender) > 0 { - i -= len(m.Sender) - copy(dAtA[i:], m.Sender) - i = encodeVarintTx(dAtA, i, uint64(len(m.Sender))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func (m *MsgEmitIBCAckResponse) Marshal() (dAtA []byte, err error) { - size := m.Size() - dAtA = make([]byte, size) - n, err := m.MarshalToSizedBuffer(dAtA[:size]) - if err != nil { - return nil, err - } - return dAtA[:n], nil -} - -func (m *MsgEmitIBCAckResponse) MarshalTo(dAtA []byte) (int, error) { - size := m.Size() - return m.MarshalToSizedBuffer(dAtA[:size]) -} - -func (m *MsgEmitIBCAckResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) { - i := len(dAtA) - _ = i - var l int - _ = l - if len(m.IbcAck) > 0 { - i -= len(m.IbcAck) - copy(dAtA[i:], m.IbcAck) - i = encodeVarintTx(dAtA, i, uint64(len(m.IbcAck))) - i-- - dAtA[i] = 0x12 - } - if len(m.ContractResult) > 0 { - i -= len(m.ContractResult) - copy(dAtA[i:], m.ContractResult) - i = encodeVarintTx(dAtA, i, uint64(len(m.ContractResult))) - i-- - dAtA[i] = 0xa - } - return len(dAtA) - i, nil -} - -func encodeVarintTx(dAtA []byte, offset int, v uint64) int { - offset -= sovTx(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *MsgEmitIBCAck) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Sender) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - if m.PacketSequence != 0 { - n += 1 + sovTx(uint64(m.PacketSequence)) - } - l = len(m.Channel) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func (m *MsgEmitIBCAckResponse) Size() (n int) { - if m == nil { - return 0 - } - var l int - _ = l - l = len(m.ContractResult) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - l = len(m.IbcAck) - if l > 0 { - n += 1 + l + sovTx(uint64(l)) - } - return n -} - -func sovTx(x uint64) (n int) { - return (math_bits.Len64(x|1) + 6) / 7 + Methods: []grpc.MethodDesc{}, + Streams: []grpc.StreamDesc{}, + Metadata: "kujira/onion/tx.proto", } -func sozTx(x uint64) (n int) { - return sovTx(uint64((x << 1) ^ uint64((int64(x) >> 63)))) -} -func (m *MsgEmitIBCAck) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgEmitIBCAck: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgEmitIBCAck: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Sender", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Sender = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field PacketSequence", wireType) - } - m.PacketSequence = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.PacketSequence |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - case 3: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field Channel", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.Channel = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func (m *MsgEmitIBCAckResponse) Unmarshal(dAtA []byte) error { - l := len(dAtA) - iNdEx := 0 - for iNdEx < l { - preIndex := iNdEx - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - fieldNum := int32(wire >> 3) - wireType := int(wire & 0x7) - if wireType == 4 { - return fmt.Errorf("proto: MsgEmitIBCAckResponse: wiretype end group for non-group") - } - if fieldNum <= 0 { - return fmt.Errorf("proto: MsgEmitIBCAckResponse: illegal tag %d (wire type %d)", fieldNum, wire) - } - switch fieldNum { - case 1: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field ContractResult", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.ContractResult = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - case 2: - if wireType != 2 { - return fmt.Errorf("proto: wrong wireType = %d for field IbcAck", wireType) - } - var stringLen uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowTx - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - stringLen |= uint64(b&0x7F) << shift - if b < 0x80 { - break - } - } - intStringLen := int(stringLen) - if intStringLen < 0 { - return ErrInvalidLengthTx - } - postIndex := iNdEx + intStringLen - if postIndex < 0 { - return ErrInvalidLengthTx - } - if postIndex > l { - return io.ErrUnexpectedEOF - } - m.IbcAck = string(dAtA[iNdEx:postIndex]) - iNdEx = postIndex - default: - iNdEx = preIndex - skippy, err := skipTx(dAtA[iNdEx:]) - if err != nil { - return err - } - if (skippy < 0) || (iNdEx+skippy) < 0 { - return ErrInvalidLengthTx - } - if (iNdEx + skippy) > l { - return io.ErrUnexpectedEOF - } - iNdEx += skippy - } - } - - if iNdEx > l { - return io.ErrUnexpectedEOF - } - return nil -} -func skipTx(dAtA []byte) (n int, err error) { - l := len(dAtA) - iNdEx := 0 - depth := 0 - for iNdEx < l { - var wire uint64 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTx - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - wire |= (uint64(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - wireType := int(wire & 0x7) - switch wireType { - case 0: - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTx - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - iNdEx++ - if dAtA[iNdEx-1] < 0x80 { - break - } - } - case 1: - iNdEx += 8 - case 2: - var length int - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return 0, ErrIntOverflowTx - } - if iNdEx >= l { - return 0, io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - length |= (int(b) & 0x7F) << shift - if b < 0x80 { - break - } - } - if length < 0 { - return 0, ErrInvalidLengthTx - } - iNdEx += length - case 3: - depth++ - case 4: - if depth == 0 { - return 0, ErrUnexpectedEndOfGroupTx - } - depth-- - case 5: - iNdEx += 4 - default: - return 0, fmt.Errorf("proto: illegal wireType %d", wireType) - } - if iNdEx < 0 { - return 0, ErrInvalidLengthTx - } - if depth == 0 { - return iNdEx, nil - } - } - return 0, io.ErrUnexpectedEOF -} - -var ( - ErrInvalidLengthTx = fmt.Errorf("proto: negative length found during unmarshaling") - ErrIntOverflowTx = fmt.Errorf("proto: integer overflow") - ErrUnexpectedEndOfGroupTx = fmt.Errorf("proto: unexpected end of group") -) diff --git a/x/onion/types/types.go b/x/onion/types/types.go index d3caffa6..ab1254f4 100644 --- a/x/onion/types/types.go +++ b/x/onion/types/types.go @@ -1,85 +1 @@ package types - -import ( - "encoding/json" - - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" -) - -// Async: The following types represent the response sent by a contract on OnRecvPacket when it wants the ack to be async - -// OnRecvPacketAsyncAckResponse the response a contract sends to instruct the module to make the ack async -type OnRecvPacketAsyncAckResponse struct { - IsAsyncAck bool `json:"is_async_ack"` -} - -// Async The following types are used to ask a contract that has sent a packet to generate an ack for it - -// RequestAckI internals of IBCAsync -type RequestAckI struct { - PacketSequence uint64 `json:"packet_sequence"` - SourceChannel string `json:"source_channel"` -} - -// RequestAck internals of IBCAsync -type RequestAck struct { - RequestAckI `json:"request_ack"` -} - -// IBCAsync is the sudo message to be sent to the contract for it to generate an ack for a sent packet -type IBCAsync struct { - RequestAck `json:"ibc_async"` -} - -// General - -// ContractAck is the response to be stored when a wasm hook is executed -type ContractAck struct { - ContractResult []byte `json:"contract_result"` - IbcAck []byte `json:"ibc_ack"` -} - -// IBCAckResponse is the response that a contract returns from the sudo() call on OnRecvPacket or RequestAck -type IBCAckResponse struct { - Packet channeltypes.Packet `json:"packet"` - ContractAck ContractAck `json:"contract_ack"` -} - -// IBCAckError is the error that a contract returns from the sudo() call on RequestAck -type IBCAckError struct { - Packet channeltypes.Packet `json:"packet"` - ErrorDescription string `json:"error_description"` - ErrorResponse string `json:"error_response"` -} - -type IBCAck struct { - Type string `json:"type"` - Content json.RawMessage `json:"content"` - // Note: These two fields have to be pointers so that they can be null - // If they are not pointers, they will be empty structs when null, - // which will cause issues with json.Unmarshal. - AckResponse *IBCAckResponse `json:"response,omitempty"` - AckError *IBCAckError `json:"error,omitempty"` -} - -func UnmarshalIBCAck(bz []byte) (*IBCAck, error) { - var ack IBCAck - if err := json.Unmarshal(bz, &ack); err != nil { - return nil, err - } - - switch ack.Type { - case "ack_response": - ack.AckResponse = &IBCAckResponse{} - if err := json.Unmarshal(ack.Content, ack.AckResponse); err != nil { - return nil, err - } - case "ack_error": - ack.AckError = &IBCAckError{} - if err := json.Unmarshal(ack.Content, ack.AckError); err != nil { - return nil, err - } - } - - return &ack, nil -} diff --git a/x/onion/wasm_hook.go b/x/onion/wasm_hook.go deleted file mode 100644 index cca116ae..00000000 --- a/x/onion/wasm_hook.go +++ /dev/null @@ -1,381 +0,0 @@ -package onion - -import ( - "encoding/json" - "fmt" - - sdk "github.com/cosmos/cosmos-sdk/types" - capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - - errorsmod "cosmossdk.io/errors" - "cosmossdk.io/math" - wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" - wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types" - - "github.com/Team-Kujira/core/x/onion/keeper" - transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" - clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types" - channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" - ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" - - "github.com/Team-Kujira/core/x/onion/types" -) - -type WasmHooks struct { - ContractKeeper *wasmkeeper.Keeper - ibcHooksKeeper *keeper.Keeper - bech32PrefixAccAddr string -} - -func NewWasmHooks(ibcHooksKeeper *keeper.Keeper, contractKeeper *wasmkeeper.Keeper, bech32PrefixAccAddr string) WasmHooks { - return WasmHooks{ - ContractKeeper: contractKeeper, - ibcHooksKeeper: ibcHooksKeeper, - bech32PrefixAccAddr: bech32PrefixAccAddr, - } -} - -func (h WasmHooks) ProperlyConfigured() bool { - return h.ContractKeeper != nil && h.ibcHooksKeeper != nil -} - -func (h WasmHooks) OnRecvPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) ibcexported.Acknowledgement { - if !h.ProperlyConfigured() { - // Not configured - return im.App.OnRecvPacket(ctx, packet, relayer) - } - isIcs20, data := isIcs20Packet(packet.GetData()) - if !isIcs20 { - return im.App.OnRecvPacket(ctx, packet, relayer) - } - - // Validate the memo - isWasmRouted, contractAddr, msgBytes, err := ValidateAndParseMemo(data.GetMemo(), data.Receiver) - if !isWasmRouted { - return im.App.OnRecvPacket(ctx, packet, relayer) - } - if err != nil { - return NewEmitErrorAcknowledgement(ctx, types.ErrMsgValidation, err.Error()) - } - if msgBytes == nil || contractAddr == nil { // This should never happen - return NewEmitErrorAcknowledgement(ctx, types.ErrMsgValidation) - } - - // Calculate the receiver / contract caller based on the packet's channel and sender - channel := packet.GetDestChannel() - sender := data.GetSender() - senderBech32, err := keeper.DeriveIntermediateSender(channel, sender, h.bech32PrefixAccAddr) - if err != nil { - return NewEmitErrorAcknowledgement(ctx, types.ErrBadSender, fmt.Sprintf("cannot convert sender address %s/%s to bech32: %s", channel, sender, err.Error())) - } - - // The funds sent on this packet need to be transferred to the intermediary account for the sender. - // For this, we override the ICS20 packet's Receiver (essentially hijacking the funds to this new address) - // and execute the underlying OnRecvPacket() call (which should eventually land on the transfer app's - // relay.go and send the sunds to the intermediary account. - // - // If that succeeds, we make the contract call - data.Receiver = senderBech32 - bz, err := json.Marshal(data) - if err != nil { - return NewEmitErrorAcknowledgement(ctx, types.ErrMarshaling, err.Error()) - } - packet.Data = bz - - // Execute the receive - ack := im.App.OnRecvPacket(ctx, packet, relayer) - if !ack.Success() { - return ack - } - - amount, ok := math.NewIntFromString(data.GetAmount()) - if !ok { - // This should never happen, as it should've been caught in the underlying call to OnRecvPacket, - // but returning here for completeness - return NewEmitErrorAcknowledgement(ctx, types.ErrInvalidPacket, "Amount is not an int") - } - - // The packet's denom is the denom in the sender chain. This needs to be converted to the local denom. - denom := MustExtractDenomFromPacketOnRecv(packet) - funds := sdk.NewCoins(sdk.NewCoin(denom, amount)) - - // Execute the contract - execMsg := wasmtypes.MsgExecuteContract{ - Sender: senderBech32, - Contract: contractAddr.String(), - Msg: msgBytes, - Funds: funds, - } - response, err := h.execWasmMsg(ctx, &execMsg) - if err != nil { - return NewEmitErrorAcknowledgement(ctx, types.ErrWasmError, err.Error()) - } - - // Check if the contract is requesting for the ack to be async. - var asyncAckRequest types.OnRecvPacketAsyncAckResponse - err = json.Unmarshal(response.Data, &asyncAckRequest) - if err == nil { - // If unmarshalling succeeds, the contract is requesting for the ack to be async. - if asyncAckRequest.IsAsyncAck { // in which case IsAsyncAck is expected to be set to true - if !h.ibcHooksKeeper.IsInAllowList(ctx, contractAddr.String()) { - // Only allowed contracts can send async acks - return NewEmitErrorAcknowledgement(ctx, types.ErrAsyncAckNotAllowed) - } - // Store the contract as the packet's ack actor and return nil - h.ibcHooksKeeper.StorePacketAckActor(ctx, packet, contractAddr.String()) - return nil - } - } - - // If the ack is not async, we continue generating the ack and return it - fullAck := types.ContractAck{ContractResult: response.Data, IbcAck: ack.Acknowledgement()} - bz, err = json.Marshal(fullAck) - if err != nil { - return NewEmitErrorAcknowledgement(ctx, types.ErrBadResponse, err.Error()) - } - - return channeltypes.NewResultAcknowledgement(bz) -} - -func (h WasmHooks) execWasmMsg(ctx sdk.Context, execMsg *wasmtypes.MsgExecuteContract) (*wasmtypes.MsgExecuteContractResponse, error) { - if err := execMsg.ValidateBasic(); err != nil { - return nil, fmt.Errorf(types.ErrBadExecutionMsg, err.Error()) - } - wasmMsgServer := wasmkeeper.NewMsgServerImpl(h.ContractKeeper) - return wasmMsgServer.ExecuteContract(sdk.WrapSDKContext(ctx), execMsg) -} - -func isIcs20Packet(data []byte) (isIcs20 bool, ics20data transfertypes.FungibleTokenPacketData) { - var packetdata transfertypes.FungibleTokenPacketData - if err := json.Unmarshal(data, &packetdata); err != nil { - return false, packetdata - } - return true, packetdata -} - -// jsonStringHasKey parses the memo as a json object and checks if it contains the key. -func jsonStringHasKey(memo, key string) (found bool, jsonObject map[string]interface{}) { - jsonObject = make(map[string]interface{}) - - // If there is no memo, the packet was either sent with an earlier version of IBC, or the memo was - // intentionally left blank. Nothing to do here. Ignore the packet and pass it down the stack. - if len(memo) == 0 { - return false, jsonObject - } - - // the jsonObject must be a valid JSON object - err := json.Unmarshal([]byte(memo), &jsonObject) - if err != nil { - return false, jsonObject - } - - // If the key doesn't exist, there's nothing to do on this hook. Continue by passing the packet - // down the stack - _, ok := jsonObject[key] - if !ok { - return false, jsonObject - } - - return true, jsonObject -} - -func ValidateAndParseMemo(memo string, receiver string) (isWasmRouted bool, contractAddr sdk.AccAddress, msgBytes []byte, err error) { - isWasmRouted, metadata := jsonStringHasKey(memo, "wasm") - if !isWasmRouted { - return isWasmRouted, sdk.AccAddress{}, nil, nil - } - - wasmRaw := metadata["wasm"] - - // Make sure the wasm key is a map. If it isn't, ignore this packet - wasm, ok := wasmRaw.(map[string]interface{}) - if !ok { - return isWasmRouted, sdk.AccAddress{}, nil, - fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, "wasm metadata is not a valid JSON map object") - } - - // Get the contract - contract, ok := wasm["contract"].(string) - if !ok { - // The tokens will be returned - return isWasmRouted, sdk.AccAddress{}, nil, - fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, `Could not find key wasm["contract"]`) - } - - contractAddr, err = sdk.AccAddressFromBech32(contract) - if err != nil { - return isWasmRouted, sdk.AccAddress{}, nil, - fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, `wasm["contract"] is not a valid bech32 address`) - } - - // The contract and the receiver should be the same for the packet to be valid - if contract != receiver { - return isWasmRouted, sdk.AccAddress{}, nil, - fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, `wasm["contract"] should be the same as the receiver of the packet`) - } - - // Ensure the message key is provided - if wasm["msg"] == nil { - return isWasmRouted, sdk.AccAddress{}, nil, - fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, `Could not find key wasm["msg"]`) - } - - // Make sure the msg key is a map. If it isn't, return an error - _, ok = wasm["msg"].(map[string]interface{}) - if !ok { - return isWasmRouted, sdk.AccAddress{}, nil, - fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, `wasm["msg"] is not a map object`) - } - - // Get the message string by serializing the map - msgBytes, err = json.Marshal(wasm["msg"]) - if err != nil { - // The tokens will be returned - return isWasmRouted, sdk.AccAddress{}, nil, - fmt.Errorf(types.ErrBadMetadataFormatMsg, memo, err.Error()) - } - - return isWasmRouted, contractAddr, msgBytes, nil -} - -func (h WasmHooks) SendPacketOverride(i ICS4Middleware, ctx sdk.Context, chanCap *capabilitytypes.Capability, sourcePort string, sourceChannel string, timeoutHeight clienttypes.Height, timeoutTimestamp uint64, data []byte) (uint64, error) { - isIcs20, ics20data := isIcs20Packet(data) - if !isIcs20 { - return i.channel.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data) // continue - } - - isCallbackRouted, metadata := jsonStringHasKey(ics20data.GetMemo(), types.IBCCallbackKey) - if !isCallbackRouted { - return i.channel.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, data) // continue - } - - // We remove the callback metadata from the memo as it has already been processed. - - // If the only available key in the memo is the callback, we should remove the memo - // from the data completely so the packet is sent without it. - // This way receiver chains that are on old versions of IBC will be able to process the packet - callbackRaw := metadata[types.IBCCallbackKey] // This will be used later. - delete(metadata, types.IBCCallbackKey) - bzMetadata, err := json.Marshal(metadata) - if err != nil { - return 0, errorsmod.Wrap(err, "Send packet with callback error") - } - stringMetadata := string(bzMetadata) - if stringMetadata == "{}" { - ics20data.Memo = "" - } else { - ics20data.Memo = stringMetadata - } - dataBytes, err := json.Marshal(ics20data) - if err != nil { - return 0, errorsmod.Wrap(err, "Send packet with callback error") - } - - seq, err := i.channel.SendPacket(ctx, chanCap, sourcePort, sourceChannel, timeoutHeight, timeoutTimestamp, dataBytes) - if err != nil { - return 0, err - } - - // Make sure the callback contract is a string and a valid bech32 addr. If it isn't, ignore this packet - contract, ok := callbackRaw.(string) - if !ok { - return 0, nil - } - _, err = sdk.AccAddressFromBech32(contract) - if err != nil { - return 0, nil - } - - h.ibcHooksKeeper.StorePacketCallback(ctx, sourceChannel, seq, contract) - return seq, nil -} - -func (h WasmHooks) OnAcknowledgementPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, relayer sdk.AccAddress) error { - err := im.App.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer) - if err != nil { - return err - } - - if !h.ProperlyConfigured() { - // Not configured. Return from the underlying implementation - return nil - } - - contract := h.ibcHooksKeeper.GetPacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) - if contract == "" { - // No callback configured - return nil - } - - contractAddr, err := sdk.AccAddressFromBech32(contract) - if err != nil { - return errorsmod.Wrap(err, "Ack callback error") // The callback configured is not a bech32. Error out - } - - success := "false" - if !IsAckError(acknowledgement) { - success = "true" - } - - // Notify the sender that the ack has been received - ackAsJson, err := json.Marshal(acknowledgement) - if err != nil { - // If the ack is not a json object, error - return err - } - - sudoMsg := []byte(fmt.Sprintf( - `{"ibc_lifecycle_complete": {"ibc_ack": {"channel": "%s", "sequence": %d, "ack": %s, "success": %s}}}`, - packet.SourceChannel, packet.Sequence, ackAsJson, success)) - _, err = h.ContractKeeper.Sudo(ctx, contractAddr, sudoMsg) - if err != nil { - // error processing the callback - // ToDo: Open Question: Should we also delete the callback here? - return errorsmod.Wrap(err, "Ack callback error") - } - h.ibcHooksKeeper.DeletePacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) - return nil -} - -func (h WasmHooks) OnTimeoutPacketOverride(im IBCMiddleware, ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress) error { - err := im.App.OnTimeoutPacket(ctx, packet, relayer) - if err != nil { - return err - } - - if !h.ProperlyConfigured() { - // Not configured. Return from the underlying implementation - return nil - } - - contract := h.ibcHooksKeeper.GetPacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) - if contract == "" { - // No callback configured - return nil - } - - contractAddr, err := sdk.AccAddressFromBech32(contract) - if err != nil { - return errorsmod.Wrap(err, "Timeout callback error") // The callback configured is not a bech32. Error out - } - - sudoMsg := []byte(fmt.Sprintf( - `{"ibc_lifecycle_complete": {"ibc_timeout": {"channel": "%s", "sequence": %d}}}`, - packet.SourceChannel, packet.Sequence)) - _, err = h.ContractKeeper.Sudo(ctx, contractAddr, sudoMsg) - if err != nil { - // error processing the callback. This could be because the contract doesn't implement the message type to - // process the callback. Retrying this will not help, so we can delete the callback from storage. - // Since the packet has timed out, we don't expect any other responses that may trigger the callback. - ctx.EventManager().EmitEvents(sdk.Events{ - sdk.NewEvent( - "ibc-timeout-callback-error", - sdk.NewAttribute("contract", contractAddr.String()), - sdk.NewAttribute("message", string(sudoMsg)), - sdk.NewAttribute("error", err.Error()), - ), - }) - } - h.ibcHooksKeeper.DeletePacketCallback(ctx, packet.GetSourceChannel(), packet.GetSequence()) - return nil -} From cdb95950b86ce273b495bae689323d0b5f0bd1f9 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Fri, 28 Jun 2024 10:55:11 +0800 Subject: [PATCH 07/15] Update onion tx account number to use max uint64 --- x/onion/client/cli/tx.go | 1 + x/onion/keeper/execute.go | 6 +----- x/onion/types/keys.go | 2 ++ 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/x/onion/client/cli/tx.go b/x/onion/client/cli/tx.go index 604066fe..9c21bf31 100644 --- a/x/onion/client/cli/tx.go +++ b/x/onion/client/cli/tx.go @@ -95,6 +95,7 @@ func WriteBase64Tx(clientCtx client.Context, flagSet *pflag.FlagSet, msgs ...sdk newSeq = res.Seq.Sequence } txf = txf.WithSequence(newSeq) + txf = txf.WithAccountNumber(types.AccountNumber) if txf.SimulateAndExecute() || clientCtx.Simulate { if clientCtx.Offline { diff --git a/x/onion/keeper/execute.go b/x/onion/keeper/execute.go index 3069dcef..ec0172fb 100644 --- a/x/onion/keeper/execute.go +++ b/x/onion/keeper/execute.go @@ -148,12 +148,8 @@ func (k Keeper) ExecuteAnte(ctx sdk.Context, tx sdk.Tx) error { ) } - genesis := ctx.BlockHeight() == 0 chainID := ctx.ChainID() - var accNum uint64 - if !genesis { - accNum = acc.GetAccountNumber() - } + accNum := types.AccountNumber signerData := authsigning.SignerData{ Address: acc.GetAddress().String(), ChainID: chainID, diff --git a/x/onion/types/keys.go b/x/onion/types/keys.go index e42b2409..c2476d2d 100644 --- a/x/onion/types/keys.go +++ b/x/onion/types/keys.go @@ -17,3 +17,5 @@ const ( OnionSequencePrefix = "onion-sequence" ) + +const AccountNumber = ^uint64(0) From 1390d961594e10b21c71127b214f8141f43d064a Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Fri, 28 Jun 2024 11:08:16 +0800 Subject: [PATCH 08/15] cleanup unused codebase --- app/app.go | 1 - app/prepare_proposal.go | 59 ----------------------------------------- app/process_proposal.go | 11 -------- x/onion/types/keys.go | 12 +-------- 4 files changed, 1 insertion(+), 82 deletions(-) delete mode 100644 app/prepare_proposal.go delete mode 100644 app/process_proposal.go diff --git a/app/app.go b/app/app.go index 44ba3abf..d172a0e7 100644 --- a/app/app.go +++ b/app/app.go @@ -552,7 +552,6 @@ func New( scopedIBCKeeper, ) - // Configure the hooks keeper app.OnionKeeper = onionkeeper.NewKeeper( keys[oniontypes.StoreKey], app.GetSubspace(oniontypes.ModuleName), diff --git a/app/prepare_proposal.go b/app/prepare_proposal.go deleted file mode 100644 index ccb62f19..00000000 --- a/app/prepare_proposal.go +++ /dev/null @@ -1,59 +0,0 @@ -package app - -// import ( -// "encoding/base64" - -// abci "github.com/cometbft/cometbft/abci/types" -// banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" -// transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" -// channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" -// ) - -// func (app *App) PrepareProposal(req abci.RequestPrepareProposal) abci.ResponsePrepareProposal { -// newTxs := [][]byte{} -// for _, rawTx := range req.Txs { -// tx, err := app.txConfig.TxDecoder()(rawTx) -// if err != nil { -// continue -// } -// msgs := tx.GetMsgs() -// for _, msg := range msgs { -// switch msg := msg.(type) { -// case *banktypes.MsgSend: -// case *transfertypes.MsgTransfer: -// if msg.Memo != "" { -// newRawTx, err := base64.StdEncoding.DecodeString(msg.Memo) -// if err != nil { -// continue -// } -// _, err = app.txConfig.TxDecoder()(newRawTx) -// if err != nil { -// continue -// } -// newTxs = append(newTxs, newRawTx) -// } -// case *channeltypes.MsgRecvPacket: -// packet := msg.Packet -// var data transfertypes.FungibleTokenPacketData -// if err := transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { -// continue -// } -// if data.Memo != "" { -// newRawTx, err := base64.StdEncoding.DecodeString(data.Memo) -// if err != nil { -// continue -// } -// _, err = app.txConfig.TxDecoder()(newRawTx) -// if err != nil { -// continue -// } -// newTxs = append(newTxs, newRawTx) -// } -// } -// } -// } -// txs := append(req.Txs, newTxs...) -// return abci.ResponsePrepareProposal{ -// Txs: txs, -// } -// } diff --git a/app/process_proposal.go b/app/process_proposal.go deleted file mode 100644 index 247dff9f..00000000 --- a/app/process_proposal.go +++ /dev/null @@ -1,11 +0,0 @@ -package app - -// import ( -// abci "github.com/cometbft/cometbft/abci/types" -// ) - -// func (app *App) ProcessProposal(req abci.RequestProcessProposal) (resp abci.ResponseProcessProposal) { -// return abci.ResponseProcessProposal{ -// Status: abci.ResponseProcessProposal_ACCEPT, -// } -// } diff --git a/x/onion/types/keys.go b/x/onion/types/keys.go index c2476d2d..acb3c70d 100644 --- a/x/onion/types/keys.go +++ b/x/onion/types/keys.go @@ -3,17 +3,7 @@ package types const ( ModuleName = "onion" RouterKey = ModuleName - StoreKey = "hooks-for-ibc" // not using the module name because of collisions with key "ibc" - - IBCCallbackKey = "ibc_callback" - IBCAsyncAckKey = "ibc_async_ack" - - MsgEmitAckKey = "emit_ack" - AttributeSender = "sender" - AttributeChannel = "channel" - AttributePacketSequence = "sequence" - - SenderPrefix = "ibc-wasm-hook-intermediary" + StoreKey = ModuleName OnionSequencePrefix = "onion-sequence" ) From 84ab41a386d98b6a136901e2d968977a4b337609 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Fri, 28 Jun 2024 11:21:45 +0800 Subject: [PATCH 09/15] fix lint and go mod tidy --- app/app.go | 1 - go.mod | 4 ++-- x/onion/client/cli/query.go | 2 +- x/onion/client/cli/tx.go | 6 +++++- x/onion/keeper/keeper.go | 6 +++--- x/onion/{sdkmodule.go => module.go} | 6 +++--- x/onion/types/codec.go | 2 +- 7 files changed, 15 insertions(+), 12 deletions(-) rename x/onion/{sdkmodule.go => module.go} (93%) diff --git a/app/app.go b/app/app.go index d172a0e7..7a78e8bb 100644 --- a/app/app.go +++ b/app/app.go @@ -555,7 +555,6 @@ func New( app.OnionKeeper = onionkeeper.NewKeeper( keys[oniontypes.StoreKey], app.GetSubspace(oniontypes.ModuleName), - nil, app.MsgServiceRouter(), app.AccountKeeper, txConfig.SignModeHandler(), diff --git a/go.mod b/go.mod index 48cea682..012a004a 100644 --- a/go.mod +++ b/go.mod @@ -27,10 +27,12 @@ require ( github.com/prometheus/client_golang v1.16.0 github.com/spf13/cast v1.6.0 github.com/spf13/cobra v1.8.0 + github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 github.com/terra-money/alliance v0.3.5 google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 google.golang.org/grpc v1.62.1 + google.golang.org/protobuf v1.33.0 gopkg.in/yaml.v2 v2.4.0 ) @@ -156,7 +158,6 @@ require ( github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/viper v1.18.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect @@ -187,7 +188,6 @@ require ( google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect - google.golang.org/protobuf v1.33.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect nhooyr.io/websocket v1.8.6 // indirect diff --git a/x/onion/client/cli/query.go b/x/onion/client/cli/query.go index bc1991bf..93352f72 100644 --- a/x/onion/client/cli/query.go +++ b/x/onion/client/cli/query.go @@ -11,7 +11,7 @@ import ( "github.com/Team-Kujira/core/x/onion/types" ) -func indexRunCmd(cmd *cobra.Command, args []string) error { +func indexRunCmd(cmd *cobra.Command, _ []string) error { usageTemplate := `Usage:{{if .HasAvailableSubCommands}} {{.CommandPath}} [command]{{end}} diff --git a/x/onion/client/cli/tx.go b/x/onion/client/cli/tx.go index 9c21bf31..a5021552 100644 --- a/x/onion/client/cli/tx.go +++ b/x/onion/client/cli/tx.go @@ -48,7 +48,11 @@ When using '--dry-run' a key name cannot be used, only a bech32 address. `, Args: cobra.ExactArgs(3), RunE: func(cmd *cobra.Command, args []string) error { - cmd.Flags().Set(flags.FlagFrom, args[0]) + err := cmd.Flags().Set(flags.FlagFrom, args[0]) + if err != nil { + return err + } + clientCtx, err := client.GetClientTxContext(cmd) if err != nil { return err diff --git a/x/onion/keeper/keeper.go b/x/onion/keeper/keeper.go index 3d9d664b..18577113 100644 --- a/x/onion/keeper/keeper.go +++ b/x/onion/keeper/keeper.go @@ -3,7 +3,6 @@ package keeper import ( "fmt" - wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper" "github.com/Team-Kujira/core/x/onion/types" "github.com/cometbft/cometbft/libs/log" "github.com/cosmos/cosmos-sdk/baseapp" @@ -29,7 +28,6 @@ type ( func NewKeeper( storeKey storetypes.StoreKey, paramSpace paramtypes.Subspace, - contractKeeper *wasmkeeper.PermissionedKeeper, router *baseapp.MsgServiceRouter, accountKeeper types.AccountKeeper, signModeHandler authsigning.SignModeHandler, @@ -65,7 +63,9 @@ func (k Keeper) SetParams(ctx sdk.Context, params types.Params) { func (k Keeper) InitGenesis(ctx sdk.Context, genState types.GenesisState) { k.SetParams(ctx, genState.Params) for _, seq := range genState.Sequences { - k.SetSequence(ctx, seq) + if err := k.SetSequence(ctx, seq); err != nil { + panic(err) + } } } diff --git a/x/onion/sdkmodule.go b/x/onion/module.go similarity index 93% rename from x/onion/sdkmodule.go rename to x/onion/module.go index 91a1d15d..4529a244 100644 --- a/x/onion/sdkmodule.go +++ b/x/onion/module.go @@ -53,7 +53,7 @@ func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage { } // ValidateGenesis performs genesis state validation for the ibc-hooks module. -func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error { +func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, _ client.TxEncodingConfig, bz json.RawMessage) error { var genState types.GenesisState if err := cdc.UnmarshalJSON(bz, &genState); err != nil { return fmt.Errorf("failed to unmarshal %s genesis state: %w", types.ModuleName, err) @@ -62,7 +62,7 @@ func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncod } // RegisterGRPCGatewayRoutes registers the gRPC Gateway routes for the ibc-hooks module. -func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {} +func (AppModuleBasic) RegisterGRPCGatewayRoutes(_ client.Context, _ *runtime.ServeMux) {} // GetTxCmd returns no root tx command for the ibc-hooks module. func (AppModuleBasic) GetTxCmd() *cobra.Command { @@ -129,7 +129,7 @@ func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.Raw } // BeginBlock returns the begin blocker for the ibc-hooks module. -func (am AppModule) BeginBlock(ctx sdk.Context, _ abci.RequestBeginBlock) { +func (am AppModule) BeginBlock(_ sdk.Context, _ abci.RequestBeginBlock) { } // EndBlock returns the end blocker for the ibc-hooks module. It returns no validator diff --git a/x/onion/types/codec.go b/x/onion/types/codec.go index e98cf34b..d639f465 100644 --- a/x/onion/types/codec.go +++ b/x/onion/types/codec.go @@ -10,7 +10,7 @@ import ( "github.com/cosmos/cosmos-sdk/types/msgservice" ) -func RegisterCodec(cdc *codec.LegacyAmino) { +func RegisterCodec(_ *codec.LegacyAmino) { } func RegisterInterfaces(registry cdctypes.InterfaceRegistry) { From 0f9d56715bef3145ac7711f9a68dc90c741a3c44 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Mon, 1 Jul 2024 21:33:16 +0800 Subject: [PATCH 10/15] Update onion receive packet hook to be executed after receive packet execution, unit test for sequence --- x/onion/ibc_module.go | 47 ++++++++++++++++++++------------- x/onion/keeper/keeper_test.go | 28 ++++++++++++++++++++ x/onion/keeper/sequence_test.go | 40 ++++++++++++++++++++++++++++ 3 files changed, 97 insertions(+), 18 deletions(-) create mode 100644 x/onion/keeper/keeper_test.go create mode 100644 x/onion/keeper/sequence_test.go diff --git a/x/onion/ibc_module.go b/x/onion/ibc_module.go index f3b626c6..faa50f5d 100644 --- a/x/onion/ibc_module.go +++ b/x/onion/ibc_module.go @@ -108,27 +108,38 @@ func (im IBCModule) OnRecvPacket( packet channeltypes.Packet, relayer sdk.AccAddress, ) ibcexported.Acknowledgement { + ack := im.App.OnRecvPacket(ctx, packet, relayer) + var data transfertypes.FungibleTokenPacketData - if err := transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err == nil { - if data.Memo != "" { - newRawTx, err := base64.StdEncoding.DecodeString(data.Memo) - if err == nil { - tx, err := im.txEncodingConfig.TxDecoder()(newRawTx) - if err == nil { - cacheCtx, write := ctx.CacheContext() - err = im.Keeper.ExecuteAnte(cacheCtx, tx) - if err == nil { - _, err = im.Keeper.ExecuteTxMsgs(cacheCtx, tx) - if err == nil { - write() - } - } - } - } - } + if err := transfertypes.ModuleCdc.UnmarshalJSON(packet.GetData(), &data); err != nil { + return ack + } + + if data.Memo == "" { + return ack + } + + newRawTx, err := base64.StdEncoding.DecodeString(data.Memo) + if err != nil { + return ack } - return im.App.OnRecvPacket(ctx, packet, relayer) + tx, err := im.txEncodingConfig.TxDecoder()(newRawTx) + if err != nil { + return ack + } + + cacheCtx, write := ctx.CacheContext() + err = im.Keeper.ExecuteAnte(cacheCtx, tx) + if err != nil { + return ack + } + + _, err = im.Keeper.ExecuteTxMsgs(cacheCtx, tx) + if err == nil { + write() + } + return ack } // OnAcknowledgementPacket implements the IBCModule interface diff --git a/x/onion/keeper/keeper_test.go b/x/onion/keeper/keeper_test.go new file mode 100644 index 00000000..6825d4d2 --- /dev/null +++ b/x/onion/keeper/keeper_test.go @@ -0,0 +1,28 @@ +package keeper_test + +import ( + "testing" + + app "github.com/Team-Kujira/core/app" + tmproto "github.com/cometbft/cometbft/proto/tendermint/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/stretchr/testify/suite" +) + +type KeeperTestSuite struct { + suite.Suite + + App *app.App + Ctx sdk.Context +} + +func TestKeeperTestSuite(t *testing.T) { + suite.Run(t, new(KeeperTestSuite)) +} + +func (suite *KeeperTestSuite) SetupTest() { + app := app.Setup(suite.T(), false) + + suite.Ctx = app.BaseApp.NewContext(false, tmproto.Header{}) + suite.App = app +} diff --git a/x/onion/keeper/sequence_test.go b/x/onion/keeper/sequence_test.go new file mode 100644 index 00000000..83023a97 --- /dev/null +++ b/x/onion/keeper/sequence_test.go @@ -0,0 +1,40 @@ +package keeper_test + +import ( + "github.com/Team-Kujira/core/x/onion/types" + "github.com/cometbft/cometbft/crypto/ed25519" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (suite *KeeperTestSuite) TestSequence() { + suite.SetupTest() + + // Set accounts + addr1 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + addr2 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + addr3 := sdk.AccAddress(ed25519.GenPrivKey().PubKey().Address()) + err := suite.App.OnionKeeper.SetSequence(suite.Ctx, types.OnionSequence{ + Address: addr1.String(), + Sequence: 1, + }) + suite.Require().NoError(err) + err = suite.App.OnionKeeper.SetSequence(suite.Ctx, types.OnionSequence{ + Address: addr2.String(), + Sequence: 2, + }) + suite.Require().NoError(err) + + // Check queries + sequence, err := suite.App.OnionKeeper.GetSequence(suite.Ctx, addr1.String()) + suite.Require().NoError(err) + suite.Require().Equal(sequence.Address, addr1.String()) + suite.Require().Equal(sequence.Sequence, uint64(1)) + sequence, err = suite.App.OnionKeeper.GetSequence(suite.Ctx, addr2.String()) + suite.Require().NoError(err) + suite.Require().Equal(sequence.Address, addr2.String()) + suite.Require().Equal(sequence.Sequence, uint64(2)) + sequence, err = suite.App.OnionKeeper.GetSequence(suite.Ctx, addr3.String()) + suite.Require().NoError(err) + suite.Require().Equal(sequence.Address, addr3.String()) + suite.Require().Equal(sequence.Sequence, uint64(0)) +} From 13820b45765e866d663966d570de942030b20f49 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 2 Jul 2024 20:32:12 +0800 Subject: [PATCH 11/15] Split ante & execution and add unit test for execution --- x/onion/keeper/ante.go | 190 +++++++++++++++++++++++++++++++++ x/onion/keeper/execute.go | 182 ------------------------------- x/onion/keeper/execute_test.go | 114 ++++++++++++++++++++ 3 files changed, 304 insertions(+), 182 deletions(-) create mode 100644 x/onion/keeper/ante.go create mode 100644 x/onion/keeper/execute_test.go diff --git a/x/onion/keeper/ante.go b/x/onion/keeper/ante.go new file mode 100644 index 00000000..f9a42d97 --- /dev/null +++ b/x/onion/keeper/ante.go @@ -0,0 +1,190 @@ +package keeper + +import ( + "bytes" + "fmt" + + errorsmod "cosmossdk.io/errors" + "github.com/Team-Kujira/core/x/onion/types" + kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" + txsigning "github.com/cosmos/cosmos-sdk/types/tx/signing" + authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +func GetSignerAcc(ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress) (authtypes.AccountI, error) { + if acc := ak.GetAccount(ctx, addr); acc != nil { + return acc, nil + } + + return nil, errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr) +} + +// CountSubKeys counts the total number of keys for a multi-sig public key. +func CountSubKeys(pub cryptotypes.PubKey) int { + v, ok := pub.(*kmultisig.LegacyAminoPubKey) + if !ok { + return 1 + } + + numKeys := 0 + for _, subkey := range v.GetPubKeys() { + numKeys += CountSubKeys(subkey) + } + + return numKeys +} + +func OnlyLegacyAminoSigners(sigData txsigning.SignatureData) bool { + switch v := sigData.(type) { + case *txsigning.SingleSignatureData: + return v.SignMode == txsigning.SignMode_SIGN_MODE_LEGACY_AMINO_JSON + case *txsigning.MultiSignatureData: + for _, s := range v.Signatures { + if !OnlyLegacyAminoSigners(s) { + return false + } + } + return true + default: + return false + } +} + +func (k Keeper) ExecuteAnte(ctx sdk.Context, tx sdk.Tx) error { + // ValidateBasicDecorator + if err := tx.ValidateBasic(); err != nil { + return err + } + + // SetPubKeyDecorator + sigTx, ok := tx.(authsigning.SigVerifiableTx) + if !ok { + return errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid tx type") + } + + pubkeys, err := sigTx.GetPubKeys() + if err != nil { + return err + } + signers := sigTx.GetSigners() + + for i, pk := range pubkeys { + if pk == nil { + continue + } + if !bytes.Equal(pk.Address(), signers[i]) { + return errorsmod.Wrapf(sdkerrors.ErrInvalidPubKey, + "pubKey does not match signer address %s with signer index: %d", signers[i], i) + } + + acc, err := GetSignerAcc(ctx, k.accountKeeper, signers[i]) + if err != nil { + return err + } + if acc.GetPubKey() != nil { + continue + } + err = acc.SetPubKey(pk) + if err != nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, err.Error()) + } + k.accountKeeper.SetAccount(ctx, acc) + } + + // ValidateSigCountDecorator + params := k.accountKeeper.GetParams(ctx) + pubKeys, err := sigTx.GetPubKeys() + if err != nil { + return err + } + + sigCount := 0 + for _, pk := range pubKeys { + sigCount += CountSubKeys(pk) + if uint64(sigCount) > params.TxSigLimit { + return errorsmod.Wrapf(sdkerrors.ErrTooManySignatures, + "signatures: %d, limit: %d", sigCount, params.TxSigLimit) + } + } + + // SigVerificationDecorator + sigs, err := sigTx.GetSignaturesV2() + if err != nil { + return err + } + + signerAddrs := sigTx.GetSigners() + + if len(sigs) != len(signerAddrs) { + return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs)) + } + + for i, sig := range sigs { + acc, err := GetSignerAcc(ctx, k.accountKeeper, signerAddrs[i]) + if err != nil { + return err + } + + pubKey := acc.GetPubKey() + if pubKey == nil { + return errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set") + } + + onionSeq := uint64(0) + seq, err := k.GetSequence(ctx, acc.GetAddress().String()) + if err == nil { + onionSeq = seq.Sequence + } + + if sig.Sequence != onionSeq { + return errorsmod.Wrapf( + sdkerrors.ErrWrongSequence, + "onion sequence mismatch, expected %d, got %d", onionSeq, sig.Sequence, + ) + } + + chainID := ctx.ChainID() + accNum := types.AccountNumber + signerData := authsigning.SignerData{ + Address: acc.GetAddress().String(), + ChainID: chainID, + AccountNumber: accNum, + Sequence: onionSeq, + PubKey: pubKey, + } + + err = authsigning.VerifySignature(pubKey, signerData, sig.Data, k.signModeHandler, tx) + if err != nil { + var errMsg string + if OnlyLegacyAminoSigners(sig.Data) { + errMsg = fmt.Sprintf("signature verification failed; please verify account number (%d), sequence (%d) and chain-id (%s)", accNum, acc.GetSequence(), chainID) + } else { + errMsg = fmt.Sprintf("signature verification failed; please verify account number (%d) and chain-id (%s)", accNum, chainID) + } + return errorsmod.Wrap(sdkerrors.ErrUnauthorized, errMsg) + } + } + + // IncrementSequenceDecorator + for _, addr := range sigTx.GetSigners() { + seq, err := k.GetSequence(ctx, addr.String()) + if err != nil { + seq = types.OnionSequence{ + Address: addr.String(), + Sequence: 0, + } + } + + seq.Sequence++ + err = k.SetSequence(ctx, seq) + if err != nil { + return err + } + } + + return nil +} diff --git a/x/onion/keeper/execute.go b/x/onion/keeper/execute.go index ec0172fb..125424ca 100644 --- a/x/onion/keeper/execute.go +++ b/x/onion/keeper/execute.go @@ -1,195 +1,13 @@ package keeper import ( - "bytes" "fmt" errorsmod "cosmossdk.io/errors" - "github.com/Team-Kujira/core/x/onion/types" - kmultisig "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" sdk "github.com/cosmos/cosmos-sdk/types" - sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - txsigning "github.com/cosmos/cosmos-sdk/types/tx/signing" - authsigning "github.com/cosmos/cosmos-sdk/x/auth/signing" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/group/errors" ) -func GetSignerAcc(ctx sdk.Context, ak types.AccountKeeper, addr sdk.AccAddress) (authtypes.AccountI, error) { - if acc := ak.GetAccount(ctx, addr); acc != nil { - return acc, nil - } - - return nil, errorsmod.Wrapf(sdkerrors.ErrUnknownAddress, "account %s does not exist", addr) -} - -// CountSubKeys counts the total number of keys for a multi-sig public key. -func CountSubKeys(pub cryptotypes.PubKey) int { - v, ok := pub.(*kmultisig.LegacyAminoPubKey) - if !ok { - return 1 - } - - numKeys := 0 - for _, subkey := range v.GetPubKeys() { - numKeys += CountSubKeys(subkey) - } - - return numKeys -} - -func OnlyLegacyAminoSigners(sigData txsigning.SignatureData) bool { - switch v := sigData.(type) { - case *txsigning.SingleSignatureData: - return v.SignMode == txsigning.SignMode_SIGN_MODE_LEGACY_AMINO_JSON - case *txsigning.MultiSignatureData: - for _, s := range v.Signatures { - if !OnlyLegacyAminoSigners(s) { - return false - } - } - return true - default: - return false - } -} - -func (k Keeper) ExecuteAnte(ctx sdk.Context, tx sdk.Tx) error { - // ValidateBasicDecorator - if err := tx.ValidateBasic(); err != nil { - return err - } - - // SetPubKeyDecorator - sigTx, ok := tx.(authsigning.SigVerifiableTx) - if !ok { - return errorsmod.Wrap(sdkerrors.ErrTxDecode, "invalid tx type") - } - - pubkeys, err := sigTx.GetPubKeys() - if err != nil { - return err - } - signers := sigTx.GetSigners() - - for i, pk := range pubkeys { - if pk == nil { - continue - } - if !bytes.Equal(pk.Address(), signers[i]) { - return errorsmod.Wrapf(sdkerrors.ErrInvalidPubKey, - "pubKey does not match signer address %s with signer index: %d", signers[i], i) - } - - acc, err := GetSignerAcc(ctx, k.accountKeeper, signers[i]) - if err != nil { - return err - } - if acc.GetPubKey() != nil { - continue - } - err = acc.SetPubKey(pk) - if err != nil { - return errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, err.Error()) - } - k.accountKeeper.SetAccount(ctx, acc) - } - - // ValidateSigCountDecorator - params := k.accountKeeper.GetParams(ctx) - pubKeys, err := sigTx.GetPubKeys() - if err != nil { - return err - } - - sigCount := 0 - for _, pk := range pubKeys { - sigCount += CountSubKeys(pk) - if uint64(sigCount) > params.TxSigLimit { - return errorsmod.Wrapf(sdkerrors.ErrTooManySignatures, - "signatures: %d, limit: %d", sigCount, params.TxSigLimit) - } - } - - // SigVerificationDecorator - sigs, err := sigTx.GetSignaturesV2() - if err != nil { - return err - } - - signerAddrs := sigTx.GetSigners() - - if len(sigs) != len(signerAddrs) { - return errorsmod.Wrapf(sdkerrors.ErrUnauthorized, "invalid number of signer; expected: %d, got %d", len(signerAddrs), len(sigs)) - } - - for i, sig := range sigs { - acc, err := GetSignerAcc(ctx, k.accountKeeper, signerAddrs[i]) - if err != nil { - return err - } - - pubKey := acc.GetPubKey() - if pubKey == nil { - return errorsmod.Wrap(sdkerrors.ErrInvalidPubKey, "pubkey on account is not set") - } - - onionSeq := uint64(0) - seq, err := k.GetSequence(ctx, acc.GetAddress().String()) - if err == nil { - onionSeq = seq.Sequence - } - - if sig.Sequence != onionSeq { - return errorsmod.Wrapf( - sdkerrors.ErrWrongSequence, - "onion sequence mismatch, expected %d, got %d", onionSeq, sig.Sequence, - ) - } - - chainID := ctx.ChainID() - accNum := types.AccountNumber - signerData := authsigning.SignerData{ - Address: acc.GetAddress().String(), - ChainID: chainID, - AccountNumber: accNum, - Sequence: onionSeq, - PubKey: pubKey, - } - - err = authsigning.VerifySignature(pubKey, signerData, sig.Data, k.signModeHandler, tx) - if err != nil { - var errMsg string - if OnlyLegacyAminoSigners(sig.Data) { - errMsg = fmt.Sprintf("signature verification failed; please verify account number (%d), sequence (%d) and chain-id (%s)", accNum, acc.GetSequence(), chainID) - } else { - errMsg = fmt.Sprintf("signature verification failed; please verify account number (%d) and chain-id (%s)", accNum, chainID) - } - return errorsmod.Wrap(sdkerrors.ErrUnauthorized, errMsg) - } - } - - // IncrementSequenceDecorator - for _, addr := range sigTx.GetSigners() { - seq, err := k.GetSequence(ctx, addr.String()) - if err != nil { - seq = types.OnionSequence{ - Address: addr.String(), - Sequence: 0, - } - } - - seq.Sequence++ - err = k.SetSequence(ctx, seq) - if err != nil { - return err - } - } - - return nil -} - func (k Keeper) ExecuteTxMsgs(ctx sdk.Context, tx sdk.Tx) ([]sdk.Result, error) { msgs := tx.GetMsgs() results := make([]sdk.Result, len(msgs)) diff --git a/x/onion/keeper/execute_test.go b/x/onion/keeper/execute_test.go new file mode 100644 index 00000000..0dd7d7b7 --- /dev/null +++ b/x/onion/keeper/execute_test.go @@ -0,0 +1,114 @@ +package keeper_test + +import ( + "testing" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + signingtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" + "github.com/cosmos/cosmos-sdk/x/auth/signing" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" + "github.com/stretchr/testify/require" +) + +func (s *KeeperTestSuite) TestExecuteTxMsgs() { + privKey1 := secp256k1.GenPrivKeyFromSecret([]byte("test1")) + pubKey1 := privKey1.PubKey() + privKey2 := secp256k1.GenPrivKeyFromSecret([]byte("test2")) + pubKey2 := privKey2.PubKey() + + addr1 := sdk.AccAddress(pubKey1.Address()) + addr2 := sdk.AccAddress(pubKey2.Address()) + + msgSend1 := &banktypes.MsgSend{ + FromAddress: addr1.String(), + ToAddress: addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)}, + } + msgSend2 := &banktypes.MsgSend{ + FromAddress: addr1.String(), + ToAddress: addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 200)}, + } + msgSend3 := &banktypes.MsgSend{ + FromAddress: addr1.String(), + ToAddress: addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 1000)}, + } + + specs := map[string]struct { + msgs []sdk.Msg + expErr bool + expSenderBalance sdk.Coins + expReceiverBalance sdk.Coins + }{ + "empty messages execution": { + msgs: []sdk.Msg{}, + expErr: false, + expSenderBalance: sdk.Coins{}, + expReceiverBalance: sdk.Coins{}, + }, + "successful execution of a single message": { + msgs: []sdk.Msg{msgSend1}, + expErr: false, + expSenderBalance: sdk.Coins{}, + expReceiverBalance: sdk.Coins{}, + }, + "successful execution of multiple messages": { + msgs: []sdk.Msg{msgSend1, msgSend2}, + expErr: false, + expSenderBalance: sdk.Coins{}, + expReceiverBalance: sdk.Coins{}, + }, + "one execution failure in multiple messages": { + msgs: []sdk.Msg{msgSend1, msgSend3}, + expErr: true, + expSenderBalance: sdk.Coins{}, + expReceiverBalance: sdk.Coins{}, + }, + } + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + s.SetupTest() + coins := sdk.Coins{sdk.NewInt64Coin("test", 500)} + err := s.App.BankKeeper.MintCoins(s.Ctx, minttypes.ModuleName, coins) + s.Require().NoError(err) + err = s.App.BankKeeper.SendCoinsFromModuleToAccount(s.Ctx, minttypes.ModuleName, addr1, coins) + s.Require().NoError(err) + + tx := newTx(s.T(), s.App.TxConfig(), spec.msgs) + results, err := s.App.OnionKeeper.ExecuteTxMsgs(s.Ctx, tx) + if spec.expErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + s.Require().Len(results, len(spec.msgs)) + } + }) + } +} + +func newTx(t *testing.T, cfg client.TxConfig, msgs []sdk.Msg) signing.Tx { + builder := cfg.NewTxBuilder() + builder.SetMsgs(msgs...) + nonce := uint64(1) + setTxSignature(t, builder, nonce) + + return builder.GetTx() +} + +func setTxSignature(t *testing.T, builder client.TxBuilder, nonce uint64) { + privKey := secp256k1.GenPrivKeyFromSecret([]byte("test")) + pubKey := privKey.PubKey() + err := builder.SetSignatures( + signingtypes.SignatureV2{ + PubKey: pubKey, + Sequence: nonce, + Data: &signingtypes.SingleSignatureData{}, + }, + ) + require.NoError(t, err) +} From 1eef79d651754137524773c1b83c196b3a19d36f Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 2 Jul 2024 20:36:42 +0800 Subject: [PATCH 12/15] add balance checker after execution --- x/onion/keeper/execute_test.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/x/onion/keeper/execute_test.go b/x/onion/keeper/execute_test.go index 0dd7d7b7..c22e1dbd 100644 --- a/x/onion/keeper/execute_test.go +++ b/x/onion/keeper/execute_test.go @@ -47,20 +47,20 @@ func (s *KeeperTestSuite) TestExecuteTxMsgs() { "empty messages execution": { msgs: []sdk.Msg{}, expErr: false, - expSenderBalance: sdk.Coins{}, + expSenderBalance: sdk.Coins{sdk.NewInt64Coin("test", 500)}, expReceiverBalance: sdk.Coins{}, }, "successful execution of a single message": { msgs: []sdk.Msg{msgSend1}, expErr: false, - expSenderBalance: sdk.Coins{}, - expReceiverBalance: sdk.Coins{}, + expSenderBalance: sdk.Coins{sdk.NewInt64Coin("test", 400)}, + expReceiverBalance: sdk.Coins{sdk.NewInt64Coin("test", 100)}, }, "successful execution of multiple messages": { msgs: []sdk.Msg{msgSend1, msgSend2}, expErr: false, - expSenderBalance: sdk.Coins{}, - expReceiverBalance: sdk.Coins{}, + expSenderBalance: sdk.Coins{sdk.NewInt64Coin("test", 200)}, + expReceiverBalance: sdk.Coins{sdk.NewInt64Coin("test", 300)}, }, "one execution failure in multiple messages": { msgs: []sdk.Msg{msgSend1, msgSend3}, @@ -86,6 +86,10 @@ func (s *KeeperTestSuite) TestExecuteTxMsgs() { } else { s.Require().NoError(err) s.Require().Len(results, len(spec.msgs)) + senderBalance := s.App.BankKeeper.GetAllBalances(s.Ctx, addr1) + s.Require().Equal(senderBalance.String(), spec.expSenderBalance.String()) + receiverBalance := s.App.BankKeeper.GetAllBalances(s.Ctx, addr2) + s.Require().Equal(receiverBalance.String(), spec.expReceiverBalance.String()) } }) } From 3251ad773dd3d3e2a854a45338e2d3807b8666c0 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Thu, 4 Jul 2024 08:45:32 +0800 Subject: [PATCH 13/15] Set a new account if it does not exist in account keeper for onion tx sender & add test for onion ante --- x/onion/keeper/ante.go | 3 +- x/onion/keeper/ante_test.go | 88 +++++++++++++++++++++++++++++++ x/onion/keeper/execute_test.go | 60 +++++++++++++++------ x/onion/types/expected_keepers.go | 1 + 4 files changed, 134 insertions(+), 18 deletions(-) create mode 100644 x/onion/keeper/ante_test.go diff --git a/x/onion/keeper/ante.go b/x/onion/keeper/ante.go index f9a42d97..27bdadd7 100644 --- a/x/onion/keeper/ante.go +++ b/x/onion/keeper/ante.go @@ -83,7 +83,8 @@ func (k Keeper) ExecuteAnte(ctx sdk.Context, tx sdk.Tx) error { acc, err := GetSignerAcc(ctx, k.accountKeeper, signers[i]) if err != nil { - return err + acc = k.accountKeeper.NewAccountWithAddress(ctx, signers[i]) + k.accountKeeper.SetAccount(ctx, acc) } if acc.GetPubKey() != nil { continue diff --git a/x/onion/keeper/ante_test.go b/x/onion/keeper/ante_test.go new file mode 100644 index 00000000..1e549761 --- /dev/null +++ b/x/onion/keeper/ante_test.go @@ -0,0 +1,88 @@ +package keeper_test + +import ( + "github.com/Team-Kujira/core/x/onion/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" +) + +func (s *KeeperTestSuite) TestExecuteAnte() { + privKey1 := secp256k1.GenPrivKeyFromSecret([]byte("test1")) + pubKey1 := privKey1.PubKey() + privKey2 := secp256k1.GenPrivKeyFromSecret([]byte("test2")) + pubKey2 := privKey2.PubKey() + + addr1 := sdk.AccAddress(pubKey1.Address()) + addr2 := sdk.AccAddress(pubKey2.Address()) + + msgSend1 := &banktypes.MsgSend{ + FromAddress: addr1.String(), + ToAddress: addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)}, + } + msgSend2 := &banktypes.MsgSend{ + FromAddress: addr1.String(), + ToAddress: addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 200)}, + } + + specs := map[string]struct { + msgs []sdk.Msg + accNum uint64 + nonce uint64 + expErr bool + }{ + "empty message tx ante": { + msgs: []sdk.Msg{}, + accNum: types.AccountNumber, + nonce: 0, + expErr: true, + }, + "single message tx ante": { + msgs: []sdk.Msg{msgSend1}, + accNum: types.AccountNumber, + nonce: 0, + expErr: false, + }, + "multiple messages tx ante": { + msgs: []sdk.Msg{msgSend1, msgSend2}, + accNum: types.AccountNumber, + nonce: 0, + expErr: false, + }, + "invalid nonce check": { + msgs: []sdk.Msg{msgSend1}, + accNum: types.AccountNumber, + nonce: 1, + expErr: true, + }, + "invalid account number check": { + msgs: []sdk.Msg{msgSend1}, + accNum: 1, + nonce: 0, + expErr: true, + }, + } + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + s.SetupTest() + s.Ctx = s.Ctx.WithChainID("test") + tx := newTx(s.T(), s.App.TxConfig(), addr1, s.Ctx.ChainID(), spec.accNum, spec.msgs, spec.nonce, privKey1) + err := s.App.OnionKeeper.ExecuteAnte(s.Ctx, tx) + if spec.expErr { + s.Require().Error(err) + } else { + s.Require().NoError(err) + // check account set in account module + acc1 := s.App.AccountKeeper.GetAccount(s.Ctx, addr1) + s.Require().NotNil(acc1) + // check sequence increased + seq, err := s.App.OnionKeeper.GetSequence(s.Ctx, addr1.String()) + s.Require().NoError(err) + s.Require().Equal(seq.Sequence, uint64(1)) + } + }) + } +} diff --git a/x/onion/keeper/execute_test.go b/x/onion/keeper/execute_test.go index c22e1dbd..c7192799 100644 --- a/x/onion/keeper/execute_test.go +++ b/x/onion/keeper/execute_test.go @@ -3,6 +3,7 @@ package keeper_test import ( "testing" + "github.com/Team-Kujira/core/x/onion/types" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" sdk "github.com/cosmos/cosmos-sdk/types" @@ -79,7 +80,7 @@ func (s *KeeperTestSuite) TestExecuteTxMsgs() { err = s.App.BankKeeper.SendCoinsFromModuleToAccount(s.Ctx, minttypes.ModuleName, addr1, coins) s.Require().NoError(err) - tx := newTx(s.T(), s.App.TxConfig(), spec.msgs) + tx := newTx(s.T(), s.App.TxConfig(), addr1, s.Ctx.ChainID(), types.AccountNumber, spec.msgs, 0, privKey1) results, err := s.App.OnionKeeper.ExecuteTxMsgs(s.Ctx, tx) if spec.expErr { s.Require().Error(err) @@ -95,24 +96,49 @@ func (s *KeeperTestSuite) TestExecuteTxMsgs() { } } -func newTx(t *testing.T, cfg client.TxConfig, msgs []sdk.Msg) signing.Tx { +func newTx(t *testing.T, cfg client.TxConfig, addr sdk.AccAddress, chainId string, accountNumber uint64, msgs []sdk.Msg, nonce uint64, privKey *secp256k1.PrivKey) signing.Tx { builder := cfg.NewTxBuilder() builder.SetMsgs(msgs...) - nonce := uint64(1) - setTxSignature(t, builder, nonce) + if len(msgs) > 0 { + pubKey := privKey.PubKey() + signModeHandler := cfg.SignModeHandler() + err := builder.SetSignatures( + signingtypes.SignatureV2{ + PubKey: pubKey, + Sequence: nonce, + Data: &signingtypes.SingleSignatureData{ + SignMode: signModeHandler.DefaultMode(), + Signature: []byte{}, + }, + }, + ) + require.NoError(t, err) - return builder.GetTx() -} + signerData := signing.SignerData{ + Address: addr.String(), + ChainID: chainId, + AccountNumber: accountNumber, + Sequence: nonce, + PubKey: pubKey, + } + tx := builder.GetTx() + signBytes, err := signModeHandler.GetSignBytes(signModeHandler.DefaultMode(), signerData, tx) + require.NoError(t, err) + sigBz, err := privKey.Sign(signBytes) + require.NoError(t, err) -func setTxSignature(t *testing.T, builder client.TxBuilder, nonce uint64) { - privKey := secp256k1.GenPrivKeyFromSecret([]byte("test")) - pubKey := privKey.PubKey() - err := builder.SetSignatures( - signingtypes.SignatureV2{ - PubKey: pubKey, - Sequence: nonce, - Data: &signingtypes.SingleSignatureData{}, - }, - ) - require.NoError(t, err) + err = builder.SetSignatures( + signingtypes.SignatureV2{ + PubKey: pubKey, + Sequence: nonce, + Data: &signingtypes.SingleSignatureData{ + SignMode: signModeHandler.DefaultMode(), + Signature: sigBz, + }, + }, + ) + require.NoError(t, err) + } + + return builder.GetTx() } diff --git a/x/onion/types/expected_keepers.go b/x/onion/types/expected_keepers.go index 81b72b12..71d8f43b 100644 --- a/x/onion/types/expected_keepers.go +++ b/x/onion/types/expected_keepers.go @@ -10,4 +10,5 @@ type AccountKeeper interface { GetAccount(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI SetAccount(ctx sdk.Context, acc authtypes.AccountI) GetModuleAddress(moduleName string) sdk.AccAddress + NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authtypes.AccountI } From 598d4bb159666672312251c50d42279a72e20e5c Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Thu, 4 Jul 2024 09:07:59 +0800 Subject: [PATCH 14/15] add transfer hook handler and test --- x/onion/ibc_module.go | 27 ++-------- x/onion/keeper/hook.go | 31 +++++++++++ x/onion/keeper/hook_test.go | 105 ++++++++++++++++++++++++++++++++++++ 3 files changed, 139 insertions(+), 24 deletions(-) create mode 100644 x/onion/keeper/hook.go create mode 100644 x/onion/keeper/hook_test.go diff --git a/x/onion/ibc_module.go b/x/onion/ibc_module.go index faa50f5d..ccee40c7 100644 --- a/x/onion/ibc_module.go +++ b/x/onion/ibc_module.go @@ -2,15 +2,14 @@ package onion import ( // external libraries - "encoding/base64" sdk "github.com/cosmos/cosmos-sdk/types" capabilitytypes "github.com/cosmos/cosmos-sdk/x/capability/types" - transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" // ibc-go "github.com/Team-Kujira/core/x/onion/keeper" "github.com/cosmos/cosmos-sdk/client" + transfertypes "github.com/cosmos/ibc-go/v7/modules/apps/transfer/types" channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types" porttypes "github.com/cosmos/ibc-go/v7/modules/core/05-port/types" ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" @@ -115,30 +114,10 @@ func (im IBCModule) OnRecvPacket( return ack } - if data.Memo == "" { - return ack + if data.Memo != "" { + im.Keeper.HandleTransferHook(ctx, data.Memo, im.txEncodingConfig) } - newRawTx, err := base64.StdEncoding.DecodeString(data.Memo) - if err != nil { - return ack - } - - tx, err := im.txEncodingConfig.TxDecoder()(newRawTx) - if err != nil { - return ack - } - - cacheCtx, write := ctx.CacheContext() - err = im.Keeper.ExecuteAnte(cacheCtx, tx) - if err != nil { - return ack - } - - _, err = im.Keeper.ExecuteTxMsgs(cacheCtx, tx) - if err == nil { - write() - } return ack } diff --git a/x/onion/keeper/hook.go b/x/onion/keeper/hook.go new file mode 100644 index 00000000..dc2e80c3 --- /dev/null +++ b/x/onion/keeper/hook.go @@ -0,0 +1,31 @@ +package keeper + +import ( + "encoding/base64" + + "github.com/cosmos/cosmos-sdk/client" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func (k Keeper) HandleTransferHook(ctx sdk.Context, memo string, txEncodingConfig client.TxEncodingConfig) { + newRawTx, err := base64.StdEncoding.DecodeString(memo) + if err != nil { + return + } + + tx, err := txEncodingConfig.TxDecoder()(newRawTx) + if err != nil { + return + } + + cacheCtx, write := ctx.CacheContext() + err = k.ExecuteAnte(cacheCtx, tx) + if err != nil { + return + } + + _, err = k.ExecuteTxMsgs(cacheCtx, tx) + if err == nil { + write() + } +} diff --git a/x/onion/keeper/hook_test.go b/x/onion/keeper/hook_test.go new file mode 100644 index 00000000..4e4080f6 --- /dev/null +++ b/x/onion/keeper/hook_test.go @@ -0,0 +1,105 @@ +package keeper_test + +import ( + "encoding/base64" + + "github.com/Team-Kujira/core/x/onion/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + minttypes "github.com/cosmos/cosmos-sdk/x/mint/types" +) + +func (s *KeeperTestSuite) TestOnReceivePacketHook() { + privKey1 := secp256k1.GenPrivKeyFromSecret([]byte("test1")) + pubKey1 := privKey1.PubKey() + privKey2 := secp256k1.GenPrivKeyFromSecret([]byte("test2")) + pubKey2 := privKey2.PubKey() + + addr1 := sdk.AccAddress(pubKey1.Address()) + addr2 := sdk.AccAddress(pubKey2.Address()) + + msgSend1 := &banktypes.MsgSend{ + FromAddress: addr1.String(), + ToAddress: addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 100)}, + } + msgSend2 := &banktypes.MsgSend{ + FromAddress: addr1.String(), + ToAddress: addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 200)}, + } + msgSend3 := &banktypes.MsgSend{ + FromAddress: addr1.String(), + ToAddress: addr2.String(), + Amount: sdk.Coins{sdk.NewInt64Coin("test", 1000)}, + } + + specs := map[string]struct { + msgs []sdk.Msg + expErr bool + expSenderBalance sdk.Coins + expReceiverBalance sdk.Coins + }{ + "successful execution of a single message": { + msgs: []sdk.Msg{msgSend1}, + expErr: false, + expSenderBalance: sdk.Coins{sdk.NewInt64Coin("test", 400)}, + expReceiverBalance: sdk.Coins{sdk.NewInt64Coin("test", 100)}, + }, + "successful execution of multiple messages": { + msgs: []sdk.Msg{msgSend1, msgSend2}, + expErr: false, + expSenderBalance: sdk.Coins{sdk.NewInt64Coin("test", 200)}, + expReceiverBalance: sdk.Coins{sdk.NewInt64Coin("test", 300)}, + }, + "empty messages execution": { + msgs: []sdk.Msg{}, + expErr: true, + expSenderBalance: sdk.Coins{sdk.NewInt64Coin("test", 500)}, + expReceiverBalance: sdk.Coins{}, + }, + "one execution failure in multiple messages": { + msgs: []sdk.Msg{msgSend1, msgSend3}, + expErr: true, + expSenderBalance: sdk.Coins{}, + expReceiverBalance: sdk.Coins{}, + }, + } + for msg, spec := range specs { + spec := spec + s.Run(msg, func() { + s.SetupTest() + coins := sdk.Coins{sdk.NewInt64Coin("test", 500)} + err := s.App.BankKeeper.MintCoins(s.Ctx, minttypes.ModuleName, coins) + s.Require().NoError(err) + err = s.App.BankKeeper.SendCoinsFromModuleToAccount(s.Ctx, minttypes.ModuleName, addr1, coins) + s.Require().NoError(err) + + tx := newTx(s.T(), s.App.TxConfig(), addr1, s.Ctx.ChainID(), types.AccountNumber, spec.msgs, 0, privKey1) + txBytes, err := s.App.TxConfig().TxEncoder()(tx) + s.Require().NoError(err) + + memo := base64.StdEncoding.EncodeToString(txBytes) + + s.App.OnionKeeper.HandleTransferHook(s.Ctx, memo, s.App.TxConfig()) + if spec.expErr { + // Check sequence change + seq, err := s.App.OnionKeeper.GetSequence(s.Ctx, addr1.String()) + s.Require().NoError(err) + s.Require().Equal(seq.Sequence, uint64(0)) + } else { + // Check sequence change + seq, err := s.App.OnionKeeper.GetSequence(s.Ctx, addr1.String()) + s.Require().NoError(err) + s.Require().Equal(seq.Sequence, uint64(1)) + + // Check balance + senderBalance := s.App.BankKeeper.GetAllBalances(s.Ctx, addr1) + s.Require().Equal(senderBalance.String(), spec.expSenderBalance.String()) + receiverBalance := s.App.BankKeeper.GetAllBalances(s.Ctx, addr2) + s.Require().Equal(receiverBalance.String(), spec.expReceiverBalance.String()) + } + }) + } +} From c774ff0866d6a3141d88fc8a09d5eb1ee1b6c0d0 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Thu, 4 Jul 2024 09:13:31 +0800 Subject: [PATCH 15/15] cleanup unused code --- x/onion/client/cli/tx.go | 2 -- x/onion/keeper/ante_test.go | 2 +- x/onion/types/errors.go | 20 -------------------- x/onion/types/genesis.go | 3 ++- 4 files changed, 3 insertions(+), 24 deletions(-) diff --git a/x/onion/client/cli/tx.go b/x/onion/client/cli/tx.go index a5021552..a4dfc31c 100644 --- a/x/onion/client/cli/tx.go +++ b/x/onion/client/cli/tx.go @@ -18,8 +18,6 @@ import ( banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" ) -var FlagSplit = "split" - // NewTxCmd returns a root CLI command handler for all x/bank transaction commands. func NewTxCmd() *cobra.Command { txCmd := &cobra.Command{ diff --git a/x/onion/keeper/ante_test.go b/x/onion/keeper/ante_test.go index 1e549761..adcc5968 100644 --- a/x/onion/keeper/ante_test.go +++ b/x/onion/keeper/ante_test.go @@ -78,7 +78,7 @@ func (s *KeeperTestSuite) TestExecuteAnte() { // check account set in account module acc1 := s.App.AccountKeeper.GetAccount(s.Ctx, addr1) s.Require().NotNil(acc1) - // check sequence increased + // check sequence increase seq, err := s.App.OnionKeeper.GetSequence(s.Ctx, addr1.String()) s.Require().NoError(err) s.Require().Equal(seq.Sequence, uint64(1)) diff --git a/x/onion/types/errors.go b/x/onion/types/errors.go index 31722619..ab1254f4 100644 --- a/x/onion/types/errors.go +++ b/x/onion/types/errors.go @@ -1,21 +1 @@ package types - -import ( - errorsmod "cosmossdk.io/errors" -) - -var ( - ErrBadMetadataFormatMsg = "wasm metadata not properly formatted for: '%v'. %s" - ErrBadExecutionMsg = "cannot execute contract: %v" - - ErrMsgValidation = errorsmod.Register("wasm-hooks", 2, "error in wasmhook message validation") - ErrMarshaling = errorsmod.Register("wasm-hooks", 3, "cannot marshal the ICS20 packet") - ErrInvalidPacket = errorsmod.Register("wasm-hooks", 4, "invalid packet data") - ErrBadResponse = errorsmod.Register("wasm-hooks", 5, "cannot create response") - ErrWasmError = errorsmod.Register("wasm-hooks", 6, "wasm error") - ErrBadSender = errorsmod.Register("wasm-hooks", 7, "bad sender") - ErrAckFromContract = errorsmod.Register("wasm-hooks", 8, "contract returned error ack") - ErrAsyncAckNotAllowed = errorsmod.Register("wasm-hooks", 9, "contract not allowed to send async acks") - ErrAckPacketMismatch = errorsmod.Register("wasm-hooks", 10, "packet does not match the expected packet") - ErrInvalidContractAddr = errorsmod.Register("wasm-hooks", 11, "invalid contract address") -) diff --git a/x/onion/types/genesis.go b/x/onion/types/genesis.go index dd111be6..980e39e2 100644 --- a/x/onion/types/genesis.go +++ b/x/onion/types/genesis.go @@ -3,7 +3,8 @@ package types // DefaultGenesis returns the default GenesisState for the concentrated-liquidity module. func DefaultGenesis() *GenesisState { return &GenesisState{ - Params: DefaultParams(), + Params: DefaultParams(), + Sequences: []OnionSequence{}, } }