Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

Commit

Permalink
feat(ante, evm): set priority for eth transactions (#1214)
Browse files Browse the repository at this point in the history
* Set priority for eth transactions

Set the tx priority to the lowest priority in the messages.

fix unit tests

code cleanup and spec

update spec

fix go lint

add priority integration test

add python linter job

add access list tx type

fix gas limit

remove ledger tag, so no need to replace hid dependency

fix earlier check

ibc-go v5.0.0-beta1

* fix pruned node integration test

* Update x/feemarket/spec/09_antehandlers.md

Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
  • Loading branch information
yihuang and fedekunze committed Aug 5, 2022
1 parent 53f160c commit e156084
Show file tree
Hide file tree
Showing 25 changed files with 307 additions and 63 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ Ref: https://keepachangelog.com/en/1.0.0/
recompute eth tx hashes in JSON-RPC APIs to fix old blocks.
* (deps) [#1168](https://github.com/evmos/ethermint/pull/1168) Upgrade cosmos-sdk to v0.46.

### API Breaking

* (ante) [#1214](https://github.com/evmos/ethermint/pull/1214) Set mempool priority to evm transactions.

### Improvements

* (feemarket) [\#1165](https://github.com/evmos/ethermint/pull/1165) Add hint in specs about different gas terminology for gas in Cosmos and Ethereum.
Expand Down
15 changes: 12 additions & 3 deletions app/ante/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ante

import (
"errors"
"math"
"math/big"
"strconv"

Expand Down Expand Up @@ -170,7 +171,7 @@ func NewEthGasConsumeDecorator(
// - 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) {
func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate bool, next sdk.AnteHandler) (sdk.Context, error) {
params := egcd.evmKeeper.GetParams(ctx)

ethCfg := params.ChainConfig.EthereumConfig(egcd.evmKeeper.ChainID())
Expand All @@ -183,6 +184,9 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
gasWanted := uint64(0)
var events sdk.Events

// Use the lowest priority of all the messages as the final one.
minPriority := int64(math.MaxInt64)

for _, msg := range tx.GetMsgs() {
msgEthTx, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
Expand All @@ -205,7 +209,7 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
gasWanted += txData.GetGas()
}

fees, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
fees, priority, err := egcd.evmKeeper.DeductTxCostsFromUserBalance(
ctx,
*msgEthTx,
txData,
Expand All @@ -219,6 +223,9 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
}

events = append(events, sdk.NewEvent(sdk.EventTypeTx, sdk.NewAttribute(sdk.AttributeKeyFee, fees.String())))
if priority < minPriority {
minPriority = priority
}
}

// TODO: change to typed events
Expand All @@ -240,8 +247,10 @@ func (egcd EthGasConsumeDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simula
ctx = ctx.WithGasMeter(ethermint.NewInfiniteGasMeterWithLimit(gasWanted))
ctx.GasMeter().ConsumeGas(gasConsumed, "copy gas consumed")

newCtx := ctx.WithPriority(minPriority)

// we know that we have enough gas on the pool to cover the intrinsic gas
return next(ctx, tx, simulate)
return next(newCtx, tx, simulate)
}

// CanTransferDecorator checks if the sender is allowed to transfer funds according to the EVM block
Expand Down
58 changes: 46 additions & 12 deletions app/ante/eth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/evmos/ethermint/app/ante"
"github.com/evmos/ethermint/server/config"
"github.com/evmos/ethermint/tests"
evmkeeper "github.com/evmos/ethermint/x/evm/keeper"
"github.com/evmos/ethermint/x/evm/statedb"
evmtypes "github.com/evmos/ethermint/x/evm/types"

Expand Down Expand Up @@ -221,41 +222,61 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
tx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), txGasLimit, big.NewInt(1), nil, nil, nil, nil)
tx.From = addr.Hex()

ethCfg := suite.app.EvmKeeper.GetParams(suite.ctx).
ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
baseFee := suite.app.EvmKeeper.GetBaseFee(suite.ctx, ethCfg)
suite.Require().Equal(int64(1000000000), baseFee.Int64())

gasPrice := new(big.Int).Add(baseFee, evmkeeper.DefaultPriorityReduction.BigInt())

tx2GasLimit := uint64(1000000)
tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx2GasLimit, big.NewInt(1), nil, nil, nil, &ethtypes.AccessList{{Address: addr, StorageKeys: nil}})
tx2 := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx2GasLimit, gasPrice, nil, nil, nil, &ethtypes.AccessList{{Address: addr, StorageKeys: nil}})
tx2.From = addr.Hex()
tx2Priority := int64(1)

dynamicFeeTx := evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), tx2GasLimit,
nil, // gasPrice
new(big.Int).Add(baseFee, big.NewInt(evmkeeper.DefaultPriorityReduction.Int64()*2)), // gasFeeCap
evmkeeper.DefaultPriorityReduction.BigInt(), // gasTipCap
nil, &ethtypes.AccessList{{Address: addr, StorageKeys: nil}})
dynamicFeeTx.From = addr.Hex()
dynamicFeeTxPriority := int64(1)

