diff --git a/e2e/go.mod b/e2e/go.mod index 24bcea1d362..34876ccae4d 100644 --- a/e2e/go.mod +++ b/e2e/go.mod @@ -67,7 +67,6 @@ require ( github.com/avast/retry-go/v4 v4.5.1 // indirect github.com/aws/aws-sdk-go v1.55.5 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bgentry/speakeasy v0.2.0 // indirect github.com/bits-and-blooms/bitset v1.12.0 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect @@ -255,6 +254,7 @@ require ( cosmossdk.io/x/nft v0.0.0-00010101000000-000000000000 // indirect github.com/FactomProject/basen v0.0.0-20150613233007-fe3947df716e // indirect github.com/FactomProject/btcutilecc v0.0.0-20130527213604-d3a63a5752ec // indirect + github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect github.com/bytedance/sonic v1.12.4 // indirect github.com/bytedance/sonic/loader v0.2.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect diff --git a/modules/apps/27-interchain-accounts/host/ibc_module.go b/modules/apps/27-interchain-accounts/host/ibc_module.go index e23b0514e59..77c7060ae34 100644 --- a/modules/apps/27-interchain-accounts/host/ibc_module.go +++ b/modules/apps/27-interchain-accounts/host/ibc_module.go @@ -116,8 +116,11 @@ func (im IBCModule) OnRecvPacket( _ sdk.AccAddress, ) ibcexported.Acknowledgement { if !im.keeper.GetParams(ctx).HostEnabled { - im.keeper.Logger(ctx).Info("host submodule is disabled") - keeper.EmitHostDisabledEvent(ctx, packet) + im.keeper.Logger.Info("host submodule is disabled") + if err := im.keeper.EmitHostDisabledEvent(ctx, packet); err != nil { + return channeltypes.NewErrorAcknowledgement(err) + } + return channeltypes.NewErrorAcknowledgement(types.ErrHostSubModuleDisabled) } @@ -125,13 +128,15 @@ func (im IBCModule) OnRecvPacket( ack := channeltypes.NewResultAcknowledgement(txResponse) if err != nil { ack = channeltypes.NewErrorAcknowledgement(err) - im.keeper.Logger(ctx).Error(fmt.Sprintf("%s sequence %d", err.Error(), packet.Sequence)) + im.keeper.Logger.Error(fmt.Sprintf("%s sequence %d", err.Error(), packet.Sequence)) } else { - im.keeper.Logger(ctx).Info("successfully handled packet", "sequence", packet.Sequence) + im.keeper.Logger.Info("successfully handled packet", "sequence", packet.Sequence) } // Emit an event indicating a successful or failed acknowledgement. - keeper.EmitAcknowledgementEvent(ctx, packet, ack, err) + if err := im.keeper.EmitAcknowledgementEvent(ctx, packet, ack, err); err != nil { + return channeltypes.NewErrorAcknowledgement(err) + } // NOTE: acknowledgement will be written synchronously during IBC handler execution. return ack diff --git a/modules/apps/27-interchain-accounts/host/keeper/events.go b/modules/apps/27-interchain-accounts/host/keeper/events.go index fb497ec2ca3..f4d6e8e1429 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/events.go +++ b/modules/apps/27-interchain-accounts/host/keeper/events.go @@ -4,6 +4,8 @@ import ( "context" "strconv" + "cosmossdk.io/core/event" + sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/ibc-go/v9/modules/apps/27-interchain-accounts/host/types" @@ -14,35 +16,30 @@ import ( // EmitAcknowledgementEvent emits an event signalling a successful or failed acknowledgement and including the error // details if any. -func EmitAcknowledgementEvent(ctx context.Context, packet channeltypes.Packet, ack exported.Acknowledgement, err error) { - attributes := []sdk.Attribute{ - sdk.NewAttribute(sdk.AttributeKeyModule, icatypes.ModuleName), - sdk.NewAttribute(icatypes.AttributeKeyHostChannelID, packet.GetDestChannel()), - sdk.NewAttribute(icatypes.AttributeKeyAckSuccess, strconv.FormatBool(ack.Success())), +func (k *Keeper) EmitAcknowledgementEvent(ctx context.Context, packet channeltypes.Packet, ack exported.Acknowledgement, err error) error { + attributes := []event.Attribute{ + event.NewAttribute(sdk.AttributeKeyModule, icatypes.ModuleName), + event.NewAttribute(icatypes.AttributeKeyHostChannelID, packet.GetDestChannel()), + event.NewAttribute(icatypes.AttributeKeyAckSuccess, strconv.FormatBool(ack.Success())), } if err != nil { - attributes = append(attributes, sdk.NewAttribute(icatypes.AttributeKeyAckError, err.Error())) + attributes = append(attributes, event.NewAttribute(icatypes.AttributeKeyAckError, err.Error())) } - sdkCtx := sdk.UnwrapSDKContext(ctx) // TODO: https://github.com/cosmos/ibc-go/issues/5917 - sdkCtx.EventManager().EmitEvent( - sdk.NewEvent( - icatypes.EventTypePacket, - attributes..., - ), + + return k.EventService.EventManager(ctx).EmitKV( + icatypes.EventTypePacket, + attributes..., ) } // EmitHostDisabledEvent emits an event signalling that the host submodule is disabled. -func EmitHostDisabledEvent(ctx context.Context, packet channeltypes.Packet) { - sdkCtx := sdk.UnwrapSDKContext(ctx) // TODO: https://github.com/cosmos/ibc-go/issues/5917 - sdkCtx.EventManager().EmitEvent( - sdk.NewEvent( - icatypes.EventTypePacket, - sdk.NewAttribute(sdk.AttributeKeyModule, icatypes.ModuleName), - sdk.NewAttribute(icatypes.AttributeKeyHostChannelID, packet.GetDestChannel()), - sdk.NewAttribute(icatypes.AttributeKeyAckError, types.ErrHostSubModuleDisabled.Error()), - sdk.NewAttribute(icatypes.AttributeKeyAckSuccess, "false"), - ), +func (k *Keeper) EmitHostDisabledEvent(ctx context.Context, packet channeltypes.Packet) error { + return k.EventService.EventManager(ctx).EmitKV( + icatypes.EventTypePacket, + event.NewAttribute(sdk.AttributeKeyModule, icatypes.ModuleName), + event.NewAttribute(icatypes.AttributeKeyHostChannelID, packet.GetDestChannel()), + event.NewAttribute(icatypes.AttributeKeyAckError, types.ErrHostSubModuleDisabled.Error()), + event.NewAttribute(icatypes.AttributeKeyAckSuccess, "false"), ) } diff --git a/modules/apps/27-interchain-accounts/host/keeper/handshake.go b/modules/apps/27-interchain-accounts/host/keeper/handshake.go index e35159f8217..ee4fbba0509 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/handshake.go +++ b/modules/apps/27-interchain-accounts/host/keeper/handshake.go @@ -40,7 +40,7 @@ func (k Keeper) OnChanOpenTry( return "", errorsmod.Wrapf(err, "failed to retrieve connection %s", connectionHops[0]) } - k.Logger(ctx).Debug("counterparty version is invalid, proposing default metadata") + k.Logger.Debug("counterparty version is invalid, proposing default metadata") metadata = icatypes.NewDefaultMetadata(connection.Counterparty.ConnectionId, connectionHops[0]) } @@ -72,7 +72,7 @@ func (k Keeper) OnChanOpenTry( interchainAccAddr, found := k.GetInterchainAccountAddress(ctx, metadata.HostConnectionId, counterparty.PortId) if found { // reopening an interchain account - k.Logger(ctx).Info("reopening existing interchain account", "address", interchainAccAddr) + k.Logger.Info("reopening existing interchain account", "address", interchainAccAddr) accAddress = sdk.MustAccAddressFromBech32(interchainAccAddr) if _, ok := k.authKeeper.GetAccount(ctx, accAddress).(*icatypes.InterchainAccount); !ok { return "", errorsmod.Wrapf(icatypes.ErrInvalidAccountReopening, "existing account address %s, does not have interchain account type", accAddress) @@ -83,7 +83,7 @@ func (k Keeper) OnChanOpenTry( if err != nil { return "", err } - k.Logger(ctx).Info("successfully created new interchain account", "host-connection-id", metadata.HostConnectionId, "port-id", counterparty.PortId, "address", accAddress) + k.Logger.Info("successfully created new interchain account", "host-connection-id", metadata.HostConnectionId, "port-id", counterparty.PortId, "address", accAddress) } metadata.Address = accAddress.String() diff --git a/modules/apps/27-interchain-accounts/host/keeper/keeper.go b/modules/apps/27-interchain-accounts/host/keeper/keeper.go index 2b3eefef249..bc137083883 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/keeper.go +++ b/modules/apps/27-interchain-accounts/host/keeper/keeper.go @@ -12,14 +12,12 @@ import ( msgv1 "cosmossdk.io/api/cosmos/msg/v1" queryv1 "cosmossdk.io/api/cosmos/query/v1" - corestore "cosmossdk.io/core/store" + "cosmossdk.io/core/appmodule" errorsmod "cosmossdk.io/errors" - "cosmossdk.io/log" storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/runtime" - sdk "github.com/cosmos/cosmos-sdk/types" genesistypes "github.com/cosmos/ibc-go/v9/modules/apps/27-interchain-accounts/genesis/types" "github.com/cosmos/ibc-go/v9/modules/apps/27-interchain-accounts/host/types" @@ -27,13 +25,13 @@ import ( channeltypes "github.com/cosmos/ibc-go/v9/modules/core/04-channel/types" porttypes "github.com/cosmos/ibc-go/v9/modules/core/05-port/types" ibcerrors "github.com/cosmos/ibc-go/v9/modules/core/errors" - "github.com/cosmos/ibc-go/v9/modules/core/exported" coretypes "github.com/cosmos/ibc-go/v9/modules/core/types" ) // Keeper defines the IBC interchain accounts host keeper type Keeper struct { - storeService corestore.KVStoreService + appmodule.Environment + cdc codec.Codec legacySubspace icatypes.ParamSubspace @@ -41,9 +39,6 @@ type Keeper struct { channelKeeper icatypes.ChannelKeeper authKeeper icatypes.AuthKeeper - msgRouter icatypes.MessageRouter - queryRouter icatypes.QueryRouter - // mqsAllowList is a list of all module safe query paths mqsAllowList []string @@ -54,9 +49,9 @@ type Keeper struct { // NewKeeper creates a new interchain accounts host Keeper instance func NewKeeper( - cdc codec.Codec, storeService corestore.KVStoreService, legacySubspace icatypes.ParamSubspace, + cdc codec.Codec, env appmodule.Environment, legacySubspace icatypes.ParamSubspace, ics4Wrapper porttypes.ICS4Wrapper, channelKeeper icatypes.ChannelKeeper, - authKeeper icatypes.AuthKeeper, msgRouter icatypes.MessageRouter, queryRouter icatypes.QueryRouter, authority string, + authKeeper icatypes.AuthKeeper, authority string, ) Keeper { // ensure ibc interchain accounts module account is set if addr := authKeeper.GetModuleAddress(icatypes.ModuleName); addr == nil { @@ -68,14 +63,12 @@ func NewKeeper( } return Keeper{ - storeService: storeService, + Environment: env, cdc: cdc, legacySubspace: legacySubspace, ics4Wrapper: ics4Wrapper, channelKeeper: channelKeeper, authKeeper: authKeeper, - msgRouter: msgRouter, - queryRouter: queryRouter, mqsAllowList: newModuleQuerySafeAllowList(), authority: authority, } @@ -93,12 +86,6 @@ func (k Keeper) GetICS4Wrapper() porttypes.ICS4Wrapper { return k.ics4Wrapper } -// Logger returns the application logger, scoped to the associated module -func (Keeper) Logger(ctx context.Context) log.Logger { - sdkCtx := sdk.UnwrapSDKContext(ctx) // TODO: remove after context.Context is removed from core IBC - return sdkCtx.Logger().With("module", fmt.Sprintf("x/%s-%s", exported.ModuleName, icatypes.ModuleName)) -} - // getConnectionID returns the connection id for the given port and channelIDs. func (k Keeper) getConnectionID(ctx context.Context, portID, channelID string) (string, error) { channel, found := k.channelKeeper.GetChannel(ctx, portID, channelID) @@ -110,7 +97,7 @@ func (k Keeper) getConnectionID(ctx context.Context, portID, channelID string) ( // setPort sets the provided portID in state. func (k Keeper) setPort(ctx context.Context, portID string) { - store := k.storeService.OpenKVStore(ctx) + store := k.KVStoreService.OpenKVStore(ctx) if err := store.Set(icatypes.KeyPort(portID), []byte{0x01}); err != nil { panic(err) } @@ -133,7 +120,7 @@ func (k Keeper) getAppMetadata(ctx context.Context, portID, channelID string) (i // GetActiveChannelID retrieves the active channelID from the store keyed by the provided connectionID and portID func (k Keeper) GetActiveChannelID(ctx context.Context, connectionID, portID string) (string, bool) { - store := k.storeService.OpenKVStore(ctx) + store := k.KVStoreService.OpenKVStore(ctx) key := icatypes.KeyActiveChannel(portID, connectionID) bz, err := store.Get(key) @@ -165,9 +152,9 @@ func (k Keeper) GetOpenActiveChannel(ctx context.Context, connectionID, portID s // GetAllActiveChannels returns a list of all active interchain accounts host channels and their associated connection and port identifiers func (k Keeper) GetAllActiveChannels(ctx context.Context) []genesistypes.ActiveChannel { - store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := runtime.KVStoreAdapter(k.KVStoreService.OpenKVStore(ctx)) iterator := storetypes.KVStorePrefixIterator(store, []byte(icatypes.ActiveChannelKeyPrefix)) - defer coretypes.LogDeferred(k.Logger(ctx), func() error { return iterator.Close() }) + defer coretypes.LogDeferred(k.Logger, func() error { return iterator.Close() }) var activeChannels []genesistypes.ActiveChannel for ; iterator.Valid(); iterator.Next() { @@ -187,7 +174,7 @@ func (k Keeper) GetAllActiveChannels(ctx context.Context) []genesistypes.ActiveC // SetActiveChannelID stores the active channelID, keyed by the provided connectionID and portID func (k Keeper) SetActiveChannelID(ctx context.Context, connectionID, portID, channelID string) { - store := k.storeService.OpenKVStore(ctx) + store := k.KVStoreService.OpenKVStore(ctx) if err := store.Set(icatypes.KeyActiveChannel(portID, connectionID), []byte(channelID)); err != nil { panic(err) } @@ -201,7 +188,7 @@ func (k Keeper) IsActiveChannel(ctx context.Context, connectionID, portID string // GetInterchainAccountAddress retrieves the InterchainAccount address from the store associated with the provided connectionID and portID func (k Keeper) GetInterchainAccountAddress(ctx context.Context, connectionID, portID string) (string, bool) { - store := k.storeService.OpenKVStore(ctx) + store := k.KVStoreService.OpenKVStore(ctx) key := icatypes.KeyOwnerAccount(portID, connectionID) bz, err := store.Get(key) @@ -217,7 +204,7 @@ func (k Keeper) GetInterchainAccountAddress(ctx context.Context, connectionID, p // GetAllInterchainAccounts returns a list of all registered interchain account addresses and their associated connection and controller port identifiers func (k Keeper) GetAllInterchainAccounts(ctx context.Context) []genesistypes.RegisteredInterchainAccount { - store := runtime.KVStoreAdapter(k.storeService.OpenKVStore(ctx)) + store := runtime.KVStoreAdapter(k.KVStoreService.OpenKVStore(ctx)) iterator := storetypes.KVStorePrefixIterator(store, []byte(icatypes.OwnerKeyPrefix)) var interchainAccounts []genesistypes.RegisteredInterchainAccount @@ -238,7 +225,7 @@ func (k Keeper) GetAllInterchainAccounts(ctx context.Context) []genesistypes.Reg // SetInterchainAccountAddress stores the InterchainAccount address, keyed by the associated connectionID and portID func (k Keeper) SetInterchainAccountAddress(ctx context.Context, connectionID, portID, address string) { - store := k.storeService.OpenKVStore(ctx) + store := k.KVStoreService.OpenKVStore(ctx) if err := store.Set(icatypes.KeyOwnerAccount(portID, connectionID), []byte(address)); err != nil { panic(err) } @@ -251,7 +238,7 @@ func (k Keeper) GetAuthority() string { // GetParams returns the total set of the host submodule parameters. func (k Keeper) GetParams(ctx context.Context) types.Params { - store := k.storeService.OpenKVStore(ctx) + store := k.KVStoreService.OpenKVStore(ctx) bz, err := store.Get([]byte(types.ParamsKey)) if err != nil { panic(err) @@ -267,7 +254,7 @@ func (k Keeper) GetParams(ctx context.Context) types.Params { // SetParams sets the total set of the host submodule parameters. func (k Keeper) SetParams(ctx context.Context, params types.Params) { - store := k.storeService.OpenKVStore(ctx) + store := k.KVStoreService.OpenKVStore(ctx) bz := k.cdc.MustMarshal(¶ms) if err := store.Set([]byte(types.ParamsKey), bz); err != nil { panic(err) diff --git a/modules/apps/27-interchain-accounts/host/keeper/keeper_test.go b/modules/apps/27-interchain-accounts/host/keeper/keeper_test.go index bf595d96869..42cd66c2a15 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/keeper_test.go +++ b/modules/apps/27-interchain-accounts/host/keeper/keeper_test.go @@ -6,6 +6,8 @@ import ( testifysuite "github.com/stretchr/testify/suite" + "cosmossdk.io/log" + "github.com/cosmos/cosmos-sdk/runtime" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" @@ -142,39 +144,33 @@ func (suite *KeeperTestSuite) TestNewKeeper() { {"success", func() { keeper.NewKeeper( suite.chainA.GetSimApp().AppCodec(), - runtime.NewKVStoreService(suite.chainA.GetSimApp().GetKey(types.StoreKey)), + runtime.NewEnvironment(runtime.NewKVStoreService(suite.chainA.GetSimApp().GetKey(types.StoreKey)), log.NewNopLogger()), suite.chainA.GetSimApp().GetSubspace(types.SubModuleName), suite.chainA.GetSimApp().IBCKeeper.ChannelKeeper, suite.chainA.GetSimApp().IBCKeeper.ChannelKeeper, suite.chainA.GetSimApp().AuthKeeper, - suite.chainA.GetSimApp().MsgServiceRouter(), - suite.chainA.GetSimApp().GRPCQueryRouter(), suite.chainA.GetSimApp().ICAHostKeeper.GetAuthority(), ) }, ""}, {"failure: interchain accounts module account does not exist", func() { keeper.NewKeeper( suite.chainA.GetSimApp().AppCodec(), - runtime.NewKVStoreService(suite.chainA.GetSimApp().GetKey(types.StoreKey)), + runtime.NewEnvironment(runtime.NewKVStoreService(suite.chainA.GetSimApp().GetKey(types.StoreKey)), log.NewNopLogger()), suite.chainA.GetSimApp().GetSubspace(types.SubModuleName), suite.chainA.GetSimApp().IBCKeeper.ChannelKeeper, suite.chainA.GetSimApp().IBCKeeper.ChannelKeeper, authkeeper.AccountKeeper{}, // empty account keeper - suite.chainA.GetSimApp().MsgServiceRouter(), - suite.chainA.GetSimApp().GRPCQueryRouter(), suite.chainA.GetSimApp().ICAHostKeeper.GetAuthority(), ) }, "the Interchain Accounts module account has not been set"}, {"failure: empty mock staking keeper", func() { keeper.NewKeeper( suite.chainA.GetSimApp().AppCodec(), - runtime.NewKVStoreService(suite.chainA.GetSimApp().GetKey(types.StoreKey)), + runtime.NewEnvironment(runtime.NewKVStoreService(suite.chainA.GetSimApp().GetKey(types.StoreKey)), log.NewNopLogger()), suite.chainA.GetSimApp().GetSubspace(types.SubModuleName), suite.chainA.GetSimApp().IBCKeeper.ChannelKeeper, suite.chainA.GetSimApp().IBCKeeper.ChannelKeeper, suite.chainA.GetSimApp().AuthKeeper, - suite.chainA.GetSimApp().MsgServiceRouter(), - suite.chainA.GetSimApp().GRPCQueryRouter(), "", // authority ) }, "authority must be non-empty"}, diff --git a/modules/apps/27-interchain-accounts/host/keeper/migrations.go b/modules/apps/27-interchain-accounts/host/keeper/migrations.go index 3bdd997cd19..b229d23c116 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/migrations.go +++ b/modules/apps/27-interchain-accounts/host/keeper/migrations.go @@ -32,7 +32,7 @@ func (m Migrator) MigrateParams(ctx context.Context) error { return err } m.keeper.SetParams(ctx, params) - m.keeper.Logger(ctx).Info("successfully migrated ica/host submodule to self-manage params") + m.keeper.Logger.Info("successfully migrated ica/host submodule to self-manage params") } return nil } diff --git a/modules/apps/27-interchain-accounts/host/keeper/migrations_test.go b/modules/apps/27-interchain-accounts/host/keeper/migrations_test.go index 0d5746d45d6..9b0e44fbbe7 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/migrations_test.go +++ b/modules/apps/27-interchain-accounts/host/keeper/migrations_test.go @@ -3,6 +3,7 @@ package keeper_test import ( "fmt" + "cosmossdk.io/log" govtypes "cosmossdk.io/x/gov/types" "github.com/cosmos/cosmos-sdk/runtime" @@ -32,13 +33,11 @@ func (suite *KeeperTestSuite) TestMigratorMigrateParams() { func() { suite.chainA.GetSimApp().ICAHostKeeper = icahostkeeper.NewKeeper( suite.chainA.Codec, - runtime.NewKVStoreService(suite.chainA.GetSimApp().GetKey(icahosttypes.StoreKey)), + runtime.NewEnvironment(runtime.NewKVStoreService(suite.chainA.GetSimApp().GetKey(icahosttypes.StoreKey)), log.NewNopLogger()), nil, // assign a nil legacy param subspace suite.chainA.GetSimApp().IBCFeeKeeper, suite.chainA.GetSimApp().IBCKeeper.ChannelKeeper, suite.chainA.GetSimApp().AuthKeeper, - suite.chainA.GetSimApp().MsgServiceRouter(), - suite.chainA.GetSimApp().GRPCQueryRouter(), authtypes.NewModuleAddress(govtypes.ModuleName).String(), ) }, diff --git a/modules/apps/27-interchain-accounts/host/keeper/msg_server.go b/modules/apps/27-interchain-accounts/host/keeper/msg_server.go index afa952f6a02..7e9806a9626 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/msg_server.go +++ b/modules/apps/27-interchain-accounts/host/keeper/msg_server.go @@ -2,13 +2,15 @@ package keeper import ( "context" + "fmt" + "reflect" "slices" + "strings" - errorsmod "cosmossdk.io/errors" - - sdk "github.com/cosmos/cosmos-sdk/types" + gogoproto "github.com/cosmos/gogoproto/proto" + "google.golang.org/protobuf/reflect/protoreflect" - abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" + errorsmod "cosmossdk.io/errors" "github.com/cosmos/ibc-go/v9/modules/apps/27-interchain-accounts/host/types" ibcerrors "github.com/cosmos/ibc-go/v9/modules/core/errors" @@ -28,9 +30,7 @@ func NewMsgServerImpl(keeper *Keeper) types.MsgServer { // ModuleQuerySafe routes the queries to the keeper's query router if they are module_query_safe. // This handler doesn't use the signer. -func (m msgServer) ModuleQuerySafe(goCtx context.Context, msg *types.MsgModuleQuerySafe) (*types.MsgModuleQuerySafeResponse, error) { - ctx := sdk.UnwrapSDKContext(goCtx) - +func (m msgServer) ModuleQuerySafe(ctx context.Context, msg *types.MsgModuleQuerySafe) (*types.MsgModuleQuerySafeResponse, error) { responses := make([][]byte, len(msg.Requests)) for i, query := range msg.Requests { isModuleQuerySafe := slices.Contains(m.mqsAllowList, query.Path) @@ -38,27 +38,57 @@ func (m msgServer) ModuleQuerySafe(goCtx context.Context, msg *types.MsgModuleQu return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "not module query safe: %s", query.Path) } - route := m.queryRouter.Route(query.Path) - if route == nil { - return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "no route to query: %s", query.Path) + path := strings.TrimPrefix(query.Path, "/") + pathFullName := protoreflect.FullName(strings.ReplaceAll(path, "/", ".")) + + desc, err := gogoproto.GogoResolver.FindDescriptorByName(pathFullName) + if err != nil { + return nil, err + } + + md, isGRPC := desc.(protoreflect.MethodDescriptor) + if !isGRPC { + return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "no descriptor found for query path: %s", string(desc.FullName())) } - res, err := route(ctx, &abci.QueryRequest{ - Path: query.Path, - Data: query.Data, - }) + msg, err := forgeProtoTypeFromName(string(md.Input().FullName())) if err != nil { - m.Logger(ctx).Debug("query failed", "path", query.Path, "error", err) return nil, err } - if res == nil || res.Value == nil { + + if err := m.cdc.Unmarshal(query.Data, msg); err != nil { + return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidType, "cannot unmarshal query request data to: %s", md.Input().FullName()) + } + + res, err := m.QueryRouterService.Invoke(ctx, msg) + if err != nil { + m.Logger.Debug("query failed", "path", query.Path, "error", err) + return nil, err + } + if res == nil { return nil, errorsmod.Wrapf(ibcerrors.ErrInvalidRequest, "no response for query: %s", query.Path) } - responses[i] = res.Value + responses[i] = m.cdc.MustMarshal(res) + } + + height := m.HeaderService.HeaderInfo(ctx).Height + return &types.MsgModuleQuerySafeResponse{Responses: responses, Height: uint64(height)}, nil +} + +// see: https://github.com/cosmos/cosmos-sdk/issues/22833 +func forgeProtoTypeFromName(msgName string) (gogoproto.Message, error) { + typ := gogoproto.MessageType(msgName) + if typ == nil { + return nil, fmt.Errorf("no message type found for %s", msgName) + } + + msg, ok := reflect.New(typ.Elem()).Interface().(gogoproto.Message) + if !ok { + return nil, fmt.Errorf("could not create response message %s", msgName) } - return &types.MsgModuleQuerySafeResponse{Responses: responses, Height: uint64(ctx.BlockHeight())}, nil + return msg, nil } // UpdateParams updates the host submodule's params. diff --git a/modules/apps/27-interchain-accounts/host/keeper/relay.go b/modules/apps/27-interchain-accounts/host/keeper/relay.go index 42e685738c8..46932c9af24 100644 --- a/modules/apps/27-interchain-accounts/host/keeper/relay.go +++ b/modules/apps/27-interchain-accounts/host/keeper/relay.go @@ -66,10 +66,6 @@ func (k Keeper) executeTx(ctx context.Context, sourcePort, destPort, destChannel MsgResponses: make([]*codectypes.Any, len(msgs)), } - // CacheContext returns a new context with the multi-store branched into a cached storage object - // writeCache is called only if all msgs succeed, performing state transitions atomically - sdkCtx := sdk.UnwrapSDKContext(ctx) // TODO: https://github.com/cosmos/ibc-go/issues/5917 - cacheCtx, writeCache := sdkCtx.CacheContext() for i, msg := range msgs { if m, ok := msg.(sdk.HasValidateBasic); ok { if err := m.ValidateBasic(); err != nil { @@ -77,16 +73,19 @@ func (k Keeper) executeTx(ctx context.Context, sourcePort, destPort, destChannel } } - protoAny, err := k.executeMsg(cacheCtx, msg) - if err != nil { + if err := k.BranchService.Execute(ctx, func(ctx context.Context) error { + protoAny, err := k.executeMsg(ctx, msg) + if err != nil { + return err + } + + txMsgData.MsgResponses[i] = protoAny + return nil + }); err != nil { return nil, err } - - txMsgData.MsgResponses[i] = protoAny } - writeCache() - txResponse, err := proto.Marshal(txMsgData) if err != nil { return nil, errorsmod.Wrap(err, "failed to marshal tx data") @@ -110,7 +109,7 @@ func (k Keeper) authenticateTx(ctx context.Context, msgs []sdk.Msg, connectionID } // obtain the message signers using the proto signer annotations - // the msgv2 return value is discarded as it is not used + // the protoreflect msg return value is discarded as it is not used signers, _, err := k.cdc.GetMsgSigners(msg) if err != nil { return errorsmod.Wrapf(err, "failed to obtain message signers for message type %s", sdk.MsgTypeURL(msg)) @@ -131,24 +130,19 @@ func (k Keeper) authenticateTx(ctx context.Context, msgs []sdk.Msg, connectionID // Attempts to get the message handler from the router and if found will then execute the message. // If the message execution is successful, the proto marshaled message response will be returned. -func (k Keeper) executeMsg(ctx sdk.Context, msg sdk.Msg) (*codectypes.Any, error) { // TODO: https://github.com/cosmos/ibc-go/issues/7223 - handler := k.msgRouter.Handler(msg) - if handler == nil { - return nil, icatypes.ErrInvalidRoute +func (k Keeper) executeMsg(ctx context.Context, msg sdk.Msg) (*codectypes.Any, error) { + if err := k.MsgRouterService.CanInvoke(ctx, sdk.MsgTypeURL(msg)); err != nil { + return nil, errorsmod.Wrap(err, icatypes.ErrInvalidRoute.Error()) } - res, err := handler(ctx, msg) + res, err := k.MsgRouterService.Invoke(ctx, msg) if err != nil { return nil, err } - // NOTE: The sdk msg handler creates a new EventManager, so events must be correctly propagated back to the current context - ctx.EventManager().EmitEvents(res.GetEvents()) - - // Each individual sdk.Result has exactly one Msg response. We aggregate here. - msgResponse := res.MsgResponses[0] - if msgResponse == nil { - return nil, errorsmod.Wrapf(ibcerrors.ErrLogic, "got nil Msg response for msg %s", sdk.MsgTypeURL(msg)) + msgResponse, err := codectypes.NewAnyWithValue(res) + if err != nil { + return nil, errorsmod.Wrapf(ibcerrors.ErrPackAny, "failed to pack msg response as Any: %T", res) } return msgResponse, nil diff --git a/modules/apps/27-interchain-accounts/types/router.go b/modules/apps/27-interchain-accounts/types/router.go deleted file mode 100644 index 6c1dcee6d39..00000000000 --- a/modules/apps/27-interchain-accounts/types/router.go +++ /dev/null @@ -1,20 +0,0 @@ -package types - -import ( - "github.com/cosmos/cosmos-sdk/baseapp" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// MessageRouter ADR 031 request type routing -// https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-031-msg-service.md -type MessageRouter interface { - Handler(msg sdk.Msg) baseapp.MsgServiceHandler -} - -// QueryRouter ADR 021 query type routing -// https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-021-protobuf-query-encoding.md -type QueryRouter interface { - // Route returns the GRPCQueryHandler for a given query route path or nil - // if not found - Route(path string) baseapp.GRPCQueryHandler -} diff --git a/modules/apps/callbacks/testing/simapp/app.go b/modules/apps/callbacks/testing/simapp/app.go index df5818a7b53..fb16cc6a2d3 100644 --- a/modules/apps/callbacks/testing/simapp/app.go +++ b/modules/apps/callbacks/testing/simapp/app.go @@ -444,11 +444,13 @@ func NewSimApp( // ICA Host keeper app.ICAHostKeeper = icahostkeeper.NewKeeper( - appCodec, runtime.NewKVStoreService(keys[icahosttypes.StoreKey]), app.GetSubspace(icahosttypes.SubModuleName), + appCodec, + runtime.NewEnvironment(runtime.NewKVStoreService(keys[icahosttypes.StoreKey]), logger.With(log.ModuleKey, "x/icahost"), runtime.EnvWithMsgRouterService(app.MsgServiceRouter()), runtime.EnvWithQueryRouterService(app.GRPCQueryRouter())), + app.GetSubspace(icahosttypes.SubModuleName), app.IBCFeeKeeper, // use ics29 fee as ics4Wrapper in middleware stack app.IBCKeeper.ChannelKeeper, - app.AuthKeeper, app.MsgServiceRouter(), - app.GRPCQueryRouter(), authtypes.NewModuleAddress(govtypes.ModuleName).String(), + app.AuthKeeper, + govModuleAddr, ) // Create IBC Router diff --git a/modules/light-clients/08-wasm/testing/simapp/app.go b/modules/light-clients/08-wasm/testing/simapp/app.go index 4ef571e774e..65f05041ad2 100644 --- a/modules/light-clients/08-wasm/testing/simapp/app.go +++ b/modules/light-clients/08-wasm/testing/simapp/app.go @@ -580,11 +580,13 @@ func NewSimApp( // ICA Host keeper app.ICAHostKeeper = icahostkeeper.NewKeeper( - appCodec, runtime.NewKVStoreService(keys[icahosttypes.StoreKey]), app.GetSubspace(icahosttypes.SubModuleName), + appCodec, + runtime.NewEnvironment(runtime.NewKVStoreService(keys[icahosttypes.StoreKey]), logger.With(log.ModuleKey, "x/icahost"), runtime.EnvWithMsgRouterService(app.MsgServiceRouter()), runtime.EnvWithQueryRouterService(app.GRPCQueryRouter())), + app.GetSubspace(icahosttypes.SubModuleName), app.IBCFeeKeeper, // use ics29 fee as ics4Wrapper in middleware stack app.IBCKeeper.ChannelKeeper, - app.AuthKeeper, app.MsgServiceRouter(), - app.GRPCQueryRouter(), authtypes.NewModuleAddress(govtypes.ModuleName).String(), + app.AuthKeeper, + govModuleAddr, ) // Create IBC Router diff --git a/simapp/app.go b/simapp/app.go index 45aaff5b1a0..99da8903a36 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -555,10 +555,12 @@ func NewSimApp( // ICA Host keeper app.ICAHostKeeper = icahostkeeper.NewKeeper( - appCodec, runtime.NewKVStoreService(keys[icahosttypes.StoreKey]), app.GetSubspace(icahosttypes.SubModuleName), + appCodec, + runtime.NewEnvironment(runtime.NewKVStoreService(keys[icahosttypes.StoreKey]), logger.With(log.ModuleKey, "x/icahost"), runtime.EnvWithMsgRouterService(app.MsgServiceRouter()), runtime.EnvWithQueryRouterService(app.GRPCQueryRouter())), + app.GetSubspace(icahosttypes.SubModuleName), app.IBCFeeKeeper, // use ics29 fee as ics4Wrapper in middleware stack - app.IBCKeeper.ChannelKeeper, app.AuthKeeper, - app.MsgServiceRouter(), app.GRPCQueryRouter(), + app.IBCKeeper.ChannelKeeper, + app.AuthKeeper, govModuleAddr, ) diff --git a/testing/simapp/app.go b/testing/simapp/app.go index 95c1ad6f6e1..9fc8fad4d4a 100644 --- a/testing/simapp/app.go +++ b/testing/simapp/app.go @@ -532,10 +532,12 @@ func NewSimApp( // ICA Host keeper app.ICAHostKeeper = icahostkeeper.NewKeeper( - appCodec, runtime.NewKVStoreService(keys[icahosttypes.StoreKey]), app.GetSubspace(icahosttypes.SubModuleName), + appCodec, + runtime.NewEnvironment(runtime.NewKVStoreService(keys[icahosttypes.StoreKey]), logger.With(log.ModuleKey, "x/icahost"), runtime.EnvWithMsgRouterService(app.MsgServiceRouter()), runtime.EnvWithQueryRouterService(app.GRPCQueryRouter())), + app.GetSubspace(icahosttypes.SubModuleName), app.IBCFeeKeeper, // use ics29 fee as ics4Wrapper in middleware stack - app.IBCKeeper.ChannelKeeper, app.AuthKeeper, - app.MsgServiceRouter(), app.GRPCQueryRouter(), + app.IBCKeeper.ChannelKeeper, + app.AuthKeeper, govModuleAddr, )