From 36909df529ec6c28c8764837aef666d9bbf3f664 Mon Sep 17 00:00:00 2001 From: AlphonseMehounme Date: Fri, 20 Dec 2024 15:54:43 +0100 Subject: [PATCH 1/2] add domain and bytes dependencies --- lib/core/Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/core/Cargo.toml b/lib/core/Cargo.toml index 9c1e1c132..bd042152f 100644 --- a/lib/core/Cargo.toml +++ b/lib/core/Cargo.toml @@ -54,6 +54,8 @@ electrum-client = { version = "0.19.0" } zbase32 = "0.1.2" x509-parser = { version = "0.16.0" } tempfile = "3" +domain = { version = "0.8.0", features = ["resolv"] } +bytes = "1.0" [dev-dependencies] lazy_static = "1.5.0" From 91514f55b902ac6bbf5be182c767f3e1b7479a9d Mon Sep 17 00:00:00 2001 From: AlphonseMehounme Date: Fri, 20 Dec 2024 18:26:25 +0100 Subject: [PATCH 2/2] implement bip353 address resolver --- cli/Cargo.lock | 28 ++++++++++++++++++++++++ lib/Cargo.lock | 28 ++++++++++++++++++++++++ lib/core/src/sdk.rs | 52 +++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 106 insertions(+), 2 deletions(-) diff --git a/cli/Cargo.lock b/cli/Cargo.lock index e12051610..0be636766 100644 --- a/cli/Cargo.lock +++ b/cli/Cargo.lock @@ -651,7 +651,9 @@ dependencies = [ "async-trait", "bip39", "boltz-client", + "bytes", "chrono", + "domain", "electrum-client", "env_logger 0.11.5", "flutter_rust_bridge", @@ -1006,6 +1008,22 @@ dependencies = [ "syn 2.0.75", ] +[[package]] +name = "domain" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2fbe77a63bf2445649b4ec41ba5300d30dc8358fef4503da03bf2313e31bef3" +dependencies = [ + "bytes", + "futures", + "libc", + "octseq", + "rand", + "smallvec", + "time", + "tokio", +] + [[package]] name = "either" version = "1.13.0" @@ -2234,6 +2252,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "octseq" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5190e3482f38446ee3f3ab50b049a16b072b6111cba008381b816598478ba65d" +dependencies = [ + "bytes", + "smallvec", +] + [[package]] name = "oid-registry" version = "0.7.1" diff --git a/lib/Cargo.lock b/lib/Cargo.lock index 2029f6971..fcf2a19dd 100644 --- a/lib/Cargo.lock +++ b/lib/Cargo.lock @@ -749,7 +749,9 @@ dependencies = [ "async-trait", "bip39", "boltz-client", + "bytes", "chrono", + "domain", "electrum-client", "env_logger 0.11.5", "flutter_rust_bridge", @@ -1187,6 +1189,22 @@ dependencies = [ "syn 2.0.77", ] +[[package]] +name = "domain" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2fbe77a63bf2445649b4ec41ba5300d30dc8358fef4503da03bf2313e31bef3" +dependencies = [ + "bytes", + "futures", + "libc", + "octseq", + "rand 0.8.5", + "smallvec", + "time", + "tokio", +] + [[package]] name = "either" version = "1.13.0" @@ -2418,6 +2436,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "octseq" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5190e3482f38446ee3f3ab50b049a16b072b6111cba008381b816598478ba65d" +dependencies = [ + "bytes", + "smallvec", +] + [[package]] name = "oid-registry" version = "0.7.1" diff --git a/lib/core/src/sdk.rs b/lib/core/src/sdk.rs index 17397fa0a..d5ec3c6fa 100644 --- a/lib/core/src/sdk.rs +++ b/lib/core/src/sdk.rs @@ -21,11 +21,14 @@ use sdk_common::prelude::{FiatAPI, FiatCurrency, LnUrlPayError, LnUrlWithdrawErr use signer::SdkSigner; use std::collections::HashMap; use std::time::Instant; -use std::{fs, path::PathBuf, str::FromStr, sync::Arc, time::Duration}; +use std::{fs, path::PathBuf, str::FromStr, str, sync::Arc, time::Duration}; use tokio::sync::{watch, Mutex, RwLock}; use tokio::time::MissedTickBehavior; use tokio_stream::wrappers::BroadcastStream; use x509_parser::parse_x509_certificate; +use domain::base::name::Dname; +use domain::rdata::Txt; +use domain::resolv::stub::StubResolver; use crate::chain::bitcoin::BitcoinChainService; use crate::chain_swap::ChainSwapHandler; @@ -2706,11 +2709,56 @@ impl LiquidSdk { Ok(config) } + /// + /// + pub async fn bip353_address_resolver(&self, input: &str) -> Option { + let resolver = StubResolver::new(); + let input_parts : Vec<&str> = input.split("@").collect(); + let input_formated = input_parts[0].to_owned() + ".user._bitcoin-payment." + input_parts[1]; + let domain : domain::base::Dname> = Dname::from_str(&input_formated)?; + + let response = resolver.query((domain, domain::base::iana::Rtype::Txt)).await?; + + match response.answer() { + Ok(answer) => { + for record in answer.limit_to::>() { + if let Ok(txt_record) = record { + for txt in txt_record.data() { + match str::from_utf8(txt) { + Ok(text) => { + if text.starts_with("bitcoin:") { + if let Some((_, bolt12_offer)) = text.split_once("lno=") { + return Some(bolt12_offer.to_string()); + } + } + }, + Err(_) => { + return None + } + } + } + } + } + } + Err(e) => { + eprintln!("Failed to resolve the address {}", e); + } + } + + None + } + /// Parses a string into an [InputType]. See [input_parser::parse]. /// /// Can optionally be configured to use external input parsers by providing `external_input_parsers` in [Config]. pub async fn parse(&self, input: &str) -> Result { - if let Ok(offer) = input.parse::() { + // Get bolt12offer from the address + let new_input = match self.bip353_address_resolver(input).await { + Some(b12offer) => b12offer, + None => input.to_string(), + }; + + if let Ok(offer) = new_input.parse::() { // TODO This conversion (between lightning-v0.0.125 to -v0.0.118 Amount types) // won't be needed when Liquid SDK uses the same lightning crate version as sdk-common let min_amount = offer