code: func (s *Service) assembleBlockStats(block *types.Block) *blockStats {
  	// Gather the block infos from the local blockchain
  	var (
  		header *types.Header
  		td     *big.Int
  		txs    []txStats
  		uncles []*types.Header
  	)
  	if s.eth != nil {
  		// Full nodes have all needed information available
  		if block == nil {
  			block = s.eth.BlockChain().CurrentBlock()
  		}
  		header = block.Header()
  		td = s.eth.BlockChain().GetTd(header.Hash(), header.Number.Uint64())
  
  		txs = make([]txStats, len(block.Transactions()))
  		for i, tx := range block.Transactions() {
  			txs[i].Hash = tx.Hash()
  		}
  		uncles = block.Uncles()
  	} else {
  		// Light nodes would need on-demand lookups for transactions/uncles, skip
  		if block != nil {
  			header = block.Header()
  		} else {
  			header = s.les.BlockChain().CurrentHeader()
  		}
  		td = s.les.BlockChain().GetTd(header.Hash(), header.Number.Uint64())
  		txs = []txStats{}
  	}
  	// Assemble and return the block stats
  	author, _ := s.engine.Author(header)
  
  	return &blockStats{
  		Number:     header.Number,
  		Hash:       header.Hash(),
  		ParentHash: header.ParentHash,
  		Timestamp:  new(big.Int).SetUint64(header.Time),
  		Miner:      author,
  		GasUsed:    header.GasUsed,
  		GasLimit:   header.GasLimit,
  		Diff:       header.Difficulty.String(),
  		TotalDiff:  td.String(),
  		Txs:        txs,
  		TxHash:     header.TxHash,
  		Root:       header.Root,
  		Uncles:     uncles,
  	}
  }
docs: // assembleBlockStats retrieves any required metadata to report a single block
  // and assembles the block stats. If block is nil, the current head is processed.