Skip to content

Commit b2162b5

Browse files
committed
Pass HRNResolver or DomainResolver into OnionMessenger
Inject specialized resolution capabilities into OnionMessenger to support outbound payments and third-party resolution services. This change refines the previous resolution logic by allowing the node to act as a robust BIP 353 participant. If configured as a service provider, the node utilizes a Domain Resolver to handle requests for other participants. Otherwise, it uses an HRN Resolver specifically for initiating its own outbound payments. Providing these as optional parameters in the Node constructor ensures the logic matches the node's designated role in the ecosystem.
1 parent 9d92c1b commit b2162b5

File tree

7 files changed

+90
-25
lines changed

7 files changed

+90
-25
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ default = []
3838
#lightning-transaction-sync = { version = "0.2.0", features = ["esplora-async-https", "time", "electrum-rustls-ring"] }
3939
#lightning-liquidity = { version = "0.2.0", features = ["std"] }
4040
#lightning-macros = { version = "0.2.0" }
41+
#lightning-dns-resolver = { version = "0.3.0" }
4142

4243
lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "7fe3268475551b0664d315bfbc860416ca8fc774", features = ["std"] }
4344
lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "7fe3268475551b0664d315bfbc860416ca8fc774" }
@@ -50,6 +51,7 @@ lightning-block-sync = { git = "https://github.com/lightningdevkit/rust-lightnin
5051
lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "7fe3268475551b0664d315bfbc860416ca8fc774", features = ["esplora-async-https", "time", "electrum-rustls-ring"] }
5152
lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "7fe3268475551b0664d315bfbc860416ca8fc774", features = ["std"] }
5253
lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "7fe3268475551b0664d315bfbc860416ca8fc774" }
54+
lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "7fe3268475551b0664d315bfbc860416ca8fc774" }
5355

5456
bdk_chain = { version = "0.23.0", default-features = false, features = ["std"] }
5557
bdk_esplora = { version = "0.22.0", default-features = false, features = ["async-https-rustls", "tokio"]}
@@ -141,6 +143,7 @@ harness = false
141143
#lightning-transaction-sync = { path = "../rust-lightning/lightning-transaction-sync" }
142144
#lightning-liquidity = { path = "../rust-lightning/lightning-liquidity" }
143145
#lightning-macros = { path = "../rust-lightning/lightning-macros" }
146+
#lightning-dns-resolver = { path = "../rust-lightning/lightning-dns-resolver" }
144147

145148
#lightning = { git = "https://github.com/lightningdevkit/rust-lightning", branch = "main" }
146149
#lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", branch = "main" }
@@ -153,6 +156,7 @@ harness = false
153156
#lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", branch = "main" }
154157
#lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", branch = "main" }
155158
#lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", branch = "main" }
159+
#lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightning", branch = "main" }
156160

157161
#lightning = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "21e9a9c0ef80021d0669f2a366f55d08ba8d9b03" }
158162
#lightning-types = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "21e9a9c0ef80021d0669f2a366f55d08ba8d9b03" }
@@ -165,6 +169,7 @@ harness = false
165169
#lightning-transaction-sync = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "21e9a9c0ef80021d0669f2a366f55d08ba8d9b03" }
166170
#lightning-liquidity = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "21e9a9c0ef80021d0669f2a366f55d08ba8d9b03" }
167171
#lightning-macros = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "21e9a9c0ef80021d0669f2a366f55d08ba8d9b03" }
172+
#lightning-dns-resolver = { git = "https://github.com/lightningdevkit/rust-lightning", rev = "21e9a9c0ef80021d0669f2a366f55d08ba8d9b03" }
168173

169174
#vss-client-ng = { path = "../vss-client" }
170175
#vss-client-ng = { git = "https://github.com/lightningdevkit/vss-client", branch = "main" }

bindings/ldk_node.udl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ enum NodeError {
352352
"InvalidBlindedPaths",
353353
"AsyncPaymentServicesDisabled",
354354
"HrnParsingFailed",
355+
"HrnResolverNotConfigured",
355356
};
356357

