Skip to content

Commit

Permalink
Use multiple dns services.
Browse files Browse the repository at this point in the history
  • Loading branch information
SoraSuegami committed Nov 5, 2024
1 parent 8912640 commit b8e159b
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 43 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ For example, this is used in ZK Email to update a dkim registry contract, which

Our repository contains the implementations of theee canisters as follows:
- Poseidon hash canister: this simply computes the Poseidon hash of the given RSA public key.
- DNS client canister: this fetches an RSA public key for the given selector and domain from Google DNS.
- DNS client canister: this fetches an RSA public key for the given selector and domain from either Google DNS, Cloudflare DNS, or Next DNS.
- IC DNS oracle backend canister: this is our main canister that generates an ECDSA signature for the fetched public key corresponding to the given selector and domain. The output signature can be verified by smart contracts on Ethereum.

## How to try our canister
Expand Down
97 changes: 55 additions & 42 deletions src/dns_client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,53 +56,37 @@ pub async fn get_dkim_public_key(
return Err("Invalid selector".to_string());
}

let host = "dns.google";
let url = format!(
"https://{}/resolve?name={}._domainkey.{}&type=TXT",
host, selector, domain
);

let request_headers = vec![
HttpHeader {
name: "Host".to_string(),
value: format!("{host}:443"),
},
HttpHeader {
name: "User-Agent".to_string(),
value: "exchange_rate_canister".to_string(),
},
let prefixes = vec![
"https://dns.google/resolve",
"https://cloudflare-dns.com/dns-query",
"https://dns.nextdns.io/dns-query",
];

let transform = TransformContext::from_name("transform".to_string(), vec![]);
let request = CanisterHttpRequestArgument {
url: url.to_string(),
method: HttpMethod::GET,
body: None, // Optional for request
max_response_bytes: Some(65536), // 64KB
transform: Some(transform),
headers: request_headers,
};

match http_request(request, cycle as u128).await {
// Decode and return the response.
Ok((response,)) => {
if response.status != Nat::from(200u64) {
return Err(format!(
"Received an error from google dns: err = {:?}",
response.body
));
let mut errors = vec![];
for prefix in prefixes {
let request = _construct_request(prefix, &selector, &domain);
match http_request(request, cycle as u128).await {
// Decode and return the response.
Ok((response,)) => {
if response.status != Nat::from(200u64) {
continue;
}
let pubkey_hex = "0x".to_string() + &hex::encode(&response.body);
return Ok(pubkey_hex);
}
Err((r, m)) => {
let message = format!(
"[Access to {prefix}] The http_request resulted into error. RejectionCode: {r:?}, Error: {m}."
);
errors.push(message);

// Return the error as a string and end the method.
// return Err(message);
}
let pubkey_hex = "0x".to_string() + &hex::encode(&response.body);
Ok(pubkey_hex)
}
Err((r, m)) => {
let message =
format!("The http_request resulted into error. RejectionCode: {r:?}, Error: {m}");

// Return the error as a string and end the method.
Err(message)
}
}
// Return the error as a string and end the method.
return Err(errors.join("\n"));
}

/// Transforms the raw HTTP response into a structured `HttpResponse`.
Expand All @@ -122,6 +106,35 @@ fn transform(raw: TransformArgs) -> HttpResponse {
}
}

/// Helper function to construct the HTTP request.
/// # Arguments
/// * `prefix` - The prefix of the DNS resolver.
/// * `selector` - The DKIM selector.
/// * `domain` - The domain for which to fetch the DKIM public key.
/// # Returns
/// A structured `CanisterHttpRequestArgument`.
fn _construct_request(prefix: &str, selector: &str, domain: &str) -> CanisterHttpRequestArgument {
let url = format!(
"{}?name={}._domainkey.{}&type=TXT",
prefix, selector, domain
);

let request_headers = vec![HttpHeader {
name: "Accept".to_string(),
value: "application/dns-json".to_string(),
}];

let transform = TransformContext::from_name("transform".to_string(), vec![]);
CanisterHttpRequestArgument {
url: url.to_string(),
method: HttpMethod::GET,
body: None, // Optional for request
max_response_bytes: Some(65536), // 64KB
transform: Some(transform),
headers: request_headers,
}
}

/// Helper function to transform the raw HTTP response.
///
/// # Arguments
Expand Down

0 comments on commit b8e159b

Please sign in to comment.