discovery: remove retries from DNS based SampleNodeAddrs, allow down seeds

In this commit, we modify the `SampleNodeAddrs` method to no longer
retry itself. Instead, we'll now leave this task to the caller of the
this method. Additionally, we'll no longer return with an error if we
can't hit a particular seed. Instead, we'll log the error and move onto
the next seed. Finally, we'll also no longer require that the DNS seed
has a secondary seed in order to support a wider array of DNS seeds.
This commit is contained in:
Olaoluwa Osuntokun 2019-06-27 18:48:57 -07:00
parent 7f48ff6717
commit 9c957193cf
No known key found for this signature in database
GPG Key ID: CE58F7F8E20FD9A2

@ -379,59 +379,64 @@ func (d *DNSSeedBootstrapper) SampleNodeAddrs(numAddrs uint32,
var netAddrs []*lnwire.NetAddress
// We'll continue this loop until we reach our target address limit.
// Each SRV query to the seed will return 25 random nodes, so we can
// continue to query until we reach our target.
// We'll try all the registered DNS seeds, exiting early if one of them
// gives us all the peers we need.
//
// TODO(roasbeef): should combine results from both
search:
for uint32(len(netAddrs)) < numAddrs {
for _, dnsSeedTuple := range d.dnsSeeds {
// We'll first query the seed with an SRV record so we
// can obtain a random sample of the encoded public
// keys of nodes. We use the lndLookupSRV function for
// this task.
// We'll first query the seed with an SRV record so we can
// obtain a random sample of the encoded public keys of nodes.
// We use the lndLookupSRV function for this task.
primarySeed := dnsSeedTuple[0]
_, addrs, err := d.net.LookupSRV("nodes", "tcp", primarySeed)
if err != nil {
log.Tracef("Unable to lookup SRV records via "+
"primary seed: %v", err)
"primary seed (%v): %v", primarySeed, err)
log.Trace("Falling back to secondary")
// If the host of the secondary seed is blank,
// then we'll bail here as we can't proceed.
// If the host of the secondary seed is blank, then
// we'll bail here as we can't proceed.
if dnsSeedTuple[1] == "" {
return nil, fmt.Errorf("Secondary seed is blank")
log.Tracef("DNS seed %v has no secondary, "+
"skipping fallback", primarySeed)
continue
}
// If we get an error when trying to query via
// the primary seed, we'll fallback to the
// secondary seed before concluding failure.
// If we get an error when trying to query via the
// primary seed, we'll fallback to the secondary seed
// before concluding failure.
soaShim := dnsSeedTuple[1]
addrs, err = d.fallBackSRVLookup(
soaShim, primarySeed,
)
if err != nil {
return nil, err
log.Tracef("Unable to query fall "+
"back dns seed (%v): %v", soaShim, err)
continue
}
log.Tracef("Successfully queried fallback DNS seed")
}
log.Tracef("Retrieved SRV records from dns seed: %v",
spew.Sdump(addrs))
newLogClosure(func() string {
return spew.Sdump(addrs)
}),
)
// Next, we'll need to issue an A record request for
// each of the nodes, skipping it if nothing comes
// back.
// Next, we'll need to issue an A record request for each of
// the nodes, skipping it if nothing comes back.
for _, nodeSrv := range addrs {
if uint32(len(netAddrs)) >= numAddrs {
break search
}
// With the SRV target obtained, we'll now
// perform another query to obtain the IP
// address for the matching bech32 encoded node
// key. We use the lndLookup function for this
// task.
// With the SRV target obtained, we'll now perform
// another query to obtain the IP address for the
// matching bech32 encoded node key. We use the
// lndLookup function for this task.
bechNodeHost := nodeSrv.Target
addrs, err := d.net.LookupHost(bechNodeHost)
if err != nil {
@ -446,20 +451,27 @@ search:
log.Tracef("Attempting to convert: %v", bechNodeHost)
// If we have a set of valid addresses, then
// we'll need to parse the public key from the
// original bech32 encoded string.
// If the host isn't correctly formatted, then we'll
// skip it.
if len(bechNodeHost) == 0 ||
!strings.Contains(bechNodeHost, ".") {
continue
}
// If we have a set of valid addresses, then we'll need
// to parse the public key from the original bech32
// encoded string.
bechNode := strings.Split(bechNodeHost, ".")
_, nodeBytes5Bits, err := bech32.Decode(bechNode[0])
if err != nil {
return nil, err
}
// Once we have the bech32 decoded pubkey,
// we'll need to convert the 5-bit word
// grouping into our regular 8-bit word
// grouping so we can convert it into a public
// key.
// Once we have the bech32 decoded pubkey, we'll need
// to convert the 5-bit word grouping into our regular
// 8-bit word grouping so we can convert it into a
// public key.
nodeBytes, err := bech32.ConvertBits(
nodeBytes5Bits, 5, 8, false,
)
@ -473,9 +485,8 @@ search:
return nil, err
}
// If we have an ignore list, and this node is
// in the ignore list, then we'll go to the
// next candidate.
// If we have an ignore list, and this node is in the
// ignore list, then we'll go to the next candidate.
if ignore != nil {
nID := autopilot.NewNodeID(nodeKey)
if _, ok := ignore[nID]; ok {
@ -483,21 +494,22 @@ search:
}
}
// Finally we'll convert the host:port peer to
// a proper TCP address to use within the
// lnwire.NetAddress. We don't need to use
// the lndResolveTCP function here because we
// already have the host:port peer.
addr := net.JoinHostPort(addrs[0],
strconv.FormatUint(uint64(nodeSrv.Port), 10))
// Finally we'll convert the host:port peer to a proper
// TCP address to use within the lnwire.NetAddress. We
// don't need to use the lndResolveTCP function here
// because we already have the host:port peer.
addr := net.JoinHostPort(
addrs[0],
strconv.FormatUint(uint64(nodeSrv.Port), 10),
)
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
return nil, err
}
// Finally, with all the information parsed,
// we'll return this fully valid address as a
// connection attempt.
// Finally, with all the information parsed, we'll
// return this fully valid address as a connection
// attempt.
lnAddr := &lnwire.NetAddress{
IdentityKey: nodeKey,
Address: tcpAddr,
@ -509,7 +521,6 @@ search:
netAddrs = append(netAddrs, lnAddr)
}
}
}
return netAddrs, nil
}