Sync from fork #74
@ -45,6 +45,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
|||||||
|
|
||||||
### API Breaking
|
### API Breaking
|
||||||
|
|
||||||
|
* (rpc) [\#1126](https://github.com/evmos/ethermint/pull/1126) Make some JSON-RPC APIS work for pruned nodes.
|
||||||
* (rpc) [\#1143](https://github.com/evmos/ethermint/pull/1143) Restrict unprotected txs on the node JSON-RPC configuration.
|
* (rpc) [\#1143](https://github.com/evmos/ethermint/pull/1143) Restrict unprotected txs on the node JSON-RPC configuration.
|
||||||
* (all) [\#1137](https://github.com/evmos/ethermint/pull/1137) Rename go module to `evmos/ethermint`
|
* (all) [\#1137](https://github.com/evmos/ethermint/pull/1137) Rename go module to `evmos/ethermint`
|
||||||
|
|
||||||
|
@ -52,6 +52,7 @@ type EVMBackend interface {
|
|||||||
// Blockchain API
|
// Blockchain API
|
||||||
BlockNumber() (hexutil.Uint64, error)
|
BlockNumber() (hexutil.Uint64, error)
|
||||||
GetTendermintBlockByNumber(blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error)
|
GetTendermintBlockByNumber(blockNum types.BlockNumber) (*tmrpctypes.ResultBlock, error)
|
||||||
|
GetTendermintBlockResultByNumber(height *int64) (*tmrpctypes.ResultBlockResults, error)
|
||||||
GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error)
|
GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error)
|
||||||
GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error)
|
GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error)
|
||||||
GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error)
|
GetBlockByHash(hash common.Hash, fullTx bool) (map[string]interface{}, error)
|
||||||
@ -68,7 +69,7 @@ type EVMBackend interface {
|
|||||||
GetTxByEthHash(txHash common.Hash) (*tmrpctypes.ResultTx, error)
|
GetTxByEthHash(txHash common.Hash) (*tmrpctypes.ResultTx, error)
|
||||||
GetTxByTxIndex(height int64, txIndex uint) (*tmrpctypes.ResultTx, error)
|
GetTxByTxIndex(height int64, txIndex uint) (*tmrpctypes.ResultTx, error)
|
||||||
EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *types.BlockNumber) (hexutil.Uint64, error)
|
EstimateGas(args evmtypes.TransactionArgs, blockNrOptional *types.BlockNumber) (hexutil.Uint64, error)
|
||||||
BaseFee(height int64) (*big.Int, error)
|
BaseFee(blockRes *tmrpctypes.ResultBlockResults) (*big.Int, error)
|
||||||
GlobalMinGasPrice() (sdk.Dec, error)
|
GlobalMinGasPrice() (sdk.Dec, error)
|
||||||
|
|
||||||
// Fee API
|
// Fee API
|
||||||
|
@ -70,7 +70,13 @@ func (b *Backend) GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := b.EthBlockFromTendermint(resBlock, fullTx)
|
blockRes, err := b.GetTendermintBlockResultByNumber(&resBlock.Block.Height)
|
||||||
|
if err != nil {
|
||||||
|
b.logger.Debug("failed to fetch block result from Tendermint", "height", blockNum, "error", err.Error())
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := b.EthBlockFromTendermint(resBlock, blockRes, fullTx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.logger.Debug("EthBlockFromTendermint failed", "height", blockNum, "error", err.Error())
|
b.logger.Debug("EthBlockFromTendermint failed", "height", blockNum, "error", err.Error())
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -85,12 +91,19 @@ func (b *Backend) GetBlockByHash(hash common.Hash, fullTx bool) (map[string]inte
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if resBlock == nil {
|
if resBlock == nil {
|
||||||
// block not found
|
// block not found
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.EthBlockFromTendermint(resBlock, fullTx)
|
blockRes, err := b.GetTendermintBlockResultByNumber(&resBlock.Block.Height)
|
||||||
|
if err != nil {
|
||||||
|
b.logger.Debug("failed to fetch block result from Tendermint", "block-hash", hash.String(), "error", err.Error())
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.EthBlockFromTendermint(resBlock, blockRes, fullTx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockByNumber returns the block identified by number.
|
// BlockByNumber returns the block identified by number.
|
||||||
@ -101,10 +114,15 @@ func (b *Backend) BlockByNumber(blockNum types.BlockNumber) (*ethtypes.Block, er
|
|||||||
}
|
}
|
||||||
if resBlock == nil {
|
if resBlock == nil {
|
||||||
// block not found
|
// block not found
|
||||||
return nil, errors.Errorf("block not found for height %d", blockNum)
|
return nil, fmt.Errorf("block not found for height %d", blockNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.EthBlockFromTm(resBlock)
|
blockRes, err := b.GetTendermintBlockResultByNumber(&resBlock.Block.Height)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height)
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.EthBlockFromTm(resBlock, blockRes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BlockByHash returns the block identified by hash.
|
// BlockByHash returns the block identified by hash.
|
||||||
@ -115,29 +133,34 @@ func (b *Backend) BlockByHash(hash common.Hash) (*ethtypes.Block, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if resBlock == nil || resBlock.Block == nil {
|
if resBlock == nil || resBlock.Block == nil {
|
||||||
return nil, errors.Errorf("block not found for hash %s", hash)
|
return nil, fmt.Errorf("block not found for hash %s", hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
return b.EthBlockFromTm(resBlock)
|
blockRes, err := b.GetTendermintBlockResultByNumber(&resBlock.Block.Height)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("block result not found for hash %s", hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) EthBlockFromTm(resBlock *tmrpctypes.ResultBlock) (*ethtypes.Block, error) {
|
return b.EthBlockFromTm(resBlock, blockRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *Backend) EthBlockFromTm(resBlock *tmrpctypes.ResultBlock, blockRes *tmrpctypes.ResultBlockResults) (*ethtypes.Block, error) {
|
||||||
block := resBlock.Block
|
block := resBlock.Block
|
||||||
height := block.Height
|
height := block.Height
|
||||||
bloom, err := b.BlockBloom(&height)
|
bloom, err := b.BlockBloom(blockRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.logger.Debug("HeaderByNumber BlockBloom failed", "height", height)
|
b.logger.Debug("HeaderByNumber BlockBloom failed", "height", height)
|
||||||
}
|
}
|
||||||
|
|
||||||
baseFee, err := b.BaseFee(height)
|
baseFee, err := b.BaseFee(blockRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.logger.Debug("HeaderByNumber BaseFee failed", "height", height, "error", err.Error())
|
// handle error for pruned node and log
|
||||||
return nil, err
|
b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", height, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ethHeader := types.EthHeaderFromTendermint(block.Header, bloom, baseFee)
|
ethHeader := types.EthHeaderFromTendermint(block.Header, bloom, baseFee)
|
||||||
|
|
||||||
resBlockResult, err := b.clientCtx.Client.BlockResults(b.ctx, &block.Height)
|
resBlockResult, err := b.GetTendermintBlockResultByNumber(&block.Height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -179,6 +202,11 @@ func (b *Backend) GetTendermintBlockByNumber(blockNum types.BlockNumber) (*tmrpc
|
|||||||
return resBlock, nil
|
return resBlock, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTendermintBlockResultByNumber returns a Tendermint-formatted block result by block number
|
||||||
|
func (b *Backend) GetTendermintBlockResultByNumber(height *int64) (*tmrpctypes.ResultBlockResults, error) {
|
||||||
|
return b.clientCtx.Client.BlockResults(b.ctx, height)
|
||||||
|
}
|
||||||
|
|
||||||
// GetTendermintBlockByHash returns a Tendermint format block by block number
|
// GetTendermintBlockByHash returns a Tendermint format block by block number
|
||||||
func (b *Backend) GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) {
|
func (b *Backend) GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.ResultBlock, error) {
|
||||||
resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, blockHash.Bytes())
|
resBlock, err := b.clientCtx.Client.BlockByHash(b.ctx, blockHash.Bytes())
|
||||||
@ -196,12 +224,8 @@ func (b *Backend) GetTendermintBlockByHash(blockHash common.Hash) (*tmrpctypes.R
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BlockBloom query block bloom filter from block results
|
// BlockBloom query block bloom filter from block results
|
||||||
func (b *Backend) BlockBloom(height *int64) (ethtypes.Bloom, error) {
|
func (b *Backend) BlockBloom(blockRes *tmrpctypes.ResultBlockResults) (ethtypes.Bloom, error) {
|
||||||
result, err := b.clientCtx.Client.BlockResults(b.ctx, height)
|
for _, event := range blockRes.EndBlockEvents {
|
||||||
if err != nil {
|
|
||||||
return ethtypes.Bloom{}, err
|
|
||||||
}
|
|
||||||
for _, event := range result.EndBlockEvents {
|
|
||||||
if event.Type != evmtypes.EventTypeBlockBloom {
|
if event.Type != evmtypes.EventTypeBlockBloom {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -218,22 +242,19 @@ func (b *Backend) BlockBloom(height *int64) (ethtypes.Bloom, error) {
|
|||||||
// EthBlockFromTendermint returns a JSON-RPC compatible Ethereum block from a given Tendermint block and its block result.
|
// EthBlockFromTendermint returns a JSON-RPC compatible Ethereum block from a given Tendermint block and its block result.
|
||||||
func (b *Backend) EthBlockFromTendermint(
|
func (b *Backend) EthBlockFromTendermint(
|
||||||
resBlock *tmrpctypes.ResultBlock,
|
resBlock *tmrpctypes.ResultBlock,
|
||||||
|
blockRes *tmrpctypes.ResultBlockResults,
|
||||||
fullTx bool,
|
fullTx bool,
|
||||||
) (map[string]interface{}, error) {
|
) (map[string]interface{}, error) {
|
||||||
ethRPCTxs := []interface{}{}
|
ethRPCTxs := []interface{}{}
|
||||||
block := resBlock.Block
|
block := resBlock.Block
|
||||||
|
|
||||||
baseFee, err := b.BaseFee(block.Height)
|
baseFee, err := b.BaseFee(blockRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
// handle the error for pruned node.
|
||||||
|
b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", block.Height, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
resBlockResult, err := b.clientCtx.Client.BlockResults(b.ctx, &block.Height)
|
msgs := b.GetEthereumMsgsFromTendermintBlock(resBlock, blockRes)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
msgs := b.GetEthereumMsgsFromTendermintBlock(resBlock, resBlockResult)
|
|
||||||
for txIndex, ethMsg := range msgs {
|
for txIndex, ethMsg := range msgs {
|
||||||
if !fullTx {
|
if !fullTx {
|
||||||
hash := common.HexToHash(ethMsg.Hash)
|
hash := common.HexToHash(ethMsg.Hash)
|
||||||
@ -256,7 +277,7 @@ func (b *Backend) EthBlockFromTendermint(
|
|||||||
ethRPCTxs = append(ethRPCTxs, rpcTx)
|
ethRPCTxs = append(ethRPCTxs, rpcTx)
|
||||||
}
|
}
|
||||||
|
|
||||||
bloom, err := b.BlockBloom(&block.Height)
|
bloom, err := b.BlockBloom(blockRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.logger.Debug("failed to query BlockBloom", "height", block.Height, "error", err.Error())
|
b.logger.Debug("failed to query BlockBloom", "height", block.Height, "error", err.Error())
|
||||||
}
|
}
|
||||||
@ -265,6 +286,8 @@ func (b *Backend) EthBlockFromTendermint(
|
|||||||
ConsAddress: sdk.ConsAddress(block.Header.ProposerAddress).String(),
|
ConsAddress: sdk.ConsAddress(block.Header.ProposerAddress).String(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var validatorAccAddr sdk.AccAddress
|
||||||
|
|
||||||
ctx := types.ContextWithHeight(block.Height)
|
ctx := types.ContextWithHeight(block.Height)
|
||||||
res, err := b.queryClient.ValidatorAccount(ctx, req)
|
res, err := b.queryClient.ValidatorAccount(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -274,15 +297,16 @@ func (b *Backend) EthBlockFromTendermint(
|
|||||||
"cons-address", req.ConsAddress,
|
"cons-address", req.ConsAddress,
|
||||||
"error", err.Error(),
|
"error", err.Error(),
|
||||||
)
|
)
|
||||||
return nil, err
|
// use zero address as the validator operator address
|
||||||
}
|
validatorAccAddr = sdk.AccAddress(common.Address{}.Bytes())
|
||||||
|
} else {
|
||||||
addr, err := sdk.AccAddressFromBech32(res.AccountAddress)
|
validatorAccAddr, err = sdk.AccAddressFromBech32(res.AccountAddress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
validatorAddr := common.BytesToAddress(addr)
|
validatorAddr := common.BytesToAddress(validatorAccAddr)
|
||||||
|
|
||||||
gasLimit, err := types.BlockMaxGasFromConsensusParams(ctx, b.clientCtx, block.Height)
|
gasLimit, err := types.BlockMaxGasFromConsensusParams(ctx, b.clientCtx, block.Height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -291,7 +315,7 @@ func (b *Backend) EthBlockFromTendermint(
|
|||||||
|
|
||||||
gasUsed := uint64(0)
|
gasUsed := uint64(0)
|
||||||
|
|
||||||
for _, txsResult := range resBlockResult.TxsResults {
|
for _, txsResult := range blockRes.TxsResults {
|
||||||
// workaround for cosmos-sdk bug. https://github.com/cosmos/cosmos-sdk/issues/10832
|
// workaround for cosmos-sdk bug. https://github.com/cosmos/cosmos-sdk/issues/10832
|
||||||
if ShouldIgnoreGasUsed(txsResult) {
|
if ShouldIgnoreGasUsed(txsResult) {
|
||||||
// block gas limit has exceeded, other txs must have failed with same reason.
|
// block gas limit has exceeded, other txs must have failed with same reason.
|
||||||
@ -325,15 +349,20 @@ func (b *Backend) HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header,
|
|||||||
return nil, errors.Errorf("block not found for height %d", blockNum)
|
return nil, errors.Errorf("block not found for height %d", blockNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
bloom, err := b.BlockBloom(&resBlock.Block.Height)
|
blockRes, err := b.GetTendermintBlockResultByNumber(&resBlock.Block.Height)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("block result not found for height %d", resBlock.Block.Height)
|
||||||
|
}
|
||||||
|
|
||||||
|
bloom, err := b.BlockBloom(blockRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.logger.Debug("HeaderByNumber BlockBloom failed", "height", resBlock.Block.Height)
|
b.logger.Debug("HeaderByNumber BlockBloom failed", "height", resBlock.Block.Height)
|
||||||
}
|
}
|
||||||
|
|
||||||
baseFee, err := b.BaseFee(resBlock.Block.Height)
|
baseFee, err := b.BaseFee(blockRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.logger.Debug("HeaderByNumber BaseFee failed", "height", resBlock.Block.Height, "error", err.Error())
|
// handle the error for pruned node.
|
||||||
return nil, err
|
b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", resBlock.Block.Height, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ethHeader := types.EthHeaderFromTendermint(resBlock.Block.Header, bloom, baseFee)
|
ethHeader := types.EthHeaderFromTendermint(resBlock.Block.Header, bloom, baseFee)
|
||||||
@ -350,15 +379,20 @@ func (b *Backend) HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error)
|
|||||||
return nil, errors.Errorf("block not found for hash %s", blockHash.Hex())
|
return nil, errors.Errorf("block not found for hash %s", blockHash.Hex())
|
||||||
}
|
}
|
||||||
|
|
||||||
bloom, err := b.BlockBloom(&resBlock.Block.Height)
|
blockRes, err := b.GetTendermintBlockResultByNumber(&resBlock.Block.Height)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Errorf("block result not found for height %d", resBlock.Block.Height)
|
||||||
|
}
|
||||||
|
|
||||||
|
bloom, err := b.BlockBloom(blockRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.logger.Debug("HeaderByHash BlockBloom failed", "height", resBlock.Block.Height)
|
b.logger.Debug("HeaderByHash BlockBloom failed", "height", resBlock.Block.Height)
|
||||||
}
|
}
|
||||||
|
|
||||||
baseFee, err := b.BaseFee(resBlock.Block.Height)
|
baseFee, err := b.BaseFee(blockRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
b.logger.Debug("HeaderByHash BaseFee failed", "height", resBlock.Block.Height, "error", err.Error())
|
// handle the error for pruned node.
|
||||||
return nil, err
|
b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", resBlock.Block.Height, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ethHeader := types.EthHeaderFromTendermint(resBlock.Block.Header, bloom, baseFee)
|
ethHeader := types.EthHeaderFromTendermint(resBlock.Block.Header, bloom, baseFee)
|
||||||
@ -388,22 +422,12 @@ func (b *Backend) PendingTransactions() ([]*sdk.Tx, error) {
|
|||||||
// GetLogsByHeight returns all the logs from all the ethereum transactions in a block.
|
// GetLogsByHeight returns all the logs from all the ethereum transactions in a block.
|
||||||
func (b *Backend) GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error) {
|
func (b *Backend) GetLogsByHeight(height *int64) ([][]*ethtypes.Log, error) {
|
||||||
// NOTE: we query the state in case the tx result logs are not persisted after an upgrade.
|
// NOTE: we query the state in case the tx result logs are not persisted after an upgrade.
|
||||||
blockRes, err := b.clientCtx.Client.BlockResults(b.ctx, height)
|
blockRes, err := b.GetTendermintBlockResultByNumber(height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
blockLogs := [][]*ethtypes.Log{}
|
return GetLogsFromBlockResults(blockRes)
|
||||||
for _, txResult := range blockRes.TxsResults {
|
|
||||||
logs, err := AllTxLogsFromEvents(txResult.Events)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
blockLogs = append(blockLogs, logs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return blockLogs, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLogs returns all the logs from all the ethereum transactions in a block.
|
// GetLogs returns all the logs from all the ethereum transactions in a block.
|
||||||
@ -520,12 +544,14 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*types.RPCTransactio
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if parsedTx.EthTxIndex == -1 {
|
blockRes, err := b.GetTendermintBlockResultByNumber(&block.Block.Height)
|
||||||
// Fallback to find tx index by iterating all valid eth transactions
|
|
||||||
blockRes, err := b.clientCtx.Client.BlockResults(b.ctx, &block.Block.Height)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
b.logger.Debug("block result not found", "height", block.Block.Height, "error", err.Error())
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if parsedTx.EthTxIndex == -1 {
|
||||||
|
// Fallback to find tx index by iterating all valid eth transactions
|
||||||
msgs := b.GetEthereumMsgsFromTendermintBlock(block, blockRes)
|
msgs := b.GetEthereumMsgsFromTendermintBlock(block, blockRes)
|
||||||
for i := range msgs {
|
for i := range msgs {
|
||||||
if msgs[i].Hash == hexTx {
|
if msgs[i].Hash == hexTx {
|
||||||
@ -538,9 +564,10 @@ func (b *Backend) GetTransactionByHash(txHash common.Hash) (*types.RPCTransactio
|
|||||||
return nil, errors.New("can't find index of ethereum tx")
|
return nil, errors.New("can't find index of ethereum tx")
|
||||||
}
|
}
|
||||||
|
|
||||||
baseFee, err := b.BaseFee(block.Block.Height)
|
baseFee, err := b.BaseFee(blockRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
// handle the error for pruned node.
|
||||||
|
b.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", blockRes.Height, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return types.NewTransactionFromMsg(
|
return types.NewTransactionFromMsg(
|
||||||
@ -812,10 +839,22 @@ func (b *Backend) SuggestGasTipCap(baseFee *big.Int) (*big.Int, error) {
|
|||||||
// If the base fee is not enabled globally, the query returns nil.
|
// If the base fee is not enabled globally, the query returns nil.
|
||||||
// If the London hard fork is not activated at the current height, the query will
|
// If the London hard fork is not activated at the current height, the query will
|
||||||
// return nil.
|
// return nil.
|
||||||
func (b *Backend) BaseFee(height int64) (*big.Int, error) {
|
func (b *Backend) BaseFee(blockRes *tmrpctypes.ResultBlockResults) (*big.Int, error) {
|
||||||
// return BaseFee if London hard fork is activated and feemarket is enabled
|
// return BaseFee if London hard fork is activated and feemarket is enabled
|
||||||
res, err := b.queryClient.BaseFee(types.ContextWithHeight(height), &evmtypes.QueryBaseFeeRequest{})
|
res, err := b.queryClient.BaseFee(types.ContextWithHeight(blockRes.Height), &evmtypes.QueryBaseFeeRequest{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// fallback to parsing from begin blocker event, could happen on pruned nodes.
|
||||||
|
// faster to iterate reversely
|
||||||
|
for i := len(blockRes.BeginBlockEvents) - 1; i >= 0; i-- {
|
||||||
|
evt := blockRes.BeginBlockEvents[i]
|
||||||
|
if evt.Type == feemarkettypes.EventTypeFeeMarket && len(evt.Attributes) > 0 {
|
||||||
|
baseFee, err := strconv.ParseInt(string(evt.Attributes[0].Value), 10, 64)
|
||||||
|
if err == nil {
|
||||||
|
return big.NewInt(baseFee), nil
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -892,7 +931,7 @@ func (b *Backend) FeeHistory(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tendermint block result
|
// tendermint block result
|
||||||
tendermintBlockResult, err := b.clientCtx.Client.BlockResults(b.ctx, &tendermintblock.Block.Height)
|
tendermintBlockResult, err := b.GetTendermintBlockResultByNumber(&tendermintblock.Block.Height)
|
||||||
if tendermintBlockResult == nil {
|
if tendermintBlockResult == nil {
|
||||||
b.logger.Debug("block result not found", "height", tendermintblock.Block.Height, "error", err.Error())
|
b.logger.Debug("block result not found", "height", tendermintblock.Block.Height, "error", err.Error())
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -232,7 +232,7 @@ func (b *Backend) processBlock(
|
|||||||
targetOneFeeHistory *types.OneFeeHistory,
|
targetOneFeeHistory *types.OneFeeHistory,
|
||||||
) error {
|
) error {
|
||||||
blockHeight := tendermintBlock.Block.Height
|
blockHeight := tendermintBlock.Block.Height
|
||||||
blockBaseFee, err := b.BaseFee(blockHeight)
|
blockBaseFee, err := b.BaseFee(tendermintBlockResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -390,3 +390,18 @@ func TxSuccessOrExceedsBlockGasLimit(res *abci.ResponseDeliverTx) bool {
|
|||||||
func ShouldIgnoreGasUsed(res *abci.ResponseDeliverTx) bool {
|
func ShouldIgnoreGasUsed(res *abci.ResponseDeliverTx) bool {
|
||||||
return res.GetCode() == 11 && strings.Contains(res.GetLog(), "no block gas left to run tx: out of gas")
|
return res.GetCode() == 11 && strings.Contains(res.GetLog(), "no block gas left to run tx: out of gas")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetLogsFromBlockResults returns the list of event logs from the tendermint block result response
|
||||||
|
func GetLogsFromBlockResults(blockRes *tmrpctypes.ResultBlockResults) ([][]*ethtypes.Log, error) {
|
||||||
|
blockLogs := [][]*ethtypes.Log{}
|
||||||
|
for _, txResult := range blockRes.TxsResults {
|
||||||
|
logs, err := AllTxLogsFromEvents(txResult.Events)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
blockLogs = append(blockLogs, logs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return blockLogs, nil
|
||||||
|
}
|
||||||
|
@ -339,7 +339,7 @@ func (e *PublicAPI) GetBlockTransactionCountByHash(hash common.Hash) *hexutil.Ui
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &block.Block.Height)
|
blockRes, err := e.backend.GetTendermintBlockResultByNumber(&block.Block.Height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -363,7 +363,7 @@ func (e *PublicAPI) GetBlockTransactionCountByNumber(blockNum rpctypes.BlockNumb
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &block.Block.Height)
|
blockRes, err := e.backend.GetTendermintBlockResultByNumber(&block.Block.Height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -753,6 +753,11 @@ func (e *PublicAPI) GetTransactionByHash(hash common.Hash) (*rpctypes.RPCTransac
|
|||||||
|
|
||||||
// getTransactionByBlockAndIndex is the common code shared by `GetTransactionByBlockNumberAndIndex` and `GetTransactionByBlockHashAndIndex`.
|
// getTransactionByBlockAndIndex is the common code shared by `GetTransactionByBlockNumberAndIndex` and `GetTransactionByBlockHashAndIndex`.
|
||||||
func (e *PublicAPI) getTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
|
func (e *PublicAPI) getTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock, idx hexutil.Uint) (*rpctypes.RPCTransaction, error) {
|
||||||
|
blockRes, err := e.backend.GetTendermintBlockResultByNumber(&block.Block.Height)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
var msg *evmtypes.MsgEthereumTx
|
var msg *evmtypes.MsgEthereumTx
|
||||||
// try /tx_search first
|
// try /tx_search first
|
||||||
res, err := e.backend.GetTxByTxIndex(block.Block.Height, uint(idx))
|
res, err := e.backend.GetTxByTxIndex(block.Block.Height, uint(idx))
|
||||||
@ -781,11 +786,6 @@ func (e *PublicAPI) getTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock,
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &block.Block.Height)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
i := int(idx)
|
i := int(idx)
|
||||||
ethMsgs := e.backend.GetEthereumMsgsFromTendermintBlock(block, blockRes)
|
ethMsgs := e.backend.GetEthereumMsgsFromTendermintBlock(block, blockRes)
|
||||||
if i >= len(ethMsgs) {
|
if i >= len(ethMsgs) {
|
||||||
@ -796,9 +796,10 @@ func (e *PublicAPI) getTransactionByBlockAndIndex(block *tmrpctypes.ResultBlock,
|
|||||||
msg = ethMsgs[i]
|
msg = ethMsgs[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
baseFee, err := e.backend.BaseFee(block.Block.Height)
|
baseFee, err := e.backend.BaseFee(blockRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
// handle the error for pruned node.
|
||||||
|
e.logger.Error("failed to fetch Base Fee from prunned block. Check node prunning configuration", "height", block.Block.Height, "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return rpctypes.NewTransactionFromMsg(
|
return rpctypes.NewTransactionFromMsg(
|
||||||
@ -903,7 +904,7 @@ func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
cumulativeGasUsed := uint64(0)
|
cumulativeGasUsed := uint64(0)
|
||||||
blockRes, err := e.clientCtx.Client.BlockResults(e.ctx, &res.Height)
|
blockRes, err := e.backend.GetTendermintBlockResultByNumber(&res.Height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e.logger.Debug("failed to retrieve block results", "height", res.Height, "error", err.Error())
|
e.logger.Debug("failed to retrieve block results", "height", res.Height, "error", err.Error())
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -982,12 +983,14 @@ func (e *PublicAPI) GetTransactionReceipt(hash common.Hash) (map[string]interfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
if dynamicTx, ok := txData.(*evmtypes.DynamicFeeTx); ok {
|
if dynamicTx, ok := txData.(*evmtypes.DynamicFeeTx); ok {
|
||||||
baseFee, err := e.backend.BaseFee(res.Height)
|
baseFee, err := e.backend.BaseFee(blockRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
// tolerate the error for pruned node.
|
||||||
}
|
e.logger.Error("fetch basefee failed, node is pruned?", "height", res.Height, "error", err)
|
||||||
|
} else {
|
||||||
receipt["effectiveGasPrice"] = hexutil.Big(*dynamicTx.GetEffectiveGasPrice(baseFee))
|
receipt["effectiveGasPrice"] = hexutil.Big(*dynamicTx.GetEffectiveGasPrice(baseFee))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return receipt, nil
|
return receipt, nil
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,11 @@ type Backend interface {
|
|||||||
GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error)
|
GetBlockByNumber(blockNum types.BlockNumber, fullTx bool) (map[string]interface{}, error)
|
||||||
HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error)
|
HeaderByNumber(blockNum types.BlockNumber) (*ethtypes.Header, error)
|
||||||
HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error)
|
HeaderByHash(blockHash common.Hash) (*ethtypes.Header, error)
|
||||||
|
GetTendermintBlockByHash(hash common.Hash) (*coretypes.ResultBlock, error)
|
||||||
|
GetTendermintBlockResultByNumber(height *int64) (*coretypes.ResultBlockResults, error)
|
||||||
GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error)
|
GetLogs(blockHash common.Hash) ([][]*ethtypes.Log, error)
|
||||||
GetLogsByHeight(*int64) ([][]*ethtypes.Log, error)
|
GetLogsByHeight(*int64) ([][]*ethtypes.Log, error)
|
||||||
BlockBloom(height *int64) (ethtypes.Bloom, error)
|
BlockBloom(blockRes *coretypes.ResultBlockResults) (ethtypes.Bloom, error)
|
||||||
|
|
||||||
BloomStatus() (uint64, uint64)
|
BloomStatus() (uint64, uint64)
|
||||||
|
|
||||||
|
@ -3,12 +3,15 @@ package filters
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/evmos/ethermint/rpc/backend"
|
||||||
"github.com/evmos/ethermint/rpc/types"
|
"github.com/evmos/ethermint/rpc/types"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/tendermint/tendermint/libs/log"
|
"github.com/tendermint/tendermint/libs/log"
|
||||||
|
tmrpctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||||
@ -89,28 +92,35 @@ const (
|
|||||||
|
|
||||||
// Logs searches the blockchain for matching log entries, returning all from the
|
// Logs searches the blockchain for matching log entries, returning all from the
|
||||||
// first block that contains matches, updating the start of the filter accordingly.
|
// first block that contains matches, updating the start of the filter accordingly.
|
||||||
func (f *Filter) Logs(_ context.Context, logLimit int, blockLimit int64) ([]*ethtypes.Log, error) {
|
func (f *Filter) Logs(ctx context.Context, logLimit int, blockLimit int64) ([]*ethtypes.Log, error) {
|
||||||
logs := []*ethtypes.Log{}
|
logs := []*ethtypes.Log{}
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// If we're doing singleton block filtering, execute and return
|
// If we're doing singleton block filtering, execute and return
|
||||||
if f.criteria.BlockHash != nil && *f.criteria.BlockHash != (common.Hash{}) {
|
if f.criteria.BlockHash != nil && *f.criteria.BlockHash != (common.Hash{}) {
|
||||||
header, err := f.backend.HeaderByHash(*f.criteria.BlockHash)
|
resBlock, err := f.backend.GetTendermintBlockByHash(*f.criteria.BlockHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to fetch header by hash")
|
return nil, fmt.Errorf("failed to fetch header by hash %s: %w", f.criteria.BlockHash, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if header == nil {
|
blockRes, err := f.backend.GetTendermintBlockResultByNumber(&resBlock.Block.Height)
|
||||||
return nil, errors.Errorf("unknown block header %s", f.criteria.BlockHash.String())
|
if err != nil {
|
||||||
|
f.logger.Debug("failed to fetch block result from Tendermint", "height", resBlock.Block.Height, "error", err.Error())
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return f.blockLogs(header.Number.Int64(), header.Bloom)
|
bloom, err := f.backend.BlockBloom(blockRes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return f.blockLogs(blockRes, bloom)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Figure out the limits of the filter range
|
// Figure out the limits of the filter range
|
||||||
header, err := f.backend.HeaderByNumber(types.EthLatestBlockNumber)
|
header, err := f.backend.HeaderByNumber(types.EthLatestBlockNumber)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to fetch header by number (latest)")
|
return nil, fmt.Errorf("failed to fetch header by number (latest): %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if header == nil || header.Number == nil {
|
if header == nil || header.Number == nil {
|
||||||
@ -131,7 +141,7 @@ func (f *Filter) Logs(_ context.Context, logLimit int, blockLimit int64) ([]*eth
|
|||||||
}
|
}
|
||||||
|
|
||||||
if f.criteria.ToBlock.Int64()-f.criteria.FromBlock.Int64() > blockLimit {
|
if f.criteria.ToBlock.Int64()-f.criteria.FromBlock.Int64() > blockLimit {
|
||||||
return nil, errors.Errorf("maximum [from, to] blocks distance: %d", blockLimit)
|
return nil, fmt.Errorf("maximum [from, to] blocks distance: %d", blockLimit)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check bounds
|
// check bounds
|
||||||
@ -145,19 +155,25 @@ func (f *Filter) Logs(_ context.Context, logLimit int, blockLimit int64) ([]*eth
|
|||||||
to := f.criteria.ToBlock.Int64()
|
to := f.criteria.ToBlock.Int64()
|
||||||
|
|
||||||
for height := from; height <= to; height++ {
|
for height := from; height <= to; height++ {
|
||||||
bloom, err := f.backend.BlockBloom(&height)
|
blockRes, err := f.backend.GetTendermintBlockResultByNumber(&height)
|
||||||
|
if err != nil {
|
||||||
|
f.logger.Debug("failed to fetch block result from Tendermint", "height", height, "error", err.Error())
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
bloom, err := f.backend.BlockBloom(blockRes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
filtered, err := f.blockLogs(height, bloom)
|
filtered, err := f.blockLogs(blockRes, bloom)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to fetch block by number %d", height)
|
return nil, errors.Wrapf(err, "failed to fetch block by number %d", height)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check logs limit
|
// check logs limit
|
||||||
if len(logs)+len(filtered) > logLimit {
|
if len(logs)+len(filtered) > logLimit {
|
||||||
return nil, errors.Errorf("query returned more than %d results", logLimit)
|
return nil, fmt.Errorf("query returned more than %d results", logLimit)
|
||||||
}
|
}
|
||||||
logs = append(logs, filtered...)
|
logs = append(logs, filtered...)
|
||||||
}
|
}
|
||||||
@ -165,16 +181,14 @@ func (f *Filter) Logs(_ context.Context, logLimit int, blockLimit int64) ([]*eth
|
|||||||
}
|
}
|
||||||
|
|
||||||
// blockLogs returns the logs matching the filter criteria within a single block.
|
// blockLogs returns the logs matching the filter criteria within a single block.
|
||||||
func (f *Filter) blockLogs(height int64, bloom ethtypes.Bloom) ([]*ethtypes.Log, error) {
|
func (f *Filter) blockLogs(blockRes *tmrpctypes.ResultBlockResults, bloom ethtypes.Bloom) ([]*ethtypes.Log, error) {
|
||||||
if !bloomFilter(bloom, f.criteria.Addresses, f.criteria.Topics) {
|
if !bloomFilter(bloom, f.criteria.Addresses, f.criteria.Topics) {
|
||||||
return []*ethtypes.Log{}, nil
|
return []*ethtypes.Log{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DANGER: do not call GetLogs(header.Hash())
|
logsList, err := backend.GetLogsFromBlockResults(blockRes)
|
||||||
// eth header's hash doesn't match tm block hash
|
|
||||||
logsList, err := f.backend.GetLogsByHeight(&height)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []*ethtypes.Log{}, errors.Wrapf(err, "failed to fetch logs block number %d", height)
|
return []*ethtypes.Log{}, errors.Wrapf(err, "failed to fetch logs block number %d", blockRes.Height)
|
||||||
}
|
}
|
||||||
|
|
||||||
unfiltered := make([]*ethtypes.Log, 0)
|
unfiltered := make([]*ethtypes.Log, 0)
|
||||||
|
Loading…
Reference in New Issue
Block a user