1#[macro_use]
22extern crate tracing;
23
24mod cache_store;
25pub mod config;
26pub mod contacts;
27pub mod error;
28mod initial_peers;
29
30use ant_protocol::version::{get_network_id_str, get_truncate_version_str};
31use libp2p::{multiaddr::Protocol, Multiaddr, PeerId};
32use serde::{Deserialize, Serialize};
33use std::time::SystemTime;
34use thiserror::Error;
35
36pub use cache_store::BootstrapCacheStore;
37pub use config::BootstrapCacheConfig;
38pub use contacts::ContactsFetcher;
39pub use error::{Error, Result};
40pub use initial_peers::{InitialPeersConfig, ANT_PEERS_ENV};
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43pub struct BootstrapAddresses(pub Vec<BootstrapAddr>);
45
46impl BootstrapAddresses {
47 pub fn insert_addr(&mut self, addr: &BootstrapAddr) {
48 if let Some(bootstrap_addr) = self.get_addr_mut(&addr.addr) {
49 bootstrap_addr.sync(addr);
50 } else {
51 self.0.push(addr.clone());
52 }
53 }
54
55 pub fn get_addr(&self, addr: &Multiaddr) -> Option<&BootstrapAddr> {
56 self.0
57 .iter()
58 .find(|bootstrap_addr| &bootstrap_addr.addr == addr)
59 }
60
61 pub fn get_addr_mut(&mut self, addr: &Multiaddr) -> Option<&mut BootstrapAddr> {
62 self.0
63 .iter_mut()
64 .find(|bootstrap_addr| &bootstrap_addr.addr == addr)
65 }
66
67 pub fn get_least_faulty(&self) -> Option<&BootstrapAddr> {
68 self.0.iter().min_by_key(|addr| addr.failure_rate() as u64)
69 }
70
71 pub fn remove_addr(&mut self, addr: &Multiaddr) {
72 if let Some(idx) = self
73 .0
74 .iter()
75 .position(|bootstrap_addr| &bootstrap_addr.addr == addr)
76 {
77 let bootstrap_addr = self.0.remove(idx);
78 debug!("Removed {bootstrap_addr:?}");
79 }
80 }
81
82 pub fn sync(&mut self, other: &Self) {
83 for other_addr in other.0.iter() {
84 if let Some(bootstrap_addr) = self.get_addr_mut(&other_addr.addr) {
85 bootstrap_addr.sync(other_addr);
86 } else {
87 trace!(
88 "Addr {:?} from other not found in self, inserting it.",
89 other_addr.addr
90 );
91 self.insert_addr(other_addr);
92 }
93 }
94 }
95
96 pub fn update_addr_status(&mut self, addr: &Multiaddr, success: bool) {
97 if let Some(bootstrap_addr) = self.get_addr_mut(addr) {
98 bootstrap_addr.update_status(success);
99 } else {
100 debug!("Addr not found in cache to update, skipping: {addr:?}")
101 }
102 }
103}
104
105#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct BootstrapAddr {
108 pub addr: Multiaddr,
110 pub success_count: u32,
112 pub failure_count: u32,
114 pub last_seen: SystemTime,
116}
117
118impl BootstrapAddr {
119 pub fn new(addr: Multiaddr) -> Self {
120 Self {
121 addr,
122 success_count: 0,
123 failure_count: 0,
124 last_seen: SystemTime::now(),
125 }
126 }
127
128 pub fn peer_id(&self) -> Option<PeerId> {
129 multiaddr_get_peer_id(&self.addr)
130 }
131
132 pub fn update_status(&mut self, success: bool) {
133 if success {
134 if let Some(new_value) = self.success_count.checked_add(1) {
135 self.success_count = new_value;
136 } else {
137 self.success_count = 1;
138 self.failure_count = 0;
139 }
140 }
141 self.last_seen = SystemTime::now();
142 if !success {
143 if let Some(new_value) = self.failure_count.checked_add(1) {
144 self.failure_count = new_value;
145 } else {
146 self.failure_count = 1;
147 self.success_count = 0;
148 }
149 }
150 }
151
152 pub fn is_reliable(&self) -> bool {
154 self.success_count >= self.failure_count
155 }
156
157 pub fn sync(&mut self, other: &Self) {
159 trace!("Syncing our state {self:?} with and other: {other:?}.");
160 if self.last_seen == other.last_seen {
161 return;
162 }
163
164 self.success_count = self.success_count.saturating_add(other.success_count);
165 self.failure_count = self.failure_count.saturating_add(other.failure_count);
166
167 if self.success_count == u32::MAX {
169 self.success_count = 1;
170 self.failure_count = 0;
171 } else if self.failure_count == u32::MAX {
172 self.failure_count = 1;
173 self.success_count = 0;
174 }
175 self.last_seen = std::cmp::max(self.last_seen, other.last_seen);
176 trace!("Successfully synced BootstrapAddr: {self:?}");
177 }
178
179 fn failure_rate(&self) -> f64 {
180 if self.success_count + self.failure_count == 0 {
181 0.0
182 } else {
183 self.failure_count as f64 / (self.success_count + self.failure_count) as f64
184 }
185 }
186}
187
188pub fn craft_valid_multiaddr(addr: &Multiaddr, ignore_peer_id: bool) -> Option<Multiaddr> {
192 let peer_id = addr
193 .iter()
194 .find(|protocol| matches!(protocol, Protocol::P2p(_)));
195
196 let mut output_address = Multiaddr::empty();
197
198 let ip = addr
199 .iter()
200 .find(|protocol| matches!(protocol, Protocol::Ip4(_)))?;
201 output_address.push(ip);
202
203 let udp = addr
204 .iter()
205 .find(|protocol| matches!(protocol, Protocol::Udp(_)));
206 let tcp = addr
207 .iter()
208 .find(|protocol| matches!(protocol, Protocol::Tcp(_)));
209
210 if let Some(udp) = udp {
212 output_address.push(udp);
213 if let Some(quic) = addr
214 .iter()
215 .find(|protocol| matches!(protocol, Protocol::QuicV1))
216 {
217 output_address.push(quic);
218 }
219 } else if let Some(tcp) = tcp {
220 output_address.push(tcp);
221
222 if let Some(ws) = addr
223 .iter()
224 .find(|protocol| matches!(protocol, Protocol::Ws(_)))
225 {
226 output_address.push(ws);
227 }
228 } else {
229 return None;
230 }
231
232 if let Some(peer_id) = peer_id {
233 output_address.push(peer_id);
234 } else if !ignore_peer_id {
235 return None;
236 }
237
238 Some(output_address)
239}
240
241pub fn craft_valid_multiaddr_from_str(addr_str: &str, ignore_peer_id: bool) -> Option<Multiaddr> {
243 let Ok(addr) = addr_str.parse::<Multiaddr>() else {
244 warn!("Failed to parse multiaddr from str {addr_str}");
245 return None;
246 };
247 craft_valid_multiaddr(&addr, ignore_peer_id)
248}
249
250pub fn multiaddr_get_peer_id(addr: &Multiaddr) -> Option<PeerId> {
251 match addr.iter().find(|p| matches!(p, Protocol::P2p(_))) {
252 Some(Protocol::P2p(id)) => Some(id),
253 _ => None,
254 }
255}
256
257pub fn get_network_version() -> String {
258 format!("{}_{}", get_network_id_str(), get_truncate_version_str())
259}