discovery: randomize order of different bootstrappers
In this commit, we randomize the order of the different bootstrappers in order to prevent from always querying potentially unreliable bootstrappers first.
This commit is contained in:
parent
9593e3772e
commit
800b1363ab
@ -4,10 +4,13 @@ import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
prand "math/rand"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/lightningnetwork/lnd/autopilot"
|
||||
@ -18,6 +21,10 @@ import (
|
||||
"github.com/roasbeef/btcutil/bech32"
|
||||
)
|
||||
|
||||
func init() {
|
||||
prand.Seed(time.Now().Unix())
|
||||
}
|
||||
|
||||
// NetworkPeerBootstrapper is an interface that represents an initial peer
|
||||
// bootstrap mechanism. This interface is to be used to bootstrap a new peer to
|
||||
// the connection by providing it with the pubkey+address of a set of existing
|
||||
@ -44,40 +51,64 @@ type NetworkPeerBootstrapper interface {
|
||||
// the ignore map is populated, then the bootstrappers will be instructed to
|
||||
// skip those nodes.
|
||||
func MultiSourceBootstrap(ignore map[autopilot.NodeID]struct{}, numAddrs uint32,
|
||||
bootStrappers ...NetworkPeerBootstrapper) ([]*lnwire.NetAddress, error) {
|
||||
bootstrappers ...NetworkPeerBootstrapper) ([]*lnwire.NetAddress, error) {
|
||||
|
||||
// We'll randomly shuffle our bootstrappers before querying them in
|
||||
// order to avoid from querying the same bootstrapper method over and
|
||||
// over, as some of these might tend to provide better/worse results
|
||||
// than others.
|
||||
bootstrappers = shuffleBootstrappers(bootstrappers)
|
||||
|
||||
var addrs []*lnwire.NetAddress
|
||||
for _, bootStrapper := range bootStrappers {
|
||||
for _, bootstrapper := range bootstrappers {
|
||||
// If we already have enough addresses, then we can exit early
|
||||
// w/o querying the additional bootstrappers.
|
||||
if uint32(len(addrs)) >= numAddrs {
|
||||
break
|
||||
}
|
||||
|
||||
log.Infof("Attempting to bootstrap with: %v", bootStrapper.Name())
|
||||
log.Infof("Attempting to bootstrap with: %v", bootstrapper.Name())
|
||||
|
||||
// If we still need additional addresses, then we'll compute
|
||||
// the number of address remaining that we need to fetch.
|
||||
numAddrsLeft := numAddrs - uint32(len(addrs))
|
||||
log.Tracef("Querying for %v addresses", numAddrsLeft)
|
||||
netAddrs, err := bootStrapper.SampleNodeAddrs(numAddrsLeft, ignore)
|
||||
netAddrs, err := bootstrapper.SampleNodeAddrs(numAddrsLeft, ignore)
|
||||
if err != nil {
|
||||
// If we encounter an error with a bootstrapper, then
|
||||
// we'll continue on to the next available
|
||||
// bootstrapper.
|
||||
log.Errorf("Unable to query bootstrapper %v: %v",
|
||||
bootStrapper.Name(), err)
|
||||
bootstrapper.Name(), err)
|
||||
continue
|
||||
}
|
||||
|
||||
addrs = append(addrs, netAddrs...)
|
||||
}
|
||||
|
||||
if len(addrs) == 0 {
|
||||
return nil, errors.New("no addresses found")
|
||||
}
|
||||
|
||||
log.Infof("Obtained %v addrs to bootstrap network with", len(addrs))
|
||||
|
||||
return addrs, nil
|
||||
}
|
||||
|
||||
// shuffleBootstrappers shuffles the set of bootstrappers in order to avoid
|
||||
// querying the same bootstrapper over and over. To shuffle the set of
|
||||
// candidates, we use a version of the Fisher–Yates shuffle algorithm.
|
||||
func shuffleBootstrappers(candidates []NetworkPeerBootstrapper) []NetworkPeerBootstrapper {
|
||||
shuffled := make([]NetworkPeerBootstrapper, len(candidates))
|
||||
perm := prand.Perm(len(candidates))
|
||||
|
||||
for i, v := range perm {
|
||||
shuffled[v] = candidates[i]
|
||||
}
|
||||
|
||||
return shuffled
|
||||
}
|
||||
|
||||
// ChannelGraphBootstrapper is an implementation of the NetworkPeerBootstrapper
|
||||
// which attempts to retrieve advertised peers directly from the active channel
|
||||
// graph. This instance requires a backing autopilot.ChannelGraph instance in
|
||||
|
Loading…
Reference in New Issue
Block a user