Skip to content

Commit

Permalink
Problem: get unnecessary block result in header related api call (#535)
Browse files Browse the repository at this point in the history
* Problem: get unnecessary block result in DoCall

* GetProof GetBalance

* HeaderByNumber

* EstimateGas

* TraceCall

* fix test
  • Loading branch information
mmsqe authored Oct 4, 2024
1 parent 5acb559 commit b16b489
Show file tree
Hide file tree
Showing 12 changed files with 174 additions and 104 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (ante) [#504](https://github.com/crypto-org-chain/ethermint/pull/504) Optimize AnteHandle method to skip checks if disabledMsgs is empty.
* [#517](https://github.com/crypto-org-chain/ethermint/pull/517) Add check for integer overflow to ensure safe conversion.
* [#522](https://github.com/crypto-org-chain/ethermint/pull/522) block-stm executor support optional pre-estimations.
* [#526](https://github.com/crypto-org-chain/ethermint/pull/526) Avoid unnecessary block result in header related api call.
* [#526](https://github.com/crypto-org-chain/ethermint/pull/526), [#535](https://github.com/crypto-org-chain/ethermint/pull/535) Avoid unnecessary block result in header related api call.
* [#533](https://github.com/crypto-org-chain/ethermint/pull/533) Bump cosmos-sdk to v0.50.10, cometbft to v0.38.13 and ibc-go to v8.5.1.

## v0.21.x-cronos
Expand Down
4 changes: 2 additions & 2 deletions rpc/backend/account_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNr
}

height := blockNum.Int64()
_, err = b.TendermintBlockByNumber(blockNum)
_, err = b.TendermintHeaderByNumber(blockNum)
if err != nil {
// the error message imitates geth behavior
return nil, errors.New("header not found")
Expand Down Expand Up @@ -163,7 +163,7 @@ func (b *Backend) GetBalance(address common.Address, blockNrOrHash rpctypes.Bloc
Address: address.String(),
}

_, err = b.TendermintBlockByNumber(blockNum)
_, err = b.TendermintHeaderByNumber(blockNum)
if err != nil {
return nil, err
}
Expand Down
29 changes: 18 additions & 11 deletions rpc/backend/account_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ func (suite *BackendTestSuite) TestGetProof() {
rpctypes.BlockNumberOrHash{BlockNumber: &blockNrInvalid},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, bn.Int64(), nil)
height := bn.Int64()
RegisterHeader(client, &height, nil)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterAccount(queryClient, addr, blockNrInvalid.Int64())
},
Expand All @@ -111,7 +112,8 @@ func (suite *BackendTestSuite) TestGetProof() {
rpctypes.BlockNumberOrHash{BlockNumber: &blockNrInvalid},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlockError(client, bn.Int64())
height := bn.Int64()
RegisterHeaderError(client, &height)
},
false,
&rpctypes.AccountResult{},
Expand All @@ -122,12 +124,12 @@ func (suite *BackendTestSuite) TestGetProof() {
[]string{"0x0"},
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(bn rpctypes.BlockNumber, addr common.Address) {
suite.backend.ctx = rpctypes.ContextWithHeight(bn.Int64())

height := bn.Int64()
suite.backend.ctx = rpctypes.ContextWithHeight(height)
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, bn.Int64(), nil)
RegisterHeader(client, &height, nil)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterAccount(queryClient, addr, bn.Int64())
RegisterAccount(queryClient, addr, height)

// Use the IAVL height if a valid tendermint height is passed in.
iavlHeight := bn.Int64()
Expand Down Expand Up @@ -270,7 +272,8 @@ func (suite *BackendTestSuite) TestGetBalance() {
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlockError(client, bn.Int64())
height := bn.Int64()
RegisterHeaderError(client, &height)
},
false,
nil,
Expand All @@ -281,7 +284,8 @@ func (suite *BackendTestSuite) TestGetBalance() {
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, bn.Int64(), nil)
height := bn.Int64()
RegisterHeader(client, &height, nil)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBalanceError(queryClient, addr, bn.Int64())
},
Expand All @@ -294,7 +298,8 @@ func (suite *BackendTestSuite) TestGetBalance() {
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, bn.Int64(), nil)
height := bn.Int64()
RegisterHeader(client, &height, nil)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBalanceInvalid(queryClient, addr, bn.Int64())
},
Expand All @@ -307,7 +312,8 @@ func (suite *BackendTestSuite) TestGetBalance() {
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, bn.Int64(), nil)
height := bn.Int64()
RegisterHeader(client, &height, nil)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBalanceNegative(queryClient, addr, bn.Int64())
},
Expand All @@ -320,7 +326,8 @@ func (suite *BackendTestSuite) TestGetBalance() {
rpctypes.BlockNumberOrHash{BlockNumber: &blockNr},
func(bn rpctypes.BlockNumber, addr common.Address) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, bn.Int64(), nil)
height := bn.Int64()
RegisterHeader(client, &height, nil)
queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
RegisterBalance(queryClient, addr, bn.Int64())
},
Expand Down
66 changes: 47 additions & 19 deletions rpc/backend/blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,30 +173,52 @@ func (b *Backend) GetBlockTransactionCount(block *tmrpctypes.ResultBlock) *hexut
// TendermintBlockByNumber returns a Tendermint-formatted block for a given
// block number
func (b *Backend) TendermintBlockByNumber(blockNum rpctypes.BlockNumber) (*tmrpctypes.ResultBlock, error) {
height, err := b.getHeightByBlockNum(blockNum)
if err != nil {
return nil, err
}
resBlock, err := b.clientCtx.Client.Block(b.ctx, &height)
if err != nil {
b.logger.Debug("tendermint client failed to get block", "height", height, "error", err.Error())
return nil, err
}

if resBlock.Block == nil {
b.logger.Debug("TendermintBlockByNumber block not found", "height", height)
return nil, nil
}

return resBlock, nil
}

func (b *Backend) getHeightByBlockNum(blockNum rpctypes.BlockNumber) (int64, error) {
height := blockNum.Int64()
if height <= 0 {
// fetch the latest block number from the app state, more accurate than the tendermint block store state.
n, err := b.BlockNumber()
if err != nil {
return nil, err
return 0, err
}
height, err = ethermint.SafeHexToInt64(n)
if err != nil {
return nil, err
return 0, err
}
}
resBlock, err := b.clientCtx.Client.Block(b.ctx, &height)
return height, nil
}

// TendermintHeaderByNumber returns a Tendermint-formatted header for a given
// block number
func (b *Backend) TendermintHeaderByNumber(blockNum rpctypes.BlockNumber) (*tmrpctypes.ResultHeader, error) {
height, err := b.getHeightByBlockNum(blockNum)
if err != nil {
b.logger.Debug("tendermint client failed to get block", "height", height, "error", err.Error())
return nil, err
}

if resBlock.Block == nil {
b.logger.Debug("TendermintBlockByNumber block not found", "height", height)
return nil, nil
sc, ok := b.clientCtx.Client.(tmrpcclient.SignClient)
if !ok {
return nil, errors.New("invalid rpc client")
}

return resBlock, nil
return sc.Header(b.ctx, &height)
}

// TendermintBlockResultByNumber returns a Tendermint-formatted block result
Expand Down Expand Up @@ -257,6 +279,9 @@ func (b *Backend) BlockNumberFromTendermintByHash(blockHash common.Hash) (*big.I
if err != nil {
return nil, err
}
if resHeader.Header == nil {
return nil, errors.Errorf("header not found for hash %s", blockHash.Hex())
}
return big.NewInt(resHeader.Header.Height), nil
}

Expand Down Expand Up @@ -302,35 +327,35 @@ func (b *Backend) EthMsgsFromTendermintBlock(

// HeaderByNumber returns the block header identified by height.
func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error) {
resBlock, err := b.TendermintBlockByNumber(blockNum)
res, err := b.TendermintHeaderByNumber(blockNum)
if err != nil {
return nil, err
}

if resBlock == nil {
return nil, errors.Errorf("block not found for height %d", blockNum)
if res == nil || res.Header == nil {
return nil, errors.Errorf("header not found for height %d", blockNum)
}

blockRes, err := b.TendermintBlockResultByNumber(&resBlock.Block.Height)
blockRes, err := b.TendermintBlockResultByNumber(&res.Header.Height)
if err != nil {
return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height)
return nil, fmt.Errorf("header result not found for height %d", res.Header.Height)
}

bloom, err := b.BlockBloom(blockRes)
if err != nil {
b.logger.Debug("HeaderByNumber BlockBloom failed", "height", resBlock.Block.Height)
b.logger.Debug("HeaderByNumber BlockBloom failed", "height", res.Header.Height)
}

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", resBlock.Block.Height, "error", err)
b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", res.Header.Height, "error", err)
}
validator, err := b.getValidatorAccount(&resBlock.Block.Header)
validator, err := b.getValidatorAccount(res.Header)
if err != nil {
return nil, err
}
ethHeader := rpctypes.EthHeaderFromTendermint(resBlock.Block.Header, bloom, baseFee, validator)
ethHeader := rpctypes.EthHeaderFromTendermint(*res.Header, bloom, baseFee, validator)
return ethHeader, nil
}

Expand All @@ -344,6 +369,9 @@ func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error)
if err != nil {
return nil, err
}
if resHeader.Header == nil {
return nil, errors.Errorf("header not found for hash %s", blockHash.Hex())
}
blockRes, err := b.TendermintBlockResultByNumber(&resHeader.Header.Height)
if err != nil {
return nil, errors.Errorf("block result not found for height %d", resHeader.Header.Height)
Expand Down
31 changes: 20 additions & 11 deletions rpc/backend/blocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1191,7 +1191,7 @@ func (suite *BackendTestSuite) TestEthMsgsFromTendermintBlock() {
}

func (suite *BackendTestSuite) TestHeaderByNumber() {
var expResultBlock *tmrpctypes.ResultBlock
var expResultHeader *tmrpctypes.ResultHeader

_, bz := suite.buildEthereumTx()
validator := sdk.AccAddress(tests.GenerateAddress().Bytes())
Expand All @@ -1210,29 +1210,29 @@ func (suite *BackendTestSuite) TestHeaderByNumber() {
func(blockNum ethrpc.BlockNumber, baseFee sdkmath.Int) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlockError(client, height)
RegisterHeaderError(client, &height)
},
false,
},
{
"fail - block not found for height",
"fail - header not found for height",
ethrpc.BlockNumber(1),
sdkmath.NewInt(1).BigInt(),
func(blockNum ethrpc.BlockNumber, baseFee sdkmath.Int) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlockNotFound(client, height)
RegisterHeaderNotFound(client, height)
},
false,
},
{
"fail - block not found for height",
"fail - header not found for height",
ethrpc.BlockNumber(1),
sdkmath.NewInt(1).BigInt(),
func(blockNum ethrpc.BlockNumber, baseFee sdkmath.Int) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterBlock(client, height, nil)
RegisterHeader(client, &height, nil)
RegisterBlockResultsError(client, height)
},
false,
Expand All @@ -1244,7 +1244,7 @@ func (suite *BackendTestSuite) TestHeaderByNumber() {
func(blockNum ethrpc.BlockNumber, baseFee sdkmath.Int) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
expResultBlock, _ = RegisterBlock(client, height, nil)
expResultHeader, _ = RegisterHeader(client, &height, nil)
RegisterBlockResults(client, height)

queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
Expand All @@ -1260,7 +1260,7 @@ func (suite *BackendTestSuite) TestHeaderByNumber() {
func(blockNum ethrpc.BlockNumber, baseFee sdkmath.Int) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
expResultBlock, _ = RegisterBlock(client, height, nil)
expResultHeader, _ = RegisterHeader(client, &height, nil)
RegisterBlockResults(client, height)

queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
Expand All @@ -1276,7 +1276,7 @@ func (suite *BackendTestSuite) TestHeaderByNumber() {
func(blockNum ethrpc.BlockNumber, baseFee sdkmath.Int) {
height := blockNum.Int64()
client := suite.backend.clientCtx.Client.(*mocks.Client)
expResultBlock, _ = RegisterBlock(client, height, bz)
expResultHeader, _ = RegisterHeader(client, &height, bz)
RegisterBlockResults(client, height)

queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient)
Expand All @@ -1294,7 +1294,7 @@ func (suite *BackendTestSuite) TestHeaderByNumber() {
header, err := suite.backend.HeaderByNumber(tc.blockNumber)

if tc.expPass {
expHeader := ethrpc.EthHeaderFromTendermint(expResultBlock.Block.Header, ethtypes.Bloom{}, tc.baseFee, validator)
expHeader := ethrpc.EthHeaderFromTendermint(*expResultHeader.Header, ethtypes.Bloom{}, tc.baseFee, validator)
suite.Require().NoError(err)
suite.Require().Equal(expHeader, header)
} else {
Expand Down Expand Up @@ -1330,6 +1330,16 @@ func (suite *BackendTestSuite) TestHeaderByHash() {
},
false,
},
{
"fail - header not found for height",
common.BytesToHash(block.Hash()),
sdkmath.NewInt(1).BigInt(),
func(hash common.Hash, baseFee sdkmath.Int) {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterHeaderByHashNotFound(client, hash, bz)
},
false,
},
{
"fail - block not found for height",
common.BytesToHash(block.Hash()),
Expand All @@ -1339,7 +1349,6 @@ func (suite *BackendTestSuite) TestHeaderByHash() {
client := suite.backend.clientCtx.Client.(*mocks.Client)
RegisterHeaderByHash(client, hash, bz)
RegisterBlockResultsError(client, height)
RegisterHeaderByHashError(client, hash, bz)
},
false,
},
Expand Down
9 changes: 4 additions & 5 deletions rpc/backend/call_tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ func (b *Backend) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rp
return 0, err
}

header, err := b.TendermintBlockByNumber(blockNr)
header, err := b.TendermintHeaderByNumber(blockNr)
if err != nil {
// the error message imitates geth behavior
return 0, errors.New("header not found")
Expand All @@ -342,7 +342,7 @@ func (b *Backend) EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rp
req := evmtypes.EthCallRequest{
Args: bz,
GasCap: b.RPCGasCap(),
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
ProposerAddress: sdk.ConsAddress(header.Header.ProposerAddress),
ChainId: b.chainID.Int64(),
}

Expand All @@ -369,12 +369,11 @@ func (b *Backend) DoCall(
if err != nil {
return nil, err
}
header, err := b.TendermintBlockByNumber(blockNr)
header, err := b.TendermintHeaderByNumber(blockNr)
if err != nil {
// the error message imitates geth behavior
return nil, errors.New("header not found")
}

var bzOverrides []byte
if overrides != nil {
bzOverrides = *overrides
Expand All @@ -383,7 +382,7 @@ func (b *Backend) DoCall(
req := evmtypes.EthCallRequest{
Args: bz,
GasCap: b.RPCGasCap(),
ProposerAddress: sdk.ConsAddress(header.Block.ProposerAddress),
ProposerAddress: sdk.ConsAddress(header.Header.ProposerAddress),
ChainId: b.chainID.Int64(),
Overrides: bzOverrides,
}
Expand Down
Loading

0 comments on commit b16b489

Please sign in to comment.