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

Benchmark evm keeper #586

Merged
merged 9 commits into from
Sep 24, 2021
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) [tharsis#461](https://github.com/tharsis/ethermint/pull/461) Increase performance of `StateDB` transaction log storage (r/w).
* (evm) [tharsis#566](https://github.com/tharsis/ethermint/pull/566) Introduce `stateErr` store in `StateDB` to avoid meaningless operations if any error happened before
* (evm) [tharsis#586](https://github.com/tharsis/ethermint/pull/586) Benchmark evm keeper

## [v0.5.0] - 2021-08-20

Expand Down
18 changes: 18 additions & 0 deletions x/evm/keeper/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,21 @@ func BenchmarkEmitLogs(b *testing.B) {
return types.NewTx(suite.app.EvmKeeper.ChainID(), nonce, &contract, big.NewInt(0), 4100000, big.NewInt(1), input, nil)
})
}

func BenchmarkTokenTransferFrom(b *testing.B) {
DoBenchmark(b, func(suite *KeeperTestSuite, contract common.Address) *types.MsgEthereumTx {
input, err := ContractABI.Pack("transferFrom", suite.address, common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(0))
require.NoError(b, err)
nonce := suite.app.EvmKeeper.GetNonce(suite.address)
return types.NewTx(suite.app.EvmKeeper.ChainID(), nonce, &contract, big.NewInt(0), 410000, big.NewInt(1), input, nil)
})
}

func BenchmarkTokenMint(b *testing.B) {
DoBenchmark(b, func(suite *KeeperTestSuite, contract common.Address) *types.MsgEthereumTx {
input, err := ContractABI.Pack("mint", common.HexToAddress("0x378c50D9264C63F3F92B806d4ee56E9D86FfB3Ec"), big.NewInt(1000))
require.NoError(b, err)
nonce := suite.app.EvmKeeper.GetNonce(suite.address)
return types.NewTx(suite.app.EvmKeeper.ChainID(), nonce, &contract, big.NewInt(0), 410000, big.NewInt(1), input, nil)
})
}
220 changes: 220 additions & 0 deletions x/evm/keeper/state_transition_benchmark_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
package keeper_test

import (
"errors"
"math/big"
"testing"

"github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
evmtypes "github.com/tharsis/ethermint/x/evm/types"
)

var templateAccessListTx = &ethtypes.AccessListTx{
GasPrice: big.NewInt(1),
Gas: 21000,
To: &common.Address{},
Value: big.NewInt(0),
Data: []byte{},
}

var templateLegacyTx = &ethtypes.LegacyTx{
GasPrice: big.NewInt(1),
Gas: 21000,
To: &common.Address{},
Value: big.NewInt(0),
Data: []byte{},
}

func newSignedEthTx(
txData ethtypes.TxData,
nonce uint64,
addr sdk.Address,
krSigner keyring.Signer,
ethSigner ethtypes.Signer,
) (*ethtypes.Transaction, error) {
var ethTx *ethtypes.Transaction
switch txData := txData.(type) {
case *ethtypes.AccessListTx:
txData.Nonce = nonce
ethTx = ethtypes.NewTx(txData)
case *ethtypes.LegacyTx:
txData.Nonce = nonce
ethTx = ethtypes.NewTx(txData)
default:
return nil, errors.New("unknown transaction type!")
}

sig, _, err := krSigner.SignByAddress(addr, ethTx.Hash().Bytes())
if err != nil {
return nil, err
}

ethTx, err = ethTx.WithSignature(ethSigner, sig)
if err != nil {
return nil, err
}

return ethTx, nil
}

func newNativeMessage(
nonce uint64,
blockHeight int64,
address common.Address,
cfg *params.ChainConfig,
krSigner keyring.Signer,
ethSigner ethtypes.Signer,
isLegacy bool,
) (core.Message, error) {
msgSigner := ethtypes.MakeSigner(cfg, big.NewInt(blockHeight))

var ethTx *ethtypes.Transaction
if isLegacy {
templateLegacyTx.Nonce = nonce
ethTx = ethtypes.NewTx(templateLegacyTx)
} else {
templateAccessListTx.Nonce = nonce
ethTx = ethtypes.NewTx(templateAccessListTx)
}

msg := &evmtypes.MsgEthereumTx{}
msg.FromEthereumTx(ethTx)
msg.From = address.Hex()

if err := msg.Sign(ethSigner, krSigner); err != nil {
return nil, err
}

m, err := msg.AsMessage(msgSigner)
if err != nil {
return nil, err
}

return m, nil
}

func BenchmarkApplyTransaction(b *testing.B) {
suite := KeeperTestSuite{}
suite.DoSetupTest(b)

ethSigner := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())

b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
b.StopTimer()
tx, err := newSignedEthTx(templateAccessListTx,
suite.app.EvmKeeper.GetNonce(suite.address),
sdk.AccAddress(suite.address.Bytes()),
suite.signer,
ethSigner,
)
require.NoError(b, err)

b.StartTimer()
resp, err := suite.app.EvmKeeper.ApplyTransaction(tx)
b.StopTimer()

require.NoError(b, err)
require.False(b, resp.Failed())
}
}

