From 9c903b9737d0f62a7c555eaec1f8b99c09b2f2de Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 23 Aug 2024 13:07:39 +0800 Subject: [PATCH 1/5] Problem: method eth_chainId crashed occasionally add fallback default config to ensure no panic in IsEIP155 check --- CHANGELOG.md | 3 ++- rpc/backend/chain_info.go | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7980fc8963..edc97cec2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (rpc) [#488](https://github.com/crypto-org-chain/ethermint/pull/488) Fix handling of pending transactions related APIs. * (rpc) [#501](https://github.com/crypto-org-chain/ethermint/pull/501) Avoid invalid chain id for signer error when rpc call before chain id set in BeginBlock. * (block-stm) [#510](https://github.com/crypto-org-chain/ethermint/pull/510) Include a fix to avoid nondeterministic account set when stm workers execute in parallel. +* (rpc) [#516](https://github.com/crypto-org-chain/ethermint/pull/516) Avoid method eth_chainId crashed due to nil pointer on IsEIP155 check. ### Improvements @@ -80,7 +81,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (app) [#483](https://github.com/crypto-org-chain/ethermint/pull/483) Make keyring-backend client config accessible in app. * (deps) [#489](https://github.com/crypto-org-chain/ethermint/pull/489) Update cosmos-sdk to `v0.50.7`. * (rpc) [#491](https://github.com/crypto-org-chain/ethermint/pull/491) Avoid unnecessary tx decode in tx listener. -* [#496](https://github.com/crypto-org-chain/cronos/pull/496) Set mempool MaxTx from config. +* [#496](https://github.com/crypto-org-chain/ethermint/pull/496) Set mempool MaxTx from config. * (ante) [#497](https://github.com/crypto-org-chain/ethermint/pull/497) Enforce positive value check in eth transaction. * (deps) [#505](https://github.com/crypto-org-chain/ethermint/pull/505) Update cometbft to v0.38.10. * (ante) [#504](https://github.com/crypto-org-chain/ethermint/pull/504) Optimize AnteHandle method to skip checks if disabledMsgs is empty. diff --git a/rpc/backend/chain_info.go b/rpc/backend/chain_info.go index 883b062544..e38c109c3c 100644 --- a/rpc/backend/chain_info.go +++ b/rpc/backend/chain_info.go @@ -52,7 +52,11 @@ func (b *Backend) ChainID() (*hexutil.Big, error) { return (*hexutil.Big)(eip155ChainID), nil } - if config := b.ChainConfig(); config.IsEIP155(new(big.Int).SetUint64(uint64(bn))) { + config := b.ChainConfig() + if config == nil { + config = evmtypes.DefaultChainConfig().EthereumConfig(eip155ChainID) + } + if config.IsEIP155(new(big.Int).SetUint64(uint64(bn))) { return (*hexutil.Big)(config.ChainID), nil } From 7e08a46f8ea58bf8363bc2764d481d5e1f9dfa12 Mon Sep 17 00:00:00 2001 From: huangyi Date: Tue, 27 Aug 2024 11:34:41 +0800 Subject: [PATCH 2/5] cleanup --- rpc/backend/chain_info.go | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/rpc/backend/chain_info.go b/rpc/backend/chain_info.go index e38c109c3c..0d4c353b3f 100644 --- a/rpc/backend/chain_info.go +++ b/rpc/backend/chain_info.go @@ -33,7 +33,6 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" rpctypes "github.com/evmos/ethermint/rpc/types" - ethermint "github.com/evmos/ethermint/types" evmtypes "github.com/evmos/ethermint/x/evm/types" feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" "github.com/pkg/errors" @@ -41,21 +40,19 @@ import ( // ChainID is the EIP-155 replay-protection chain id for the current ethereum chain config. func (b *Backend) ChainID() (*hexutil.Big, error) { - eip155ChainID, err := ethermint.ParseChainID(b.clientCtx.ChainID) - if err != nil { - panic(err) - } // if current block is at or past the EIP-155 replay-protection fork block, return chainID from config bn, err := b.BlockNumber() if err != nil { b.logger.Debug("failed to fetch latest block number", "error", err.Error()) - return (*hexutil.Big)(eip155ChainID), nil + return (*hexutil.Big)(b.chainID), nil } config := b.ChainConfig() if config == nil { - config = evmtypes.DefaultChainConfig().EthereumConfig(eip155ChainID) + // assume eip-155 is enabled + return (*hexutil.Big)(b.chainID), nil } + if config.IsEIP155(new(big.Int).SetUint64(uint64(bn))) { return (*hexutil.Big)(config.ChainID), nil } From 39d9f98ef70d52cc3eb10acb1c63f7bf7c9e6504 Mon Sep 17 00:00:00 2001 From: huangyi Date: Tue, 10 Sep 2024 11:59:36 +0800 Subject: [PATCH 3/5] fix --- rpc/backend/chain_info.go | 1 + 1 file changed, 1 insertion(+) diff --git a/rpc/backend/chain_info.go b/rpc/backend/chain_info.go index b5de2e64e4..f2af291057 100644 --- a/rpc/backend/chain_info.go +++ b/rpc/backend/chain_info.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" rpctypes "github.com/evmos/ethermint/rpc/types" + ethermint "github.com/evmos/ethermint/types" evmtypes "github.com/evmos/ethermint/x/evm/types" feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" "github.com/pkg/errors" From 67ca8625470aac1b3efe42a9f0f37adaa3845e83 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Tue, 10 Sep 2024 15:12:50 +0800 Subject: [PATCH 4/5] lint --- indexer/kv_indexer.go | 12 +++++-- rpc/backend/blocks.go | 23 +++++++++----- rpc/backend/chain_info.go | 2 +- rpc/backend/node_info.go | 13 ++++++-- rpc/backend/tx_info.go | 47 ++++++++++++++++++++++------ rpc/backend/utils.go | 12 +++++-- rpc/namespaces/ethereum/debug/api.go | 2 +- rpc/namespaces/ethereum/eth/api.go | 7 +++-- rpc/stream/rpc.go | 7 ++++- rpc/types/events.go | 6 +++- rpc/types/utils.go | 32 +++++++++++++++---- testutil/base_test_suite.go | 2 +- types/int.go | 36 ++++++++++++++++++--- x/evm/keeper/config.go | 7 +++-- x/evm/keeper/grpc_query.go | 15 +++++++-- x/evm/types/key.go | 19 +++++++++-- 16 files changed, 193 insertions(+), 49 deletions(-) diff --git a/indexer/kv_indexer.go b/indexer/kv_indexer.go index c6ca943a67..a4bd61d308 100644 --- a/indexer/kv_indexer.go +++ b/indexer/kv_indexer.go @@ -190,8 +190,16 @@ func TxHashKey(hash common.Hash) []byte { // TxIndexKey returns the key for db entry: `(block number, tx index) -> tx hash` func TxIndexKey(blockNumber int64, txIndex int32) []byte { - bz1 := sdk.Uint64ToBigEndian(uint64(blockNumber)) - bz2 := sdk.Uint64ToBigEndian(uint64(txIndex)) + value, err := ethermint.SafeUint64(blockNumber) + if err != nil { + panic(err) + } + bz1 := sdk.Uint64ToBigEndian(value) + value, err = ethermint.SafeInt32ToUint64(txIndex) + if err != nil { + panic(err) + } + bz2 := sdk.Uint64ToBigEndian(value) return append(append([]byte{KeyPrefixTxIndex}, bz1...), bz2...) } diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index 4b7f70a1d2..26aff3f7d8 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -385,7 +385,10 @@ func (b *Backend) RPCBlockFromTendermintBlock( ) (map[string]interface{}, error) { ethRPCTxs := []interface{}{} block := resBlock.Block - + height, err := ethermint.SafeUint64(block.Height) + if err != nil { + return nil, err + } baseFee, err := b.BaseFee(blockRes) if err != nil { // handle the error for pruned node. @@ -398,12 +401,15 @@ func (b *Backend) RPCBlockFromTendermintBlock( ethRPCTxs = append(ethRPCTxs, ethMsg.Hash()) continue } - + index, err := ethermint.SafeIntToUint64(txIndex) + if err != nil { + return nil, err + } rpcTx, err := rpctypes.NewRPCTransaction( ethMsg, common.BytesToHash(block.Hash()), - uint64(block.Height), - uint64(txIndex), + height, + index, baseFee, b.chainID, ) @@ -450,15 +456,18 @@ func (b *Backend) RPCBlockFromTendermintBlock( b.logger.Error("failed to query consensus params", "error", err.Error()) } - gasUsed := uint64(0) - + var gasUsed uint64 for _, txsResult := range blockRes.TxsResults { // workaround for cosmos-sdk bug. https://github.com/cosmos/cosmos-sdk/issues/10832 if ShouldIgnoreGasUsed(txsResult) { // block gas limit has exceeded, other txs must have failed with same reason. break } - gasUsed += uint64(txsResult.GetGasUsed()) + gas, err := ethermint.SafeUint64(txsResult.GetGasUsed()) + if err != nil { + return nil, err + } + gasUsed += gas } formattedBlock := rpctypes.FormatBlock( diff --git a/rpc/backend/chain_info.go b/rpc/backend/chain_info.go index f2af291057..4f9d4c4d67 100644 --- a/rpc/backend/chain_info.go +++ b/rpc/backend/chain_info.go @@ -295,7 +295,7 @@ func (b *Backend) FeeHistory( } } } - }(int32(value)) //nolint:gosec // checked + }(int32(value)) } go func() { wg.Wait() diff --git a/rpc/backend/node_info.go b/rpc/backend/node_info.go index 94745a040b..764ec1c1fc 100644 --- a/rpc/backend/node_info.go +++ b/rpc/backend/node_info.go @@ -78,10 +78,17 @@ func (b *Backend) Syncing() (interface{}, error) { if !status.SyncInfo.CatchingUp { return false, nil } - + start, err := ethermint.SafeUint64(status.SyncInfo.EarliestBlockHeight) + if err != nil { + return false, err + } + current, err := ethermint.SafeUint64(status.SyncInfo.LatestBlockHeight) + if err != nil { + return false, err + } return map[string]interface{}{ - "startingBlock": hexutil.Uint64(status.SyncInfo.EarliestBlockHeight), - "currentBlock": hexutil.Uint64(status.SyncInfo.LatestBlockHeight), + "startingBlock": hexutil.Uint64(start), + "currentBlock": hexutil.Uint64(current), // "highestBlock": nil, // NA // "pulledStates": nil, // NA // "knownStates": nil, // NA diff --git a/rpc/backend/tx_info.go b/rpc/backend/tx_info.go index e004b413ee..c1ad777ad0 100644 --- a/rpc/backend/tx_info.go +++ b/rpc/backend/tx_info.go @@ -38,7 +38,14 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac if err != nil { return b.getTransactionByHashPending(txHash) } - + height, err := ethermint.SafeUint64(res.Height) + if err != nil { + return nil, err + } + index, err := ethermint.SafeInt32ToUint64(res.EthTxIndex) + if err != nil { + return nil, err + } block, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(res.Height)) if err != nil { return nil, err @@ -85,12 +92,11 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac // handle the error for pruned node. b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", blockRes.Height, "error", err) } - return rpctypes.NewTransactionFromMsg( msg, common.BytesToHash(block.BlockID.Hash.Bytes()), - uint64(res.Height), - uint64(res.EthTxIndex), + height, + index, baseFee, b.chainID, ) @@ -171,14 +177,18 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ return nil, err } - cumulativeGasUsed := uint64(0) + var cumulativeGasUsed uint64 blockRes, err := b.TendermintBlockResultByNumber(&res.Height) if err != nil { b.logger.Debug("failed to retrieve block results", "height", res.Height, "error", err.Error()) return nil, nil } for _, txResult := range blockRes.TxsResults[0:res.TxIndex] { - cumulativeGasUsed += uint64(txResult.GasUsed) + gas, err := ethermint.SafeUint64(txResult.GasUsed) + if err != nil { + return nil, err + } + cumulativeGasUsed += gas } cumulativeGasUsed += res.CumulativeGasUsed @@ -198,12 +208,16 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ return nil, err } + height, err := ethermint.SafeUint64(blockRes.Height) + if err != nil { + return nil, err + } // parse tx logs from events logs, err := evmtypes.DecodeMsgLogsFromEvents( blockRes.TxsResults[res.TxIndex].Data, blockRes.TxsResults[res.TxIndex].Events, int(res.MsgIndex), - uint64(blockRes.Height), + height, ) if err != nil { b.logger.Debug("failed to parse logs", "hash", hash, "error", err.Error()) @@ -228,6 +242,14 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ return nil, errors.New("can't find index of ethereum tx") } + blockNumber, err := ethermint.SafeUint64(res.Height) + if err != nil { + return nil, err + } + transactionIndex, err := ethermint.SafeInt32ToUint64(res.EthTxIndex) + if err != nil { + return nil, err + } receipt := map[string]interface{}{ // Consensus fields: These fields are defined by the Yellow Paper "status": status, @@ -244,8 +266,8 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ // Inclusion information: These fields provide information about the inclusion of the // transaction corresponding to this receipt. "blockHash": common.BytesToHash(resBlock.Block.Header.Hash()).Hex(), - "blockNumber": hexutil.Uint64(res.Height), - "transactionIndex": hexutil.Uint64(res.EthTxIndex), + "blockNumber": hexutil.Uint64(blockNumber), + "transactionIndex": hexutil.Uint64(transactionIndex), // sender and receiver (contract or EOA) addreses "from": from, @@ -433,10 +455,15 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, i b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", block.Block.Height, "error", err) } + height, err := ethermint.SafeUint64(block.Block.Height) + if err != nil { + return nil, err + } + return rpctypes.NewTransactionFromMsg( msg, common.BytesToHash(block.Block.Hash()), - uint64(block.Block.Height), + height, uint64(idx), baseFee, b.chainID, diff --git a/rpc/backend/utils.go b/rpc/backend/utils.go index 46760319f0..f236b994da 100644 --- a/rpc/backend/utils.go +++ b/rpc/backend/utils.go @@ -39,6 +39,7 @@ import ( "github.com/cometbft/cometbft/proto/tendermint/crypto" "github.com/evmos/ethermint/rpc/types" + ethermint "github.com/evmos/ethermint/types" evmtypes "github.com/evmos/ethermint/x/evm/types" feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" ) @@ -244,7 +245,10 @@ func (b *Backend) processBlock( b.logger.Debug("failed to decode transaction in block", "height", blockHeight, "error", err.Error()) continue } - txGasUsed := uint64(eachTendermintTxResult.GasUsed) + txGasUsed, err := ethermint.SafeUint64(eachTendermintTxResult.GasUsed) + if err != nil { + return err + } for _, msg := range tx.GetMsgs() { ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) if !ok { @@ -290,9 +294,13 @@ func ShouldIgnoreGasUsed(res *abci.ExecTxResult) bool { // GetLogsFromBlockResults returns the list of event logs from the tendermint block result response func GetLogsFromBlockResults(blockRes *tmrpctypes.ResultBlockResults) ([][]*ethtypes.Log, error) { + height, err := ethermint.SafeUint64(blockRes.Height) + if err != nil { + return nil, err + } blockLogs := [][]*ethtypes.Log{} for _, txResult := range blockRes.TxsResults { - logs, err := evmtypes.DecodeTxLogsFromEvents(txResult.Data, txResult.Events, uint64(blockRes.Height)) + logs, err := evmtypes.DecodeTxLogsFromEvents(txResult.Data, txResult.Events, height) if err != nil { return nil, err } diff --git a/rpc/namespaces/ethereum/debug/api.go b/rpc/namespaces/ethereum/debug/api.go index 52219c9685..7860f915ee 100644 --- a/rpc/namespaces/ethereum/debug/api.go +++ b/rpc/namespaces/ethereum/debug/api.go @@ -132,7 +132,7 @@ func parseDuration(nsec uint) (time.Duration, error) { if nsec > uint(time.Duration(1<<63-1)/time.Second) { return time.Duration(0), fmt.Errorf("value %d exceeds maximum duration for time.Duration", nsec) } - return time.Duration(nsec) * time.Second, nil //nolint:gosec // checked + return time.Duration(nsec) * time.Second, nil } // BlockProfile turns on goroutine profiling for nsec seconds and writes profile data to diff --git a/rpc/namespaces/ethereum/eth/api.go b/rpc/namespaces/ethereum/eth/api.go index df9c8577a3..2572f1726e 100644 --- a/rpc/namespaces/ethereum/eth/api.go +++ b/rpc/namespaces/ethereum/eth/api.go @@ -448,13 +448,16 @@ func (e *PublicAPI) GetTransactionLogs(txHash common.Hash) ([]*ethtypes.Log, err e.logger.Debug("block result not found", "number", res.Height, "error", err.Error()) return nil, nil } - + height, err := ethermint.SafeUint64(resBlockResult.Height) + if err != nil { + return nil, err + } // parse tx logs from events logs, err := evmtypes.DecodeMsgLogsFromEvents( resBlockResult.TxsResults[res.TxIndex].Data, resBlockResult.TxsResults[res.TxIndex].Events, int(res.MsgIndex), - uint64(resBlockResult.Height), + height, ) if err != nil { e.logger.Debug("failed to parse tx logs", "error", err.Error()) diff --git a/rpc/stream/rpc.go b/rpc/stream/rpc.go index d23388ada7..680cfc67e7 100644 --- a/rpc/stream/rpc.go +++ b/rpc/stream/rpc.go @@ -14,6 +14,7 @@ import ( "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/evmos/ethermint/rpc/types" + ethermint "github.com/evmos/ethermint/types" evmtypes "github.com/evmos/ethermint/x/evm/types" ) @@ -167,7 +168,11 @@ func (s *RPCStream) start( s.logger.Error("event data type mismatch", "type", fmt.Sprintf("%T", ev.Data)) continue } - txLogs, err := evmtypes.DecodeTxLogsFromEvents(dataTx.TxResult.Result.Data, dataTx.TxResult.Result.Events, uint64(dataTx.TxResult.Height)) + height, err := ethermint.SafeUint64(dataTx.TxResult.Height) + if err != nil { + continue + } + txLogs, err := evmtypes.DecodeTxLogsFromEvents(dataTx.TxResult.Result.Data, dataTx.TxResult.Result.Events, height) if err != nil { s.logger.Error("fail to decode evm tx response", "error", err.Error()) continue diff --git a/rpc/types/events.go b/rpc/types/events.go index 16bc3f46ef..0b53f5e282 100644 --- a/rpc/types/events.go +++ b/rpc/types/events.go @@ -135,7 +135,11 @@ func ParseTxResult(result *abci.ExecTxResult, tx sdk.Tx) (*ParsedTxs, error) { // some old versions miss some events, fill it with tx result if len(p.Txs) == 1 { - p.Txs[0].GasUsed = uint64(result.GasUsed) + value, err := ethermint.SafeUint64(result.GasUsed) + if err != nil { + return nil, err + } + p.Txs[0].GasUsed = value } // this could only happen if tx exceeds block gas limit diff --git a/rpc/types/utils.go b/rpc/types/utils.go index fb7b0facfc..84f6f4faba 100644 --- a/rpc/types/utils.go +++ b/rpc/types/utils.go @@ -37,6 +37,7 @@ import ( "github.com/ethereum/go-ethereum/common/math" ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" + ethermint "github.com/evmos/ethermint/types" ) // ExceedBlockGasLimitError defines the error message when tx execution exceeds the block gas limit. @@ -69,6 +70,10 @@ func EthHeaderFromTendermint(header tmtypes.Header, bloom ethtypes.Bloom, baseFe txHash = common.BytesToHash(header.DataHash) } + value, err := ethermint.SafeUint64(header.Time.UTC().Unix()) + if err != nil { + panic(err) + } return ðtypes.Header{ ParentHash: common.BytesToHash(header.LastBlockID.Hash.Bytes()), UncleHash: ethtypes.EmptyUncleHash, @@ -81,7 +86,7 @@ func EthHeaderFromTendermint(header tmtypes.Header, bloom ethtypes.Bloom, baseFe Number: big.NewInt(header.Height), GasLimit: 0, GasUsed: 0, - Time: uint64(header.Time.UTC().Unix()), + Time: value, Extra: []byte{}, MixDigest: common.Hash{}, Nonce: ethtypes.BlockNonce{}, @@ -125,9 +130,24 @@ func FormatBlock( } else { transactionsRoot = common.BytesToHash(header.DataHash) } - + number, err := ethermint.SafeUint64(header.Height) + if err != nil { + panic(err) + } + limit, err := ethermint.SafeUint64(gasLimit) + if err != nil { + panic(err) + } + timestamp, err := ethermint.SafeUint64(header.Time.Unix()) + if err != nil { + panic(err) + } + s, err := ethermint.SafeIntToUint64(size) + if err != nil { + panic(err) + } result := map[string]interface{}{ - "number": hexutil.Uint64(header.Height), + "number": hexutil.Uint64(number), "hash": hexutil.Bytes(header.Hash()), "parentHash": common.BytesToHash(header.LastBlockID.Hash.Bytes()), "nonce": ethtypes.BlockNonce{}, // PoW specific @@ -138,10 +158,10 @@ func FormatBlock( "mixHash": common.Hash{}, "difficulty": (*hexutil.Big)(big.NewInt(0)), "extraData": "0x", - "size": hexutil.Uint64(size), - "gasLimit": hexutil.Uint64(gasLimit), // Static gas limit + "size": hexutil.Uint64(s), + "gasLimit": limit, // Static gas limit "gasUsed": (*hexutil.Big)(gasUsed), - "timestamp": hexutil.Uint64(header.Time.Unix()), + "timestamp": hexutil.Uint64(timestamp), "transactionsRoot": transactionsRoot, "receiptsRoot": ethtypes.EmptyRootHash, diff --git a/testutil/base_test_suite.go b/testutil/base_test_suite.go index 4136d45268..ab74ece864 100644 --- a/testutil/base_test_suite.go +++ b/testutil/base_test_suite.go @@ -61,7 +61,7 @@ func (suite *BaseTestSuite) MintFeeCollectorVirtual(coins sdk.Coins) { func addVirtualCoins(store storetypes.ObjKVStore, txIndex int, addr sdk.AccAddress, amt sdk.Coins) { key := make([]byte, len(addr)+8) copy(key, addr) - binary.BigEndian.PutUint64(key[len(addr):], uint64(txIndex)) + binary.BigEndian.PutUint64(key[len(addr):], uint64(txIndex)) //nolint:gosec // test only var coins sdk.Coins value := store.Get(key) diff --git a/types/int.go b/types/int.go index 3c717d3c68..de02539067 100644 --- a/types/int.go +++ b/types/int.go @@ -42,7 +42,7 @@ func SafeInt64(value uint64) (int64, error) { return 0, fmt.Errorf("uint64 value %v cannot exceed %v", value, math.MaxInt64) } - return int64(value), nil //nolint:gosec // checked + return int64(value), nil } func SafeUint64ToInt32(value uint64) (int32, error) { @@ -58,7 +58,7 @@ func SafeUint64ToInt(value uint64) (int, error) { return 0, fmt.Errorf("uint64 value %v cannot exceed %v", value, math.MaxInt64) } - return int(value), nil //nolint:gosec // checked + return int(value), nil } func SafeHexToInt64(value hexutil.Uint64) (int64, error) { @@ -77,12 +77,40 @@ func SafeUint32(value int) (uint32, error) { return uint32(value), nil //nolint:gosec // checked } +func SafeUint64(value int64) (uint64, error) { + if value < 0 { + return 0, fmt.Errorf("invalid value: %d", value) + } + return uint64(value), nil +} + +func SafeIntToUint64(value int) (uint64, error) { + if value < 0 { + return 0, fmt.Errorf("invalid value: %d", value) + } + return uint64(value), nil +} + +func SafeInt32ToUint64(value int32) (uint64, error) { + if value < 0 { + return 0, fmt.Errorf("invalid value: %d", value) + } + return uint64(value), nil +} + +func SafeUint(value int) (uint, error) { + if value < 0 { + return 0, fmt.Errorf("invalid value: %d", value) + } + return uint(value), nil +} + func SafeUintToInt32(value uint) (int32, error) { if value > uint(math.MaxInt32) { return 0, fmt.Errorf("uint value %v cannot exceed %v", value, math.MaxUint32) } - return int32(value), nil //nolint:gosec // checked + return int32(value), nil } func SafeIntToInt32(value int) (int32, error) { @@ -98,7 +126,7 @@ func SafeInt(value uint) (int, error) { return 0, fmt.Errorf("uint value %v cannot exceed %v", value, math.MaxInt64) } - return int(value), nil //nolint:gosec // checked + return int(value), nil } func SafeHexToInt(value hexutil.Uint) (int, error) { diff --git a/x/evm/keeper/config.go b/x/evm/keeper/config.go index 4a19709975..6b7941425f 100644 --- a/x/evm/keeper/config.go +++ b/x/evm/keeper/config.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/params" rpctypes "github.com/evmos/ethermint/rpc/types" + ethermint "github.com/evmos/ethermint/types" "github.com/evmos/ethermint/x/evm/statedb" "github.com/evmos/ethermint/x/evm/types" feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" @@ -85,8 +86,10 @@ func (k *Keeper) EVMBlockConfig(ctx sdk.Context, chainID *big.Int) (*EVMBlockCon baseFee = new(big.Int) } } - - blockTime := uint64(ctx.BlockHeader().Time.Unix()) + blockTime, err := ethermint.SafeUint64(ctx.BlockHeader().Time.Unix()) + if err != nil { + return nil, err + } blockNumber := big.NewInt(ctx.BlockHeight()) rules := ethCfg.Rules(blockNumber, ethCfg.MergeNetsplitBlock != nil, blockTime) diff --git a/x/evm/keeper/grpc_query.go b/x/evm/keeper/grpc_query.go index 30bed2e3b8..12179d35f4 100644 --- a/x/evm/keeper/grpc_query.go +++ b/x/evm/keeper/grpc_query.go @@ -315,7 +315,10 @@ func (k Keeper) EstimateGas(c context.Context, req *types.EthCallRequest) (*type // Query block gas limit params := ctx.ConsensusParams() if params.Block != nil && params.Block.MaxGas > 0 { - hi = uint64(params.Block.MaxGas) + hi, err = ethermint.SafeUint64(params.Block.MaxGas) + if err != nil { + return nil, err + } } else { hi = req.GasCap } @@ -491,7 +494,10 @@ func (k Keeper) TraceTx(c context.Context, req *types.QueryTraceTxRequest) (*typ continue } cfg.TxConfig.TxHash = ethTx.Hash() - cfg.TxConfig.TxIndex = uint(i) + cfg.TxConfig.TxIndex, err = ethermint.SafeUint(i) + if err != nil { + continue + } rsp, err := k.ApplyMessageWithConfig(ctx, msg, cfg, true) if err != nil { continue @@ -558,7 +564,10 @@ func (k Keeper) TraceBlock(c context.Context, req *types.QueryTraceBlockRequest) result := types.TxTraceResult{} ethTx := tx.AsTransaction() cfg.TxConfig.TxHash = ethTx.Hash() - cfg.TxConfig.TxIndex = uint(i) + cfg.TxConfig.TxIndex, err = ethermint.SafeUint(i) + if err != nil { + return nil, err + } msg, err := core.TransactionToMessage(ethTx, signer, cfg.BaseFee) if err != nil { result.Error = status.Error(codes.Internal, err.Error()).Error() diff --git a/x/evm/types/key.go b/x/evm/types/key.go index 51b19a469a..719f54df7a 100644 --- a/x/evm/types/key.go +++ b/x/evm/types/key.go @@ -19,6 +19,7 @@ import ( "encoding/binary" "github.com/ethereum/go-ethereum/common" + ethermint "github.com/evmos/ethermint/types" ) const ( @@ -80,14 +81,26 @@ func StateKey(address common.Address, key []byte) []byte { func ObjectGasUsedKey(txIndex int) []byte { var key [1 + 8]byte key[0] = prefixObjectGasUsed - binary.BigEndian.PutUint64(key[1:], uint64(txIndex)) + idx, err := ethermint.SafeIntToUint64(txIndex) + if err != nil { + panic(err) + } + binary.BigEndian.PutUint64(key[1:], idx) return key[:] } func ObjectBloomKey(txIndex, msgIndex int) []byte { var key [1 + 8 + 8]byte key[0] = prefixObjectBloom - binary.BigEndian.PutUint64(key[1:], uint64(txIndex)) - binary.BigEndian.PutUint64(key[9:], uint64(msgIndex)) + value, err := ethermint.SafeIntToUint64(txIndex) + if err != nil { + panic(err) + } + binary.BigEndian.PutUint64(key[1:], value) + value, err = ethermint.SafeIntToUint64(msgIndex) + if err != nil { + panic(err) + } + binary.BigEndian.PutUint64(key[9:], value) return key[:] } From c4548080907a07d84272dad98b24a8cd982a4255 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Tue, 10 Sep 2024 21:29:17 +0800 Subject: [PATCH 5/5] fix --- rpc/backend/tx_info.go | 9 +++---- rpc/types/utils.go | 30 +++++++++++++++-------- tests/integration_tests/test_grpc_only.py | 2 +- x/evm/keeper/config.go | 10 +++++--- x/evm/types/key.go | 6 +++++ 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/rpc/backend/tx_info.go b/rpc/backend/tx_info.go index c1ad777ad0..b33ccab66f 100644 --- a/rpc/backend/tx_info.go +++ b/rpc/backend/tx_info.go @@ -42,10 +42,6 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac if err != nil { return nil, err } - index, err := ethermint.SafeInt32ToUint64(res.EthTxIndex) - if err != nil { - return nil, err - } block, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(res.Height)) if err != nil { return nil, err @@ -86,7 +82,10 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac if res.EthTxIndex == -1 { return nil, errors.New("can't find index of ethereum tx") } - + index, err := ethermint.SafeInt32ToUint64(res.EthTxIndex) + if err != nil { + return nil, err + } baseFee, err := b.BaseFee(blockRes) if err != nil { // handle the error for pruned node. diff --git a/rpc/types/utils.go b/rpc/types/utils.go index 84f6f4faba..9f2e3d724e 100644 --- a/rpc/types/utils.go +++ b/rpc/types/utils.go @@ -69,10 +69,16 @@ func EthHeaderFromTendermint(header tmtypes.Header, bloom ethtypes.Bloom, baseFe if len(header.DataHash) == 0 { txHash = common.BytesToHash(header.DataHash) } - - value, err := ethermint.SafeUint64(header.Time.UTC().Unix()) - if err != nil { - panic(err) + var ( + blockTime uint64 + err error + ) + time := header.Time + if !time.IsZero() { + blockTime, err = ethermint.SafeUint64(time.Unix()) + if err != nil { + panic(err) + } } return ðtypes.Header{ ParentHash: common.BytesToHash(header.LastBlockID.Hash.Bytes()), @@ -86,7 +92,7 @@ func EthHeaderFromTendermint(header tmtypes.Header, bloom ethtypes.Bloom, baseFe Number: big.NewInt(header.Height), GasLimit: 0, GasUsed: 0, - Time: value, + Time: blockTime, Extra: []byte{}, MixDigest: common.Hash{}, Nonce: ethtypes.BlockNonce{}, @@ -138,9 +144,13 @@ func FormatBlock( if err != nil { panic(err) } - timestamp, err := ethermint.SafeUint64(header.Time.Unix()) - if err != nil { - panic(err) + time := header.Time + var blockTime uint64 + if !time.IsZero() { + blockTime, err = ethermint.SafeUint64(time.Unix()) + if err != nil { + panic(err) + } } s, err := ethermint.SafeIntToUint64(size) if err != nil { @@ -159,9 +169,9 @@ func FormatBlock( "difficulty": (*hexutil.Big)(big.NewInt(0)), "extraData": "0x", "size": hexutil.Uint64(s), - "gasLimit": limit, // Static gas limit + "gasLimit": hexutil.Uint64(limit), // Static gas limit "gasUsed": (*hexutil.Big)(gasUsed), - "timestamp": hexutil.Uint64(timestamp), + "timestamp": hexutil.Uint64(blockTime), "transactionsRoot": transactionsRoot, "receiptsRoot": ethtypes.EmptyRootHash, diff --git a/tests/integration_tests/test_grpc_only.py b/tests/integration_tests/test_grpc_only.py index 1fb0105c30..ecb207a57f 100644 --- a/tests/integration_tests/test_grpc_only.py +++ b/tests/integration_tests/test_grpc_only.py @@ -78,7 +78,7 @@ def test_grpc_mode(custom_ethermint): api_port = ports.api_port(custom_ethermint.base_port(1)) def expect_cb(rsp): - ret = rsp["ret"] + ret = rsp.get("ret") valid = ret is not None return valid and 9000 == int.from_bytes(base64.b64decode(ret.encode()), "big") diff --git a/x/evm/keeper/config.go b/x/evm/keeper/config.go index 6b7941425f..ef97b58f80 100644 --- a/x/evm/keeper/config.go +++ b/x/evm/keeper/config.go @@ -86,9 +86,13 @@ func (k *Keeper) EVMBlockConfig(ctx sdk.Context, chainID *big.Int) (*EVMBlockCon baseFee = new(big.Int) } } - blockTime, err := ethermint.SafeUint64(ctx.BlockHeader().Time.Unix()) - if err != nil { - return nil, err + time := ctx.BlockHeader().Time + var blockTime uint64 + if !time.IsZero() { + blockTime, err = ethermint.SafeUint64(time.Unix()) + if err != nil { + return nil, err + } } blockNumber := big.NewInt(ctx.BlockHeight()) rules := ethCfg.Rules(blockNumber, ethCfg.MergeNetsplitBlock != nil, blockTime) diff --git a/x/evm/types/key.go b/x/evm/types/key.go index 719f54df7a..b3b7173ba9 100644 --- a/x/evm/types/key.go +++ b/x/evm/types/key.go @@ -81,6 +81,9 @@ func StateKey(address common.Address, key []byte) []byte { func ObjectGasUsedKey(txIndex int) []byte { var key [1 + 8]byte key[0] = prefixObjectGasUsed + if txIndex < 0 { + return key[:] + } idx, err := ethermint.SafeIntToUint64(txIndex) if err != nil { panic(err) @@ -92,6 +95,9 @@ func ObjectGasUsedKey(txIndex int) []byte { func ObjectBloomKey(txIndex, msgIndex int) []byte { var key [1 + 8 + 8]byte key[0] = prefixObjectBloom + if txIndex < 0 || msgIndex < 0 { + return key[:] + } value, err := ethermint.SafeIntToUint64(txIndex) if err != nil { panic(err)