mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-05-20 13:56:45 +00:00

* Address manager refactor stage 1 * Use a simpler weightedRand function which makes it easier parameterize to the process * Switch back to connectionFailedCount * Simplify selected entry deletion * Fix function comment Co-authored-by: Constantine Bitensky <cbitensky1@gmail.com> Co-authored-by: Ori Newman <orinewman1@gmail.com>
64 lines
1.6 KiB
Go
64 lines
1.6 KiB
Go
package addressmanager
|
|
|
|
import (
|
|
"math"
|
|
"math/rand"
|
|
"time"
|
|
|
|
"github.com/kaspanet/kaspad/app/appmessage"
|
|
)
|
|
|
|
// AddressRandomize implement addressRandomizer interface
|
|
type AddressRandomize struct {
|
|
random *rand.Rand
|
|
maxFailedCount uint64
|
|
}
|
|
|
|
// NewAddressRandomize returns a new RandomizeAddress.
|
|
func NewAddressRandomize(maxFailedCount uint64) *AddressRandomize {
|
|
return &AddressRandomize{
|
|
random: rand.New(rand.NewSource(time.Now().UnixNano())),
|
|
maxFailedCount: maxFailedCount,
|
|
}
|
|
}
|
|
|
|
// weightedRand is a help function which returns a random index in the
|
|
// range [0, len(weights)-1] with probability weighted by `weights`
|
|
func weightedRand(weights []float32) int {
|
|
sum := float32(0)
|
|
for _, weight := range weights {
|
|
sum += weight
|
|
}
|
|
randPoint := rand.Float32()
|
|
scanPoint := float32(0)
|
|
for i, weight := range weights {
|
|
normalizedWeight := weight / sum
|
|
scanPoint += normalizedWeight
|
|
if randPoint <= scanPoint {
|
|
return i
|
|
}
|
|
}
|
|
return len(weights) - 1
|
|
}
|
|
|
|
// RandomAddresses returns count addresses at random from input list
|
|
func (amc *AddressRandomize) RandomAddresses(addresses []*address, count int) []*appmessage.NetAddress {
|
|
if len(addresses) < count {
|
|
count = len(addresses)
|
|
}
|
|
weights := make([]float32, 0, len(addresses))
|
|
for _, addr := range addresses {
|
|
weights = append(weights, float32(math.Pow(64, float64(amc.maxFailedCount-addr.connectionFailedCount))))
|
|
}
|
|
result := make([]*appmessage.NetAddress, 0, count)
|
|
for count > 0 {
|
|
i := weightedRand(weights)
|
|
result = append(result, addresses[i].netAddress)
|
|
// Zero entry i to avoid re-selection
|
|
weights[i] = 0
|
|
// Update count
|
|
count--
|
|
}
|
|
return result
|
|
}
|