cosmos-sdk/x/ibc/core/keeper/msg_server.go

619 lines
23 KiB
Go

package keeper
import (
"context"
"github.com/armon/go-metrics"
"github.com/cosmos/cosmos-sdk/telemetry"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
clienttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client/types"
connectiontypes "github.com/cosmos/cosmos-sdk/x/ibc/core/03-connection/types"
channel "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel"
channeltypes "github.com/cosmos/cosmos-sdk/x/ibc/core/04-channel/types"
porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types"
)
var _ clienttypes.MsgServer = Keeper{}
var _ connectiontypes.MsgServer = Keeper{}
var _ channeltypes.MsgServer = Keeper{}
// CreateClient defines a rpc handler method for MsgCreateClient.
func (k Keeper) CreateClient(goCtx context.Context, msg *clienttypes.MsgCreateClient) (*clienttypes.MsgCreateClientResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
clientState, err := clienttypes.UnpackClientState(msg.ClientState)
if err != nil {
return nil, err
}
consensusState, err := clienttypes.UnpackConsensusState(msg.ConsensusState)
if err != nil {
return nil, err
}
if err = k.ClientKeeper.CreateClient(ctx, msg.ClientId, clientState, consensusState); err != nil {
return nil, err
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
clienttypes.EventTypeCreateClient,
sdk.NewAttribute(clienttypes.AttributeKeyClientID, msg.ClientId),
sdk.NewAttribute(clienttypes.AttributeKeyClientType, clientState.ClientType()),
sdk.NewAttribute(clienttypes.AttributeKeyConsensusHeight, clientState.GetLatestHeight().String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory),
),
})
return &clienttypes.MsgCreateClientResponse{}, nil
}
// UpdateClient defines a rpc handler method for MsgUpdateClient.
func (k Keeper) UpdateClient(goCtx context.Context, msg *clienttypes.MsgUpdateClient) (*clienttypes.MsgUpdateClientResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
header, err := clienttypes.UnpackHeader(msg.Header)
if err != nil {
return nil, err
}
if err = k.ClientKeeper.UpdateClient(ctx, msg.ClientId, header); err != nil {
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory),
),
)
return &clienttypes.MsgUpdateClientResponse{}, nil
}
// UpgradeClient defines a rpc handler method for MsgUpgradeClient.
func (k Keeper) UpgradeClient(goCtx context.Context, msg *clienttypes.MsgUpgradeClient) (*clienttypes.MsgUpgradeClientResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
upgradedClient, err := clienttypes.UnpackClientState(msg.ClientState)
if err != nil {
return nil, err
}
if err = k.ClientKeeper.UpgradeClient(ctx, msg.ClientId, upgradedClient, msg.UpgradeHeight, msg.ProofUpgrade); err != nil {
return nil, err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, clienttypes.AttributeValueCategory),
),
)
return &clienttypes.MsgUpgradeClientResponse{}, nil
}
// SubmitMisbehaviour defines a rpc handler method for MsgSubmitMisbehaviour.
func (k Keeper) SubmitMisbehaviour(goCtx context.Context, msg *clienttypes.MsgSubmitMisbehaviour) (*clienttypes.MsgSubmitMisbehaviourResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
misbehaviour, err := clienttypes.UnpackMisbehaviour(msg.Misbehaviour)
if err != nil {
return nil, err
}
if err := k.ClientKeeper.CheckMisbehaviourAndUpdateState(ctx, misbehaviour); err != nil {
return nil, sdkerrors.Wrap(err, "failed to process misbehaviour for IBC client")
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
clienttypes.EventTypeSubmitMisbehaviour,
sdk.NewAttribute(clienttypes.AttributeKeyClientID, msg.ClientId),
sdk.NewAttribute(clienttypes.AttributeKeyClientType, misbehaviour.ClientType()),
sdk.NewAttribute(clienttypes.AttributeKeyConsensusHeight, misbehaviour.GetHeight().String()),
),
)
return &clienttypes.MsgSubmitMisbehaviourResponse{}, nil
}
// ConnectionOpenInit defines a rpc handler method for MsgConnectionOpenInit.
func (k Keeper) ConnectionOpenInit(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenInit) (*connectiontypes.MsgConnectionOpenInitResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
if err := k.ConnectionKeeper.ConnOpenInit(
ctx, msg.ConnectionId, msg.ClientId, msg.Counterparty, msg.Version,
); err != nil {
return nil, sdkerrors.Wrap(err, "connection handshake open init failed")
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
connectiontypes.EventTypeConnectionOpenInit,
sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.ConnectionId),
sdk.NewAttribute(connectiontypes.AttributeKeyClientID, msg.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, msg.Counterparty.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, msg.Counterparty.ConnectionId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory),
),
})
return &connectiontypes.MsgConnectionOpenInitResponse{}, nil
}
// ConnectionOpenTry defines a rpc handler method for MsgConnectionOpenTry.
func (k Keeper) ConnectionOpenTry(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenTry) (*connectiontypes.MsgConnectionOpenTryResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
if err != nil {
return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v.", targetClient)
}
if err := k.ConnectionKeeper.ConnOpenTry(
ctx, msg.DesiredConnectionId, msg.CounterpartyChosenConnectionId, msg.Counterparty, msg.ClientId, targetClient,
connectiontypes.ProtoVersionsToExported(msg.CounterpartyVersions), msg.ProofInit, msg.ProofClient, msg.ProofConsensus,
msg.ProofHeight, msg.ConsensusHeight,
); err != nil {
return nil, sdkerrors.Wrap(err, "connection handshake open try failed")
}
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
connectiontypes.EventTypeConnectionOpenTry,
sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.DesiredConnectionId),
sdk.NewAttribute(connectiontypes.AttributeKeyClientID, msg.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, msg.Counterparty.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, msg.Counterparty.ConnectionId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory),
),
})
return &connectiontypes.MsgConnectionOpenTryResponse{}, nil
}
// ConnectionOpenAck defines a rpc handler method for MsgConnectionOpenAck.
func (k Keeper) ConnectionOpenAck(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenAck) (*connectiontypes.MsgConnectionOpenAckResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
targetClient, err := clienttypes.UnpackClientState(msg.ClientState)
if err != nil {
return nil, sdkerrors.Wrapf(err, "client in msg is not exported.ClientState. invalid client: %v", targetClient)
}
if err := k.ConnectionKeeper.ConnOpenAck(
ctx, msg.ConnectionId, targetClient, msg.Version, msg.CounterpartyConnectionId,
msg.ProofTry, msg.ProofClient, msg.ProofConsensus,
msg.ProofHeight, msg.ConsensusHeight,
); err != nil {
return nil, sdkerrors.Wrap(err, "connection handshake open ack failed")
}
connectionEnd, _ := k.ConnectionKeeper.GetConnection(ctx, msg.ConnectionId)
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
connectiontypes.EventTypeConnectionOpenAck,
sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.ConnectionId),
sdk.NewAttribute(connectiontypes.AttributeKeyClientID, connectionEnd.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, connectionEnd.Counterparty.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, connectionEnd.Counterparty.ConnectionId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory),
),
})
return &connectiontypes.MsgConnectionOpenAckResponse{}, nil
}
// ConnectionOpenConfirm defines a rpc handler method for MsgConnectionOpenConfirm.
func (k Keeper) ConnectionOpenConfirm(goCtx context.Context, msg *connectiontypes.MsgConnectionOpenConfirm) (*connectiontypes.MsgConnectionOpenConfirmResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
if err := k.ConnectionKeeper.ConnOpenConfirm(
ctx, msg.ConnectionId, msg.ProofAck, msg.ProofHeight,
); err != nil {
return nil, sdkerrors.Wrap(err, "connection handshake open confirm failed")
}
connectionEnd, _ := k.ConnectionKeeper.GetConnection(ctx, msg.ConnectionId)
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
connectiontypes.EventTypeConnectionOpenConfirm,
sdk.NewAttribute(connectiontypes.AttributeKeyConnectionID, msg.ConnectionId),
sdk.NewAttribute(connectiontypes.AttributeKeyClientID, connectionEnd.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyClientID, connectionEnd.Counterparty.ClientId),
sdk.NewAttribute(connectiontypes.AttributeKeyCounterpartyConnectionID, connectionEnd.Counterparty.ConnectionId),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, connectiontypes.AttributeValueCategory),
),
})
return &connectiontypes.MsgConnectionOpenConfirmResponse{}, nil
}
// ChannelOpenInit defines a rpc handler method for MsgChannelOpenInit.
func (k Keeper) ChannelOpenInit(goCtx context.Context, msg *channeltypes.MsgChannelOpenInit) (*channeltypes.MsgChannelOpenInitResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 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")
}
_, 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)
}
if err = cbs.OnChanOpenInit(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.ChannelId, cap, msg.Channel.Counterparty, msg.Channel.Version); err != nil {
return nil, sdkerrors.Wrap(err, "channel open init callback failed")
}
return &channeltypes.MsgChannelOpenInitResponse{}, nil
}
// ChannelOpenTry defines a rpc handler method for MsgChannelOpenTry.
func (k Keeper) ChannelOpenTry(goCtx context.Context, msg *channeltypes.MsgChannelOpenTry) (*channeltypes.MsgChannelOpenTryResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 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")
}
_, 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)
}
if err = cbs.OnChanOpenTry(ctx, msg.Channel.Ordering, msg.Channel.ConnectionHops, msg.PortId, msg.DesiredChannelId, cap, msg.Channel.Counterparty, msg.Channel.Version, msg.CounterpartyVersion); err != nil {
return nil, sdkerrors.Wrap(err, "channel open try callback failed")
}
return &channeltypes.MsgChannelOpenTryResponse{}, nil
}
// ChannelOpenAck defines a rpc handler method for MsgChannelOpenAck.
func (k Keeper) ChannelOpenAck(goCtx context.Context, msg *channeltypes.MsgChannelOpenAck) (*channeltypes.MsgChannelOpenAckResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 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)
}
if err = cbs.OnChanOpenAck(ctx, msg.PortId, msg.ChannelId, msg.CounterpartyVersion); err != nil {
return nil, sdkerrors.Wrap(err, "channel open ack callback failed")
}
_, err = channel.HandleMsgChannelOpenAck(ctx, k.ChannelKeeper, cap, msg)
if err != nil {
return nil, err
}
return &channeltypes.MsgChannelOpenAckResponse{}, nil
}
// ChannelOpenConfirm defines a rpc handler method for MsgChannelOpenConfirm.
func (k Keeper) ChannelOpenConfirm(goCtx context.Context, msg *channeltypes.MsgChannelOpenConfirm) (*channeltypes.MsgChannelOpenConfirmResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 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)
}
if err = cbs.OnChanOpenConfirm(ctx, msg.PortId, msg.ChannelId); err != nil {
return nil, sdkerrors.Wrap(err, "channel open confirm callback failed")
}
_, err = channel.HandleMsgChannelOpenConfirm(ctx, k.ChannelKeeper, cap, msg)
if err != nil {
return nil, err
}
return &channeltypes.MsgChannelOpenConfirmResponse{}, nil
}
// ChannelCloseInit defines a rpc handler method for MsgChannelCloseInit.
func (k Keeper) ChannelCloseInit(goCtx context.Context, msg *channeltypes.MsgChannelCloseInit) (*channeltypes.MsgChannelCloseInitResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 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)
}
if err = cbs.OnChanCloseInit(ctx, msg.PortId, msg.ChannelId); err != nil {
return nil, sdkerrors.Wrap(err, "channel close init callback failed")
}
_, err = channel.HandleMsgChannelCloseInit(ctx, k.ChannelKeeper, cap, msg)
if err != nil {
return nil, err
}
return &channeltypes.MsgChannelCloseInitResponse{}, nil
}
// ChannelCloseConfirm defines a rpc handler method for MsgChannelCloseConfirm.
func (k Keeper) ChannelCloseConfirm(goCtx context.Context, msg *channeltypes.MsgChannelCloseConfirm) (*channeltypes.MsgChannelCloseConfirmResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 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)
}
if err = cbs.OnChanCloseConfirm(ctx, msg.PortId, msg.ChannelId); err != nil {
return nil, sdkerrors.Wrap(err, "channel close confirm callback failed")
}
_, err = channel.HandleMsgChannelCloseConfirm(ctx, k.ChannelKeeper, cap, msg)
if err != nil {
return nil, err
}
return &channeltypes.MsgChannelCloseConfirmResponse{}, nil
}
// RecvPacket defines a rpc handler method for MsgRecvPacket.
func (k Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacket) (*channeltypes.MsgRecvPacketResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 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 TAO verification
if err := k.ChannelKeeper.RecvPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight); err != nil {
return nil, sdkerrors.Wrap(err, "receive packet verification failed")
}
// Perform application logic callback
_, ack, err := cbs.OnRecvPacket(ctx, msg.Packet)
if err != nil {
return nil, sdkerrors.Wrap(err, "receive packet callback failed")
}
if err := k.ChannelKeeper.WriteReceipt(ctx, cap, msg.Packet); err != nil {
return nil, err
}
// Set packet acknowledgement only if the acknowledgement is not nil.
// NOTE: IBC applications modules may call the WriteAcknowledgement asynchronously if the
// acknowledgement is nil.
if ack != nil {
if err := k.ChannelKeeper.WriteAcknowledgement(ctx, msg.Packet, ack); err != nil {
return nil, err
}
}
defer func() {
telemetry.IncrCounterWithLabels(
[]string{"tx", "msg", "ibc", msg.Type()},
1,
[]metrics.Label{
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
},
)
}()
return &channeltypes.MsgRecvPacketResponse{}, nil
}
// Timeout defines a rpc handler method for MsgTimeout.
func (k Keeper) Timeout(goCtx context.Context, msg *channeltypes.MsgTimeout) (*channeltypes.MsgTimeoutResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 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 TAO verification
if err := k.ChannelKeeper.TimeoutPacket(ctx, msg.Packet, msg.Proof, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
return nil, sdkerrors.Wrap(err, "timeout packet verification failed")
}
// Perform application logic callback
_, 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
}
defer func() {
telemetry.IncrCounterWithLabels(
[]string{"ibc", "timeout", "packet"},
1,
[]metrics.Label{
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
telemetry.NewLabel("timeout-type", "height"),
},
)
}()
return &channeltypes.MsgTimeoutResponse{}, nil
}
// TimeoutOnClose defines a rpc handler method for MsgTimeoutOnClose.
func (k Keeper) TimeoutOnClose(goCtx context.Context, msg *channeltypes.MsgTimeoutOnClose) (*channeltypes.MsgTimeoutOnCloseResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 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 TAO verification
if err := k.ChannelKeeper.TimeoutOnClose(ctx, cap, msg.Packet, msg.Proof, msg.ProofClose, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
return nil, sdkerrors.Wrap(err, "timeout on close packet verification failed")
}
// Perform application logic callback
// NOTE: MsgTimeout and MsgTimeoutOnClose use the same "OnTimeoutPacket"
// application logic callback.
_, 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
}
defer func() {
telemetry.IncrCounterWithLabels(
[]string{"ibc", "timeout", "packet"},
1,
[]metrics.Label{
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
telemetry.NewLabel("timeout-type", "channel-closed"),
},
)
}()
return &channeltypes.MsgTimeoutOnCloseResponse{}, nil
}
// Acknowledgement defines a rpc handler method for MsgAcknowledgement.
func (k Keeper) Acknowledgement(goCtx context.Context, msg *channeltypes.MsgAcknowledgement) (*channeltypes.MsgAcknowledgementResponse, error) {
ctx := sdk.UnwrapSDKContext(goCtx)
// 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 TAO verification
if err := k.ChannelKeeper.AcknowledgePacket(ctx, msg.Packet, msg.Acknowledgement, msg.Proof, msg.ProofHeight); err != nil {
return nil, sdkerrors.Wrap(err, "acknowledge packet verification failed")
}
// Perform application logic callback
_, 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
}
defer func() {
telemetry.IncrCounterWithLabels(
[]string{"tx", "msg", "ibc", msg.Type()},
1,
[]metrics.Label{
telemetry.NewLabel("source-port", msg.Packet.SourcePort),
telemetry.NewLabel("source-channel", msg.Packet.SourceChannel),
telemetry.NewLabel("destination-port", msg.Packet.DestinationPort),
telemetry.NewLabel("destination-channel", msg.Packet.DestinationChannel),
},
)
}()
return &channeltypes.MsgAcknowledgementResponse{}, nil
}