357358
dictionary NodeStatus {
@@ -386,6 +387,7 @@ enum BuildError {
386387
"LoggerSetupFailed",
387388
"NetworkMismatch",
388389
"AsyncPaymentsConfigMismatch",
390+
"DNSResolverSetupFailed",
389391
};
390392

391393
[Trait]

src/builder.rs

Lines changed: 60 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use lightning::ln::channelmanager::{self, ChainParameters, ChannelManagerReadArg
2525
use lightning::ln::msgs::{RoutingMessageHandler, SocketAddress};
2626
use lightning::ln::peer_handler::{IgnoringMessageHandler, MessageHandler};
2727
use lightning::log_trace;
28+
use lightning::onion_message::dns_resolution::DNSResolverMessageHandler;
2829
use lightning::routing::gossip::NodeAlias;
2930
use lightning::routing::router::DefaultRouter;
3031
use lightning::routing::scoring::{
@@ -39,6 +40,7 @@ use lightning::util::persist::{
3940
};
4041
use lightning::util::ser::ReadableArgs;
4142
use lightning::util::sweep::OutputSweeper;
43+
use lightning_dns_resolver::OMDomainResolver;
4244
use lightning_persister::fs_store::FilesystemStore;
4345
use vss_client::headers::VssHeaderProvider;
4446

@@ -75,9 +77,9 @@ use crate::peer_store::PeerStore;
7577
use crate::runtime::{Runtime, RuntimeSpawner};
7678
use crate::tx_broadcaster::TransactionBroadcaster;
7779
use crate::types::{
78-
AsyncPersister, ChainMonitor, ChannelManager, DynStore, DynStoreWrapper, GossipSync, Graph,
79-
KeysManager, MessageRouter, OnionMessenger, PaymentStore, PeerManager, PendingPaymentStore,
80-
Persister, SyncAndAsyncKVStore,
80+
AsyncPersister, ChainMonitor, ChannelManager, DomainResolver, DynStore, DynStoreWrapper,
81+
GossipSync, Graph, HRNResolver, KeysManager, MessageRouter, OnionMessenger, PaymentStore,
82+
PeerManager, PendingPaymentStore, Persister, SyncAndAsyncKVStore,
8183
};
8284
use crate::wallet::persist::KVStoreWalletPersister;
8385
use crate::wallet::Wallet;
@@ -189,6 +191,8 @@ pub enum BuildError {
189191
NetworkMismatch,
190192
/// The role of the node in an asynchronous payments context is not compatible with the current configuration.
191193
AsyncPaymentsConfigMismatch,
194+
/// An attempt to setup a DNS Resolver failed.
195+
DNSResolverSetupFailed,
192196
}
193197

194198
impl fmt::Display for BuildError {
@@ -221,12 +225,21 @@ impl fmt::Display for BuildError {
221225
"The async payments role is not compatible with the current configuration."
222226
)
223227
},
228+
Self::DNSResolverSetupFailed => {
229+
write!(f, "An attempt to setup a DNS resolver has failed.")
230+
},
224231
}
225232
}
226233
}
227234

228235
impl std::error::Error for BuildError {}
229236

237+
enum Resolver {
238+
HRN(Arc<HRNResolver>),
239+
DNS(Arc<DomainResolver>),
240+
Ignore(Arc<IgnoringMessageHandler>),
241+
}
242+
230243
/// A builder for an [`Node`] instance, allowing to set some configuration and module choices from
231244
/// the getgo.
232245
///
@@ -1517,7 +1530,34 @@ fn build_with_store_internal(
15171530
})?;
15181531
}
15191532

1520-
let hrn_resolver = Arc::new(LDKOnionMessageDNSSECHrnResolver::new(Arc::clone(&network_graph)));
1533+
let resolver = if let Some(hrn_config) = &config.hrn_config {
1534+
if hrn_config.is_hrn_resolver {
1535+
let dns_addr = hrn_config.dns_server_address.as_str();
1536+
1537+
Resolver::DNS(Arc::new(OMDomainResolver::ignoring_incoming_proofs(
1538+
dns_addr.parse().map_err(|_| BuildError::DNSResolverSetupFailed)?,
1539+
)))
1540+
} else {
1541+
Resolver::HRN(Arc::new(LDKOnionMessageDNSSECHrnResolver::new(Arc::clone(
1542+
&network_graph,
1543+
))))
1544+
}
1545+
} else {
1546+
// hrn_config is None, default to the IgnoringMessaageHandler.
1547+
Resolver::Ignore(Arc::new(IgnoringMessageHandler {}))
1548+
};
1549+
1550+
let om_resolver = match resolver {
1551+
Resolver::DNS(ref dns_resolver) => {
1552+
Arc::clone(dns_resolver) as Arc<dyn DNSResolverMessageHandler + Send + Sync>
1553+
},
1554+
Resolver::HRN(ref hrn_resolver) => {
1555+
Arc::clone(hrn_resolver) as Arc<dyn DNSResolverMessageHandler + Send + Sync>
1556+
},
1557+
Resolver::Ignore(ref ignoring_handler) => {
1558+
Arc::clone(ignoring_handler) as Arc<dyn DNSResolverMessageHandler + Send + Sync>
1559+
},
1560+
};
15211561

