@@ -2,6 +2,7 @@ package ante
22
33import (
44 sdk "github.com/cosmos/cosmos-sdk/types"
5+ sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
56
67 clienttypes "github.com/cosmos/ibc-go/v7/modules/core/02-client/types"
78 channeltypes "github.com/cosmos/ibc-go/v7/modules/core/04-channel/types"
@@ -30,10 +31,22 @@ func (rrd RedundantRelayDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
3031 for _ , m := range tx .GetMsgs () {
3132 switch msg := m .(type ) {
3233 case * channeltypes.MsgRecvPacket :
33- response , err := rrd .k .RecvPacket (sdk .WrapSDKContext (ctx ), msg )
34+ var (
35+ response * channeltypes.MsgRecvPacketResponse
36+ err error
37+ )
38+ // when we are in ReCheckTx mode, ctx.IsCheckTx() will also return true
39+ // there we must start the if statement on ctx.IsReCheckTx() to correctly
40+ // determine which mode we are in
41+ if ctx .IsReCheckTx () {
42+ response , err = rrd .k .RecvPacket (sdk .WrapSDKContext (ctx ), msg )
43+ } else {
44+ response , err = rrd .recvPacketCheckTx (ctx , msg )
45+ }
3446 if err != nil {
3547 return ctx , err
3648 }
49+
3750 if response .Result == channeltypes .NOOP {
3851 redundancies ++
3952 }
@@ -90,3 +103,29 @@ func (rrd RedundantRelayDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
90103 }
91104 return next (ctx , tx , simulate )
92105}
106+
107+ // recvPacketCheckTx runs a subset of ibc recv packet logic to be used specifically within the RedundantRelayDecorator AnteHandler.
108+ // It only performs core IBC receiving logic and skips any application logic.
109+ func (rrd RedundantRelayDecorator ) recvPacketCheckTx (ctx sdk.Context , msg * channeltypes.MsgRecvPacket ) (* channeltypes.MsgRecvPacketResponse , error ) {
110+ // grab channel capability
111+ _ , capability , err := rrd .k .ChannelKeeper .LookupModuleByChannel (ctx , msg .Packet .DestinationPort , msg .Packet .DestinationChannel )
112+ if err != nil {
113+ return nil , sdkerrors .Wrap (err , "could not retrieve module from port-id" )
114+ }
115+
116+ // If the packet was already received, perform a no-op
117+ // Use a cached context to prevent accidental state changes
118+ cacheCtx , writeFn := ctx .CacheContext ()
119+ err = rrd .k .ChannelKeeper .RecvPacket (cacheCtx , capability , msg .Packet , msg .ProofCommitment , msg .ProofHeight )
120+
121+ switch err {
122+ case nil :
123+ writeFn ()
124+ case channeltypes .ErrNoOpMsg :
125+ return & channeltypes.MsgRecvPacketResponse {Result : channeltypes .NOOP }, nil
126+ default :
127+ return nil , sdkerrors .Wrap (err , "receive packet verification failed" )
128+ }
129+
130+ return & channeltypes.MsgRecvPacketResponse {Result : channeltypes .SUCCESS }, nil
131+ }
0 commit comments