/ crates / libp2p-ui / src / p2p.rs
p2p.rs
  1  use std::{
  2      hash::{DefaultHasher, Hash as _, Hasher as _},
  3      time::Duration,
  4  };
  5  
  6  use anyhow::Error;
  7  use culpa::throws;
  8  use libp2p::{
  9      Multiaddr, PeerId, Swarm, dcutr, gossipsub, identify,
 10      kad::{self, store::MemoryStore},
 11      mdns, noise, ping, relay, tcp, yamux,
 12  };
 13  use libp2p_swarm::NetworkBehaviour;
 14  
 15  const BOOTSTRAP: &str = "/dnsaddr/bootstrap.libp2p.io";
 16  
 17  const BOOTNODES: [&str; 4] = [
 18      "QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
 19      "QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa",
 20      "QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb",
 21      "QmcZf59bWwK5XFi76CZX8cbJ4BhTzzA3gU1ZjYZcYW3dwt",
 22  ];
 23  
 24  #[derive(NetworkBehaviour)]
 25  pub struct PeerieBehaviour {
 26      pub dcutr: dcutr::Behaviour,
 27      pub gossipsub: gossipsub::Behaviour,
 28      pub identify: identify::Behaviour,
 29      pub kad: kad::Behaviour<MemoryStore>,
 30      pub mdns: mdns::tokio::Behaviour,
 31      pub ping: ping::Behaviour,
 32      pub stream: libp2p_stream::Behaviour,
 33      pub relay_client: relay::client::Behaviour,
 34      // pub relay_server: relay::Behaviour,
 35  }
 36  
 37  impl PeerieBehaviour {
 38      #[throws]
 39      pub async fn try_init_swarm() -> Swarm<PeerieBehaviour> {
 40          let mut swarm = libp2p::SwarmBuilder::with_new_identity()
 41              .with_tokio()
 42              .with_tcp(
 43                  tcp::Config::default(),
 44                  noise::Config::new,
 45                  yamux::Config::default,
 46              )?
 47              .with_quic()
 48              .with_relay_client(noise::Config::new, yamux::Config::default)?
 49              .with_behaviour(|key, relay_client| {
 50                  let dcutr = dcutr::Behaviour::new(key.public().to_peer_id());
 51  
 52                  // To content-address message, we can take the hash of message and use it as an ID.
 53                  let message_id_fn = |message: &gossipsub::Message| {
 54                      let mut s = DefaultHasher::new();
 55                      message.data.hash(&mut s);
 56                      gossipsub::MessageId::from(s.finish().to_string())
 57                  };
 58  
 59                  // Set a custom gossipsub configuration
 60                  let gossipsub_config = gossipsub::ConfigBuilder::default()
 61                      .heartbeat_interval(Duration::from_secs(10)) // This is set to aid debugging by not cluttering the log space
 62                      .validation_mode(gossipsub::ValidationMode::Strict) // This sets the kind of message validation. The default is Strict (enforce message signing)
 63                      .message_id_fn(message_id_fn) // content-address messages. No two messages of the same content will be propagated.
 64                      .build()?;
 65  
 66                  // build a gossipsub network behaviour
 67                  let gossipsub = gossipsub::Behaviour::new(
 68                      gossipsub::MessageAuthenticity::Signed(key.clone()),
 69                      gossipsub_config,
 70                  )?;
 71  
 72                  let identify = identify::Behaviour::new(identify::Config::new(
 73                      "/prototype/0.0.1".to_string(),
 74                      key.public(),
 75                  ));
 76  
 77                  let kad = {
 78                      let mut kad = kad::Behaviour::new(
 79                          key.public().to_peer_id(),
 80                          MemoryStore::new(key.public().to_peer_id()),
 81                      );
 82  
 83                      let bootaddr = BOOTSTRAP.parse::<Multiaddr>()?;
 84                      for peer in &BOOTNODES {
 85                          kad.add_address(&peer.parse::<PeerId>()?, bootaddr.clone());
 86                      }
 87  
 88                      kad
 89                  };
 90  
 91                  let mdns = mdns::tokio::Behaviour::new(
 92                      mdns::Config::default(),
 93                      key.public().to_peer_id(),
 94                  )?;
 95  
 96                  let ping =
 97                      ping::Behaviour::new(ping::Config::new().with_interval(Duration::from_secs(3)));
 98  
 99                  // let relay_server =
100                  //     relay::Behaviour::new(key.public().to_peer_id(), Default::default());
101                  let stream = libp2p_stream::Behaviour::new();
102  
103                  Ok(PeerieBehaviour {
104                      dcutr,
105                      gossipsub,
106                      identify,
107                      kad,
108                      mdns,
109                      ping,
110                      stream,
111                      relay_client,
112                      // relay_server,
113                  })
114              })?
115              .with_swarm_config(|c| c.with_idle_connection_timeout(Duration::from_secs(60)))
116              .build();
117  
118          // Create a Gossipsub topic
119          // let topic = gossipsub::IdentTopic::new("test-net");
120          // subscribes to our topic
121          // swarm.behaviour_mut().gossipsub.subscribe(&topic)?;
122  
123          // Listen on all interfaces and whatever port the OS assigns
124          swarm.listen_on("/ip4/0.0.0.0/udp/0/quic-v1".parse()?)?;
125          swarm.listen_on("/ip4/0.0.0.0/tcp/0".parse()?)?;
126          let local_peer_id = *swarm.local_peer_id();
127          let query_id = swarm.behaviour_mut().kad.get_closest_peers(local_peer_id);
128          tracing::info!(%local_peer_id, %query_id, "Kademlia query");
129  
130          // swarm.listen_on(
131          //     BOOTSTRAP
132          //         .parse::<Multiaddr>()
133          //         .unwrap()
134          //         .with(Protocol::P2pCircuit),
135          // )?;
136  
137          swarm
138      }
139  }