forked from cerc-io/laconicd-deprecated
fix: GasMeter reset in AnteHandler EthGasConsumeDecorator (#964)
* Fix GasMeter reset in AnteHandler - EthGasConsumeDecorator Conforming to the spec: https://github.com/cosmos/cosmos-sdk/blob/e7066c4271ff3d33dc426dc6313c82a1201ae3c6/docs/basics/gas-fees.md > Set newCtx.GasMeter to 0, with a limit of GasWanted. > This step is extremely important, as it not only makes sure the transaction cannot consume infinite gas, > but also that ctx.GasMeter is reset in-between each DeliverTx > (ctx is set to newCtx after anteHandler is run, and the anteHandler is run each time DeliverTx is called). * Compute gasWanted in ante handler based on msg gas * Tests - check gas meter limit after EthGasConsumeDecorator ante handler runs * Update CHANGELOG.md * EthGasConsumeDecorator ante handler resets the gas meter only for CheckTx * Reset the gas meter in Keeper.EthereumTx to an infinite gas meter * Fix TestOutOfGasWhenDeployContract error check * Move gas meter reset to the innermost EthAnteHandle * add NewInfiniteGasMeterWithLimit for setting the user provided gas limit Fixes block's consumed gas calculation in the block creation phase. * Fix lint * Fix lint Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
co-authored by
Federico Kunze Küllmer
parent
805b2eada5
commit
77d9e29923
@@ -159,6 +159,7 @@ func NewEthGasConsumeDecorator(
|
||||
// - transaction's gas limit is lower than the intrinsic gas
|
||||
// - user doesn't have enough balance to deduct the transaction fees (gas_limit * gas_price)
|
||||
// - transaction or block gas meter runs out of gas
|
||||
// - sets the gas meter limit
|
||||
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
params := egcd.evmKeeper.GetParams(ctx)
|
||||
|
||||
@@ -169,6 +170,7 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
||||
istanbul := ethCfg.IsIstanbul(blockHeight)
|
||||
london := ethCfg.IsLondon(blockHeight)
|
||||
evmDenom := params.EvmDenom
|
||||
gasWanted := uint64(0)
|
||||
|
||||
var events sdk.Events
|
||||
|
||||
@@ -182,6 +184,7 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
||||
if err != nil {
|
||||
return ctx, sdkerrors.Wrap(err, "failed to unpack tx data")
|
||||
}
|
||||
gasWanted += txData.GetGas()
|
||||
|
||||
fees, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
|
||||
ctx,
|
||||
@@ -213,6 +216,11 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
||||
gasPool.ConsumeGas(ctx.GasMeter().GasConsumedToLimit(), "gas pool check")
|
||||
}
|
||||
|
||||
// Set ctx.GasMeter with a limit of GasWanted (gasLimit)
|
||||
gasConsumed := ctx.GasMeter().GasConsumed()
|
||||
ctx = ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted))
|
||||
ctx.GasMeter().ConsumeGas(gasConsumed, "copy gas consumed")
|
||||
|
||||
// we know that we have enough gas on the pool to cover the intrinsic gas
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
+14
-4
@@ -205,10 +205,12 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
|
||||
addr := tests.GenerateAddress()
|
||||
|
||||
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil)
|
||||
txGasLimit := uint64(1000)
|
||||
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), txGasLimit, big.NewInt(1), nil, nil, nil, nil)
|
||||
tx.From = addr.Hex()
|
||||
|
||||
tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000000, big.NewInt(1), nil, nil, nil, ðtypes.AccessList{{Address: addr, StorageKeys: nil}})
|
||||
tx2GasLimit := uint64(1000000)
|
||||
tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx2GasLimit, big.NewInt(1), nil, nil, nil, ðtypes.AccessList{{Address: addr, StorageKeys: nil}})
|
||||
tx2.From = addr.Hex()
|
||||
|
||||
var vmdb *statedb.StateDB
|
||||
@@ -216,32 +218,37 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
testCases := []struct {
|
||||
name string
|
||||
tx sdk.Tx
|
||||
gasLimit uint64
|
||||
malleate func()
|
||||
expPass bool
|
||||
expPanic bool
|
||||
}{
|
||||
{"invalid transaction type", &invalidTx{}, func() {}, false, false},
|
||||
{"invalid transaction type", &invalidTx{}, 0, func() {}, false, false},
|
||||
{
|
||||
"sender not found",
|
||||
evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
|
||||
0,
|
||||
func() {},
|
||||
false, false,
|
||||
},
|
||||
{
|
||||
"gas limit too low",
|
||||
tx,
|
||||
0,
|
||||
func() {},
|
||||
false, false,
|
||||
},
|
||||
{
|
||||
"not enough balance for fees",
|
||||
tx2,
|
||||
0,
|
||||
func() {},
|
||||
false, false,
|
||||
},
|
||||
{
|
||||
"not enough tx gas",
|
||||
tx2,
|
||||
0,
|
||||
func() {
|
||||
vmdb.AddBalance(addr, big.NewInt(1000000))
|
||||
},
|
||||
@@ -250,6 +257,7 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
{
|
||||
"not enough block gas",
|
||||
tx2,
|
||||
0,
|
||||
func() {
|
||||
vmdb.AddBalance(addr, big.NewInt(1000000))
|
||||
|
||||
@@ -260,6 +268,7 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
{
|
||||
"success",
|
||||
tx2,
|
||||
tx2GasLimit,
|
||||
func() {
|
||||
vmdb.AddBalance(addr, big.NewInt(1000000))
|
||||
|
||||
@@ -282,12 +291,13 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
return
|
||||
}
|
||||
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
|
||||
ctx, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewInfiniteGasMeter()), tc.tx, false, nextFn)
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
suite.Require().Equal(tc.gasLimit, ctx.GasMeter().Limit())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user