mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 06:36:43 +00:00
internal/ethapi: ensure that getBlock* doesn't return backend errors
This commit is contained in:
parent
aa70048e50
commit
87a8ef6b70
1 changed files with 52 additions and 38 deletions
|
|
@ -304,74 +304,88 @@ func (s *PublicBlockChainAPI) BlockNumber() *big.Int {
|
||||||
// transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
|
// transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
|
||||||
func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
|
func (s *PublicBlockChainAPI) GetBlockByNumber(ctx context.Context, blockNr rpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
|
||||||
block, err := blockByNumber(ctx, s.b, blockNr)
|
block, err := blockByNumber(ctx, s.b, blockNr)
|
||||||
if block != nil {
|
if block == nil || err != nil {
|
||||||
response, err := s.rpcOutputBlock(ctx, block, true, fullTx)
|
return nil, err
|
||||||
if err == nil && blockNr == rpc.PendingBlockNumber {
|
|
||||||
// Pending blocks need to nil out a few fields
|
|
||||||
for _, field := range []string{"hash", "nonce", "logsBloom", "miner"} {
|
|
||||||
response[field] = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return response, err
|
|
||||||
}
|
}
|
||||||
return nil, err
|
response := s.rpcOutputBlock(ctx, block, true, fullTx)
|
||||||
|
if blockNr == rpc.PendingBlockNumber {
|
||||||
|
// Pending blocks need to nil out a few fields
|
||||||
|
for _, field := range []string{"hash", "nonce", "logsBloom", "miner"} {
|
||||||
|
response[field] = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func blockByNumber(ctx context.Context, b Backend, blockNr rpc.BlockNumber) (*types.Block, error) {
|
func blockByNumber(ctx context.Context, b Backend, blockNr rpc.BlockNumber) (block *types.Block, err error) {
|
||||||
switch blockNr {
|
switch blockNr {
|
||||||
case rpc.PendingBlockNumber:
|
case rpc.PendingBlockNumber:
|
||||||
ps, ok := b.(PendingState)
|
ps, ok := b.(PendingState)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("can't access the pending block with the current backend")
|
return nil, ErrNoPendingState
|
||||||
}
|
}
|
||||||
return ps.PendingBlock()
|
block, err = ps.PendingBlock()
|
||||||
case rpc.LatestBlockNumber:
|
case rpc.LatestBlockNumber:
|
||||||
return b.BlockByNumber(ctx, nil)
|
block, err = b.BlockByNumber(ctx, nil)
|
||||||
default:
|
default:
|
||||||
return b.BlockByNumber(ctx, big.NewInt(int64(blockNr)))
|
block, err = b.BlockByNumber(ctx, big.NewInt(int64(blockNr)))
|
||||||
}
|
}
|
||||||
|
// Don't return errors to the client. This is bad but we can't distinguish errors at
|
||||||
|
// this level and the API requires returning null for non-existent blocks.
|
||||||
|
if err != nil && glog.V(logger.Debug) {
|
||||||
|
glog.Warningf("can't get block %q: %v", blockNr, err)
|
||||||
|
}
|
||||||
|
return block, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
|
// GetBlockByHash returns the requested block. When fullTx is true all transactions in the block are returned in full
|
||||||
// detail, otherwise only the transaction hash is returned.
|
// detail, otherwise only the transaction hash is returned.
|
||||||
func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) (map[string]interface{}, error) {
|
func (s *PublicBlockChainAPI) GetBlockByHash(ctx context.Context, blockHash common.Hash, fullTx bool) map[string]interface{} {
|
||||||
block, err := s.b.BlockByHash(ctx, blockHash)
|
block, err := s.b.BlockByHash(ctx, blockHash)
|
||||||
if block != nil {
|
if block != nil {
|
||||||
return s.rpcOutputBlock(ctx, block, true, fullTx)
|
return s.rpcOutputBlock(ctx, block, true, fullTx)
|
||||||
}
|
}
|
||||||
return nil, err
|
if err != nil {
|
||||||
|
if glog.V(logger.Debug) {
|
||||||
|
glog.Warningf("can't get block %x: %v", blockHash[:], err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. When fullTx is true
|
// GetUncleByBlockNumberAndIndex returns the uncle block for the given block hash and index. When fullTx is true
|
||||||
// all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
|
// all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
|
||||||
func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index rpc.HexNumber) (map[string]interface{}, error) {
|
func (s *PublicBlockChainAPI) GetUncleByBlockNumberAndIndex(ctx context.Context, blockNr rpc.BlockNumber, index rpc.HexNumber) (map[string]interface{}, error) {
|
||||||
block, err := blockByNumber(ctx, s.b, blockNr)
|
block, err := blockByNumber(ctx, s.b, blockNr)
|
||||||
if block != nil {
|
if block == nil || err != nil {
|
||||||
uncles := block.Uncles()
|
return nil, err
|
||||||
if index.Int() < 0 || index.Int() >= len(uncles) {
|
|
||||||
glog.V(logger.Debug).Infof("uncle block on index %d not found for block #%d", index.Int(), blockNr)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
block = types.NewBlockWithHeader(uncles[index.Int()])
|
|
||||||
return s.rpcOutputBlock(ctx, block, false, false)
|
|
||||||
}
|
}
|
||||||
return nil, err
|
uncles := block.Uncles()
|
||||||
|
if index.Int() < 0 || index.Int() >= len(uncles) {
|
||||||
|
glog.V(logger.Debug).Infof("uncle block on index %d not found for block #%d", index.Int(), blockNr)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
block = types.NewBlockWithHeader(uncles[index.Int()])
|
||||||
|
return s.rpcOutputBlock(ctx, block, false, false), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index. When fullTx is true
|
// GetUncleByBlockHashAndIndex returns the uncle block for the given block hash and index. When fullTx is true
|
||||||
// all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
|
// all transactions in the block are returned in full detail, otherwise only the transaction hash is returned.
|
||||||
func (s *PublicBlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index rpc.HexNumber) (map[string]interface{}, error) {
|
func (s *PublicBlockChainAPI) GetUncleByBlockHashAndIndex(ctx context.Context, blockHash common.Hash, index rpc.HexNumber) map[string]interface{} {
|
||||||
block, err := s.b.BlockByHash(ctx, blockHash)
|
block, err := s.b.BlockByHash(ctx, blockHash)
|
||||||
if block != nil {
|
if err != nil && glog.V(logger.Debug) {
|
||||||
uncles := block.Uncles()
|
glog.Warningf("can't get block %x: %v", blockHash[:], err)
|
||||||
if index.Int() < 0 || index.Int() >= len(uncles) {
|
|
||||||
glog.V(logger.Debug).Infof("uncle block on index %d not found for block %s", index.Int(), blockHash.Hex())
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
block = types.NewBlockWithHeader(uncles[index.Int()])
|
|
||||||
return s.rpcOutputBlock(ctx, block, false, false)
|
|
||||||
}
|
}
|
||||||
return nil, err
|
if block == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
uncles := block.Uncles()
|
||||||
|
if index.Int() < 0 || index.Int() >= len(uncles) {
|
||||||
|
glog.V(logger.Debug).Infof("uncle block on index %d not found for block %s", index.Int(), blockHash.Hex())
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
block = types.NewBlockWithHeader(uncles[index.Int()])
|
||||||
|
return s.rpcOutputBlock(ctx, block, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUncleCountByBlockNumber returns number of uncles in the block for the given block number
|
// GetUncleCountByBlockNumber returns number of uncles in the block for the given block number
|
||||||
|
|
@ -559,7 +573,7 @@ func FormatLogs(structLogs []vm.StructLog) []StructLogRes {
|
||||||
// rpcOutputBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
|
// rpcOutputBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
|
||||||
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
|
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
|
||||||
// transaction hashes.
|
// transaction hashes.
|
||||||
func (s *PublicBlockChainAPI) rpcOutputBlock(ctx context.Context, b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
|
func (s *PublicBlockChainAPI) rpcOutputBlock(ctx context.Context, b *types.Block, inclTx bool, fullTx bool) map[string]interface{} {
|
||||||
head := b.Header() // copies the header once
|
head := b.Header() // copies the header once
|
||||||
fields := map[string]interface{}{
|
fields := map[string]interface{}{
|
||||||
"number": rpc.NewHexNumber(head.Number),
|
"number": rpc.NewHexNumber(head.Number),
|
||||||
|
|
@ -604,7 +618,7 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(ctx context.Context, b *types.Block
|
||||||
}
|
}
|
||||||
fields["uncles"] = uncleHashes
|
fields["uncles"] = uncleHashes
|
||||||
|
|
||||||
return fields, nil
|
return fields
|
||||||
}
|
}
|
||||||
|
|
||||||
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
|
// RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue