ETH源码阅读(通过区块高度获得区块GetBlockByNumb
2018-09-19 本文已影响0人
坠叶飘香
1.流程图:
GetBlockByNumber.png2.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)
}