peer: Improve address sampling in PushAddrMsg.

This changes fixes shuffling algorithm in PushAddrMsg to select a
uniformly random subset of the given addresses using Fisher-Yates.
This commit is contained in:
Jim Posen 2017-08-08 15:55:51 -07:00 committed by Dave Collins
parent fd081f5ae4
commit f4d376d7af

View file

@ -849,21 +849,22 @@ func (p *Peer) localVersionMsg() (*wire.MsgVersion, error) {
// //
// This function is safe for concurrent access. // This function is safe for concurrent access.
func (p *Peer) PushAddrMsg(addresses []*wire.NetAddress) ([]*wire.NetAddress, error) { func (p *Peer) PushAddrMsg(addresses []*wire.NetAddress) ([]*wire.NetAddress, error) {
addressCount := len(addresses)
// Nothing to send. // Nothing to send.
if len(addresses) == 0 { if addressCount == 0 {
return nil, nil return nil, nil
} }
msg := wire.NewMsgAddr() msg := wire.NewMsgAddr()
msg.AddrList = make([]*wire.NetAddress, len(addresses)) msg.AddrList = make([]*wire.NetAddress, addressCount)
copy(msg.AddrList, addresses) copy(msg.AddrList, addresses)
// Randomize the addresses sent if there are more than the maximum allowed. // Randomize the addresses sent if there are more than the maximum allowed.
if len(msg.AddrList) > wire.MaxAddrPerMsg { if addressCount > wire.MaxAddrPerMsg {
// Shuffle the address list. // Shuffle the address list.
for i := range msg.AddrList { for i := 0; i < wire.MaxAddrPerMsg; i++ {
j := rand.Intn(i + 1) j := i + rand.Intn(addressCount-i)
msg.AddrList[i], msg.AddrList[j] = msg.AddrList[j], msg.AddrList[i] msg.AddrList[i], msg.AddrList[j] = msg.AddrList[j], msg.AddrList[i]
} }