Connection is not esthablished

I’m trying to establish a connection using rust linp2p but somehow it dosen’t work, this is my first time using it anyway

use libp2p::{
    futures::StreamExt,
    gossipsub::{self, IdentTopic},
    noise, ping,
    swarm::{NetworkBehaviour, SwarmEvent},
    tcp, yamux, Multiaddr, Swarm, SwarmBuilder,
};
use std::error::Error;
use std::time::Duration;
use tokio::signal;

#[derive(Debug)]
enum LightClientEvent {
    Ping(ping::Event),
    Gossipsub(gossipsub::Event),
}

impl From<ping::Event> for LightClientEvent {
    fn from(event: ping::Event) -> Self {
        LightClientEvent::Ping(event)
    }
}

impl From<gossipsub::Event> for LightClientEvent {
    fn from(event: gossipsub::Event) -> Self {
        LightClientEvent::Gossipsub(event)
    }
}

#[derive(NetworkBehaviour)]
#[behaviour(out_event = "LightClientEvent")]
struct LightClientBehaviour {
    gossipsub: gossipsub::Behaviour,
    ping: ping::Behaviour,
}

pub struct LightClient {
    swarm: Swarm<LightClientBehaviour>,
}

impl LightClient {
    pub fn new() -> Result<Self, Box<dyn Error>> {
        let mut swarm = SwarmBuilder::with_new_identity()
            .with_tokio()
            .with_tcp(
                tcp::Config::default(),
                noise::Config::new,
                yamux::Config::default,
            )?
            .with_behaviour(|_key| {
                let gossipsub_config = gossipsub::ConfigBuilder::default()
                    .flood_publish(true)
                    .history_length(5)
                    .validation_mode(gossipsub::ValidationMode::Anonymous)
                    .build()?;

                let mut gossipsub = gossipsub::Behaviour::new(
                    gossipsub::MessageAuthenticity::Anonymous,
                    gossipsub_config,
                )?;

                gossipsub.subscribe(&IdentTopic::new(
                    "/eth2/beacon_chain/light_client/finality_update/1/",
                ))?;
                gossipsub.subscribe(&IdentTopic::new(
                    "/eth2/beacon_chain/light_client/optimistic_update/1/",
                ))?;

                Ok(LightClientBehaviour {
                    gossipsub,
                    ping: ping::Behaviour::default(),
                })
            })?
            .build();

        swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;

        Ok(Self { swarm })
    }

    pub async fn start(&mut self) -> Result<(), Box<dyn Error>> {
        loop {
            tokio::select! {
                event = self.swarm.select_next_some() => {
                    match event {
                        SwarmEvent::NewListenAddr { address, .. } => {
                            println!("Listening on {:?}", address);
                        }
                        SwarmEvent::Behaviour(event) => {
                            println!("Behaviour event: {:?}", event);
                        }
                        _ => {}
                    }
                }
                _ = signal::ctrl_c() => {
                    println!("Shutting down...");
                    break;
                }
            }
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[tokio::test]
    async fn test_light_client_network() -> Result<(), Box<dyn Error>> {
        let mut client1 = LightClient::new()?;
        let mut client2 = LightClient::new()?;

        let addr = if let Some(SwarmEvent::NewListenAddr { address, .. }) = client1.swarm.next().await {
            address
        } else {
            return Err("No listen address".into());
        };

        client2.swarm.dial(addr.clone())?;

        // Wait for connection
        let mut connected = false;
        for _ in 0..10 {
            if let Some(SwarmEvent::ConnectionEstablished { .. }) = client2.swarm.next().await {
                connected = true;
                break;
            }
            tokio::time::sleep(Duration::from_secs(1)).await;
        }

        if !connected {
            return Err("Connection not established".into());
        }

        // Publish a message
        let msg_id = client1.swarm.behaviour_mut().gossipsub.publish(
            IdentTopic::new("/eth2/beacon_chain/light_client/finality_update/1/"),
            b"test".to_vec(),
        )?;
        println!("Published message: {:?}", msg_id);

        Ok(())
    }
}

I mean the test, I’m trying to build a light client using libp2p

Hi!

From what I can see, I think the main problem is that you are not making an initial connection, i.e. bootstrap your peer so that it makes the network aware of its existence, as well as learning other peers.

Depending on the peer-discovery method that this network uses, you will likely need to add more Behaviour to your implementation.

Here is an example that uses Kademlia with mDNS, see where it adds an address to Kademlia here.

In another example, Kademlia uses the bootstrap as I mentioned above, and it has access to a static list of addresses on launch, which you probably need!

We can see some bootnode addresses here but I’m not entirely sure how those translate to addresses on this side. :confused:

1 Like