hashiverse_lib/transport/bootstrap_provider/
dnssec_bootstrap_provider.rs1use crate::tools::{config, tools};
14use crate::transport::bootstrap_provider::bootstrap_provider::BootstrapProvider;
15use hickory_resolver::{
16 config::{LookupIpStrategy, ResolverConfig},
17 name_server::TokioConnectionProvider,
18 Resolver, TokioResolver,
19};
20use log::warn;
21use std::collections::HashSet;
22
23pub struct DnssecBootstrapProvider {
24 resolvers: Vec<TokioResolver>,
25}
26
27impl DnssecBootstrapProvider {
28 pub fn new() -> Self {
29 let resolver_configs = [
30 ResolverConfig::cloudflare_https(),
31 ResolverConfig::google_https(),
32 ];
34
35 let resolvers = resolver_configs
36 .into_iter()
37 .map(|resolver_config| {
38 let mut builder = Resolver::builder_with_config(resolver_config, TokioConnectionProvider::default());
39 builder.options_mut().validate = true;
40 builder.options_mut().ip_strategy = LookupIpStrategy::Ipv4Only;
41 builder.build()
42 })
43 .collect();
44
45 Self { resolvers }
46 }
47}
48
49#[async_trait::async_trait]
50impl BootstrapProvider for DnssecBootstrapProvider {
51 async fn get_bootstrap_addresses(&self) -> Vec<String> {
52 let mut addresses = HashSet::new();
53 for domain in config::BOOTSTRAP_DOMAINS {
54 for resolver in &self.resolvers {
55 match resolver.lookup_ip(*domain).await {
56 Ok(response) => {
57 for ip in response.iter() {
58 addresses.insert(format!("{}:443", ip));
59 }
60 }
61 Err(e) => {
62 warn!("DNSSEC bootstrap lookup failed for {}: {}", domain, e);
63 }
64 }
65 }
66 }
67 let mut addresses: Vec<String> = addresses.drain().collect();
68 tools::shuffle(&mut addresses);
69 addresses
70 }
71}