forked from cerc-io/laconicd-deprecated
ante, evm: update gas consumption logic (#178)
* clean up logic by ignoring cosmos gas meter * set gas used in txResponse * reset and set the gas in context * rename ante handler * fix refundedgas logic * remove gas update logic in keeper * update context in keeper * add test for EthSetupContextDecorator * fix broken test due to gas logic change
This commit is contained in:
+1
-1
@@ -60,7 +60,7 @@ func NewAnteHandler(
|
||||
// handle as *evmtypes.MsgEthereumTx
|
||||
|
||||
anteHandler = sdk.ChainAnteDecorators(
|
||||
authante.NewSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
|
||||
NewEthSetUpContextDecorator(), // outermost AnteDecorator. SetUpContext must be called first
|
||||
authante.NewMempoolFeeDecorator(),
|
||||
authante.NewTxTimeoutHeightDecorator(),
|
||||
authante.NewValidateMemoDecorator(ak),
|
||||
|
||||
+38
-48
@@ -56,13 +56,9 @@ func (esvd EthSigVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, s
|
||||
)
|
||||
}
|
||||
|
||||
// get and set account must be called with an infinite gas meter in order to prevent
|
||||
// additional gas from being deducted.
|
||||
infCtx := ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
|
||||
chainID := esvd.evmKeeper.ChainID()
|
||||
|
||||
config, found := esvd.evmKeeper.GetChainConfig(infCtx)
|
||||
config, found := esvd.evmKeeper.GetChainConfig(ctx)
|
||||
if !found {
|
||||
return ctx, evmtypes.ErrChainConfigNotFound
|
||||
}
|
||||
@@ -122,11 +118,8 @@ func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// get and set account must be called with an infinite gas meter in order to prevent
|
||||
// additional gas from being deducted.
|
||||
infCtx := ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
avd.evmKeeper.WithContext(infCtx)
|
||||
evmDenom := avd.evmKeeper.GetParams(infCtx).EvmDenom
|
||||
avd.evmKeeper.WithContext(ctx)
|
||||
evmDenom := avd.evmKeeper.GetParams(ctx).EvmDenom
|
||||
|
||||
for i, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
@@ -154,14 +147,14 @@ func (avd EthAccountVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx
|
||||
"the sender is not EOA: address <%v>, codeHash <%s>", fromAddr, codeHash), "")
|
||||
}
|
||||
|
||||
acc := avd.ak.GetAccount(infCtx, from)
|
||||
acc := avd.ak.GetAccount(ctx, from)
|
||||
if acc == nil {
|
||||
acc = avd.ak.NewAccountWithAddress(infCtx, from)
|
||||
avd.ak.SetAccount(infCtx, acc)
|
||||
acc = avd.ak.NewAccountWithAddress(ctx, from)
|
||||
avd.ak.SetAccount(ctx, acc)
|
||||
}
|
||||
|
||||
// validate sender has enough funds to pay for tx cost
|
||||
balance := avd.bankKeeper.GetBalance(infCtx, from, evmDenom)
|
||||
balance := avd.bankKeeper.GetBalance(ctx, from, evmDenom)
|
||||
if balance.Amount.BigInt().Cmp(msgEthTx.Cost()) < 0 {
|
||||
return ctx, stacktrace.Propagate(
|
||||
sdkerrors.Wrapf(
|
||||
@@ -199,10 +192,6 @@ func (nvd EthNonceVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx,
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// get and set account must be called with an infinite gas meter in order to prevent
|
||||
// additional gas from being deducted.
|
||||
infCtx := ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
|
||||
for i, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
if !ok {
|
||||
@@ -213,7 +202,7 @@ func (nvd EthNonceVerificationDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx,
|
||||
}
|
||||
|
||||
// sender address should be in the tx cache from the previous AnteHandle call
|
||||
seq, err := nvd.ak.GetSequence(infCtx, msgEthTx.GetFrom())
|
||||
seq, err := nvd.ak.GetSequence(ctx, msgEthTx.GetFrom())
|
||||
if err != nil {
|
||||
return ctx, stacktrace.Propagate(err, "sequence not found for address %s", msgEthTx.From)
|
||||
}
|
||||
@@ -267,14 +256,10 @@ func NewEthGasConsumeDecorator(ak AccountKeeper, bankKeeper BankKeeper, ek EVMKe
|
||||
// - user doesn't have enough balance to deduct the transaction fees (gas_limit * gas_price)
|
||||
// - transaction or block gas meter runs out of gas
|
||||
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
// get and set account must be called with an infinite gas meter in order to prevent
|
||||
// additional gas from being deducted.
|
||||
infCtx := ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
|
||||
// reset the refund gas value in the keeper for the current transaction
|
||||
egcd.evmKeeper.ResetRefundTransient(infCtx)
|
||||
egcd.evmKeeper.ResetRefundTransient(ctx)
|
||||
|
||||
config, found := egcd.evmKeeper.GetChainConfig(infCtx)
|
||||
config, found := egcd.evmKeeper.GetChainConfig(ctx)
|
||||
if !found {
|
||||
return ctx, evmtypes.ErrChainConfigNotFound
|
||||
}
|
||||
@@ -297,7 +282,7 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
||||
isContractCreation := msgEthTx.To() == nil
|
||||
|
||||
// fetch sender account from signature
|
||||
signerAcc, err := authante.GetSignerAcc(infCtx, egcd.ak, msgEthTx.GetFrom())
|
||||
signerAcc, err := authante.GetSignerAcc(ctx, egcd.ak, msgEthTx.GetFrom())
|
||||
if err != nil {
|
||||
return ctx, stacktrace.Propagate(err, "account not found for sender %s", msgEthTx.From)
|
||||
}
|
||||
@@ -324,20 +309,16 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
|
||||
// calculate the fees paid to validators based on gas limit and price
|
||||
feeAmt := msgEthTx.Fee() // fee = gas limit * gas price
|
||||
|
||||
evmDenom := egcd.evmKeeper.GetParams(infCtx).EvmDenom
|
||||
evmDenom := egcd.evmKeeper.GetParams(ctx).EvmDenom
|
||||
fees := sdk.Coins{sdk.NewCoin(evmDenom, sdk.NewIntFromBigInt(feeAmt))}
|
||||
|
||||
// deduct the full gas cost from the user balance
|
||||
if err := authante.DeductFees(egcd.bankKeeper, infCtx, signerAcc, fees); err != nil {
|
||||
if err := authante.DeductFees(egcd.bankKeeper, ctx, signerAcc, fees); err != nil {
|
||||
return ctx, stacktrace.Propagate(
|
||||
err,
|
||||
"failed to deduct full gas cost %s from the user %s balance", fees, msgEthTx.From,
|
||||
)
|
||||
}
|
||||
|
||||
// consume intrinsic gas for the current transaction. After runTx is executed on Baseapp, the
|
||||
// application will consume gas from the block gas pool.
|
||||
ctx.GasMeter().ConsumeGas(intrinsicGas, "intrinsic gas")
|
||||
}
|
||||
|
||||
// TODO: deprecate after https://github.com/cosmos/cosmos-sdk/issues/9514 is fixed on SDK
|
||||
@@ -373,12 +354,9 @@ func NewCanTransferDecorator(evmKeeper EVMKeeper) CanTransferDecorator {
|
||||
// AnteHandle creates an EVM from the message and calls the BlockContext CanTransfer function to
|
||||
// see if the address can execute the transaction.
|
||||
func (ctd CanTransferDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
// get and set account must be called with an infinite gas meter in order to prevent
|
||||
// additional gas from being deducted.
|
||||
infCtx := ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
ctd.evmKeeper.WithContext(infCtx)
|
||||
ctd.evmKeeper.WithContext(ctx)
|
||||
|
||||
config, found := ctd.evmKeeper.GetChainConfig(infCtx)
|
||||
config, found := ctd.evmKeeper.GetChainConfig(ctx)
|
||||
if !found {
|
||||
return ctx, evmtypes.ErrChainConfigNotFound
|
||||
}
|
||||
@@ -444,12 +422,8 @@ func NewAccessListDecorator(evmKeeper EVMKeeper) AccessListDecorator {
|
||||
//
|
||||
// The AnteHandler will only prepare the access list if Yolov3/Berlin/EIPs 2929 and 2930 are applicable at the current number.
|
||||
func (ald AccessListDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
// get and set account must be called with an infinite gas meter in order to prevent
|
||||
// additional gas from being deducted.
|
||||
|
||||
infCtx := ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
|
||||
config, found := ald.evmKeeper.GetChainConfig(infCtx)
|
||||
config, found := ald.evmKeeper.GetChainConfig(ctx)
|
||||
if !found {
|
||||
return ctx, evmtypes.ErrChainConfigNotFound
|
||||
}
|
||||
@@ -464,7 +438,7 @@ func (ald AccessListDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate b
|
||||
}
|
||||
|
||||
// setup the keeper context before setting the access list
|
||||
ald.evmKeeper.WithContext(infCtx)
|
||||
ald.evmKeeper.WithContext(ctx)
|
||||
|
||||
for i, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
@@ -501,9 +475,6 @@ func NewEthIncrementSenderSequenceDecorator(ak AccountKeeper) EthIncrementSender
|
||||
// contract creation, the nonce will be incremented during the transaction execution and not within
|
||||
// this AnteHandler decorator.
|
||||
func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
|
||||
// get and set account must be called with an infinite gas meter in order to prevent
|
||||
// additional gas from being deducted.
|
||||
infCtx := ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
|
||||
for i, msg := range tx.GetMsgs() {
|
||||
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
|
||||
@@ -524,7 +495,7 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
|
||||
|
||||
// increment sequence of all signers
|
||||
for _, addr := range msg.GetSigners() {
|
||||
acc := issd.ak.GetAccount(infCtx, addr)
|
||||
acc := issd.ak.GetAccount(ctx, addr)
|
||||
|
||||
if acc == nil {
|
||||
return ctx, stacktrace.Propagate(
|
||||
@@ -540,7 +511,7 @@ func (issd EthIncrementSenderSequenceDecorator) AnteHandle(ctx sdk.Context, tx s
|
||||
return ctx, stacktrace.Propagate(err, "failed to set sequence to %d", acc.GetSequence()+1)
|
||||
}
|
||||
|
||||
issd.ak.SetAccount(infCtx, acc)
|
||||
issd.ak.SetAccount(ctx, acc)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,3 +542,22 @@ func (vbd EthValidateBasicDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simu
|
||||
|
||||
return next(ctx, tx, simulate)
|
||||
}
|
||||
|
||||
// EthSetupContextDecorator is adapted from SetUpContextDecorator from cosmos-sdk, it ignores gas consumption
|
||||
// by setting the gas meter to infinite
|
||||
type EthSetupContextDecorator struct{}
|
||||
|
||||
func NewEthSetUpContextDecorator() EthSetupContextDecorator {
|
||||
return EthSetupContextDecorator{}
|
||||
}
|
||||
|
||||
func (esc EthSetupContextDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (newCtx sdk.Context, err error) {
|
||||
// all transactions must implement GasTx
|
||||
_, ok := tx.(authante.GasTx)
|
||||
if !ok {
|
||||
return newCtx, sdkerrors.Wrap(sdkerrors.ErrTxDecode, "Tx must be GasTx")
|
||||
}
|
||||
|
||||
newCtx = ctx.WithGasMeter(sdk.NewInfiniteGasMeter())
|
||||
return next(newCtx, tx, simulate)
|
||||
}
|
||||
|
||||
+38
-24
@@ -11,7 +11,6 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
func nextFn(ctx sdk.Context, _ sdk.Tx, _ bool) (sdk.Context, error) {
|
||||
@@ -46,9 +45,7 @@ func (suite AnteTestSuite) TestEthSigVerificationDecorator() {
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
consumed := suite.ctx.GasMeter().GasConsumed()
|
||||
ctx, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, nextFn)
|
||||
suite.Require().Equal(consumed, ctx.GasMeter().GasConsumed())
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, nextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
@@ -133,10 +130,7 @@ func (suite AnteTestSuite) TestNewEthAccountVerificationDecorator() {
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
tc.malleate()
|
||||
|
||||
consumed := suite.ctx.GasMeter().GasConsumed()
|
||||
ctx, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(tc.checkTx), tc.tx, false, nextFn)
|
||||
suite.Require().Equal(consumed, ctx.GasMeter().GasConsumed())
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(tc.checkTx), tc.tx, false, nextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
@@ -193,9 +187,7 @@ func (suite AnteTestSuite) TestEthNonceVerificationDecorator() {
|
||||
suite.Run(tc.name, func() {
|
||||
|
||||
tc.malleate()
|
||||
consumed := suite.ctx.GasMeter().GasConsumed()
|
||||
ctx, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, nextFn)
|
||||
suite.Require().Equal(consumed, ctx.GasMeter().GasConsumed())
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsReCheckTx(tc.reCheckTx), tc.tx, false, nextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
@@ -303,11 +295,9 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
|
||||
return
|
||||
}
|
||||
|
||||
consumed := suite.ctx.GasMeter().GasConsumed()
|
||||
ctx, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().Equal(int(params.TxGasContractCreation+params.TxAccessListAddressGas), int(ctx.GasMeter().GasConsumed()-consumed))
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
@@ -364,9 +354,7 @@ func (suite AnteTestSuite) TestCanTransferDecorator() {
|
||||
|
||||
tc.malleate()
|
||||
|
||||
consumed := suite.ctx.GasMeter().GasConsumed()
|
||||
ctx, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
|
||||
suite.Require().Equal(consumed, ctx.GasMeter().GasConsumed())
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
@@ -426,10 +414,7 @@ func (suite AnteTestSuite) TestAccessListDecorator() {
|
||||
suite.Run(tc.name, func() {
|
||||
|
||||
tc.malleate()
|
||||
|
||||
consumed := suite.ctx.GasMeter().GasConsumed()
|
||||
ctx, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
|
||||
suite.Require().Equal(consumed, ctx.GasMeter().GasConsumed())
|
||||
_, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true), tc.tx, false, nextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
@@ -503,7 +488,6 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
|
||||
suite.Run(tc.name, func() {
|
||||
|
||||
tc.malleate()
|
||||
consumed := suite.ctx.GasMeter().GasConsumed()
|
||||
|
||||
if tc.expPanic {
|
||||
suite.Require().Panics(func() {
|
||||
@@ -512,8 +496,7 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
|
||||
return
|
||||
}
|
||||
|
||||
ctx, err := dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)
|
||||
suite.Require().Equal(consumed, ctx.GasMeter().GasConsumed())
|
||||
_, err := dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
@@ -530,3 +513,34 @@ func (suite AnteTestSuite) TestEthIncrementSenderSequenceDecorator() {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite AnteTestSuite) TestEthSetupContextDecorator() {
|
||||
dec := ante.NewEthSetUpContextDecorator()
|
||||
tx := evmtypes.NewMsgEthereumTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
tx sdk.Tx
|
||||
expPass bool
|
||||
}{
|
||||
{"invalid transaction type - does not implement GasTx", &invalidTx{}, false},
|
||||
{
|
||||
"success - transaction implement GasTx",
|
||||
tx,
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
_, err := dec.AnteHandle(suite.ctx, tc.tx, false, nextFn)
|
||||
|
||||
if tc.expPass {
|
||||
suite.Require().NoError(err)
|
||||
} else {
|
||||
suite.Require().Error(err)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user