1#![allow(clippy::expect_used)]
11#![allow(clippy::enum_variant_names)]
12
13#[macro_use]
26extern crate tracing;
27
28pub mod bootstrap;
29pub mod cache_store;
30pub mod config;
31pub mod contacts_fetcher;
32pub mod error;
33
34use ant_protocol::version::{get_network_id_str, get_truncate_version_str};
35use libp2p::{Multiaddr, PeerId, multiaddr::Protocol};
36use thiserror::Error;
37
38pub use bootstrap::Bootstrap;
39pub use cache_store::BootstrapCacheStore;
40pub use config::BootstrapConfig;
41pub use config::InitialPeersConfig;
42pub use contacts_fetcher::ContactsFetcher;
43pub use error::{Error, Result};
44
45pub const ANT_PEERS_ENV: &str = "ANT_PEERS";
47
48pub fn craft_valid_multiaddr(addr: &Multiaddr, ignore_peer_id: bool) -> Option<Multiaddr> {
52 let peer_id = addr
53 .iter()
54 .find(|protocol| matches!(protocol, Protocol::P2p(_)));
55
56 let mut output_address = Multiaddr::empty();
57
58 let ip = addr
59 .iter()
60 .find(|protocol| matches!(protocol, Protocol::Ip4(_)))?;
61 output_address.push(ip);
62
63 let udp = addr
64 .iter()
65 .find(|protocol| matches!(protocol, Protocol::Udp(_)));
66 let tcp = addr
67 .iter()
68 .find(|protocol| matches!(protocol, Protocol::Tcp(_)));
69
70 if let Some(udp) = udp {
72 output_address.push(udp);
73 if let Some(quic) = addr
74 .iter()
75 .find(|protocol| matches!(protocol, Protocol::QuicV1))
76 {
77 output_address.push(quic);
78 }
79 } else if let Some(tcp) = tcp {
80 output_address.push(tcp);
81
82 if let Some(ws) = addr
83 .iter()
84 .find(|protocol| matches!(protocol, Protocol::Ws(_)))
85 {
86 output_address.push(ws);
87 }
88 } else {
89 return None;
90 }
91
92 if let Some(peer_id) = peer_id {
93 output_address.push(peer_id);
94 } else if !ignore_peer_id {
95 return None;
96 }
97
98 Some(output_address)
99}
100
101pub fn craft_valid_multiaddr_from_str(addr_str: &str, ignore_peer_id: bool) -> Option<Multiaddr> {
103 let Ok(addr) = addr_str.parse::<Multiaddr>() else {
104 warn!("Failed to parse multiaddr from str {addr_str}");
105 return None;
106 };
107 craft_valid_multiaddr(&addr, ignore_peer_id)
108}
109
110pub fn multiaddr_get_peer_id(addr: &Multiaddr) -> Option<PeerId> {
111 match addr.iter().find(|p| matches!(p, Protocol::P2p(_))) {
112 Some(Protocol::P2p(id)) => Some(id),
113 _ => None,
114 }
115}
116
117pub fn get_network_version() -> String {
118 format!("{}_{}", get_network_id_str(), get_truncate_version_str())
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124 use libp2p::Multiaddr;
125
126 #[test]
127 fn test_transport_protocol_variants() {
128 let variants = [
129 (
130 "/ip4/127.0.0.1/udp/8080/quic-v1/p2p/12D3KooWRBhwfeP2Y4TCx1SM6s9rUoHhR5STiGwxBhgFRcw3UERE",
131 true,
132 ),
133 (
134 "/ip4/127.0.0.1/tcp/8080/ws/p2p/12D3KooWRBhwfeP2Y4TCx1SM6s9rUoHhR5STiGwxBhgFRcw3UERE",
135 true,
136 ),
137 (
138 "/ip4/127.0.0.1/tcp/8080/p2p/12D3KooWRBhwfeP2Y4TCx1SM6s9rUoHhR5STiGwxBhgFRcw3UERE",
139 true,
140 ),
141 ("/ip4/127.0.0.1/tcp/8080", false),
142 (
143 "/ip4/127.0.0.1/p2p/12D3KooWRBhwfeP2Y4TCx1SM6s9rUoHhR5STiGwxBhgFRcw3UERE",
144 false,
145 ),
146 (
147 "/ip4/127.0.0.1/wss/p2p/12D3KooWRBhwfeP2Y4TCx1SM6s9rUoHhR5STiGwxBhgFRcw3UERE",
148 false,
149 ),
150 ];
151
152 for (addr, should_be_valid) in variants {
153 let parsed: Multiaddr = addr.parse().unwrap();
154 let result = craft_valid_multiaddr(&parsed, false);
155
156 if should_be_valid {
157 let crafted = result.unwrap_or_else(|| panic!("Expected valid multiaddr: {addr}"));
158 assert_eq!(crafted.to_string(), parsed.to_string());
159 } else {
160 assert!(result.is_none(), "Expected invalid multiaddr: {addr}");
161 }
162 }
163 }
164
165 #[test]
166 fn test_craft_valid_multiaddr_from_str() {
167 let valid = "/ip4/127.0.0.1/udp/8080/quic-v1/p2p/12D3KooWRBhwfeP2Y4TCx1SM6s9rUoHhR5STiGwxBhgFRcw3UERE";
168 assert!(craft_valid_multiaddr_from_str(valid, false).is_some());
169
170 let invalid = "not a multiaddr";
171 assert!(craft_valid_multiaddr_from_str(invalid, false).is_none());
172
173 let missing_peer = "/ip4/127.0.0.1/tcp/8080";
174 assert!(craft_valid_multiaddr_from_str(missing_peer, false).is_none());
175 assert!(craft_valid_multiaddr_from_str(missing_peer, true).is_some());
176 }
177
178 #[test]
179 fn test_craft_valid_multiaddr_ignore_peer_id() {
180 let addr_without_peer: Multiaddr = "/ip4/127.0.0.1/udp/8080/quic-v1".parse().unwrap();
181 assert!(craft_valid_multiaddr(&addr_without_peer, false).is_none());
182 assert!(craft_valid_multiaddr(&addr_without_peer, true).is_some());
183 }
184
185 #[test]
186 fn test_multiaddr_get_peer_id() {
187 let addr_with_peer: Multiaddr =
188 "/ip4/127.0.0.1/udp/8080/quic-v1/p2p/12D3KooWRBhwfeP2Y4TCx1SM6s9rUoHhR5STiGwxBhgFRcw3UERE"
189 .parse()
190 .unwrap();
191 assert!(multiaddr_get_peer_id(&addr_with_peer).is_some());
192
193 let addr_without_peer: Multiaddr = "/ip4/127.0.0.1/udp/8080/quic-v1".parse().unwrap();
194 assert!(multiaddr_get_peer_id(&addr_without_peer).is_none());
195 }
196}