diff --git a/CHANGELOG.md b/CHANGELOG.md index 66ecd33b3..3abd75137 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - [\#687](https://github.com/cosmos/evm/pull/687) Avoid blocking node shutdown when evm indexer is enabled, log startup failures instead of using errgroup. - [\#689](https://github.com/cosmos/evm/pull/689) Align debug addr for hex address. - [\#668](https://github.com/cosmos/evm/pull/668) Fix panic in legacy mempool when Reset() was called with a skipped header between old and new block. +- [\#725](https://github.com/cosmos/evm/pull/725) Fix inconsistent block hash in json-rpc. - [\#727](https://github.com/cosmos/evm/pull/727) Avoid nil pointer for `tx evm raw` due to uninitialized EVM coin info. - [\#730](https://github.com/cosmos/evm/pull/730) Fix panic if evm mempool not used. - [\#733](https://github.com/cosmos/evm/pull/733) Avoid rejecting tx with unsupported extension option for ExtensionOptionDynamicFeeTx. diff --git a/rpc/backend/comet_to_eth.go b/rpc/backend/comet_to_eth.go index a56112181..20345c38b 100644 --- a/rpc/backend/comet_to_eth.go +++ b/rpc/backend/comet_to_eth.go @@ -25,13 +25,12 @@ func (b *Backend) RPCHeaderFromCometBlock( resBlock *cmtrpctypes.ResultBlock, blockRes *cmtrpctypes.ResultBlockResults, ) (map[string]interface{}, error) { - cmtBlock := resBlock.Block ethBlock, err := b.EthBlockFromCometBlock(resBlock, blockRes) if err != nil { return nil, fmt.Errorf("failed to get rpc block from comet block: %w", err) } - return rpctypes.RPCMarshalHeader(ethBlock.Header(), cmtBlock.Header), nil + return rpctypes.RPCMarshalHeader(ethBlock.Header(), resBlock.BlockID.Hash), nil } // RPCBlockFromCometBlock returns a JSON-RPC compatible Ethereum block from a @@ -41,14 +40,13 @@ func (b *Backend) RPCBlockFromCometBlock( blockRes *cmtrpctypes.ResultBlockResults, fullTx bool, ) (map[string]interface{}, error) { - cmtBlock := resBlock.Block msgs := b.EthMsgsFromCometBlock(resBlock, blockRes) ethBlock, err := b.EthBlockFromCometBlock(resBlock, blockRes) if err != nil { return nil, fmt.Errorf("failed to get rpc block from comet block: %w", err) } - return rpctypes.RPCMarshalBlock(ethBlock, cmtBlock, msgs, true, fullTx, b.ChainConfig()) + return rpctypes.RPCMarshalBlock(ethBlock, resBlock, msgs, true, fullTx, b.ChainConfig()) } // BlockNumberFromComet returns the BlockNumber from BlockNumberOrHash @@ -235,7 +233,7 @@ func (b *Backend) ReceiptsFromCometBlock( b.Logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", resBlock.Block.Height, "error", err) } - blockHash := common.BytesToHash(resBlock.Block.Header.Hash()) + blockHash := common.BytesToHash(resBlock.BlockID.Hash) receipts := make([]*ethtypes.Receipt, len(msgs)) cumulatedGasUsed := uint64(0) for i, ethMsg := range msgs { diff --git a/rpc/backend/tx_info.go b/rpc/backend/tx_info.go index fbbd13a1e..9c84198ff 100644 --- a/rpc/backend/tx_info.go +++ b/rpc/backend/tx_info.go @@ -403,7 +403,7 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *cmtrpctypes.ResultBlock, index := uint64(idx) // #nosec G115 -- checked for int overflow already return rpctypes.NewTransactionFromMsg( msg, - common.BytesToHash(block.Block.Hash()), + common.BytesToHash(block.BlockID.Hash), height, blockTime, index, diff --git a/rpc/stream/rpc.go b/rpc/stream/rpc.go index 49b8b611b..684f09468 100644 --- a/rpc/stream/rpc.go +++ b/rpc/stream/rpc.go @@ -165,7 +165,7 @@ func (s *RPCStream) start( // TODO: After indexer improvement, we should get eth header event from indexer // Currently, many fields are missing or incorrect (e.g. bloom, receiptsRoot, ...) header := types.EthHeaderFromComet(data.Block.Header, ethtypes.Bloom{}, baseFee) - s.headerStream.Add(RPCHeader{EthHeader: header, Hash: common.BytesToHash(data.Block.Header.Hash())}) + s.headerStream.Add(RPCHeader{EthHeader: header, Hash: common.BytesToHash(data.BlockID.Hash)}) case ev, ok := <-chLogs: if !ok { diff --git a/rpc/types/utils.go b/rpc/types/utils.go index 88600ce28..d2554f7be 100644 --- a/rpc/types/utils.go +++ b/rpc/types/utils.go @@ -15,6 +15,7 @@ import ( abci "github.com/cometbft/cometbft/abci/types" cmtrpcclient "github.com/cometbft/cometbft/rpc/client" + cmtrpccore "github.com/cometbft/cometbft/rpc/core/types" cmttypes "github.com/cometbft/cometbft/types" feemarkettypes "github.com/cosmos/evm/x/feemarket/types" @@ -382,10 +383,10 @@ func CalcBaseFee(config *ethparams.ChainConfig, parent *ethtypes.Header, p feema // This method refers to internal package method of go-ethereum v1.16.3 - RPCMarshalHeader // (https://github.com/ethereum/go-ethereum/blob/d818a9af7bd5919808df78f31580f59382c53150/internal/ethapi/api.go#L888-L927) // but it uses the cometbft Header to get the block hash. -func RPCMarshalHeader(head *ethtypes.Header, cmtHeader cmttypes.Header) map[string]interface{} { +func RPCMarshalHeader(head *ethtypes.Header, blockHash []byte) map[string]interface{} { result := map[string]interface{}{ "number": (*hexutil.Big)(head.Number), - "hash": hexutil.Bytes(cmtHeader.Hash()), // use cometbft header hash + "hash": hexutil.Bytes(blockHash), // use cometbft header hash "parentHash": head.ParentHash, "nonce": head.Nonce, "mixHash": head.MixDigest, @@ -428,8 +429,9 @@ func RPCMarshalHeader(head *ethtypes.Header, cmtHeader cmttypes.Header) map[stri // // 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 *cmttypes.Block, msgs []*evmtypes.MsgEthereumTx, inclTx bool, fullTx bool, config *ethparams.ChainConfig) (map[string]interface{}, error) { - fields := RPCMarshalHeader(block.Header(), cmtBlock.Header) +func RPCMarshalBlock(block *ethtypes.Block, cmtBlock *cmtrpccore.ResultBlock, msgs []*evmtypes.MsgEthereumTx, 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()) if inclTx { @@ -439,7 +441,7 @@ func RPCMarshalBlock(block *ethtypes.Block, cmtBlock *cmttypes.Block, msgs []*ev if fullTx { formatTx = func(idx int, _ *ethtypes.Transaction) interface{} { txIdx := uint64(idx) //nolint:gosec // G115 - return newRPCTransactionFromBlockIndex(block, txIdx, config) + return newRPCTransactionFromBlockIndex(block, common.BytesToHash(blockHash), txIdx, config) } } txs := block.Transactions() @@ -462,12 +464,12 @@ func RPCMarshalBlock(block *ethtypes.Block, cmtBlock *cmttypes.Block, msgs []*ev } // newRPCTransactionFromBlockIndex returns a transaction that will serialize to the RPC representation. -func newRPCTransactionFromBlockIndex(b *ethtypes.Block, index uint64, config *ethparams.ChainConfig) *RPCTransaction { +func newRPCTransactionFromBlockIndex(b *ethtypes.Block, blockHash common.Hash, index uint64, config *ethparams.ChainConfig) *RPCTransaction { txs := b.Transactions() if index >= uint64(len(txs)) { return nil } - return NewRPCTransaction(txs[index], b.Hash(), b.NumberU64(), b.Time(), index, b.BaseFee(), config) + return NewRPCTransaction(txs[index], blockHash, b.NumberU64(), b.Time(), index, b.BaseFee(), config) } // RPCMarshalReceipt marshals a transaction receipt into a JSON object. diff --git a/tests/integration/rpc/backend/test_backend_suite.go b/tests/integration/rpc/backend/test_backend_suite.go index aa19d9145..c056d6d6a 100644 --- a/tests/integration/rpc/backend/test_backend_suite.go +++ b/tests/integration/rpc/backend/test_backend_suite.go @@ -175,7 +175,7 @@ func (s *TestSuite) buildFormattedBlock( msgs = []*evmtypes.MsgEthereumTx{tx} } ethBlock := s.buildEthBlock(blockRes, resBlock, msgs, validator, baseFee) - res, err := rpctypes.RPCMarshalBlock(ethBlock, resBlock.Block, msgs, true, fullTx, s.backend.ChainConfig()) + res, err := rpctypes.RPCMarshalBlock(ethBlock, resBlock, msgs, true, fullTx, s.backend.ChainConfig()) s.Require().NoError(err) return res