code: func (pm *ProtocolManager) BroadcastBlock(block *types.Block, propagate bool) {
  	hash := block.Hash()
  	peers := pm.peers.PeersWithoutBlock(hash)
  
  	// If propagation is requested, send to a subset of the peer
  	if propagate {
  		// Calculate the TD of the block (it's not imported yet, so block.Td is not valid)
  		var td *big.Int
  		if parent := pm.blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1); parent != nil {
  			td = new(big.Int).Add(block.Difficulty(), pm.blockchain.GetTd(block.ParentHash(), block.NumberU64()-1))
  		} else {
  			log.Error("Propagating dangling block", "number", block.Number(), "hash", hash)
  			return
  		}
  		// Send the block to a subset of our peers
  		transferLen := int(math.Sqrt(float64(len(peers))))
  		if transferLen < minBroadcastPeers {
  			transferLen = minBroadcastPeers
  		}
  		if transferLen > len(peers) {
  			transferLen = len(peers)
  		}
  		transfer := peers[:transferLen]
  		for _, peer := range transfer {
  			peer.AsyncSendNewBlock(block, td)
  		}
  		log.Trace("Propagated block", "hash", hash, "recipients", len(transfer), "duration", common.PrettyDuration(time.Since(block.ReceivedAt)))
  		return
  	}
  	// Otherwise if the block is indeed in out own chain, announce it
  	if pm.blockchain.HasBlock(hash, block.NumberU64()) {
  		for _, peer := range peers {
  			peer.AsyncSendNewBlockHash(block)
  		}
  		log.Trace("Announced block", "hash", hash, "recipients", len(peers), "duration", common.PrettyDuration(time.Since(block.ReceivedAt)))
  	}
  }
docs: // BroadcastBlock will either propagate a block to a subset of it's peers, or
  // will only announce it's availability (depending what's requested).