forked from cerc-io/laconicd-deprecated
		
	tests(rpc): add backend blocks tests (#1296)
* wip * rename GetTendermintBlockByNumber to TendermintBlockByNumber * rename GetTendermintBlockResultByNumber to TendermintBlockResultByNumber * rename GetTendermintBlockByHash to TendermintBlockByHash * rename BlockByNumber to EthBlockByNumber * rename BlockByHash to EthBlockByHash * rename GetBlockNumberByHash to BlockNumberFromTendermintByHash * rename GetBlockNumber to BlockNumberFromTendermint * rename GetEthereumMsgsFromTendermintBlock to EthMsgsFromTendermintBlock * rename GetEthBlockFromTendermint to BlockFromTendermintBlock * rename EthBlockFromTendermint to EthBlockFromTendermintBlock * add TestEthBlockFromTendermintBlock with no transactions. Note that this endpoint is breaking when querying a block with transactions * add block transaction count tests * add TendermintBlockByHash test' * add TestBlockNumberFromTendermint tests * add HeaderByHash and HeaderByNumber tests * add EthBlockFromTendermintBlock test * add TestEthBlockByNumber tests * Specificy that the endpoints are getting Etherum transactions in comments * Refactor shared logic into GetBlockTransactionCount * rename BlockFromTendermintBlock to RPCBlockFromTendermintBlock * add CHangelog
This commit is contained in:
		
							parent
							
								
									7bef408068
								
							
						
					
					
						commit
						9f03ca713d
					
				| @ -61,6 +61,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ | ||||
| * (cli) [#1230](https://github.com/evmos/ethermint/pull/1230) Remove redundant positional height parameter from feemarket's query cli. | ||||
| * (ante) [#1289](https://github.com/evmos/ethermint/pull/1289) Change the fallback tx priority mechanism to be based on gas price. | ||||
| * (test) [#1311](https://github.com/evmos/ethermint/pull/1311) add integration test for the rollback cmd | ||||
| * (rpc) [#1296](https://github.com/evmos/ethermint/pull/1296) add backend blocks.go unit tests. | ||||
| 
 | ||||
| ### Bug Fixes | ||||
| 
 | ||||
|  | ||||
| @ -17,7 +17,7 @@ import ( | ||||
| 
 | ||||
| // GetCode returns the contract code at the given address and block number.
 | ||||
| func (b *Backend) GetCode(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Bytes, error) { | ||||
| 	blockNum, err := b.GetBlockNumber(blockNrOrHash) | ||||
| 	blockNum, err := b.BlockNumberFromTendermint(blockNrOrHash) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -35,17 +35,14 @@ func (b *Backend) GetCode(address common.Address, blockNrOrHash rpctypes.BlockNu | ||||
| } | ||||
| 
 | ||||
| // GetProof returns an account object with proof and any storage proofs
 | ||||
| func (b *Backend) GetProof(address common.Address, | ||||
| 	storageKeys []string, | ||||
| 	blockNrOrHash rpctypes.BlockNumberOrHash, | ||||
| ) (*rpctypes.AccountResult, error) { | ||||
| 	blockNum, err := b.GetBlockNumber(blockNrOrHash) | ||||
| func (b *Backend) GetProof(address common.Address, storageKeys []string, blockNrOrHash rpctypes.BlockNumberOrHash) (*rpctypes.AccountResult, error) { | ||||
| 	blockNum, err := b.BlockNumberFromTendermint(blockNrOrHash) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	height := blockNum.Int64() | ||||
| 	_, err = b.GetTendermintBlockByNumber(blockNum) | ||||
| 	_, err = b.TendermintBlockByNumber(blockNum) | ||||
| 	if err != nil { | ||||
| 		// the error message imitates geth behavior
 | ||||
| 		return nil, errors.New("header not found") | ||||
| @ -132,7 +129,7 @@ func (b *Backend) GetProof(address common.Address, | ||||
| 
 | ||||
| // GetStorageAt returns the contract storage at the given address, block number, and key.
 | ||||
| func (b *Backend) GetStorageAt(address common.Address, key string, blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Bytes, error) { | ||||
| 	blockNum, err := b.GetBlockNumber(blockNrOrHash) | ||||
| 	blockNum, err := b.BlockNumberFromTendermint(blockNrOrHash) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -153,7 +150,7 @@ func (b *Backend) GetStorageAt(address common.Address, key string, blockNrOrHash | ||||
| 
 | ||||
| // GetBalance returns the provided account's balance up to the provided block number.
 | ||||
| func (b *Backend) GetBalance(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (*hexutil.Big, error) { | ||||
| 	blockNum, err := b.GetBlockNumber(blockNrOrHash) | ||||
| 	blockNum, err := b.BlockNumberFromTendermint(blockNrOrHash) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -162,7 +159,7 @@ func (b *Backend) GetBalance(address common.Address, blockNrOrHash rpctypes.Bloc | ||||
| 		Address: address.String(), | ||||
| 	} | ||||
| 
 | ||||
| 	_, err = b.GetTendermintBlockByNumber(blockNum) | ||||
| 	_, err = b.TendermintBlockByNumber(blockNum) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| @ -67,22 +67,21 @@ type EVMBackend interface { | ||||
| 	// Blocks Info
 | ||||
| 	BlockNumber() (hexutil.Uint64, error) | ||||
| 	GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) | ||||
| 	GetTendermintBlockByNumber(blockNum rpctypes.BlockNumber) (*tmrpctypes.ResultBlock, error) | ||||
| 	GetTendermintBlockResultByNumber(height *int64) (*tmrpctypes.ResultBlockResults, error) | ||||
| 	GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) | ||||
| 	GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) | ||||
| 	BlockByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Block, error) | ||||
| 	BlockByHash(blockHash common.Hash) (*ethtypes.Block, error) | ||||
| 	GetBlockNumberByHash(blockHash common.Hash) (*big.Int, error) | ||||
| 	GetBlockNumber(blockNrOrHash rpctypes.BlockNumberOrHash) (rpctypes.BlockNumber, error) | ||||
| 	GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint | ||||
| 	GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint | ||||
| 	TendermintBlockByNumber(blockNum rpctypes.BlockNumber) (*tmrpctypes.ResultBlock, error) | ||||
| 	TendermintBlockResultByNumber(height *int64) (*tmrpctypes.ResultBlockResults, error) | ||||
| 	TendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) | ||||
| 	BlockNumberFromTendermint(blockNrOrHash rpctypes.BlockNumberOrHash) (rpctypes.BlockNumber, error) | ||||
| 	BlockNumberFromTendermintByHash(blockHash common.Hash) (*big.Int, error) | ||||
| 	EthMsgsFromTendermintBlock(block *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) []*evmtypes.MsgEthereumTx | ||||
| 	BlockBloom(blockRes *tmrpctypes.ResultBlockResults) (ethtypes.Bloom, error) | ||||
| 	GetEthereumMsgsFromTendermintBlock(block *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) []*evmtypes.MsgEthereumTx | ||||
| 	HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error) | ||||
| 	HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) | ||||
| 	EthBlockFromTendermint(resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults, fullTx bool) (map[string]interface{}, error) | ||||
| 	EthBlockFromTm(resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) (*ethtypes.Block, error) | ||||
| 	RPCBlockFromTendermintBlock(resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults, fullTx bool) (map[string]interface{}, error) | ||||
| 	EthBlockByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Block, error) | ||||
| 	EthBlockFromTendermintBlock(resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) (*ethtypes.Block, error) | ||||
| 
 | ||||
| 	// Account Info
 | ||||
| 	GetCode(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (hexutil.Bytes, error) | ||||
| @ -117,6 +116,7 @@ type EVMBackend interface { | ||||
| 	SetTxDefaults(args evmtypes.TransactionArgs) (evmtypes.TransactionArgs, error) | ||||
| 	EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *rpctypes.BlockNumber) (hexutil.Uint64, error) | ||||
| 	DoCall(args evmtypes.TransactionArgs, blockNr rpctypes.BlockNumber) (*evmtypes.MsgEthereumTxResponse, error) | ||||
| 	GasPrice() (*hexutil.Big, error) | ||||
| 
 | ||||
| 	// Filter API
 | ||||
| 	GetLogs(hash common.Hash) ([][]*ethtypes.Log, error) | ||||
|  | ||||
| @ -11,6 +11,7 @@ import ( | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/common/hexutil" | ||||
| 	ethtypes "github.com/ethereum/go-ethereum/core/types" | ||||
| 	"github.com/ethereum/go-ethereum/trie" | ||||
| 	rpctypes "github.com/evmos/ethermint/rpc/types" | ||||
| 	evmtypes "github.com/evmos/ethermint/x/evm/types" | ||||
| 	"github.com/pkg/errors" | ||||
| @ -19,16 +20,10 @@ import ( | ||||
| 	"google.golang.org/grpc/metadata" | ||||
| ) | ||||
| 
 | ||||
| // Getting Blocks
 | ||||
| //
 | ||||
| // Retrieves information from a particular block in the blockchain.
 | ||||
| // BlockNumber() (hexutil.Uint64, error)
 | ||||
| // GetBlockByNumber(ethBlockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error)
 | ||||
| // GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error)
 | ||||
| 
 | ||||
| // 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.
 | ||||
| // 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 (b *Backend) BlockNumber() (hexutil.Uint64, error) { | ||||
| 	// do any grpc query, ignore the response and use the returned block height
 | ||||
| 	var header metadata.MD | ||||
| @ -50,9 +45,11 @@ func (b *Backend) BlockNumber() (hexutil.Uint64, error) { | ||||
| 	return hexutil.Uint64(height), nil | ||||
| } | ||||
| 
 | ||||
| // GetBlockByNumber returns the block identified by number.
 | ||||
| // GetBlockByNumber returns the JSON-RPC compatible Ethereum block identified by
 | ||||
| // block number. Depending on fullTx it either returns the full transaction
 | ||||
| // objects or if false only the hashes of the transactions.
 | ||||
| func (b *Backend) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) { | ||||
| 	resBlock, err := b.GetTendermintBlockByNumber(blockNum) | ||||
| 	resBlock, err := b.TendermintBlockByNumber(blockNum) | ||||
| 	if err != nil { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| @ -62,24 +59,25 @@ func (b *Backend) GetBlockByNumber(blockNum rpctypes.BlockNumber, fullTx bool) ( | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	blockRes, err := b.GetTendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 	blockRes, err := b.TendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("failed to fetch block result from Tendermint", "height", blockNum, "error", err.Error()) | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	res, err := b.EthBlockFromTendermint(resBlock, blockRes, fullTx) | ||||
| 	res, err := b.RPCBlockFromTendermintBlock(resBlock, blockRes, fullTx) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("EthBlockFromTendermint failed", "height", blockNum, "error", err.Error()) | ||||
| 		b.logger.Debug("GetEthBlockFromTendermint failed", "height", blockNum, "error", err.Error()) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // GetBlockByHash returns the block identified by hash.
 | ||||
| // GetBlockByHash returns the JSON-RPC compatible Ethereum block identified by
 | ||||
| // hash.
 | ||||
| func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) { | ||||
| 	resBlock, err := b.GetTendermintBlockByHash(hash) | ||||
| 	resBlock, err := b.TendermintBlockByHash(hash) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -89,24 +87,71 @@ func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]inte | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	blockRes, err := b.GetTendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 	blockRes, err := b.TendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("failed to fetch block result from Tendermint", "block-hash", hash.String(), "error", err.Error()) | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	res, err := b.EthBlockFromTendermint(resBlock, blockRes, fullTx) | ||||
| 	res, err := b.RPCBlockFromTendermintBlock(resBlock, blockRes, fullTx) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("EthBlockFromTendermint failed", "hash", hash, "error", err.Error()) | ||||
| 		b.logger.Debug("GetEthBlockFromTendermint failed", "hash", hash, "error", err.Error()) | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // GetTendermintBlockByNumber returns a Tendermint formatted block for a given
 | ||||
| // GetBlockTransactionCountByHash returns the number of Ethereum transactions in
 | ||||
| // the block identified by hash.
 | ||||
| func (b *Backend) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint { | ||||
| 	block, err := b.clientCtx.Client.BlockByHash(b.ctx, hash.Bytes()) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error()) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if block.Block == nil { | ||||
| 		b.logger.Debug("block not found", "hash", hash.Hex()) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	return b.GetBlockTransactionCount(block) | ||||
| } | ||||
| 
 | ||||
| // GetBlockTransactionCountByNumber returns the number of Ethereum transactions
 | ||||
| // in the block identified by number.
 | ||||
| func (b *Backend) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { | ||||
| 	block, err := b.TendermintBlockByNumber(blockNum) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if block.Block == nil { | ||||
| 		b.logger.Debug("block not found", "height", blockNum.Int64()) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	return b.GetBlockTransactionCount(block) | ||||
| } | ||||
| 
 | ||||
| // GetBlockTransactionCount returns the number of Ethereum transactions in a
 | ||||
| // given block.
 | ||||
| func (b *Backend) GetBlockTransactionCount(block *tmrpctypes.ResultBlock) *hexutil.Uint { | ||||
| 	blockRes, err := b.TendermintBlockResultByNumber(&block.Block.Height) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	ethMsgs := b.EthMsgsFromTendermintBlock(block, blockRes) | ||||
| 	n := hexutil.Uint(len(ethMsgs)) | ||||
| 	return &n | ||||
| } | ||||
| 
 | ||||
| // TendermintBlockByNumber returns a Tendermint-formatted block for a given
 | ||||
| // block number
 | ||||
| func (b *Backend) GetTendermintBlockByNumber(blockNum rpctypes.BlockNumber) (*tmrpctypes.ResultBlock, error) { | ||||
| func (b *Backend) TendermintBlockByNumber(blockNum rpctypes.BlockNumber) (*tmrpctypes.ResultBlock, error) { | ||||
| 	height := blockNum.Int64() | ||||
| 	if height <= 0 { | ||||
| 		// fetch the latest block number from the app state, more accurate than the tendermint block store state.
 | ||||
| @ -123,36 +168,21 @@ func (b *Backend) GetTendermintBlockByNumber(blockNum rpctypes.BlockNumber) (*tm | ||||
| 	} | ||||
| 
 | ||||
| 	if resBlock.Block == nil { | ||||
| 		b.logger.Debug("GetTendermintBlockByNumber block not found", "height", height) | ||||
| 		b.logger.Debug("TendermintBlockByNumber block not found", "height", height) | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	return resBlock, nil | ||||
| } | ||||
| 
 | ||||
| // BlockBloom query block bloom filter from block results
 | ||||
| func (b *Backend) BlockBloom(blockRes *tmrpctypes.ResultBlockResults) (ethtypes.Bloom, error) { | ||||
| 	for _, event := range blockRes.EndBlockEvents { | ||||
| 		if event.Type != evmtypes.EventTypeBlockBloom { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		for _, attr := range event.Attributes { | ||||
| 			if bytes.Equal(attr.Key, bAttributeKeyEthereumBloom) { | ||||
| 				return ethtypes.BytesToBloom(attr.Value), nil | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return ethtypes.Bloom{}, errors.New("block bloom event is not found") | ||||
| } | ||||
| 
 | ||||
| // GetTendermintBlockResultByNumber returns a Tendermint-formatted block result by block number
 | ||||
| func (b *Backend) GetTendermintBlockResultByNumber(height *int64) (*tmrpctypes.ResultBlockResults, error) { | ||||
| // TendermintBlockResultByNumber returns a Tendermint-formatted block result
 | ||||
| // by block number
 | ||||
| func (b *Backend) TendermintBlockResultByNumber(height *int64) (*tmrpctypes.ResultBlockResults, error) { | ||||
| 	return b.clientCtx.Client.BlockResults(b.ctx, height) | ||||
| } | ||||
| 
 | ||||
| // GetTendermintBlockByHash returns a Tendermint format block by block number
 | ||||
| func (b *Backend) GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) { | ||||
| // TendermintBlockByHash returns a Tendermint-formatted block by block number
 | ||||
| func (b *Backend) TendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) { | ||||
| 	resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, blockHash.Bytes()) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("tendermint client failed to get block", "blockHash", blockHash.Hex(), "error", err.Error()) | ||||
| @ -160,70 +190,20 @@ func (b *Backend) GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.R | ||||
| 	} | ||||
| 
 | ||||
| 	if resBlock == nil || resBlock.Block == nil { | ||||
| 		b.logger.Debug("GetTendermintBlockByHash block not found", "blockHash", blockHash.Hex()) | ||||
| 		b.logger.Debug("TendermintBlockByHash block not found", "blockHash", blockHash.Hex()) | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	return resBlock, nil | ||||
| } | ||||
| 
 | ||||
| // BlockByNumber returns the block identified by number.
 | ||||
| func (b *Backend) BlockByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Block, error) { | ||||
| 	resBlock, err := b.GetTendermintBlockByNumber(blockNum) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if resBlock == nil { | ||||
| 		// block not found
 | ||||
| 		return nil, fmt.Errorf("block not found for height %d", blockNum) | ||||
| 	} | ||||
| 
 | ||||
| 	blockRes, err := b.GetTendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height) | ||||
| 	} | ||||
| 
 | ||||
| 	return b.EthBlockFromTm(resBlock, blockRes) | ||||
| } | ||||
| 
 | ||||
| // BlockByHash returns the block identified by hash.
 | ||||
| func (b *Backend) BlockByHash(hash common.Hash) (*ethtypes.Block, error) { | ||||
| 	resBlock, err := b.GetTendermintBlockByHash(hash) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	if resBlock == nil || resBlock.Block == nil { | ||||
| 		return nil, fmt.Errorf("block not found for hash %s", hash) | ||||
| 	} | ||||
| 
 | ||||
| 	blockRes, err := b.GetTendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("block result not found for hash %s", hash) | ||||
| 	} | ||||
| 
 | ||||
| 	return b.EthBlockFromTm(resBlock, blockRes) | ||||
| } | ||||
| 
 | ||||
| // GetBlockNumberByHash returns the block height of given block hash
 | ||||
| func (b *Backend) GetBlockNumberByHash(blockHash common.Hash) (*big.Int, error) { | ||||
| 	resBlock, err := b.GetTendermintBlockByHash(blockHash) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if resBlock == nil { | ||||
| 		return nil, errors.Errorf("block not found for hash %s", blockHash.Hex()) | ||||
| 	} | ||||
| 	return big.NewInt(resBlock.Block.Height), nil | ||||
| } | ||||
| 
 | ||||
| // getBlockNumber returns the BlockNumber from BlockNumberOrHash
 | ||||
| func (b *Backend) GetBlockNumber(blockNrOrHash rpctypes.BlockNumberOrHash) (rpctypes.BlockNumber, error) { | ||||
| // BlockNumberFromTendermint returns the BlockNumber from BlockNumberOrHash
 | ||||
| func (b *Backend) BlockNumberFromTendermint(blockNrOrHash rpctypes.BlockNumberOrHash) (rpctypes.BlockNumber, error) { | ||||
| 	switch { | ||||
| 	case blockNrOrHash.BlockHash == nil && blockNrOrHash.BlockNumber == nil: | ||||
| 		return rpctypes.EthEarliestBlockNumber, fmt.Errorf("types BlockHash and BlockNumber cannot be both nil") | ||||
| 	case blockNrOrHash.BlockHash != nil: | ||||
| 		blockNumber, err := b.GetBlockNumberByHash(*blockNrOrHash.BlockHash) | ||||
| 		blockNumber, err := b.BlockNumberFromTendermintByHash(*blockNrOrHash.BlockHash) | ||||
| 		if err != nil { | ||||
| 			return rpctypes.EthEarliestBlockNumber, err | ||||
| 		} | ||||
| @ -235,56 +215,22 @@ func (b *Backend) GetBlockNumber(blockNrOrHash rpctypes.BlockNumberOrHash) (rpct | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // GetBlockTransactionCountByHash returns the number of transactions in the block identified by hash.
 | ||||
| func (b *Backend) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint { | ||||
| 	block, err := b.clientCtx.Client.BlockByHash(b.ctx, hash.Bytes()) | ||||
| // BlockNumberFromTendermintByHash returns the block height of given block hash
 | ||||
| func (b *Backend) BlockNumberFromTendermintByHash(blockHash common.Hash) (*big.Int, error) { | ||||
| 	resBlock, err := b.TendermintBlockByHash(blockHash) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("block not found", "hash", hash.Hex(), "error", err.Error()) | ||||
| 		return nil | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if resBlock == nil { | ||||
| 		return nil, errors.Errorf("block not found for hash %s", blockHash.Hex()) | ||||
| 	} | ||||
| 	return big.NewInt(resBlock.Block.Height), nil | ||||
| } | ||||
| 
 | ||||
| 	if block.Block == nil { | ||||
| 		b.logger.Debug("block not found", "hash", hash.Hex()) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	blockRes, err := b.GetTendermintBlockResultByNumber(&block.Block.Height) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	ethMsgs := b.GetEthereumMsgsFromTendermintBlock(block, blockRes) | ||||
| 	n := hexutil.Uint(len(ethMsgs)) | ||||
| 	return &n | ||||
| } | ||||
| 
 | ||||
| // GetBlockTransactionCountByNumber returns the number of transactions in the block identified by number.
 | ||||
| func (b *Backend) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { | ||||
| 	block, err := b.GetTendermintBlockByNumber(blockNum) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	if block.Block == nil { | ||||
| 		b.logger.Debug("block not found", "height", blockNum.Int64()) | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	blockRes, err := b.GetTendermintBlockResultByNumber(&block.Block.Height) | ||||
| 	if err != nil { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	ethMsgs := b.GetEthereumMsgsFromTendermintBlock(block, blockRes) | ||||
| 	n := hexutil.Uint(len(ethMsgs)) | ||||
| 	return &n | ||||
| } | ||||
| 
 | ||||
| // GetEthereumMsgsFromTendermintBlock returns all real MsgEthereumTxs from a
 | ||||
| // EthMsgsFromTendermintBlock returns all real MsgEthereumTxs from a
 | ||||
| // Tendermint block. It also ensures consistency over the correct txs indexes
 | ||||
| // across RPC endpoints
 | ||||
| func (b *Backend) GetEthereumMsgsFromTendermintBlock( | ||||
| func (b *Backend) EthMsgsFromTendermintBlock( | ||||
| 	resBlock *tmrpctypes.ResultBlock, | ||||
| 	blockRes *tmrpctypes.ResultBlockResults, | ||||
| ) []*evmtypes.MsgEthereumTx { | ||||
| @ -324,7 +270,7 @@ func (b *Backend) GetEthereumMsgsFromTendermintBlock( | ||||
| 
 | ||||
| // HeaderByNumber returns the block header identified by height.
 | ||||
| func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Header, error) { | ||||
| 	resBlock, err := b.GetTendermintBlockByNumber(blockNum) | ||||
| 	resBlock, err := b.TendermintBlockByNumber(blockNum) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -333,7 +279,7 @@ func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Heade | ||||
| 		return nil, errors.Errorf("block not found for height %d", blockNum) | ||||
| 	} | ||||
| 
 | ||||
| 	blockRes, err := b.GetTendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 	blockRes, err := b.TendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height) | ||||
| 	} | ||||
| @ -355,7 +301,7 @@ func (b *Backend) HeaderByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Heade | ||||
| 
 | ||||
| // HeaderByHash returns the block header identified by hash.
 | ||||
| func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) { | ||||
| 	resBlock, err := b.GetTendermintBlockByHash(blockHash) | ||||
| 	resBlock, err := b.TendermintBlockByHash(blockHash) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -363,7 +309,7 @@ func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) | ||||
| 		return nil, errors.Errorf("block not found for hash %s", blockHash.Hex()) | ||||
| 	} | ||||
| 
 | ||||
| 	blockRes, err := b.GetTendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 	blockRes, err := b.TendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 	if err != nil { | ||||
| 		return nil, errors.Errorf("block result not found for height %d", resBlock.Block.Height) | ||||
| 	} | ||||
| @ -383,9 +329,25 @@ func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) | ||||
| 	return ethHeader, nil | ||||
| } | ||||
| 
 | ||||
| // EthBlockFromTendermint returns a JSON-RPC compatible Ethereum block from a
 | ||||
| // BlockBloom query block bloom filter from block results
 | ||||
| func (b *Backend) BlockBloom(blockRes *tmrpctypes.ResultBlockResults) (ethtypes.Bloom, error) { | ||||
| 	for _, event := range blockRes.EndBlockEvents { | ||||
| 		if event.Type != evmtypes.EventTypeBlockBloom { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		for _, attr := range event.Attributes { | ||||
| 			if bytes.Equal(attr.Key, bAttributeKeyEthereumBloom) { | ||||
| 				return ethtypes.BytesToBloom(attr.Value), nil | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	return ethtypes.Bloom{}, errors.New("block bloom event is not found") | ||||
| } | ||||
| 
 | ||||
| // RPCBlockFromTendermintBlock returns a JSON-RPC compatible Ethereum block from a
 | ||||
| // given Tendermint block and its block result.
 | ||||
| func (b *Backend) EthBlockFromTendermint( | ||||
| func (b *Backend) RPCBlockFromTendermintBlock( | ||||
| 	resBlock *tmrpctypes.ResultBlock, | ||||
| 	blockRes *tmrpctypes.ResultBlockResults, | ||||
| 	fullTx bool, | ||||
| @ -399,7 +361,7 @@ func (b *Backend) EthBlockFromTendermint( | ||||
| 		b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", block.Height, "error", err) | ||||
| 	} | ||||
| 
 | ||||
| 	msgs := b.GetEthereumMsgsFromTendermintBlock(resBlock, blockRes) | ||||
| 	msgs := b.EthMsgsFromTendermintBlock(resBlock, blockRes) | ||||
| 	for txIndex, ethMsg := range msgs { | ||||
| 		if !fullTx { | ||||
| 			hash := common.HexToHash(ethMsg.Hash) | ||||
| @ -477,8 +439,31 @@ func (b *Backend) EthBlockFromTendermint( | ||||
| 	return formattedBlock, nil | ||||
| } | ||||
| 
 | ||||
| // Returns and Ethereum Block type from Tendermint block
 | ||||
| func (b *Backend) EthBlockFromTm(resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) (*ethtypes.Block, error) { | ||||
| // EthBlockByNumber returns the Ethereum Block identified by number.
 | ||||
| func (b *Backend) EthBlockByNumber(blockNum rpctypes.BlockNumber) (*ethtypes.Block, error) { | ||||
| 	resBlock, err := b.TendermintBlockByNumber(blockNum) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if resBlock == nil { | ||||
| 		// block not found
 | ||||
| 		return nil, fmt.Errorf("block not found for height %d", blockNum) | ||||
| 	} | ||||
| 
 | ||||
| 	blockRes, err := b.TendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height) | ||||
| 	} | ||||
| 
 | ||||
| 	return b.EthBlockFromTendermintBlock(resBlock, blockRes) | ||||
| } | ||||
| 
 | ||||
| // EthBlockFromTendermintBlock returns an Ethereum Block type from Tendermint block
 | ||||
| // EthBlockFromTendermintBlock
 | ||||
| func (b *Backend) EthBlockFromTendermintBlock( | ||||
| 	resBlock *tmrpctypes.ResultBlock, | ||||
| 	blockRes *tmrpctypes.ResultBlockResults, | ||||
| ) (*ethtypes.Block, error) { | ||||
| 	block := resBlock.Block | ||||
| 	height := block.Height | ||||
| 	bloom, err := b.BlockBloom(blockRes) | ||||
| @ -493,13 +478,7 @@ func (b *Backend) EthBlockFromTm(resBlock *tmrpctypes.ResultBlock, blockRes *tmr | ||||
| 	} | ||||
| 
 | ||||
| 	ethHeader := rpctypes.EthHeaderFromTendermint(block.Header, bloom, baseFee) | ||||
| 
 | ||||
| 	resBlockResult, err := b.GetTendermintBlockResultByNumber(&block.Height) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	msgs := b.GetEthereumMsgsFromTendermintBlock(resBlock, resBlockResult) | ||||
| 	msgs := b.EthMsgsFromTendermintBlock(resBlock, blockRes) | ||||
| 
 | ||||
| 	txs := make([]*ethtypes.Transaction, len(msgs)) | ||||
| 	for i, ethMsg := range msgs { | ||||
| @ -507,6 +486,6 @@ func (b *Backend) EthBlockFromTm(resBlock *tmrpctypes.ResultBlock, blockRes *tmr | ||||
| 	} | ||||
| 
 | ||||
| 	// TODO: add tx receipts
 | ||||
| 	ethBlock := ethtypes.NewBlock(ethHeader, txs, nil, nil, nil) | ||||
| 	ethBlock := ethtypes.NewBlock(ethHeader, txs, nil, nil, trie.NewStackTrie(nil)) | ||||
| 	return ethBlock, nil | ||||
| } | ||||
| @ -8,6 +8,7 @@ import ( | ||||
| 	"github.com/ethereum/go-ethereum/common" | ||||
| 	"github.com/ethereum/go-ethereum/common/hexutil" | ||||
| 	ethtypes "github.com/ethereum/go-ethereum/core/types" | ||||
| 	"github.com/ethereum/go-ethereum/trie" | ||||
| 	"github.com/tendermint/tendermint/abci/types" | ||||
| 	tmrpctypes "github.com/tendermint/tendermint/rpc/core/types" | ||||
| 	tmtypes "github.com/tendermint/tendermint/types" | ||||
| @ -17,7 +18,6 @@ import ( | ||||
| 	ethrpc "github.com/evmos/ethermint/rpc/types" | ||||
| 	"github.com/evmos/ethermint/tests" | ||||
| 	evmtypes "github.com/evmos/ethermint/x/evm/types" | ||||
| 	feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" | ||||
| ) | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestBlockNumber() { | ||||
| @ -242,6 +242,54 @@ func (suite *BackendTestSuite) TestGetBlockByHash() { | ||||
| 		expNoop      bool | ||||
| 		expPass      bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"fail - tendermint failed to get block", | ||||
| 			common.BytesToHash(block.Hash()), | ||||
| 			true, | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			sdk.AccAddress(tests.GenerateAddress().Bytes()), | ||||
| 			nil, | ||||
| 			nil, | ||||
| 			func(hash common.Hash, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) { | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockByHashError(client, hash, txBz) | ||||
| 			}, | ||||
| 			false, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"noop - tendermint blockres not found", | ||||
| 			common.BytesToHash(block.Hash()), | ||||
| 			true, | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			sdk.AccAddress(tests.GenerateAddress().Bytes()), | ||||
| 			nil, | ||||
| 			nil, | ||||
| 			func(hash common.Hash, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) { | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockByHashNotFound(client, hash, txBz) | ||||
| 			}, | ||||
| 			true, | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"noop - tendermint failed to fetch block result", | ||||
| 			common.BytesToHash(block.Hash()), | ||||
| 			true, | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			sdk.AccAddress(tests.GenerateAddress().Bytes()), | ||||
| 			nil, | ||||
| 			nil, | ||||
| 			func(hash common.Hash, baseFee sdk.Int, validator sdk.AccAddress, txBz []byte) { | ||||
| 				height := int64(1) | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				resBlock, _ = RegisterBlockByHash(client, hash, txBz) | ||||
| 
 | ||||
| 				RegisterBlockResultsError(client, height) | ||||
| 			}, | ||||
| 			true, | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - without tx", | ||||
| 			common.BytesToHash(block.Hash()), | ||||
| @ -319,7 +367,156 @@ func (suite *BackendTestSuite) TestGetBlockByHash() { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestGetTendermintBlockByNumber() { | ||||
| func (suite *BackendTestSuite) TestGetBlockTransactionCountByHash() { | ||||
| 	_, bz := suite.buildEthereumTx() | ||||
| 	block := tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil) | ||||
| 	emptyBlock := tmtypes.MakeBlock(1, []tmtypes.Tx{}, nil, nil) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name         string | ||||
| 		hash         common.Hash | ||||
| 		registerMock func(common.Hash) | ||||
| 		expCount     hexutil.Uint | ||||
| 		expPass      bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"fail - block not found", | ||||
| 			common.BytesToHash(emptyBlock.Hash()), | ||||
| 			func(hash common.Hash) { | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockByHashError(client, hash, nil) | ||||
| 			}, | ||||
| 			hexutil.Uint(0), | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - tendermint client failed to get block result", | ||||
| 			common.BytesToHash(emptyBlock.Hash()), | ||||
| 			func(hash common.Hash) { | ||||
| 				height := int64(1) | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockByHash(client, hash, nil) | ||||
| 				RegisterBlockResultsError(client, height) | ||||
| 			}, | ||||
| 			hexutil.Uint(0), | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - block without tx", | ||||
| 			common.BytesToHash(emptyBlock.Hash()), | ||||
| 			func(hash common.Hash) { | ||||
| 				height := int64(1) | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockByHash(client, hash, nil) | ||||
| 				RegisterBlockResults(client, height) | ||||
| 			}, | ||||
| 			hexutil.Uint(0), | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - block with tx", | ||||
| 			common.BytesToHash(block.Hash()), | ||||
| 			func(hash common.Hash) { | ||||
| 				height := int64(1) | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockByHash(client, hash, bz) | ||||
| 				RegisterBlockResults(client, height) | ||||
| 			}, | ||||
| 			hexutil.Uint(1), | ||||
| 			true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(fmt.Sprintf("Case %s", tc.name), func() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 
 | ||||
| 			tc.registerMock(tc.hash) | ||||
| 			count := suite.backend.GetBlockTransactionCountByHash(tc.hash) | ||||
| 			if tc.expPass { | ||||
| 				suite.Require().Equal(tc.expCount, *count) | ||||
| 			} else { | ||||
| 				suite.Require().Nil(count) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestGetBlockTransactionCountByNumber() { | ||||
| 	_, bz := suite.buildEthereumTx() | ||||
| 	block := tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil) | ||||
| 	emptyBlock := tmtypes.MakeBlock(1, []tmtypes.Tx{}, nil, nil) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name         string | ||||
| 		blockNum     ethrpc.BlockNumber | ||||
| 		registerMock func(ethrpc.BlockNumber) | ||||
| 		expCount     hexutil.Uint | ||||
| 		expPass      bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"fail - block not found", | ||||
| 			ethrpc.BlockNumber(emptyBlock.Height), | ||||
| 			func(blockNum ethrpc.BlockNumber) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockError(client, height) | ||||
| 			}, | ||||
| 			hexutil.Uint(0), | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - tendermint client failed to get block result", | ||||
| 			ethrpc.BlockNumber(emptyBlock.Height), | ||||
| 			func(blockNum ethrpc.BlockNumber) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlock(client, height, nil) | ||||
| 				RegisterBlockResultsError(client, height) | ||||
| 			}, | ||||
| 			hexutil.Uint(0), | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - block without tx", | ||||
| 			ethrpc.BlockNumber(emptyBlock.Height), | ||||
| 			func(blockNum ethrpc.BlockNumber) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlock(client, height, nil) | ||||
| 				RegisterBlockResults(client, height) | ||||
| 			}, | ||||
| 			hexutil.Uint(0), | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - block with tx", | ||||
| 			ethrpc.BlockNumber(block.Height), | ||||
| 			func(blockNum ethrpc.BlockNumber) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlock(client, height, bz) | ||||
| 				RegisterBlockResults(client, height) | ||||
| 			}, | ||||
| 			hexutil.Uint(1), | ||||
| 			true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(fmt.Sprintf("Case %s", tc.name), func() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 
 | ||||
| 			tc.registerMock(tc.blockNum) | ||||
| 			count := suite.backend.GetBlockTransactionCountByNumber(tc.blockNum) | ||||
| 			if tc.expPass { | ||||
| 				suite.Require().Equal(tc.expCount, *count) | ||||
| 			} else { | ||||
| 				suite.Require().Nil(count) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestTendermintBlockByNumber() { | ||||
| 	var expResultBlock *tmrpctypes.ResultBlock | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| @ -407,7 +604,7 @@ func (suite *BackendTestSuite) TestGetTendermintBlockByNumber() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 
 | ||||
| 			tc.registerMock(tc.blockNumber) | ||||
| 			resultBlock, err := suite.backend.GetTendermintBlockByNumber(tc.blockNumber) | ||||
| 			resultBlock, err := suite.backend.TendermintBlockByNumber(tc.blockNumber) | ||||
| 
 | ||||
| 			if tc.expPass { | ||||
| 				suite.Require().NoError(err) | ||||
| @ -425,7 +622,7 @@ func (suite *BackendTestSuite) TestGetTendermintBlockByNumber() { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestGetTendermintBlockResultByNumber() { | ||||
| func (suite *BackendTestSuite) TestTendermintBlockResultByNumber() { | ||||
| 	var expBlockRes *tmrpctypes.ResultBlockResults | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| @ -463,7 +660,7 @@ func (suite *BackendTestSuite) TestGetTendermintBlockResultByNumber() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 			tc.registerMock(tc.blockNumber) | ||||
| 
 | ||||
| 			blockRes, err := suite.backend.GetTendermintBlockResultByNumber(&tc.blockNumber) | ||||
| 			blockRes, err := suite.backend.TendermintBlockResultByNumber(&tc.blockNumber) | ||||
| 
 | ||||
| 			if tc.expPass { | ||||
| 				suite.Require().NoError(err) | ||||
| @ -475,6 +672,141 @@ func (suite *BackendTestSuite) TestGetTendermintBlockResultByNumber() { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestBlockNumberFromTendermint() { | ||||
| 	var resBlock *tmrpctypes.ResultBlock | ||||
| 
 | ||||
| 	_, bz := suite.buildEthereumTx() | ||||
| 	block := tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil) | ||||
| 	blockNum := ethrpc.NewBlockNumber(big.NewInt(block.Height)) | ||||
| 	blockHash := common.BytesToHash(block.Hash()) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name         string | ||||
| 		blockNum     *ethrpc.BlockNumber | ||||
| 		hash         *common.Hash | ||||
| 		registerMock func(*common.Hash) | ||||
| 		expPass      bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"error - without blockHash or blockNum", | ||||
| 			nil, | ||||
| 			nil, | ||||
| 			func(hash *common.Hash) {}, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"error - with blockHash, tendermint client failed to get block", | ||||
| 			nil, | ||||
| 			&blockHash, | ||||
| 			func(hash *common.Hash) { | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockByHashError(client, *hash, bz) | ||||
| 			}, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - with blockHash", | ||||
| 			nil, | ||||
| 			&blockHash, | ||||
| 			func(hash *common.Hash) { | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				resBlock, _ = RegisterBlockByHash(client, *hash, bz) | ||||
| 			}, | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - without blockHash & with blockNumber", | ||||
| 			&blockNum, | ||||
| 			nil, | ||||
| 			func(hash *common.Hash) {}, | ||||
| 			true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(fmt.Sprintf("Case %s", tc.name), func() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 
 | ||||
| 			blockNrOrHash := ethrpc.BlockNumberOrHash{ | ||||
| 				BlockNumber: tc.blockNum, | ||||
| 				BlockHash:   tc.hash, | ||||
| 			} | ||||
| 
 | ||||
| 			tc.registerMock(tc.hash) | ||||
| 			blockNum, err := suite.backend.BlockNumberFromTendermint(blockNrOrHash) | ||||
| 
 | ||||
| 			if tc.expPass { | ||||
| 				suite.Require().NoError(err) | ||||
| 				if tc.hash == nil { | ||||
| 					suite.Require().Equal(*tc.blockNum, blockNum) | ||||
| 				} else { | ||||
| 					expHeight := ethrpc.NewBlockNumber(big.NewInt(resBlock.Block.Height)) | ||||
| 					suite.Require().Equal(expHeight, blockNum) | ||||
| 				} | ||||
| 			} else { | ||||
| 				suite.Require().Error(err) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestBlockNumberFromTendermintByHash() { | ||||
| 	var resBlock *tmrpctypes.ResultBlock | ||||
| 
 | ||||
| 	_, bz := suite.buildEthereumTx() | ||||
| 	block := tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil) | ||||
| 	emptyBlock := tmtypes.MakeBlock(1, []tmtypes.Tx{}, nil, nil) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name         string | ||||
| 		hash         common.Hash | ||||
| 		registerMock func(common.Hash) | ||||
| 		expPass      bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"fail - tendermint client failed to get block", | ||||
| 			common.BytesToHash(block.Hash()), | ||||
| 			func(hash common.Hash) { | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockByHashError(client, hash, bz) | ||||
| 			}, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - block without tx", | ||||
| 			common.BytesToHash(emptyBlock.Hash()), | ||||
| 			func(hash common.Hash) { | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				resBlock, _ = RegisterBlockByHash(client, hash, bz) | ||||
| 			}, | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - block with tx", | ||||
| 			common.BytesToHash(block.Hash()), | ||||
| 			func(hash common.Hash) { | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				resBlock, _ = RegisterBlockByHash(client, hash, bz) | ||||
| 			}, | ||||
| 			true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(fmt.Sprintf("Case %s", tc.name), func() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 
 | ||||
| 			tc.registerMock(tc.hash) | ||||
| 			blockNum, err := suite.backend.BlockNumberFromTendermintByHash(tc.hash) | ||||
| 			if tc.expPass { | ||||
| 				expHeight := big.NewInt(resBlock.Block.Height) | ||||
| 				suite.Require().NoError(err) | ||||
| 				suite.Require().Equal(expHeight, blockNum) | ||||
| 			} else { | ||||
| 				suite.Require().Error(err) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestBlockBloom() { | ||||
| 	testCases := []struct { | ||||
| 		name          string | ||||
| @ -512,7 +844,7 @@ func (suite *BackendTestSuite) TestBlockBloom() { | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - nonblock bloom attribute key", | ||||
| 			"pass - block bloom attribute key", | ||||
| 			&tmrpctypes.ResultBlockResults{ | ||||
| 				EndBlockEvents: []types.Event{ | ||||
| 					{ | ||||
| @ -541,7 +873,7 @@ func (suite *BackendTestSuite) TestBlockBloom() { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestEthBlockFromTendermint() { | ||||
| func (suite *BackendTestSuite) TestGetEthBlockFromTendermint() { | ||||
| 	msgEthereumTx, bz := suite.buildEthereumTx() | ||||
| 	emptyBlock := tmtypes.MakeBlock(1, []tmtypes.Tx{}, nil, nil) | ||||
| 
 | ||||
| @ -735,7 +1067,7 @@ func (suite *BackendTestSuite) TestEthBlockFromTendermint() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 			tc.registerMock(sdk.NewIntFromBigInt(tc.baseFee), tc.validator, tc.height) | ||||
| 
 | ||||
| 			block, err := suite.backend.EthBlockFromTendermint(tc.resBlock, tc.blockRes, tc.fullTx) | ||||
| 			block, err := suite.backend.RPCBlockFromTendermintBlock(tc.resBlock, tc.blockRes, tc.fullTx) | ||||
| 
 | ||||
| 			var expBlock map[string]interface{} | ||||
| 			header := tc.resBlock.Block.Header | ||||
| @ -785,139 +1117,7 @@ func (suite *BackendTestSuite) TestEthBlockFromTendermint() { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestBaseFee() { | ||||
| 	baseFee := sdk.NewInt(1) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name         string | ||||
| 		blockRes     *tmrpctypes.ResultBlockResults | ||||
| 		registerMock func() | ||||
| 		expBaseFee   *big.Int | ||||
| 		expPass      bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"fail - grpc BaseFee error", | ||||
| 			&tmrpctypes.ResultBlockResults{Height: 1}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeError(queryClient) | ||||
| 			}, | ||||
| 			nil, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - grpc BaseFee error - with non feemarket block event", | ||||
| 			&tmrpctypes.ResultBlockResults{ | ||||
| 				Height: 1, | ||||
| 				BeginBlockEvents: []types.Event{ | ||||
| 					{ | ||||
| 						Type: evmtypes.EventTypeBlockBloom, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeError(queryClient) | ||||
| 			}, | ||||
| 			nil, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - grpc BaseFee error - with feemarket block event", | ||||
| 			&tmrpctypes.ResultBlockResults{ | ||||
| 				Height: 1, | ||||
| 				BeginBlockEvents: []types.Event{ | ||||
| 					{ | ||||
| 						Type: feemarkettypes.EventTypeFeeMarket, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeError(queryClient) | ||||
| 			}, | ||||
| 			nil, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - grpc BaseFee error - with feemarket block event with wrong attribute value", | ||||
| 			&tmrpctypes.ResultBlockResults{ | ||||
| 				Height: 1, | ||||
| 				BeginBlockEvents: []types.Event{ | ||||
| 					{ | ||||
| 						Type: feemarkettypes.EventTypeFeeMarket, | ||||
| 						Attributes: []types.EventAttribute{ | ||||
| 							{Value: []byte{0x1}}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeError(queryClient) | ||||
| 			}, | ||||
| 			nil, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - grpc baseFee error - with feemarket block event with baseFee attribute value", | ||||
| 			&tmrpctypes.ResultBlockResults{ | ||||
| 				Height: 1, | ||||
| 				BeginBlockEvents: []types.Event{ | ||||
| 					{ | ||||
| 						Type: feemarkettypes.EventTypeFeeMarket, | ||||
| 						Attributes: []types.EventAttribute{ | ||||
| 							{Value: []byte(baseFee.String())}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeError(queryClient) | ||||
| 			}, | ||||
| 			baseFee.BigInt(), | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - base fee or london fork not enabled", | ||||
| 			&tmrpctypes.ResultBlockResults{Height: 1}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeDisabled(queryClient) | ||||
| 			}, | ||||
| 			nil, | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass", | ||||
| 			&tmrpctypes.ResultBlockResults{Height: 1}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFee(queryClient, baseFee) | ||||
| 			}, | ||||
| 			baseFee.BigInt(), | ||||
| 			true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(fmt.Sprintf("Case %s", tc.name), func() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 			tc.registerMock() | ||||
| 
 | ||||
| 			baseFee, err := suite.backend.BaseFee(tc.blockRes) | ||||
| 
 | ||||
| 			if tc.expPass { | ||||
| 				suite.Require().NoError(err) | ||||
| 				suite.Require().Equal(tc.expBaseFee, baseFee) | ||||
| 			} else { | ||||
| 				suite.Require().Error(err) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestGetEthereumMsgsFromTendermintBlock() { | ||||
| func (suite *BackendTestSuite) TestEthMsgsFromTendermintBlock() { | ||||
| 	msgEthereumTx, bz := suite.buildEthereumTx() | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| @ -975,8 +1175,437 @@ func (suite *BackendTestSuite) TestGetEthereumMsgsFromTendermintBlock() { | ||||
| 		suite.Run(fmt.Sprintf("Case %s", tc.name), func() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 
 | ||||
| 			msgs := suite.backend.GetEthereumMsgsFromTendermintBlock(tc.resBlock, tc.blockRes) | ||||
| 			msgs := suite.backend.EthMsgsFromTendermintBlock(tc.resBlock, tc.blockRes) | ||||
| 			suite.Require().Equal(tc.expMsgs, msgs) | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestHeaderByNumber() { | ||||
| 	var expResultBlock *tmrpctypes.ResultBlock | ||||
| 
 | ||||
| 	_, bz := suite.buildEthereumTx() | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name         string | ||||
| 		blockNumber  ethrpc.BlockNumber | ||||
| 		baseFee      *big.Int | ||||
| 		registerMock func(ethrpc.BlockNumber, sdk.Int) | ||||
| 		expPass      bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"fail - tendermint client failed to get block", | ||||
| 			ethrpc.BlockNumber(1), | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			func(blockNum ethrpc.BlockNumber, baseFee sdk.Int) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockError(client, height) | ||||
| 			}, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - block not found for height", | ||||
| 			ethrpc.BlockNumber(1), | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			func(blockNum ethrpc.BlockNumber, baseFee sdk.Int) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockNotFound(client, height) | ||||
| 			}, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - block not found for height", | ||||
| 			ethrpc.BlockNumber(1), | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			func(blockNum ethrpc.BlockNumber, baseFee sdk.Int) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlock(client, height, nil) | ||||
| 				RegisterBlockResultsError(client, height) | ||||
| 			}, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - without Base Fee, failed to fetch from prunned block", | ||||
| 			ethrpc.BlockNumber(1), | ||||
| 			nil, | ||||
| 			func(blockNum ethrpc.BlockNumber, baseFee sdk.Int) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				expResultBlock, _ = RegisterBlock(client, height, nil) | ||||
| 				RegisterBlockResults(client, height) | ||||
| 
 | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeError(queryClient) | ||||
| 			}, | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - blockNum = 1, without tx", | ||||
| 			ethrpc.BlockNumber(1), | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			func(blockNum ethrpc.BlockNumber, baseFee sdk.Int) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				expResultBlock, _ = RegisterBlock(client, height, nil) | ||||
| 				RegisterBlockResults(client, height) | ||||
| 
 | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFee(queryClient, baseFee) | ||||
| 			}, | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - blockNum = 1, with tx", | ||||
| 			ethrpc.BlockNumber(1), | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			func(blockNum ethrpc.BlockNumber, baseFee sdk.Int) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				expResultBlock, _ = RegisterBlock(client, height, bz) | ||||
| 				RegisterBlockResults(client, height) | ||||
| 
 | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFee(queryClient, baseFee) | ||||
| 			}, | ||||
| 			true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(fmt.Sprintf("Case %s", tc.name), func() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 
 | ||||
| 			tc.registerMock(tc.blockNumber, sdk.NewIntFromBigInt(tc.baseFee)) | ||||
| 			header, err := suite.backend.HeaderByNumber(tc.blockNumber) | ||||
| 
 | ||||
| 			if tc.expPass { | ||||
| 				expHeader := ethrpc.EthHeaderFromTendermint(expResultBlock.Block.Header, ethtypes.Bloom{}, tc.baseFee) | ||||
| 				suite.Require().NoError(err) | ||||
| 				suite.Require().Equal(expHeader, header) | ||||
| 			} else { | ||||
| 				suite.Require().Error(err) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestHeaderByHash() { | ||||
| 	var expResultBlock *tmrpctypes.ResultBlock | ||||
| 
 | ||||
| 	_, bz := suite.buildEthereumTx() | ||||
| 	block := tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil) | ||||
| 	emptyBlock := tmtypes.MakeBlock(1, []tmtypes.Tx{}, nil, nil) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name         string | ||||
| 		hash         common.Hash | ||||
| 		baseFee      *big.Int | ||||
| 		registerMock func(common.Hash, sdk.Int) | ||||
| 		expPass      bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"fail - tendermint client failed to get block", | ||||
| 			common.BytesToHash(block.Hash()), | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			func(hash common.Hash, baseFee sdk.Int) { | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockByHashError(client, hash, bz) | ||||
| 			}, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - block not found for height", | ||||
| 			common.BytesToHash(block.Hash()), | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			func(hash common.Hash, baseFee sdk.Int) { | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockByHashNotFound(client, hash, bz) | ||||
| 			}, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - block not found for height", | ||||
| 			common.BytesToHash(block.Hash()), | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			func(hash common.Hash, baseFee sdk.Int) { | ||||
| 				height := int64(1) | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockByHash(client, hash, bz) | ||||
| 				RegisterBlockResultsError(client, height) | ||||
| 			}, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - without Base Fee, failed to fetch from prunned block", | ||||
| 			common.BytesToHash(block.Hash()), | ||||
| 			nil, | ||||
| 			func(hash common.Hash, baseFee sdk.Int) { | ||||
| 				height := int64(1) | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				expResultBlock, _ = RegisterBlockByHash(client, hash, bz) | ||||
| 				RegisterBlockResults(client, height) | ||||
| 
 | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeError(queryClient) | ||||
| 			}, | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - blockNum = 1, without tx", | ||||
| 			common.BytesToHash(emptyBlock.Hash()), | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			func(hash common.Hash, baseFee sdk.Int) { | ||||
| 				height := int64(1) | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				expResultBlock, _ = RegisterBlockByHash(client, hash, nil) | ||||
| 				RegisterBlockResults(client, height) | ||||
| 
 | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFee(queryClient, baseFee) | ||||
| 			}, | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - with tx", | ||||
| 			common.BytesToHash(block.Hash()), | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			func(hash common.Hash, baseFee sdk.Int) { | ||||
| 				height := int64(1) | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				expResultBlock, _ = RegisterBlockByHash(client, hash, bz) | ||||
| 				RegisterBlockResults(client, height) | ||||
| 
 | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFee(queryClient, baseFee) | ||||
| 			}, | ||||
| 			true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(fmt.Sprintf("Case %s", tc.name), func() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 
 | ||||
| 			tc.registerMock(tc.hash, sdk.NewIntFromBigInt(tc.baseFee)) | ||||
| 			header, err := suite.backend.HeaderByHash(tc.hash) | ||||
| 
 | ||||
| 			if tc.expPass { | ||||
| 				expHeader := ethrpc.EthHeaderFromTendermint(expResultBlock.Block.Header, ethtypes.Bloom{}, tc.baseFee) | ||||
| 				suite.Require().NoError(err) | ||||
| 				suite.Require().Equal(expHeader, header) | ||||
| 			} else { | ||||
| 				suite.Require().Error(err) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestEthBlockByNumber() { | ||||
| 	msgEthereumTx, bz := suite.buildEthereumTx() | ||||
| 	emptyBlock := tmtypes.MakeBlock(1, []tmtypes.Tx{}, nil, nil) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name         string | ||||
| 		blockNumber  ethrpc.BlockNumber | ||||
| 		registerMock func(ethrpc.BlockNumber) | ||||
| 		expEthBlock  *ethtypes.Block | ||||
| 		expPass      bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"fail - tendermint client failed to get block", | ||||
| 			ethrpc.BlockNumber(1), | ||||
| 			func(blockNum ethrpc.BlockNumber) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlockError(client, height) | ||||
| 			}, | ||||
| 			nil, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - block result not found for height", | ||||
| 			ethrpc.BlockNumber(1), | ||||
| 			func(blockNum ethrpc.BlockNumber) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlock(client, height, nil) | ||||
| 				RegisterBlockResultsError(client, blockNum.Int64()) | ||||
| 			}, | ||||
| 			nil, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - block without tx", | ||||
| 			ethrpc.BlockNumber(1), | ||||
| 			func(blockNum ethrpc.BlockNumber) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlock(client, height, nil) | ||||
| 
 | ||||
| 				RegisterBlockResults(client, blockNum.Int64()) | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				baseFee := sdk.NewInt(1) | ||||
| 				RegisterBaseFee(queryClient, baseFee) | ||||
| 			}, | ||||
| 			ethtypes.NewBlock( | ||||
| 				ethrpc.EthHeaderFromTendermint( | ||||
| 					emptyBlock.Header, | ||||
| 					ethtypes.Bloom{}, | ||||
| 					sdk.NewInt(1).BigInt(), | ||||
| 				), | ||||
| 				[]*ethtypes.Transaction{}, | ||||
| 				nil, | ||||
| 				nil, | ||||
| 				nil, | ||||
| 			), | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - block with tx", | ||||
| 			ethrpc.BlockNumber(1), | ||||
| 			func(blockNum ethrpc.BlockNumber) { | ||||
| 				height := blockNum.Int64() | ||||
| 				client := suite.backend.clientCtx.Client.(*mocks.Client) | ||||
| 				RegisterBlock(client, height, bz) | ||||
| 
 | ||||
| 				RegisterBlockResults(client, blockNum.Int64()) | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				baseFee := sdk.NewInt(1) | ||||
| 				RegisterBaseFee(queryClient, baseFee) | ||||
| 			}, | ||||
| 			ethtypes.NewBlock( | ||||
| 				ethrpc.EthHeaderFromTendermint( | ||||
| 					emptyBlock.Header, | ||||
| 					ethtypes.Bloom{}, | ||||
| 					sdk.NewInt(1).BigInt(), | ||||
| 				), | ||||
| 				[]*ethtypes.Transaction{msgEthereumTx.AsTransaction()}, | ||||
| 				nil, | ||||
| 				nil, | ||||
| 				trie.NewStackTrie(nil), | ||||
| 			), | ||||
| 			true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(fmt.Sprintf("Case %s", tc.name), func() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 			tc.registerMock(tc.blockNumber) | ||||
| 
 | ||||
| 			ethBlock, err := suite.backend.EthBlockByNumber(tc.blockNumber) | ||||
| 
 | ||||
| 			if tc.expPass { | ||||
| 				suite.Require().NoError(err) | ||||
| 				suite.Require().Equal(tc.expEthBlock.Header(), ethBlock.Header()) | ||||
| 				suite.Require().Equal(tc.expEthBlock.Uncles(), ethBlock.Uncles()) | ||||
| 				suite.Require().Equal(tc.expEthBlock.ReceiptHash(), ethBlock.ReceiptHash()) | ||||
| 				for i, tx := range tc.expEthBlock.Transactions() { | ||||
| 					suite.Require().Equal(tx.Data(), ethBlock.Transactions()[i].Data()) | ||||
| 				} | ||||
| 
 | ||||
| 			} else { | ||||
| 				suite.Require().Error(err) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestEthBlockFromTendermintBlock() { | ||||
| 	msgEthereumTx, bz := suite.buildEthereumTx() | ||||
| 	emptyBlock := tmtypes.MakeBlock(1, []tmtypes.Tx{}, nil, nil) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name         string | ||||
| 		baseFee      *big.Int | ||||
| 		resBlock     *tmrpctypes.ResultBlock | ||||
| 		blockRes     *tmrpctypes.ResultBlockResults | ||||
| 		registerMock func(sdk.Int, int64) | ||||
| 		expEthBlock  *ethtypes.Block | ||||
| 		expPass      bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"pass - block without tx", | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			&tmrpctypes.ResultBlock{ | ||||
| 				Block: emptyBlock, | ||||
| 			}, | ||||
| 			&tmrpctypes.ResultBlockResults{ | ||||
| 				Height:     1, | ||||
| 				TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}}, | ||||
| 			}, | ||||
| 			func(baseFee sdk.Int, blockNum int64) { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFee(queryClient, baseFee) | ||||
| 			}, | ||||
| 			ethtypes.NewBlock( | ||||
| 				ethrpc.EthHeaderFromTendermint( | ||||
| 					emptyBlock.Header, | ||||
| 					ethtypes.Bloom{}, | ||||
| 					sdk.NewInt(1).BigInt(), | ||||
| 				), | ||||
| 				[]*ethtypes.Transaction{}, | ||||
| 				nil, | ||||
| 				nil, | ||||
| 				nil, | ||||
| 			), | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass - block with tx", | ||||
| 			sdk.NewInt(1).BigInt(), | ||||
| 			&tmrpctypes.ResultBlock{ | ||||
| 				Block: tmtypes.MakeBlock(1, []tmtypes.Tx{bz}, nil, nil), | ||||
| 			}, | ||||
| 			&tmrpctypes.ResultBlockResults{ | ||||
| 				Height:     1, | ||||
| 				TxsResults: []*types.ResponseDeliverTx{{Code: 0, GasUsed: 0}}, | ||||
| 				EndBlockEvents: []types.Event{ | ||||
| 					{ | ||||
| 						Type: evmtypes.EventTypeBlockBloom, | ||||
| 						Attributes: []types.EventAttribute{ | ||||
| 							{Key: []byte(bAttributeKeyEthereumBloom)}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			func(baseFee sdk.Int, blockNum int64) { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFee(queryClient, baseFee) | ||||
| 			}, | ||||
| 			ethtypes.NewBlock( | ||||
| 				ethrpc.EthHeaderFromTendermint( | ||||
| 					emptyBlock.Header, | ||||
| 					ethtypes.Bloom{}, | ||||
| 					sdk.NewInt(1).BigInt(), | ||||
| 				), | ||||
| 				[]*ethtypes.Transaction{msgEthereumTx.AsTransaction()}, | ||||
| 				nil, | ||||
| 				nil, | ||||
| 				trie.NewStackTrie(nil), | ||||
| 			), | ||||
| 			true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(fmt.Sprintf("Case %s", tc.name), func() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 			tc.registerMock(sdk.NewIntFromBigInt(tc.baseFee), tc.blockRes.Height) | ||||
| 
 | ||||
| 			ethBlock, err := suite.backend.EthBlockFromTendermintBlock(tc.resBlock, tc.blockRes) | ||||
| 
 | ||||
| 			if tc.expPass { | ||||
| 				suite.Require().NoError(err) | ||||
| 				suite.Require().Equal(tc.expEthBlock.Header(), ethBlock.Header()) | ||||
| 				suite.Require().Equal(tc.expEthBlock.Uncles(), ethBlock.Uncles()) | ||||
| 				suite.Require().Equal(tc.expEthBlock.ReceiptHash(), ethBlock.ReceiptHash()) | ||||
| 				for i, tx := range tc.expEthBlock.Transactions() { | ||||
| 					suite.Require().Equal(tx.Data(), ethBlock.Transactions()[i].Data()) | ||||
| 				} | ||||
| 
 | ||||
| 			} else { | ||||
| 				suite.Require().Error(err) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| @ -361,3 +361,32 @@ func (b *Backend) DoCall( | ||||
| 
 | ||||
| 	return res, nil | ||||
| } | ||||
| 
 | ||||
| // GasPrice returns the current gas price based on Ethermint's gas price oracle.
 | ||||
| func (b *Backend) GasPrice() (*hexutil.Big, error) { | ||||
| 	var ( | ||||
| 		result *big.Int | ||||
| 		err    error | ||||
| 	) | ||||
| 	if head := b.CurrentHeader(); head.BaseFee != nil { | ||||
| 		result, err = b.SuggestGasTipCap(head.BaseFee) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		result = result.Add(result, head.BaseFee) | ||||
| 	} else { | ||||
| 		result = big.NewInt(b.RPCMinGasPrice()) | ||||
| 	} | ||||
| 
 | ||||
| 	// return at least GlobalMinGasPrice from FeeMarket module
 | ||||
| 	minGasPrice, err := b.GlobalMinGasPrice() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	minGasPriceInt := minGasPrice.TruncateInt().BigInt() | ||||
| 	if result.Cmp(minGasPriceInt) < 0 { | ||||
| 		result = minGasPriceInt | ||||
| 	} | ||||
| 
 | ||||
| 	return (*hexutil.Big)(result), nil | ||||
| } | ||||
|  | ||||
| @ -183,7 +183,7 @@ func (b *Backend) FeeHistory( | ||||
| 	for blockID := blockStart; blockID < blockEnd; blockID++ { | ||||
| 		index := int32(blockID - blockStart) | ||||
| 		// tendermint block
 | ||||
| 		tendermintblock, err := b.GetTendermintBlockByNumber(rpctypes.BlockNumber(blockID)) | ||||
| 		tendermintblock, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(blockID)) | ||||
| 		if tendermintblock == nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| @ -195,7 +195,7 @@ func (b *Backend) FeeHistory( | ||||
| 		} | ||||
| 
 | ||||
| 		// tendermint block result
 | ||||
| 		tendermintBlockResult, err := b.GetTendermintBlockResultByNumber(&tendermintblock.Block.Height) | ||||
| 		tendermintBlockResult, err := b.TendermintBlockResultByNumber(&tendermintblock.Block.Height) | ||||
| 		if tendermintBlockResult == nil { | ||||
| 			b.logger.Debug("block result not found", "height", tendermintblock.Block.Height, "error", err.Error()) | ||||
| 			return nil, err | ||||
|  | ||||
							
								
								
									
										146
									
								
								rpc/backend/chain_info_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								rpc/backend/chain_info_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,146 @@ | ||||
| package backend | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"math/big" | ||||
| 
 | ||||
| 	sdk "github.com/cosmos/cosmos-sdk/types" | ||||
| 	"github.com/tendermint/tendermint/abci/types" | ||||
| 	tmrpctypes "github.com/tendermint/tendermint/rpc/core/types" | ||||
| 
 | ||||
| 	"github.com/evmos/ethermint/rpc/backend/mocks" | ||||
| 	evmtypes "github.com/evmos/ethermint/x/evm/types" | ||||
| 	feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" | ||||
| ) | ||||
| 
 | ||||
| func (suite *BackendTestSuite) TestBaseFee() { | ||||
| 	baseFee := sdk.NewInt(1) | ||||
| 
 | ||||
| 	testCases := []struct { | ||||
| 		name         string | ||||
| 		blockRes     *tmrpctypes.ResultBlockResults | ||||
| 		registerMock func() | ||||
| 		expBaseFee   *big.Int | ||||
| 		expPass      bool | ||||
| 	}{ | ||||
| 		{ | ||||
| 			"fail - grpc BaseFee error", | ||||
| 			&tmrpctypes.ResultBlockResults{Height: 1}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeError(queryClient) | ||||
| 			}, | ||||
| 			nil, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - grpc BaseFee error - with non feemarket block event", | ||||
| 			&tmrpctypes.ResultBlockResults{ | ||||
| 				Height: 1, | ||||
| 				BeginBlockEvents: []types.Event{ | ||||
| 					{ | ||||
| 						Type: evmtypes.EventTypeBlockBloom, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeError(queryClient) | ||||
| 			}, | ||||
| 			nil, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - grpc BaseFee error - with feemarket block event", | ||||
| 			&tmrpctypes.ResultBlockResults{ | ||||
| 				Height: 1, | ||||
| 				BeginBlockEvents: []types.Event{ | ||||
| 					{ | ||||
| 						Type: feemarkettypes.EventTypeFeeMarket, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeError(queryClient) | ||||
| 			}, | ||||
| 			nil, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - grpc BaseFee error - with feemarket block event with wrong attribute value", | ||||
| 			&tmrpctypes.ResultBlockResults{ | ||||
| 				Height: 1, | ||||
| 				BeginBlockEvents: []types.Event{ | ||||
| 					{ | ||||
| 						Type: feemarkettypes.EventTypeFeeMarket, | ||||
| 						Attributes: []types.EventAttribute{ | ||||
| 							{Value: []byte{0x1}}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeError(queryClient) | ||||
| 			}, | ||||
| 			nil, | ||||
| 			false, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - grpc baseFee error - with feemarket block event with baseFee attribute value", | ||||
| 			&tmrpctypes.ResultBlockResults{ | ||||
| 				Height: 1, | ||||
| 				BeginBlockEvents: []types.Event{ | ||||
| 					{ | ||||
| 						Type: feemarkettypes.EventTypeFeeMarket, | ||||
| 						Attributes: []types.EventAttribute{ | ||||
| 							{Value: []byte(baseFee.String())}, | ||||
| 						}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeError(queryClient) | ||||
| 			}, | ||||
| 			baseFee.BigInt(), | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"fail - base fee or london fork not enabled", | ||||
| 			&tmrpctypes.ResultBlockResults{Height: 1}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFeeDisabled(queryClient) | ||||
| 			}, | ||||
| 			nil, | ||||
| 			true, | ||||
| 		}, | ||||
| 		{ | ||||
| 			"pass", | ||||
| 			&tmrpctypes.ResultBlockResults{Height: 1}, | ||||
| 			func() { | ||||
| 				queryClient := suite.backend.queryClient.QueryClient.(*mocks.QueryClient) | ||||
| 				RegisterBaseFee(queryClient, baseFee) | ||||
| 			}, | ||||
| 			baseFee.BigInt(), | ||||
| 			true, | ||||
| 		}, | ||||
| 	} | ||||
| 	for _, tc := range testCases { | ||||
| 		suite.Run(fmt.Sprintf("Case %s", tc.name), func() { | ||||
| 			suite.SetupTest() // reset test and queries
 | ||||
| 			tc.registerMock() | ||||
| 
 | ||||
| 			baseFee, err := suite.backend.BaseFee(tc.blockRes) | ||||
| 
 | ||||
| 			if tc.expPass { | ||||
| 				suite.Require().NoError(err) | ||||
| 				suite.Require().Equal(tc.expBaseFee, baseFee) | ||||
| 			} else { | ||||
| 				suite.Require().Error(err) | ||||
| 			} | ||||
| 		}) | ||||
| 	} | ||||
| } | ||||
| @ -145,3 +145,13 @@ func RegisterBlockByHash( | ||||
| 		Return(resBlock, nil) | ||||
| 	return resBlock, nil | ||||
| } | ||||
| 
 | ||||
| func RegisterBlockByHashError(client *mocks.Client, hash common.Hash, tx []byte) { | ||||
| 	client.On("BlockByHash", rpc.ContextWithHeight(1), []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}). | ||||
| 		Return(nil, sdkerrors.ErrInvalidRequest) | ||||
| } | ||||
| 
 | ||||
| func RegisterBlockByHashNotFound(client *mocks.Client, hash common.Hash, tx []byte) { | ||||
| 	client.On("BlockByHash", rpc.ContextWithHeight(1), []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}). | ||||
| 		Return(nil, nil) | ||||
| } | ||||
|  | ||||
| @ -8,7 +8,7 @@ import ( | ||||
| 
 | ||||
| // GetLogs returns all the logs from all the ethereum transactions in a block.
 | ||||
| func (b *Backend) GetLogs(hash common.Hash) ([][]*ethtypes.Log, error) { | ||||
| 	resBlock, err := b.GetTendermintBlockByHash(hash) | ||||
| 	resBlock, err := b.TendermintBlockByHash(hash) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -22,7 +22,7 @@ func (b *Backend) GetLogs(hash common.Hash) ([][]*ethtypes.Log, error) { | ||||
| // GetLogsByHeight returns all the logs from all the ethereum transactions in a block.
 | ||||
| func (b *Backend) GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error) { | ||||
| 	// NOTE: we query the state in case the tx result logs are not persisted after an upgrade.
 | ||||
| 	blockRes, err := b.GetTendermintBlockResultByNumber(height) | ||||
| 	blockRes, err := b.TendermintBlockResultByNumber(height) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
|  | ||||
| @ -26,7 +26,7 @@ func (b *Backend) TraceTransaction(hash common.Hash, config *evmtypes.TraceConfi | ||||
| 		return nil, errors.New("genesis is not traceable") | ||||
| 	} | ||||
| 
 | ||||
| 	blk, err := b.GetTendermintBlockByNumber(rpctypes.BlockNumber(transaction.Height)) | ||||
| 	blk, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(transaction.Height)) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("block not found", "height", transaction.Height) | ||||
| 		return nil, err | ||||
|  | ||||
| @ -25,7 +25,7 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac | ||||
| 		return b.getTransactionByHashPending(txHash) | ||||
| 	} | ||||
| 
 | ||||
| 	block, err := b.GetTendermintBlockByNumber(rpctypes.BlockNumber(res.Height)) | ||||
| 	block, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(res.Height)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -41,7 +41,7 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac | ||||
| 		return nil, errors.New("invalid ethereum tx") | ||||
| 	} | ||||
| 
 | ||||
| 	blockRes, err := b.GetTendermintBlockResultByNumber(&block.Block.Height) | ||||
| 	blockRes, err := b.TendermintBlockResultByNumber(&block.Block.Height) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("block result not found", "height", block.Block.Height, "error", err.Error()) | ||||
| 		return nil, nil | ||||
| @ -49,7 +49,7 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*rpctypes.RPCTransac | ||||
| 
 | ||||
| 	if res.EthTxIndex == -1 { | ||||
| 		// Fallback to find tx index by iterating all valid eth transactions
 | ||||
| 		msgs := b.GetEthereumMsgsFromTendermintBlock(block, blockRes) | ||||
| 		msgs := b.EthMsgsFromTendermintBlock(block, blockRes) | ||||
| 		for i := range msgs { | ||||
| 			if msgs[i].Hash == hexTx { | ||||
| 				res.EthTxIndex = int32(i) | ||||
| @ -125,7 +125,7 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	resBlock, err := b.GetTendermintBlockByNumber(rpctypes.BlockNumber(res.Height)) | ||||
| 	resBlock, err := b.TendermintBlockByNumber(rpctypes.BlockNumber(res.Height)) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("block not found", "height", res.Height, "error", err.Error()) | ||||
| 		return nil, nil | ||||
| @ -144,7 +144,7 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ | ||||
| 	} | ||||
| 
 | ||||
| 	cumulativeGasUsed := uint64(0) | ||||
| 	blockRes, err := b.GetTendermintBlockResultByNumber(&res.Height) | ||||
| 	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 | ||||
| @ -179,7 +179,7 @@ func (b *Backend) GetTransactionReceipt(hash common.Hash) (map[string]interface{ | ||||
| 
 | ||||
| 	if res.EthTxIndex == -1 { | ||||
| 		// Fallback to find tx index by iterating all valid eth transactions
 | ||||
| 		msgs := b.GetEthereumMsgsFromTendermintBlock(resBlock, blockRes) | ||||
| 		msgs := b.EthMsgsFromTendermintBlock(resBlock, blockRes) | ||||
| 		for i := range msgs { | ||||
| 			if msgs[i].Hash == hexTx { | ||||
| 				res.EthTxIndex = int32(i) | ||||
| @ -260,7 +260,7 @@ func (b *Backend) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexuti | ||||
| func (b *Backend) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { | ||||
| 	b.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) | ||||
| 
 | ||||
| 	block, err := b.GetTendermintBlockByNumber(blockNum) | ||||
| 	block, err := b.TendermintBlockByNumber(blockNum) | ||||
| 	if err != nil { | ||||
| 		b.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) | ||||
| 		return nil, nil | ||||
| @ -341,7 +341,7 @@ func (b *Backend) queryTendermintTxIndexer(query string, txGetter func(*rpctypes | ||||
| 
 | ||||
| // getTransactionByBlockAndIndex is the common code shared by `GetTransactionByBlockNumberAndIndex` and `GetTransactionByBlockHashAndIndex`.
 | ||||
| func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { | ||||
| 	blockRes, err := b.GetTendermintBlockResultByNumber(&block.Block.Height) | ||||
| 	blockRes, err := b.TendermintBlockResultByNumber(&block.Block.Height) | ||||
| 	if err != nil { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| @ -365,7 +365,7 @@ func (b *Backend) GetTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, i | ||||
| 		} | ||||
| 	} else { | ||||
| 		i := int(idx) | ||||
| 		ethMsgs := b.GetEthereumMsgsFromTendermintBlock(block, blockRes) | ||||
| 		ethMsgs := b.EthMsgsFromTendermintBlock(block, blockRes) | ||||
| 		if i >= len(ethMsgs) { | ||||
| 			b.logger.Debug("block txs index out of bound", "index", i) | ||||
| 			return nil, nil | ||||
|  | ||||
| @ -74,7 +74,7 @@ func (a *API) TraceBlockByNumber(height rpctypes.BlockNumber, config *evmtypes.T | ||||
| 		return nil, errors.New("genesis is not traceable") | ||||
| 	} | ||||
| 	// Get Tendermint Block
 | ||||
| 	resBlock, err := a.backend.GetTendermintBlockByNumber(height) | ||||
| 	resBlock, err := a.backend.TendermintBlockByNumber(height) | ||||
| 	if err != nil { | ||||
| 		a.logger.Debug("get block failed", "height", height, "error", err.Error()) | ||||
| 		return nil, err | ||||
| @ -88,7 +88,7 @@ func (a *API) TraceBlockByNumber(height rpctypes.BlockNumber, config *evmtypes.T | ||||
| func (a *API) TraceBlockByHash(hash common.Hash, config *evmtypes.TraceConfig) ([]*evmtypes.TxTraceResult, error) { | ||||
| 	a.logger.Debug("debug_traceBlockByHash", "hash", hash) | ||||
| 	// Get Tendermint Block
 | ||||
| 	resBlock, err := a.backend.GetTendermintBlockByHash(hash) | ||||
| 	resBlock, err := a.backend.TendermintBlockByHash(hash) | ||||
| 	if err != nil { | ||||
| 		a.logger.Debug("get block failed", "hash", hash.Hex(), "error", err.Error()) | ||||
| 		return nil, err | ||||
| @ -298,7 +298,7 @@ func (a *API) GetHeaderRlp(number uint64) (hexutil.Bytes, error) { | ||||
| 
 | ||||
| // GetBlockRlp retrieves the RLP encoded for of a single block.
 | ||||
| func (a *API) GetBlockRlp(number uint64) (hexutil.Bytes, error) { | ||||
| 	block, err := a.backend.BlockByNumber(rpctypes.BlockNumber(number)) | ||||
| 	block, err := a.backend.EthBlockByNumber(rpctypes.BlockNumber(number)) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -308,7 +308,7 @@ func (a *API) GetBlockRlp(number uint64) (hexutil.Bytes, error) { | ||||
| 
 | ||||
| // PrintBlock retrieves a block and returns its pretty printed form.
 | ||||
| func (a *API) PrintBlock(number uint64) (string, error) { | ||||
| 	block, err := a.backend.BlockByNumber(rpctypes.BlockNumber(number)) | ||||
| 	block, err := a.backend.EthBlockByNumber(rpctypes.BlockNumber(number)) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| @ -2,7 +2,6 @@ package eth | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"math/big" | ||||
| 
 | ||||
| 	"github.com/ethereum/go-ethereum/signer/core/apitypes" | ||||
| 
 | ||||
| @ -34,6 +33,8 @@ type EthereumAPI interface { | ||||
| 	BlockNumber() (hexutil.Uint64, error) | ||||
| 	GetBlockByNumber(ethBlockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) | ||||
| 	GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) | ||||
| 	GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint | ||||
| 	GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint | ||||
| 
 | ||||
| 	// Reading Transactions
 | ||||
| 	//
 | ||||
| @ -42,8 +43,6 @@ type EthereumAPI interface { | ||||
| 	GetTransactionByHash(hash common.Hash) (*rpctypes.RPCTransaction, error) | ||||
| 	GetTransactionCount(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (*hexutil.Uint64, error) | ||||
| 	GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) | ||||
| 	GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint | ||||
| 	GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint | ||||
| 	GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) | ||||
| 	GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) | ||||
| 	// eth_getBlockReceipts
 | ||||
| @ -123,10 +122,7 @@ type PublicAPI struct { | ||||
| } | ||||
| 
 | ||||
| // NewPublicAPI creates an instance of the public ETH Web3 API.
 | ||||
| func NewPublicAPI( | ||||
| 	logger log.Logger, | ||||
| 	backend backend.EVMBackend, | ||||
| ) *PublicAPI { | ||||
| func NewPublicAPI(logger log.Logger, backend backend.EVMBackend) *PublicAPI { | ||||
| 	api := &PublicAPI{ | ||||
| 		ctx:     context.Background(), | ||||
| 		logger:  logger.With("client", "json-rpc"), | ||||
| @ -171,7 +167,7 @@ func (e *PublicAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.RPCTransac | ||||
| // GetTransactionCount returns the number of transactions at the given address up to the given block number.
 | ||||
| func (e *PublicAPI) GetTransactionCount(address common.Address, blockNrOrHash rpctypes.BlockNumberOrHash) (*hexutil.Uint64, error) { | ||||
| 	e.logger.Debug("eth_getTransactionCount", "address", address.Hex(), "block number or hash", blockNrOrHash) | ||||
| 	blockNum, err := e.backend.GetBlockNumber(blockNrOrHash) | ||||
| 	blockNum, err := e.backend.BlockNumberFromTendermint(blockNrOrHash) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -182,21 +178,18 @@ func (e *PublicAPI) GetTransactionCount(address common.Address, blockNrOrHash rp | ||||
| func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) { | ||||
| 	hexTx := hash.Hex() | ||||
| 	e.logger.Debug("eth_getTransactionReceipt", "hash", hexTx) | ||||
| 
 | ||||
| 	return e.backend.GetTransactionReceipt(hash) | ||||
| } | ||||
| 
 | ||||
| // GetBlockTransactionCountByHash returns the number of transactions in the block identified by hash.
 | ||||
| func (e *PublicAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint { | ||||
| 	e.logger.Debug("eth_getBlockTransactionCountByHash", "hash", hash.Hex()) | ||||
| 
 | ||||
| 	return e.backend.GetBlockTransactionCountByHash(hash) | ||||
| } | ||||
| 
 | ||||
| // GetBlockTransactionCountByNumber returns the number of transactions in the block identified by number.
 | ||||
| func (e *PublicAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { | ||||
| 	e.logger.Debug("eth_getBlockTransactionCountByNumber", "height", blockNum.Int64()) | ||||
| 
 | ||||
| 	return e.backend.GetBlockTransactionCountByNumber(blockNum) | ||||
| } | ||||
| 
 | ||||
| @ -209,19 +202,7 @@ func (e *PublicAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexu | ||||
| // GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index.
 | ||||
| func (e *PublicAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { | ||||
| 	e.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) | ||||
| 
 | ||||
| 	block, err := e.backend.GetTendermintBlockByNumber(blockNum) | ||||
| 	if err != nil { | ||||
| 		e.logger.Debug("block not found", "height", blockNum.Int64(), "error", err.Error()) | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	if block.Block == nil { | ||||
| 		e.logger.Debug("block not found", "height", blockNum.Int64()) | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	return e.backend.GetTransactionByBlockAndIndex(block, idx) | ||||
| 	return e.backend.GetTransactionByBlockNumberAndIndex(blockNum, idx) | ||||
| } | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| @ -288,7 +269,7 @@ func (e *PublicAPI) Call(args evmtypes.TransactionArgs, | ||||
| ) (hexutil.Bytes, error) { | ||||
| 	e.logger.Debug("eth_call", "args", args.String(), "block number or hash", blockNrOrHash) | ||||
| 
 | ||||
| 	blockNum, err := e.backend.GetBlockNumber(blockNrOrHash) | ||||
| 	blockNum, err := e.backend.BlockNumberFromTendermint(blockNrOrHash) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @ -303,7 +284,7 @@ func (e *PublicAPI) Call(args evmtypes.TransactionArgs, | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| ///                           Event Logs													          ///
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| // FILTER API
 | ||||
| // FILTER API at ./filters/api.go
 | ||||
| 
 | ||||
| ///////////////////////////////////////////////////////////////////////////////
 | ||||
| ///                           Chain Information										          ///
 | ||||
| @ -318,31 +299,7 @@ func (e *PublicAPI) ProtocolVersion() hexutil.Uint { | ||||
| // GasPrice returns the current gas price based on Ethermint's gas price oracle.
 | ||||
| func (e *PublicAPI) GasPrice() (*hexutil.Big, error) { | ||||
| 	e.logger.Debug("eth_gasPrice") | ||||
| 	var ( | ||||
| 		result *big.Int | ||||
| 		err    error | ||||
| 	) | ||||
| 	if head := e.backend.CurrentHeader(); head.BaseFee != nil { | ||||
| 		result, err = e.backend.SuggestGasTipCap(head.BaseFee) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 		result = result.Add(result, head.BaseFee) | ||||
| 	} else { | ||||
| 		result = big.NewInt(e.backend.RPCMinGasPrice()) | ||||
| 	} | ||||
| 
 | ||||
| 	// return at least GlobalMinGasPrice from FeeMarket module
 | ||||
| 	minGasPrice, err := e.backend.GlobalMinGasPrice() | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	minGasPriceInt := minGasPrice.TruncateInt().BigInt() | ||||
| 	if result.Cmp(minGasPriceInt) < 0 { | ||||
| 		result = minGasPriceInt | ||||
| 	} | ||||
| 
 | ||||
| 	return (*hexutil.Big)(result), nil | ||||
| 	return e.backend.GasPrice() | ||||
| } | ||||
| 
 | ||||
| // EstimateGas returns an estimate of gas usage for the given smart contract call.
 | ||||
| @ -466,7 +423,7 @@ func (e *PublicAPI) GetTransactionLogs(txHash common.Hash) ([]*ethtypes.Log, err | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 
 | ||||
| 	resBlockResult, err := e.backend.GetTendermintBlockResultByNumber(&res.Height) | ||||
| 	resBlockResult, err := e.backend.TendermintBlockResultByNumber(&res.Height) | ||||
| 	if err != nil { | ||||
| 		e.logger.Debug("block result not found", "number", res.Height, "error", err.Error()) | ||||
| 		return nil, nil | ||||
|  | ||||
| @ -39,8 +39,8 @@ type Backend interface { | ||||
| 	GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error) | ||||
| 	HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error) | ||||
| 	HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error) | ||||
| 	GetTendermintBlockByHash(hash common.Hash) (*coretypes.ResultBlock, error) | ||||
| 	GetTendermintBlockResultByNumber(height *int64) (*coretypes.ResultBlockResults, error) | ||||
| 	TendermintBlockByHash(hash common.Hash) (*coretypes.ResultBlock, error) | ||||
| 	TendermintBlockResultByNumber(height *int64) (*coretypes.ResultBlockResults, error) | ||||
| 	GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error) | ||||
| 	GetLogsByHeight(*int64) ([][]*ethtypes.Log, error) | ||||
| 	BlockBloom(blockRes *coretypes.ResultBlockResults) (ethtypes.Bloom, error) | ||||
|  | ||||
| @ -98,12 +98,12 @@ func (f *Filter) Logs(ctx context.Context, logLimit int, blockLimit int64) ([]*e | ||||
| 
 | ||||
| 	// If we're doing singleton block filtering, execute and return
 | ||||
| 	if f.criteria.BlockHash != nil && *f.criteria.BlockHash != (common.Hash{}) { | ||||
| 		resBlock, err := f.backend.GetTendermintBlockByHash(*f.criteria.BlockHash) | ||||
| 		resBlock, err := f.backend.TendermintBlockByHash(*f.criteria.BlockHash) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("failed to fetch header by hash %s: %w", f.criteria.BlockHash, err) | ||||
| 		} | ||||
| 
 | ||||
| 		blockRes, err := f.backend.GetTendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 		blockRes, err := f.backend.TendermintBlockResultByNumber(&resBlock.Block.Height) | ||||
| 		if err != nil { | ||||
| 			f.logger.Debug("failed to fetch block result from Tendermint", "height", resBlock.Block.Height, "error", err.Error()) | ||||
| 			return nil, nil | ||||
| @ -155,7 +155,7 @@ func (f *Filter) Logs(ctx context.Context, logLimit int, blockLimit int64) ([]*e | ||||
| 	to := f.criteria.ToBlock.Int64() | ||||
| 
 | ||||
| 	for height := from; height <= to; height++ { | ||||
| 		blockRes, err := f.backend.GetTendermintBlockResultByNumber(&height) | ||||
| 		blockRes, err := f.backend.TendermintBlockResultByNumber(&height) | ||||
| 		if err != nil { | ||||
| 			f.logger.Debug("failed to fetch block result from Tendermint", "height", height, "error", err.Error()) | ||||
| 			return nil, nil | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user