Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (evm) [#450](https://github.com/crypto-org-chain/ethermint/pull/450) Refactor transient stores to be compatible with parallel tx execution.
* (evm) [#454](https://github.com/crypto-org-chain/ethermint/pull/454) Migrate transient stores to object stores.
* (evm) [#461](https://github.com/crypto-org-chain/ethermint/pull/461) Remove custom signer getter, use the option in protobuf file instead.
* (evm) [#469](https://github.com/crypto-org-chain/ethermint/pull/469) More aggressive cache of common parameters in object store.

## v0.21.x-cronos

Expand Down
1 change: 1 addition & 0 deletions app/ante/ante_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,7 @@ func (suite *AnteTestSuite) TestAnteHandler() {
setup()

suite.ctx = suite.ctx.WithIsCheckTx(tc.checkTx).WithIsReCheckTx(tc.reCheckTx).WithConsensusParams(*app.DefaultConsensusParams)
suite.app.EvmKeeper.RemoveParamsCache(suite.ctx)

// expConsumed := params.TxGasContractCreation + params.TxGas
_, err := suite.anteHandler(suite.ctx, tc.txFn(), false)
Expand Down
13 changes: 4 additions & 9 deletions app/ante/eth.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,18 +101,13 @@ func VerifyEthAccount(
// - gas limit is greater than the block gas meter limit
func CheckEthGasConsume(
ctx sdk.Context, tx sdk.Tx,
ethCfg *params.ChainConfig,
rules params.Rules,
evmKeeper EVMKeeper,
baseFee *big.Int,
maxGasWanted uint64,
evmDenom string,
) (sdk.Context, error) {
gasWanted := uint64(0)

blockHeight := big.NewInt(ctx.BlockHeight())
homestead := ethCfg.IsHomestead(blockHeight)
istanbul := ethCfg.IsIstanbul(blockHeight)
shanghai := ethCfg.IsShanghai(uint64(ctx.BlockHeader().Time.Unix()))
var events sdk.Events

// Use the lowest priority of all the messages as the final one.
Expand Down Expand Up @@ -152,7 +147,7 @@ func CheckEthGasConsume(
continue
}

fees, err := keeper.VerifyFee(txData, evmDenom, baseFee, homestead, istanbul, shanghai, ctx.IsCheckTx())
fees, err := keeper.VerifyFee(txData, evmDenom, baseFee, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai, ctx.IsCheckTx())
if err != nil {
return ctx, errorsmod.Wrapf(err, "failed to verify the fees")
}
Expand Down Expand Up @@ -207,7 +202,7 @@ func CheckEthGasConsume(
func CheckEthCanTransfer(
ctx sdk.Context, tx sdk.Tx,
baseFee *big.Int,
ethCfg *params.ChainConfig,
rules params.Rules,
evmKeeper EVMKeeper,
evmParams *evmtypes.Params,
) error {
Expand All @@ -225,7 +220,7 @@ func CheckEthCanTransfer(
)
}

if evmtypes.IsLondon(ethCfg, ctx.BlockHeight()) {
if rules.IsLondon {
if baseFee == nil {
return errorsmod.Wrap(
evmtypes.ErrInvalidBaseFee,
Expand Down
8 changes: 5 additions & 3 deletions app/ante/eth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ func (suite *AnteTestSuite) TestEthGasConsumeDecorator() {
chainCfg := evmParams.GetChainConfig()
ethCfg := chainCfg.EthereumConfig(chainID)
baseFee := suite.app.EvmKeeper.GetBaseFee(suite.ctx, ethCfg)
rules := ethCfg.Rules(big.NewInt(suite.ctx.BlockHeight()), ethCfg.MergeNetsplitBlock != nil, uint64(suite.ctx.BlockHeader().Time.Unix()))

addr := tests.GenerateAddress()

Expand Down Expand Up @@ -298,15 +299,15 @@ func (suite *AnteTestSuite) TestEthGasConsumeDecorator() {
suite.Require().Panics(func() {
_, _ = ante.CheckEthGasConsume(
suite.ctx.WithIsCheckTx(true).WithGasMeter(storetypes.NewGasMeter(1)), tc.tx,
ethCfg, suite.app.EvmKeeper, baseFee, config.DefaultMaxTxGasWanted, evmtypes.DefaultEVMDenom,
rules, suite.app.EvmKeeper, baseFee, config.DefaultMaxTxGasWanted, evmtypes.DefaultEVMDenom,
)
})
return
}

ctx, err := ante.CheckEthGasConsume(
suite.ctx.WithIsCheckTx(true).WithGasMeter(storetypes.NewInfiniteGasMeter()), tc.tx,
ethCfg, suite.app.EvmKeeper, baseFee, config.DefaultMaxTxGasWanted, evmtypes.DefaultEVMDenom,
rules, suite.app.EvmKeeper, baseFee, config.DefaultMaxTxGasWanted, evmtypes.DefaultEVMDenom,
)
if tc.expPass {
suite.Require().NoError(err)
Expand All @@ -328,6 +329,7 @@ func (suite *AnteTestSuite) TestCanTransferDecorator() {
chainCfg := evmParams.GetChainConfig()
ethCfg := chainCfg.EthereumConfig(chainID)
baseFee := suite.app.EvmKeeper.GetBaseFee(suite.ctx, ethCfg)
rules := ethCfg.Rules(big.NewInt(suite.ctx.BlockHeight()), ethCfg.MergeNetsplitBlock != nil, uint64(suite.ctx.BlockHeader().Time.Unix()))

tx := evmtypes.NewTxContract(
suite.app.EvmKeeper.ChainID(),
Expand Down Expand Up @@ -397,7 +399,7 @@ func (suite *AnteTestSuite) TestCanTransferDecorator() {

err := ante.CheckEthCanTransfer(
suite.ctx.WithIsCheckTx(true), tc.tx,
baseFee, ethCfg, suite.app.EvmKeeper, &evmParams,
baseFee, rules, suite.app.EvmKeeper, &evmParams,
)

if tc.expPass {
Expand Down
22 changes: 12 additions & 10 deletions app/ante/handler_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,16 @@ func (options HandlerOptions) validate() error {

func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler {
return func(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, error) {
var err error
evmParams := options.EvmKeeper.GetParams(ctx)
blockCfg, err := options.EvmKeeper.EVMBlockConfig(ctx, options.EvmKeeper.ChainID())
if err != nil {
return ctx, errorsmod.Wrap(errortypes.ErrLogic, err.Error())
}
evmParams := &blockCfg.Params
evmDenom := evmParams.EvmDenom
feemarketParams := options.FeeMarketKeeper.GetParams(ctx)
chainID := options.EvmKeeper.ChainID()
chainCfg := evmParams.GetChainConfig()
ethCfg := chainCfg.EthereumConfig(chainID)
baseFee := evmtypes.GetBaseFee(ctx.BlockHeight(), ethCfg, &feemarketParams)
feemarketParams := &blockCfg.FeeMarketParams
chainID := blockCfg.ChainConfig.ChainID
baseFee := blockCfg.BaseFee
rules := blockCfg.Rules

// all transactions must implement FeeTx
_, ok := tx.(sdk.FeeTx)
Expand All @@ -100,7 +102,7 @@ func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler {
return ctx, err
}

if err := ValidateEthBasic(ctx, tx, &evmParams, baseFee); err != nil {
if err := ValidateEthBasic(ctx, tx, evmParams, baseFee); err != nil {
return ctx, err
}

Expand All @@ -112,12 +114,12 @@ func newEthAnteHandler(options HandlerOptions) sdk.AnteHandler {
return ctx, err
}

if err := CheckEthCanTransfer(ctx, tx, baseFee, ethCfg, options.EvmKeeper, &evmParams); err != nil {
if err := CheckEthCanTransfer(ctx, tx, baseFee, rules, options.EvmKeeper, evmParams); err != nil {
return ctx, err
}

ctx, err = CheckEthGasConsume(
ctx, tx, ethCfg, options.EvmKeeper,
ctx, tx, rules, options.EvmKeeper,
baseFee, options.MaxTxGasWanted, evmDenom,
)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions app/ante/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
tx "github.com/cosmos/cosmos-sdk/types/tx"

"github.com/ethereum/go-ethereum/common"
evmkeeper "github.com/evmos/ethermint/x/evm/keeper"
"github.com/evmos/ethermint/x/evm/statedb"
feemarkettypes "github.com/evmos/ethermint/x/feemarket/types"
)
Expand All @@ -30,6 +31,7 @@ import (
type EVMKeeper interface {
statedb.Keeper
ChainID() *big.Int
EVMBlockConfig(sdk.Context, *big.Int) (*evmkeeper.EVMBlockConfig, error)

DeductTxCostsFromUserBalance(ctx sdk.Context, fees sdk.Coins, from common.Address) error
}
Expand Down
4 changes: 2 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ func NewEthermintApp(
// Add the EVM transient store key
tkeys := storetypes.NewTransientStoreKeys(paramstypes.TStoreKey)
memKeys := storetypes.NewMemoryStoreKeys(capabilitytypes.MemStoreKey)
okeys := storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey, evmtypes.ObjectStoreKey, feemarkettypes.ObjectStoreKey)
okeys := storetypes.NewObjectStoreKeys(banktypes.ObjectStoreKey, evmtypes.ObjectStoreKey)

// load state streaming if enabled
if err := bApp.RegisterStreamingServices(appOpts, keys); err != nil {
Expand Down Expand Up @@ -510,7 +510,7 @@ func NewEthermintApp(
app.FeeMarketKeeper = feemarketkeeper.NewKeeper(
appCodec,
authtypes.NewModuleAddress(govtypes.ModuleName),
keys[feemarkettypes.StoreKey], okeys[feemarkettypes.ObjectStoreKey],
keys[feemarkettypes.StoreKey],
feeMarketSs,
)

Expand Down
5 changes: 2 additions & 3 deletions tests/integration_tests/test_grpc_only.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,9 @@ def expect_cb(rsp):
wait_for_port(api_port)

def expect_cb(rsp):
assert rsp["code"] != 0, str(rsp)
return "validator does not exist" in rsp["message"]
return "code" not in rsp

# it don't works without proposer address neither
# it defaults to empty address without proposer address
grpc_eth_call(api_port, msg, expect_cb, chain_id=9000)

# pass the first validator's consensus address to grpc query
Expand Down
7 changes: 5 additions & 2 deletions x/evm/keeper/abci.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ import (
func (k *Keeper) BeginBlock(ctx sdk.Context) error {
k.WithChainID(ctx)

// cache params object
_ = k.GetParams(ctx)
// cache parameters that's common for the whole block.
if _, err := k.EVMBlockConfig(ctx, k.ChainID()); err != nil {
return err
}

return nil
}
Expand All @@ -34,5 +36,6 @@ func (k *Keeper) BeginBlock(ctx sdk.Context) error {
// an empty slice.
func (k *Keeper) EndBlock(ctx sdk.Context) error {
k.CollectTxBloom(ctx)
k.RemoveParamsCache(ctx)
return nil
}
88 changes: 68 additions & 20 deletions x/evm/keeper/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,41 +30,54 @@ import (
feemarkettypes "github.com/evmos/ethermint/x/feemarket/types"
)

// EVMConfig encapsulates common parameters needed to create an EVM to execute a message
// It's mainly to reduce the number of method parameters
type EVMConfig struct {
// EVMBlockConfig encapsulates the common parameters needed to execute an EVM message,
// it's cached in object store during the block execution.
type EVMBlockConfig struct {
Params types.Params
FeeMarketParams feemarkettypes.Params
ChainConfig *params.ChainConfig
CoinBase common.Address
BaseFee *big.Int
TxConfig statedb.TxConfig
Tracer vm.EVMLogger
DebugTrace bool
Overrides *rpctypes.StateOverride
BlockOverrides *rpctypes.BlockOverrides
// not supported, always zero
Random *common.Hash
// unused, always zero
Difficulty *big.Int
// cache the big.Int version of block number, avoid repeated allocation
BlockNumber *big.Int
BlockTime uint64
Rules params.Rules
}

// EVMConfig creates the EVMConfig based on current state
func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress, chainID *big.Int, txHash common.Hash) (*EVMConfig, error) {
// EVMConfig encapsulates common parameters needed to create an EVM to execute a message
// It's mainly to reduce the number of method parameters
type EVMConfig struct {
*EVMBlockConfig
TxConfig statedb.TxConfig
Tracer vm.EVMLogger
DebugTrace bool
Overrides *rpctypes.StateOverride
BlockOverrides *rpctypes.BlockOverrides
}

// EVMBlockConfig creates the EVMBlockConfig based on current state
func (k *Keeper) EVMBlockConfig(ctx sdk.Context, chainID *big.Int) (*EVMBlockConfig, error) {
objStore := ctx.ObjectStore(k.objectKey)
v := objStore.Get(types.KeyPrefixObjectParams)
if v != nil {
return v.(*EVMBlockConfig), nil
}

params := k.GetParams(ctx)
ethCfg := params.ChainConfig.EthereumConfig(chainID)

feemarketParams := k.feeMarketKeeper.GetParams(ctx)

// get the coinbase address from the block proposer
coinbase, err := k.GetCoinbaseAddress(ctx, proposerAddress)
coinbase, err := k.GetCoinbaseAddress(ctx)
if err != nil {
return nil, errorsmod.Wrap(err, "failed to obtain coinbase address")
}

var txConfig statedb.TxConfig
if txHash == (common.Hash{}) {
txConfig = statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))
} else {
txConfig = k.TxConfig(ctx, txHash)
}

var baseFee *big.Int
if types.IsLondon(ethCfg, ctx.BlockHeight()) {
baseFee = feemarketParams.GetBaseFee()
Expand All @@ -74,13 +87,48 @@ func (k *Keeper) EVMConfig(ctx sdk.Context, proposerAddress sdk.ConsAddress, cha
}
}

return &EVMConfig{
blockTime := uint64(ctx.BlockHeader().Time.Unix())
blockNumber := big.NewInt(ctx.BlockHeight())
rules := ethCfg.Rules(blockNumber, ethCfg.MergeNetsplitBlock != nil, blockTime)

var zero common.Hash
cfg := &EVMBlockConfig{
Params: params,
FeeMarketParams: feemarketParams,
ChainConfig: ethCfg,
CoinBase: coinbase,
BaseFee: baseFee,
TxConfig: txConfig,
Difficulty: big.NewInt(0),
Random: &zero,
BlockNumber: blockNumber,
BlockTime: blockTime,
Rules: rules,
}
objStore.Set(types.KeyPrefixObjectParams, cfg)
return cfg, nil
}

func (k *Keeper) RemoveParamsCache(ctx sdk.Context) {
ctx.ObjectStore(k.objectKey).Delete(types.KeyPrefixObjectParams)
}

// EVMConfig creates the EVMConfig based on current state
func (k *Keeper) EVMConfig(ctx sdk.Context, chainID *big.Int, txHash common.Hash) (*EVMConfig, error) {
blockCfg, err := k.EVMBlockConfig(ctx, chainID)
if err != nil {
return nil, err
}

var txConfig statedb.TxConfig
if txHash == (common.Hash{}) {
txConfig = statedb.NewEmptyTxConfig(common.BytesToHash(ctx.HeaderHash()))
} else {
txConfig = k.TxConfig(ctx, txHash)
}

return &EVMConfig{
EVMBlockConfig: blockCfg,
TxConfig: txConfig,
}, nil
}

Expand Down
9 changes: 2 additions & 7 deletions x/evm/keeper/gas.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,8 @@ import (
)

// GetEthIntrinsicGas returns the intrinsic gas cost for the transaction
func (k *Keeper) GetEthIntrinsicGas(ctx sdk.Context, msg core.Message, cfg *params.ChainConfig, isContractCreation bool) (uint64, error) {
height := big.NewInt(ctx.BlockHeight())
homestead := cfg.IsHomestead(height)
istanbul := cfg.IsIstanbul(height)
shanghai := cfg.IsShanghai(uint64(ctx.BlockHeader().Time.Unix()))

return core.IntrinsicGas(msg.Data, msg.AccessList, isContractCreation, homestead, istanbul, shanghai)
func (k *Keeper) GetEthIntrinsicGas(msg core.Message, rules params.Rules, isContractCreation bool) (uint64, error) {
return core.IntrinsicGas(msg.Data, msg.AccessList, isContractCreation, rules.IsHomestead, rules.IsIstanbul, rules.IsShanghai)
}

// RefundGas transfers the leftover gas to the sender of the message, caped to half of the total gas
Expand Down
Loading