node: configure p2p routing table with bootstrapping nodes (#1455)

Configure the bootstrapping nodes that we will connect to to seed and refresh
the Routing Table if it becomes empty.

Fixes an issue where the spy stops receiving gossiped messages after the node
is restarted, because the Routing Table becomes empty and is never refreshed.
This commit is contained in:
kev1n-peters 2022-08-24 11:27:59 -05:00 committed by GitHub
parent 33f1b28662
commit 536a97066e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 24 additions and 46 deletions

View File

@ -92,17 +92,40 @@ func Run(obsvC chan *gossipv1.SignedObservation, obsvReqC chan *gossipv1.Observa
// Let's prevent our peer from having too many
// connections by attaching a connection manager.
libp2p.ConnectionManager(connmgr.NewConnManager(
100, // Lowwater
100, // LowWater
400, // HighWater,
time.Minute, // GracePeriod
)),
// Let this host use the DHT to find other hosts
libp2p.Routing(func(h host.Host) (routing.PeerRouting, error) {
logger.Info("Connecting to bootstrap peers", zap.String("bootstrap_peers", bootstrapPeers))
bootstrappers := make([]peer.AddrInfo, 0)
for _, addr := range strings.Split(bootstrapPeers, ",") {
if addr == "" {
continue
}
ma, err := multiaddr.NewMultiaddr(addr)
if err != nil {
logger.Error("Invalid bootstrap address", zap.String("peer", addr), zap.Error(err))
continue
}
pi, err := peer.AddrInfoFromP2pAddr(ma)
if err != nil {
logger.Error("Invalid bootstrap address", zap.String("peer", addr), zap.Error(err))
continue
}
if pi.ID == h.ID() {
logger.Info("We're a bootstrap node")
continue
}
bootstrappers = append(bootstrappers, *pi)
}
// TODO(leo): Persistent data store (i.e. address book)
idht, err := dht.New(ctx, h, dht.Mode(dht.ModeServer),
// This intentionally makes us incompatible with the global IPFS DHT
dht.ProtocolPrefix(protocol.ID("/"+networkID)),
dht.BootstrapPeers(bootstrappers...),
)
return idht, err
}),
@ -118,8 +141,6 @@ func Run(obsvC chan *gossipv1.SignedObservation, obsvReqC chan *gossipv1.Observa
rootCtxCancel()
}()
logger.Info("Connecting to bootstrap peers", zap.String("bootstrap_peers", bootstrapPeers))
topic := fmt.Sprintf("%s/%s", networkID, "broadcast")
logger.Info("Subscribing pubsub topic", zap.String("topic", topic))
@ -138,49 +159,6 @@ func Run(obsvC chan *gossipv1.SignedObservation, obsvReqC chan *gossipv1.Observa
return fmt.Errorf("failed to subscribe topic: %w", err)
}
// Add our own bootstrap nodes
// Count number of successful connection attempts. If we fail to connect to any bootstrap peer, kill
// the service and have supervisor retry it.
successes := 0
// Are we a bootstrap node? If so, it's okay to not have any peers.
bootstrapNode := false
for _, addr := range strings.Split(bootstrapPeers, ",") {
if addr == "" {
continue
}
ma, err := multiaddr.NewMultiaddr(addr)
if err != nil {
logger.Error("Invalid bootstrap address", zap.String("peer", addr), zap.Error(err))
continue
}
pi, err := peer.AddrInfoFromP2pAddr(ma)
if err != nil {
logger.Error("Invalid bootstrap address", zap.String("peer", addr), zap.Error(err))
continue
}
if pi.ID == h.ID() {
logger.Info("We're a bootstrap node")
bootstrapNode = true
continue
}
if err = h.Connect(ctx, *pi); err != nil {
logger.Error("Failed to connect to bootstrap peer", zap.String("peer", addr), zap.Error(err))
} else {
successes += 1
}
}
// TODO: continually reconnect to bootstrap nodes?
if successes == 0 && !bootstrapNode {
return fmt.Errorf("failed to connect to any bootstrap peer")
} else {
logger.Info("Connected to bootstrap peers", zap.Int("num", successes))
}
logger.Info("Node has been started", zap.String("peer_id", h.ID().String()),
zap.String("addrs", fmt.Sprintf("%v", h.Addrs())))