diff --git a/CHANGELOG.md b/CHANGELOG.md index d249a64b28..75aada6eed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -60,6 +60,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (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). +* (ante) [#1717](https://github.com/evmos/ethermint/pull/1717) Reuse sender recovery result. ### Bug Fixes 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..5327052a37 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, msgEth *types.MsgEthereumTx) (*types.MsgEthereumTxResponse, error) { var ( bloom *big.Int bloomReceipt ethtypes.Bloom @@ -156,11 +156,12 @@ 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 := msgEth.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())) - msg, err := tx.AsMessage(signer, cfg.BaseFee) + msg, err := msgEth.AsMessage(signer, cfg.BaseFee) if err != nil { return nil, errorsmod.Wrap(err, "failed to return ethereum transaction as core message") } @@ -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..71164c593e 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,42 @@ 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 { + // user can't set arbitrary value in `From` field in transaction, + // the SigVerify ante handler will verify the signature and recover + // the sender address and populate the `From` field, so the other code can + // use it directly when available. + 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.