Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem: method eth_chainId crashed occasionally #516

Merged
merged 6 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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.
Expand Down
12 changes: 10 additions & 2 deletions indexer/kv_indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,16 @@

// 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)

Check warning on line 195 in indexer/kv_indexer.go

View check run for this annotation

Codecov / codecov/patch

indexer/kv_indexer.go#L195

Added line #L195 was not covered by tests
}
bz1 := sdk.Uint64ToBigEndian(value)
value, err = ethermint.SafeInt32ToUint64(txIndex)
if err != nil {
panic(err)

Check warning on line 200 in indexer/kv_indexer.go

View check run for this annotation

Codecov / codecov/patch

indexer/kv_indexer.go#L200

Added line #L200 was not covered by tests
}
bz2 := sdk.Uint64ToBigEndian(value)
return append(append([]byte{KeyPrefixTxIndex}, bz1...), bz2...)
}

Expand Down
23 changes: 16 additions & 7 deletions rpc/backend/blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,10 @@
) (map[string]interface{}, error) {
ethRPCTxs := []interface{}{}
block := resBlock.Block

height, err := ethermint.SafeUint64(block.Height)
if err != nil {
return nil, err

Check warning on line 390 in rpc/backend/blocks.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/blocks.go#L390

Added line #L390 was not covered by tests
}
baseFee, err := b.BaseFee(blockRes)
if err != nil {
// handle the error for pruned node.
Expand All @@ -398,12 +401,15 @@
ethRPCTxs = append(ethRPCTxs, ethMsg.Hash())
continue
}

index, err := ethermint.SafeIntToUint64(txIndex)
if err != nil {
return nil, err

Check warning on line 406 in rpc/backend/blocks.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/blocks.go#L406

Added line #L406 was not covered by tests
}
rpcTx, err := rpctypes.NewRPCTransaction(
ethMsg,
common.BytesToHash(block.Hash()),
uint64(block.Height),
uint64(txIndex),
height,
index,
baseFee,
b.chainID,
)
Expand Down Expand Up @@ -450,15 +456,18 @@
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

Check warning on line 468 in rpc/backend/blocks.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/blocks.go#L468

Added line #L468 was not covered by tests
}
gasUsed += gas
}

formattedBlock := rpctypes.FormatBlock(
Expand Down
16 changes: 9 additions & 7 deletions rpc/backend/chain_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,18 +41,20 @@

// 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 {
// assume eip-155 is enabled
return (*hexutil.Big)(b.chainID), nil

Check warning on line 54 in rpc/backend/chain_info.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/chain_info.go#L54

Added line #L54 was not covered by tests
}

if config := b.ChainConfig(); config.IsEIP155(new(big.Int).SetUint64(uint64(bn))) {
if config.IsEIP155(new(big.Int).SetUint64(uint64(bn))) {
return (*hexutil.Big)(config.ChainID), nil
}

Expand Down Expand Up @@ -293,7 +295,7 @@
}
}
}
}(int32(value)) //nolint:gosec // checked
}(int32(value))
}
go func() {
wg.Wait()
Expand Down
13 changes: 10 additions & 3 deletions rpc/backend/node_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,17 @@
if !status.SyncInfo.CatchingUp {
return false, nil
}

start, err := ethermint.SafeUint64(status.SyncInfo.EarliestBlockHeight)
if err != nil {
return false, err

Check warning on line 83 in rpc/backend/node_info.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/node_info.go#L83

Added line #L83 was not covered by tests
}
current, err := ethermint.SafeUint64(status.SyncInfo.LatestBlockHeight)
if err != nil {
return false, err

Check warning on line 87 in rpc/backend/node_info.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/node_info.go#L87

Added line #L87 was not covered by tests
}
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
Expand Down
48 changes: 37 additions & 11 deletions rpc/backend/tx_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@
if err != nil {
return b.getTransactionByHashPending(txHash)
}

height, err := ethermint.SafeUint64(res.Height)
if err != nil {
return nil, err

Check warning on line 43 in rpc/backend/tx_info.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/tx_info.go#L43

Added line #L43 was not covered by tests
}
block, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(res.Height))
if err != nil {
return nil, err
Expand Down Expand Up @@ -79,18 +82,20 @@
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

Check warning on line 87 in rpc/backend/tx_info.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/tx_info.go#L87

Added line #L87 was not covered by tests
}
baseFee, err := b.BaseFee(blockRes)
if err != nil {
// 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,
)
Expand Down Expand Up @@ -171,14 +176,18 @@
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

