@@ -9,7 +9,7 @@ use std::collections::HashMap;
99use std:: convert:: TryInto ;
1010use std:: default:: Default ;
1111use std:: path:: PathBuf ;
12- use std:: sync:: { Arc , Mutex , Once , RwLock } ;
12+ use std:: sync:: { Arc , Mutex , Once , RwLock , Weak } ;
1313use std:: time:: SystemTime ;
1414use std:: { fmt, fs} ;
1515
@@ -19,12 +19,13 @@ use bitcoin::bip32::{ChildNumber, Xpriv};
1919use bitcoin:: key:: Secp256k1 ;
2020use bitcoin:: secp256k1:: PublicKey ;
2121use bitcoin:: { BlockHash , Network } ;
22+ use bitcoin_payment_instructions:: dns_resolver:: DNSHrnResolver ;
2223use bitcoin_payment_instructions:: onion_message_resolver:: LDKOnionMessageDNSSECHrnResolver ;
2324use lightning:: chain:: { chainmonitor, BestBlock } ;
2425use lightning:: ln:: channelmanager:: { self , ChainParameters , ChannelManagerReadArgs } ;
2526use lightning:: ln:: msgs:: { RoutingMessageHandler , SocketAddress } ;
2627use lightning:: ln:: peer_handler:: { IgnoringMessageHandler , MessageHandler } ;
27- use lightning:: log_trace ;
28+ use lightning:: onion_message :: dns_resolution :: DNSResolverMessageHandler ;
2829use lightning:: routing:: gossip:: NodeAlias ;
2930use lightning:: routing:: router:: DefaultRouter ;
3031use lightning:: routing:: scoring:: {
@@ -39,13 +40,15 @@ use lightning::util::persist::{
3940} ;
4041use lightning:: util:: ser:: ReadableArgs ;
4142use lightning:: util:: sweep:: OutputSweeper ;
43+ use lightning:: { log_trace, log_warn} ;
44+ use lightning_dns_resolver:: OMDomainResolver ;
4245use lightning_persister:: fs_store:: v1:: FilesystemStore ;
4346use vss_client:: headers:: VssHeaderProvider ;
4447
4548use crate :: chain:: ChainSource ;
4649use crate :: config:: {
4750 default_user_config, may_announce_channel, AnnounceError , AsyncPaymentsRole ,
48- BitcoindRestClientConfig , Config , ElectrumSyncConfig , EsploraSyncConfig ,
51+ BitcoindRestClientConfig , Config , ElectrumSyncConfig , EsploraSyncConfig , HRNResolverConfig ,
4952 DEFAULT_ESPLORA_SERVER_URL , DEFAULT_LOG_FILENAME , DEFAULT_LOG_LEVEL ,
5053} ;
5154use crate :: connection:: ConnectionManager ;
@@ -77,8 +80,8 @@ use crate::runtime::{Runtime, RuntimeSpawner};
7780use crate :: tx_broadcaster:: TransactionBroadcaster ;
7881use crate :: types:: {
7982 AsyncPersister , ChainMonitor , ChannelManager , DynStore , DynStoreWrapper , GossipSync , Graph ,
80- KeysManager , MessageRouter , OnionMessenger , PaymentStore , PeerManager , PendingPaymentStore ,
81- Persister , SyncAndAsyncKVStore ,
83+ HRNResolver , KeysManager , MessageRouter , OnionMessenger , PaymentStore , PeerManager ,
84+ PendingPaymentStore , Persister , SyncAndAsyncKVStore ,
8285} ;
8386use crate :: wallet:: persist:: KVStoreWalletPersister ;
8487use crate :: wallet:: Wallet ;
@@ -191,6 +194,8 @@ pub enum BuildError {
191194 NetworkMismatch ,
192195 /// The role of the node in an asynchronous payments context is not compatible with the current configuration.
193196 AsyncPaymentsConfigMismatch ,
197+ /// An attempt to setup a DNS Resolver failed.
198+ DNSResolverSetupFailed ,
194199}
195200
196201impl fmt:: Display for BuildError {
@@ -223,6 +228,9 @@ impl fmt::Display for BuildError {
223228 "The async payments role is not compatible with the current configuration."
224229 )
225230 } ,
231+ Self :: DNSResolverSetupFailed => {
232+ write ! ( f, "An attempt to setup a DNS resolver has failed." )
233+ } ,
226234 }
227235 }
228236}
@@ -1613,7 +1621,75 @@ fn build_with_store_internal(
16131621 } ) ?;
16141622 }
16151623
1616- let hrn_resolver = Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1624+ // This hook resolves a circular dependency:
1625+ // 1. PeerManager requires OnionMessenger (via MessageHandler).
1626+ // 2. OnionMessenger (via HRN resolver) needs to call PeerManager::process_events.
1627+ //
1628+ // We provide the resolver with a Weak pointer via this Mutex-protected "hook."
1629+ // This allows us to initialize the resolver before the PeerManager exists,
1630+ // and prevents a reference cycle (memory leak).
1631+ let peer_manager_hook: Arc < Mutex < Option < Weak < PeerManager > > > > = Arc :: new ( Mutex :: new ( None ) ) ;
1632+ let hrn_resolver;
1633+
1634+ let runtime_handle = runtime. handle ( ) ;
1635+
1636+ let om_resolver: Arc < dyn DNSResolverMessageHandler + Send + Sync > = match & config
1637+ . hrn_config
1638+ . resolution_config
1639+ {
1640+ HRNResolverConfig :: Blip32 => {
1641+ let hrn_res =
1642+ Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1643+ hrn_resolver = HRNResolver :: Onion ( Arc :: clone ( & hrn_res) ) ;
1644+
1645+ // We clone the hook because it's moved into a Send + Sync closure that outlives this scope.
1646+ let pm_hook_clone = Arc :: clone ( & peer_manager_hook) ;
1647+ hrn_res. register_post_queue_action ( Box :: new ( move || {
1648+ if let Ok ( guard) = pm_hook_clone. lock ( ) {
1649+ if let Some ( pm) = guard. as_ref ( ) . and_then ( |weak| weak. upgrade ( ) ) {
1650+ pm. process_events ( ) ;
1651+ }
1652+ }
1653+ } ) ) ;
1654+ hrn_res as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1655+ } ,
1656+ HRNResolverConfig :: Dns { dns_server_address, enable_hrn_resolution_service, .. } => {
1657+ let addr = dns_server_address. parse ( ) . map_err ( |_| {
1658+ log_error ! ( logger, "Failed to parse DNS server address: {}" , dns_server_address) ;
1659+ BuildError :: DNSResolverSetupFailed
1660+ } ) ?;
1661+
1662+ if * enable_hrn_resolution_service && may_announce_channel ( & config) . is_ok ( ) {
1663+ let hrn_res = Arc :: new ( DNSHrnResolver ( addr) ) ;
1664+ hrn_resolver = HRNResolver :: Local ( hrn_res) ;
1665+
1666+ Arc :: new ( OMDomainResolver :: < IgnoringMessageHandler > :: with_runtime (
1667+ addr,
1668+ None ,
1669+ Some ( runtime_handle. clone ( ) ) ,
1670+ ) ) as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1671+ } else {
1672+ if * enable_hrn_resolution_service {
1673+ log_warn ! ( logger, "Unable to act as an HRN resolution service. To act as an HRN resolution service, the node must be configured to announce channels." ) ;
1674+ }
1675+
1676+ // Fallback/Default: Onion resolver
1677+ let hrn_res =
1678+ Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1679+ hrn_resolver = HRNResolver :: Onion ( Arc :: clone ( & hrn_res) ) ;
1680+
1681+ let pm_hook_clone = Arc :: clone ( & peer_manager_hook) ;
1682+ hrn_res. register_post_queue_action ( Box :: new ( move || {
1683+ if let Ok ( guard) = pm_hook_clone. lock ( ) {
1684+ if let Some ( pm) = guard. as_ref ( ) . and_then ( |weak| weak. upgrade ( ) ) {
1685+ pm. process_events ( ) ;
1686+ }
1687+ }
1688+ } ) ) ;
1689+ hrn_res as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1690+ }
1691+ } ,
1692+ } ;
16171693
16181694 // Initialize the PeerManager
16191695 let onion_messenger: Arc < OnionMessenger > =
@@ -1626,7 +1702,7 @@ fn build_with_store_internal(
16261702 message_router,
16271703 Arc :: clone ( & channel_manager) ,
16281704 Arc :: clone ( & channel_manager) ,
1629- Arc :: clone ( & hrn_resolver ) ,
1705+ Arc :: clone ( & om_resolver ) ,
16301706 IgnoringMessageHandler { } ,
16311707 ) )
16321708 } else {
@@ -1638,7 +1714,7 @@ fn build_with_store_internal(
16381714 message_router,
16391715 Arc :: clone ( & channel_manager) ,
16401716 Arc :: clone ( & channel_manager) ,
1641- Arc :: clone ( & hrn_resolver ) ,
1717+ Arc :: clone ( & om_resolver ) ,
16421718 IgnoringMessageHandler { } ,
16431719 ) )
16441720 } ;
@@ -1770,12 +1846,7 @@ fn build_with_store_internal(
17701846 Arc :: clone ( & keys_manager) ,
17711847 ) ) ;
17721848
1773- let peer_manager_clone = Arc :: downgrade ( & peer_manager) ;
1774- hrn_resolver. register_post_queue_action ( Box :: new ( move || {
1775- if let Some ( upgraded_pointer) = peer_manager_clone. upgrade ( ) {
1776- upgraded_pointer. process_events ( ) ;
1777- }
1778- } ) ) ;
1849+ * peer_manager_hook. lock ( ) . unwrap ( ) = Some ( Arc :: downgrade ( & peer_manager) ) ;
17791850
17801851 liquidity_source. as_ref ( ) . map ( |l| l. set_peer_manager ( Arc :: downgrade ( & peer_manager) ) ) ;
17811852
@@ -1885,7 +1956,7 @@ fn build_with_store_internal(
18851956 node_metrics,
18861957 om_mailbox,
18871958 async_payments_role,
1888- hrn_resolver,
1959+ hrn_resolver : Arc :: new ( hrn_resolver ) ,
18891960 #[ cfg( cycle_tests) ]
18901961 _leak_checker,
18911962 } )
0 commit comments