chia_sdk_client/
network.rs

1use std::{net::SocketAddr, time::Duration};
2
3use chia_protocol::Bytes32;
4use chia_sdk_types::{MAINNET_CONSTANTS, TESTNET11_CONSTANTS};
5use futures_util::{stream::FuturesUnordered, StreamExt};
6use tracing::{info, instrument, warn};
7
8use crate::ClientError;
9
10#[derive(Debug, Clone)]
11pub struct Network {
12    pub default_port: u16,
13    pub genesis_challenge: Bytes32,
14    pub dns_introducers: Vec<String>,
15}
16
17impl Network {
18    pub fn default_mainnet() -> Self {
19        Self {
20            default_port: 8444,
21            genesis_challenge: MAINNET_CONSTANTS.genesis_challenge,
22            dns_introducers: vec![
23                "dns-introducer.chia.net".to_string(),
24                "chia.ctrlaltdel.ch".to_string(),
25                "seeder.dexie.space".to_string(),
26                "chia.hoffmang.com".to_string(),
27            ],
28        }
29    }
30
31    pub fn default_testnet11() -> Self {
32        Self {
33            default_port: 58444,
34            genesis_challenge: TESTNET11_CONSTANTS.genesis_challenge,
35            dns_introducers: vec!["dns-introducer-testnet11.chia.net".to_string()],
36        }
37    }
38
39    #[instrument]
40    pub async fn lookup_all(&self, timeout: Duration, batch_size: usize) -> Vec<SocketAddr> {
41        let mut result = Vec::new();
42
43        for batch in self.dns_introducers.chunks(batch_size) {
44            let mut futures = FuturesUnordered::new();
45
46            for dns_introducer in batch {
47                futures.push(async move {
48                    match tokio::time::timeout(timeout, self.lookup_host(dns_introducer)).await {
49                        Ok(Ok(addrs)) => addrs,
50                        Ok(Err(error)) => {
51                            warn!("Failed to lookup DNS introducer {dns_introducer}: {error}");
52                            Vec::new()
53                        }
54                        Err(_timeout) => {
55                            warn!("Timeout looking up DNS introducer {dns_introducer}");
56                            Vec::new()
57                        }
58                    }
59                });
60            }
61
62            while let Some(addrs) = futures.next().await {
63                result.extend(addrs);
64            }
65        }
66
67        result
68    }
69
70    #[instrument]
71    pub async fn lookup_host(&self, dns_introducer: &str) -> Result<Vec<SocketAddr>, ClientError> {
72        info!("Looking up DNS introducer {dns_introducer}");
73        let mut result = Vec::new();
74        for addr in tokio::net::lookup_host(format!("{dns_introducer}:80")).await? {
75            result.push(SocketAddr::new(addr.ip(), self.default_port));
76        }
77        Ok(result)
78    }
79}