Check warning on line 188 in rpc/backend/tx_info.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/tx_info.go#L186-L188

Added lines #L186 - L188 were not covered by tests
}
cumulativeGasUsed += gas

Check warning on line 190 in rpc/backend/tx_info.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/tx_info.go#L190

Added line #L190 was not covered by tests
}
cumulativeGasUsed += res.CumulativeGasUsed

Expand All @@ -198,12 +207,16 @@
return nil, err
}

height, err := ethermint.SafeUint64(blockRes.Height)
if err != nil {
return nil, err

Check warning on line 212 in rpc/backend/tx_info.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/tx_info.go#L212

Added line #L212 was not covered by tests
}
// 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())
Expand All @@ -228,6 +241,14 @@
return nil, errors.New("can't find index of ethereum tx")
}

blockNumber, err := ethermint.SafeUint64(res.Height)
if err != nil {
return nil, err

Check warning on line 246 in rpc/backend/tx_info.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/tx_info.go#L246

Added line #L246 was not covered by tests
}
transactionIndex, err := ethermint.SafeInt32ToUint64(res.EthTxIndex)
if err != nil {
return nil, err

Check warning on line 250 in rpc/backend/tx_info.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/tx_info.go#L250

Added line #L250 was not covered by tests
}
receipt := map[string]interface{}{
// Consensus fields: These fields are defined by the Yellow Paper
"status": status,
Expand All @@ -244,8 +265,8 @@
// 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,
Expand Down Expand Up @@ -433,10 +454,15 @@
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

Check warning on line 459 in rpc/backend/tx_info.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/tx_info.go#L459

Added line #L459 was not covered by tests
}

return rpctypes.NewTransactionFromMsg(
msg,
common.BytesToHash(block.Block.Hash()),
uint64(block.Block.Height),
height,
uint64(idx),
baseFee,
b.chainID,
Expand Down
12 changes: 10 additions & 2 deletions rpc/backend/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

"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"
)
Expand Down Expand Up @@ -244,7 +245,10 @@
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

Check warning on line 250 in rpc/backend/utils.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/utils.go#L248-L250

Added lines #L248 - L250 were not covered by tests
}
for _, msg := range tx.GetMsgs() {
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
if !ok {
Expand Down Expand Up @@ -290,9 +294,13 @@

// 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

Check warning on line 299 in rpc/backend/utils.go

View check run for this annotation

Codecov / codecov/patch

rpc/backend/utils.go#L299

Added line #L299 was not covered by tests
}
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
}
Expand Down
2 changes: 1 addition & 1 deletion rpc/namespaces/ethereum/debug/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 5 additions & 2 deletions rpc/namespaces/ethereum/eth/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
7 changes: 6 additions & 1 deletion rpc/stream/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"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"
)

Expand Down Expand Up @@ -167,7 +168,11 @@
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

Check warning on line 173 in rpc/stream/rpc.go

View check run for this annotation

Codecov / codecov/patch

rpc/stream/rpc.go#L171-L173

Added lines #L171 - L173 were not covered by tests
}
txLogs, err := evmtypes.DecodeTxLogsFromEvents(dataTx.TxResult.Result.Data, dataTx.TxResult.Result.Events, height)

Check warning on line 175 in rpc/stream/rpc.go

View check run for this annotation

Codecov / codecov/patch

rpc/stream/rpc.go#L175

Added line #L175 was not covered by tests
if err != nil {
s.logger.Error("fail to decode evm tx response", "error", err.Error())
continue
Expand Down
6 changes: 5 additions & 1 deletion rpc/types/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@

// 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

Check warning on line 140 in rpc/types/events.go

View check run for this annotation

Codecov / codecov/patch

rpc/types/events.go#L140

Added line #L140 was not covered by tests
}
p.Txs[0].GasUsed = value
}

// this could only happen if tx exceeds block gas limit
Expand Down
Loading
Loading