github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/core/ante/ante.go (about) 1 package ante 2 3 import ( 4 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 5 clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types" 6 channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types" 7 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/keeper" 8 "github.com/fibonacci-chain/fbc/libs/tendermint/types" 9 ) 10 11 type AnteDecorator struct { 12 k keeper.IBCServerKeeper 13 } 14 15 func NewAnteDecorator(k keeper.IBCServerKeeper) AnteDecorator { 16 return AnteDecorator{k: k} 17 } 18 19 // AnteDecorator returns an error if a multiMsg tx only contains packet messages (Recv, Ack, Timeout) and additional update messages and all packet messages 20 // are redundant. If the transaction is just a single UpdateClient message, or the multimsg transaction contains some other message type, then the antedecorator returns no error 21 // and continues processing to ensure these transactions are included. 22 // This will ensure that relayers do not waste fees on multiMsg transactions when another relayer has already submitted all packets, by rejecting the tx at the mempool layer. 23 func (ad AnteDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { 24 if !types.HigherThanVenus1(ctx.BlockHeight()) { 25 return next(ctx, tx, simulate) 26 } 27 if types.HigherThanVenus4(ctx.BlockHeight()) { 28 return ad.v4(ctx, tx, simulate, next) 29 } 30 // do not run redundancy check on DeliverTx or simulate 31 if (ctx.IsCheckTx() || ctx.IsReCheckTx()) && !simulate { 32 // keep track of total packet messages and number of redundancies across `RecvPacket`, `AcknowledgePacket`, and `TimeoutPacket/OnClose` 33 redundancies := 0 34 packetMsgs := 0 35 for _, m := range tx.GetMsgs() { 36 switch msg := m.(type) { 37 case *channeltypes.MsgRecvPacket: 38 39 if _, found := ad.k.GetPacketReceipt(ctx, msg.Packet.GetDestPort(), msg.Packet.GetDestChannel(), msg.Packet.GetSequence()); found { 40 redundancies += 1 41 } 42 packetMsgs += 1 43 44 case *channeltypes.MsgAcknowledgement: 45 if commitment := ad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { 46 redundancies += 1 47 } 48 packetMsgs += 1 49 50 case *channeltypes.MsgTimeout: 51 if commitment := ad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { 52 redundancies += 1 53 } 54 packetMsgs += 1 55 56 case *channeltypes.MsgTimeoutOnClose: 57 if commitment := ad.k.GetPacketCommitment(ctx, msg.Packet.GetSourcePort(), msg.Packet.GetSourceChannel(), msg.Packet.GetSequence()); len(commitment) == 0 { 58 redundancies += 1 59 } 60 packetMsgs += 1 61 62 case *clienttypes.MsgUpdateClient: 63 // do nothing here, as we want to avoid updating clients if it is batched with only redundant messages 64 65 default: 66 // if the multiMsg tx has a msg that is not a packet msg or update msg, then we will not return error 67 // regardless of if all packet messages are redundant. This ensures that non-packet messages get processed 68 // even if they get batched with redundant packet messages. 69 return next(ctx, tx, simulate) 70 } 71 72 } 73 74 // only return error if all packet messages are redundant 75 if redundancies == packetMsgs && packetMsgs > 0 { 76 return ctx, channeltypes.ErrRedundantTx 77 } 78 } 79 return next(ctx, tx, simulate) 80 } 81 82 func (ad AnteDecorator) v4(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) { 83 // do not run redundancy check on DeliverTx or simulate 84 if (ctx.IsCheckTx() || ctx.IsReCheckTx()) && !simulate { 85 // keep track of total packet messages and number of redundancies across `RecvPacket`, `AcknowledgePacket`, and `TimeoutPacket/OnClose` 86 redundancies := 0 87 packetMsgs := 0 88 for _, m := range tx.GetMsgs() { 89 switch msg := m.(type) { 90 case *channeltypes.MsgRecvPacket: 91 response, err := ad.k.RecvPacket(sdk.WrapSDKContext(ctx), msg) 92 if err != nil { 93 return ctx, err 94 } 95 if response.Result == channeltypes.NOOP { 96 redundancies += 1 97 } 98 packetMsgs += 1 99 100 case *channeltypes.MsgAcknowledgement: 101 response, err := ad.k.Acknowledgement(sdk.WrapSDKContext(ctx), msg) 102 if err != nil { 103 return ctx, err 104 } 105 if response.Result == channeltypes.NOOP { 106 redundancies += 1 107 } 108 packetMsgs += 1 109 110 case *channeltypes.MsgTimeout: 111 response, err := ad.k.Timeout(sdk.WrapSDKContext(ctx), msg) 112 if err != nil { 113 return ctx, err 114 } 115 if response.Result == channeltypes.NOOP { 116 redundancies += 1 117 } 118 packetMsgs += 1 119 120 case *channeltypes.MsgTimeoutOnClose: 121 response, err := ad.k.TimeoutOnClose(sdk.WrapSDKContext(ctx), msg) 122 if err != nil { 123 return ctx, err 124 } 125 if response.Result == channeltypes.NOOP { 126 redundancies += 1 127 } 128 packetMsgs += 1 129 130 case *clienttypes.MsgUpdateClient: 131 _, err := ad.k.UpdateClient(sdk.WrapSDKContext(ctx), msg) 132 if err != nil { 133 return ctx, err 134 } 135 136 default: 137 // if the multiMsg tx has a msg that is not a packet msg or update msg, then we will not return error 138 // regardless of if all packet messages are redundant. This ensures that non-packet messages get processed 139 // even if they get batched with redundant packet messages. 140 return next(ctx, tx, simulate) 141 } 142 } 143 144 // only return error if all packet messages are redundant 145 if redundancies == packetMsgs && packetMsgs > 0 { 146 return ctx, channeltypes.ErrRedundantTx 147 } 148 } 149 return next(ctx, tx, simulate) 150 }