func BenchmarkApplyTransactionWithLegacyTx(b *testing.B) {
suite := KeeperTestSuite{}
suite.DoSetupTest(b)

ethSigner := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())

b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
b.StopTimer()
tx, err := newSignedEthTx(templateLegacyTx,
suite.app.EvmKeeper.GetNonce(suite.address),
sdk.AccAddress(suite.address.Bytes()),
suite.signer,
ethSigner,
)
require.NoError(b, err)

b.StartTimer()
resp, err := suite.app.EvmKeeper.ApplyTransaction(tx)
b.StopTimer()

require.NoError(b, err)
require.False(b, resp.Failed())
}
}

func BenchmarkApplyNativeMessage(b *testing.B) {
suite := KeeperTestSuite{}
suite.DoSetupTest(b)

params := suite.app.EvmKeeper.GetParams(suite.ctx)
ethCfg := params.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
signer := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())

b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
b.StopTimer()

m, err := newNativeMessage(
suite.app.EvmKeeper.GetNonce(suite.address),
suite.ctx.BlockHeight(),
suite.address,
ethCfg,
suite.signer,
signer,
false,
)
require.NoError(b, err)

b.StartTimer()
resp, err := suite.app.EvmKeeper.ApplyNativeMessage(m)
b.StopTimer()

require.NoError(b, err)
require.False(b, resp.Failed())
}
}

func BenchmarkApplyNativeMessageWithLegacyTx(b *testing.B) {
suite := KeeperTestSuite{}
suite.DoSetupTest(b)

params := suite.app.EvmKeeper.GetParams(suite.ctx)
ethCfg := params.ChainConfig.EthereumConfig(suite.app.EvmKeeper.ChainID())
signer := ethtypes.LatestSignerForChainID(suite.app.EvmKeeper.ChainID())

b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
b.StopTimer()

m, err := newNativeMessage(
suite.app.EvmKeeper.GetNonce(suite.address),
suite.ctx.BlockHeight(),
suite.address,
ethCfg,
suite.signer,
signer,
true,
)
require.NoError(b, err)

b.StartTimer()
resp, err := suite.app.EvmKeeper.ApplyNativeMessage(m)
b.StopTimer()

require.NoError(b, err)
require.False(b, resp.Failed())
}
}
54 changes: 54 additions & 0 deletions x/evm/keeper/statedb_benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,57 @@ func BenchmarkSnapshot(b *testing.B) {
})
}
}

func BenchmarkSubBalance(b *testing.B) {
suite := KeeperTestSuite{}
suite.DoSetupTest(b)

amt := big.NewInt(10)

b.ResetTimer()
b.ReportAllocs()

for i := 0; i < b.N; i++ {
suite.app.EvmKeeper.SubBalance(suite.address, amt)
}
}

func BenchmarkSetNonce(b *testing.B) {
suite := KeeperTestSuite{}
suite.DoSetupTest(b)

b.ResetTimer()
b.ReportAllocs()

for i := 0; i < b.N; i++ {
suite.app.EvmKeeper.SetNonce(suite.address, 1)
}
}

func BenchmarkAddRefund(b *testing.B) {
suite := KeeperTestSuite{}
suite.DoSetupTest(b)

b.ResetTimer()
b.ReportAllocs()

for i := 0; i < b.N; i++ {
suite.app.EvmKeeper.AddRefund(1)
}
}

func BenchmarkSuicide(b *testing.B) {
suite := KeeperTestSuite{}
suite.DoSetupTest(b)

b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
b.StopTimer()
addr := tests.GenerateAddress()
suite.app.EvmKeeper.CreateAccount(addr)
b.StartTimer()

suite.app.EvmKeeper.Suicide(addr)
}
}