diff --git a/antd/Cargo.lock b/antd/Cargo.lock index f381c84..20dfcc3 100644 --- a/antd/Cargo.lock +++ b/antd/Cargo.lock @@ -954,6 +954,7 @@ dependencies = [ "thiserror 2.0.18", "tokio", "tokio-stream", + "toml", "tonic", "tonic-build", "tower-http", diff --git a/antd/Cargo.toml b/antd/Cargo.toml index 404ea23..1741bff 100644 --- a/antd/Cargo.toml +++ b/antd/Cargo.toml @@ -28,6 +28,7 @@ thiserror = "2" futures = "0.3" rand = "0.8" postcard = { version = "1.1.3", features = ["use-std"] } +toml = "0.8" [build-dependencies] tonic-build = "0.12" diff --git a/antd/resources/bootstrap_peers.toml b/antd/resources/bootstrap_peers.toml new file mode 100644 index 0000000..2923934 --- /dev/null +++ b/antd/resources/bootstrap_peers.toml @@ -0,0 +1,22 @@ +# Autonomi Network — Bootstrap Peers (compiled-in default for antd) +# +# This file is embedded into the antd binary via include_str! and used as a +# last-resort fallback when no peers are supplied via: +# 1. --peers / ANTD_PEERS (CLI/env) +# 2. %APPDATA%/ant/bootstrap_peers.toml (Linux: ~/.config/ant/) — the file +# ant-client's installer drops in +# +# Vendored from ant-client `resources/bootstrap_peers.toml`. Refresh on each +# antd release if upstream rotates the list. +# +# Format: "ip:port" socket addresses. Port range for ant-node: 10000-10999. + +peers = [ + "207.148.94.42:10000", + "45.77.50.10:10000", + "66.135.23.83:10000", + "149.248.9.2:10000", + "49.12.119.240:10000", + "5.161.25.133:10000", + "18.228.202.183:10000", +] diff --git a/antd/src/main.rs b/antd/src/main.rs index 3808758..f813d51 100644 --- a/antd/src/main.rs +++ b/antd/src/main.rs @@ -116,6 +116,20 @@ async fn main() -> Result<(), Box> { } } + // Last-resort fallback: peers vendored into the binary at compile time. + // Lets a fresh release binary reach mainnet without any prior ant-client + // installer step. CLI/env/file all take precedence over this. + if bootstrap_peers.is_empty() && config.network != "local" { + let compiled_in = peers::compiled_in_default_peers(); + if !compiled_in.is_empty() { + tracing::info!( + count = compiled_in.len(), + "loaded compiled-in default bootstrap peers (no CLI/env/file peers were supplied)" + ); + bootstrap_peers = compiled_in; + } + } + if bootstrap_peers.is_empty() { if config.network != "local" { tracing::warn!( diff --git a/antd/src/peers.rs b/antd/src/peers.rs index 9f660a7..80c2ebd 100644 --- a/antd/src/peers.rs +++ b/antd/src/peers.rs @@ -4,6 +4,17 @@ use std::net::SocketAddr; use ant_core::data::MultiAddr; +/// Mainnet bootstrap peers vendored from `ant-client/resources/bootstrap_peers.toml`. +/// Used as a last-resort fallback when neither CLI/env nor the on-disk +/// `bootstrap_peers.toml` provided any peers, so a fresh release binary can +/// reach mainnet without manual setup. +const COMPILED_IN_BOOTSTRAP_PEERS_TOML: &str = include_str!("../resources/bootstrap_peers.toml"); + +#[derive(serde::Deserialize)] +struct BootstrapConfig { + peers: Vec, +} + /// Convert a [`SocketAddr`] (as read from ant-client's `bootstrap_peers.toml`) /// into the libp2p-style `/ip4//udp//quic` multiaddr string that /// saorsa-core expects, then parse it into a [`MultiAddr`]. @@ -44,6 +55,24 @@ pub fn load_from_ant_client_config() -> (Vec, Option Vec { + match toml::from_str::(COMPILED_IN_BOOTSTRAP_PEERS_TOML) { + Ok(cfg) => cfg + .peers + .iter() + .filter_map(|s| s.parse::().ok()) + .filter_map(|sa| socket_addr_to_multiaddr(&sa)) + .collect(), + Err(e) => { + tracing::warn!(error = %e, "failed to parse compiled-in bootstrap_peers.toml"); + Vec::new() + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -71,4 +100,20 @@ mod tests { "unexpected multiaddr: {as_str}" ); } + + #[test] + fn compiled_in_default_peers_parses_and_yields_multiaddrs() { + let peers = compiled_in_default_peers(); + assert!( + !peers.is_empty(), + "embedded bootstrap_peers.toml produced zero peers" + ); + for ma in &peers { + let as_str = format!("{ma}"); + assert!( + as_str.contains("/udp/") && as_str.contains("/quic"), + "unexpected multiaddr shape: {as_str}" + ); + } + } }