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 }