-
Notifications
You must be signed in to change notification settings - Fork 650
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perform a no-op on redundant relay messages #268
Changes from 2 commits
0ffbcec
990d6a8
59ad180
f45469f
31a55f4
beb3d46
d7443a5
560ad17
c23ae39
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -492,13 +492,23 @@ func (k Keeper) RecvPacket(goCtx context.Context, msg *channeltypes.MsgRecvPacke | |
} | ||
|
||
// Perform TAO verification | ||
if err := k.ChannelKeeper.RecvPacket(ctx, cap, msg.Packet, msg.ProofCommitment, msg.ProofHeight); err != nil { | ||
// | ||
// If the packet was already received we want to perform a no-op | ||
// Use a cached context to prevent accidental state changes | ||
cacheCtx, writeFn := ctx.CacheContext() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this seems like the best solution to me. I need to return before performing the application callbacks, but I also don't want to skip some of the earlier IBC checks in case the sender misconfigured their msg (used wrong channel id or something like that). I also don't want to allow state changes to slip through |
||
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 | ||
} | ||
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() | ||
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. | ||
|
@@ -556,9 +566,18 @@ func (k Keeper) Timeout(goCtx context.Context, msg *channeltypes.MsgTimeout) (*c | |
} | ||
|
||
// Perform TAO verification | ||
if err := k.ChannelKeeper.TimeoutPacket(ctx, msg.Packet, msg.ProofUnreceived, msg.ProofHeight, msg.NextSequenceRecv); err != nil { | ||
// | ||
// 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 | ||
} | ||
return nil, sdkerrors.Wrap(err, "timeout packet verification failed") | ||
} | ||
writeFn() | ||
|
||
// Perform application logic callback | ||
err = cbs.OnTimeoutPacket(ctx, msg.Packet, relayer) | ||
|
@@ -610,11 +629,21 @@ func (k Keeper) TimeoutOnClose(goCtx context.Context, msg *channeltypes.MsgTimeo | |
} | ||
|
||
// Perform TAO verification | ||
if err := k.ChannelKeeper.TimeoutOnClose(ctx, cap, msg.Packet, msg.ProofUnreceived, msg.ProofClose, msg.ProofHeight, msg.NextSequenceRecv); err != nil { | ||
// | ||
// 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 | ||
} | ||
return nil, sdkerrors.Wrap(err, "timeout on close packet verification failed") | ||
} | ||
writeFn() | ||
|
||
// Perform application logic callback | ||
// | ||
// NOTE: MsgTimeout and MsgTimeoutOnClose use the same "OnTimeoutPacket" | ||
// application logic callback. | ||
err = cbs.OnTimeoutPacket(ctx, msg.Packet, relayer) | ||
|
@@ -666,9 +695,18 @@ func (k Keeper) Acknowledgement(goCtx context.Context, msg *channeltypes.MsgAckn | |
} | ||
|
||
// Perform TAO verification | ||
if err := k.ChannelKeeper.AcknowledgePacket(ctx, cap, msg.Packet, msg.Acknowledgement, msg.ProofAcked, msg.ProofHeight); err != nil { | ||
// | ||
// If the acknowledgement was already received we want to 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 | ||
} | ||
return nil, sdkerrors.Wrap(err, "acknowledge packet verification failed") | ||
} | ||
writeFn() | ||
|
||
// Perform application logic callback | ||
err = cbs.OnAcknowledgementPacket(ctx, msg.Packet, msg.Acknowledgement, relayer) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a packet is timed out on an ordered channel, all future timeout packets need to be timed out via timeout on close (since the channel is closed). I want this "channel closed" error message to be sent to relayers only when the relay isn't redundant (packet commitment doesn't exist). Thus I moved it below the redundant check
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so if there's a redundant timeout for the first timed out packet on an ORDERED channel, the relayer gets a no-op rather than this error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's correct. When I did the change though I was thinking more packets would return a no op here. I'm fine to revert this in order to keep consistency with the spec. Thoughts?