diff --git a/ethereum/rpc/backend/backend.go b/ethereum/rpc/backend/backend.go index bc5887d7..10909f4f 100644 --- a/ethereum/rpc/backend/backend.go +++ b/ethereum/rpc/backend/backend.go @@ -5,8 +5,10 @@ import ( "fmt" "math/big" "regexp" + "strconv" - "github.com/tharsis/ethermint/ethereum/rpc/types" + "google.golang.org/grpc" + "google.golang.org/grpc/metadata" "github.com/pkg/errors" "github.com/tendermint/tendermint/libs/log" @@ -14,10 +16,12 @@ import ( "github.com/cosmos/cosmos-sdk/client" sdk "github.com/cosmos/cosmos-sdk/types" + grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/tharsis/ethermint/ethereum/rpc/types" ethermint "github.com/tharsis/ethermint/types" evmtypes "github.com/tharsis/ethermint/x/evm/types" ) @@ -69,15 +73,28 @@ func NewEVMBackend(logger log.Logger, clientCtx client.Context) *EVMBackend { } } -// BlockNumber returns the current block number. +// BlockNumber returns the current block number in abci app state. +// Because abci app state could lag behind from tendermint latest block, it's more stable +// for the client to use the latest block number in abci app state than tendermint rpc. func (e *EVMBackend) BlockNumber() (hexutil.Uint64, error) { - // NOTE: using 0 as min and max height returns the blockchain info up to the latest block. - info, err := e.clientCtx.Client.BlockchainInfo(e.ctx, 0, 0) + // do any grpc query, ignore the response and use the returned block height + var header metadata.MD + _, err := e.queryClient.Params(e.ctx, &evmtypes.QueryParamsRequest{}, grpc.Header(&header)) if err != nil { return hexutil.Uint64(0), err } - return hexutil.Uint64(info.LastHeight), nil + blockHeightHeader := header.Get(grpctypes.GRPCBlockHeightHeader) + if headerLen := len(blockHeightHeader); headerLen != 1 { + return 0, fmt.Errorf("unexpected '%s' gRPC header length; got %d, expected: %d", grpctypes.GRPCBlockHeightHeader, headerLen, 1) + } + + height, err := strconv.ParseUint(blockHeightHeader[0], 10, 64) + if err != nil { + return 0, fmt.Errorf("failed to parse block height: %w", err) + } + + return hexutil.Uint64(height), nil } // GetBlockByNumber returns the block identified by number.