From 5f7c4c368b8a1e5c25a5916a13bf6f331e7a667c Mon Sep 17 00:00:00 2001 From: yihuang Date: Wed, 15 Mar 2023 11:22:57 +0800 Subject: [PATCH] Problem: repeated tx sender recovery is wastful Solution: - only do once in ante handler, reuse the result * Update CHANGELOG.md Signed-off-by: yihuang * Update x/evm/types/msg.go Co-authored-by: mmsqe Signed-off-by: yihuang * return value * fix unit test --------- Signed-off-by: yihuang Co-authored-by: mmsqe --- CHANGELOG.md | 16 +-------- x/evm/keeper/msg_server.go | 2 +- x/evm/keeper/state_transition.go | 7 ++-- .../keeper/state_transition_benchmark_test.go | 8 +++-- x/evm/types/msg.go | 34 ++++++++++++++++++- 5 files changed, 45 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0904e251f7..40d16ccc71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,21 +53,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements * (cli) [#1615](https://github.com/evmos/ethermint/pull/1615) Support customize db opener in `StartCmd`. -* (evm) [#1582](https://github.com/evmos/ethermint/pull/1582) Cleanup `evm` files -* (evm) [#1544](https://github.com/evmos/ethermint/pull/1544) Migrate deprecated event emitting to new `TypedEvent` -* (deps) [#1532](https://github.com/evmos/ethermint/pull/1532) Upgrade Go-Ethereum version to [`v1.10.26`](https://github.com/ethereum/go-ethereum/releases/tag/v1.10.26). - -### Bug Fixes - -* (upgrade) [#1617](https://github.com/evmos/ethermint/pull/1617) Refactor `evm` module's parameters to store them under a single store key -* (rpc) [#1600](https://github.com/evmos/ethermint/pull/1600) Revert changes from `TypedEvents` -* (rpc) [#1613](https://github.com/evmos/ethermint/pull/1613) Change the default json-rpc listen address to localhost. -* (rpc) [#1611](https://github.com/evmos/ethermint/pull/1611) Add missing next fee in fee history, fix wrong oldestBlock and align earliest input as ethereum. -* (proto) [#1586](https://github.com/evmos/ethermint/pull/1586) Avoid duplicate register proto type in `evm` & `feemarket` -* (rpc) [#1638](https://github.com/evmos/ethermint/pull/1638) Align results when querying `eth_getTransactionCount` for future blocks for accounts with zero and non-zero transaction counts. -* (rpc) [#1639](https://github.com/evmos/ethermint/pull/1639) Align block number input behaviour for `eth_getProof` as Ethereum. - -## [v0.20.0] - 2022-12-28 +* (ante) [#227](https://github.com/crypto-org-chain/ethermint/pull/227) Reuse sender recovery result. ### State Machine Breaking diff --git a/x/evm/keeper/msg_server.go b/x/evm/keeper/msg_server.go index 0e1b7eb6d5..0a96b48917 100644 --- a/x/evm/keeper/msg_server.go +++ b/x/evm/keeper/msg_server.go @@ -56,7 +56,7 @@ func (k *Keeper) EthereumTx(goCtx context.Context, msg *types.MsgEthereumTx) (*t labels = append(labels, telemetry.NewLabel("execution", "call")) } - response, err := k.ApplyTransaction(ctx, tx) + response, err := k.ApplyTransaction(ctx, msg) if err != nil { return nil, errorsmod.Wrap(err, "failed to apply transaction") } diff --git a/x/evm/keeper/state_transition.go b/x/evm/keeper/state_transition.go index ad90dba5fd..3c5ab28ff5 100644 --- a/x/evm/keeper/state_transition.go +++ b/x/evm/keeper/state_transition.go @@ -146,7 +146,7 @@ func (k Keeper) GetHashFn(ctx sdk.Context) vm.GetHashFunc { // returning. // // For relevant discussion see: https://github.com/cosmos/cosmos-sdk/discussions/9072 -func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*types.MsgEthereumTxResponse, error) { +func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *types.MsgEthereumTx) (*types.MsgEthereumTxResponse, error) { var ( bloom *big.Int bloomReceipt ethtypes.Bloom @@ -156,7 +156,8 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t if err != nil { return nil, errorsmod.Wrap(err, "failed to load evm config") } - txConfig := k.TxConfig(ctx, tx.Hash()) + ethTx := tx.AsTransaction() + txConfig := k.TxConfig(ctx, ethTx.Hash()) // get the signer according to the chain rules from the config and block height signer := ethtypes.MakeSigner(cfg.ChainConfig, big.NewInt(ctx.BlockHeight())) @@ -206,7 +207,7 @@ func (k *Keeper) ApplyTransaction(ctx sdk.Context, tx *ethtypes.Transaction) (*t } receipt := ðtypes.Receipt{ - Type: tx.Type(), + Type: ethTx.Type(), PostState: nil, // TODO: intermediate state root CumulativeGasUsed: cumulativeGasUsed, Bloom: bloomReceipt, diff --git a/x/evm/keeper/state_transition_benchmark_test.go b/x/evm/keeper/state_transition_benchmark_test.go index 77df3af9ef..68e93d1ce5 100644 --- a/x/evm/keeper/state_transition_benchmark_test.go +++ b/x/evm/keeper/state_transition_benchmark_test.go @@ -46,7 +46,7 @@ func newSignedEthTx( addr sdk.Address, krSigner keyring.Signer, ethSigner ethtypes.Signer, -) (*ethtypes.Transaction, error) { +) (*evmtypes.MsgEthereumTx, error) { var ethTx *ethtypes.Transaction switch txData := txData.(type) { case *ethtypes.AccessListTx: @@ -72,7 +72,11 @@ func newSignedEthTx( return nil, err } - return ethTx, nil + var msg evmtypes.MsgEthereumTx + if err := msg.FromEthereumTx(ethTx); err != nil { + return nil, err + } + return &msg, nil } func newEthMsgTx( diff --git a/x/evm/types/msg.go b/x/evm/types/msg.go index f227e36a75..eadbd4d12c 100644 --- a/x/evm/types/msg.go +++ b/x/evm/types/msg.go @@ -35,6 +35,7 @@ import ( "github.com/evmos/ethermint/types" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/core" ethtypes "github.com/ethereum/go-ethereum/core/types" ) @@ -325,7 +326,38 @@ func (msg MsgEthereumTx) AsTransaction() *ethtypes.Transaction { // AsMessage creates an Ethereum core.Message from the msg fields func (msg MsgEthereumTx) AsMessage(signer ethtypes.Signer, baseFee *big.Int) (core.Message, error) { - return msg.AsTransaction().AsMessage(signer, baseFee) + txData, err := UnpackTxData(msg.Data) + if err != nil { + return nil, err + } + + gasPrice, gasFeeCap, gasTipCap := txData.GetGasPrice(), txData.GetGasFeeCap(), txData.GetGasTipCap() + if baseFee != nil { + gasPrice = math.BigMin(gasPrice.Add(gasTipCap, baseFee), gasFeeCap) + } + var from common.Address + if len(msg.From) > 0 { + from = common.HexToAddress(msg.From) + } else { + // heavy path + from, err = signer.Sender(msg.AsTransaction()) + if err != nil { + return nil, err + } + } + ethMsg := ethtypes.NewMessage( + from, + txData.GetTo(), + txData.GetNonce(), + txData.GetValue(), + txData.GetGas(), + gasPrice, gasFeeCap, gasTipCap, + txData.GetData(), + txData.GetAccessList(), + false, + ) + + return ethMsg, nil } // GetSender extracts the sender address from the signature values using the latest signer for the given chainID.