Skip to content

Commit

Permalink
add events for no op messages
Browse files Browse the repository at this point in the history
  • Loading branch information
colin-axner committed Jul 20, 2021
1 parent d7443a5 commit 560ad17
Show file tree
Hide file tree
Showing 4 changed files with 138 additions and 85 deletions.
86 changes: 86 additions & 0 deletions modules/core/04-channel/keeper/events.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package keeper

import (
"encoding/hex"
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/cosmos/ibc-go/modules/core/04-channel/types"
"github.com/cosmos/ibc-go/modules/core/exported"
)

// EmitRecvPacketEvent emits a receive packet event. It will be emitted both the first time a packet
// is received for a certain sequence and for all duplicate receives.
func EmitRecvPacketEvent(ctx sdk.Context, packet exported.PacketI, channel types.Channel) {
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeRecvPacket,
sdk.NewAttribute(types.AttributeKeyData, string(packet.GetData())), // DEPRECATED
sdk.NewAttribute(types.AttributeKeyDataHex, hex.EncodeToString(packet.GetData())),
sdk.NewAttribute(types.AttributeKeyTimeoutHeight, packet.GetTimeoutHeight().String()),
sdk.NewAttribute(types.AttributeKeyTimeoutTimestamp, fmt.Sprintf("%d", packet.GetTimeoutTimestamp())),
sdk.NewAttribute(types.AttributeKeySequence, fmt.Sprintf("%d", packet.GetSequence())),
sdk.NewAttribute(types.AttributeKeySrcPort, packet.GetSourcePort()),
sdk.NewAttribute(types.AttributeKeySrcChannel, packet.GetSourceChannel()),
sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()),
sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()),
sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()),
// we only support 1-hop packets now, and that is the most important hop for a relayer
// (is it going to a chain I am connected to)
sdk.NewAttribute(types.AttributeKeyConnection, channel.ConnectionHops[0]),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
})
}

// EmitAcknowledgePacketEvent emits an acknowledge packet event. It will be emitted both the first time
// a packet is acknowledged for a certain sequence and for all duplicate acknowledgements.
func EmitAcknowledgePacketEvent(ctx sdk.Context, packet exported.PacketI, channel types.Channel) {
// emit an event marking that we have processed the acknowledgement
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeAcknowledgePacket,
sdk.NewAttribute(types.AttributeKeyTimeoutHeight, packet.GetTimeoutHeight().String()),
sdk.NewAttribute(types.AttributeKeyTimeoutTimestamp, fmt.Sprintf("%d", packet.GetTimeoutTimestamp())),
sdk.NewAttribute(types.AttributeKeySequence, fmt.Sprintf("%d", packet.GetSequence())),
sdk.NewAttribute(types.AttributeKeySrcPort, packet.GetSourcePort()),
sdk.NewAttribute(types.AttributeKeySrcChannel, packet.GetSourceChannel()),
sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()),
sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()),
sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()),
// we only support 1-hop packets now, and that is the most important hop for a relayer
// (is it going to a chain I am connected to)
sdk.NewAttribute(types.AttributeKeyConnection, channel.ConnectionHops[0]),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
})
}

