cosmos-sdk/x/ibc/handler.go

244 lines
8.8 KiB
Go

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"
connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/03-connection/types"
channel "github.com/cosmos/cosmos-sdk/x/ibc/04-channel"
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/04-channel/types"
porttypes "github.com/cosmos/cosmos-sdk/x/ibc/05-port/types"
"github.com/cosmos/cosmos-sdk/x/ibc/keeper"
)
// NewHandler defines the IBC handler
func NewHandler(k keeper.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 *connectiontypes.MsgConnectionOpenInit:
return connection.HandleMsgConnectionOpenInit(ctx, k.ConnectionKeeper, msg)
case *connectiontypes.MsgConnectionOpenTry:
return connection.HandleMsgConnectionOpenTry(ctx, k.ConnectionKeeper, msg)
case *connectiontypes.MsgConnectionOpenAck:
return connection.HandleMsgConnectionOpenAck(ctx, k.ConnectionKeeper, msg)
case *connectiontypes.MsgConnectionOpenConfirm:
return connection.HandleMsgConnectionOpenConfirm(ctx, k.ConnectionKeeper, msg)
// IBC channel msgs
case *channeltypes.MsgChannelOpenInit:
// Lookup module by port capability
module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortID)
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
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(porttypes.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, sdkerrors.Wrap(err, "channel open init callback failed")
}
return res, nil
case *channeltypes.MsgChannelOpenTry:
// Lookup module by port capability
module, portCap, err := k.PortKeeper.LookupModuleByPort(ctx, msg.PortID)
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
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(porttypes.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, sdkerrors.Wrap(err, "channel open try callback failed")
}
return res, nil
case *channeltypes.MsgChannelOpenAck:
// Lookup module by channel capability
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortID, msg.ChannelID)
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
err = cbs.OnChanOpenAck(ctx, msg.PortID, msg.ChannelID, msg.CounterpartyVersion)
if err != nil {
return nil, sdkerrors.Wrap(err, "channel open ack callback failed")
}
return channel.HandleMsgChannelOpenAck(ctx, k.ChannelKeeper, cap, msg)
case *channeltypes.MsgChannelOpenConfirm:
// Lookup module by channel capability
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortID, msg.ChannelID)
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
err = cbs.OnChanOpenConfirm(ctx, msg.PortID, msg.ChannelID)
if err != nil {
return nil, sdkerrors.Wrap(err, "channel open confirm callback failed")
}
return channel.HandleMsgChannelOpenConfirm(ctx, k.ChannelKeeper, cap, msg)
case *channeltypes.MsgChannelCloseInit:
// Lookup module by channel capability
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortID, msg.ChannelID)
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
err = cbs.OnChanCloseInit(ctx, msg.PortID, msg.ChannelID)
if err != nil {
return nil, sdkerrors.Wrap(err, "channel close init callback failed")
}
return channel.HandleMsgChannelCloseInit(ctx, k.ChannelKeeper, cap, msg)
case *channeltypes.MsgChannelCloseConfirm:
// Lookup module by channel capability
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.PortID, msg.ChannelID)
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
err = cbs.OnChanCloseConfirm(ctx, msg.PortID, msg.ChannelID)
if err != nil {
return nil, sdkerrors.Wrap(err, "channel close confirm callback failed")
}
return channel.HandleMsgChannelCloseConfirm(ctx, k.ChannelKeeper, cap, msg)
// IBC packet msgs get routed to the appropriate module callback
case *channeltypes.MsgPacket:
// Lookup module by channel capability
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.DestinationPort, msg.Packet.DestinationChannel)
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
// Perform application logic callback
res, ack, err := cbs.OnRecvPacket(ctx, msg.Packet)
if err != nil {
return nil, sdkerrors.Wrap(err, "receive packet callback failed")
}
// Set packet acknowledgement
if err = k.ChannelKeeper.PacketExecuted(ctx, cap, msg.Packet, ack); err != nil {
return nil, err
}
return res, nil
case *channeltypes.MsgAcknowledgement:
// Lookup module by channel capability
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
// Perform application logic callback
res, err := cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement)
if err != nil {
return nil, sdkerrors.Wrap(err, "acknowledge packet callback failed")
}
// Delete packet commitment
if err = k.ChannelKeeper.AcknowledgementExecuted(ctx, cap, msg.Packet); err != nil {
return nil, err
}
return res, nil
case *channeltypes.MsgTimeout:
// Lookup module by channel capability
module, cap, err := k.ChannelKeeper.LookupModuleByChannel(ctx, msg.Packet.SourcePort, msg.Packet.SourceChannel)
if err != nil {
return nil, sdkerrors.Wrap(err, "could not retrieve module from port-id")
}
// Retrieve callbacks from router
cbs, ok := k.Router.GetRoute(module)
if !ok {
return nil, sdkerrors.Wrapf(porttypes.ErrInvalidRoute, "route not found to module: %s", module)
}
// Perform application logic callback
res, err := cbs.OnTimeoutPacket(ctx, msg.Packet)
if err != nil {
return nil, sdkerrors.Wrap(err, "timeout packet callback failed")
}
// Delete packet commitment
if err = k.ChannelKeeper.TimeoutExecuted(ctx, cap, msg.Packet); err != nil {
return nil, err
}
return res, nil
default:
return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized IBC message type: %T", msg)
}
}
}