ant_bootstrap/
lib.rs

1// Copyright 2024 MaidSafe.net limited.
2//
3// This SAFE Network Software is licensed to you under The General Public License (GPL), version 3.
4// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
5// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
6// KIND, either express or implied. Please review the Licences for the specific language governing
7// permissions and limitations relating to use of the SAFE Network Software.
8
9// Allow expect usage and enum variant names (comes from thiserror derives)
10#![allow(clippy::expect_used)]
11#![allow(clippy::enum_variant_names)]
12
13//! Bootstrap Cache for the Autonomous Network
14//!
15//! This crate provides a decentralized peer discovery and caching system for the Autonomi Network.
16//! It implements a robust peer management system with the following features:
17//!
18//! - Decentralized Design: No dedicated bootstrap nodes required
19//! - Cross-Platform Support: Works on Linux, macOS, and Windows
20//! - Shared Cache: System-wide cache file accessible by both nodes and clients
21//! - Concurrent Access: File locking for safe multi-process access
22//! - Atomic Operations: Safe cache updates using atomic file operations
23//! - Initial Peer Discovery: Fallback web endpoints for new/stale cache scenarios
24
25#[macro_use]
26extern crate tracing;
27
28pub mod cache_store;
29pub mod config;
30pub mod contacts;
31pub mod error;
32mod initial_peers;
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 cache_store::BootstrapCacheStore;
39pub use config::BootstrapCacheConfig;
40pub use contacts::ContactsFetcher;
41pub use error::{Error, Result};
42pub use initial_peers::{ANT_PEERS_ENV, InitialPeersConfig};
43
44/// Craft a proper address to avoid any ill formed addresses
45///
46/// ignore_peer_id is only used for nat-detection contact list
47pub fn craft_valid_multiaddr(addr: &Multiaddr, ignore_peer_id: bool) -> Option<Multiaddr> {
48    let peer_id = addr
49        .iter()
50        .find(|protocol| matches!(protocol, Protocol::P2p(_)));
51
52    let mut output_address = Multiaddr::empty();
53
54    let ip = addr
55        .iter()
56        .find(|protocol| matches!(protocol, Protocol::Ip4(_)))?;
57    output_address.push(ip);
58
59    let udp = addr
60        .iter()
61        .find(|protocol| matches!(protocol, Protocol::Udp(_)));
62    let tcp = addr
63        .iter()
64        .find(|protocol| matches!(protocol, Protocol::Tcp(_)));
65
66    // UDP or TCP
67    if let Some(udp) = udp {
68        output_address.push(udp);
69        if let Some(quic) = addr
70            .iter()
71            .find(|protocol| matches!(protocol, Protocol::QuicV1))
72        {
73            output_address.push(quic);
74        }
75    } else if let Some(tcp) = tcp {
76        output_address.push(tcp);
77
78        if let Some(ws) = addr
79            .iter()
80            .find(|protocol| matches!(protocol, Protocol::Ws(_)))
81        {
82            output_address.push(ws);
83        }
84    } else {
85        return None;
86    }
87
88    if let Some(peer_id) = peer_id {
89        output_address.push(peer_id);
90    } else if !ignore_peer_id {
91        return None;
92    }
93
94    Some(output_address)
95}
96
97/// ignore_peer_id is only used for nat-detection contact list
98pub fn craft_valid_multiaddr_from_str(addr_str: &str, ignore_peer_id: bool) -> Option<Multiaddr> {
99    let Ok(addr) = addr_str.parse::<Multiaddr>() else {
100        warn!("Failed to parse multiaddr from str {addr_str}");
101        return None;
102    };
103    craft_valid_multiaddr(&addr, ignore_peer_id)
104}
105
106pub fn multiaddr_get_peer_id(addr: &Multiaddr) -> Option<PeerId> {
107    match addr.iter().find(|p| matches!(p, Protocol::P2p(_))) {
108        Some(Protocol::P2p(id)) => Some(id),
109        _ => None,
110    }
111}
112
113pub fn get_network_version() -> String {
114    format!("{}_{}", get_network_id_str(), get_truncate_version_str())
115}