@@ -95,6 +95,8 @@ type P2p struct {
9595 bootstrapPeers []peer.AddrInfo
9696 startedAt time.Time
9797 bootstrapsInfo atomic.Pointer [map [string ]BootstrapPeerDebugInfo ]
98+
99+ dhtBootstrapFinishedChan chan struct {}
98100}
99101
100102func NewP2p (ctx context.Context ) * P2p {
@@ -103,6 +105,8 @@ func NewP2p(ctx context.Context) *P2p {
103105 ctx : newCtx ,
104106 ctxCancel : ctxCancel ,
105107 logger : log .Logger ("awl/p2p" ),
108+
109+ dhtBootstrapFinishedChan : make (chan struct {}),
106110 }
107111}
108112
@@ -300,45 +304,68 @@ func (p *P2p) SubscribeConnectionEvents(onConnected, onDisconnected func(network
300304 p .host .Network ().Notify (notifyBundle )
301305}
302306
303- func (p * P2p ) Bootstrap () error {
304- p .logger .Debug ("Bootstrapping the DHT" )
305- // connect to the bootstrap nodes first
306- ctx , cancel := context .WithTimeout (p .ctx , 2 * time .Second )
307- defer cancel ()
307+ func (p * P2p ) Bootstrap () {
308+ ctx , cancel := context .WithTimeout (p .ctx , 3 * time .Second )
308309 var wg sync.WaitGroup
310+ successfulConnectionsCh := make (chan struct {}, len (p .bootstrapPeers ))
309311
312+ p .logger .Debug ("Start bootstrapping the DHT" )
310313 for _ , peerAddr := range p .bootstrapPeers {
311314 wg .Add (1 )
312- p .host .ConnManager ().Protect (peerAddr .ID , protectedBootstrapPeerTag )
313-
314315 go func () {
315316 defer wg .Done ()
316317 if err := p .host .Connect (ctx , peerAddr ); err != nil && ! errors .Is (err , context .Canceled ) {
317318 p .logger .Warnf ("Failed to connect to bootstrap node %s: %v" , peerAddr .ID , err )
318319 } else if err == nil {
319320 p .logger .Infof ("Connection established with bootstrap node: %s" , peerAddr .ID )
321+ successfulConnectionsCh <- struct {}{}
320322 }
321323 }()
322324 }
323- wg .Wait ()
324- p .logger .Info ("Connection established with all bootstrap nodes" )
325325
326- if err := p .dht .Bootstrap (p .ctx ); err != nil {
327- return fmt .Errorf ("bootstrap dht: %v" , err )
328- }
326+ go func () {
327+ defer cancel ()
329328
330- return nil
329+ // wait for at least 2 bootstrap nodes
330+ for range min (2 , len (p .bootstrapPeers )) {
331+ select {
332+ case <- ctx .Done ():
333+ case <- successfulConnectionsCh :
334+ }
335+ }
336+
337+ p .logger .Info ("Bootstrapping the DHT" )
338+ if err := p .dht .Bootstrap (p .ctx ); err != nil {
339+ // from the code err is always nil for now
340+ p .logger .Warnf ("Failed to bootstrap DHT: %v" , err )
341+ }
342+ close (p .dhtBootstrapFinishedChan )
343+
344+ wg .Wait ()
345+ p .logger .Info ("Finished connecting to all bootstrap nodes" )
346+ }()
331347}
332348
333349func (p * P2p ) MaintainBackgroundConnections (ctx context.Context , interval time.Duration , knownPeersIdsFunc func () []peer.ID ) {
334- const firstTryInterval = 5 * time .Second
335- p .connectToKnownPeers (ctx , firstTryInterval , knownPeersIdsFunc ())
350+ const timeout = 5 * time .Second
351+ const firstRetryDelay = 5 * time .Second
352+
353+ // wait for bootstrapping
354+ select {
355+ case <- ctx .Done ():
356+ return
357+ case <- p .dhtBootstrapFinishedChan :
358+ }
359+
360+ p .connectToKnownPeers (ctx , timeout , knownPeersIdsFunc ())
361+
362+ // retry once after a short delay in case of network instability
336363 select {
337364 case <- ctx .Done ():
338365 return
339- case <- time .After (firstTryInterval ):
366+ case <- time .After (firstRetryDelay ):
340367 }
341- p .connectToKnownPeers (ctx , interval , knownPeersIdsFunc ())
368+ p .connectToKnownPeers (ctx , timeout , knownPeersIdsFunc ())
342369
343370 ticker := time .NewTicker (interval )
344371 defer ticker .Stop ()
@@ -350,7 +377,7 @@ func (p *P2p) MaintainBackgroundConnections(ctx context.Context, interval time.D
350377 case <- ticker .C :
351378 }
352379
353- p .connectToKnownPeers (ctx , interval , knownPeersIdsFunc ())
380+ p .connectToKnownPeers (ctx , timeout , knownPeersIdsFunc ())
354381 ticker .Reset (interval )
355382 }
356383}
@@ -380,6 +407,8 @@ func (p *P2p) connectToKnownPeers(ctx context.Context, timeout time.Duration, pe
380407
381408 for _ , peerAddr := range p .bootstrapPeers {
382409 wg .Add (1 )
410+ p .host .ConnManager ().Protect (peerAddr .ID , protectedBootstrapPeerTag )
411+
383412 go func () {
384413 defer wg .Done ()
385414
0 commit comments