package ibc import ( sdk "github.com/cosmos/cosmos-sdk/types" sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" client "github.com/cosmos/cosmos-sdk/x/ibc/02-client" clientexported "github.com/cosmos/cosmos-sdk/x/ibc/02-client/exported" connection "github.com/cosmos/cosmos-sdk/x/ibc/03-connection" channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel" port "github.com/cosmos/cosmos-sdk/x/ibc/05-port" ) // NewHandler defines the IBC handler func NewHandler(k Keeper) sdk.Handler { return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) { ctx = ctx.WithEventManager(sdk.NewEventManager()) switch msg := msg.(type) { // IBC client msg interface types case clientexported.MsgCreateClient: return client.HandleMsgCreateClient(ctx, k.ClientKeeper, msg) case clientexported.MsgUpdateClient: return &sdk.Result{}, nil // IBC connection msgs case connection.MsgConnectionOpenInit: return connection.HandleMsgConnectionOpenInit(ctx, k.ConnectionKeeper, msg) case connection.MsgConnectionOpenTry: return connection.HandleMsgConnectionOpenTry(ctx, k.ConnectionKeeper, msg) case connection.MsgConnectionOpenAck: return connection.HandleMsgConnectionOpenAck(ctx, k.ConnectionKeeper, msg) case connection.MsgConnectionOpenConfirm: return connection.HandleMsgConnectionOpenConfirm(ctx, k.ConnectionKeeper, msg) // IBC channel msgs case channel.MsgChannelOpenInit: // Lookup module by port capability module, portCap, ok := k.PortKeeper.LookupModuleByPort(ctx, msg.PortID) if !ok { return nil, sdkerrors.Wrap(port.ErrInvalidPort, "could not retrieve module from portID") } res, cap, err := channel.HandleMsgChannelOpenInit(ctx, k.ChannelKeeper, portCap, msg) if err != nil { return nil, err } // Retrieve callbacks from router cbs, ok := k.Router.GetRoute(module) if !ok { return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module) } err = cbs.OnChanOpenInit(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortID, msg.ChannelID, cap, msg.Channel.Counterparty, msg.Channel.Version) if err != nil { return nil, err } return res, nil case channel.MsgChannelOpenTry: // Lookup module by port capability module, portCap, ok := k.PortKeeper.LookupModuleByPort(ctx, msg.PortID) if !ok { return nil, sdkerrors.Wrap(port.ErrInvalidPort, "could not retrieve module from portID") } res, cap, err := channel.HandleMsgChannelOpenTry(ctx, k.ChannelKeeper, portCap, msg) if err != nil { return nil, err } // Retrieve callbacks from router cbs, ok := k.Router.GetRoute(module) if !ok { return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module) } err = cbs.OnChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortID, msg.ChannelID, cap, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion) if err != nil { return nil, err } return res, nil case channel.MsgChannelOpenAck: // Lookup module by channel capability module, cap, ok := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortID, msg.ChannelID) if !ok { return nil, sdkerrors.Wrap(channel.ErrChannelCapabilityNotFound, "could not retrieve module from channel capability") } // Retrieve callbacks from router cbs, ok := k.Router.GetRoute(module) if !ok { return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module) } err := cbs.OnChanOpenAck(ctx, msg.PortID, msg.ChannelID, msg.CounterpartyVersion) if err != nil { return nil, err } return channel.HandleMsgChannelOpenAck(ctx, k.ChannelKeeper, cap, msg) case channel.MsgChannelOpenConfirm: // Lookup module by channel capability module, cap, ok := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortID, msg.ChannelID) if !ok { return nil, sdkerrors.Wrap(channel.ErrChannelCapabilityNotFound, "could not retrieve module from channel capability") } // Retrieve callbacks from router cbs, ok := k.Router.GetRoute(module) if !ok { return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module) } err := cbs.OnChanOpenConfirm(ctx, msg.PortID, msg.ChannelID) if err != nil { return nil, err } return channel.HandleMsgChannelOpenConfirm(ctx, k.ChannelKeeper, cap, msg) case channel.MsgChannelCloseInit: // Lookup module by channel capability module, cap, ok := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortID, msg.ChannelID) if !ok { return nil, sdkerrors.Wrap(channel.ErrChannelCapabilityNotFound, "could not retrieve module from channel capability") } // Retrieve callbacks from router cbs, ok := k.Router.GetRoute(module) if !ok { return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module) } err := cbs.OnChanCloseInit(ctx, msg.PortID, msg.ChannelID) if err != nil { return nil, err } return channel.HandleMsgChannelCloseInit(ctx, k.ChannelKeeper, cap, msg) case channel.MsgChannelCloseConfirm: // Lookup module by channel capability module, cap, ok := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortID, msg.ChannelID) if !ok { return nil, sdkerrors.Wrap(channel.ErrChannelCapabilityNotFound, "could not retrieve module from channel capability") } // Retrieve callbacks from router cbs, ok := k.Router.GetRoute(module) if !ok { return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module) } err := cbs.OnChanCloseConfirm(ctx, msg.PortID, msg.ChannelID) if err != nil { return nil, err } return channel.HandleMsgChannelCloseConfirm(ctx, k.ChannelKeeper, cap, msg) // IBC packet msgs get routed to the appropriate module callback case channel.MsgPacket: // Lookup module by channel capability module, _, ok := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.DestinationPort, msg.Packet.DestinationChannel) if !ok { return nil, sdkerrors.Wrap(channel.ErrChannelCapabilityNotFound, "could not retrieve module from channel capability") } // Retrieve callbacks from router cbs, ok := k.Router.GetRoute(module) if !ok { return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module) } return cbs.OnRecvPacket(ctx, msg.Packet) case channel.MsgAcknowledgement: // Lookup module by channel capability module, _, ok := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel) if !ok { return nil, sdkerrors.Wrap(channel.ErrChannelCapabilityNotFound, "could not retrieve module from channel capability") } // Retrieve callbacks from router cbs, ok := k.Router.GetRoute(module) if !ok { return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module) } return cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement) case channel.MsgTimeout: // Lookup module by channel capability module, cap, ok := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel) if !ok { return nil, sdkerrors.Wrap(channel.ErrChannelCapabilityNotFound, "could not retrieve module from channel capability") } // Retrieve callbacks from router cbs, ok := k.Router.GetRoute(module) if !ok { return nil, sdkerrors.Wrapf(port.ErrInvalidRoute, "route not found to module: %s", module) } res, err := cbs.OnTimeoutPacket(ctx, msg.Packet) if err != nil { return nil, err } err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet) if err != nil { return nil, err } return res, err default: return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized IBC message type: %T", msg) } } }