diff --git a/modules/apps/27-interchain-accounts/controller/ibc_module.go b/modules/apps/27-interchain-accounts/controller/ibc_middleware.go similarity index 67% rename from modules/apps/27-interchain-accounts/controller/ibc_module.go rename to modules/apps/27-interchain-accounts/controller/ibc_middleware.go index 325ec70959b..c12f5d3e9ce 100644 --- a/modules/apps/27-interchain-accounts/controller/ibc_module.go +++ b/modules/apps/27-interchain-accounts/controller/ibc_middleware.go @@ -13,27 +13,30 @@ import ( ibcexported "github.com/cosmos/ibc-go/v3/modules/core/exported" ) -// IBCModule implements the ICS26 interface for interchain accounts controller chains -type IBCModule struct { - keeper keeper.Keeper +var _ porttypes.Middleware = &IBCMiddleware{} + +// IBCMiddleware implements the ICS26 callbacks for the fee middleware given the +// ICA controller keeper and the underlying application. +type IBCMiddleware struct { app porttypes.IBCModule + keeper keeper.Keeper } -// NewIBCModule creates a new IBCModule given the associated keeper and underlying application -func NewIBCModule(k keeper.Keeper, app porttypes.IBCModule) IBCModule { - return IBCModule{ - keeper: k, +// IBCMiddleware creates a new IBCMiddleware given the associated keeper and underlying application +func NewIBCMiddleware(app porttypes.IBCModule, k keeper.Keeper) IBCMiddleware { + return IBCMiddleware{ app: app, + keeper: k, } } -// OnChanOpenInit implements the IBCModule interface +// OnChanOpenInit implements the IBCMiddleware interface // // Interchain Accounts is implemented to act as middleware for connected authentication modules on // the controller side. The connected modules may not change the controller side portID or // version. They will be allowed to perform custom logic without changing // the parameters stored within a channel struct. -func (im IBCModule) OnChanOpenInit( +func (im IBCMiddleware) OnChanOpenInit( ctx sdk.Context, order channeltypes.Order, connectionHops []string, @@ -56,8 +59,8 @@ func (im IBCModule) OnChanOpenInit( chanCap, counterparty, version) } -// OnChanOpenTry implements the IBCModule interface -func (im IBCModule) OnChanOpenTry( +// OnChanOpenTry implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanOpenTry( ctx sdk.Context, order channeltypes.Order, connectionHops []string, @@ -70,13 +73,13 @@ func (im IBCModule) OnChanOpenTry( return "", sdkerrors.Wrap(icatypes.ErrInvalidChannelFlow, "channel handshake must be initiated by controller chain") } -// OnChanOpenAck implements the IBCModule interface +// OnChanOpenAck implements the IBCMiddleware interface // // Interchain Accounts is implemented to act as middleware for connected authentication modules on // the controller side. The connected modules may not change the portID or // version. They will be allowed to perform custom logic without changing // the parameters stored within a channel struct. -func (im IBCModule) OnChanOpenAck( +func (im IBCMiddleware) OnChanOpenAck( ctx sdk.Context, portID, channelID string, @@ -95,8 +98,8 @@ func (im IBCModule) OnChanOpenAck( return im.app.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) } -// OnChanOpenAck implements the IBCModule interface -func (im IBCModule) OnChanOpenConfirm( +// OnChanOpenAck implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanOpenConfirm( ctx sdk.Context, portID, channelID string, @@ -104,8 +107,8 @@ func (im IBCModule) OnChanOpenConfirm( return sdkerrors.Wrap(icatypes.ErrInvalidChannelFlow, "channel handshake must be initiated by controller chain") } -// OnChanCloseInit implements the IBCModule interface -func (im IBCModule) OnChanCloseInit( +// OnChanCloseInit implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanCloseInit( ctx sdk.Context, portID, channelID string, @@ -114,8 +117,8 @@ func (im IBCModule) OnChanCloseInit( return sdkerrors.Wrap(sdkerrors.ErrInvalidRequest, "user cannot close channel") } -// OnChanCloseConfirm implements the IBCModule interface -func (im IBCModule) OnChanCloseConfirm( +// OnChanCloseConfirm implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanCloseConfirm( ctx sdk.Context, portID, channelID string, @@ -123,8 +126,8 @@ func (im IBCModule) OnChanCloseConfirm( return im.keeper.OnChanCloseConfirm(ctx, portID, channelID) } -// OnRecvPacket implements the IBCModule interface -func (im IBCModule) OnRecvPacket( +// OnRecvPacket implements the IBCMiddleware interface +func (im IBCMiddleware) OnRecvPacket( ctx sdk.Context, packet channeltypes.Packet, _ sdk.AccAddress, @@ -132,8 +135,8 @@ func (im IBCModule) OnRecvPacket( return channeltypes.NewErrorAcknowledgement("cannot receive packet on controller chain") } -// OnAcknowledgementPacket implements the IBCModule interface -func (im IBCModule) OnAcknowledgementPacket( +// OnAcknowledgementPacket implements the IBCMiddleware interface +func (im IBCMiddleware) OnAcknowledgementPacket( ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, @@ -147,8 +150,8 @@ func (im IBCModule) OnAcknowledgementPacket( return im.app.OnAcknowledgementPacket(ctx, packet, acknowledgement, relayer) } -// OnTimeoutPacket implements the IBCModule interface -func (im IBCModule) OnTimeoutPacket( +// OnTimeoutPacket implements the IBCMiddleware interface +func (im IBCMiddleware) OnTimeoutPacket( ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, @@ -164,7 +167,27 @@ func (im IBCModule) OnTimeoutPacket( return im.app.OnTimeoutPacket(ctx, packet, relayer) } +// SendPacket implements the ICS4 Wrapper interface +// The ICA controller module builds the outgoing ICA packet and calls the core IBC SendPacket +func (im IBCMiddleware) SendPacket( + ctx sdk.Context, + chanCap *capabilitytypes.Capability, + packet ibcexported.PacketI, +) error { + panic("SendPacket not supported for ICA-auth module. Please use SendTx") +} + +// WriteAcknowledgement implements the ICS4 Wrapper interface +func (im IBCMiddleware) WriteAcknowledgement( + ctx sdk.Context, + chanCap *capabilitytypes.Capability, + packet ibcexported.PacketI, + ack ibcexported.Acknowledgement, +) error { + panic("WriteAcknowledgement not supported for ICA controller module") +} + // GetAppVersion returns the interchain accounts metadata. -func (im IBCModule) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { +func (im IBCMiddleware) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { return im.keeper.GetAppVersion(ctx, portID, channelID) } diff --git a/modules/apps/27-interchain-accounts/controller/ibc_module_test.go b/modules/apps/27-interchain-accounts/controller/ibc_middleware_test.go similarity index 99% rename from modules/apps/27-interchain-accounts/controller/ibc_module_test.go rename to modules/apps/27-interchain-accounts/controller/ibc_middleware_test.go index 608996515c1..ea1b5185af2 100644 --- a/modules/apps/27-interchain-accounts/controller/ibc_module_test.go +++ b/modules/apps/27-interchain-accounts/controller/ibc_middleware_test.go @@ -717,7 +717,7 @@ func (suite *InterchainAccountsTestSuite) TestGetAppVersion() { cbs, ok := suite.chainA.App.GetIBCKeeper().Router.GetRoute(module) suite.Require().True(ok) - controllerModule := cbs.(icacontroller.IBCModule) + controllerModule := cbs.(icacontroller.IBCMiddleware) appVersion, found := controllerModule.GetAppVersion(suite.chainA.GetContext(), path.EndpointA.ChannelConfig.PortID, path.EndpointA.ChannelID) suite.Require().True(found) diff --git a/modules/apps/27-interchain-accounts/module.go b/modules/apps/27-interchain-accounts/module.go index 1bb870fca5d..c7a5651baa6 100644 --- a/modules/apps/27-interchain-accounts/module.go +++ b/modules/apps/27-interchain-accounts/module.go @@ -16,7 +16,6 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/client/cli" - "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/controller" controllerkeeper "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/controller/keeper" controllertypes "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/controller/types" "github.com/cosmos/ibc-go/v3/modules/apps/27-interchain-accounts/host" @@ -31,7 +30,6 @@ var ( _ module.AppModule = AppModule{} _ module.AppModuleBasic = AppModuleBasic{} - _ porttypes.IBCModule = controller.IBCModule{} _ porttypes.IBCModule = host.IBCModule{} ) diff --git a/modules/apps/29-fee/ibc_module.go b/modules/apps/29-fee/ibc_middleware.go similarity index 82% rename from modules/apps/29-fee/ibc_module.go rename to modules/apps/29-fee/ibc_middleware.go index 6ed9faa1f34..236c7456b0d 100644 --- a/modules/apps/29-fee/ibc_module.go +++ b/modules/apps/29-fee/ibc_middleware.go @@ -12,22 +12,25 @@ import ( "github.com/cosmos/ibc-go/v3/modules/core/exported" ) -// IBCModule implements the ICS26 callbacks for the fee middleware given the fee keeper and the underlying application. -type IBCModule struct { - keeper keeper.Keeper +var _ porttypes.Middleware = &IBCMiddleware{} + +// IBCMiddleware implements the ICS26 callbacks for the fee middleware given the +// fee keeper and the underlying application. +type IBCMiddleware struct { app porttypes.IBCModule + keeper keeper.Keeper } -// NewIBCModule creates a new IBCModule given the keeper and underlying application -func NewIBCModule(k keeper.Keeper, app porttypes.IBCModule) IBCModule { - return IBCModule{ - keeper: k, +// NewIBCMiddleware creates a new IBCMiddlware given the keeper and underlying application +func NewIBCMiddleware(app porttypes.IBCModule, k keeper.Keeper) IBCMiddleware { + return IBCMiddleware{ app: app, + keeper: k, } } -// OnChanOpenInit implements the IBCModule interface -func (im IBCModule) OnChanOpenInit( +// OnChanOpenInit implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanOpenInit( ctx sdk.Context, order channeltypes.Order, connectionHops []string, @@ -57,10 +60,10 @@ func (im IBCModule) OnChanOpenInit( chanCap, counterparty, versionMetadata.AppVersion) } -// OnChanOpenTry implements the IBCModule interface +// OnChanOpenTry implements the IBCMiddleware interface // If the channel is not fee enabled the underlying application version will be returned // If the channel is fee enabled we merge the underlying application version with the ics29 version -func (im IBCModule) OnChanOpenTry( +func (im IBCMiddleware) OnChanOpenTry( ctx sdk.Context, order channeltypes.Order, connectionHops []string, @@ -100,8 +103,8 @@ func (im IBCModule) OnChanOpenTry( return string(versionBytes), nil } -// OnChanOpenAck implements the IBCModule interface -func (im IBCModule) OnChanOpenAck( +// OnChanOpenAck implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanOpenAck( ctx sdk.Context, portID, channelID string, @@ -128,8 +131,8 @@ func (im IBCModule) OnChanOpenAck( return im.app.OnChanOpenAck(ctx, portID, channelID, counterpartyChannelID, counterpartyVersion) } -// OnChanOpenConfirm implements the IBCModule interface -func (im IBCModule) OnChanOpenConfirm( +// OnChanOpenConfirm implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanOpenConfirm( ctx sdk.Context, portID, channelID string, @@ -138,8 +141,8 @@ func (im IBCModule) OnChanOpenConfirm( return im.app.OnChanOpenConfirm(ctx, portID, channelID) } -// OnChanCloseInit implements the IBCModule interface -func (im IBCModule) OnChanCloseInit( +// OnChanCloseInit implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanCloseInit( ctx sdk.Context, portID, channelID string, @@ -155,8 +158,8 @@ func (im IBCModule) OnChanCloseInit( return nil } -// OnChanCloseConfirm implements the IBCModule interface -func (im IBCModule) OnChanCloseConfirm( +// OnChanCloseConfirm implements the IBCMiddleware interface +func (im IBCMiddleware) OnChanCloseConfirm( ctx sdk.Context, portID, channelID string, @@ -172,9 +175,9 @@ func (im IBCModule) OnChanCloseConfirm( return nil } -// OnRecvPacket implements the IBCModule interface. +// OnRecvPacket implements the IBCMiddleware interface. // If fees are not enabled, this callback will default to the ibc-core packet callback -func (im IBCModule) OnRecvPacket( +func (im IBCMiddleware) OnRecvPacket( ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, @@ -197,9 +200,9 @@ func (im IBCModule) OnRecvPacket( return types.NewIncentivizedAcknowledgement(forwardRelayer, ack.Acknowledgement(), ack.Success()) } -// OnAcknowledgementPacket implements the IBCModule interface +// OnAcknowledgementPacket implements the IBCMiddleware interface // If fees are not enabled, this callback will default to the ibc-core packet callback -func (im IBCModule) OnAcknowledgementPacket( +func (im IBCMiddleware) OnAcknowledgementPacket( ctx sdk.Context, packet channeltypes.Packet, acknowledgement []byte, @@ -239,9 +242,9 @@ func (im IBCModule) OnAcknowledgementPacket( return im.app.OnAcknowledgementPacket(ctx, packet, ack.Result, relayer) } -// OnTimeoutPacket implements the IBCModule interface +// OnTimeoutPacket implements the IBCMiddleware interface // If fees are not enabled, this callback will default to the ibc-core packet callback -func (im IBCModule) OnTimeoutPacket( +func (im IBCMiddleware) OnTimeoutPacket( ctx sdk.Context, packet channeltypes.Packet, relayer sdk.AccAddress, @@ -268,7 +271,26 @@ func (im IBCModule) OnTimeoutPacket( return im.app.OnTimeoutPacket(ctx, packet, relayer) } +// SendPacket implements the ICS4 Wrapper interface +func (im IBCMiddleware) SendPacket( + ctx sdk.Context, + chanCap *capabilitytypes.Capability, + packet exported.PacketI, +) error { + return im.keeper.SendPacket(ctx, chanCap, packet) +} + +// WriteAcknowledgement implements the ICS4 Wrapper interface +func (im IBCMiddleware) WriteAcknowledgement( + ctx sdk.Context, + chanCap *capabilitytypes.Capability, + packet exported.PacketI, + ack exported.Acknowledgement, +) error { + return im.keeper.WriteAcknowledgement(ctx, chanCap, packet, ack) +} + // GetAppVersion returns the application version of the underlying application -func (im IBCModule) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { +func (im IBCMiddleware) GetAppVersion(ctx sdk.Context, portID, channelID string) (string, bool) { return im.keeper.GetAppVersion(ctx, portID, channelID) } diff --git a/modules/apps/29-fee/ibc_module_test.go b/modules/apps/29-fee/ibc_middleware_test.go similarity index 99% rename from modules/apps/29-fee/ibc_module_test.go rename to modules/apps/29-fee/ibc_middleware_test.go index 3f5cf64635a..d46c414270e 100644 --- a/modules/apps/29-fee/ibc_module_test.go +++ b/modules/apps/29-fee/ibc_middleware_test.go @@ -896,7 +896,7 @@ func (suite *FeeTestSuite) TestGetAppVersion() { cbs, ok := suite.chainA.App.GetIBCKeeper().Router.GetRoute(module) suite.Require().True(ok) - feeModule := cbs.(fee.IBCModule) + feeModule := cbs.(fee.IBCMiddleware) appVersion, found := feeModule.GetAppVersion(suite.chainA.GetContext(), portID, channelID) diff --git a/modules/apps/29-fee/module.go b/modules/apps/29-fee/module.go index e493e047837..895a475b512 100644 --- a/modules/apps/29-fee/module.go +++ b/modules/apps/29-fee/module.go @@ -20,12 +20,10 @@ import ( "github.com/cosmos/ibc-go/v3/modules/apps/29-fee/client/cli" "github.com/cosmos/ibc-go/v3/modules/apps/29-fee/keeper" "github.com/cosmos/ibc-go/v3/modules/apps/29-fee/types" - porttypes "github.com/cosmos/ibc-go/v3/modules/core/05-port/types" ) var ( _ module.AppModule = AppModule{} - _ porttypes.IBCModule = IBCModule{} _ module.AppModuleBasic = AppModuleBasic{} ) diff --git a/testing/simapp/app.go b/testing/simapp/app.go index 738e29cdd59..f707ba6087b 100644 --- a/testing/simapp/app.go +++ b/testing/simapp/app.go @@ -300,7 +300,8 @@ func NewSimApp( // seal capability keeper after scoping modules app.CapabilityKeeper.Seal() - // add keepers + // SDK module keepers + app.AccountKeeper = authkeeper.NewAccountKeeper( appCodec, keys[authtypes.StoreKey], app.GetSubspace(authtypes.ModuleName), authtypes.ProtoBaseAccount, maccPerms, ) @@ -334,13 +335,14 @@ func NewSimApp( stakingtypes.NewMultiStakingHooks(app.DistrKeeper.Hooks(), app.SlashingKeeper.Hooks()), ) - // Create IBC Keeper + app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.BaseApp.MsgServiceRouter()) + + // IBC Keepers + app.IBCKeeper = ibckeeper.NewKeeper( appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper, ) - app.AuthzKeeper = authzkeeper.NewKeeper(keys[authzkeeper.StoreKey], appCodec, app.BaseApp.MsgServiceRouter()) - // register the proposal types govRouter := govtypes.NewRouter() govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler). @@ -353,69 +355,111 @@ func NewSimApp( &stakingKeeper, govRouter, ) - app.IBCFeeKeeper = ibcfeekeeper.NewKeeper(appCodec, keys[ibcfeetypes.StoreKey], app.GetSubspace(ibcfeetypes.ModuleName), - app.IBCKeeper.ChannelKeeper, app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper, + // IBC Fee Module keeper + app.IBCFeeKeeper = ibcfeekeeper.NewKeeper( + appCodec, keys[ibcfeetypes.StoreKey], app.GetSubspace(ibcfeetypes.ModuleName), + app.IBCKeeper.ChannelKeeper, // may be replaced with IBC middleware + app.IBCKeeper.ChannelKeeper, + &app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper, + ) + + // ICA Controller keeper + app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper( + appCodec, keys[icacontrollertypes.StoreKey], app.GetSubspace(icacontrollertypes.SubModuleName), + app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee + app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, + scopedICAControllerKeeper, app.MsgServiceRouter(), ) + // ICA Host keeper + app.ICAHostKeeper = icahostkeeper.NewKeeper( + appCodec, keys[icahosttypes.StoreKey], app.GetSubspace(icahosttypes.SubModuleName), + app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, + app.AccountKeeper, scopedICAHostKeeper, app.MsgServiceRouter(), + ) + + // Create IBC Router + ibcRouter := porttypes.NewRouter() + + // Middleware Stacks + // Create Transfer Keeper and pass IBCFeeKeeper as expected Channel and PortKeeper // since fee middleware will wrap the IBCKeeper for underlying application. app.TransferKeeper = ibctransferkeeper.NewKeeper( appCodec, keys[ibctransfertypes.StoreKey], app.GetSubspace(ibctransfertypes.ModuleName), - app.IBCFeeKeeper, app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, + app.IBCFeeKeeper, // ISC4 Wrapper: fee IBC middleware + app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, app.AccountKeeper, app.BankKeeper, scopedTransferKeeper, ) - transferModule := transfer.NewAppModule(app.TransferKeeper) - transferIBCModule := transfer.NewIBCModule(app.TransferKeeper) - - // create fee-wrapped transfer module - feeTransferModule := ibcfee.NewIBCModule(app.IBCFeeKeeper, transferIBCModule) - feeModule := ibcfee.NewAppModule(app.IBCFeeKeeper) + // Mock Module Stack + // Mock Module setup for testing IBC and also acts as the interchain accounts authentication module // NOTE: the IBC mock keeper and application module is used only for testing core IBC. Do // not replicate if you do not need to test core IBC or light clients. mockModule := ibcmock.NewAppModule(&app.IBCKeeper.PortKeeper) - // create fee wrapped mock module - feeMockModule := ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp(MockFeePort, scopedFeeMockKeeper)) - app.FeeMockModule = feeMockModule + // The mock module is used for testing IBC + mockIBCModule := ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp(ibcmock.ModuleName, scopedIBCMockKeeper)) + ibcRouter.AddRoute(ibcmock.ModuleName, mockIBCModule) - feeWithMockModule := ibcfee.NewIBCModule(app.IBCFeeKeeper, feeMockModule) + // Create Transfer Stack + // SendPacket, since it is originating from the application to core IBC: + // transferKeeper.SendPacket -> fee.SendPacket -> channel.SendPacket - mockIBCModule := ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp(ibcmock.ModuleName, scopedIBCMockKeeper)) + // RecvPacket, message that originates from core IBC and goes down to app, the flow is the other way + // channel.RecvPacket -> fee.OnRecvPacket -> transfer.OnRecvPacket - app.ICAControllerKeeper = icacontrollerkeeper.NewKeeper( - appCodec, keys[icacontrollertypes.StoreKey], app.GetSubspace(icacontrollertypes.SubModuleName), - app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee - app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, - scopedICAControllerKeeper, app.MsgServiceRouter(), - ) + // transfer stack contains (from top to bottom): + // - IBC Fee Middleware + // - Transfer - app.ICAHostKeeper = icahostkeeper.NewKeeper( - appCodec, keys[icahosttypes.StoreKey], app.GetSubspace(icahosttypes.SubModuleName), - app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, - app.AccountKeeper, scopedICAHostKeeper, app.MsgServiceRouter(), - ) + // create IBC module from bottom to top of stack + var transferStack porttypes.IBCModule + transferStack = transfer.NewIBCModule(app.TransferKeeper) + transferStack = ibcfee.NewIBCMiddleware(transferStack, app.IBCFeeKeeper) + + // Add transfer stack to IBC Router + ibcRouter.AddRoute(ibctransfertypes.ModuleName, transferStack) - icaModule := ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper) + // Create Interchain Accounts Stack + // SendPacket, since it is originating from the application to core IBC: + // icaAuthModuleKeeper.SendTx -> icaControllerKeeper.SendPacket -> channel.SendPacket // initialize ICA module with mock module as the authentication module on the controller side - icaAuthModule := ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp("", scopedICAMockKeeper)) - app.ICAAuthModule = icaAuthModule + var icaControllerStack porttypes.IBCModule + icaControllerStack = ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp("", scopedICAMockKeeper)) + app.ICAAuthModule = icaControllerStack.(ibcmock.IBCModule) + icaControllerStack = icacontroller.NewIBCMiddleware(icaControllerStack, app.ICAControllerKeeper) - icaControllerIBCModule := icacontroller.NewIBCModule(app.ICAControllerKeeper, icaAuthModule) icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper) - // Create static IBC router, add app routes, then set and seal it - // pass in top-level (fully-wrapped) IBCModules to IBC Router - ibcRouter := porttypes.NewRouter() - ibcRouter.AddRoute(icacontrollertypes.SubModuleName, icaControllerIBCModule). + // Add host, controller & ica auth modules to IBC router + ibcRouter. + // the ICA Controller middleware needs to be explicitly added to the IBC Router because the + // ICA controller module owns the port capability for ICA. The ICA authentication module + // owns the channel capability. + AddRoute(icacontrollertypes.SubModuleName, icaControllerStack). AddRoute(icahosttypes.SubModuleName, icaHostIBCModule). - AddRoute(ibcmock.ModuleName+icacontrollertypes.SubModuleName, icaControllerIBCModule). // ica with mock auth module stack route to ica (top level of middleware stack) - AddRoute(ibctransfertypes.ModuleName, feeTransferModule). - AddRoute(ibcmock.ModuleName, mockIBCModule). - AddRoute(MockFeePort, feeWithMockModule) + AddRoute(ibcmock.ModuleName+icacontrollertypes.SubModuleName, icaControllerStack) // ica with mock auth module stack route to ica (top level of middleware stack) + + // Create Mock IBC Fee module stack for testing + // SendPacket, since it is originating from the application to core IBC: + // mockModule.SendPacket -> fee.SendPacket -> channel.SendPacket + + // OnRecvPacket, message that originates from core IBC and goes down to app, the flow is the otherway + // channel.RecvPacket -> fee.OnRecvPacket -> mockModule.OnRecvPacket + // OnAcknowledgementPacket as this is where fee's are paid out + // mockModule.OnAcknowledgementPacket -> fee.OnAcknowledgementPacket -> channel.OnAcknowledgementPacket + + // create fee wrapped mock module + feeMockModule := ibcmock.NewIBCModule(&mockModule, ibcmock.NewMockIBCApp(MockFeePort, scopedFeeMockKeeper)) + app.FeeMockModule = feeMockModule + feeWithMockModule := ibcfee.NewIBCMiddleware(feeMockModule, app.IBCFeeKeeper) + ibcRouter.AddRoute(MockFeePort, feeWithMockModule) + + // Seal the IBC Router app.IBCKeeper.SetRouter(ibcRouter) // create evidence keeper with router @@ -434,6 +478,7 @@ func NewSimApp( // NOTE: Any module instantiated in the module manager that is later modified // must be passed by reference here. app.mm = module.NewManager( + // SDK app modules genutil.NewAppModule( app.AccountKeeper, app.StakingKeeper, app.BaseApp.DeliverTx, encodingConfig.TxConfig, @@ -454,9 +499,11 @@ func NewSimApp( ibc.NewAppModule(app.IBCKeeper), params.NewAppModule(app.ParamsKeeper), authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), - transferModule, - feeModule, - icaModule, + + // IBC modules + transfer.NewAppModule(app.TransferKeeper), + ibcfee.NewAppModule(app.IBCFeeKeeper), + ica.NewAppModule(&app.ICAControllerKeeper, &app.ICAHostKeeper), mockModule, ) @@ -516,7 +563,7 @@ func NewSimApp( evidence.NewAppModule(app.EvidenceKeeper), authzmodule.NewAppModule(appCodec, app.AuthzKeeper, app.AccountKeeper, app.BankKeeper, app.interfaceRegistry), ibc.NewAppModule(app.IBCKeeper), - transferModule, + transfer.NewAppModule(app.TransferKeeper), ) app.sm.RegisterStoreDecoders()