15221562
// Initialize the PeerManager
15231563
let onion_messenger: Arc<OnionMessenger> =
@@ -1530,7 +1570,7 @@ fn build_with_store_internal(
15301570
message_router,
15311571
Arc::clone(&channel_manager),
15321572
Arc::clone(&channel_manager),
1533-
Arc::clone(&hrn_resolver),
1573+
Arc::clone(&om_resolver),
15341574
IgnoringMessageHandler {},
15351575
))
15361576
} else {
@@ -1542,7 +1582,7 @@ fn build_with_store_internal(
15421582
message_router,
15431583
Arc::clone(&channel_manager),
15441584
Arc::clone(&channel_manager),
1545-
Arc::clone(&hrn_resolver),
1585+
Arc::clone(&om_resolver),
15461586
IgnoringMessageHandler {},
15471587
))
15481588
};
@@ -1675,11 +1715,19 @@ fn build_with_store_internal(
16751715
));
16761716

16771717
let peer_manager_clone = Arc::downgrade(&peer_manager);
1678-
hrn_resolver.register_post_queue_action(Box::new(move || {
1679-
if let Some(upgraded_pointer) = peer_manager_clone.upgrade() {
1680-
upgraded_pointer.process_events();
1681-
}
1682-
}));
1718+
1719+
let hrn_resolver = match resolver {
1720+
Resolver::DNS(_) => None,
1721+
Resolver::HRN(ref hrn_resolver) => {
1722+
hrn_resolver.register_post_queue_action(Box::new(move || {
1723+
if let Some(upgraded_pointer) = peer_manager_clone.upgrade() {
1724+
upgraded_pointer.process_events();
1725+
}
1726+
}));
1727+
Some(hrn_resolver)
1728+
},
1729+
Resolver::Ignore(_) => None,
1730+
};
16831731

16841732
liquidity_source.as_ref().map(|l| l.set_peer_manager(Arc::downgrade(&peer_manager)));
16851733

@@ -1786,7 +1834,7 @@ fn build_with_store_internal(
17861834
node_metrics,
17871835
om_mailbox,
17881836
async_payments_role,
1789-
hrn_resolver,
1837+
hrn_resolver: hrn_resolver.cloned(),
17901838
#[cfg(cycle_tests)]
17911839
_leak_checker,
17921840
})

src/error.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ pub enum Error {
131131
AsyncPaymentServicesDisabled,
132132
/// Parsing a Human-Readable Name has failed.
133133
HrnParsingFailed,
134+
/// A HRN resolver was not configured
135+
HrnResolverNotConfigured,
134136
}
135137

136138
impl fmt::Display for Error {
@@ -213,6 +215,9 @@ impl fmt::Display for Error {
213215
Self::HrnParsingFailed => {
214216
write!(f, "Failed to parse a human-readable name.")
215217
},
218+
Self::HrnResolverNotConfigured => {
219+
write!(f, "A HRN resolver was not configured.")
220+
},
216221
}
217222
}
218223
}

src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ pub struct Node {
226226
node_metrics: Arc<RwLock<NodeMetrics>>,
227227
om_mailbox: Option<Arc<OnionMessageMailbox>>,
228228
async_payments_role: Option<AsyncPaymentsRole>,
229-
hrn_resolver: Arc<HRNResolver>,
229+
hrn_resolver: Option<Arc<HRNResolver>>,
230230
#[cfg(cycle_tests)]
231231
_leak_checker: LeakChecker,
232232
}
@@ -979,7 +979,7 @@ impl Node {
979979
self.bolt12_payment().into(),
980980
Arc::clone(&self.config),
981981
Arc::clone(&self.logger),
982-
Arc::clone(&self.hrn_resolver),
982+
Arc::new(self.hrn_resolver.clone()),
983983
)
984984
}
985985

@@ -1000,7 +1000,7 @@ impl Node {
10001000
self.bolt12_payment(),
10011001
Arc::clone(&self.config),
10021002
Arc::clone(&self.logger),
1003-
Arc::clone(&self.hrn_resolver),
1003+
Arc::new(self.hrn_resolver.clone()),
10041004
))
10051005
}
10061006

