From 244d83666936fb7ee4b8704bd4a18bb07954487f Mon Sep 17 00:00:00 2001 From: noot <36753753+noot@users.noreply.github.com> Date: Tue, 15 Sep 2020 14:42:06 -0400 Subject: [PATCH] add rpc logs, ignore block bloom errors (#492) --- rpc/eth_api.go | 42 +++++++++++++++++++++++++++++++++++++++--- x/evm/keeper/keeper.go | 7 ++++--- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/rpc/eth_api.go b/rpc/eth_api.go index d3904663..3974c066 100644 --- a/rpc/eth_api.go +++ b/rpc/eth_api.go @@ -4,8 +4,8 @@ import ( "bytes" "errors" "fmt" - "log" "math/big" + "os" "strconv" "sync" @@ -20,6 +20,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/crypto/merkle" + "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/rpc/client" tmtypes "github.com/tendermint/tendermint/types" @@ -42,6 +43,7 @@ import ( // PublicEthAPI is the eth_ prefixed set of APIs in the Web3 JSON-RPC spec. type PublicEthAPI struct { cliCtx context.CLIContext + logger log.Logger backend Backend keys []crypto.PrivKeySecp256k1 nonceLock *AddrLocker @@ -54,6 +56,7 @@ func NewPublicEthAPI(cliCtx context.CLIContext, backend Backend, nonceLock *Addr return &PublicEthAPI{ cliCtx: cliCtx, + logger: log.NewTMLogger(log.NewSyncWriter(os.Stdout)).With("module", "json-rpc"), backend: backend, keys: key, nonceLock: nonceLock, @@ -62,11 +65,14 @@ func NewPublicEthAPI(cliCtx context.CLIContext, backend Backend, nonceLock *Addr // ProtocolVersion returns the supported Ethereum protocol version. func (e *PublicEthAPI) ProtocolVersion() hexutil.Uint { + e.logger.Debug("eth_protocolVersion") return hexutil.Uint(version.ProtocolVersion) } // ChainId returns the chain's identifier in hex format func (e *PublicEthAPI) ChainId() (hexutil.Uint, error) { // nolint + e.logger.Debug("eth_chainId") + // parse the chainID from a integer string intChainID, err := strconv.ParseUint(e.cliCtx.ChainID, 0, 64) if err != nil { @@ -79,6 +85,8 @@ func (e *PublicEthAPI) ChainId() (hexutil.Uint, error) { // nolint // Syncing returns whether or not the current node is syncing with other peers. Returns false if not, or a struct // outlining the state of the sync if it is. func (e *PublicEthAPI) Syncing() (interface{}, error) { + e.logger.Debug("eth_syncing") + status, err := e.cliCtx.Client.Status() if err != nil { return false, err @@ -99,6 +107,8 @@ func (e *PublicEthAPI) Syncing() (interface{}, error) { // Coinbase is the address that staking rewards will be send to (alias for Etherbase). func (e *PublicEthAPI) Coinbase() (common.Address, error) { + e.logger.Debug("eth_coinbase") + node, err := e.cliCtx.GetNode() if err != nil { return common.Address{}, err @@ -114,22 +124,26 @@ func (e *PublicEthAPI) Coinbase() (common.Address, error) { // Mining returns whether or not this node is currently mining. Always false. func (e *PublicEthAPI) Mining() bool { + e.logger.Debug("eth_mining") return false } // Hashrate returns the current node's hashrate. Always 0. func (e *PublicEthAPI) Hashrate() hexutil.Uint64 { + e.logger.Debug("eth_hashrate") return 0 } // GasPrice returns the current gas price based on Ethermint's gas price oracle. func (e *PublicEthAPI) GasPrice() *hexutil.Big { + e.logger.Debug("eth_gasPrice") out := big.NewInt(0) return (*hexutil.Big)(out) } // Accounts returns the list of accounts available to this node. func (e *PublicEthAPI) Accounts() ([]common.Address, error) { + e.logger.Debug("eth_accounts") e.keybaseLock.Lock() addresses := make([]common.Address, 0) // return [] instead of nil if empty @@ -162,11 +176,13 @@ func (e *PublicEthAPI) Accounts() ([]common.Address, error) { // BlockNumber returns the current block number. func (e *PublicEthAPI) BlockNumber() (hexutil.Uint64, error) { + e.logger.Debug("eth_blockNumber") return e.backend.BlockNumber() } // GetBalance returns the provided account's balance up to the provided block number. func (e *PublicEthAPI) GetBalance(address common.Address, blockNum BlockNumber) (*hexutil.Big, error) { + e.logger.Debug("eth_getBalance", "address", address, "block number", blockNum) ctx := e.cliCtx.WithHeight(blockNum.Int64()) res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/balance/%s", evmtypes.ModuleName, address.Hex()), nil) if err != nil { @@ -185,6 +201,7 @@ func (e *PublicEthAPI) GetBalance(address common.Address, blockNum BlockNumber) // GetStorageAt returns the contract storage at the given address, block number, and key. func (e *PublicEthAPI) GetStorageAt(address common.Address, key string, blockNum BlockNumber) (hexutil.Bytes, error) { + e.logger.Debug("eth_getStorageAt", "address", address, "key", key, "block number", blockNum) ctx := e.cliCtx.WithHeight(blockNum.Int64()) res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/storage/%s/%s", evmtypes.ModuleName, address.Hex(), key), nil) if err != nil { @@ -198,6 +215,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 BlockNumber) (*hexutil.Uint64, error) { + e.logger.Debug("eth_getTransactionCount", "address", address, "block number", blockNum) ctx := e.cliCtx.WithHeight(blockNum.Int64()) // Get nonce (sequence) from account @@ -222,6 +240,7 @@ func (e *PublicEthAPI) GetTransactionCount(address common.Address, blockNum Bloc // GetBlockTransactionCountByHash returns the number of transactions in the block identified by hash. func (e *PublicEthAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Uint { + e.logger.Debug("eth_getBlockTransactionCountByHash", "hash", hash) res, _, err := e.cliCtx.Query(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryHashToHeight, hash.Hex())) if err != nil { // Return nil if block does not exist @@ -235,6 +254,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 BlockNumber) *hexutil.Uint { + e.logger.Debug("eth_getBlockTransactionCountByNumber", "block number", blockNum) height := blockNum.Int64() return e.getBlockTransactionCountByNumber(height) } @@ -262,6 +282,7 @@ func (e *PublicEthAPI) GetUncleCountByBlockNumber(blockNum BlockNumber) hexutil. // GetCode returns the contract code at the given address and block number. func (e *PublicEthAPI) GetCode(address common.Address, blockNumber BlockNumber) (hexutil.Bytes, error) { + e.logger.Debug("eth_getCode", "address", address, "block number", blockNumber) ctx := e.cliCtx.WithHeight(blockNumber.Int64()) res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryCode, address.Hex()), nil) if err != nil { @@ -275,12 +296,14 @@ func (e *PublicEthAPI) GetCode(address common.Address, blockNumber BlockNumber) // GetTransactionLogs returns the logs given a transaction hash. func (e *PublicEthAPI) GetTransactionLogs(txHash common.Hash) ([]*ethtypes.Log, error) { + e.logger.Debug("eth_getTransactionLogs", "hash", txHash) return e.backend.GetTransactionLogs(txHash) } // ExportAccount exports an account's balance, code, and storage at the given block number // TODO: deprecate this once the export genesis command works func (e *PublicEthAPI) ExportAccount(address common.Address, blockNumber BlockNumber) (string, error) { + e.logger.Debug("eth_exportAccount", "address", address, "block number", blockNumber) ctx := e.cliCtx.WithHeight(blockNumber.Int64()) res, _, err := ctx.QueryWithData(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryExportAccount, address.Hex()), nil) @@ -304,6 +327,7 @@ func checkKeyInKeyring(keys []crypto.PrivKeySecp256k1, address common.Address) ( // Sign signs the provided data using the private key of address via Geth's signature standard. func (e *PublicEthAPI) Sign(address common.Address, data hexutil.Bytes) (hexutil.Bytes, error) { + e.logger.Debug("eth_sign", "address", address, "data", data) // TODO: Change this functionality to find an unlocked account by address key, exist := checkKeyInKeyring(e.keys, address) @@ -322,6 +346,7 @@ func (e *PublicEthAPI) Sign(address common.Address, data hexutil.Bytes) (hexutil // SendTransaction sends an Ethereum transaction. func (e *PublicEthAPI) SendTransaction(args params.SendTxArgs) (common.Hash, error) { + e.logger.Debug("eth_sendTransaction", "args", args) // TODO: Change this functionality to find an unlocked account by address key, exist := checkKeyInKeyring(e.keys, args.From) @@ -374,6 +399,7 @@ func (e *PublicEthAPI) SendTransaction(args params.SendTxArgs) (common.Hash, err // SendRawTransaction send a raw Ethereum transaction. func (e *PublicEthAPI) SendRawTransaction(data hexutil.Bytes) (common.Hash, error) { + e.logger.Debug("eth_sendRawTransaction", "data", data) tx := new(evmtypes.MsgEthereumTx) // RLP decode raw transaction bytes @@ -411,7 +437,8 @@ type CallArgs struct { } // Call performs a raw contract call. -func (e *PublicEthAPI) Call(args CallArgs, blockNr BlockNumber, overrides *map[common.Address]account) (hexutil.Bytes, error) { +func (e *PublicEthAPI) Call(args CallArgs, blockNr BlockNumber, _ *map[common.Address]account) (hexutil.Bytes, error) { + e.logger.Debug("eth_call", "args", args, "block number", blockNr) simRes, err := e.doCall(args, blockNr, big.NewInt(emint.DefaultRPCGasLimit)) if err != nil { return []byte{}, err @@ -471,7 +498,7 @@ func (e *PublicEthAPI) doCall( gas = uint64(*args.Gas) } if globalGasCap != nil && globalGasCap.Uint64() < gas { - log.Println("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap) + e.logger.Debug("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap) gas = globalGasCap.Uint64() } @@ -531,6 +558,7 @@ func (e *PublicEthAPI) doCall( // It adds 1,000 gas to the returned value instead of using the gas adjustment // param from the SDK. func (e *PublicEthAPI) EstimateGas(args CallArgs) (hexutil.Uint64, error) { + e.logger.Debug("eth_estimateGas", "args", args) simResponse, err := e.doCall(args, 0, big.NewInt(emint.DefaultRPCGasLimit)) if err != nil { return 0, err @@ -545,11 +573,13 @@ func (e *PublicEthAPI) EstimateGas(args CallArgs) (hexutil.Uint64, error) { // GetBlockByHash returns the block identified by hash. func (e *PublicEthAPI) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error) { + e.logger.Debug("eth_getBlockByHash", "hash", hash, "full", fullTx) return e.backend.GetBlockByHash(hash, fullTx) } // GetBlockByNumber returns the block identified by number. func (e *PublicEthAPI) GetBlockByNumber(blockNum BlockNumber, fullTx bool) (map[string]interface{}, error) { + e.logger.Debug("eth_getBlockByNumber", "number", blockNum, "full", fullTx) return e.backend.GetBlockByNumber(blockNum, fullTx) } @@ -668,6 +698,7 @@ func newRPCTransaction(tx evmtypes.MsgEthereumTx, txHash, blockHash common.Hash, // GetTransactionByHash returns the transaction identified by hash. func (e *PublicEthAPI) GetTransactionByHash(hash common.Hash) (*Transaction, error) { + e.logger.Debug("eth_getTransactionByHash", "hash", hash) tx, err := e.cliCtx.Client.Tx(hash.Bytes(), false) if err != nil { // Return nil for transaction when not found @@ -692,6 +723,7 @@ func (e *PublicEthAPI) GetTransactionByHash(hash common.Hash) (*Transaction, err // GetTransactionByBlockHashAndIndex returns the transaction identified by hash and index. func (e *PublicEthAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx hexutil.Uint) (*Transaction, error) { + e.logger.Debug("eth_getTransactionByHashAndIndex", "hash", hash, "index", idx) res, _, err := e.cliCtx.Query(fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryHashToHeight, hash.Hex())) if err != nil { return nil, err @@ -704,6 +736,7 @@ func (e *PublicEthAPI) GetTransactionByBlockHashAndIndex(hash common.Hash, idx h // GetTransactionByBlockNumberAndIndex returns the transaction identified by number and index. func (e *PublicEthAPI) GetTransactionByBlockNumberAndIndex(blockNum BlockNumber, idx hexutil.Uint) (*Transaction, error) { + e.logger.Debug("eth_getTransactionByBlockNumberAndIndex", "number", blockNum, "index", idx) value := blockNum.Int64() return e.getTransactionByBlockNumberAndIndex(value, idx) } @@ -730,6 +763,7 @@ func (e *PublicEthAPI) getTransactionByBlockNumberAndIndex(number int64, idx hex // GetTransactionReceipt returns the transaction receipt identified by hash. func (e *PublicEthAPI) GetTransactionReceipt(hash common.Hash) (map[string]interface{}, error) { + e.logger.Debug("eth_getTransactionReceipt", "hash", hash) tx, err := e.cliCtx.Client.Tx(hash.Bytes(), false) if err != nil { // Return nil for transaction when not found @@ -803,6 +837,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() ([]*Transaction, error) { + e.logger.Debug("eth_getPendingTransactions") return e.backend.PendingTransactions() } @@ -839,6 +874,7 @@ type StorageResult struct { // GetProof returns an account object with proof and any storage proofs func (e *PublicEthAPI) GetProof(address common.Address, storageKeys []string, block BlockNumber) (*AccountResult, error) { + e.logger.Debug("eth_getProof", "address", address, "keys", storageKeys, "number", block) e.cliCtx = e.cliCtx.WithHeight(int64(block)) path := fmt.Sprintf("custom/%s/%s/%s", evmtypes.ModuleName, evmtypes.QueryAccount, address.Hex()) diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 9706d16d..18bfd945 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -96,11 +96,12 @@ func (k Keeper) SetBlockHash(ctx sdk.Context, hash []byte, height int64) { // GetBlockBloom gets bloombits from block height func (k Keeper) GetBlockBloom(ctx sdk.Context, height int64) (ethtypes.Bloom, bool) { store := prefix.NewStore(ctx.KVStore(k.storeKey), types.KeyPrefixBloom) - bz := store.Get(types.BloomKey(height)) - if len(bz) == 0 { - return ethtypes.Bloom{}, false + has := store.Has(types.BloomKey(height)) + if !has { + return ethtypes.Bloom{}, true // TODO: sometimes bloom cannot be found, fix this } + bz := store.Get(types.BloomKey(height)) return ethtypes.BytesToBloom(bz), true }