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  }