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 Default for DnssecBootstrapProvider {
28 fn default() -> Self {
29 Self::new()
30 }
31}
32
33impl DnssecBootstrapProvider {
34 pub fn new() -> Self {
35 let resolver_configs = [
36 ResolverConfig::cloudflare_https(),
37 ResolverConfig::google_https(),
38 ];
40
41 let resolvers = resolver_configs
42 .into_iter()
43 .map(|resolver_config| {
44 let mut builder = Resolver::builder_with_config(resolver_config, TokioConnectionProvider::default());
45 builder.options_mut().validate = true;
46 builder.options_mut().ip_strategy = LookupIpStrategy::Ipv4Only;
47 builder.build()
48 })
49 .collect();
50
51 Self { resolvers }
52 }
53}
54
55#[async_trait::async_trait]
56impl BootstrapProvider for DnssecBootstrapProvider {
57 async fn get_bootstrap_addresses(&self) -> Vec<String> {
58 let mut addresses = HashSet::new();
59 for domain in config::BOOTSTRAP_DOMAINS {
60 for resolver in &self.resolvers {
61 match resolver.lookup_ip(*domain).await {
62 Ok(response) => {
63 for ip in response.iter() {
64 addresses.insert(format!("{}:443", ip));
65 }
66 }
67 Err(e) => {
68 warn!("DNSSEC bootstrap lookup failed for {}: {}", domain, e);
69 }
70 }
71 }
72 }
73 let mut addresses: Vec<String> = addresses.drain().collect();
74 tools::shuffle(&mut addresses);
75 addresses
76 }
77}