@@ -95,6 +95,12 @@ pub struct NetworkNode {
9595 /// Bootstrap peers to connect to
9696 bootstrap_peers : Vec < Multiaddr > ,
9797
98+ /// Bootstrap peer IDs (extracted from multiaddrs)
99+ bootstrap_peer_ids : HashSet < PeerId > ,
100+
101+ /// Whether we've ever successfully connected to a bootstrap peer
102+ bootstrap_connected : Arc < RwLock < bool > > ,
103+
98104 /// Event sender
99105 event_tx : mpsc:: Sender < NetworkEvent > ,
100106
@@ -138,11 +144,28 @@ impl NetworkNode {
138144
139145 let ( event_tx, event_rx) = mpsc:: channel ( 1000 ) ;
140146
147+ // Extract peer IDs from bootstrap multiaddrs
148+ let bootstrap_peer_ids: HashSet < PeerId > = config
149+ . bootstrap_peers
150+ . iter ( )
151+ . filter_map ( |addr| {
152+ addr. iter ( ) . find_map ( |p| {
153+ if let libp2p:: multiaddr:: Protocol :: P2p ( peer_id) = p {
154+ Some ( peer_id)
155+ } else {
156+ None
157+ }
158+ } )
159+ } )
160+ . collect ( ) ;
161+
141162 Ok ( Self {
142163 swarm,
143164 local_peer_id,
144165 peers : Arc :: new ( RwLock :: new ( HashSet :: new ( ) ) ) ,
145166 bootstrap_peers : config. bootstrap_peers . clone ( ) ,
167+ bootstrap_peer_ids,
168+ bootstrap_connected : Arc :: new ( RwLock :: new ( false ) ) ,
146169 event_tx,
147170 event_rx : Some ( event_rx) ,
148171 } )
@@ -193,14 +216,24 @@ impl NetworkNode {
193216 if self . bootstrap_peers . is_empty ( ) {
194217 return true ; // No bootstrap peers configured
195218 }
196- // Check if we have any peers connected
197- !self . peers . read ( ) . is_empty ( )
219+ // Check if we're connected to at least one bootstrap peer
220+ let peers = self . peers . read ( ) ;
221+ for peer in peers. iter ( ) {
222+ if self . bootstrap_peer_ids . contains ( peer) {
223+ return true ;
224+ }
225+ }
226+ false
198227 }
199228
200229 /// Retry connecting to bootstrap peers if not connected
201230 pub fn retry_bootstrap_if_needed ( & mut self ) {
231+ if self . bootstrap_peers . is_empty ( ) {
232+ return ; // No bootnode configured
233+ }
234+
202235 if !self . has_bootstrap_connection ( ) {
203- info ! ( "No peers connected, retrying bootstrap peers ..." ) ;
236+ info ! ( "Not connected to bootnode , retrying in 30s ..." ) ;
204237 self . dial_bootstrap_peers ( ) ;
205238 }
206239 }
@@ -238,40 +271,8 @@ impl NetworkNode {
238271
239272 /// Process the next swarm event (single step)
240273 pub async fn process_next_event ( & mut self ) {
241- match self . swarm . select_next_some ( ) . await {
242- SwarmEvent :: Behaviour ( event) => {
243- self . handle_behaviour_event ( event) . await ;
244- }
245- SwarmEvent :: NewListenAddr { address, .. } => {
246- info ! ( "Listening on {}" , address) ;
247- }
248- SwarmEvent :: ConnectionEstablished { peer_id, .. } => {
249- info ! ( "Connected to peer: {}" , peer_id) ;
250- self . peers . write ( ) . insert ( peer_id) ;
251- let _ = self
252- . event_tx
253- . send ( NetworkEvent :: PeerConnected ( peer_id) )
254- . await ;
255- }
256- SwarmEvent :: ConnectionClosed { peer_id, .. } => {
257- info ! ( "Disconnected from peer: {}" , peer_id) ;
258- self . peers . write ( ) . remove ( & peer_id) ;
259- let _ = self
260- . event_tx
261- . send ( NetworkEvent :: PeerDisconnected ( peer_id) )
262- . await ;
263- }
264- SwarmEvent :: IncomingConnection { .. } => { }
265- SwarmEvent :: OutgoingConnectionError {
266- peer_id : Some ( peer_id) ,
267- error,
268- ..
269- } => {
270- warn ! ( "Failed to connect to {}: {}" , peer_id, error) ;
271- }
272- SwarmEvent :: OutgoingConnectionError { .. } => { }
273- _ => { }
274- }
274+ let event = self . swarm . select_next_some ( ) . await ;
275+ self . handle_swarm_event ( event) . await ;
275276 }
276277
277278 /// Run the event loop (should be spawned as a task)
@@ -302,15 +303,26 @@ impl NetworkNode {
302303 info ! ( "Listening on {}" , address) ;
303304 }
304305 SwarmEvent :: ConnectionEstablished { peer_id, .. } => {
305- info ! ( "Connected to peer: {}" , peer_id) ;
306+ let is_bootstrap = self . bootstrap_peer_ids . contains ( & peer_id) ;
307+ if is_bootstrap {
308+ info ! ( "Connected to bootnode: {}" , peer_id) ;
309+ * self . bootstrap_connected . write ( ) = true ;
310+ } else {
311+ info ! ( "Connected to peer: {}" , peer_id) ;
312+ }
306313 self . peers . write ( ) . insert ( peer_id) ;
307314 let _ = self
308315 . event_tx
309316 . send ( NetworkEvent :: PeerConnected ( peer_id) )
310317 . await ;
311318 }
312319 SwarmEvent :: ConnectionClosed { peer_id, .. } => {
313- info ! ( "Disconnected from peer: {}" , peer_id) ;
320+ let is_bootstrap = self . bootstrap_peer_ids . contains ( & peer_id) ;
321+ if is_bootstrap {
322+ info ! ( "Disconnected from bootnode: {}" , peer_id) ;
323+ } else {
324+ info ! ( "Disconnected from peer: {}" , peer_id) ;
325+ }
314326 self . peers . write ( ) . remove ( & peer_id) ;
315327 let _ = self
316328 . event_tx
@@ -323,7 +335,12 @@ impl NetworkNode {
323335 error,
324336 ..
325337 } => {
326- warn ! ( "Failed to connect to {}: {}" , peer_id, error) ;
338+ let is_bootstrap = self . bootstrap_peer_ids . contains ( & peer_id) ;
339+ if is_bootstrap {
340+ warn ! ( "Failed to connect to bootnode {}: {} (will retry in 30s)" , peer_id, error) ;
341+ } else {
342+ warn ! ( "Failed to connect to {}: {}" , peer_id, error) ;
343+ }
327344 }
328345 SwarmEvent :: OutgoingConnectionError { .. } => { }
329346 _ => { }
0 commit comments