From b16b4891a23b2f9f6f7ad5352c28e4cc1f5ba5f6 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 4 Oct 2024 09:24:09 +0800 Subject: [PATCH 1/2] Problem: get unnecessary block result in header related api call (#535) * Problem: get unnecessary block result in DoCall * GetProof GetBalance * HeaderByNumber * EstimateGas * TraceCall * fix test --- CHANGELOG.md | 2 +- rpc/backend/account_info.go | 4 +- rpc/backend/account_info_test.go | 29 ++++++----- rpc/backend/blocks.go | 66 +++++++++++++++++-------- rpc/backend/blocks_test.go | 31 +++++++----- rpc/backend/call_tx.go | 9 ++-- rpc/backend/call_tx_test.go | 75 +++++++++++++++-------------- rpc/backend/client_test.go | 23 +++++++++ rpc/backend/sign_tx_test.go | 22 ++++----- rpc/backend/tracing.go | 12 ++--- rpc/backend/tracing_test.go | 3 +- tests/integration_tests/test_gas.py | 2 +- 12 files changed, 174 insertions(+), 104 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 400cc0827f..0ca67bb764 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/rpc/backend/account_info.go b/rpc/backend/account_info.go index b3069038a2..fe3af58b88 100644 --- a/rpc/backend/account_info.go +++ b/rpc/backend/account_info.go @@ -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") @@ -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 } diff --git a/rpc/backend/account_info_test.go b/rpc/backend/account_info_test.go index 200cf36385..e3a7abe018 100644 --- a/rpc/backend/account_info_test.go +++ b/rpc/backend/account_info_test.go @@ -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()) }, @@ -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{}, @@ -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() @@ -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, @@ -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()) }, @@ -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()) }, @@ -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()) }, @@ -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()) }, diff --git a/rpc/backend/blocks.go b/rpc/backend/blocks.go index 28ab754487..131c8407ff 100644 --- a/rpc/backend/blocks.go +++ b/rpc/backend/blocks.go @@ -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 @@ -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 } @@ -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 } @@ -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) diff --git a/rpc/backend/blocks_test.go b/rpc/backend/blocks_test.go index cf36189793..f40e96d6c8 100644 --- a/rpc/backend/blocks_test.go +++ b/rpc/backend/blocks_test.go @@ -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()) @@ -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, @@ -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) @@ -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) @@ -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) @@ -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 { @@ -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()), @@ -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, }, diff --git a/rpc/backend/call_tx.go b/rpc/backend/call_tx.go index f9be170c78..c42a33fda1 100644 --- a/rpc/backend/call_tx.go +++ b/rpc/backend/call_tx.go @@ -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") @@ -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(), } @@ -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 @@ -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, } diff --git a/rpc/backend/call_tx_test.go b/rpc/backend/call_tx_test.go index 9ace06c491..dd1a377913 100644 --- a/rpc/backend/call_tx_test.go +++ b/rpc/backend/call_tx_test.go @@ -24,6 +24,7 @@ func (suite *BackendTestSuite) TestResend() { toAddr := tests.GenerateAddress() chainID := (*hexutil.Big)(suite.backend.chainID) validator := sdk.AccAddress(tests.GenerateAddress().Bytes()) + height := int64(1) callArgs := evmtypes.TransactionArgs{ From: nil, To: &toAddr, @@ -65,8 +66,8 @@ func (suite *BackendTestSuite) TestResend() { var header metadata.MD client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, 1) - RegisterBlock(client, 1, nil) + RegisterParams(queryClient, &header, height) + RegisterHeader(client, &height, nil) RegisterBlockResults(client, 1) RegisterBaseFeeDisabled(queryClient) RegisterValidatorAccount(queryClient, validator) @@ -87,10 +88,10 @@ func (suite *BackendTestSuite) TestResend() { client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient) - RegisterParams(queryClient, &header, 1) - RegisterFeeMarketParams(feeMarketClient, 1) - RegisterBlock(client, 1, nil) - RegisterBlockResults(client, 1) + RegisterParams(queryClient, &header, height) + RegisterFeeMarketParams(feeMarketClient, height) + RegisterHeader(client, &height, nil) + RegisterBlockResults(client, height) RegisterBaseFee(queryClient, baseFee) RegisterValidatorAccount(queryClient, validator) }, @@ -108,9 +109,9 @@ func (suite *BackendTestSuite) TestResend() { var header metadata.MD client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, 1) - RegisterBlock(client, 1, nil) - RegisterBlockResults(client, 1) + RegisterParams(queryClient, &header, height) + RegisterHeader(client, &height, nil) + RegisterBlockResults(client, height) RegisterBaseFeeDisabled(queryClient) RegisterValidatorAccount(queryClient, validator) }, @@ -145,8 +146,8 @@ func (suite *BackendTestSuite) TestResend() { var header metadata.MD client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, 1) - RegisterBlockError(client, 1) + RegisterParams(queryClient, &header, height) + RegisterHeaderError(client, &height) }, evmtypes.TransactionArgs{ Nonce: &txNonce, @@ -162,9 +163,9 @@ func (suite *BackendTestSuite) TestResend() { var header metadata.MD client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, 1) - RegisterBlock(client, 1, nil) - RegisterBlockResults(client, 1) + RegisterParams(queryClient, &header, height) + RegisterHeader(client, &height, nil) + RegisterBlockResults(client, height) RegisterBaseFee(queryClient, baseFee) RegisterValidatorAccount(queryClient, validator) }, @@ -186,9 +187,9 @@ func (suite *BackendTestSuite) TestResend() { var header metadata.MD client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterParams(queryClient, &header, 1) - RegisterBlock(client, 1, nil) - RegisterBlockResults(client, 1) + RegisterParams(queryClient, &header, height) + RegisterHeader(client, &height, nil) + RegisterBlockResults(client, height) RegisterBaseFee(queryClient, baseFee) RegisterValidatorAccount(queryClient, validator) }, @@ -208,12 +209,12 @@ func (suite *BackendTestSuite) TestResend() { var header metadata.MD client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBlock(client, 1, nil) - RegisterBlockResults(client, 1) + RegisterHeader(client, &height, nil) + RegisterBlockResults(client, height) RegisterBaseFee(queryClient, baseFee) RegisterEstimateGas(queryClient, callArgs) - RegisterParams(queryClient, &header, 1) - RegisterParamsWithoutHeader(queryClient, 1) + RegisterParams(queryClient, &header, height) + RegisterParamsWithoutHeader(queryClient, height) RegisterUnconfirmedTxsError(client, nil) RegisterValidatorAccount(queryClient, validator) }, @@ -237,12 +238,12 @@ func (suite *BackendTestSuite) TestResend() { var header metadata.MD client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBlock(client, 1, nil) - RegisterBlockResults(client, 1) + RegisterHeader(client, &height, nil) + RegisterBlockResults(client, height) RegisterBaseFee(queryClient, baseFee) RegisterEstimateGas(queryClient, callArgs) - RegisterParams(queryClient, &header, 1) - RegisterParamsWithoutHeader(queryClient, 1) + RegisterParams(queryClient, &header, height) + RegisterParamsWithoutHeader(queryClient, height) RegisterUnconfirmedTxsEmpty(client, nil) RegisterValidatorAccount(queryClient, validator) }, @@ -405,7 +406,8 @@ func (suite *BackendTestSuite) TestDoCall() { func() { client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBlock(client, 1, bz) + height := int64(1) + RegisterHeader(client, &height, bz) RegisterEthCallError(queryClient, &evmtypes.EthCallRequest{Args: argsBz, ChainId: suite.backend.chainID.Int64()}) }, rpctypes.BlockNumber(1), @@ -418,7 +420,8 @@ func (suite *BackendTestSuite) TestDoCall() { func() { client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBlock(client, 1, bz) + height := int64(1) + RegisterHeader(client, &height, bz) RegisterEthCall(queryClient, &evmtypes.EthCallRequest{Args: argsBz, ChainId: suite.backend.chainID.Int64()}) }, rpctypes.BlockNumber(1), @@ -447,7 +450,7 @@ func (suite *BackendTestSuite) TestDoCall() { func (suite *BackendTestSuite) TestGasPrice() { defaultGasPrice := (*hexutil.Big)(big.NewInt(1)) validator := sdk.AccAddress(tests.GenerateAddress().Bytes()) - + height := int64(1) testCases := []struct { name string registerMock func() @@ -461,10 +464,10 @@ func (suite *BackendTestSuite) TestGasPrice() { client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient) - RegisterFeeMarketParams(feeMarketClient, 1) - RegisterParams(queryClient, &header, 1) - RegisterBlock(client, 1, nil) - RegisterBlockResults(client, 1) + RegisterFeeMarketParams(feeMarketClient, height) + RegisterParams(queryClient, &header, height) + RegisterHeader(client, &height, nil) + RegisterBlockResults(client, height) RegisterBaseFee(queryClient, sdkmath.NewInt(1)) RegisterValidatorAccount(queryClient, validator) }, @@ -478,10 +481,10 @@ func (suite *BackendTestSuite) TestGasPrice() { client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) feeMarketClient := suite.backend.queryClient.FeeMarket.(*mocks.FeeMarketQueryClient) - RegisterFeeMarketParamsError(feeMarketClient, 1) - RegisterParams(queryClient, &header, 1) - RegisterBlock(client, 1, nil) - RegisterBlockResults(client, 1) + RegisterFeeMarketParamsError(feeMarketClient, height) + RegisterParams(queryClient, &header, height) + RegisterHeader(client, &height, nil) + RegisterBlockResults(client, height) RegisterBaseFee(queryClient, sdkmath.NewInt(1)) RegisterValidatorAccount(queryClient, validator) }, diff --git a/rpc/backend/client_test.go b/rpc/backend/client_test.go index f4708137ef..0e1d8b2a36 100644 --- a/rpc/backend/client_test.go +++ b/rpc/backend/client_test.go @@ -289,6 +289,29 @@ func RegisterHeaderByHashError(client *mocks.Client, hash common.Hash, tx []byte Return(nil, errortypes.ErrInvalidRequest) } +func RegisterHeaderByHashNotFound(client *mocks.Client, hash common.Hash, tx []byte) { + client.On("HeaderByHash", rpc.ContextWithHeight(1), bytes.HexBytes(hash.Bytes())). + Return(&tmrpctypes.ResultHeader{Header: nil}, nil) +} + +// Header +func RegisterHeader(client *mocks.Client, height *int64, tx []byte) (*tmrpctypes.ResultHeader, error) { + block := types.MakeBlock(*height, []types.Tx{tx}, nil, nil) + resHeader := &tmrpctypes.ResultHeader{Header: &block.Header} + client.On("Header", rpc.ContextWithHeight(*height), height).Return(resHeader, nil) + return resHeader, nil +} + +func RegisterHeaderError(client *mocks.Client, height *int64) { + client.On("Header", rpc.ContextWithHeight(*height), height).Return(nil, errortypes.ErrInvalidRequest) +} + +// Header not found +func RegisterHeaderNotFound(client *mocks.Client, height int64) { + client.On("Header", rpc.ContextWithHeight(height), mock.AnythingOfType("*int64")). + Return(&tmrpctypes.ResultHeader{Header: nil}, nil) +} + func RegisterABCIQueryWithOptions(client *mocks.Client, height int64, path string, data bytes.HexBytes, opts tmrpcclient.ABCIQueryOptions) { client.On("ABCIQueryWithOptions", context.Background(), path, data, opts). Return(&tmrpctypes.ResultABCIQuery{ diff --git a/rpc/backend/sign_tx_test.go b/rpc/backend/sign_tx_test.go index a8bcb24803..d555bc995e 100644 --- a/rpc/backend/sign_tx_test.go +++ b/rpc/backend/sign_tx_test.go @@ -37,7 +37,7 @@ func (suite *BackendTestSuite) TestSendTransaction() { } hash := common.Hash{} validator := sdk.AccAddress(tests.GenerateAddress().Bytes()) - + height := int64(1) testCases := []struct { name string registerMock func() @@ -60,8 +60,8 @@ func (suite *BackendTestSuite) TestSendTransaction() { client := suite.backend.clientCtx.Client.(*mocks.Client) armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1") suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "") - RegisterParams(queryClient, &header, 1) - RegisterBlockError(client, 1) + RegisterParams(queryClient, &header, height) + RegisterHeaderError(client, &height) }, callArgsDefault, hash, @@ -76,8 +76,8 @@ func (suite *BackendTestSuite) TestSendTransaction() { armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1") suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "") RegisterParams(queryClient, &header, 1) - RegisterBlock(client, 1, nil) - RegisterBlockResults(client, 1) + RegisterHeader(client, &height, nil) + RegisterBlockResults(client, height) RegisterBaseFee(queryClient, baseFee) RegisterValidatorAccount(queryClient, validator) }, @@ -100,10 +100,10 @@ func (suite *BackendTestSuite) TestSendTransaction() { armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1") suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "") RegisterParams(queryClient, &header, 1) - RegisterBlock(client, 1, nil) - RegisterBlockResults(client, 1) + RegisterHeader(client, &height, nil) + RegisterBlockResults(client, height) RegisterBaseFee(queryClient, baseFee) - RegisterParamsWithoutHeader(queryClient, 1) + RegisterParamsWithoutHeader(queryClient, height) ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig()) msg := callArgsDefault.ToTransaction() msg.Sign(ethSigner, suite.backend.clientCtx.Keyring) @@ -126,10 +126,10 @@ func (suite *BackendTestSuite) TestSendTransaction() { armor := crypto.EncryptArmorPrivKey(priv, "", "eth_secp256k1") suite.backend.clientCtx.Keyring.ImportPrivKey("test_key", armor, "") RegisterParams(queryClient, &header, 1) - RegisterBlock(client, 1, nil) - RegisterBlockResults(client, 1) + RegisterHeader(client, &height, nil) + RegisterBlockResults(client, height) RegisterBaseFee(queryClient, baseFee) - RegisterParamsWithoutHeader(queryClient, 1) + RegisterParamsWithoutHeader(queryClient, height) ethSigner := ethtypes.LatestSigner(suite.backend.ChainConfig()) msg := callArgsDefault.ToTransaction() msg.Sign(ethSigner, suite.backend.clientCtx.Keyring) diff --git a/rpc/backend/tracing.go b/rpc/backend/tracing.go index ab0845dc5a..fe70f9eca7 100644 --- a/rpc/backend/tracing.go +++ b/rpc/backend/tracing.go @@ -231,7 +231,7 @@ func (b *Backend) TraceCall( if err != nil { return nil, err } - blk, 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") @@ -240,10 +240,10 @@ func (b *Backend) TraceCall( traceCallRequest := evmtypes.QueryTraceCallRequest{ Args: bz, GasCap: b.RPCGasCap(), - ProposerAddress: sdk.ConsAddress(blk.Block.ProposerAddress), - BlockNumber: blk.Block.Height, - BlockHash: common.Bytes2Hex(blk.BlockID.Hash), - BlockTime: blk.Block.Time, + ProposerAddress: sdk.ConsAddress(header.Header.ProposerAddress), + BlockNumber: header.Header.Height, + BlockHash: common.Bytes2Hex(header.Header.Hash()), + BlockTime: header.Header.Time, ChainId: b.chainID.Int64(), } @@ -252,7 +252,7 @@ func (b *Backend) TraceCall( } // get the context of provided block - contextHeight := blk.Block.Height + contextHeight := header.Header.Height if contextHeight < 1 { // 0 is a special value in `ContextWithHeight` contextHeight = 1 diff --git a/rpc/backend/tracing_test.go b/rpc/backend/tracing_test.go index 78f2284aaa..1cf69ffe61 100644 --- a/rpc/backend/tracing_test.go +++ b/rpc/backend/tracing_test.go @@ -307,7 +307,8 @@ func (suite *BackendTestSuite) TestDebugTraceCall() { func() { client := suite.backend.clientCtx.Client.(*mocks.Client) queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) - RegisterBlock(client, 1, bz) + height := int64(1) + RegisterHeader(client, &height, bz) RegisterTraceCall( queryClient, &evmtypes.QueryTraceCallRequest{Args: argsBz, ChainId: suite.backend.chainID.Int64(), BlockNumber: 1}, diff --git a/tests/integration_tests/test_gas.py b/tests/integration_tests/test_gas.py index 9ab4c5480f..99f88eea2f 100644 --- a/tests/integration_tests/test_gas.py +++ b/tests/integration_tests/test_gas.py @@ -119,4 +119,4 @@ def discard(request, tmp_path_factory): def test_discard_abci_responses(discard): with pytest.raises(ValueError) as exc: discard.w3.eth.gas_price - assert "block result not found for height" in str(exc) + assert "header result not found for height" in str(exc) From c4cef0fc4056e135f5c62e7dbf2362992e3cc872 Mon Sep 17 00:00:00 2001 From: mmsqe Date: Fri, 4 Oct 2024 09:51:19 +0800 Subject: [PATCH 2/2] Problem: unsuppored sign mode SIGN_MODE_TEXTUAL in bank transfer (#537) --- CHANGELOG.md | 1 + app/app.go | 18 ++++++++++++++++++ cmd/ethermintd/root.go | 21 +++++++++++++++------ tests/integration_tests/test_batch.py | 12 ++++++++++++ 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ca67bb764..372dbc4ac4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ * (rpc) [#516](https://github.com/crypto-org-chain/ethermint/pull/516) Avoid method eth_chainId crashed due to nil pointer on IsEIP155 check. * (cli) [#524](https://github.com/crypto-org-chain/ethermint/pull/524) Allow tx evm raw run for generate only when offline with evm-denom flag. * (rpc) [#527](https://github.com/crypto-org-chain/ethermint/pull/527) Fix balance consistency between trace-block and state machine. +* (cli) [#537](https://github.com/crypto-org-chain/ethermint/pull/537) Fix unsuppored sign mode SIGN_MODE_TEXTUAL for bank transfer. ### Improvements diff --git a/app/app.go b/app/app.go index f3033bbba6..112f7f1b11 100644 --- a/app/app.go +++ b/app/app.go @@ -23,6 +23,7 @@ import ( "net/http" "os" "path/filepath" + "slices" "sort" autocliv1 "cosmossdk.io/api/cosmos/autocli/v1" @@ -31,6 +32,7 @@ import ( "cosmossdk.io/core/appmodule" runtimeservices "github.com/cosmos/cosmos-sdk/runtime/services" "github.com/cosmos/cosmos-sdk/server" + sigtypes "github.com/cosmos/cosmos-sdk/types/tx/signing" "github.com/cosmos/gogoproto/proto" "github.com/gorilla/mux" @@ -75,6 +77,7 @@ import ( "github.com/cosmos/cosmos-sdk/x/auth/posthandler" authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" authtx "github.com/cosmos/cosmos-sdk/x/auth/tx" + txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/cosmos/cosmos-sdk/x/auth/vesting" vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" @@ -380,6 +383,21 @@ func NewEthermintApp( authAddr, logger, ) + // optional: enable sign mode textual by overwriting the default tx config (after setting the bank keeper) + enabledSignModes := slices.Clone(authtx.DefaultSignModes) + enabledSignModes = append(enabledSignModes, sigtypes.SignMode_SIGN_MODE_TEXTUAL) + txConfigOpts := authtx.ConfigOptions{ + EnabledSignModes: enabledSignModes, + TextualCoinMetadataQueryFn: txmodule.NewBankKeeperCoinMetadataQueryFn(app.BankKeeper), + } + txConfig, err := authtx.NewTxConfigWithOptions( + appCodec, + txConfigOpts, + ) + if err != nil { + panic(err) + } + app.txConfig = txConfig app.StakingKeeper = stakingkeeper.NewKeeper( appCodec, runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), diff --git a/cmd/ethermintd/root.go b/cmd/ethermintd/root.go index 9b87971820..02501654da 100644 --- a/cmd/ethermintd/root.go +++ b/cmd/ethermintd/root.go @@ -19,6 +19,7 @@ import ( "errors" "io" "os" + "slices" "github.com/spf13/cobra" @@ -43,6 +44,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/client/debug" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" "github.com/cosmos/cosmos-sdk/types/tx/signing" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -65,14 +67,13 @@ const ( ChainID = "ethermint_9000-1" ) -type emptyAppOptions struct{} - -func (ao emptyAppOptions) Get(_ string) interface{} { return nil } - // NewRootCmd creates a new root command for simd. It is called once in the // main function. func NewRootCmd() (*cobra.Command, ethermint.EncodingConfig) { - tempApp := app.NewEthermintApp(cmtlog.NewNopLogger(), dbm.NewMemDB(), nil, true, emptyAppOptions{}) + tempApp := app.NewEthermintApp( + cmtlog.NewNopLogger(), dbm.NewMemDB(), nil, true, + simtestutil.NewAppOptionsWithFlagHome(app.DefaultNodeHome), + ) encodingConfig := tempApp.EncodingConfig() initClientCtx := client.Context{}. WithCodec(encodingConfig.Codec). @@ -86,6 +87,11 @@ func NewRootCmd() (*cobra.Command, ethermint.EncodingConfig) { WithKeyringOptions(hd.EthSecp256k1Option()). WithViper(EnvPrefix) + initClientCtx, err := clientcfg.ReadDefaultValuesFromDefaultClientConfig(initClientCtx) + if err != nil { + panic(err) + } + eip712.SetEncodingConfig(encodingConfig) rootCmd := &cobra.Command{ @@ -96,6 +102,7 @@ func NewRootCmd() (*cobra.Command, ethermint.EncodingConfig) { cmd.SetOut(cmd.OutOrStdout()) cmd.SetErr(cmd.ErrOrStderr()) + initClientCtx = initClientCtx.WithCmdContext(cmd.Context()) initClientCtx, err := client.ReadPersistentCommandFlags(initClientCtx, cmd.Flags()) if err != nil { return err @@ -110,8 +117,10 @@ func NewRootCmd() (*cobra.Command, ethermint.EncodingConfig) { // sets the RPC client needed for SIGN_MODE_TEXTUAL. This sign mode // is only available if the client is online. if !initClientCtx.Offline { + enabledSignModes := slices.Clone(tx.DefaultSignModes) + enabledSignModes = append(enabledSignModes, signing.SignMode_SIGN_MODE_TEXTUAL) txConfigOpts := tx.ConfigOptions{ - EnabledSignModes: append(tx.DefaultSignModes, signing.SignMode_SIGN_MODE_TEXTUAL), + EnabledSignModes: enabledSignModes, TextualCoinMetadataQueryFn: txmodule.NewGRPCCoinMetadataQueryFn(initClientCtx), } txConfig, err := tx.NewTxConfigWithOptions( diff --git a/tests/integration_tests/test_batch.py b/tests/integration_tests/test_batch.py index 80181d45c0..b43934a5b4 100644 --- a/tests/integration_tests/test_batch.py +++ b/tests/integration_tests/test_batch.py @@ -119,3 +119,15 @@ def test_multisig(ethermint, tmp_path): cli.account(multi_addr)["account"]["value"]["base_account"]["address"] == acc["address"] ) + + +def test_textual(ethermint): + cli = ethermint.cosmos_cli() + rsp = cli.transfer( + cli.address("validator"), + cli.address("signer2"), + "1aphoton", + sign_mode="textual", + ) + print("mm-rsp", rsp) + assert rsp["code"] == 0, rsp["raw_log"]