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//! Bootstrap Cache for the Autonomous Network
10//!
11//! This crate provides a decentralized peer discovery and caching system for the Autonomi Network.
12//! It implements a robust peer management system with the following features:
13//!
14//! - Decentralized Design: No dedicated bootstrap nodes required
15//! - Cross-Platform Support: Works on Linux, macOS, and Windows
16//! - Shared Cache: System-wide cache file accessible by both nodes and clients
17//! - Concurrent Access: File locking for safe multi-process access
18//! - Atomic Operations: Safe cache updates using atomic file operations
19//! - Initial Peer Discovery: Fallback web endpoints for new/stale cache scenarios
20
21#[macro_use]
22extern crate tracing;
23
24pub mod 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 thiserror::Error;
33
34pub use cache_store::BootstrapCacheStore;
35pub use config::BootstrapCacheConfig;
36pub use contacts::ContactsFetcher;
37pub use error::{Error, Result};
38pub use initial_peers::{InitialPeersConfig, ANT_PEERS_ENV};
39
40/// Craft a proper address to avoid any ill formed addresses
41///
42/// ignore_peer_id is only used for nat-detection contact list
43pub fn craft_valid_multiaddr(addr: &Multiaddr, ignore_peer_id: bool) -> Option<Multiaddr> {
44    let peer_id = addr
45        .iter()
46        .find(|protocol| matches!(protocol, Protocol::P2p(_)));
47
48    let mut output_address = Multiaddr::empty();
49
50    let ip = addr
51        .iter()
52        .find(|protocol| matches!(protocol, Protocol::Ip4(_)))?;
53    output_address.push(ip);
54
55    let udp = addr
56        .iter()
57        .find(|protocol| matches!(protocol, Protocol::Udp(_)));
58    let tcp = addr
59        .iter()
60        .find(|protocol| matches!(protocol, Protocol::Tcp(_)));
61
62    // UDP or TCP
63    if let Some(udp) = udp {
64        output_address.push(udp);
65        if let Some(quic) = addr
66            .iter()
67            .find(|protocol| matches!(protocol, Protocol::QuicV1))
68        {
69            output_address.push(quic);
70        }
71    } else if let Some(tcp) = tcp {
72        output_address.push(tcp);
73
74        if let Some(ws) = addr
75            .iter()
76            .find(|protocol| matches!(protocol, Protocol::Ws(_)))
77        {
78            output_address.push(ws);
79        }
80    } else {
81        return None;
82    }
83
84    if let Some(peer_id) = peer_id {
85        output_address.push(peer_id);
86    } else if !ignore_peer_id {
87        return None;
88    }
89
90    Some(output_address)
91}
92
93/// ignore_peer_id is only used for nat-detection contact list
94pub fn craft_valid_multiaddr_from_str(addr_str: &str, ignore_peer_id: bool) -> Option<Multiaddr> {
95    let Ok(addr) = addr_str.parse::<Multiaddr>() else {
96        warn!("Failed to parse multiaddr from str {addr_str}");
97        return None;
98    };
99    craft_valid_multiaddr(&addr, ignore_peer_id)
100}
101
102pub fn multiaddr_get_peer_id(addr: &Multiaddr) -> Option<PeerId> {
103    match addr.iter().find(|p| matches!(p, Protocol::P2p(_))) {
104        Some(Protocol::P2p(id)) => Some(id),
105        _ => None,
106    }
107}
108
109pub fn get_network_version() -> String {
110    format!("{}_{}", get_network_id_str(), get_truncate_version_str())
111}