ETH源码阅读(通过区块高度获得区块GetBlockByNumber)

1.流程图:

ETH源码阅读(通过区块高度获得区块GetBlockByNumber)_第1张图片
GetBlockByNumber.png

2.1通过区块高度获得Block

go-ethereum/internal/ethapi/api.go

// GetBlockByNumber returns the requested block. When blockNr is -1 the chain head is returned. When fullTx is true all
// 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) {
    block, err := s.b.BlockByNumber(ctx, blockNr) //通过区块高度获得Block
    if block != nil {
        response, err := s.rpcOutputBlock(block, true, fullTx)
        if err == nil && blockNr == rpc.PendingBlockNumber {
            // Pending blocks need to nil out a few fields
            for _, field := range []string{"hash", "nonce", "miner"} {
                response[field] = nil
            }
        }
        return response, err
    }
    return nil, err
}

2.2通过区块高度获得Block

go-ethereum/eth/api_backend.go

func (b *EthAPIBackend) BlockByNumber(ctx context.Context, blockNr rpc.BlockNumber) (*types.Block, error) {
    // Pending block is only known by the miner
    if blockNr == rpc.PendingBlockNumber {
        block := b.eth.miner.PendingBlock()
        return block, nil
    }
    // Otherwise resolve and return the block
    if blockNr == rpc.LatestBlockNumber {
        return b.eth.blockchain.CurrentBlock(), nil
    }
    return b.eth.blockchain.GetBlockByNumber(uint64(blockNr)), nil  //通过区块高度获得Block
}

2.3

  • 通过区块高度获得区块hash
  • 通过区块高度和区块hash获得Block
    go-ethereum/core/blockchain.go
// GetBlockByNumber retrieves a block from the database by number, caching it
// (associated with its hash) if found.
func (bc *BlockChain) GetBlockByNumber(number uint64) *types.Block {
    hash := rawdb.ReadCanonicalHash(bc.db, number) //通过区块高度获得区块hash
    if hash == (common.Hash{}) {
        return nil
    }
    return bc.GetBlock(hash, number) //通过区块高度和区块hash获得Block
}

2.4

go-ethereum/core/blockchain.go

  • 从缓存blockCache读取,如果读取到,返回
  • 从缓存读取失败,从db读取
  • 将从db读取到的block放入blockCache,返回
// GetBlock retrieves a block from the database by hash and number,
// caching it if found.
func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block {
    // Short circuit if the block's already in the cache, retrieve otherwise
    if block, ok := bc.blockCache.Get(hash); ok { //从缓存blockCache读取,如果读取到,返回
        return block.(*types.Block) 
    }
    block := rawdb.ReadBlock(bc.db, hash, number) //从缓存读取失败,从db读取
    if block == nil {
        return nil
    }
    // Cache the found block for next time and return
    bc.blockCache.Add(block.Hash(), block)  //将从db读取到的block放入blockCache,返回
    return block
}

2.5

  • 从db读取Header
  • 从db读取Body
  • 由Header和Body生成Block
    go-ethereum/core/rawdb/accessors_chain.go
// ReadBlock retrieves an entire block corresponding to the hash, assembling it
// back from the stored header and body. If either the header or body could not
// be retrieved nil is returned.
//
// Note, due to concurrent download of header and block body the header and thus
// canonical hash can be stored in the database but the body data not (yet).
func ReadBlock(db DatabaseReader, hash common.Hash, number uint64) *types.Block {
    header := ReadHeader(db, hash, number) //从db读取Header
    if header == nil {
        return nil
    }
    body := ReadBody(db, hash, number) //从db读取Body
    if body == nil {
        return nil
    }
        //由Header和Body生成Block
    return types.NewBlockWithHeader(header).WithBody(body.Transactions, body.Uncles)
}

你可能感兴趣的:(ETH源码阅读(通过区块高度获得区块GetBlockByNumber))