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(())
}
}