@@ -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 ;
42- use lightning_persister:: fs_store:: v1:: FilesystemStore ;
43+ use lightning:: { log_trace, log_warn} ;
44+ use lightning_dns_resolver:: OMDomainResolver ;
45+ use lightning_persister:: fs_store:: 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 ;
@@ -76,8 +79,8 @@ use crate::runtime::{Runtime, RuntimeSpawner};
7679use crate :: tx_broadcaster:: TransactionBroadcaster ;
7780use crate :: types:: {
7881 AsyncPersister , ChainMonitor , ChannelManager , DynStore , DynStoreWrapper , GossipSync , Graph ,
79- KeysManager , MessageRouter , OnionMessenger , PaymentStore , PeerManager , PendingPaymentStore ,
80- Persister , SyncAndAsyncKVStore ,
82+ HRNResolver , KeysManager , MessageRouter , OnionMessenger , PaymentStore , PeerManager ,
83+ PendingPaymentStore , Persister , SyncAndAsyncKVStore ,
8184} ;
8285use crate :: wallet:: persist:: KVStoreWalletPersister ;
8386use crate :: wallet:: Wallet ;
@@ -190,6 +193,8 @@ pub enum BuildError {
190193 NetworkMismatch ,
191194 /// The role of the node in an asynchronous payments context is not compatible with the current configuration.
192195 AsyncPaymentsConfigMismatch ,
196+ /// An attempt to setup a DNS Resolver failed.
197+ DNSResolverSetupFailed ,
193198}
194199
195200impl fmt:: Display for BuildError {
@@ -222,6 +227,9 @@ impl fmt::Display for BuildError {
222227 "The async payments role is not compatible with the current configuration."
223228 )
224229 } ,
230+ Self :: DNSResolverSetupFailed => {
231+ write ! ( f, "An attempt to setup a DNS resolver has failed." )
232+ } ,
225233 }
226234 }
227235}
@@ -1542,7 +1550,75 @@ fn build_with_store_internal(
15421550 } ) ?;
15431551 }
15441552
1545- let hrn_resolver = Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1553+ // This hook resolves a circular dependency:
1554+ // 1. PeerManager requires OnionMessenger (via MessageHandler).
1555+ // 2. OnionMessenger (via HRN resolver) needs to call PeerManager::process_events.
1556+ //
1557+ // We provide the resolver with a Weak pointer via this Mutex-protected "hook."
1558+ // This allows us to initialize the resolver before the PeerManager exists,
1559+ // and prevents a reference cycle (memory leak).
1560+ let peer_manager_hook: Arc < Mutex < Option < Weak < PeerManager > > > > = Arc :: new ( Mutex :: new ( None ) ) ;
1561+ let hrn_resolver;
1562+
1563+ let runtime_handle = runtime. handle ( ) ;
1564+
1565+ let om_resolver: Arc < dyn DNSResolverMessageHandler + Send + Sync > = match & config
1566+ . hrn_config
1567+ . resolution_config
1568+ {
1569+ HRNResolverConfig :: Blip32 => {
1570+ let hrn_res =
1571+ Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1572+ hrn_resolver = HRNResolver :: Onion ( Arc :: clone ( & hrn_res) ) ;
1573+
1574+ // We clone the hook because it's moved into a Send + Sync closure that outlives this scope.
1575+ let pm_hook_clone = Arc :: clone ( & peer_manager_hook) ;
1576+ hrn_res. register_post_queue_action ( Box :: new ( move || {
1577+ if let Ok ( guard) = pm_hook_clone. lock ( ) {
1578+ if let Some ( pm) = guard. as_ref ( ) . and_then ( |weak| weak. upgrade ( ) ) {
1579+ pm. process_events ( ) ;
1580+ }
1581+ }
1582+ } ) ) ;
1583+ hrn_res as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1584+ } ,
1585+ HRNResolverConfig :: Dns { dns_server_address, enable_hrn_resolution_service, .. } => {
1586+ let addr = dns_server_address. parse ( ) . map_err ( |_| {
1587+ log_error ! ( logger, "Failed to parse DNS server address: {}" , dns_server_address) ;
1588+ BuildError :: DNSResolverSetupFailed
1589+ } ) ?;
1590+
1591+ if * enable_hrn_resolution_service && may_announce_channel ( & config) . is_ok ( ) {
1592+ let hrn_res = Arc :: new ( DNSHrnResolver ( addr) ) ;
1593+ hrn_resolver = HRNResolver :: Local ( hrn_res) ;
1594+
1595+ Arc :: new ( OMDomainResolver :: < IgnoringMessageHandler > :: with_runtime (
1596+ addr,
1597+ None ,
1598+ Some ( runtime_handle. clone ( ) ) ,
1599+ ) ) as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1600+ } else {
1601+ if * enable_hrn_resolution_service {
1602+ 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." ) ;
1603+ }
1604+
1605+ // Fallback/Default: Onion resolver
1606+ let hrn_res =
1607+ Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1608+ hrn_resolver = HRNResolver :: Onion ( Arc :: clone ( & hrn_res) ) ;
1609+
1610+ let pm_hook_clone = Arc :: clone ( & peer_manager_hook) ;
1611+ hrn_res. register_post_queue_action ( Box :: new ( move || {
1612+ if let Ok ( guard) = pm_hook_clone. lock ( ) {
1613+ if let Some ( pm) = guard. as_ref ( ) . and_then ( |weak| weak. upgrade ( ) ) {
1614+ pm. process_events ( ) ;
1615+ }
1616+ }
1617+ } ) ) ;
1618+ hrn_res as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1619+ }
1620+ } ,
1621+ } ;
15461622
15471623 // Initialize the PeerManager
15481624 let onion_messenger: Arc < OnionMessenger > =
@@ -1555,7 +1631,7 @@ fn build_with_store_internal(
15551631 message_router,
15561632 Arc :: clone ( & channel_manager) ,
15571633 Arc :: clone ( & channel_manager) ,
1558- Arc :: clone ( & hrn_resolver ) ,
1634+ Arc :: clone ( & om_resolver ) ,
15591635 IgnoringMessageHandler { } ,
15601636 ) )
15611637 } else {
@@ -1567,7 +1643,7 @@ fn build_with_store_internal(
15671643 message_router,
15681644 Arc :: clone ( & channel_manager) ,
15691645 Arc :: clone ( & channel_manager) ,
1570- Arc :: clone ( & hrn_resolver ) ,
1646+ Arc :: clone ( & om_resolver ) ,
15711647 IgnoringMessageHandler { } ,
15721648 ) )
15731649 } ;
@@ -1699,12 +1775,7 @@ fn build_with_store_internal(
16991775 Arc :: clone ( & keys_manager) ,
17001776 ) ) ;
17011777
1702- let peer_manager_clone = Arc :: downgrade ( & peer_manager) ;
1703- hrn_resolver. register_post_queue_action ( Box :: new ( move || {
1704- if let Some ( upgraded_pointer) = peer_manager_clone. upgrade ( ) {
1705- upgraded_pointer. process_events ( ) ;
1706- }
1707- } ) ) ;
1778+ * peer_manager_hook. lock ( ) . unwrap ( ) = Some ( Arc :: downgrade ( & peer_manager) ) ;
17081779
17091780 liquidity_source. as_ref ( ) . map ( |l| l. set_peer_manager ( Arc :: downgrade ( & peer_manager) ) ) ;
17101781
@@ -1811,7 +1882,7 @@ fn build_with_store_internal(
18111882 node_metrics,
18121883 om_mailbox,
18131884 async_payments_role,
1814- hrn_resolver,
1885+ hrn_resolver : Arc :: new ( hrn_resolver ) ,
18151886 #[ cfg( cycle_tests) ]
18161887 _leak_checker,
18171888 } )
0 commit comments