From 2c722d03cee8b00277b222a86c8a7ac3b64b0d1e Mon Sep 17 00:00:00 2001 From: Federico Kunze <31522760+fedekunze@users.noreply.github.com> Date: Mon, 17 May 2021 06:13:08 -0400 Subject: [PATCH] rpc, evm: gRPC tests (#28) * rpc, evm: grpc tests * address validation * update rpc * test cleanup * additional tests --- docs/core/proto-docs.md | 12 +- ethereum/rpc/backend.go | 31 +- ethereum/rpc/eth_api.go | 78 ++- go.mod | 4 +- go.sum | 8 +- proto/ethermint/evm/v1alpha1/query.proto | 11 +- x/evm/keeper/abci.go | 2 +- x/evm/keeper/grpc_query.go | 84 +-- x/evm/keeper/grpc_query_test.go | 786 +++++++++++++++++++++++ x/evm/keeper/keeper.go | 13 +- x/evm/keeper/keeper_test.go | 15 +- x/evm/types/genesis.go | 5 +- x/evm/types/logs.go | 10 +- x/evm/types/msg.go | 2 +- x/evm/types/query.pb.go | 210 +++--- x/evm/types/query.pb.gw.go | 56 +- x/evm/types/state_object.go | 12 +- x/evm/types/utils.go | 19 - 18 files changed, 982 insertions(+), 376 deletions(-) create mode 100644 x/evm/keeper/grpc_query_test.go diff --git a/docs/core/proto-docs.md b/docs/core/proto-docs.md index 0a8127a1..49928ddd 100644 --- a/docs/core/proto-docs.md +++ b/docs/core/proto-docs.md @@ -477,11 +477,6 @@ QueryBlockBloomRequest is the request type for the Query/BlockBloom RPC method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | | - - @@ -779,11 +774,6 @@ QueryTxReceiptsByBlockHashResponse is the response type for the Query/TxReceipts QueryTxReceiptsByBlockHeightRequest is the request type for the Query/TxReceiptsByBlockHeight RPC method. -| Field | Type | Label | Description | -| ----- | ---- | ----- | ----------- | -| `height` | [int64](#int64) | | height is the block height to query tx receipts for | - - @@ -823,7 +813,7 @@ Query defines the gRPC querier service. | `Code` | [QueryCodeRequest](#ethermint.evm.v1alpha1.QueryCodeRequest) | [QueryCodeResponse](#ethermint.evm.v1alpha1.QueryCodeResponse) | Code queries the balance of all coins for a single account. | GET|/ethermint/evm/v1alpha1/codes/{address}| | `TxLogs` | [QueryTxLogsRequest](#ethermint.evm.v1alpha1.QueryTxLogsRequest) | [QueryTxLogsResponse](#ethermint.evm.v1alpha1.QueryTxLogsResponse) | TxLogs queries ethereum logs from a transaction. | GET|/ethermint/evm/v1alpha1/tx_logs/{hash}| | `TxReceipt` | [QueryTxReceiptRequest](#ethermint.evm.v1alpha1.QueryTxReceiptRequest) | [QueryTxReceiptResponse](#ethermint.evm.v1alpha1.QueryTxReceiptResponse) | TxReceipt queries a receipt by a transaction hash. | GET|/ethermint/evm/v1alpha1/tx_receipt/{hash}| -| `TxReceiptsByBlockHeight` | [QueryTxReceiptsByBlockHeightRequest](#ethermint.evm.v1alpha1.QueryTxReceiptsByBlockHeightRequest) | [QueryTxReceiptsByBlockHeightResponse](#ethermint.evm.v1alpha1.QueryTxReceiptsByBlockHeightResponse) | TxReceiptsByBlockHeight queries tx receipts by a block height. | GET|/ethermint/evm/v1alpha1/tx_receipts_block/{height}| +| `TxReceiptsByBlockHeight` | [QueryTxReceiptsByBlockHeightRequest](#ethermint.evm.v1alpha1.QueryTxReceiptsByBlockHeightRequest) | [QueryTxReceiptsByBlockHeightResponse](#ethermint.evm.v1alpha1.QueryTxReceiptsByBlockHeightResponse) | TxReceiptsByBlockHeight queries tx receipts by a block height. | GET|/ethermint/evm/v1alpha1/tx_receipts_block| | `TxReceiptsByBlockHash` | [QueryTxReceiptsByBlockHashRequest](#ethermint.evm.v1alpha1.QueryTxReceiptsByBlockHashRequest) | [QueryTxReceiptsByBlockHashResponse](#ethermint.evm.v1alpha1.QueryTxReceiptsByBlockHashResponse) | TxReceiptsByBlockHash queries tx receipts by a block hash. | GET|/ethermint/evm/v1alpha1/tx_receipts_block_hash/{hash}| | `BlockLogs` | [QueryBlockLogsRequest](#ethermint.evm.v1alpha1.QueryBlockLogsRequest) | [QueryBlockLogsResponse](#ethermint.evm.v1alpha1.QueryBlockLogsResponse) | BlockLogs queries all the ethereum logs for a given block hash. | GET|/ethermint/evm/v1alpha1/block_logs/{hash}| | `BlockBloom` | [QueryBlockBloomRequest](#ethermint.evm.v1alpha1.QueryBlockBloomRequest) | [QueryBlockBloomResponse](#ethermint.evm.v1alpha1.QueryBlockBloomResponse) | BlockBloom queries the block bloom filter bytes at a given height. | GET|/ethermint/evm/v1alpha1/block_bloom| diff --git a/ethereum/rpc/backend.go b/ethereum/rpc/backend.go index 85d73c58..9178b232 100644 --- a/ethereum/rpc/backend.go +++ b/ethereum/rpc/backend.go @@ -101,14 +101,14 @@ func (e *EVMBackend) GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) ( if err != nil { // e.logger.Debugf("GetBlockByNumber safely bumping down from %d to latest", height) if resBlock, err = e.clientCtx.Client.Block(e.ctx, nil); err != nil { - e.logger.Warningln("GetBlockByNumber failed to get latest block") + e.logger.Debugln("GetBlockByNumber failed to get latest block") return nil, nil } } res, err := e.EthBlockFromTendermint(e.clientCtx, e.queryClient, resBlock.Block, fullTx) if err != nil { - e.logger.WithError(err).Warningf("EthBlockFromTendermint failed with block %s", resBlock.Block.String()) + e.logger.WithError(err).Debugf("EthBlockFromTendermint failed with block %s", resBlock.Block.String()) } return res, err @@ -133,13 +133,11 @@ func (e *EVMBackend) EthBlockFromTendermint( fullTx bool, ) (map[string]interface{}, error) { - req := &evmtypes.QueryTxReceiptsByBlockHeightRequest{ - Height: block.Height, - } + req := &evmtypes.QueryTxReceiptsByBlockHeightRequest{} - txReceiptsResp, err := queryClient.TxReceiptsByBlockHeight(types.ContextWithHeight(0), req) + txReceiptsResp, err := queryClient.TxReceiptsByBlockHeight(types.ContextWithHeight(block.Height), req) if err != nil { - e.logger.Warningf("TxReceiptsByBlockHeight fail: %s", err.Error()) + e.logger.Debugf("TxReceiptsByBlockHeight fail: %s", err.Error()) return nil, err } @@ -161,7 +159,7 @@ func (e *EVMBackend) EthBlockFromTendermint( ) if err != nil { - e.logger.Warningf("NewTransactionFromData for receipt %s failed: %s", hash, err.Error()) + e.logger.WithError(err).Warningf("NewTransactionFromData for receipt %s failed", hash) continue } @@ -173,17 +171,16 @@ func (e *EVMBackend) EthBlockFromTendermint( } } - blockBloomResp, err := queryClient.BlockBloom(types.ContextWithHeight(0), &evmtypes.QueryBlockBloomRequest{ - Height: block.Height, - }) + blockBloomResp, err := queryClient.BlockBloom(types.ContextWithHeight(block.Height), &evmtypes.QueryBlockBloomRequest{}) if err != nil { - err = errors.Wrapf(err, "failed to query BlockBloom for height %d", block.Height) - return nil, err + e.logger.WithError(err).Debugln("failed to query BlockBloom at height", block.Height) + blockBloomResp.Bloom = ethtypes.Bloom{}.Bytes() } bloom := ethtypes.BytesToBloom(blockBloomResp.Bloom) formattedBlock := types.FormatBlock(block.Header, block.Size(), ethermint.DefaultRPCGasLimit, gasUsed, ethRPCTxs, bloom) + e.logger.Infoln(formattedBlock) return formattedBlock, nil } @@ -216,9 +213,7 @@ func (e *EVMBackend) HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Heade return nil, err } - req := &evmtypes.QueryBlockBloomRequest{ - Height: resBlock.Block.Height, - } + req := &evmtypes.QueryBlockBloomRequest{} res, err := e.queryClient.BlockBloom(types.ContextWithHeight(resBlock.Block.Height), req) if err != nil { @@ -239,9 +234,7 @@ func (e *EVMBackend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, erro return nil, err } - req := &evmtypes.QueryBlockBloomRequest{ - Height: resBlock.Block.Height, - } + req := &evmtypes.QueryBlockBloomRequest{} res, err := e.queryClient.BlockBloom(types.ContextWithHeight(resBlock.Block.Height), req) if err != nil { diff --git a/ethereum/rpc/eth_api.go b/ethereum/rpc/eth_api.go index 20a0460e..134ced69 100644 --- a/ethereum/rpc/eth_api.go +++ b/ethereum/rpc/eth_api.go @@ -32,7 +32,6 @@ import ( "github.com/ethereum/go-ethereum/rlp" "github.com/cosmos/ethermint/crypto/hd" - "github.com/cosmos/ethermint/ethereum/rpc/types" rpctypes "github.com/cosmos/ethermint/ethereum/rpc/types" ethermint "github.com/cosmos/ethermint/types" evmtypes "github.com/cosmos/ethermint/x/evm/types" @@ -54,7 +53,7 @@ type PublicEthAPI struct { func NewPublicEthAPI( clientCtx client.Context, backend Backend, - nonceLock *types.AddrLocker, + nonceLock *rpctypes.AddrLocker, ) *PublicEthAPI { epoch, err := ethermint.ParseChainID(clientCtx.ChainID) if err != nil { @@ -82,7 +81,7 @@ func NewPublicEthAPI( api := &PublicEthAPI{ ctx: context.Background(), clientCtx: clientCtx, - queryClient: types.NewQueryClient(clientCtx), + queryClient: rpctypes.NewQueryClient(clientCtx), chainIDEpoch: epoch, logger: log.WithField("module", "json-rpc"), backend: backend, @@ -194,14 +193,14 @@ func (e *PublicEthAPI) BlockNumber() (hexutil.Uint64, error) { } // GetBalance returns the provided account's balance up to the provided block number. -func (e *PublicEthAPI) GetBalance(address common.Address, blockNum types.BlockNumber) (*hexutil.Big, error) { // nolint: interfacer +func (e *PublicEthAPI) GetBalance(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Big, error) { // nolint: interfacer e.logger.Debugln("eth_getBalance", "address", address.String(), "block number", blockNum) req := &evmtypes.QueryBalanceRequest{ Address: address.String(), } - res, err := e.queryClient.Balance(types.ContextWithHeight(blockNum.Int64()), req) + res, err := e.queryClient.Balance(rpctypes.ContextWithHeight(blockNum.Int64()), req) if err != nil { return nil, err } @@ -215,7 +214,7 @@ func (e *PublicEthAPI) GetBalance(address common.Address, blockNum types.BlockNu } // GetStorageAt returns the contract storage at the given address, block number, and key. -func (e *PublicEthAPI) GetStorageAt(address common.Address, key string, blockNum types.BlockNumber) (hexutil.Bytes, error) { // nolint: interfacer +func (e *PublicEthAPI) GetStorageAt(address common.Address, key string, blockNum rpctypes.BlockNumber) (hexutil.Bytes, error) { // nolint: interfacer e.logger.Debugln("eth_getStorageAt", "address", address.Hex(), "key", key, "block number", blockNum) req := &evmtypes.QueryStorageRequest{ @@ -223,7 +222,7 @@ func (e *PublicEthAPI) GetStorageAt(address common.Address, key string, blockNum Key: key, } - res, err := e.queryClient.Storage(types.ContextWithHeight(blockNum.Int64()), req) + res, err := e.queryClient.Storage(rpctypes.ContextWithHeight(blockNum.Int64()), req) if err != nil { return nil, err } @@ -233,7 +232,7 @@ func (e *PublicEthAPI) GetStorageAt(address common.Address, key string, blockNum } // GetTransactionCount returns the number of transactions at the given address up to the given block number. -func (e *PublicEthAPI) GetTransactionCount(address common.Address, blockNum types.BlockNumber) (*hexutil.Uint64, error) { +func (e *PublicEthAPI) GetTransactionCount(address common.Address, blockNum rpctypes.BlockNumber) (*hexutil.Uint64, error) { e.logger.Debugln("eth_getTransactionCount", "address", address.Hex(), "block number", blockNum) // Get nonce (sequence) from account @@ -270,7 +269,7 @@ func (e *PublicEthAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil } // GetBlockTransactionCountByNumber returns the number of transactions in the block identified by number. -func (e *PublicEthAPI) GetBlockTransactionCountByNumber(blockNum types.BlockNumber) *hexutil.Uint { +func (e *PublicEthAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumber) *hexutil.Uint { e.logger.Debugln("eth_getBlockTransactionCountByNumber", "block number", blockNum) resBlock, err := e.clientCtx.Client.Block(e.ctx, blockNum.TmHeight()) if err != nil { @@ -287,19 +286,19 @@ func (e *PublicEthAPI) GetUncleCountByBlockHash(hash common.Hash) hexutil.Uint { } // GetUncleCountByBlockNumber returns the number of uncles in the block identified by number. Always zero. -func (e *PublicEthAPI) GetUncleCountByBlockNumber(blockNum types.BlockNumber) hexutil.Uint { +func (e *PublicEthAPI) GetUncleCountByBlockNumber(blockNum rpctypes.BlockNumber) hexutil.Uint { return 0 } // GetCode returns the contract code at the given address and block number. -func (e *PublicEthAPI) GetCode(address common.Address, blockNumber types.BlockNumber) (hexutil.Bytes, error) { // nolint: interfacer +func (e *PublicEthAPI) GetCode(address common.Address, blockNumber rpctypes.BlockNumber) (hexutil.Bytes, error) { // nolint: interfacer e.logger.Debugln("eth_getCode", "address", address.Hex(), "block number", blockNumber) req := &evmtypes.QueryCodeRequest{ Address: address.String(), } - res, err := e.queryClient.Code(types.ContextWithHeight(blockNumber.Int64()), req) + res, err := e.queryClient.Code(rpctypes.ContextWithHeight(blockNumber.Int64()), req) if err != nil { return nil, err } @@ -337,7 +336,7 @@ func (e *PublicEthAPI) Sign(address common.Address, data hexutil.Bytes) (hexutil } // SendTransaction sends an Ethereum transaction. -func (e *PublicEthAPI) SendTransaction(args types.SendTxArgs) (common.Hash, error) { +func (e *PublicEthAPI) SendTransaction(args rpctypes.SendTxArgs) (common.Hash, error) { e.logger.Debugln("eth_sendTransaction", "args", args) // Look up the wallet containing the requested signer @@ -460,7 +459,7 @@ func (e *PublicEthAPI) SendRawTransaction(data hexutil.Bytes) (common.Hash, erro } // Call performs a raw contract call. -func (e *PublicEthAPI) Call(args types.CallArgs, blockNr types.BlockNumber, _ *types.StateOverride) (hexutil.Bytes, error) { +func (e *PublicEthAPI) Call(args rpctypes.CallArgs, blockNr rpctypes.BlockNumber, _ *rpctypes.StateOverride) (hexutil.Bytes, error) { //e.logger.Debugln("eth_call", "args", args, "block number", blockNr) simRes, err := e.doCall(args, blockNr, big.NewInt(ethermint.DefaultRPCGasLimit)) if err != nil { @@ -468,20 +467,20 @@ func (e *PublicEthAPI) Call(args types.CallArgs, blockNr types.BlockNumber, _ *t } if len(simRes.Result.Log) > 0 { - var logs []types.SDKTxLogs + var logs []rpctypes.SDKTxLogs if err := json.Unmarshal([]byte(simRes.Result.Log), &logs); err != nil { e.logger.WithError(err).Errorln("failed to unmarshal simRes.Result.Log") } - if len(logs) > 0 && logs[0].Log == types.LogRevertedFlag { + if len(logs) > 0 && logs[0].Log == rpctypes.LogRevertedFlag { data, err := evmtypes.DecodeTxResponse(simRes.Result.Data) if err != nil { e.logger.WithError(err).Warningln("call result decoding failed") return []byte{}, err } - return []byte{}, types.ErrRevertedWith(data.Ret) + return []byte{}, rpctypes.ErrRevertedWith(data.Ret) } } @@ -497,7 +496,7 @@ func (e *PublicEthAPI) Call(args types.CallArgs, blockNr types.BlockNumber, _ *t // DoCall performs a simulated call operation through the evmtypes. It returns the // estimated gas used on the operation or an error if fails. func (e *PublicEthAPI) doCall( - args types.CallArgs, blockNr types.BlockNumber, globalGasCap *big.Int, + args rpctypes.CallArgs, blockNr rpctypes.BlockNumber, globalGasCap *big.Int, ) (*sdk.SimulationResponse, error) { // Set default gas & gas price if none were set // Change this to uint64(math.MaxUint64 / 2) if gas cap can be configured @@ -605,7 +604,7 @@ func (e *PublicEthAPI) doCall( // EstimateGas returns an estimate of gas usage for the given smart contract call. // It adds 1,000 gas to the returned value instead of using the gas adjustment // param from the SDK. -func (e *PublicEthAPI) EstimateGas(args types.CallArgs) (hexutil.Uint64, error) { +func (e *PublicEthAPI) EstimateGas(args rpctypes.CallArgs) (hexutil.Uint64, error) { e.logger.Debugln("eth_estimateGas") // From ContextWithHeight: if the provided height is 0, @@ -617,20 +616,20 @@ func (e *PublicEthAPI) EstimateGas(args types.CallArgs) (hexutil.Uint64, error) } if len(simRes.Result.Log) > 0 { - var logs []types.SDKTxLogs + var logs []rpctypes.SDKTxLogs if err := json.Unmarshal([]byte(simRes.Result.Log), &logs); err != nil { e.logger.WithError(err).Errorln("failed to unmarshal simRes.Result.Log") return 0, err } - if len(logs) > 0 && logs[0].Log == types.LogRevertedFlag { + if len(logs) > 0 && logs[0].Log == rpctypes.LogRevertedFlag { data, err := evmtypes.DecodeTxResponse(simRes.Result.Data) if err != nil { e.logger.WithError(err).Warningln("call result decoding failed") return 0, err } - return 0, types.ErrRevertedWith(data.Ret) + return 0, rpctypes.ErrRevertedWith(data.Ret) } } @@ -648,13 +647,13 @@ func (e *PublicEthAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map[string } // GetBlockByNumber returns the block identified by number. -func (e *PublicEthAPI) GetBlockByNumber(ethBlockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error) { - // e.logger.Debugln("eth_getBlockByNumber", "number", ethBlockNum, "full", fullTx) +func (e *PublicEthAPI) GetBlockByNumber(ethBlockNum rpctypes.BlockNumber, fullTx bool) (map[string]interface{}, error) { + e.logger.Debugln("eth_getBlockByNumber", "number", ethBlockNum, "full", fullTx) return e.backend.GetBlockByNumber(ethBlockNum, fullTx) } // GetTransactionByHash returns the transaction identified by hash. -func (e *PublicEthAPI) GetTransactionByHash(hash common.Hash) (*types.RPCTransaction, error) { +func (e *PublicEthAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.RPCTransaction, error) { e.logger.Debugln("eth_getTransactionByHash", "hash", hash.Hex()) resp, err := e.queryClient.TxReceipt(e.ctx, &evmtypes.QueryTxReceiptRequest{ @@ -665,7 +664,7 @@ func (e *PublicEthAPI) GetTransactionByHash(hash common.Hash) (*types.RPCTransac return nil, nil } - return types.NewTransactionFromData( + return rpctypes.NewTransactionFromData( resp.Receipt.Data, common.HexToAddress(resp.Receipt.From), common.HexToHash(resp.Receipt.Hash), @@ -676,7 +675,7 @@ func (e *PublicEthAPI) GetTransactionByHash(hash common.Hash) (*types.RPCTransac } // GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index. -func (e *PublicEthAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*types.RPCTransaction, error) { +func (e *PublicEthAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { e.logger.Debugln("eth_getTransactionByHashAndIndex", "hash", hash.Hex(), "index", idx) resp, err := e.queryClient.TxReceiptsByBlockHash(e.ctx, &evmtypes.QueryTxReceiptsByBlockHashRequest{ @@ -691,12 +690,11 @@ func (e *PublicEthAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx h } // GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index. -func (e *PublicEthAPI) GetTransactionByBlockNumberAndIndex(blockNum types.BlockNumber, idx hexutil.Uint) (*types.RPCTransaction, error) { +func (e *PublicEthAPI) GetTransactionByBlockNumberAndIndex(blockNum rpctypes.BlockNumber, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { e.logger.Debugln("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) - resp, err := e.queryClient.TxReceiptsByBlockHeight(e.ctx, &evmtypes.QueryTxReceiptsByBlockHeightRequest{ - Height: blockNum.Int64(), - }) + req := &evmtypes.QueryTxReceiptsByBlockHeightRequest{} + resp, err := e.queryClient.TxReceiptsByBlockHeight(rpctypes.ContextWithHeight(blockNum.Int64()), req) if err != nil { err = errors.Wrap(err, "failed to query tx receipts by block height") return nil, err @@ -705,7 +703,7 @@ func (e *PublicEthAPI) GetTransactionByBlockNumberAndIndex(blockNum types.BlockN return e.getReceiptByIndex(resp.Receipts, common.Hash{}, idx) } -func (e *PublicEthAPI) getReceiptByIndex(receipts []*evmtypes.TxReceipt, blockHash common.Hash, idx hexutil.Uint) (*types.RPCTransaction, error) { +func (e *PublicEthAPI) getReceiptByIndex(receipts []*evmtypes.TxReceipt, blockHash common.Hash, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) { // return if index out of bounds if uint64(idx) >= uint64(len(receipts)) { return nil, nil @@ -723,7 +721,7 @@ func (e *PublicEthAPI) getReceiptByIndex(receipts []*evmtypes.TxReceipt, blockHa } } - return types.NewTransactionFromData( + return rpctypes.NewTransactionFromData( receipt.Data, common.HexToAddress(receipt.From), common.HexToHash(receipt.Hash), @@ -737,7 +735,7 @@ func (e *PublicEthAPI) getReceiptByIndex(receipts []*evmtypes.TxReceipt, blockHa func (e *PublicEthAPI) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) { e.logger.Debugln("eth_getTransactionReceipt", "hash", hash.Hex()) - ctx := types.ContextWithHeight(int64(0)) + ctx := rpctypes.ContextWithHeight(int64(0)) tx, err := e.queryClient.TxReceipt(ctx, &evmtypes.QueryTxReceiptRequest{ Hash: hash.Hex(), }) @@ -802,7 +800,7 @@ func (e *PublicEthAPI) GetTransactionReceipt(hash common.Hash) (map[string]inter // PendingTransactions returns the transactions that are in the transaction pool // and have a from address that is one of the accounts this node manages. -func (e *PublicEthAPI) PendingTransactions() ([]*types.RPCTransaction, error) { +func (e *PublicEthAPI) PendingTransactions() ([]*rpctypes.RPCTransaction, error) { e.logger.Debugln("eth_getPendingTransactions") return e.backend.PendingTransactions() } @@ -818,15 +816,15 @@ func (e *PublicEthAPI) GetUncleByBlockNumberAndIndex(number hexutil.Uint, idx he } // GetProof returns an account object with proof and any storage proofs -func (e *PublicEthAPI) GetProof(address common.Address, storageKeys []string, blockNumber types.BlockNumber) (*types.AccountResult, error) { +func (e *PublicEthAPI) GetProof(address common.Address, storageKeys []string, blockNumber rpctypes.BlockNumber) (*rpctypes.AccountResult, error) { height := blockNumber.Int64() e.logger.Debugln("eth_getProof", "address", address.Hex(), "keys", storageKeys, "number", height) - ctx := types.ContextWithHeight(height) + ctx := rpctypes.ContextWithHeight(height) clientCtx := e.clientCtx.WithHeight(height) // query storage proofs - storageProofs := make([]types.StorageResult, len(storageKeys)) + storageProofs := make([]rpctypes.StorageResult, len(storageKeys)) for i, key := range storageKeys { hexKey := common.HexToHash(key) valueBz, proof, err := e.queryClient.GetProof(clientCtx, evmtypes.StoreKey, evmtypes.StateKey(address, hexKey.Bytes())) @@ -840,7 +838,7 @@ func (e *PublicEthAPI) GetProof(address common.Address, storageKeys []string, bl proofStr = proof.String() } - storageProofs[i] = types.StorageResult{ + storageProofs[i] = rpctypes.StorageResult{ Key: key, Value: (*hexutil.Big)(new(big.Int).SetBytes(valueBz)), Proof: []string{proofStr}, @@ -875,7 +873,7 @@ func (e *PublicEthAPI) GetProof(address common.Address, storageKeys []string, bl return nil, err } - return &types.AccountResult{ + return &rpctypes.AccountResult{ Address: address, AccountProof: []string{accProofStr}, Balance: (*hexutil.Big)(balance), diff --git a/go.mod b/go.mod index a15f8d92..7dd3fde0 100644 --- a/go.mod +++ b/go.mod @@ -45,9 +45,9 @@ require ( github.com/tyler-smith/go-bip39 v1.1.0 github.com/xlab/closer v0.0.0-20190328110542-03326addb7c2 github.com/xlab/suplog v1.3.0 - golang.org/x/crypto v0.0.0-20210513122933-cd7d49e622d5 + golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6 // indirect - google.golang.org/genproto v0.0.0-20210510173355-fb37daa5cd7a + google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384 google.golang.org/grpc v1.37.1 gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect diff --git a/go.sum b/go.sum index a0de0f0a..df76e2fb 100644 --- a/go.sum +++ b/go.sum @@ -918,8 +918,8 @@ golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210513122933-cd7d49e622d5 h1:N6Jp/LCiEoIBX56BZSR2bepK5GtbSC2DDOYT742mMfE= -golang.org/x/crypto v0.0.0-20210513122933-cd7d49e622d5/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= +golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1163,8 +1163,8 @@ google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210510173355-fb37daa5cd7a h1:tzkHckzMzgPr8SC4taTC3AldLr4+oJivSoq1xf/nhsc= -google.golang.org/genproto v0.0.0-20210510173355-fb37daa5cd7a/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384 h1:z+j74wi4yV+P7EtK9gPLGukOk7mFOy9wMQaC0wNb7eY= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= diff --git a/proto/ethermint/evm/v1alpha1/query.proto b/proto/ethermint/evm/v1alpha1/query.proto index 971df238..db3521f9 100644 --- a/proto/ethermint/evm/v1alpha1/query.proto +++ b/proto/ethermint/evm/v1alpha1/query.proto @@ -47,7 +47,7 @@ service Query { // TxReceiptsByBlockHeight queries tx receipts by a block height. rpc TxReceiptsByBlockHeight(QueryTxReceiptsByBlockHeightRequest) returns (QueryTxReceiptsByBlockHeightResponse) { - option (google.api.http).get = "/ethermint/evm/v1alpha1/tx_receipts_block/{height}"; + option (google.api.http).get = "/ethermint/evm/v1alpha1/tx_receipts_block"; } // TxReceiptsByBlockHash queries tx receipts by a block hash. @@ -196,11 +196,6 @@ message QueryTxReceiptResponse { // QueryTxReceiptsByBlockHeightRequest is the request type for the Query/TxReceiptsByBlockHeight RPC method. message QueryTxReceiptsByBlockHeightRequest { - option (gogoproto.equal) = false; - option (gogoproto.goproto_getters) = false; - - // height is the block height to query tx receipts for - int64 height = 1; } // QueryTxReceiptsByBlockHeightResponse is the response type for the Query/TxReceiptsByBlockHeight RPC method. @@ -241,9 +236,7 @@ message QueryBlockLogsResponse { // QueryBlockBloomRequest is the request type for the Query/BlockBloom RPC // method. -message QueryBlockBloomRequest { - int64 height = 1; -} +message QueryBlockBloomRequest { } // QueryBlockBloomResponse is the response type for the Query/BlockBloom RPC // method. diff --git a/x/evm/keeper/abci.go b/x/evm/keeper/abci.go index 43ca1839..373ed4ec 100644 --- a/x/evm/keeper/abci.go +++ b/x/evm/keeper/abci.go @@ -29,7 +29,7 @@ func (k *Keeper) BeginBlock(ctx sdk.Context, req abci.RequestBeginBlock) { // TODO: why do we have so many hash -> height mappings k.SetBlockHash(ctx, req.Hash, req.Header.Height) - k.SetBlockHeightToHash(ctx, req.Hash, req.Header.Height) + k.SetBlockHeightToHash(ctx, common.BytesToHash(req.Hash), req.Header.Height) // special setter for csdb k.SetHeightHash(ctx, uint64(req.Header.Height), common.BytesToHash(req.Hash)) diff --git a/x/evm/keeper/grpc_query.go b/x/evm/keeper/grpc_query.go index 2750d363..537f9b87 100644 --- a/x/evm/keeper/grpc_query.go +++ b/x/evm/keeper/grpc_query.go @@ -25,10 +25,9 @@ func (k Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*typ return nil, status.Error(codes.InvalidArgument, "empty request") } - if types.IsZeroAddress(req.Address) { + if err := ethermint.ValidateAddress(req.Address); err != nil { return nil, status.Error( - codes.InvalidArgument, - types.ErrZeroAddress.Error(), + codes.InvalidArgument, err.Error(), ) } @@ -47,34 +46,31 @@ func (k Keeper) Account(c context.Context, req *types.QueryAccountRequest) (*typ } func (k Keeper) CosmosAccount(c context.Context, req *types.QueryCosmosAccountRequest) (*types.QueryCosmosAccountResponse, error) { - if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } - if types.IsZeroAddress(req.Address) { + if err := ethermint.ValidateAddress(req.Address); err != nil { return nil, status.Error( - codes.InvalidArgument, - types.ErrZeroAddress.Error(), + codes.InvalidArgument, err.Error(), ) } ctx := sdk.UnwrapSDKContext(c) - ethStr := req.Address - ethAddr := ethcmn.FromHex(ethStr) + ethAddr := ethcmn.HexToAddress(req.Address) + cosmosAddr := sdk.AccAddress(ethAddr.Bytes()) - ethToCosmosAddr := sdk.AccAddress(ethAddr[:]).String() - cosmosToEthAddr, _ := sdk.AccAddressFromBech32(ethToCosmosAddr) - - acc := k.accountKeeper.GetAccount(ctx, cosmosToEthAddr) + account := k.accountKeeper.GetAccount(ctx, cosmosAddr) res := types.QueryCosmosAccountResponse{ - CosmosAddress: cosmosToEthAddr.String(), + CosmosAddress: cosmosAddr.String(), } - if acc != nil { - res.Sequence = acc.GetSequence() - res.AccountNumber = acc.GetAccountNumber() + + if account != nil { + res.Sequence = account.GetSequence() + res.AccountNumber = account.GetAccountNumber() } + return &res, nil } @@ -84,7 +80,7 @@ func (k Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (*typ return nil, status.Error(codes.InvalidArgument, "empty request") } - if types.IsZeroAddress(req.Address) { + if err := ethermint.ValidateAddress(req.Address); err != nil { return nil, status.Error( codes.InvalidArgument, types.ErrZeroAddress.Error(), @@ -109,12 +105,11 @@ func (k Keeper) Balance(c context.Context, req *types.QueryBalanceRequest) (*typ // Storage implements the Query/Storage gRPC method func (k Keeper) Storage(c context.Context, req *types.QueryStorageRequest) (*types.QueryStorageResponse, error) { - if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } - if types.IsZeroAddress(req.Address) { + if err := ethermint.ValidateAddress(req.Address); err != nil { return nil, status.Error( codes.InvalidArgument, types.ErrZeroAddress.Error(), @@ -139,7 +134,7 @@ func (k Keeper) Code(c context.Context, req *types.QueryCodeRequest) (*types.Que return nil, status.Error(codes.InvalidArgument, "empty request") } - if types.IsZeroAddress(req.Address) { + if err := ethermint.ValidateAddress(req.Address); err != nil { return nil, status.Error( codes.InvalidArgument, types.ErrZeroAddress.Error(), @@ -162,7 +157,7 @@ func (k Keeper) TxLogs(c context.Context, req *types.QueryTxLogsRequest) (*types return nil, status.Error(codes.InvalidArgument, "empty request") } - if types.IsEmptyHash(req.Hash) { + if ethermint.IsEmptyHash(req.Hash) { return nil, status.Error( codes.InvalidArgument, types.ErrEmptyHash.Error(), @@ -187,12 +182,11 @@ func (k Keeper) TxLogs(c context.Context, req *types.QueryTxLogsRequest) (*types // TxReceipt implements the Query/TxReceipt gRPC method func (k Keeper) TxReceipt(c context.Context, req *types.QueryTxReceiptRequest) (*types.QueryTxReceiptResponse, error) { - if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } - if types.IsEmptyHash(req.Hash) { + if ethermint.IsEmptyHash(req.Hash) { return nil, status.Error( codes.InvalidArgument, types.ErrEmptyHash.Error(), @@ -204,8 +198,8 @@ func (k Keeper) TxReceipt(c context.Context, req *types.QueryTxReceiptRequest) ( hash := ethcmn.HexToHash(req.Hash) receipt, found := k.GetTxReceiptFromHash(ctx, hash) if !found { - return nil, status.Error( - codes.NotFound, types.ErrTxReceiptNotFound.Error(), + return nil, status.Errorf( + codes.NotFound, "%s: %s", types.ErrTxReceiptNotFound.Error(), req.Hash, ) } @@ -215,14 +209,10 @@ func (k Keeper) TxReceipt(c context.Context, req *types.QueryTxReceiptRequest) ( } // TxReceiptsByBlockHeight implements the Query/TxReceiptsByBlockHeight gRPC method -func (k Keeper) TxReceiptsByBlockHeight(c context.Context, req *types.QueryTxReceiptsByBlockHeightRequest) (*types.QueryTxReceiptsByBlockHeightResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - +func (k Keeper) TxReceiptsByBlockHeight(c context.Context, _ *types.QueryTxReceiptsByBlockHeightRequest) (*types.QueryTxReceiptsByBlockHeightResponse, error) { ctx := sdk.UnwrapSDKContext(c) - receipts := k.GetTxReceiptsByBlockHeight(ctx, req.Height) + receipts := k.GetTxReceiptsByBlockHeight(ctx, ctx.BlockHeight()) return &types.QueryTxReceiptsByBlockHeightResponse{ Receipts: receipts, }, nil @@ -234,7 +224,7 @@ func (k Keeper) TxReceiptsByBlockHash(c context.Context, req *types.QueryTxRecei return nil, status.Error(codes.InvalidArgument, "empty request") } - if types.IsEmptyHash(req.Hash) { + if ethermint.IsEmptyHash(req.Hash) { return nil, status.Error( codes.InvalidArgument, types.ErrEmptyHash.Error(), @@ -253,12 +243,11 @@ func (k Keeper) TxReceiptsByBlockHash(c context.Context, req *types.QueryTxRecei // BlockLogs implements the Query/BlockLogs gRPC method func (k Keeper) BlockLogs(c context.Context, req *types.QueryBlockLogsRequest) (*types.QueryBlockLogsResponse, error) { - if req == nil { return nil, status.Error(codes.InvalidArgument, "empty request") } - if types.IsEmptyHash(req.Hash) { + if ethermint.IsEmptyHash(req.Hash) { return nil, status.Error( codes.InvalidArgument, types.ErrEmptyHash.Error(), @@ -275,19 +264,10 @@ func (k Keeper) BlockLogs(c context.Context, req *types.QueryBlockLogsRequest) ( } // BlockBloom implements the Query/BlockBloom gRPC method -func (k Keeper) BlockBloom(c context.Context, req *types.QueryBlockBloomRequest) (*types.QueryBlockBloomResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - +func (k Keeper) BlockBloom(c context.Context, _ *types.QueryBlockBloomRequest) (*types.QueryBlockBloomResponse, error) { ctx := sdk.UnwrapSDKContext(c) - height := ctx.BlockHeight() - if setHeight := req.Height; setHeight > 0 { - height = setHeight - } - - bloom, found := k.GetBlockBloom(ctx, height) + bloom, found := k.GetBlockBloom(ctx, ctx.BlockHeight()) if !found { return nil, status.Error( codes.NotFound, types.ErrBloomNotFound.Error(), @@ -300,11 +280,7 @@ func (k Keeper) BlockBloom(c context.Context, req *types.QueryBlockBloomRequest) } // Params implements the Query/Params gRPC method -func (k Keeper) Params(c context.Context, req *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { - if req == nil { - return nil, status.Error(codes.InvalidArgument, "empty request") - } - +func (k Keeper) Params(c context.Context, _ *types.QueryParamsRequest) (*types.QueryParamsResponse, error) { ctx := sdk.UnwrapSDKContext(c) params := k.GetParams(ctx) @@ -342,9 +318,12 @@ func (k Keeper) StaticCall(c context.Context, req *types.QueryStaticCallRequest) msg := types.NewMsgEthereumTx( chainIDEpoch, so.Nonce(), recipient, big.NewInt(0), 100000000, big.NewInt(0), req.Input, nil, ) - msg.From = sender.Hex() + if err := msg.ValidateBasic(); err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + ethMsg, err := msg.AsMessage() if err != nil { return nil, status.Error(codes.Internal, err.Error()) @@ -356,6 +335,7 @@ func (k Keeper) StaticCall(c context.Context, req *types.QueryStaticCallRequest) ChainID: chainIDEpoch, TxHash: ðHash, Simulate: ctx.IsCheckTx(), + Debug: false, } config, found := k.GetChainConfig(ctx) diff --git a/x/evm/keeper/grpc_query_test.go b/x/evm/keeper/grpc_query_test.go new file mode 100644 index 00000000..0f18d02d --- /dev/null +++ b/x/evm/keeper/grpc_query_test.go @@ -0,0 +1,786 @@ +package keeper_test + +import ( + "fmt" + + "google.golang.org/grpc/metadata" + + ethcmn "github.com/ethereum/go-ethereum/common" + ethtypes "github.com/ethereum/go-ethereum/core/types" + ethcrypto "github.com/ethereum/go-ethereum/crypto" + + sdk "github.com/cosmos/cosmos-sdk/types" + + ethermint "github.com/cosmos/ethermint/types" + "github.com/cosmos/ethermint/x/evm/types" + + grpctypes "github.com/cosmos/cosmos-sdk/types/grpc" +) + +func (suite *KeeperTestSuite) TestQueryAccount() { + var ( + req *types.QueryAccountRequest + expAccount *types.QueryAccountResponse + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + {"zero address", + func() { + suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(0)) + expAccount = &types.QueryAccountResponse{ + Balance: "0", + CodeHash: ethcrypto.Keccak256(nil), + Nonce: 0, + } + req = &types.QueryAccountRequest{ + Address: ethcmn.Address{}.String(), + } + }, + false, + }, + { + "success", + func() { + suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(100)) + expAccount = &types.QueryAccountResponse{ + Balance: "100", + CodeHash: ethcrypto.Keccak256(nil), + Nonce: 0, + } + req = &types.QueryAccountRequest{ + Address: suite.address.String(), + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + res, err := suite.queryClient.Account(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + + suite.Require().Equal(expAccount, res) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryCosmosAccount() { + var ( + req *types.QueryCosmosAccountRequest + expAccount *types.QueryCosmosAccountResponse + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + {"zero address", + func() { + suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(0)) + expAccount = &types.QueryCosmosAccountResponse{ + CosmosAddress: sdk.AccAddress(ethcmn.Address{}.Bytes()).String(), + } + req = &types.QueryCosmosAccountRequest{ + Address: ethcmn.Address{}.String(), + } + }, + false, + }, + { + "success", + func() { + expAccount = &types.QueryCosmosAccountResponse{ + CosmosAddress: sdk.AccAddress(suite.address.Bytes()).String(), + Sequence: 0, + AccountNumber: 0, + } + req = &types.QueryCosmosAccountRequest{ + Address: suite.address.String(), + } + }, + true, + }, + { + "success with seq and account number", + func() { + acc := suite.app.AccountKeeper.GetAccount(suite.ctx, suite.address.Bytes()) + suite.Require().NoError(acc.SetSequence(10)) + suite.Require().NoError(acc.SetAccountNumber(1)) + suite.app.AccountKeeper.SetAccount(suite.ctx, acc) + + expAccount = &types.QueryCosmosAccountResponse{ + CosmosAddress: sdk.AccAddress(suite.address.Bytes()).String(), + Sequence: 10, + AccountNumber: 1, + } + req = &types.QueryCosmosAccountRequest{ + Address: suite.address.String(), + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + res, err := suite.queryClient.CosmosAccount(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + + suite.Require().Equal(expAccount, res) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryBalance() { + var ( + req *types.QueryBalanceRequest + expBalance string + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + {"zero address", + func() { + suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(0)) + expBalance = "0" + req = &types.QueryBalanceRequest{ + Address: ethcmn.Address{}.String(), + } + }, + false, + }, + { + "success", + func() { + suite.app.BankKeeper.SetBalance(suite.ctx, suite.address.Bytes(), ethermint.NewPhotonCoinInt64(100)) + expBalance = "100" + req = &types.QueryBalanceRequest{ + Address: suite.address.String(), + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + res, err := suite.queryClient.Balance(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + + suite.Require().Equal(expBalance, res.Balance) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryStorage() { + var ( + req *types.QueryStorageRequest + expValue string + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + {"zero address", + func() { + req = &types.QueryStorageRequest{ + Address: ethcmn.Address{}.String(), + } + }, + false, + }, + {"empty hash", + func() { + req = &types.QueryStorageRequest{ + Address: suite.address.String(), + Key: ethcmn.Hash{}.String(), + } + exp := &types.QueryStorageResponse{Value: "0x0000000000000000000000000000000000000000000000000000000000000000"} + expValue = exp.Value + }, + true, + }, + { + "success", + func() { + key := ethcmn.BytesToHash([]byte("key")) + value := ethcmn.BytesToHash([]byte("value")) + expValue = value.String() + suite.app.EvmKeeper.SetState(suite.ctx, suite.address, key, value) + req = &types.QueryStorageRequest{ + Address: suite.address.String(), + Key: key.String(), + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + res, err := suite.queryClient.Storage(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + + suite.Require().Equal(expValue, res.Value) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryCode() { + var ( + req *types.QueryCodeRequest + expCode []byte + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + {"zero address", + func() { + req = &types.QueryCodeRequest{ + Address: ethcmn.Address{}.String(), + } + exp := &types.QueryCodeResponse{} + expCode = exp.Code + }, + false, + }, + { + "success", + func() { + expCode = []byte("code") + suite.app.EvmKeeper.SetCode(suite.ctx, suite.address, expCode) + + req = &types.QueryCodeRequest{ + Address: suite.address.String(), + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + res, err := suite.queryClient.Code(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + + suite.Require().Equal(expCode, res.Code) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryTxLogs() { + var ( + req *types.QueryTxLogsRequest + expLogs []*types.Log + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + {"empty hash", + func() { + req = &types.QueryTxLogsRequest{ + Hash: ethcmn.Hash{}.String(), + } + }, + false, + }, + {"logs not found", + func() { + hash := ethcmn.BytesToHash([]byte("hash")) + req = &types.QueryTxLogsRequest{ + Hash: hash.String(), + } + }, + true, + }, + { + "success", + func() { + hash := ethcmn.BytesToHash([]byte("tx_hash")) + + expLogs = []*types.Log{ + { + Address: suite.address.String(), + Topics: []string{ethcmn.BytesToHash([]byte("topic")).String()}, + Data: []byte("data"), + BlockNumber: 1, + TxHash: hash.String(), + TxIndex: 1, + BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(), + Index: 0, + Removed: false, + }, + } + + suite.app.EvmKeeper.SetLogs(suite.ctx, hash, types.LogsToEthereum(expLogs)) + + req = &types.QueryTxLogsRequest{ + Hash: hash.String(), + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + res, err := suite.queryClient.TxLogs(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + + suite.Require().Equal(expLogs, res.Logs) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryBlockLogs() { + var ( + req *types.QueryBlockLogsRequest + expLogs []types.TransactionLogs + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + {"empty hash", + func() { + req = &types.QueryBlockLogsRequest{ + Hash: ethcmn.Hash{}.String(), + } + }, + false, + }, + {"logs not found", + func() { + hash := ethcmn.BytesToHash([]byte("hash")) + req = &types.QueryBlockLogsRequest{ + Hash: hash.String(), + } + }, + true, + }, + { + "success", + func() { + + hash := ethcmn.BytesToHash([]byte("block_hash")) + expLogs = []types.TransactionLogs{ + { + Hash: ethcmn.BytesToHash([]byte("tx_hash_0")).String(), + Logs: []*types.Log{ + { + Address: suite.address.String(), + Topics: []string{ethcmn.BytesToHash([]byte("topic")).String()}, + Data: []byte("data"), + BlockNumber: 1, + TxHash: ethcmn.BytesToHash([]byte("tx_hash_0")).String(), + TxIndex: 1, + BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(), + Index: 0, + Removed: false, + }, + }, + }, + { + Hash: ethcmn.BytesToHash([]byte("tx_hash_1")).String(), + Logs: []*types.Log{ + { + Address: suite.address.String(), + Topics: []string{ethcmn.BytesToHash([]byte("topic")).String()}, + Data: []byte("data"), + BlockNumber: 1, + TxHash: ethcmn.BytesToHash([]byte("tx_hash_1")).String(), + TxIndex: 1, + BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(), + Index: 0, + Removed: false, + }, + { + Address: suite.address.String(), + Topics: []string{ethcmn.BytesToHash([]byte("topic_1")).String()}, + Data: []byte("data_1"), + BlockNumber: 1, + TxHash: ethcmn.BytesToHash([]byte("tx_hash_1")).String(), + TxIndex: 1, + BlockHash: ethcmn.BytesToHash([]byte("block_hash")).String(), + Index: 0, + Removed: false, + }, + }, + }, + } + + suite.app.EvmKeeper.SetLogs(suite.ctx, ethcmn.BytesToHash([]byte("tx_hash_0")), types.LogsToEthereum(expLogs[0].Logs)) + suite.app.EvmKeeper.SetLogs(suite.ctx, ethcmn.BytesToHash([]byte("tx_hash_1")), types.LogsToEthereum(expLogs[1].Logs)) + + req = &types.QueryBlockLogsRequest{ + Hash: hash.String(), + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + res, err := suite.queryClient.BlockLogs(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + + suite.Require().Equal(expLogs, res.TxLogs) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryTxReceipt() { + var ( + req *types.QueryTxReceiptRequest + expRes *types.QueryTxReceiptResponse + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + {"empty hash", + func() { + req = &types.QueryTxReceiptRequest{} + }, + false, + }, + {"tx receipt not found for hash", + func() { + hash := ethcmn.BytesToHash([]byte("thash")) + req = &types.QueryTxReceiptRequest{ + Hash: hash.Hex(), + } + }, + false, + }, + {"success", + func() { + hash := ethcmn.BytesToHash([]byte("thash")) + receipt := &types.TxReceipt{ + Hash: hash.Hex(), + From: suite.address.Hex(), + BlockHeight: uint64(suite.ctx.BlockHeight()), + BlockHash: ethcmn.BytesToHash(suite.ctx.BlockHeader().DataHash).Hex(), + } + + suite.app.EvmKeeper.SetTxReceiptToHash(suite.ctx, hash, receipt) + req = &types.QueryTxReceiptRequest{ + Hash: hash.Hex(), + } + + expRes = &types.QueryTxReceiptResponse{ + Receipt: receipt, + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + res, err := suite.queryClient.TxReceipt(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + + suite.Require().Equal(expRes, res) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryTxReceiptByBlockHeight() { + var ( + req = &types.QueryTxReceiptsByBlockHeightRequest{} + expRes *types.QueryTxReceiptsByBlockHeightResponse + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + {"empty response", + func() { + expRes = &types.QueryTxReceiptsByBlockHeightResponse{ + Receipts: nil, + } + }, + true, + }, + {"success", + func() { + hash := ethcmn.BytesToHash([]byte("thash")) + receipt := &types.TxReceipt{ + Hash: hash.Hex(), + From: suite.address.Hex(), + BlockHeight: uint64(suite.ctx.BlockHeight()), + BlockHash: ethcmn.BytesToHash(suite.ctx.BlockHeader().DataHash).Hex(), + } + + suite.app.EvmKeeper.AddTxHashToBlock(suite.ctx, suite.ctx.BlockHeight(), hash) + suite.app.EvmKeeper.SetTxReceiptToHash(suite.ctx, hash, receipt) + expRes = &types.QueryTxReceiptsByBlockHeightResponse{ + Receipts: []*types.TxReceipt{receipt}, + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, fmt.Sprintf("%d", suite.ctx.BlockHeight())) + + res, err := suite.queryClient.TxReceiptsByBlockHeight(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + + suite.Require().Equal(expRes, res) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryTxReceiptByBlockHash() { + var ( + req *types.QueryTxReceiptsByBlockHashRequest + expRes *types.QueryTxReceiptsByBlockHashResponse + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + {"empty block hash", + func() { + req = &types.QueryTxReceiptsByBlockHashRequest{ + Hash: "", + } + }, + false, + }, + {"success", + func() { + hash := ethcmn.BytesToHash([]byte("thash")) + blockHash := ethcmn.BytesToHash([]byte("bhash")) + + receipt := &types.TxReceipt{ + Hash: hash.Hex(), + From: suite.address.Hex(), + BlockHeight: uint64(suite.ctx.BlockHeight()), + BlockHash: blockHash.Hex(), + } + + suite.app.EvmKeeper.SetBlockHash(suite.ctx, blockHash.Bytes(), suite.ctx.BlockHeight()) + suite.app.EvmKeeper.AddTxHashToBlock(suite.ctx, suite.ctx.BlockHeight(), hash) + suite.app.EvmKeeper.SetTxReceiptToHash(suite.ctx, hash, receipt) + + req = &types.QueryTxReceiptsByBlockHashRequest{ + Hash: blockHash.Hex(), + } + + expRes = &types.QueryTxReceiptsByBlockHashResponse{ + Receipts: []*types.TxReceipt{receipt}, + } + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + + res, err := suite.queryClient.TxReceiptsByBlockHash(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + + suite.Require().Equal(expRes, res) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryBlockBloom() { + var ( + req *types.QueryBlockBloomRequest + expBloom []byte + ) + + testCases := []struct { + msg string + malleate func() + expPass bool + }{ + {"marshal error", + func() {}, + false, + }, + {"bloom not found for height", + func() { + req = &types.QueryBlockBloomRequest{} + bloom := ethtypes.BytesToBloom([]byte("bloom")) + expBloom = bloom.Bytes() + suite.ctx = suite.ctx.WithBlockHeight(10) + suite.app.EvmKeeper.SetBlockBloom(suite.ctx, 2, bloom) + }, + false, + }, + { + "success", + func() { + req = &types.QueryBlockBloomRequest{} + bloom := ethtypes.BytesToBloom([]byte("bloom")) + expBloom = bloom.Bytes() + suite.ctx = suite.ctx.WithBlockHeight(1) + suite.app.EvmKeeper.SetBlockBloom(suite.ctx, 1, bloom) + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(fmt.Sprintf("Case %s", tc.msg), func() { + suite.SetupTest() // reset + + tc.malleate() + ctx := sdk.WrapSDKContext(suite.ctx) + ctx = metadata.AppendToOutgoingContext(ctx, grpctypes.GRPCBlockHeightHeader, fmt.Sprintf("%d", suite.ctx.BlockHeight())) + res, err := suite.queryClient.BlockBloom(ctx, req) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(res) + + suite.Require().Equal(expBloom, res.Bloom) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *KeeperTestSuite) TestQueryParams() { + ctx := sdk.WrapSDKContext(suite.ctx) + expParams := types.DefaultParams() + + res, err := suite.queryClient.Params(ctx, &types.QueryParamsRequest{}) + suite.Require().NoError(err) + suite.Require().Equal(expParams, res.Params) +} diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 88e17316..87e5432a 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -78,14 +78,11 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { // GetBlockBloom gets bloombits from block height func (k Keeper) GetBlockBloom(ctx sdk.Context, height int64) (ethtypes.Bloom, bool) { store := ctx.KVStore(k.storeKey) - - key := types.BloomKey(height) - has := store.Has(key) - if !has { - return ethtypes.Bloom{}, true // sometimes bloom not found, fix this + bz := store.Get(types.BloomKey(height)) + if len(bz) == 0 { + return ethtypes.Bloom{}, false } - bz := store.Get(key) return ethtypes.BytesToBloom(bz), true } @@ -128,9 +125,9 @@ func (k Keeper) GetBlockHeightByHash(ctx sdk.Context, hash common.Hash) (int64, } // SetBlockHash sets the mapping from block consensus hash to block height -func (k Keeper) SetBlockHeightToHash(ctx sdk.Context, hash []byte, height int64) { +func (k Keeper) SetBlockHeightToHash(ctx sdk.Context, hash common.Hash, height int64) { store := ctx.KVStore(k.storeKey) - store.Set(types.KeyBlockHeightHash(uint64(height)), hash) + store.Set(types.KeyBlockHeightHash(uint64(height)), hash.Bytes()) } // SetTxReceiptToHash sets the mapping from tx hash to tx receipt diff --git a/x/evm/keeper/keeper_test.go b/x/evm/keeper/keeper_test.go index cb2ab1ad..2b928930 100644 --- a/x/evm/keeper/keeper_test.go +++ b/x/evm/keeper/keeper_test.go @@ -7,6 +7,7 @@ import ( "github.com/stretchr/testify/suite" + "github.com/cosmos/cosmos-sdk/baseapp" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" @@ -31,19 +32,23 @@ var ( type KeeperTestSuite struct { suite.Suite - ctx sdk.Context - querier sdk.Querier - app *app.EthermintApp - address ethcmn.Address + ctx sdk.Context + app *app.EthermintApp + queryClient types.QueryClient + address ethcmn.Address } func (suite *KeeperTestSuite) SetupTest() { checkTx := false suite.app = app.Setup(checkTx) - suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "3", Time: time.Now().UTC()}) + suite.ctx = suite.app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1, ChainID: "ethermint-3", Time: time.Now().UTC()}) suite.address = ethcmn.HexToAddress(addrHex) + queryHelper := baseapp.NewQueryServerTestHelper(suite.ctx, suite.app.InterfaceRegistry()) + types.RegisterQueryServer(queryHelper, suite.app.EvmKeeper) + suite.queryClient = types.NewQueryClient(queryHelper) + balance := ethermint.NewPhotonCoin(sdk.ZeroInt()) acc := ðermint.EthAccount{ BaseAccount: authtypes.NewBaseAccount(sdk.AccAddress(suite.address.Bytes()), nil, 0, 0), diff --git a/x/evm/types/genesis.go b/x/evm/types/genesis.go index fb084eae..8ef593b4 100644 --- a/x/evm/types/genesis.go +++ b/x/evm/types/genesis.go @@ -4,13 +4,14 @@ import ( "errors" "fmt" + ethermint "github.com/cosmos/ethermint/types" ethcmn "github.com/ethereum/go-ethereum/common" ) // Validate performs a basic validation of a GenesisAccount fields. func (ga GenesisAccount) Validate() error { - if IsZeroAddress(ga.Address) { - return fmt.Errorf("address cannot be the zero address %s", ga.Address) + if err := ethermint.ValidateAddress(ga.Address); err != nil { + return err } if len(ethcmn.Hex2Bytes(ga.Code)) == 0 { return errors.New("code cannot be empty") diff --git a/x/evm/types/logs.go b/x/evm/types/logs.go index fd6a5a4d..17ae94db 100644 --- a/x/evm/types/logs.go +++ b/x/evm/types/logs.go @@ -9,6 +9,8 @@ import ( ethcmn "github.com/ethereum/go-ethereum/common" ethtypes "github.com/ethereum/go-ethereum/core/types" + + ethermint "github.com/cosmos/ethermint/types" ) // NewTransactionLogs creates a new NewTransactionLogs instance. @@ -59,16 +61,16 @@ func (tx TransactionLogs) EthLogs() []*ethtypes.Log { // Validate performs a basic validation of an ethereum Log fields. func (log *Log) Validate() error { - if IsZeroAddress(log.Address) { - return fmt.Errorf("log address cannot be empty %s", log.Address) + if err := ethermint.ValidateAddress(log.Address); err != nil { + return fmt.Errorf("invalid log address %w", err) } - if IsEmptyHash(log.BlockHash) { + if ethermint.IsEmptyHash(log.BlockHash) { return fmt.Errorf("block hash cannot be the empty %s", log.BlockHash) } if log.BlockNumber == 0 { return errors.New("block number cannot be zero") } - if IsEmptyHash(log.TxHash) { + if ethermint.IsEmptyHash(log.TxHash) { return fmt.Errorf("tx hash cannot be the empty %s", log.TxHash) } return nil diff --git a/x/evm/types/msg.go b/x/evm/types/msg.go index 56993b3e..60275964 100644 --- a/x/evm/types/msg.go +++ b/x/evm/types/msg.go @@ -143,7 +143,7 @@ func (msg *MsgEthereumTx) GetMsgs() []sdk.Msg { // // NOTE: This method panics if 'VerifySig' hasn't been called first. func (msg MsgEthereumTx) GetSigners() []sdk.AccAddress { - if IsZeroAddress(msg.From) { + if msg.From == "" { panic("must use 'VerifySig' with a chain ID to get the signer") } diff --git a/x/evm/types/query.pb.go b/x/evm/types/query.pb.go index 6b689e1d..71913faa 100644 --- a/x/evm/types/query.pb.go +++ b/x/evm/types/query.pb.go @@ -666,8 +666,6 @@ func (m *QueryTxReceiptResponse) GetReceipt() *TxReceipt { // QueryTxReceiptsByBlockHeightRequest is the request type for the Query/TxReceiptsByBlockHeight RPC method. type QueryTxReceiptsByBlockHeightRequest struct { - // height is the block height to query tx receipts for - Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` } func (m *QueryTxReceiptsByBlockHeightRequest) Reset() { *m = QueryTxReceiptsByBlockHeightRequest{} } @@ -922,7 +920,6 @@ func (m *QueryBlockLogsResponse) GetTxLogs() []TransactionLogs { // QueryBlockBloomRequest is the request type for the Query/BlockBloom RPC // method. type QueryBlockBloomRequest struct { - Height int64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` } func (m *QueryBlockBloomRequest) Reset() { *m = QueryBlockBloomRequest{} } @@ -958,13 +955,6 @@ func (m *QueryBlockBloomRequest) XXX_DiscardUnknown() { var xxx_messageInfo_QueryBlockBloomRequest proto.InternalMessageInfo -func (m *QueryBlockBloomRequest) GetHeight() int64 { - if m != nil { - return m.Height - } - return 0 -} - // QueryBlockBloomResponse is the response type for the Query/BlockBloom RPC // method. type QueryBlockBloomResponse struct { @@ -1229,80 +1219,78 @@ func init() { } var fileDescriptor_8bbc79ec2b6c5cb2 = []byte{ - // 1157 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x57, 0x4f, 0x6f, 0x1b, 0xc5, - 0x1b, 0xf6, 0x26, 0x8e, 0x9d, 0xbc, 0x6d, 0x7e, 0xca, 0x6f, 0x70, 0xd3, 0xb0, 0x45, 0x4e, 0x3a, - 0xa5, 0x8d, 0xd3, 0xa4, 0xde, 0xc4, 0x50, 0x4a, 0xd3, 0x56, 0x28, 0xae, 0x54, 0x22, 0x51, 0x21, - 0x70, 0xe0, 0xc2, 0xc5, 0x8c, 0xd7, 0x2b, 0xdb, 0xca, 0x7a, 0xc7, 0xf5, 0xae, 0xa3, 0x44, 0x51, - 0x2e, 0x1c, 0x10, 0x48, 0x1c, 0x40, 0x1c, 0x40, 0x48, 0x48, 0xfd, 0x08, 0x7c, 0x8c, 0x5e, 0x90, - 0x22, 0x71, 0x41, 0x42, 0x42, 0x28, 0xe1, 0xc0, 0xc7, 0x40, 0x33, 0xf3, 0xee, 0x7a, 0x37, 0xf1, - 0x7a, 0x37, 0x11, 0xb7, 0x9d, 0xf1, 0xfb, 0xbc, 0xcf, 0xf3, 0xbe, 0xf3, 0xe7, 0x19, 0x03, 0xb5, - 0xbc, 0xb6, 0xd5, 0xef, 0x76, 0x1c, 0xcf, 0xb0, 0xf6, 0xba, 0xc6, 0xde, 0x06, 0xb3, 0x7b, 0x6d, - 0xb6, 0x61, 0xbc, 0x18, 0x58, 0xfd, 0x83, 0x72, 0xaf, 0xcf, 0x3d, 0x4e, 0xe6, 0x83, 0x98, 0xb2, - 0xb5, 0xd7, 0x2d, 0xfb, 0x31, 0x7a, 0xa1, 0xc5, 0x5b, 0x5c, 0x86, 0x18, 0xe2, 0x4b, 0x45, 0xeb, - 0x6f, 0xb4, 0x38, 0x6f, 0xd9, 0x96, 0xc1, 0x7a, 0x1d, 0x83, 0x39, 0x0e, 0xf7, 0x98, 0xd7, 0xe1, - 0x8e, 0x8b, 0xbf, 0x2e, 0xc5, 0xf0, 0x89, 0xc4, 0x32, 0x82, 0x3e, 0x84, 0xd7, 0x3e, 0x16, 0xe4, - 0x5b, 0xa6, 0xc9, 0x07, 0x8e, 0x57, 0xb3, 0x5e, 0x0c, 0x2c, 0xd7, 0x23, 0x0b, 0x90, 0x67, 0xcd, - 0x66, 0xdf, 0x72, 0xdd, 0x05, 0x6d, 0x49, 0x2b, 0xcd, 0xd4, 0xfc, 0xe1, 0xe6, 0xf4, 0x57, 0x2f, - 0x17, 0x33, 0xff, 0xbc, 0x5c, 0xcc, 0x50, 0x13, 0x0a, 0x51, 0xa8, 0xdb, 0xe3, 0x8e, 0x6b, 0x09, - 0x6c, 0x83, 0xd9, 0xcc, 0x31, 0x2d, 0x1f, 0x8b, 0x43, 0x72, 0x03, 0x66, 0x4c, 0xde, 0xb4, 0xea, - 0x6d, 0xe6, 0xb6, 0x17, 0x26, 0x96, 0xb4, 0xd2, 0xd5, 0xda, 0xb4, 0x98, 0xd8, 0x66, 0x6e, 0x9b, - 0x14, 0x60, 0xca, 0xe1, 0x02, 0x34, 0xb9, 0xa4, 0x95, 0xb2, 0x35, 0x35, 0xa0, 0xef, 0xc1, 0xeb, - 0x92, 0xe4, 0x29, 0x77, 0xbb, 0xdc, 0xbd, 0x84, 0xca, 0x2f, 0x35, 0xd0, 0x47, 0x65, 0x40, 0xb1, - 0xb7, 0xe1, 0x7f, 0xa6, 0xfc, 0xa1, 0x1e, 0xcd, 0x34, 0xab, 0x66, 0xb7, 0xd4, 0x24, 0xd1, 0x61, - 0xda, 0x15, 0xa4, 0x42, 0xdf, 0x84, 0xd4, 0x17, 0x8c, 0x45, 0x0a, 0xa6, 0xb2, 0xd6, 0x9d, 0x41, - 0xb7, 0x61, 0xf5, 0xb1, 0x82, 0x59, 0x9c, 0xfd, 0x50, 0x4e, 0x06, 0x9d, 0xae, 0xaa, 0x66, 0x5c, - 0xa4, 0x86, 0x75, 0xec, 0x74, 0x00, 0x4d, 0xea, 0x34, 0xfd, 0x00, 0xc9, 0x76, 0x3c, 0xde, 0x67, - 0xad, 0x64, 0x32, 0x32, 0x07, 0x93, 0xbb, 0xd6, 0x81, 0xac, 0x6d, 0xa6, 0x26, 0x3e, 0x43, 0xf4, - 0x6b, 0x48, 0x1f, 0x24, 0x43, 0xfa, 0x02, 0x4c, 0xed, 0x31, 0x7b, 0xe0, 0x93, 0xab, 0x01, 0x7d, - 0x07, 0xe6, 0xb0, 0xdf, 0xcd, 0x0b, 0x15, 0xb9, 0x0c, 0xff, 0x0f, 0xe1, 0x90, 0x82, 0x40, 0x56, - 0x6c, 0x10, 0x89, 0xba, 0x5a, 0x93, 0xdf, 0xb4, 0x02, 0x44, 0x06, 0x7e, 0xb2, 0xff, 0x9c, 0xb7, - 0x5c, 0x9f, 0x82, 0x40, 0x56, 0x6e, 0x2b, 0x95, 0x5f, 0x7e, 0x87, 0x92, 0x3f, 0xc3, 0x7e, 0xf8, - 0x18, 0x4c, 0x6f, 0x40, 0xd6, 0xe6, 0x2d, 0x21, 0x6a, 0xb2, 0x74, 0xa5, 0x72, 0xa3, 0x3c, 0xfa, - 0xe8, 0x95, 0x9f, 0xf3, 0x56, 0x4d, 0x06, 0xd2, 0xfb, 0x70, 0x0d, 0xf3, 0xd4, 0x2c, 0xd3, 0xea, - 0xf4, 0xbc, 0x74, 0xf4, 0x9f, 0xc2, 0xfc, 0x59, 0x18, 0x2a, 0x78, 0x04, 0xf9, 0xbe, 0x9a, 0x92, - 0xd0, 0x2b, 0x95, 0x9b, 0x71, 0x22, 0x86, 0x58, 0x1f, 0x41, 0xdf, 0x87, 0x5b, 0xd1, 0xb4, 0x6e, - 0xf5, 0xa0, 0x6a, 0x73, 0x73, 0x77, 0xdb, 0xea, 0xb4, 0xda, 0x81, 0xb6, 0x79, 0xc8, 0xb5, 0xe5, - 0x84, 0xa4, 0x98, 0xac, 0xe1, 0x28, 0xa4, 0xcf, 0x82, 0x37, 0xc7, 0x27, 0x42, 0xb5, 0x4f, 0x60, - 0x1a, 0xb9, 0xfd, 0x9e, 0xa5, 0x90, 0x1b, 0x40, 0xe8, 0x16, 0xdc, 0x8c, 0xa1, 0x61, 0x6e, 0x3b, - 0x5d, 0x27, 0x4d, 0xa0, 0xe3, 0x52, 0xfc, 0x37, 0x3a, 0xfd, 0x55, 0x96, 0x89, 0xd3, 0x6f, 0xb2, - 0xcf, 0x71, 0x95, 0x43, 0x30, 0xd4, 0xf3, 0x0c, 0xf2, 0xde, 0x7e, 0x3d, 0xb4, 0xd5, 0x96, 0x63, - 0xe5, 0xf4, 0x99, 0xe3, 0x32, 0x53, 0x5c, 0xe2, 0x22, 0x43, 0x35, 0xfb, 0xea, 0xcf, 0xc5, 0x4c, - 0x2d, 0xe7, 0xc9, 0x7d, 0x4b, 0xd7, 0xc3, 0x0c, 0x55, 0x9b, 0xf3, 0x6e, 0xc2, 0x1a, 0x53, 0x03, - 0xae, 0x9f, 0x43, 0x0c, 0x8f, 0x6f, 0x43, 0x4c, 0xe0, 0xe1, 0x52, 0x03, 0x5a, 0xc0, 0xd3, 0xf5, - 0x11, 0xeb, 0xb3, 0xae, 0x5f, 0x38, 0xdd, 0xc1, 0xf3, 0xe3, 0xcf, 0x62, 0x8a, 0xc7, 0x90, 0xeb, - 0xc9, 0x19, 0xdc, 0xbc, 0xc5, 0xb8, 0xb2, 0x14, 0xce, 0xaf, 0x46, 0x61, 0xe8, 0x36, 0x56, 0xb3, - 0x23, 0x4c, 0xcb, 0x7c, 0xca, 0x6c, 0x3b, 0xf9, 0x9e, 0x2a, 0xc0, 0x54, 0xc7, 0xe9, 0x0d, 0x3c, - 0xb4, 0x0f, 0x35, 0xa0, 0xf7, 0xb0, 0xca, 0x70, 0xa6, 0xe1, 0x0d, 0xd2, 0x64, 0x1e, 0xf3, 0x6f, - 0x10, 0xf1, 0x5d, 0xf9, 0x63, 0x0e, 0xa6, 0x64, 0x3c, 0xf9, 0x41, 0x83, 0x3c, 0x5a, 0x02, 0x59, - 0x8d, 0x13, 0x3f, 0xc2, 0x20, 0xf5, 0xb5, 0x74, 0xc1, 0x4a, 0x04, 0xdd, 0xf8, 0xe2, 0xb7, 0xbf, - 0xbf, 0x9f, 0x58, 0x25, 0x2b, 0x46, 0x8c, 0x21, 0xa3, 0x55, 0x18, 0x87, 0x58, 0xe7, 0x11, 0xf9, - 0x45, 0x83, 0xd9, 0x88, 0x65, 0x91, 0x8d, 0xb1, 0x94, 0xa3, 0x0c, 0x52, 0xaf, 0x5c, 0x04, 0x82, - 0x5a, 0xdf, 0x95, 0x5a, 0x2b, 0x64, 0x3d, 0x4e, 0xab, 0xef, 0x97, 0xe7, 0x24, 0xff, 0xa8, 0x41, - 0x1e, 0x2d, 0x2a, 0xa1, 0x99, 0x51, 0x0f, 0x4c, 0x68, 0xe6, 0x19, 0xd7, 0xa3, 0x15, 0x29, 0x70, - 0x8d, 0xdc, 0x8d, 0x13, 0x88, 0x26, 0xe8, 0x86, 0xa4, 0xfd, 0xac, 0x41, 0x1e, 0xed, 0x2b, 0x41, - 0x5a, 0xd4, 0x31, 0x13, 0xa4, 0x9d, 0x71, 0x44, 0xfa, 0x40, 0x4a, 0xdb, 0x20, 0x46, 0x9c, 0x34, - 0x57, 0x01, 0x86, 0xca, 0x8c, 0xc3, 0x5d, 0xeb, 0xe0, 0x88, 0x7c, 0xa3, 0x41, 0x56, 0x18, 0x1f, - 0x29, 0x25, 0xac, 0x58, 0xe0, 0xa9, 0xfa, 0x4a, 0x8a, 0x48, 0x94, 0x65, 0x48, 0x59, 0x2b, 0x64, - 0x39, 0x7e, 0x49, 0x9b, 0x91, 0x76, 0x7d, 0xa7, 0x41, 0x4e, 0x59, 0x25, 0xb9, 0x3b, 0x96, 0x26, - 0xe2, 0xc1, 0xfa, 0x6a, 0xaa, 0x58, 0x14, 0x55, 0x96, 0xa2, 0x4a, 0xe4, 0x4e, 0x9c, 0x28, 0xbc, - 0x31, 0x8d, 0x43, 0x71, 0xcd, 0xca, 0x25, 0x9c, 0x09, 0x2e, 0x6b, 0x72, 0x2f, 0x81, 0x2a, 0x6a, - 0xcf, 0x7a, 0x39, 0x6d, 0x78, 0xda, 0x03, 0xeb, 0xed, 0xd7, 0xd1, 0x2e, 0x7c, 0x7d, 0xc7, 0x1a, - 0x5c, 0x8f, 0xf1, 0x4f, 0xf2, 0x28, 0x1d, 0xfd, 0x48, 0xfb, 0xd6, 0x1f, 0x5f, 0x0e, 0x8c, 0x95, - 0x6c, 0xca, 0x4a, 0xde, 0x26, 0x95, 0xe4, 0x4a, 0xdc, 0x7a, 0x43, 0x24, 0x30, 0x0e, 0x95, 0x77, - 0x1c, 0x91, 0x5f, 0x35, 0xb8, 0x36, 0xd2, 0x68, 0xc9, 0xc3, 0x0b, 0x6a, 0x1a, 0xfa, 0xbb, 0xbe, - 0x79, 0x19, 0x28, 0x16, 0xf3, 0x44, 0x16, 0xf3, 0x80, 0xdc, 0x4f, 0x5d, 0x8c, 0xfc, 0xaf, 0x11, - 0xde, 0x42, 0x81, 0x39, 0x27, 0x6c, 0xa1, 0xb3, 0xde, 0x9f, 0xb0, 0x85, 0xce, 0x79, 0x7e, 0xf2, - 0x16, 0x52, 0xfa, 0xc2, 0x5b, 0xfc, 0x27, 0x0d, 0x60, 0x68, 0xd4, 0x24, 0x05, 0x63, 0xf8, 0x0d, - 0xa0, 0x1b, 0xa9, 0xe3, 0x51, 0xe2, 0xaa, 0x94, 0x78, 0x9b, 0xdc, 0x1a, 0x2f, 0x51, 0x3e, 0x0c, - 0xc8, 0xd7, 0x1a, 0xe4, 0x94, 0x8d, 0x27, 0xdc, 0x09, 0x91, 0x97, 0x43, 0xc2, 0x9d, 0x10, 0x7d, - 0x4f, 0xd0, 0x3b, 0x52, 0xd0, 0x12, 0x29, 0xc6, 0x09, 0x52, 0x2f, 0x07, 0xd9, 0xa8, 0xa1, 0xd7, - 0x27, 0x34, 0xea, 0xdc, 0xf3, 0x22, 0xa1, 0x51, 0xe7, 0x1f, 0x11, 0xc9, 0x8d, 0x72, 0x25, 0xa6, - 0x6e, 0x32, 0xdb, 0xae, 0x6e, 0xbd, 0x3a, 0x29, 0x6a, 0xc7, 0x27, 0x45, 0xed, 0xaf, 0x93, 0xa2, - 0xf6, 0xed, 0x69, 0x31, 0x73, 0x7c, 0x5a, 0xcc, 0xfc, 0x7e, 0x5a, 0xcc, 0x7c, 0xb6, 0xdc, 0xea, - 0x78, 0xed, 0x41, 0xa3, 0x6c, 0xf2, 0x2e, 0xba, 0x68, 0x28, 0xdf, 0xbe, 0xcc, 0xe8, 0x1d, 0xf4, - 0x2c, 0xb7, 0x91, 0x93, 0x7f, 0xce, 0xdf, 0xfa, 0x37, 0x00, 0x00, 0xff, 0xff, 0x3e, 0xd1, 0xd3, - 0x05, 0x30, 0x10, 0x00, 0x00, + // 1130 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x97, 0xcf, 0x6f, 0x1b, 0x45, + 0x14, 0xc7, 0xbd, 0x89, 0x13, 0x27, 0xaf, 0x0d, 0x0a, 0x83, 0xdb, 0x86, 0x2d, 0x72, 0xd2, 0x29, + 0x69, 0x9c, 0x26, 0xf5, 0x36, 0x46, 0xa5, 0xf4, 0x97, 0x50, 0x5c, 0xa9, 0x8a, 0x44, 0x85, 0xc0, + 0x81, 0x0b, 0x17, 0x33, 0x5e, 0x8f, 0xd6, 0x56, 0xd6, 0x3b, 0xae, 0x67, 0x1d, 0x25, 0x8a, 0x7a, + 0xe1, 0x80, 0x40, 0xe2, 0x00, 0xe2, 0x00, 0x42, 0x42, 0xea, 0x9f, 0xc0, 0x7f, 0x41, 0x2f, 0x48, + 0x15, 0x5c, 0x38, 0x21, 0x94, 0x70, 0xe0, 0xcf, 0x40, 0x33, 0xfb, 0xd6, 0xde, 0x4d, 0xbc, 0xd9, + 0x4d, 0xc4, 0x6d, 0x67, 0xfc, 0x7e, 0x7c, 0xe6, 0xcd, 0xcc, 0xfb, 0x8e, 0x81, 0x72, 0xbf, 0xcd, + 0xfb, 0xdd, 0x8e, 0xe7, 0x5b, 0x7c, 0xb7, 0x6b, 0xed, 0x6e, 0x30, 0xb7, 0xd7, 0x66, 0x1b, 0xd6, + 0xb3, 0x01, 0xef, 0xef, 0x57, 0x7a, 0x7d, 0xe1, 0x0b, 0x72, 0x79, 0x68, 0x53, 0xe1, 0xbb, 0xdd, + 0x4a, 0x68, 0x63, 0x16, 0x1d, 0xe1, 0x08, 0x6d, 0x62, 0xa9, 0xaf, 0xc0, 0xda, 0x7c, 0xcb, 0x11, + 0xc2, 0x71, 0xb9, 0xc5, 0x7a, 0x1d, 0x8b, 0x79, 0x9e, 0xf0, 0x99, 0xdf, 0x11, 0x9e, 0xc4, 0x5f, + 0x97, 0x12, 0xf2, 0xa9, 0xc0, 0xda, 0x82, 0xde, 0x83, 0x37, 0x3e, 0x56, 0xc9, 0x37, 0x6d, 0x5b, + 0x0c, 0x3c, 0xbf, 0xce, 0x9f, 0x0d, 0xb8, 0xf4, 0xc9, 0x02, 0x14, 0x58, 0xab, 0xd5, 0xe7, 0x52, + 0x2e, 0x18, 0x4b, 0x46, 0x79, 0xb6, 0x1e, 0x0e, 0xef, 0xcf, 0x7c, 0xf5, 0x62, 0x31, 0xf7, 0xef, + 0x8b, 0xc5, 0x1c, 0xb5, 0xa1, 0x18, 0x77, 0x95, 0x3d, 0xe1, 0x49, 0xae, 0x7c, 0x9b, 0xcc, 0x65, + 0x9e, 0xcd, 0x43, 0x5f, 0x1c, 0x92, 0xab, 0x30, 0x6b, 0x8b, 0x16, 0x6f, 0xb4, 0x99, 0x6c, 0x2f, + 0x4c, 0x2c, 0x19, 0xe5, 0x8b, 0xf5, 0x19, 0x35, 0xb1, 0xc5, 0x64, 0x9b, 0x14, 0x61, 0xca, 0x13, + 0xca, 0x69, 0x72, 0xc9, 0x28, 0xe7, 0xeb, 0xc1, 0x80, 0xbe, 0x0f, 0x6f, 0xea, 0x24, 0x8f, 0x85, + 0xec, 0x0a, 0x79, 0x0e, 0xca, 0x2f, 0x0d, 0x30, 0xc7, 0x45, 0x40, 0xd8, 0x65, 0x78, 0xcd, 0xd6, + 0x3f, 0x34, 0xe2, 0x91, 0xe6, 0x82, 0xd9, 0xcd, 0x60, 0x92, 0x98, 0x30, 0x23, 0x55, 0x52, 0xc5, + 0x37, 0xa1, 0xf9, 0x86, 0x63, 0x15, 0x82, 0x05, 0x51, 0x1b, 0xde, 0xa0, 0xdb, 0xe4, 0x7d, 0x5c, + 0xc1, 0x1c, 0xce, 0x7e, 0xa8, 0x27, 0x87, 0x95, 0xae, 0x05, 0xc5, 0x38, 0xcb, 0x1a, 0x6e, 0x63, + 0xa5, 0x87, 0xae, 0x69, 0x95, 0xa6, 0x1f, 0x60, 0xb2, 0x6d, 0x5f, 0xf4, 0x99, 0x93, 0x9e, 0x8c, + 0xcc, 0xc3, 0xe4, 0x0e, 0xdf, 0xd7, 0x6b, 0x9b, 0xad, 0xab, 0xcf, 0x48, 0xfa, 0x75, 0x4c, 0x3f, + 0x0c, 0x86, 0xe9, 0x8b, 0x30, 0xb5, 0xcb, 0xdc, 0x41, 0x98, 0x3c, 0x18, 0xd0, 0x77, 0x61, 0x1e, + 0xeb, 0xdd, 0x3a, 0xd3, 0x22, 0x57, 0xe0, 0xf5, 0x88, 0x1f, 0xa6, 0x20, 0x90, 0x57, 0x07, 0x44, + 0x7b, 0x5d, 0xac, 0xeb, 0x6f, 0x5a, 0x05, 0xa2, 0x0d, 0x3f, 0xd9, 0x7b, 0x2a, 0x1c, 0x19, 0xa6, + 0x20, 0x90, 0xd7, 0xc7, 0x2a, 0x88, 0xaf, 0xbf, 0x23, 0xc1, 0x9f, 0x60, 0x3d, 0x42, 0x1f, 0x0c, + 0x6f, 0x41, 0xde, 0x15, 0x8e, 0x82, 0x9a, 0x2c, 0x5f, 0xa8, 0x5e, 0xad, 0x8c, 0xbf, 0x7a, 0x95, + 0xa7, 0xc2, 0xa9, 0x6b, 0x43, 0x7a, 0x07, 0x2e, 0x61, 0x9c, 0x3a, 0xb7, 0x79, 0xa7, 0xe7, 0x67, + 0x4b, 0xff, 0x29, 0x5c, 0x3e, 0xee, 0x86, 0x04, 0x0f, 0xa0, 0xd0, 0x0f, 0xa6, 0xb4, 0xeb, 0x85, + 0xea, 0xb5, 0x24, 0x88, 0x91, 0x6f, 0xe8, 0x41, 0x97, 0xe1, 0x7a, 0x3c, 0xac, 0xac, 0xed, 0xd7, + 0x5c, 0x61, 0xef, 0x6c, 0xf1, 0x8e, 0xd3, 0x0e, 0xd9, 0x28, 0x87, 0xb7, 0x4f, 0x37, 0x43, 0x96, + 0x47, 0x30, 0x83, 0x91, 0xc3, 0x8a, 0x64, 0x80, 0x19, 0xba, 0xd0, 0x4d, 0xb8, 0x96, 0x90, 0x86, + 0xc9, 0x76, 0xb6, 0x3a, 0xd9, 0x40, 0x4f, 0x0b, 0xf1, 0xff, 0x70, 0x86, 0x7b, 0xa8, 0x03, 0x67, + 0x3f, 0x42, 0x9f, 0xe3, 0x1e, 0x46, 0xdc, 0x90, 0xe7, 0x09, 0x14, 0xfc, 0xbd, 0x46, 0xe4, 0x20, + 0xad, 0x24, 0xe2, 0xf4, 0x99, 0x27, 0x99, 0xad, 0x5a, 0xb4, 0x8a, 0x50, 0xcb, 0xbf, 0xfc, 0x6b, + 0x31, 0x57, 0x9f, 0xf6, 0xf5, 0xa9, 0xa4, 0x0b, 0xd1, 0x0c, 0x35, 0x57, 0x88, 0x6e, 0xb8, 0x83, + 0x16, 0x5c, 0x39, 0xf1, 0xcb, 0xe8, 0x12, 0x36, 0xd5, 0x04, 0x5e, 0x91, 0x60, 0x40, 0x8b, 0x78, + 0x47, 0x3e, 0x62, 0x7d, 0xd6, 0x0d, 0x17, 0x48, 0xb7, 0xf1, 0x16, 0x84, 0xb3, 0x18, 0xe2, 0x21, + 0x4c, 0xf7, 0xf4, 0x0c, 0x1e, 0xc1, 0x52, 0x12, 0x7e, 0xe0, 0x17, 0x52, 0x07, 0x3e, 0x74, 0x0b, + 0xa9, 0xb7, 0x95, 0xf4, 0xd8, 0x8f, 0x99, 0xeb, 0xa6, 0x77, 0x9b, 0x22, 0x4c, 0x75, 0xbc, 0xde, + 0xc0, 0x47, 0x11, 0x08, 0x06, 0xf4, 0x16, 0xae, 0x32, 0x1a, 0x69, 0xd4, 0x07, 0x5a, 0xcc, 0x67, + 0x61, 0x1f, 0x50, 0xdf, 0xd5, 0xdf, 0xe7, 0x61, 0x4a, 0xdb, 0x93, 0x1f, 0x0c, 0x28, 0x60, 0x63, + 0x27, 0x6b, 0x49, 0xf0, 0x63, 0x64, 0xce, 0x5c, 0xcf, 0x66, 0x1c, 0x40, 0xd0, 0x8d, 0x2f, 0xfe, + 0xf8, 0xe7, 0xfb, 0x89, 0x35, 0xb2, 0x6a, 0x25, 0xc8, 0x2a, 0x36, 0x7c, 0xeb, 0x00, 0xd7, 0xf9, + 0x9c, 0xfc, 0x62, 0xc0, 0x5c, 0x4c, 0x78, 0xc8, 0xc6, 0xa9, 0x29, 0xc7, 0xc9, 0x9c, 0x59, 0x3d, + 0x8b, 0x0b, 0xb2, 0xbe, 0xa7, 0x59, 0xab, 0xe4, 0x76, 0x12, 0x6b, 0xa8, 0x7a, 0x27, 0x90, 0x7f, + 0x34, 0xa0, 0x80, 0x42, 0x93, 0x52, 0xcc, 0xb8, 0x92, 0xa5, 0x14, 0xf3, 0x98, 0x76, 0xd1, 0xaa, + 0x06, 0x5c, 0x27, 0x37, 0x93, 0x00, 0x51, 0xca, 0x64, 0x04, 0xed, 0x67, 0x03, 0x0a, 0x28, 0x42, + 0x29, 0x68, 0x71, 0xdd, 0x4b, 0x41, 0x3b, 0xa6, 0x6b, 0xf4, 0xae, 0x46, 0xdb, 0x20, 0x56, 0x12, + 0x9a, 0x0c, 0x1c, 0x46, 0x64, 0xd6, 0xc1, 0x0e, 0xdf, 0x7f, 0x4e, 0xbe, 0x31, 0x20, 0xaf, 0xe4, + 0x8b, 0x94, 0x53, 0x76, 0x6c, 0xa8, 0x8c, 0xe6, 0x6a, 0x06, 0x4b, 0xc4, 0xb2, 0x34, 0xd6, 0x2a, + 0x59, 0x49, 0xde, 0xd2, 0x56, 0xac, 0x5c, 0xdf, 0x19, 0x30, 0x1d, 0x08, 0x1e, 0xb9, 0x79, 0x6a, + 0x9a, 0x98, 0x92, 0x9a, 0x6b, 0x99, 0x6c, 0x11, 0xaa, 0xa2, 0xa1, 0xca, 0xe4, 0x46, 0x12, 0x14, + 0x76, 0x46, 0xeb, 0x40, 0xb5, 0x53, 0xbd, 0x85, 0xb3, 0xc3, 0xa6, 0x4c, 0x6e, 0xa5, 0xa4, 0x8a, + 0x8b, 0xac, 0x59, 0xc9, 0x6a, 0x9e, 0xf5, 0xc2, 0xfa, 0x7b, 0x0d, 0x94, 0x85, 0x90, 0xef, 0x57, + 0x03, 0xae, 0x24, 0xe8, 0x24, 0x79, 0x90, 0x2d, 0xfd, 0x58, 0x11, 0x36, 0x1f, 0x9e, 0xcf, 0xf9, + 0xec, 0x2b, 0x91, 0x8d, 0xa6, 0x0a, 0x40, 0x7e, 0x33, 0xe0, 0xd2, 0x58, 0x1d, 0x25, 0xf7, 0xce, + 0x88, 0x32, 0x92, 0x6f, 0xf3, 0xfe, 0x79, 0x5c, 0x71, 0x0d, 0x8f, 0xf4, 0x1a, 0xee, 0x92, 0x3b, + 0x99, 0xd7, 0xa0, 0xff, 0x28, 0x44, 0x4f, 0xce, 0x50, 0x7b, 0x53, 0x4e, 0xce, 0x71, 0x69, 0x4f, + 0x39, 0x39, 0x27, 0x24, 0x3d, 0xbd, 0xde, 0x01, 0x5f, 0xf4, 0x64, 0xff, 0x64, 0x00, 0x8c, 0xf4, + 0x99, 0x64, 0xc8, 0x18, 0x95, 0x78, 0xd3, 0xca, 0x6c, 0x8f, 0x88, 0x6b, 0x1a, 0x71, 0x99, 0x5c, + 0x3f, 0x1d, 0x51, 0xbf, 0x07, 0xc8, 0xd7, 0x06, 0x4c, 0x07, 0xea, 0x9d, 0xd2, 0x0a, 0x62, 0x0f, + 0x86, 0x94, 0x56, 0x10, 0x7f, 0x46, 0xd0, 0x1b, 0x1a, 0x68, 0x89, 0x94, 0x92, 0x80, 0x82, 0x07, + 0x83, 0x2e, 0xd4, 0x48, 0xe2, 0x53, 0x0a, 0x75, 0xe2, 0x55, 0x91, 0x52, 0xa8, 0x93, 0x6f, 0x87, + 0xf4, 0x42, 0x49, 0xed, 0xd3, 0xb0, 0x99, 0xeb, 0xd6, 0x36, 0x5f, 0x1e, 0x96, 0x8c, 0x57, 0x87, + 0x25, 0xe3, 0xef, 0xc3, 0x92, 0xf1, 0xed, 0x51, 0x29, 0xf7, 0xea, 0xa8, 0x94, 0xfb, 0xf3, 0xa8, + 0x94, 0xfb, 0x6c, 0xc5, 0xe9, 0xf8, 0xed, 0x41, 0xb3, 0x62, 0x8b, 0x2e, 0x8a, 0x67, 0x24, 0xde, + 0x9e, 0x8e, 0xe8, 0xef, 0xf7, 0xb8, 0x6c, 0x4e, 0xeb, 0x7f, 0xd6, 0xef, 0xfc, 0x17, 0x00, 0x00, + 0xff, 0xff, 0x0c, 0x87, 0xad, 0x46, 0xed, 0x0f, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -2326,11 +2314,6 @@ func (m *QueryTxReceiptsByBlockHeightRequest) MarshalToSizedBuffer(dAtA []byte) _ = i var l int _ = l - if m.Height != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.Height)) - i-- - dAtA[i] = 0x8 - } return len(dAtA) - i, nil } @@ -2525,11 +2508,6 @@ func (m *QueryBlockBloomRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) _ = i var l int _ = l - if m.Height != 0 { - i = encodeVarintQuery(dAtA, i, uint64(m.Height)) - i-- - dAtA[i] = 0x8 - } return len(dAtA) - i, nil } @@ -2904,9 +2882,6 @@ func (m *QueryTxReceiptsByBlockHeightRequest) Size() (n int) { } var l int _ = l - if m.Height != 0 { - n += 1 + sovQuery(uint64(m.Height)) - } return n } @@ -2987,9 +2962,6 @@ func (m *QueryBlockBloomRequest) Size() (n int) { } var l int _ = l - if m.Height != 0 { - n += 1 + sovQuery(uint64(m.Height)) - } return n } @@ -4412,25 +4384,6 @@ func (m *QueryTxReceiptsByBlockHeightRequest) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: QueryTxReceiptsByBlockHeightRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) - } - m.Height = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Height |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) @@ -4915,25 +4868,6 @@ func (m *QueryBlockBloomRequest) Unmarshal(dAtA []byte) error { return fmt.Errorf("proto: QueryBlockBloomRequest: illegal tag %d (wire type %d)", fieldNum, wire) } switch fieldNum { - case 1: - if wireType != 0 { - return fmt.Errorf("proto: wrong wireType = %d for field Height", wireType) - } - m.Height = 0 - for shift := uint(0); ; shift += 7 { - if shift >= 64 { - return ErrIntOverflowQuery - } - if iNdEx >= l { - return io.ErrUnexpectedEOF - } - b := dAtA[iNdEx] - iNdEx++ - m.Height |= int64(b&0x7F) << shift - if b < 0x80 { - break - } - } default: iNdEx = preIndex skippy, err := skipQuery(dAtA[iNdEx:]) diff --git a/x/evm/types/query.pb.gw.go b/x/evm/types/query.pb.gw.go index 834bb784..fb2ce0e7 100644 --- a/x/evm/types/query.pb.gw.go +++ b/x/evm/types/query.pb.gw.go @@ -435,24 +435,6 @@ func request_Query_TxReceiptsByBlockHeight_0(ctx context.Context, marshaler runt var protoReq QueryTxReceiptsByBlockHeightRequest var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["height"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height") - } - - protoReq.Height, err = runtime.Int64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err) - } - msg, err := client.TxReceiptsByBlockHeight(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -462,24 +444,6 @@ func local_request_Query_TxReceiptsByBlockHeight_0(ctx context.Context, marshale var protoReq QueryTxReceiptsByBlockHeightRequest var metadata runtime.ServerMetadata - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["height"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "height") - } - - protoReq.Height, err = runtime.Int64(val) - - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "height", err) - } - msg, err := server.TxReceiptsByBlockHeight(ctx, &protoReq) return msg, metadata, err @@ -593,21 +557,10 @@ func local_request_Query_BlockLogs_0(ctx context.Context, marshaler runtime.Mars } -var ( - filter_Query_BlockBloom_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - func request_Query_BlockBloom_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq QueryBlockBloomRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_BlockBloom_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := client.BlockBloom(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -617,13 +570,6 @@ func local_request_Query_BlockBloom_0(ctx context.Context, marshaler runtime.Mar var protoReq QueryBlockBloomRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Query_BlockBloom_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - msg, err := server.BlockBloom(ctx, &protoReq) return msg, metadata, err @@ -1268,7 +1214,7 @@ var ( pattern_Query_TxReceipt_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"ethermint", "evm", "v1alpha1", "tx_receipt", "hash"}, "", runtime.AssumeColonVerbOpt(true))) - pattern_Query_TxReceiptsByBlockHeight_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"ethermint", "evm", "v1alpha1", "tx_receipts_block", "height"}, "", runtime.AssumeColonVerbOpt(true))) + pattern_Query_TxReceiptsByBlockHeight_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"ethermint", "evm", "v1alpha1", "tx_receipts_block"}, "", runtime.AssumeColonVerbOpt(true))) pattern_Query_TxReceiptsByBlockHash_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4}, []string{"ethermint", "evm", "v1alpha1", "tx_receipts_block_hash", "hash"}, "", runtime.AssumeColonVerbOpt(true))) diff --git a/x/evm/types/state_object.go b/x/evm/types/state_object.go index 39a68765..097f5c16 100644 --- a/x/evm/types/state_object.go +++ b/x/evm/types/state_object.go @@ -10,7 +10,7 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" - "github.com/cosmos/ethermint/types" + ethermint "github.com/cosmos/ethermint/types" ethcmn "github.com/ethereum/go-ethereum/common" ethstate "github.com/ethereum/go-ethereum/core/state" @@ -53,7 +53,7 @@ type StateObject interface { // Account values can be accessed and modified through the object. // Finally, call CommitTrie to write the modified storage trie into a database. type stateObject struct { - code types.Code // contract bytecode, which gets set when code is loaded + code ethermint.Code // contract bytecode, which gets set when code is loaded // State objects are used by the consensus core and VM which are // unable to deal with database-level errors. Any error that occurs // during a database read is memoized here and will eventually be returned @@ -64,7 +64,7 @@ type stateObject struct { // DB error dbErr error stateDB *CommitStateDB - account *types.EthAccount + account *ethermint.EthAccount // balance represents the amount of the EVM denom token that an account holds balance sdk.Int @@ -83,7 +83,7 @@ type stateObject struct { } func newStateObject(db *CommitStateDB, accProto authtypes.AccountI, balance sdk.Int) *stateObject { - ethAccount, ok := accProto.(*types.EthAccount) + ethAccount, ok := accProto.(*ethermint.EthAccount) if !ok { panic(fmt.Sprintf("invalid account type for state object: %T", accProto)) } @@ -251,7 +251,7 @@ func (so *stateObject) commitState() { key := ethcmn.HexToHash(state.Key) value := ethcmn.HexToHash(state.Value) // delete empty values from the store - if IsEmptyHash(state.Value) { + if ethermint.IsEmptyHash(state.Value) { store.Delete(key.Bytes()) } @@ -263,7 +263,7 @@ func (so *stateObject) commitState() { continue } - if IsEmptyHash(state.Value) { + if ethermint.IsEmptyHash(state.Value) { delete(so.keyToOriginStorageIndex, key) continue } diff --git a/x/evm/types/utils.go b/x/evm/types/utils.go index 11db906d..dfd7fc8a 100644 --- a/x/evm/types/utils.go +++ b/x/evm/types/utils.go @@ -1,8 +1,6 @@ package types import ( - "bytes" - log "github.com/xlab/suplog" "github.com/gogo/protobuf/proto" @@ -66,20 +64,3 @@ func DecodeTransactionLogs(data []byte) (TransactionLogs, error) { } return logs, nil } - -// ---------------------------------------------------------------------------- -// Auxiliary - -// IsEmptyHash returns true if the hash corresponds to an empty ethereum hex hash. -func IsEmptyHash(hash string) bool { - return bytes.Equal(ethcmn.HexToHash(hash).Bytes(), ethcmn.Hash{}.Bytes()) -} - -// IsZeroAddress returns true if the address corresponds to an empty ethereum hex address. -func IsZeroAddress(address string) bool { - if address == "" { - return true - } - - return bytes.Equal(ethcmn.HexToAddress(address).Bytes(), ethcmn.Address{}.Bytes()) -}