// EmitTimeoutPacketEvent emits a timeout packet event. It will be emitted both the first time a packet
// is timed out for a certain sequence and for all duplicate timeouts.
func EmitTimeoutPacketEvent(ctx sdk.Context, packet exported.PacketI, channel types.Channel) {
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeTimeoutPacket,
sdk.NewAttribute(types.AttributeKeyTimeoutHeight, packet.GetTimeoutHeight().String()),
sdk.NewAttribute(types.AttributeKeyTimeoutTimestamp, fmt.Sprintf("%d", packet.GetTimeoutTimestamp())),
sdk.NewAttribute(types.AttributeKeySequence, fmt.Sprintf("%d", packet.GetSequence())),
sdk.NewAttribute(types.AttributeKeySrcPort, packet.GetSourcePort()),
sdk.NewAttribute(types.AttributeKeySrcChannel, packet.GetSourceChannel()),
sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()),
sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()),
sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
})
}
48 changes: 5 additions & 43 deletions modules/core/04-channel/keeper/packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ func (k Keeper) RecvPacket(
// check if the packet receipt has been received already for unordered channels
_, found := k.GetPacketReceipt(ctx, packet.GetDestPort(), packet.GetDestChannel(), packet.GetSequence())
if found {
EmitRecvPacketEvent(ctx, packet, channel)
// This error indicates that the packet has already been relayed. Core IBC will
// treat this error as a no-op in order to prevent an entire relay transaction
// from failing and consuming unnecessary fees.
Expand All @@ -272,6 +273,7 @@ func (k Keeper) RecvPacket(
}

if packet.GetSequence() < nextSequenceRecv {
EmitRecvPacketEvent(ctx, packet, channel)
// This error indicates that the packet has already been relayed. Core IBC will
// treat this error as a no-op in order to prevent an entire relay transaction
// from failing and consuming unnecessary fees.
Expand Down Expand Up @@ -299,28 +301,7 @@ func (k Keeper) RecvPacket(
k.Logger(ctx).Info("packet received", "packet", fmt.Sprintf("%v", packet))

// emit an event that the relayer can query for
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeRecvPacket,
sdk.NewAttribute(types.AttributeKeyData, string(packet.GetData())), // DEPRECATED
sdk.NewAttribute(types.AttributeKeyDataHex, hex.EncodeToString(packet.GetData())),
sdk.NewAttribute(types.AttributeKeyTimeoutHeight, packet.GetTimeoutHeight().String()),
sdk.NewAttribute(types.AttributeKeyTimeoutTimestamp, fmt.Sprintf("%d", packet.GetTimeoutTimestamp())),
sdk.NewAttribute(types.AttributeKeySequence, fmt.Sprintf("%d", packet.GetSequence())),
sdk.NewAttribute(types.AttributeKeySrcPort, packet.GetSourcePort()),
sdk.NewAttribute(types.AttributeKeySrcChannel, packet.GetSourceChannel()),
sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()),
sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()),
sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()),
// we only support 1-hop packets now, and that is the most important hop for a relayer
// (is it going to a chain I am connected to)
sdk.NewAttribute(types.AttributeKeyConnection, channel.ConnectionHops[0]),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
})
EmitRecvPacketEvent(ctx, packet, channel)

return nil
}
Expand Down Expand Up @@ -479,6 +460,7 @@ func (k Keeper) AcknowledgePacket(
commitment := k.GetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())

if len(commitment) == 0 {
EmitAcknowledgePacketEvent(ctx, packet, channel)
// This error indicates that the acknowledgement has already been relayed
// or there is a misconfigured relayer attempting to prove an acknowledgement
// for a packet never sent. Core IBC will treat this error as a no-op in order to
Expand Down Expand Up @@ -532,27 +514,7 @@ func (k Keeper) AcknowledgePacket(
// log that a packet has been acknowledged
k.Logger(ctx).Info("packet acknowledged", "packet", fmt.Sprintf("%v", packet))

// emit an event marking that we have processed the acknowledgement
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeAcknowledgePacket,
sdk.NewAttribute(types.AttributeKeyTimeoutHeight, packet.GetTimeoutHeight().String()),
sdk.NewAttribute(types.AttributeKeyTimeoutTimestamp, fmt.Sprintf("%d", packet.GetTimeoutTimestamp())),
sdk.NewAttribute(types.AttributeKeySequence, fmt.Sprintf("%d", packet.GetSequence())),
sdk.NewAttribute(types.AttributeKeySrcPort, packet.GetSourcePort()),
sdk.NewAttribute(types.AttributeKeySrcChannel, packet.GetSourceChannel()),
sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()),
sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()),
sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()),
// we only support 1-hop packets now, and that is the most important hop for a relayer
// (is it going to a chain I am connected to)
sdk.NewAttribute(types.AttributeKeyConnection, channel.ConnectionHops[0]),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
})
EmitAcknowledgePacketEvent(ctx, packet, channel)

