github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/app/ante/NonceVerificationDecorator.go (about) 1 package ante 2 3 import ( 4 "github.com/ethereum/go-ethereum/common" 5 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/baseapp" 6 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 7 sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors" 8 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth" 9 evmtypes "github.com/fibonacci-chain/fbc/x/evm/types" 10 ) 11 12 // NonceVerificationDecorator checks that the account nonce from the transaction matches 13 // the sender account sequence. 14 type NonceVerificationDecorator struct { 15 ak auth.AccountKeeper 16 } 17 18 // NewNonceVerificationDecorator creates a new NonceVerificationDecorator 19 func NewNonceVerificationDecorator(ak auth.AccountKeeper) NonceVerificationDecorator { 20 return NonceVerificationDecorator{ 21 ak: ak, 22 } 23 } 24 25 // AnteHandle validates that the transaction nonce is valid (equivalent to the sender account’s 26 // current nonce). 27 func (nvd NonceVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) { 28 if simulate { 29 return next(ctx, tx, simulate) 30 } 31 32 pinAnte(ctx.AnteTracer(), "NonceVerificationDecorator") 33 msgEthTx, ok := tx.(*evmtypes.MsgEthereumTx) 34 if !ok { 35 return ctx, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "invalid transaction type: %T", tx) 36 } 37 38 if ctx.From() != "" { 39 msgEthTx.SetFrom(ctx.From()) 40 } 41 // sender address should be in the tx cache from the previous AnteHandle call 42 address := msgEthTx.AccountAddress() 43 if address.Empty() { 44 panic("sender address cannot be empty") 45 } 46 47 acc := nvd.ak.GetAccount(ctx, address) 48 if acc == nil { 49 return ctx, sdkerrors.Wrapf( 50 sdkerrors.ErrUnknownAddress, 51 "account %s (%s) is nil", common.BytesToAddress(address.Bytes()), address, 52 ) 53 } 54 55 seq := acc.GetSequence() 56 // if multiple transactions are submitted in succession with increasing nonces, 57 // all will be rejected except the first, since the first needs to be included in a block 58 // before the sequence increments 59 if ctx.IsCheckTx() { 60 ctx.SetAccountNonce(seq) 61 // will be checkTx and RecheckTx mode 62 if ctx.IsReCheckTx() { 63 // recheckTx mode 64 65 // sequence must strictly increasing 66 if msgEthTx.Data.AccountNonce != seq { 67 return ctx, sdkerrors.Wrapf( 68 sdkerrors.ErrInvalidSequence, 69 "invalid nonce; got %d, expected %d", msgEthTx.Data.AccountNonce, seq, 70 ) 71 } 72 } else { 73 if baseapp.IsMempoolEnablePendingPool() { 74 if msgEthTx.Data.AccountNonce < seq { 75 return ctx, sdkerrors.Wrapf( 76 sdkerrors.ErrInvalidSequence, 77 "invalid nonce; got %d, expected %d", 78 msgEthTx.Data.AccountNonce, seq, 79 ) 80 } 81 } else { 82 // checkTx mode 83 checkTxModeNonce := seq 84 85 if !baseapp.IsMempoolEnableRecheck() { 86 // if is enable recheck, the sequence of checkState will increase after commit(), so we do not need 87 // to add pending txs len in the mempool. 88 // but, if disable recheck, we will not increase sequence of checkState (even in force recheck case, we 89 // will also reset checkState), so we will need to add pending txs len to get the right nonce 90 gPool := baseapp.GetGlobalMempool() 91 if gPool != nil { 92 addr := evmtypes.EthAddressStringer(common.BytesToAddress(msgEthTx.AccountAddress().Bytes())).String() 93 if pendingNonce, ok := gPool.GetPendingNonce(addr); ok { 94 checkTxModeNonce = pendingNonce + 1 95 } 96 } 97 } 98 99 if baseapp.IsMempoolEnableSort() { 100 if msgEthTx.Data.AccountNonce < seq || msgEthTx.Data.AccountNonce > checkTxModeNonce { 101 return ctx, sdkerrors.Wrapf( 102 sdkerrors.ErrInvalidSequence, 103 "invalid nonce; got %d, expected in the range of [%d, %d]", 104 msgEthTx.Data.AccountNonce, seq, checkTxModeNonce, 105 ) 106 } 107 } else { 108 if msgEthTx.Data.AccountNonce != checkTxModeNonce { 109 return ctx, sdkerrors.Wrapf( 110 sdkerrors.ErrInvalidSequence, 111 "invalid nonce; got %d, expected %d", 112 msgEthTx.Data.AccountNonce, checkTxModeNonce, 113 ) 114 } 115 } 116 } 117 } 118 } else { 119 // only deliverTx mode 120 if msgEthTx.Data.AccountNonce != seq { 121 return ctx, sdkerrors.Wrapf( 122 sdkerrors.ErrInvalidSequence, 123 "invalid nonce; got %d, expected %d", msgEthTx.Data.AccountNonce, seq, 124 ) 125 } 126 } 127 128 return next(ctx, tx, simulate) 129 }