Skip to content

Commit

Permalink
DNS-over-HTTPS resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
mwalkiewicz committed Aug 1, 2024
1 parent 594d8a9 commit 4eb076e
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 1 deletion.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/erc20_payment_lib_common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ rustc-hex = { workspace = true }
secp256k1 = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
reqwest = { workspace = true, features = ["json"] }
sha3 = { workspace = true }
sqlx = { workspace = true }
structopt = { workspace = true }
Expand Down
73 changes: 73 additions & 0 deletions crates/erc20_payment_lib_common/src/dns_over_https_resolver.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use reqwest;
use serde;
use std::env;
use std::io::ErrorKind as IoErrorKind;

#[derive(serde::Deserialize)]
struct DnsOverHttpsResponse {
#[serde(rename(deserialize = "Answer"))]
pub answer: Vec<DnsOverHttpsAnswer>,
}

#[derive(serde::Deserialize)]
struct DnsOverHttpsAnswer {
pub data: String,
}

fn strip_quotes(data: &String) -> String {
let v1 = match data.strip_prefix('"') {
None => data.as_str(),
Some(x) => x,
};
String::from(match v1.strip_suffix('"') {
None => v1,
Some(x) => x,
})
}

pub enum DnsOverHttpsServer {
Google,
Cloudflare,
}

impl DnsOverHttpsServer {
pub fn get_dns_url(self: &DnsOverHttpsServer) -> &str {
match self {
DnsOverHttpsServer::Google => "https://dns.google/resolve",
DnsOverHttpsServer::Cloudflare => "https://cloudflare-dns.com/dns-query",
}
}
}

pub async fn resolve_dns_record_https(
record: &str,
record_type: &str,
dns_server: DnsOverHttpsServer,
) -> std::io::Result<Vec<String>> {
let result = reqwest::Client::new()
.get(dns_server.get_dns_url())
.query(&[("name", record), ("type", record_type)])
.header(reqwest::header::ACCEPT, "application/dns-json")
.send()
.await
.map_err(|_| std::io::Error::new(IoErrorKind::Other, "Couldn't fetch DNS record."))?
.json::<DnsOverHttpsResponse>()
.await
.map_err(|_| std::io::Error::new(IoErrorKind::Other, "Couldn't fetch DNS record."))?
.answer
.iter()
.map(|a| strip_quotes(&a.data))
.collect();
Ok(result)
}

pub async fn resolve_txt_record_to_string_array_https(
record: &str,
dns_server: DnsOverHttpsServer,
) -> std::io::Result<Vec<String>> {
resolve_dns_record_https(record, "TXT", dns_server).await
}

pub fn should_use_dns_over_https() -> bool {
matches!(env::var("YA_USE_HTTPS_DNS_RESOLVER"), Ok(value) if value == "1")
}
1 change: 1 addition & 0 deletions crates/erc20_payment_lib_common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod db;
pub mod dns_over_https_resolver;
pub mod error;
mod events;
mod metrics;
Expand Down
14 changes: 13 additions & 1 deletion crates/erc20_rpc_pool/src/rpc_pool/pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ use uuid::Uuid;
use web3::transports::Http;
use web3::Web3;

use erc20_payment_lib_common::dns_over_https_resolver::{
resolve_txt_record_to_string_array_https, should_use_dns_over_https, DnsOverHttpsServer,
};

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Web3ExternalEndpointList {
Expand Down Expand Up @@ -122,7 +126,7 @@ pub struct Web3RpcPool {
pub endpoint_verifier: Arc<EndpointsVerifier>,
}

pub async fn resolve_txt_record_to_string_array(record: &str) -> std::io::Result<Vec<String>> {
pub async fn resolve_txt_record_to_string_array_dns(record: &str) -> std::io::Result<Vec<String>> {
let resolver: TokioAsyncResolver =
TokioAsyncResolver::tokio(ResolverConfig::google(), ResolverOpts::default());

Expand All @@ -136,6 +140,14 @@ pub async fn resolve_txt_record_to_string_array(record: &str) -> std::io::Result
.collect::<Vec<_>>())
}

pub async fn resolve_txt_record_to_string_array(record: &str) -> std::io::Result<Vec<String>> {
if should_use_dns_over_https() {
resolve_txt_record_to_string_array_https(record, DnsOverHttpsServer::Google).await
} else {
resolve_txt_record_to_string_array_dns(record).await
}
}

pub struct ChooseBestEndpointsResult {
pub allowed_endpoints: Vec<Index>,
pub is_resolving: bool,
Expand Down

0 comments on commit 4eb076e

Please sign in to comment.