func (r *routes) randomNeighbours(except PeerName) []PeerName {
	destinations := make(peerNameSet)
	r.RLock()
	defer r.RUnlock()
	count := int(math.Log2(float64(len(r.unicastAll))))
	// depends on go's random map iteration
	for _, dst := range r.unicastAll {
		if dst != UnknownPeerName && dst != except {
			destinations[dst] = struct{}{}
			if len(destinations) >= count {
				break
			}
		}
	}
	res := make([]PeerName, 0, len(destinations))
	for dst := range destinations {
		res = append(res, dst)
	}
	return res
}
func (r *routes) randomNeighbours(except PeerName) []PeerName {
	destinations := make(peerNameSet)
	r.RLock()
	defer r.RUnlock()
	count := int(math.Log2(float64(len(r.unicastAll))))
	// depends on go's random map iteration
	for _, dst := range r.unicastAll {
		if dst != UnknownPeerName && dst != except {
			destinations[dst] = struct{}{}
			if len(destinations) >= count {
				break
			}
		}
	}
	res := make([]PeerName, 0, len(destinations))
	for dst := range destinations {
		res = append(res, dst)
	}
	return res
}
// RandomNeighbours chooses min(log2(n_peers), n_neighbouring_peers)
// neighbours, with a random distribution that is topology-sensitive,
// favouring neighbours at the end of "bottleneck links". We determine the
// latter based on the unicast routing table. If a neighbour appears as the
// value more frequently than others - meaning that we reach a higher
// proportion of peers via that neighbour than other neighbours - then it is
// chosen with a higher probability.
//
// Note that we choose log2(n_peers) *neighbours*, not peers. Consequently, on
// sparsely connected peers this function returns a higher proportion of
// neighbours than elsewhere. In extremis, on peers with fewer than
// log2(n_peers) neighbours, all neighbours are returned.