github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/auth/ante/basic.go (about)

     1  package ante
     2  
     3  import (
     4  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     5  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
     6  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/keeper"
     7  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/types"
     8  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto"
     9  	"github.com/fibonacci-chain/fbc/libs/tendermint/crypto/multisig"
    10  )
    11  
    12  var (
    13  	_ TxWithMemo = (*types.StdTx)(nil) // assert StdTx implements TxWithMemo
    14  )
    15  
    16  // ValidateBasicDecorator will call tx.ValidateBasic and return any non-nil error.
    17  // If ValidateBasic passes, decorator calls next AnteHandler in chain. Note,
    18  // ValidateBasicDecorator decorator will not get executed on ReCheckTx since it
    19  // is not dependent on application state.
    20  type ValidateBasicDecorator struct{}
    21  
    22  func NewValidateBasicDecorator() ValidateBasicDecorator {
    23  	return ValidateBasicDecorator{}
    24  }
    25  
    26  func (vbd ValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
    27  	// simulate means 'eth_call' or 'eth_estimateGas', when it means 'eth_estimateGas' we can not 'VerifySig'.so skip here
    28  	if simulate {
    29  		return next(ctx, tx, simulate)
    30  	}
    31  
    32  	trc := ctx.AnteTracer()
    33  	if trc != nil {
    34  		trc.RepeatingPin("ValidateBasicDecorator")
    35  	}
    36  
    37  	// no need to validate basic on recheck tx, call next antehandler
    38  	if ctx.IsReCheckTx() {
    39  		return next(ctx, tx, simulate)
    40  	}
    41  	if err := tx.ValidateBasic(); err != nil {
    42  		return ctx, err
    43  	}
    44  	return next(ctx, tx, simulate)
    45  }
    46  
    47  // Tx must have GetMemo() method to use ValidateMemoDecorator
    48  type TxWithMemo interface {
    49  	sdk.Tx
    50  	GetMemo() string
    51  }
    52  
    53  // ValidateMemoDecorator will validate memo given the parameters passed in
    54  // If memo is too large decorator returns with error, otherwise call next AnteHandler
    55  // CONTRACT: Tx must implement TxWithMemo interface
    56  type ValidateMemoDecorator struct {
    57  	ak keeper.AccountKeeper
    58  }
    59  
    60  func NewValidateMemoDecorator(ak keeper.AccountKeeper) ValidateMemoDecorator {
    61  	return ValidateMemoDecorator{
    62  		ak: ak,
    63  	}
    64  }
    65  
    66  func (vmd ValidateMemoDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
    67  	memoTx, ok := tx.(TxWithMemo)
    68  	if !ok {
    69  		return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid transaction type")
    70  	}
    71  
    72  	params := vmd.ak.GetParams(ctx)
    73  
    74  	memoLength := len(memoTx.GetMemo())
    75  	if uint64(memoLength) > params.MaxMemoCharacters {
    76  		return ctx, sdkerrors.Wrapf(sdkerrors.ErrMemoTooLarge,
    77  			"maximum number of characters is %d but received %d characters",
    78  			params.MaxMemoCharacters, memoLength,
    79  		)
    80  	}
    81  
    82  	return next(ctx, tx, simulate)
    83  }
    84  
    85  // ValidateMsgDecorator will validate msg with special requirement
    86  //type ValidateMsgDecorator struct {
    87  //	validateMsgHandler ValidateMsgHandler
    88  //}
    89  //
    90  //func NewValidateMsgDecorator(validateMsgHandler ValidateMsgHandler) ValidateMsgDecorator {
    91  //	return ValidateMsgDecorator{
    92  //		validateMsgHandler: validateMsgHandler,
    93  //	}
    94  //}
    95  //
    96  //func (vmd ValidateMsgDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
    97  //	// *ABORT* the tx in case of failing to validate it in checkTx mode
    98  //	if ctx.IsCheckTx() && !simulate && vmd.validateMsgHandler != nil {
    99  //		if err := vmd.validateMsgHandler(ctx, tx.GetMsgs()); err != nil {
   100  //			return ctx, err
   101  //		}
   102  //	}
   103  //	return next(ctx, tx, simulate)
   104  //}
   105  
   106  // ConsumeTxSizeGasDecorator will take in parameters and consume gas proportional
   107  // to the size of tx before calling next AnteHandler. Note, the gas costs will be
   108  // slightly over estimated due to the fact that any given signing account may need
   109  // to be retrieved from state.
   110  //
   111  // CONTRACT: If simulate=true, then signatures must either be completely filled
   112  // in or empty.
   113  // CONTRACT: To use this decorator, signatures of transaction must be represented
   114  // as types.StdSignature otherwise simulate mode will incorrectly estimate gas cost.
   115  type ConsumeTxSizeGasDecorator struct {
   116  	ak keeper.AccountKeeper
   117  }
   118  
   119  func NewConsumeGasForTxSizeDecorator(ak keeper.AccountKeeper) ConsumeTxSizeGasDecorator {
   120  	return ConsumeTxSizeGasDecorator{
   121  		ak: ak,
   122  	}
   123  }
   124  
   125  func (cgts ConsumeTxSizeGasDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
   126  	sigTx, ok := tx.(SigVerifiableTx)
   127  	if !ok {
   128  		return ctx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "invalid tx type")
   129  	}
   130  	params := cgts.ak.GetParams(ctx)
   131  	ctx.GasMeter().ConsumeGas(params.TxSizeCostPerByte*sdk.Gas(len(ctx.TxBytes())), "txSize")
   132  
   133  	// simulate gas cost for signatures in simulate mode
   134  	if simulate {
   135  		// in simulate mode, each element should be a nil signature
   136  		sigs := sigTx.GetSignatures()
   137  		for i, signer := range sigTx.GetSigners() {
   138  			// if signature is already filled in, no need to simulate gas cost
   139  			if sigs[i] != nil {
   140  				continue
   141  			}
   142  			acc := cgts.ak.GetAccount(ctx, signer)
   143  
   144  			var pubkey crypto.PubKey
   145  			// use placeholder simSecp256k1Pubkey if sig is nil
   146  			if acc == nil || acc.GetPubKey() == nil {
   147  				pubkey = simSecp256k1Pubkey
   148  			} else {
   149  				pubkey = acc.GetPubKey()
   150  			}
   151  			// use stdsignature to mock the size of a full signature
   152  			simSig := types.StdSignature{
   153  				Signature: simSecp256k1Sig[:],
   154  				PubKey:    pubkey,
   155  			}
   156  			sigBz := types.ModuleCdc.MustMarshalBinaryLengthPrefixed(simSig)
   157  			cost := sdk.Gas(len(sigBz) + 6)
   158  
   159  			// If the pubkey is a multi-signature pubkey, then we estimate for the maximum
   160  			// number of signers.
   161  			if _, ok := pubkey.(multisig.PubKeyMultisigThreshold); ok {
   162  				cost *= params.TxSigLimit
   163  			}
   164  
   165  			ctx.GasMeter().ConsumeGas(params.TxSizeCostPerByte*cost, "txSize")
   166  		}
   167  	}
   168  
   169  	return next(ctx, tx, simulate)
   170  }