var vmdb *statedb.StateDB

testCases := []struct {
name string
tx sdk.Tx
gasLimit uint64
malleate func()
expPass bool
expPanic bool
name string
tx sdk.Tx
gasLimit uint64
malleate func()
expPass bool
expPanic bool
expPriority int64
}{
{"invalid transaction type", &invalidTx{}, math.MaxUint64, func() {}, false, false},
{"invalid transaction type", &invalidTx{}, math.MaxUint64, func() {}, false, false, 0},
{
"sender not found",
evmtypes.NewTxContract(suite.app.EvmKeeper.ChainID(), 1, big.NewInt(10), 1000, big.NewInt(1), nil, nil, nil, nil),
math.MaxUint64,
func() {},
false, false,
0,
},
{
"gas limit too low",
tx,
math.MaxUint64,
func() {},
false, false,
0,
},
{
"not enough balance for fees",
tx2,
math.MaxUint64,
func() {},
false, false,
0,
},
{
"not enough tx gas",
Expand All @@ -265,28 +286,40 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
vmdb.AddBalance(addr, big.NewInt(1000000))
},
false, true,
0,
},
{
"not enough block gas",
tx2,
0,
func() {
vmdb.AddBalance(addr, big.NewInt(1000000))

suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(1))
},
false, true,
0,
},
{
"success",
"success - legacy tx",
tx2,
tx2GasLimit, // it's capped
func() {
vmdb.AddBalance(addr, big.NewInt(1000000))

vmdb.AddBalance(addr, big.NewInt(1001000000000000))
suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(10000000000000000000))
},
true, false,
tx2Priority,
},
{
"success - dynamic fee tx",
dynamicFeeTx,
tx2GasLimit, // it's capped
func() {
vmdb.AddBalance(addr, big.NewInt(1001000000000000))
suite.ctx = suite.ctx.WithBlockGasMeter(sdk.NewGasMeter(10000000000000000000))
},
true, false,
dynamicFeeTxPriority,
},
}