src/payment/unified.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -64,14 +64,14 @@ pub struct UnifiedPayment {
6464
bolt12_payment: Arc<Bolt12Payment>,
6565
config: Arc<Config>,
6666
logger: Arc<Logger>,
67-
hrn_resolver: Arc<HRNResolver>,
67+
hrn_resolver: Arc<Option<Arc<HRNResolver>>>,
6868
}
6969

7070
impl UnifiedPayment {
7171
pub(crate) fn new(
7272
onchain_payment: Arc<OnchainPayment>, bolt11_invoice: Arc<Bolt11Payment>,
7373
bolt12_payment: Arc<Bolt12Payment>, config: Arc<Config>, logger: Arc<Logger>,
74-
hrn_resolver: Arc<HRNResolver>,
74+
hrn_resolver: Arc<Option<Arc<HRNResolver>>>,
7575
) -> Self {
7676
Self { onchain_payment, bolt11_invoice, bolt12_payment, config, logger, hrn_resolver }
7777
}
@@ -161,12 +161,13 @@ impl UnifiedPayment {
161161
&self, uri_str: &str, amount_msat: Option<u64>,
162162
route_parameters: Option<RouteParametersConfig>,
163163
) -> Result<UnifiedPaymentResult, Error> {
164-
let parse_fut = PaymentInstructions::parse(
165-
uri_str,
166-
self.config.network,
167-
self.hrn_resolver.as_ref(),
168-
false,
169-
);
164+
let resolver = self.hrn_resolver.as_ref().clone().ok_or_else(|| {
165+
log_error!(self.logger, "No HRN resolver configured. Cannot resolve HRNs.");
166+
Error::HrnResolverNotConfigured
167+
})?;
168+
169+
let parse_fut =
170+
PaymentInstructions::parse(uri_str, self.config.network, resolver.as_ref(), false);
170171

171172
let instructions =
172173
tokio::time::timeout(Duration::from_secs(HRN_RESOLUTION_TIMEOUT_SECS), parse_fut)
@@ -192,7 +193,7 @@ impl UnifiedPayment {
192193
Error::InvalidAmount
193194
})?;
194195

195-
let fut = instr.set_amount(amt, self.hrn_resolver.as_ref());
196+
let fut = instr.set_amount(amt, resolver.as_ref());
196197

197198
tokio::time::timeout(Duration::from_secs(HRN_RESOLUTION_TIMEOUT_SECS), fut)
198199
.await

src/types.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use lightning::ln::channel_state::ChannelDetails as LdkChannelDetails;
1919
use lightning::ln::msgs::{RoutingMessageHandler, SocketAddress};
2020
use lightning::ln::peer_handler::IgnoringMessageHandler;
2121
use lightning::ln::types::ChannelId;
22+
use lightning::onion_message::dns_resolution::DNSResolverMessageHandler;
2223
use lightning::routing::gossip;
2324
use lightning::routing::router::DefaultRouter;
2425
use lightning::routing::scoring::{CombinedScorer, ProbabilisticScoringFeeParameters};
@@ -29,6 +30,7 @@ use lightning::util::persist::{
2930
use lightning::util::ser::{Readable, Writeable, Writer};
3031
use lightning::util::sweep::OutputSweeper;
3132
use lightning_block_sync::gossip::GossipVerifier;
33+
use lightning_dns_resolver::OMDomainResolver;
3234
use lightning_liquidity::utils::time::DefaultTimeProvider;
3335
use lightning_net_tokio::SocketDescriptor;
3436

@@ -289,12 +291,14 @@ pub(crate) type OnionMessenger = lightning::onion_message::messenger::OnionMesse
289291
Arc<MessageRouter>,
290292
Arc<ChannelManager>,
291293
Arc<ChannelManager>,
292-
Arc<HRNResolver>,
294+
Arc<dyn DNSResolverMessageHandler + Sync + Send>,
293295
IgnoringMessageHandler,
294296
>;
295297

296298
pub(crate) type HRNResolver = LDKOnionMessageDNSSECHrnResolver<Arc<Graph>, Arc<Logger>>;
297299

300+
pub(crate) type DomainResolver = OMDomainResolver<IgnoringMessageHandler>;
301+
298302
pub(crate) type MessageRouter = lightning::onion_message::messenger::DefaultMessageRouter<
299303
Arc<Graph>,
300304
Arc<Logger>,

0 commit comments

Comments
 (0)