return nil
}
20 changes: 3 additions & 17 deletions modules/core/04-channel/keeper/timeout.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func (k Keeper) TimeoutPacket(
commitment := k.GetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())

if len(commitment) == 0 {
EmitTimeoutPacketEvent(ctx, packet, channel)
// This error indicates that the timeout has already been relayed
// or there is a misconfigured relayer attempting to prove a timeout
// for a packet never sent. Core IBC will treat this error as a no-op in order to
Expand Down Expand Up @@ -159,23 +160,7 @@ func (k Keeper) TimeoutExecuted(
k.Logger(ctx).Info("packet timed-out", "packet", fmt.Sprintf("%v", packet))

// emit an event marking that we have processed the timeout
ctx.EventManager().EmitEvents(sdk.Events{
sdk.NewEvent(
types.EventTypeTimeoutPacket,
sdk.NewAttribute(types.AttributeKeyTimeoutHeight, packet.GetTimeoutHeight().String()),
sdk.NewAttribute(types.AttributeKeyTimeoutTimestamp, fmt.Sprintf("%d", packet.GetTimeoutTimestamp())),
sdk.NewAttribute(types.AttributeKeySequence, fmt.Sprintf("%d", packet.GetSequence())),
sdk.NewAttribute(types.AttributeKeySrcPort, packet.GetSourcePort()),
sdk.NewAttribute(types.AttributeKeySrcChannel, packet.GetSourceChannel()),
sdk.NewAttribute(types.AttributeKeyDstPort, packet.GetDestPort()),
sdk.NewAttribute(types.AttributeKeyDstChannel, packet.GetDestChannel()),
sdk.NewAttribute(types.AttributeKeyChannelOrdering, channel.Ordering.String()),
),
sdk.NewEvent(
sdk.EventTypeMessage,
sdk.NewAttribute(sdk.AttributeKeyModule, types.AttributeValueCategory),
),
})
EmitTimeoutPacketEvent(ctx, packet, channel)

return nil
}
Expand Down Expand Up @@ -227,6 +212,7 @@ func (k Keeper) TimeoutOnClose(
commitment := k.GetPacketCommitment(ctx, packet.GetSourcePort(), packet.GetSourceChannel(), packet.GetSequence())

if len(commitment) == 0 {
EmitTimeoutPacketEvent(ctx, packet, channel)
// This error indicates that the timeout has already been relayed
// or there is a misconfigured relayer attempting to prove a timeout
// for a packet never sent. Core IBC will treat this error as a no-op in order to
Expand Down
69 changes: 44 additions & 25 deletions modules/core/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -496,21 +496,25 @@ func (k Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacke
// If the packet was already received, perform a no-op
// Use a cached context to prevent accidental state changes
cacheCtx, writeFn := ctx.CacheContext()
if err := k.ChannelKeeper.RecvPacket(cacheCtx, cap, msg.Packet, msg.ProofCommitment, msg.ProofHeight); err != nil {
// packet already received
if err == channeltypes.ErrNoOpMsg {
return &channeltypes.MsgRecvPacketResponse{}, nil // no-op
}
err = k.ChannelKeeper.RecvPacket(cacheCtx, cap, msg.Packet, msg.ProofCommitment, msg.ProofHeight)

// NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context.
ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events())

switch err {
case nil:
writeFn()
case channeltypes.ErrNoOpMsg:
return &channeltypes.MsgRecvPacketResponse{}, nil // no-op
default:
return nil, sdkerrors.Wrap(err, "receive packet verification failed")
}
writeFn()

// Perform application logic callback
//
// Cache context so that we may discard state changes from callback if the acknowledgement is unsuccessful.
cacheCtx, writeFn = ctx.CacheContext()
ack := cbs.OnRecvPacket(cacheCtx, msg.Packet, relayer)
// This doesn't cause duplicate events to be emitted.
// NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context.
// Events from callback are emitted regardless of acknowledgement success
ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events())
Expand Down Expand Up @@ -570,14 +574,19 @@ func (k Keeper) Timeout(goCtx context.Context, msg *channeltypes.MsgTimeout) (*c
// If the timeout was already received, perform a no-op
// Use a cached context to prevent accidental state changes
cacheCtx, writeFn := ctx.CacheContext()
if err := k.ChannelKeeper.TimeoutPacket(cacheCtx, msg.Packet, msg.ProofUnreceived, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
// timeout already received
if err == channeltypes.ErrNoOpMsg {
return &channeltypes.MsgTimeoutResponse{}, nil // no-op
}
err = k.ChannelKeeper.TimeoutPacket(cacheCtx, msg.Packet, msg.ProofUnreceived, msg.ProofHeight, msg.NextSequenceRecv)

// NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context.
ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events())

switch err {
case nil:
writeFn()
case channeltypes.ErrNoOpMsg:
return &channeltypes.MsgTimeoutResponse{}, nil // no-op
default:
return nil, sdkerrors.Wrap(err, "timeout packet verification failed")
}
writeFn()

// Perform application logic callback
err = cbs.OnTimeoutPacket(ctx, msg.Packet, relayer)
Expand Down Expand Up @@ -633,14 +642,19 @@ func (k Keeper) TimeoutOnClose(goCtx context.Context, msg *channeltypes.MsgTimeo
// If the timeout was already received, perform a no-op
// Use a cached context to prevent accidental state changes
cacheCtx, writeFn := ctx.CacheContext()
if err := k.ChannelKeeper.TimeoutOnClose(cacheCtx, cap, msg.Packet, msg.ProofUnreceived, msg.ProofClose, msg.ProofHeight, msg.NextSequenceRecv); err != nil {
// timeout already received
if err == channeltypes.ErrNoOpMsg {
return &channeltypes.MsgTimeoutOnCloseResponse{}, nil // no-op
}
err = k.ChannelKeeper.TimeoutOnClose(cacheCtx, cap, msg.Packet, msg.ProofUnreceived, msg.ProofClose, msg.ProofHeight, msg.NextSequenceRecv)

// NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context.
ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events())

switch err {
case nil:
writeFn()
case channeltypes.ErrNoOpMsg:
return &channeltypes.MsgTimeoutOnCloseResponse{}, nil // no-op
default:
return nil, sdkerrors.Wrap(err, "timeout on close packet verification failed")
}
writeFn()

// Perform application logic callback
//
Expand Down Expand Up @@ -699,14 +713,19 @@ func (k Keeper) Acknowledgement(goCtx context.Context, msg *channeltypes.MsgAckn
// If the acknowledgement was already received, perform a no-op
// Use a cached context to prevent accidental state changes
cacheCtx, writeFn := ctx.CacheContext()
if err := k.ChannelKeeper.AcknowledgePacket(cacheCtx, cap, msg.Packet, msg.Acknowledgement, msg.ProofAcked, msg.ProofHeight); err != nil {
// acknowledgement already received
if err == channeltypes.ErrNoOpMsg {
return &channeltypes.MsgAcknowledgementResponse{}, nil // no-op
}
err = k.ChannelKeeper.AcknowledgePacket(cacheCtx, cap, msg.Packet, msg.Acknowledgement, msg.ProofAcked, msg.ProofHeight)

// NOTE: The context returned by CacheContext() refers to a new EventManager, so it needs to explicitly set events to the original context.
ctx.EventManager().EmitEvents(cacheCtx.EventManager().Events())

switch err {
case nil:
writeFn()
case channeltypes.ErrNoOpMsg:
return &channeltypes.MsgAcknowledgementResponse{}, nil // no-op
default:
return nil, sdkerrors.Wrap(err, "acknowledge packet verification failed")
}
writeFn()

// Perform application logic callback
err = cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement, relayer)
Expand Down

0 comments on commit 560ad17

Please sign in to comment.