Expand All @@ -306,6 +339,7 @@ func (suite AnteTestSuite) TestEthGasConsumeDecorator() {
ctx, err := dec.AnteHandle(suite.ctx.WithIsCheckTx(true).WithGasMeter(sdk.NewInfiniteGasMeter()), tc.tx, false, NextFn)
if tc.expPass {
suite.Require().NoError(err)
suite.Require().Equal(tc.expPriority, ctx.Priority())
} else {
suite.Require().Error(err)
}
Expand Down
4 changes: 2 additions & 2 deletions app/ante/handler_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func newCosmosAnteHandler(options HandlerOptions) sdk.AnteHandler {
ante.NewSigGasConsumeDecorator(options.AccountKeeper, options.SigGasConsumer),
ante.NewSigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewRedundancyDecorator(options.IBCKeeper),
ibcante.NewRedundantRelayDecorator(options.IBCKeeper),
NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
)
}
Expand All @@ -106,7 +106,7 @@ func newCosmosAnteHandlerEip712(options HandlerOptions) sdk.AnteHandler {
// Note: signature verification uses EIP instead of the cosmos signature validator
NewEip712SigVerificationDecorator(options.AccountKeeper, options.SignModeHandler),
ante.NewIncrementSequenceDecorator(options.AccountKeeper),
ibcante.NewRedundancyDecorator(options.IBCKeeper),
ibcante.NewRedundantRelayDecorator(options.IBCKeeper),
NewGasWantedDecorator(options.EvmKeeper, options.FeeMarketKeeper),
)
}
2 changes: 1 addition & 1 deletion app/ante/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type EVMKeeper interface {
NewEVM(ctx sdk.Context, msg core.Message, cfg *evmtypes.EVMConfig, tracer vm.EVMLogger, stateDB vm.StateDB) *vm.EVM
DeductTxCostsFromUserBalance(
ctx sdk.Context, msgEthTx evmtypes.MsgEthereumTx, txData evmtypes.TxData, denom string, homestead, istanbul, london bool,
) (sdk.Coins, error)
) (fees sdk.Coins, priority int64, err error)
GetBaseFee(ctx sdk.Context, ethCfg *params.ChainConfig) *big.Int
GetBalance(ctx sdk.Context, addr common.Address) *big.Int
ResetTransientGasUsed(ctx sdk.Context)
Expand Down
2 changes: 1 addition & 1 deletion default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
let
version = "v0.17.1";
pname = "ethermintd";
tags = [ "ledger" "netgo" ];
tags = [ "netgo" ];
ldflags = lib.concatStringsSep "\n" ([
"-X github.com/cosmos/cosmos-sdk/version.Name=ethermint"
"-X github.com/cosmos/cosmos-sdk/version.AppName=${pname}"
Expand Down
4 changes: 1 addition & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
github.com/cosmos/cosmos-sdk v0.46.0
github.com/cosmos/go-bip39 v1.0.0
github.com/cosmos/ibc-go/v5 v5.0.0
github.com/cosmos/ibc-go/v5 v5.0.0-beta1
github.com/davecgh/go-spew v1.1.1
github.com/ethereum/go-ethereum v1.10.19
github.com/gogo/protobuf v1.3.3
Expand Down Expand Up @@ -185,8 +185,6 @@ require (
replace (
github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76

github.com/cosmos/ibc-go/v5 => github.com/notional-labs/ibc-go/v5 v5.0.0-20220728121949-040aca93dda5

// Fix upstream GHSA-h395-qcrw-5vmq vulnerability.
// TODO Remove it: https://github.com/cosmos/cosmos-sdk/issues/10409
github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4
github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw=
github.com/cosmos/iavl v0.19.0 h1:sgyrjqOkycXiN7Tuupuo4QAldKFg7Sipyfeg/IL7cps=
github.com/cosmos/iavl v0.19.0/go.mod h1:l5h9pAB3m5fihB3pXVgwYqdY8aBsMagqz7T0MUjxZeA=
github.com/cosmos/ibc-go/v5 v5.0.0-beta1 h1:YqC9giQlZId8Wui8xpaUFI+TpVmEupQZSoDlmxAu6yI=
github.com/cosmos/ibc-go/v5 v5.0.0-beta1/go.mod h1:9mmcbzuidgX7nhafIKng/XhXAHDEnRqDjGy/60W1cvg=
github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76 h1:DdzS1m6o/pCqeZ8VOAit/gyATedRgjvkVI+UCrLpyuU=
github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76/go.mod h1:0mkLWIoZuQ7uBoospo5Q9zIpqq6rYCPJDSUdeCJvPM8=
github.com/cosmos/ledger-cosmos-go v0.11.1 h1:9JIYsGnXP613pb2vPjFeMMjBI5lEDsEaF6oYorTy6J4=
Expand Down Expand Up @@ -1074,8 +1076,6 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA
github.com/nishanths/exhaustive v0.7.11/go.mod h1:gX+MP7DWMKJmNa1HfMozK+u04hQd3na9i0hyqf3/dOI=
github.com/nishanths/predeclared v0.0.0-20190419143655-18a43bb90ffc/go.mod h1:62PewwiQTlm/7Rj+cxVYqZvDIUc+JjZq6GHAC1fsObQ=
github.com/nishanths/predeclared v0.2.2/go.mod h1:RROzoN6TnGQupbC+lqggsOlcgysk3LMK/HI84Mp280c=
github.com/notional-labs/ibc-go/v5 v5.0.0-20220728121949-040aca93dda5 h1:G/tpnrLpUj8avmWtggo0L3f8u9gS8s4SqCGrXvlEO5w=
github.com/notional-labs/ibc-go/v5 v5.0.0-20220728121949-040aca93dda5/go.mod h1:KxDAWaeoibbXS0remZwoFz4nil+6+Bi4X3XQh0+23Io=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
Expand Down
5 changes: 2 additions & 3 deletions gomod2nix.toml
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,8 @@ schema = 3
version = "v0.19.0"
hash = "sha256-NunBVGJqJkpOMcTmFUCnXQiJSjgNEuxlMu+bkj33wIs="
[mod."github.com/cosmos/ibc-go/v5"]
version = "v5.0.0-20220728121949-040aca93dda5"
hash = "sha256-G+hffr22KJZlbshH9HkqMP8m9XLKcSSzwpKCx9cphbo="
replaced = "github.com/notional-labs/ibc-go/v5"
version = "v5.0.0-beta1"
hash = "sha256-v+dGnhNSNkkQzuCUoWmVGMPQCEb6aL/oB7zxbYw9owE="
[mod."github.com/cosmos/ledger-cosmos-go"]
version = "v0.11.1"
hash = "sha256-yli+VvVtZmHo2LPvCY6lYVUfcCDn3sBLDL+a8KIlqDA="
Expand Down
2 changes: 1 addition & 1 deletion rpc/namespaces/ethereum/eth/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -974,7 +974,7 @@ func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interfac
// tolerate the error for pruned node.
e.logger.Error("fetch basefee failed, node is pruned?", "height", res.Height, "error", err)
} else {
receipt["effectiveGasPrice"] = hexutil.Big(*dynamicTx.GetEffectiveGasPrice(baseFee))
receipt["effectiveGasPrice"] = hexutil.Big(*dynamicTx.EffectiveGasPrice(baseFee))
}
}

Expand Down
12 changes: 11 additions & 1 deletion tests/integration_tests/configs/default.jsonnet
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
{
dotenv: '../../../scripts/.env',
'ethermintd_777-1': {
'ethermint_9000-1': {
cmd: 'ethermintd',
'start-flags': '--trace',
config: {
consensus: {
// larger timeout for more stable mempool tests
timeout_commit: '10s',
},
mempool: {
// use v1 mempool to enable tx prioritization
version: 'v1',
},
},
'app-config': {
'minimum-gas-prices': '0aphoton',
'index-events': ['ethereum_tx.ethereumTxHash'],
Expand Down
4 changes: 2 additions & 2 deletions tests/integration_tests/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import subprocess
from pathlib import Path

import tomlkit
import web3
from pystarport import ports
from web3.middleware import geth_poa_middleware
Expand Down Expand Up @@ -61,9 +60,10 @@ def __init__(self, w3):


def setup_ethermint(path, base_port):
cfg = Path(__file__).parent / "../../scripts/ethermint-devnet.yaml"
cfg = Path(__file__).parent / "configs/default.jsonnet"
yield from setup_custom_ethermint(path, base_port, cfg)


def setup_geth(path, base_port):
with (path / "geth.log").open("w") as logfile:
cmd = [
Expand Down
Loading

0 comments on commit e156084

Please sign in to comment.