Skip to content

Commit 80a8ed5

Browse files
Nic-dormanclaude
andauthored
fix(antd): embed mainnet bootstrap_peers.toml as compile-time fallback (#55)
* fix(antd): embed mainnet bootstrap_peers.toml as compile-time fallback A user who downloads only the antd release binary cannot reach mainnet out of the box: the on-disk fallback at %APPDATA%\ant\bootstrap_peers.toml is only populated by the upstream ant-client installer, and the antd release archive ships only the bare binary. The daemon then logs a warning and every chunk operation fails. Vendor ant-client/resources/bootstrap_peers.toml at antd/resources/ and load it via include_str! as a third tier after CLI/env and the on-disk file. The new fallback only fires when --network != "local" and all higher-precedence sources were empty, so existing setups are unaffected. Refresh the vendored copy at release time if the upstream peer list rotates. Smoke-tested locally: with %APPDATA%\ant\bootstrap_peers.toml moved aside, antd now logs `loaded compiled-in default bootstrap peers (count=7)` instead of the no-peers warning. Closes #36. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * style(antd): cargo fmt — collapse compiled-in peers const onto one line CI's rustfmt 1.95.0 wants the include_str! const on a single line; my local formatter had wrapped it. No semantic change. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e43f601 commit 80a8ed5

5 files changed

Lines changed: 83 additions & 0 deletions

File tree

antd/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

antd/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ thiserror = "2"
2828
futures = "0.3"
2929
rand = "0.8"
3030
postcard = { version = "1.1.3", features = ["use-std"] }
31+
toml = "0.8"
3132

3233
[build-dependencies]
3334
tonic-build = "0.12"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Autonomi Network — Bootstrap Peers (compiled-in default for antd)
2+
#
3+
# This file is embedded into the antd binary via include_str! and used as a
4+
# last-resort fallback when no peers are supplied via:
5+
# 1. --peers / ANTD_PEERS (CLI/env)
6+
# 2. %APPDATA%/ant/bootstrap_peers.toml (Linux: ~/.config/ant/) — the file
7+
# ant-client's installer drops in
8+
#
9+
# Vendored from ant-client `resources/bootstrap_peers.toml`. Refresh on each
10+
# antd release if upstream rotates the list.
11+
#
12+
# Format: "ip:port" socket addresses. Port range for ant-node: 10000-10999.
13+
14+
peers = [
15+
"207.148.94.42:10000",
16+
"45.77.50.10:10000",
17+
"66.135.23.83:10000",
18+
"149.248.9.2:10000",
19+
"49.12.119.240:10000",
20+
"5.161.25.133:10000",
21+
"18.228.202.183:10000",
22+
]

antd/src/main.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,20 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
116116
}
117117
}
118118

119+
// Last-resort fallback: peers vendored into the binary at compile time.
120+
// Lets a fresh release binary reach mainnet without any prior ant-client
121+
// installer step. CLI/env/file all take precedence over this.
122+
if bootstrap_peers.is_empty() && config.network != "local" {
123+
let compiled_in = peers::compiled_in_default_peers();
124+
if !compiled_in.is_empty() {
125+
tracing::info!(
126+
count = compiled_in.len(),
127+
"loaded compiled-in default bootstrap peers (no CLI/env/file peers were supplied)"
128+
);
129+
bootstrap_peers = compiled_in;
130+
}
131+
}
132+
119133
if bootstrap_peers.is_empty() {
120134
if config.network != "local" {
121135
tracing::warn!(

antd/src/peers.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ use std::net::SocketAddr;
44

55
use ant_core::data::MultiAddr;
66

7+
/// Mainnet bootstrap peers vendored from `ant-client/resources/bootstrap_peers.toml`.
8+
/// Used as a last-resort fallback when neither CLI/env nor the on-disk
9+
/// `bootstrap_peers.toml` provided any peers, so a fresh release binary can
10+
/// reach mainnet without manual setup.
11+
const COMPILED_IN_BOOTSTRAP_PEERS_TOML: &str = include_str!("../resources/bootstrap_peers.toml");
12+
13+
#[derive(serde::Deserialize)]
14+
struct BootstrapConfig {
15+
peers: Vec<String>,
16+
}
17+
718
/// Convert a [`SocketAddr`] (as read from ant-client's `bootstrap_peers.toml`)
819
/// into the libp2p-style `/ip4/<ip>/udp/<port>/quic` multiaddr string that
920
/// saorsa-core expects, then parse it into a [`MultiAddr`].
@@ -44,6 +55,24 @@ pub fn load_from_ant_client_config() -> (Vec<MultiAddr>, Option<std::path::PathB
4455
(peers, path)
4556
}
4657

58+
/// Last-resort fallback: parse the bootstrap_peers.toml that was vendored into
59+
/// the binary at compile time and return MultiAddrs. Returns an empty vector if
60+
/// the embedded file is malformed (which would be a build-time regression).
61+
pub fn compiled_in_default_peers() -> Vec<MultiAddr> {
62+
match toml::from_str::<BootstrapConfig>(COMPILED_IN_BOOTSTRAP_PEERS_TOML) {
63+
Ok(cfg) => cfg
64+
.peers
65+
.iter()
66+
.filter_map(|s| s.parse::<SocketAddr>().ok())
67+
.filter_map(|sa| socket_addr_to_multiaddr(&sa))
68+
.collect(),
69+
Err(e) => {
70+
tracing::warn!(error = %e, "failed to parse compiled-in bootstrap_peers.toml");
71+
Vec::new()
72+
}
73+
}
74+
}
75+
4776
#[cfg(test)]
4877
mod tests {
4978
use super::*;
@@ -71,4 +100,20 @@ mod tests {
71100
"unexpected multiaddr: {as_str}"
72101
);
73102
}
103+
104+
#[test]
105+
fn compiled_in_default_peers_parses_and_yields_multiaddrs() {
106+
let peers = compiled_in_default_peers();
107+
assert!(
108+
!peers.is_empty(),
109+
"embedded bootstrap_peers.toml produced zero peers"
110+
);
111+
for ma in &peers {
112+
let as_str = format!("{ma}");
113+
assert!(
114+
as_str.contains("/udp/") && as_str.contains("/quic"),
115+
"unexpected multiaddr shape: {as_str}"
116+
);
117+
}
118+
}
74119
}

0 commit comments

Comments
 (0)