Skip to content

Commit 5e36013

Browse files
committed
feat: configure DNS resolver
1 parent 7dcba12 commit 5e36013

File tree

5 files changed

+62
-14
lines changed

5 files changed

+62
-14
lines changed

src/core/builder.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::net::SocketAddr;
12
use std::{path::PathBuf, time::Duration};
23

34
use bitcoin::Network;
@@ -9,6 +10,7 @@ use super::{client::Client, config::NodeConfig, node::Node, FilterSyncPolicy};
910
use crate::db::error::SqlInitializationError;
1011
#[cfg(feature = "database")]
1112
use crate::db::sqlite::{headers::SqliteHeaderDb, peers::SqlitePeerDb};
13+
use crate::network::dns::DnsResolver;
1214
use crate::{
1315
chain::checkpoints::HeaderCheckpoint,
1416
db::traits::{HeaderStore, PeerStore},
@@ -176,6 +178,14 @@ impl NodeBuilder {
176178
self
177179
}
178180

181+
/// Configure the DNS resolver to use when querying DNS seeds.
182+
/// Default is `1.1.1.1:53`.
183+
pub fn use_dns_resolver(mut self, resolver: impl Into<SocketAddr>) -> Self {
184+
let socket_addr = resolver.into();
185+
self.config.dns_resolver = DnsResolver { socket_addr };
186+
self
187+
}
188+
179189
/// Stop the node from downloading and checking compact block filters until an explicit command by the client is made.
180190
/// This is only useful if the scripts to check for may not be known do to some expensive computation, like in a silent
181191
/// payments context.

src/core/config.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use std::{collections::HashSet, path::PathBuf, time::Duration};
33
use bitcoin::ScriptBuf;
44

55
use crate::{
6-
chain::checkpoints::HeaderCheckpoint, ConnectionType, PeerStoreSizeConfig, TrustedPeer,
6+
chain::checkpoints::HeaderCheckpoint, network::dns::DnsResolver, ConnectionType,
7+
PeerStoreSizeConfig, TrustedPeer,
78
};
89

910
use super::FilterSyncPolicy;
@@ -16,6 +17,7 @@ const TWO_HOUR: u64 = 60 * 60 * 2;
1617
pub(crate) struct NodeConfig {
1718
pub required_peers: u8,
1819
pub white_list: Vec<TrustedPeer>,
20+
pub dns_resolver: DnsResolver,
1921
pub addresses: HashSet<ScriptBuf>,
2022
pub data_path: Option<PathBuf>,
2123
pub header_checkpoint: Option<HeaderCheckpoint>,
@@ -31,6 +33,7 @@ impl Default for NodeConfig {
3133
Self {
3234
required_peers: REQUIRED_PEERS,
3335
white_list: Default::default(),
36+
dns_resolver: DnsResolver::default(),
3437
addresses: Default::default(),
3538
data_path: Default::default(),
3639
header_checkpoint: Default::default(),

src/core/node.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use crate::{
2525
core::{error::FetchHeaderError, peer_map::PeerMap},
2626
db::traits::{HeaderStore, PeerStore},
2727
filters::{cfheader_chain::AppendAttempt, error::CFilterSyncError},
28+
network::dns::DnsResolver,
2829
ConnectionType, PeerStoreSizeConfig, RejectPayload, TrustedPeer, TxBroadcastPolicy,
2930
};
3031

@@ -82,6 +83,7 @@ impl<H: HeaderStore, P: PeerStore> Node<H, P> {
8283
pub(crate) fn new(
8384
network: Network,
8485
white_list: Whitelist,
86+
dns_resolver: DnsResolver,
8587
scripts: HashSet<ScriptBuf>,
8688
header_checkpoint: Option<HeaderCheckpoint>,
8789
required_peers: PeerRequirement,
@@ -115,6 +117,7 @@ impl<H: HeaderStore, P: PeerStore> Node<H, P> {
115117
target_peer_size,
116118
timeout_config,
117119
Arc::clone(&height_monitor),
120+
dns_resolver,
118121
)));
119122
// Set up the transaction broadcaster
120123
let tx_broadcaster = Arc::new(Mutex::new(Broadcaster::new()));
@@ -161,6 +164,7 @@ impl<H: HeaderStore, P: PeerStore> Node<H, P> {
161164
Node::new(
162165
network,
163166
config.white_list,
167+
config.dns_resolver,
164168
config.addresses,
165169
config.header_checkpoint,
166170
config.required_peers as PeerRequirement,

src/core/peer_map.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::{
2323
chain::HeightMonitor,
2424
db::{traits::PeerStore, PeerStatus, PersistedPeer},
2525
network::{
26+
dns::DnsResolver,
2627
error::PeerError,
2728
peer::Peer,
2829
traits::{ClearNetConnection, NetworkConnector},
@@ -71,6 +72,7 @@ pub(crate) struct PeerMap<P: PeerStore> {
7172
target_db_size: PeerStoreSizeConfig,
7273
net_groups: HashSet<String>,
7374
timeout_config: PeerTimeoutConfig,
75+
dns_resolver: DnsResolver,
7476
}
7577

7678
#[allow(dead_code)]
@@ -86,6 +88,7 @@ impl<P: PeerStore> PeerMap<P> {
8688
target_db_size: PeerStoreSizeConfig,
8789
timeout_config: PeerTimeoutConfig,
8890
height_monitor: Arc<Mutex<HeightMonitor>>,
91+
dns_resolver: DnsResolver,
8992
) -> Self {
9093
let connector: Arc<Mutex<dyn NetworkConnector + Send + Sync>> = match connection_type {
9194
ConnectionType::ClearNet => Arc::new(Mutex::new(ClearNetConnection::new())),
@@ -108,6 +111,7 @@ impl<P: PeerStore> PeerMap<P> {
108111
target_db_size,
109112
net_groups: HashSet::new(),
110113
timeout_config,
114+
dns_resolver,
111115
}
112116
}
113117

@@ -392,7 +396,7 @@ impl<P: PeerStore> PeerMap<P> {
392396
use std::net::IpAddr;
393397
self.dialog.send_dialog("Bootstraping peers with DNS").await;
394398
let mut db_lock = self.db.lock().await;
395-
let new_peers = Dns::new(self.network)
399+
let new_peers = Dns::new(self.network, self.dns_resolver)
396400
.bootstrap()
397401
.await
398402
.map_err(|_| PeerManagerError::Dns)?

src/network/dns.rs

Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use bitcoin::{
66
};
77
use std::{
88
io::Read,
9-
net::{IpAddr, Ipv4Addr},
9+
net::{IpAddr, Ipv4Addr, SocketAddr},
1010
};
1111
use tokio::net::UdpSocket;
1212

@@ -35,7 +35,6 @@ const MAINNET_SEEDS: &[&str; 9] = &[
3535
"seed.bitcoin.wiz.biz",
3636
];
3737

38-
const RESOLVER: &str = "1.1.1.1:53";
3938
const LOCAL_HOST: &str = "0.0.0.0:0";
4039

4140
const HEADER_BYTES: usize = 12;
@@ -59,12 +58,31 @@ const A_RECORD: u16 = 0x01;
5958
const A_CLASS: u16 = 0x01;
6059
const EXPECTED_RDATA_LEN: u16 = 0x04;
6160

61+
#[derive(Debug, Clone, Copy)]
62+
pub(crate) struct DnsResolver {
63+
pub(crate) socket_addr: SocketAddr,
64+
}
65+
66+
impl Default for DnsResolver {
67+
fn default() -> Self {
68+
let socket_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(1, 1, 1, 1)), 53);
69+
Self { socket_addr }
70+
}
71+
}
72+
73+
impl From<DnsResolver> for SocketAddr {
74+
fn from(value: DnsResolver) -> Self {
75+
value.socket_addr
76+
}
77+
}
78+
6279
pub(crate) struct Dns<'a> {
6380
seeds: Vec<&'a str>,
81+
dns_resolver: DnsResolver,
6482
}
6583

6684
impl Dns<'_> {
67-
pub fn new(network: Network) -> Self {
85+
pub fn new(network: Network, dns_resolver: DnsResolver) -> Self {
6886
let seeds = match network {
6987
Network::Bitcoin => MAINNET_SEEDS.to_vec(),
7088
Network::Testnet => TESTNET_SEEDS.to_vec(),
@@ -73,14 +91,17 @@ impl Dns<'_> {
7391
Network::Testnet4 => Vec::with_capacity(0),
7492
_ => unreachable!(),
7593
};
76-
Self { seeds }
94+
Self {
95+
seeds,
96+
dns_resolver,
97+
}
7798
}
7899

79100
pub async fn bootstrap(&self) -> Result<Vec<IpAddr>, DnsBootstrapError> {
80101
let mut ip_addrs: Vec<IpAddr> = vec![];
81102

82103
for host in &self.seeds {
83-
match DNSQuery::new(host).lookup().await {
104+
match DNSQuery::new(host).lookup(self.dns_resolver.into()).await {
84105
Ok(addrs) => ip_addrs.extend(addrs),
85106
Err(e) => eprintln!("{e}"),
86107
}
@@ -122,11 +143,11 @@ impl DNSQuery {
122143
}
123144
}
124145

125-
async fn lookup(&self) -> Result<Vec<IpAddr>, DNSQueryError> {
146+
async fn lookup(&self, dns_resolver: SocketAddr) -> Result<Vec<IpAddr>, DNSQueryError> {
126147
let sock = UdpSocket::bind(LOCAL_HOST)
127148
.await
128149
.map_err(|_| DNSQueryError::ConnectionDenied)?;
129-
sock.connect(RESOLVER)
150+
sock.connect(dns_resolver)
130151
.await
131152
.map_err(|_| DNSQueryError::Udp)?;
132153
sock.send(&self.message)
@@ -229,15 +250,21 @@ impl DNSQuery {
229250

230251
#[cfg(test)]
231252
mod test {
232-
use super::Dns;
253+
use std::net::SocketAddr;
254+
255+
use super::*;
233256

234257
#[tokio::test]
235258
#[ignore = "dns works"]
236259
async fn dns_responds() {
237-
let addrs = Dns::new(bitcoin::network::Network::Signet)
238-
.bootstrap()
239-
.await
240-
.unwrap();
260+
let socket_addr = "1.1.1.1:53".parse::<SocketAddr>().unwrap();
261+
let addrs = Dns::new(
262+
bitcoin::network::Network::Signet,
263+
DnsResolver { socket_addr },
264+
)
265+
.bootstrap()
266+
.await
267+
.unwrap();
241268
assert!(addrs.len() > 1);
242269
}
243270
}

0 commit comments

Comments
 (0)