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

     1  package ante
     2  
     3  import (
     4  	"fmt"
     5  
     6  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     7  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
     8  )
     9  
    10  // SetUpContextDecorator sets the GasMeter in the Context and wraps the next AnteHandler with a defer clause
    11  // to recover from any downstream OutOfGas panics in the AnteHandler chain to return an error with information
    12  // on gas provided and gas used.
    13  // CONTRACT: Must be first decorator in the chain
    14  // CONTRACT: Tx must implement GasTx interface
    15  type SetUpContextDecorator struct{}
    16  
    17  func NewSetUpContextDecorator() SetUpContextDecorator {
    18  	return SetUpContextDecorator{}
    19  }
    20  
    21  func (sud SetUpContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
    22  	// all transactions must implement GasTx
    23  	gasTx := tx
    24  
    25  	SetGasMeter(simulate, &ctx, gasTx.GetGas())
    26  	newCtx = ctx
    27  
    28  	// Decorator will catch an OutOfGasPanic caused in the next antehandler
    29  	// AnteHandlers must have their own defer/recover in order for the BaseApp
    30  	// to know how much gas was used! This is because the GasMeter is created in
    31  	// the AnteHandler, but if it panics the context won't be set properly in
    32  	// runTx's recover call.
    33  	defer func() {
    34  		if r := recover(); r != nil {
    35  			switch rType := r.(type) {
    36  			case sdk.ErrorOutOfGas:
    37  				log := fmt.Sprintf(
    38  					"out of gas in location: %v; gasWanted: %d, gasUsed: %d",
    39  					rType.Descriptor, gasTx.GetGas(), newCtx.GasMeter().GasConsumed())
    40  
    41  				err = sdkerrors.Wrap(sdkerrors.ErrOutOfGas, log)
    42  			default:
    43  				panic(r)
    44  			}
    45  		}
    46  	}()
    47  
    48  	return next(newCtx, tx, simulate)
    49  }
    50  
    51  // SetGasMeter update context with a gas meter with gasLimit
    52  func SetGasMeter(simulate bool, ctx *sdk.Context, gasLimit uint64) {
    53  	// In various cases such as simulation and during the genesis block, we do not
    54  	// meter any gas utilization.
    55  	if simulate || ctx.BlockHeight() == 0 {
    56  		ctx.SetGasMeter(sdk.NewInfiniteGasMeter())
    57  		return
    58  	}
    59  
    60  	ctx.SetGasMeter(sdk.NewGasMeter(gasLimit))
    61  	return
    62  }