ant_bootstrap/
initial_peers.rs1use crate::{
10 BootstrapCacheConfig, BootstrapCacheStore, ContactsFetcher, craft_valid_multiaddr,
11 craft_valid_multiaddr_from_str,
12 error::{Error, Result},
13};
14use ant_protocol::version::{ALPHANET_ID, MAINNET_ID, get_network_id};
15use clap::Args;
16use libp2p::Multiaddr;
17use serde::{Deserialize, Serialize};
18use std::path::PathBuf;
19use url::Url;
20
21pub const ANT_PEERS_ENV: &str = "ANT_PEERS";
23
24#[derive(Args, Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
27pub struct InitialPeersConfig {
28 #[clap(long, default_value = "false")]
33 pub first: bool,
34 #[clap(
45 long = "peer",
46 value_name = "multiaddr",
47 value_delimiter = ',',
48 conflicts_with = "first"
49 )]
50 pub addrs: Vec<Multiaddr>,
51 #[clap(long, conflicts_with = "first", value_delimiter = ',')]
56 pub network_contacts_url: Vec<String>,
57 #[clap(long, conflicts_with = "network_contacts_url", default_value = "false")]
59 pub local: bool,
60 #[clap(long, default_value = "false")]
62 pub ignore_cache: bool,
63 #[clap(long)]
72 pub bootstrap_cache_dir: Option<PathBuf>,
73}
74
75impl InitialPeersConfig {
76 pub async fn get_bootstrap_addr(&self, count: Option<usize>) -> Result<Vec<Multiaddr>> {
78 if self.first {
80 info!("First node in network, no initial bootstrap peers");
81 return Ok(vec![]);
82 }
83
84 let mut bootstrap_addresses = vec![];
85
86 bootstrap_addresses.extend(Self::read_bootstrap_addr_from_env());
88
89 if !bootstrap_addresses.is_empty() {
90 info!(
91 "Found {} bootstrap addresses from environment variable",
92 bootstrap_addresses.len()
93 );
94 return Ok(bootstrap_addresses);
95 }
96
97 for addr in &self.addrs {
99 if let Some(addr) = craft_valid_multiaddr(addr, false) {
100 info!("Adding addr from arguments: {addr}");
101 bootstrap_addresses.push(addr);
102 } else {
103 warn!("Invalid multiaddress format from arguments: {addr}");
104 }
105 }
106
107 if let Some(count) = count
108 && bootstrap_addresses.len() >= count
109 {
110 bootstrap_addresses.truncate(count);
111 info!(
112 "Found {} bootstrap addresses. Returning early.",
113 bootstrap_addresses.len()
114 );
115 return Ok(bootstrap_addresses);
116 }
117
118 if !self.ignore_cache {
120 let cfg = BootstrapCacheConfig::try_from(self)
121 .inspect_err(|err| {
122 error!("Failed to create bootstrap cache config: {err}");
123 })
124 .ok();
125
126 if let Some(cfg) = cfg {
127 if let Ok(data) = BootstrapCacheStore::load_cache_data(&cfg) {
128 bootstrap_addresses.extend(data.get_all_addrs().cloned());
129
130 if let Some(count) = count
131 && bootstrap_addresses.len() >= count
132 {
133 bootstrap_addresses.truncate(count);
134 info!(
135 "Found {} bootstrap addresses. Returning early.",
136 bootstrap_addresses.len()
137 );
138 return Ok(bootstrap_addresses);
139 }
140 }
141 } else {
142 info!("Bootstrap cache config could not be created, skipping cache loading");
143 }
144 } else {
145 info!("Ignoring cache, not loading bootstrap addresses from cache");
146 }
147
148 if !self.local && !self.network_contacts_url.is_empty() {
150 info!(
151 "Fetching bootstrap address from network contacts URLs: {:?}",
152 self.network_contacts_url
153 );
154 let addrs = self
155 .network_contacts_url
156 .iter()
157 .map(|url| url.parse::<Url>().map_err(|_| Error::FailedToParseUrl))
158 .collect::<Result<Vec<Url>>>()?;
159 let mut contacts_fetcher = ContactsFetcher::with_endpoints(addrs)?;
160 if let Some(count) = count {
161 contacts_fetcher.set_max_addrs(count);
162 }
163 let addrs = contacts_fetcher.fetch_bootstrap_addresses().await?;
164 bootstrap_addresses.extend(addrs);
165
166 if let Some(count) = count
167 && bootstrap_addresses.len() >= count
168 {
169 bootstrap_addresses.truncate(count);
170 info!(
171 "Found {} bootstrap addresses. Returning early.",
172 bootstrap_addresses.len()
173 );
174 return Ok(bootstrap_addresses);
175 }
176 }
177
178 if !self.local && get_network_id() == MAINNET_ID {
179 let mut contacts_fetcher = ContactsFetcher::with_mainnet_endpoints()?;
180 if let Some(count) = count {
181 contacts_fetcher.set_max_addrs(count);
182 }
183 info!("Fetching bootstrap address from mainnet contacts");
184 let addrs = contacts_fetcher.fetch_bootstrap_addresses().await?;
185 bootstrap_addresses.extend(addrs);
186 } else if !self.local && get_network_id() == ALPHANET_ID {
187 let mut contacts_fetcher = ContactsFetcher::with_alphanet_endpoints()?;
188 if let Some(count) = count {
189 contacts_fetcher.set_max_addrs(count);
190 }
191 info!("Fetching bootstrap address from alphanet contacts");
192 let addrs = contacts_fetcher.fetch_bootstrap_addresses().await?;
193 bootstrap_addresses.extend(addrs);
194 }
195
196 if !bootstrap_addresses.is_empty() {
197 if let Some(count) = count {
198 bootstrap_addresses.truncate(count);
199 }
200 info!(
201 "Found {} bootstrap addresses. Returning early.",
202 bootstrap_addresses.len()
203 );
204 Ok(bootstrap_addresses)
205 } else {
206 error!("No initial bootstrap peers found through any means");
207 Err(Error::NoBootstrapPeersFound)
208 }
209 }
210
211 pub fn read_bootstrap_addr_from_env() -> Vec<Multiaddr> {
212 let mut bootstrap_addresses = Vec::new();
213 if let Ok(addrs) = std::env::var(ANT_PEERS_ENV) {
215 for addr_str in addrs.split(',') {
216 if let Some(addr) = craft_valid_multiaddr_from_str(addr_str, false) {
217 info!("Adding addr from environment variable: {addr}");
218 bootstrap_addresses.push(addr);
219 } else {
220 warn!("Invalid multiaddress format from environment variable: {addr_str}");
221 }
222 }
223 }
224 bootstrap_addresses
225 }
226}