code: func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt) *Block {
  	b := &Block{header: CopyHeader(header), td: new(big.Int)}
  
  	// TODO: panic if len(txs) != len(receipts)
  	if len(txs) == 0 {
  		b.header.TxHash = EmptyRootHash
  	} else {
  		b.header.TxHash = DeriveSha(Transactions(txs))
  		b.transactions = make(Transactions, len(txs))
  		copy(b.transactions, txs)
  	}
  
  	if len(receipts) == 0 {
  		b.header.ReceiptHash = EmptyRootHash
  	} else {
  		b.header.ReceiptHash = DeriveSha(Receipts(receipts))
  		b.header.Bloom = CreateBloom(receipts)
  	}
  
  	if len(uncles) == 0 {
  		b.header.UncleHash = EmptyUncleHash
  	} else {
  		b.header.UncleHash = CalcUncleHash(uncles)
  		b.uncles = make([]*Header, len(uncles))
  		for i := range uncles {
  			b.uncles[i] = CopyHeader(uncles[i])
  		}
  	}
  
  	return b
  }
docs: // NewBlock creates a new block. The input data is copied,
  // changes to header and to the field values will not affect the
  // block.
  //
  // The values of TxHash, UncleHash, ReceiptHash and Bloom in header
  // are ignored and set to values derived from the given txs, uncles
  // and receipts.