diff --git a/ante/evm/11_emit_event.go b/ante/evm/11_emit_event.go index d3541d883..0291f23a2 100644 --- a/ante/evm/11_emit_event.go +++ b/ante/evm/11_emit_event.go @@ -18,7 +18,7 @@ func EmitTxHashEvent(ctx sdk.Context, msg *evmtypes.MsgEthereumTx, blockTxIndex ctx.EventManager().EmitEvent( sdk.NewEvent( evmtypes.EventTypeEthereumTx, - sdk.NewAttribute(evmtypes.AttributeKeyEthereumTxHash, msg.Hash().String()), + sdk.NewAttribute(evmtypes.AttributeKeyEthereumTxHash, msg.AsTransaction().Hash().String()), sdk.NewAttribute(evmtypes.AttributeKeyTxIndex, strconv.FormatUint(blockTxIndex, 10)), // #nosec G115 ), ) diff --git a/ante/tx_listener.go b/ante/tx_listener.go index 7f18bcc71..27f0c338f 100644 --- a/ante/tx_listener.go +++ b/ante/tx_listener.go @@ -27,7 +27,7 @@ func (d TxListenerDecorator) AnteHandle(ctx sdk.Context, tx sdk.Tx, simulate boo if ctx.IsCheckTx() && !simulate && d.pendingTxListener != nil { for _, msg := range tx.GetMsgs() { if ethTx, ok := msg.(*evmtypes.MsgEthereumTx); ok { - d.pendingTxListener(ethTx.Hash()) + d.pendingTxListener(ethTx.AsTransaction().Hash()) } } } diff --git a/indexer/kv_indexer.go b/indexer/kv_indexer.go index 9bf85ccdc..a21471a05 100644 --- a/indexer/kv_indexer.go +++ b/indexer/kv_indexer.go @@ -82,7 +82,7 @@ func (kv *KVIndexer) IndexBlock(block *cmttypes.Block, txResults []*abci.ExecTxR var cumulativeGasUsed uint64 for msgIndex, msg := range tx.GetMsgs() { ethMsg := msg.(*evmtypes.MsgEthereumTx) - txHash := ethMsg.Hash() + txHash := ethMsg.AsTransaction().Hash() txResult := servertypes.TxResult{ Height: height, diff --git a/mempool/mempool.go b/mempool/mempool.go index 532631ed9..ba7a99c4d 100644 --- a/mempool/mempool.go +++ b/mempool/mempool.go @@ -224,7 +224,7 @@ func (m *ExperimentalEVMMempool) Insert(goCtx context.Context, tx sdk.Tx) error ethMsg, err := m.getEVMMessage(tx) if err == nil { // Insert into EVM pool - hash := ethMsg.Hash() + hash := ethMsg.AsTransaction().Hash() m.logger.Debug("inserting EVM transaction", "tx_hash", hash) ethTxs := []*ethtypes.Transaction{ethMsg.AsTransaction()} errs := m.txPool.Add(ethTxs, true) @@ -320,7 +320,7 @@ func (m *ExperimentalEVMMempool) Remove(tx sdk.Tx) error { // We should not do this with EVM transactions because removing them causes the subsequent ones to // be dequeued as temporarily invalid, only to be requeued a block later. // The EVM mempool handles removal based on account nonce automatically. - hash := msg.Hash() + hash := msg.AsTransaction().Hash() if m.shouldRemoveFromEVMPool(tx) { m.logger.Debug("manually removing EVM transaction", "tx_hash", hash) m.legacyTxPool.RemoveTx(hash, false, true) diff --git a/rpc/backend/backend.go b/rpc/backend/backend.go index 06079229d..be61d9efa 100644 --- a/rpc/backend/backend.go +++ b/rpc/backend/backend.go @@ -20,6 +20,7 @@ import ( evmmempool "github.com/cosmos/evm/mempool" "github.com/cosmos/evm/rpc/types" + "github.com/cosmos/evm/rpc/types/interfaces" "github.com/cosmos/evm/server/config" servertypes "github.com/cosmos/evm/server/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -74,7 +75,7 @@ type EVMBackend interface { CometBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) BlockNumberFromComet(blockNrOrHash types.BlockNumberOrHash) (types.BlockNumber, error) BlockNumberFromCometByHash(blockHash common.Hash) (*big.Int, error) - EthMsgsFromCometBlock(block *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) []*evmtypes.MsgEthereumTx + EthMsgsFromCometBlock(block *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) []interfaces.IMsgEthereumTx BlockBloomFromCometBlock(blockRes *tmrpctypes.ResultBlockResults) (ethtypes.Bloom, error) HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) diff --git a/rpc/backend/comet_to_eth.go b/rpc/backend/comet_to_eth.go index 8b4847726..673393dd7 100644 --- a/rpc/backend/comet_to_eth.go +++ b/rpc/backend/comet_to_eth.go @@ -14,6 +14,7 @@ import ( cmtrpctypes "github.com/cometbft/cometbft/rpc/core/types" rpctypes "github.com/cosmos/evm/rpc/types" + "github.com/cosmos/evm/rpc/types/interfaces" evmtypes "github.com/cosmos/evm/x/vm/types" sdk "github.com/cosmos/cosmos-sdk/types" @@ -87,8 +88,8 @@ func (b *Backend) BlockNumberFromCometByHash(blockHash common.Hash) (*big.Int, e func (b *Backend) EthMsgsFromCometBlock( resBlock *cmtrpctypes.ResultBlock, blockRes *cmtrpctypes.ResultBlockResults, -) []*evmtypes.MsgEthereumTx { - var result []*evmtypes.MsgEthereumTx +) []interfaces.IMsgEthereumTx { + var result []interfaces.IMsgEthereumTx block := resBlock.Block txResults := blockRes.TxsResults @@ -110,7 +111,7 @@ func (b *Backend) EthMsgsFromCometBlock( } for _, msg := range tx.GetMsgs() { - ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) + ethMsg, ok := msg.(interfaces.IMsgEthereumTx) if !ok { continue } @@ -225,7 +226,7 @@ func (b *Backend) MinerFromCometBlock( func (b *Backend) ReceiptsFromCometBlock( resBlock *cmtrpctypes.ResultBlock, blockRes *cmtrpctypes.ResultBlockResults, - msgs []*evmtypes.MsgEthereumTx, + msgs []interfaces.IMsgEthereumTx, ) ([]*ethtypes.Receipt, error) { baseFee, err := b.BaseFee(blockRes) if err != nil { @@ -237,18 +238,19 @@ func (b *Backend) ReceiptsFromCometBlock( receipts := make([]*ethtypes.Receipt, len(msgs)) cumulatedGasUsed := uint64(0) for i, ethMsg := range msgs { - txResult, err := b.GetTxByEthHash(ethMsg.Hash()) + tx := ethMsg.AsTransaction() + txResult, err := b.GetTxByEthHash(tx.Hash()) if err != nil { - return nil, fmt.Errorf("tx not found: hash=%s, error=%s", ethMsg.Hash(), err.Error()) + return nil, fmt.Errorf("tx not found: hash=%s, error=%s", tx.Hash().Hex(), err.Error()) } cumulatedGasUsed += txResult.GasUsed var effectiveGasPrice *big.Int if baseFee != nil { - effectiveGasPrice = rpctypes.EffectiveGasPrice(ethMsg.Raw.Transaction, baseFee) + effectiveGasPrice = rpctypes.EffectiveGasPrice(tx, baseFee) } else { - effectiveGasPrice = ethMsg.Raw.GasFeeCap() + effectiveGasPrice = tx.GasFeeCap() } var status uint64 @@ -259,8 +261,8 @@ func (b *Backend) ReceiptsFromCometBlock( } contractAddress := common.Address{} - if ethMsg.Raw.To() == nil { - contractAddress = crypto.CreateAddress(ethMsg.GetSender(), ethMsg.Raw.Nonce()) + if tx.To() == nil { + contractAddress = crypto.CreateAddress(common.Address(ethMsg.GetFrom().Bytes()), tx.Nonce()) } msgIndex := int(txResult.MsgIndex) // #nosec G115 -- checked for int overflow already @@ -277,7 +279,7 @@ func (b *Backend) ReceiptsFromCometBlock( receipt := ðtypes.Receipt{ // Consensus fields: These fields are defined by the Yellow Paper - Type: ethMsg.Raw.Type(), + Type: tx.Type(), PostState: nil, Status: status, // convert to 1=success, 0=failure CumulativeGasUsed: cumulatedGasUsed, @@ -285,7 +287,7 @@ func (b *Backend) ReceiptsFromCometBlock( Logs: logs, // Implementation fields: These fields are added by geth when processing a transaction. - TxHash: ethMsg.Hash(), + TxHash: tx.Hash(), ContractAddress: contractAddress, GasUsed: txResult.GasUsed, EffectiveGasPrice: effectiveGasPrice, diff --git a/rpc/backend/tx_info.go b/rpc/backend/tx_info.go index 9c84198ff..5f73c3c8f 100644 --- a/rpc/backend/tx_info.go +++ b/rpc/backend/tx_info.go @@ -20,6 +20,7 @@ import ( "github.com/cosmos/evm/mempool/txpool" rpctypes "github.com/cosmos/evm/rpc/types" + "github.com/cosmos/evm/rpc/types/interfaces" servertypes "github.com/cosmos/evm/server/types" "github.com/cosmos/evm/utils" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -47,7 +48,7 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac } // the `res.MsgIndex` is inferred from tx index, should be within the bound. - msg, ok := tx.GetMsgs()[res.MsgIndex].(*evmtypes.MsgEthereumTx) + msg, ok := tx.GetMsgs()[res.MsgIndex].(interfaces.IMsgEthereumTx) if !ok { return nil, errors.New("invalid ethereum tx") } @@ -62,7 +63,7 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac // Fallback to find tx index by iterating all valid eth transactions msgs := b.EthMsgsFromCometBlock(block, blockRes) for i := range msgs { - if msgs[i].Hash() == txHash { + if msgs[i].AsTransaction().Hash() == txHash { if i > math.MaxInt32 { return nil, errors.New("tx index overflow") } @@ -113,7 +114,7 @@ func (b *Backend) GetTransactionByHashPending(txHash common.Hash) (*rpctypes.RPC continue } - if msg.Hash() == txHash { + if msg.AsTransaction().Hash() == txHash { // use zero block values since it's not included in a block yet return rpctypes.NewTransactionFromMsg( msg, @@ -192,8 +193,8 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ return nil, fmt.Errorf("block result not found at height %d: %w", res.Height, err) } - ethMsg := tx.GetMsgs()[res.MsgIndex].(*evmtypes.MsgEthereumTx) - receipts, err := b.ReceiptsFromCometBlock(resBlock, blockRes, []*evmtypes.MsgEthereumTx{ethMsg}) + ethMsg := tx.GetMsgs()[res.MsgIndex].(interfaces.IMsgEthereumTx) + receipts, err := b.ReceiptsFromCometBlock(resBlock, blockRes, []interfaces.IMsgEthereumTx{ethMsg}) if err != nil { return nil, fmt.Errorf("failed to get receipts from comet block") } @@ -364,7 +365,7 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *cmtrpctypes.ResultBlock, return nil, nil } - var msg *evmtypes.MsgEthereumTx + var msg interfaces.IMsgEthereumTx // find in tx indexer res, err := b.GetTxByTxIndex(block.Block.Height, uint(idx)) if err == nil { @@ -376,7 +377,7 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *cmtrpctypes.ResultBlock, var ok bool // msgIndex is inferred from tx events, should be within bound. - msg, ok = tx.GetMsgs()[res.MsgIndex].(*evmtypes.MsgEthereumTx) + msg, ok = tx.GetMsgs()[res.MsgIndex].(interfaces.IMsgEthereumTx) if !ok { b.Logger.Debug("invalid ethereum tx", "height", block.Block.Header, "index", idx) return nil, nil diff --git a/rpc/backend/utils.go b/rpc/backend/utils.go index ca46109b0..9243626fd 100644 --- a/rpc/backend/utils.go +++ b/rpc/backend/utils.go @@ -19,6 +19,7 @@ import ( cmtrpctypes "github.com/cometbft/cometbft/rpc/core/types" "github.com/cosmos/evm/rpc/types" + "github.com/cosmos/evm/rpc/types/interfaces" "github.com/cosmos/evm/utils" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -91,7 +92,7 @@ func (b *Backend) getAccountNonce(accAddr common.Address, pending bool, height i // only supports `MsgEthereumTx` style tx for _, tx := range pendingTxs { for _, msg := range (*tx).GetMsgs() { - ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) + ethMsg, ok := msg.(interfaces.IMsgEthereumTx) if !ok { // not ethereum tx break @@ -247,7 +248,7 @@ func (b *Backend) ProcessBlock( } txGasUsed := uint64(cometTxResult.GasUsed) // #nosec G115 for _, msg := range tx.GetMsgs() { - ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) + ethMsg, ok := msg.(interfaces.IMsgEthereumTx) if !ok { continue } diff --git a/rpc/types/events.go b/rpc/types/events.go index 34761d811..13aeb66b8 100644 --- a/rpc/types/events.go +++ b/rpc/types/events.go @@ -9,6 +9,7 @@ import ( abci "github.com/cometbft/cometbft/abci/types" cmtrpctypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cosmos/evm/rpc/types/interfaces" "github.com/cosmos/evm/server/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -133,7 +134,7 @@ func ParseTxResult(result *abci.ExecTxResult, tx sdk.Tx) (*ParsedTxs, error) { p.Txs[i].Failed = true // replace gasUsed with gasLimit because that's what's actually deducted. - gasLimit := tx.GetMsgs()[i].(*evmtypes.MsgEthereumTx).GetGas() + gasLimit := tx.GetMsgs()[i].(interfaces.IMsgEthereumTx).GetGas() p.Txs[i].GasUsed = gasLimit } } diff --git a/rpc/types/interfaces/interface.go b/rpc/types/interfaces/interface.go new file mode 100644 index 000000000..b4fd7b086 --- /dev/null +++ b/rpc/types/interfaces/interface.go @@ -0,0 +1,22 @@ +package interfaces + +import ( + "math/big" + + 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" +) + +type IMsgEthereumTx interface { + FromEthereumTx(tx *ethtypes.Transaction) + FromSignedEthereumTx(tx *ethtypes.Transaction, signer ethtypes.Signer) error + GetFrom() sdk.AccAddress + GetGas() uint64 + GetEffectiveFee(baseFee *big.Int) *big.Int + AsTransaction() *ethtypes.Transaction + GetSenderLegacy(signer ethtypes.Signer) (common.Address, error) + AsMessage(baseFee *big.Int) *core.Message + UnmarshalBinary(b []byte, signer ethtypes.Signer) error +} diff --git a/rpc/types/utils.go b/rpc/types/utils.go index d2554f7be..1cdba242f 100644 --- a/rpc/types/utils.go +++ b/rpc/types/utils.go @@ -18,6 +18,7 @@ import ( cmtrpccore "github.com/cometbft/cometbft/rpc/core/types" cmttypes "github.com/cometbft/cometbft/types" + "github.com/cosmos/evm/rpc/types/interfaces" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" evmtypes "github.com/cosmos/evm/x/vm/types" @@ -38,15 +39,15 @@ const ExceedBlockGasLimitError = "out of gas in location: block gas meter; gasWa const StateDBCommitError = "failed to commit stateDB" // RawTxToEthTx returns a evm MsgEthereum transaction from raw tx bytes. -func RawTxToEthTx(clientCtx client.Context, txBz cmttypes.Tx) ([]*evmtypes.MsgEthereumTx, error) { +func RawTxToEthTx(clientCtx client.Context, txBz cmttypes.Tx) ([]interfaces.IMsgEthereumTx, error) { tx, err := clientCtx.TxConfig.TxDecoder()(txBz) if err != nil { return nil, errorsmod.Wrap(errortypes.ErrJSONUnmarshal, err.Error()) } - ethTxs := make([]*evmtypes.MsgEthereumTx, len(tx.GetMsgs())) + ethTxs := make([]interfaces.IMsgEthereumTx, len(tx.GetMsgs())) for i, msg := range tx.GetMsgs() { - ethTx, ok := msg.(*evmtypes.MsgEthereumTx) + ethTx, ok := msg.(interfaces.IMsgEthereumTx) if !ok { return nil, fmt.Errorf("invalid message type %T, expected %T", msg, &evmtypes.MsgEthereumTx{}) } @@ -155,7 +156,7 @@ func MakeHeader( // NewTransactionFromMsg returns a transaction that will serialize to the RPC // representation, with the given location metadata set (if available). func NewTransactionFromMsg( - msg *evmtypes.MsgEthereumTx, + msg interfaces.IMsgEthereumTx, blockHash common.Hash, blockNumber, blockTime, index uint64, baseFee *big.Int, @@ -429,7 +430,7 @@ func RPCMarshalHeader(head *ethtypes.Header, blockHash []byte) map[string]interf // // This method refers to go-ethereum v1.16.3 internal package method - RPCMarshalBlock // (https://github.com/ethereum/go-ethereum/blob/d818a9af7bd5919808df78f31580f59382c53150/internal/ethapi/api.go#L929-L962) -func RPCMarshalBlock(block *ethtypes.Block, cmtBlock *cmtrpccore.ResultBlock, msgs []*evmtypes.MsgEthereumTx, inclTx bool, fullTx bool, config *ethparams.ChainConfig) (map[string]interface{}, error) { +func RPCMarshalBlock(block *ethtypes.Block, cmtBlock *cmtrpccore.ResultBlock, msgs []interfaces.IMsgEthereumTx, inclTx bool, fullTx bool, config *ethparams.ChainConfig) (map[string]interface{}, error) { blockHash := cmtBlock.BlockID.Hash.Bytes() fields := RPCMarshalHeader(block.Header(), blockHash) fields["size"] = hexutil.Uint64(block.Size()) diff --git a/x/vm/types/msg.go b/x/vm/types/msg.go index f07099837..1f0ecf728 100644 --- a/x/vm/types/msg.go +++ b/x/vm/types/msg.go @@ -13,6 +13,7 @@ import ( protov2 "google.golang.org/protobuf/proto" evmapi "github.com/cosmos/evm/api/cosmos/evm/vm/v1" + "github.com/cosmos/evm/rpc/types/interfaces" errorsmod "cosmossdk.io/errors" sdkmath "cosmossdk.io/math" @@ -30,10 +31,11 @@ import ( ) var ( - _ sdk.Msg = &MsgEthereumTx{} - _ sdk.Tx = &MsgEthereumTx{} - _ ante.GasTx = &MsgEthereumTx{} - _ sdk.Msg = &MsgUpdateParams{} + _ sdk.Msg = &MsgEthereumTx{} + _ sdk.Tx = &MsgEthereumTx{} + _ ante.GasTx = &MsgEthereumTx{} + _ interfaces.IMsgEthereumTx = &MsgEthereumTx{} + _ sdk.Msg = &MsgUpdateParams{} ) // message type and route constants @@ -298,10 +300,6 @@ func (msg *MsgEthereumTx) UnmarshalBinary(b []byte, signer ethtypes.Signer) erro return msg.FromSignedEthereumTx(tx, signer) } -func (msg *MsgEthereumTx) Hash() common.Hash { - return msg.AsTransaction().Hash() -} - // BuildTx builds the canonical cosmos tx from ethereum msg func (msg *MsgEthereumTx) BuildTx(b client.TxBuilder, evmDenom string) (signing.Tx, error) { return msg.BuildTxWithEvmParams(b, Params{