@@ -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,14 +40,16 @@ 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 , TorConfig ,
49- DEFAULT_ESPLORA_SERVER_URL , DEFAULT_LOG_FILENAME , DEFAULT_LOG_LEVEL ,
51+ BitcoindRestClientConfig , Config , ElectrumSyncConfig , EsploraSyncConfig , HRNResolverConfig ,
52+ TorConfig , DEFAULT_ESPLORA_SERVER_URL , DEFAULT_LOG_FILENAME , DEFAULT_LOG_LEVEL ,
5053} ;
5154use crate :: connection:: ConnectionManager ;
5255use crate :: entropy:: NodeEntropy ;
@@ -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 ;
@@ -193,6 +196,8 @@ pub enum BuildError {
193196 NetworkMismatch ,
194197 /// The role of the node in an asynchronous payments context is not compatible with the current configuration.
195198 AsyncPaymentsConfigMismatch ,
199+ /// An attempt to setup a DNS Resolver failed.
200+ DNSResolverSetupFailed ,
196201}
197202
198203impl fmt:: Display for BuildError {
@@ -226,6 +231,9 @@ impl fmt::Display for BuildError {
226231 "The async payments role is not compatible with the current configuration."
227232 )
228233 } ,
234+ Self :: DNSResolverSetupFailed => {
235+ write ! ( f, "An attempt to setup a DNS resolver has failed." )
236+ } ,
229237 }
230238 }
231239}
@@ -1651,7 +1659,75 @@ fn build_with_store_internal(
16511659 } ) ?;
16521660 }
16531661
1654- let hrn_resolver = Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1662+ // This hook resolves a circular dependency:
1663+ // 1. PeerManager requires OnionMessenger (via MessageHandler).
1664+ // 2. OnionMessenger (via HRN resolver) needs to call PeerManager::process_events.
1665+ //
1666+ // We provide the resolver with a Weak pointer via this Mutex-protected "hook."
1667+ // This allows us to initialize the resolver before the PeerManager exists,
1668+ // and prevents a reference cycle (memory leak).
1669+ let peer_manager_hook: Arc < Mutex < Option < Weak < PeerManager > > > > = Arc :: new ( Mutex :: new ( None ) ) ;
1670+ let hrn_resolver;
1671+
1672+ let runtime_handle = runtime. handle ( ) ;
1673+
1674+ let om_resolver: Arc < dyn DNSResolverMessageHandler + Send + Sync > = match & config
1675+ . hrn_config
1676+ . resolution_config
1677+ {
1678+ HRNResolverConfig :: Blip32 => {
1679+ let hrn_res =
1680+ Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1681+ hrn_resolver = HRNResolver :: Onion ( Arc :: clone ( & hrn_res) ) ;
1682+
1683+ // We clone the hook because it's moved into a Send + Sync closure that outlives this scope.
1684+ let pm_hook_clone = Arc :: clone ( & peer_manager_hook) ;
1685+ hrn_res. register_post_queue_action ( Box :: new ( move || {
1686+ if let Ok ( guard) = pm_hook_clone. lock ( ) {
1687+ if let Some ( pm) = guard. as_ref ( ) . and_then ( |weak| weak. upgrade ( ) ) {
1688+ pm. process_events ( ) ;
1689+ }
1690+ }
1691+ } ) ) ;
1692+ hrn_res as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1693+ } ,
1694+ HRNResolverConfig :: Dns { dns_server_address, enable_hrn_resolution_service, .. } => {
1695+ let addr = dns_server_address. parse ( ) . map_err ( |_| {
1696+ log_error ! ( logger, "Failed to parse DNS server address: {}" , dns_server_address) ;
1697+ BuildError :: DNSResolverSetupFailed
1698+ } ) ?;
1699+
1700+ if * enable_hrn_resolution_service && may_announce_channel ( & config) . is_ok ( ) {
1701+ let hrn_res = Arc :: new ( DNSHrnResolver ( addr) ) ;
1702+ hrn_resolver = HRNResolver :: Local ( hrn_res) ;
1703+
1704+ Arc :: new ( OMDomainResolver :: < IgnoringMessageHandler > :: with_runtime (
1705+ addr,
1706+ None ,
1707+ Some ( runtime_handle. clone ( ) ) ,
1708+ ) ) as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1709+ } else {
1710+ if * enable_hrn_resolution_service {
1711+ 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." ) ;
1712+ }
1713+
1714+ // Fallback/Default: Onion resolver
1715+ let hrn_res =
1716+ Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1717+ hrn_resolver = HRNResolver :: Onion ( Arc :: clone ( & hrn_res) ) ;
1718+
1719+ let pm_hook_clone = Arc :: clone ( & peer_manager_hook) ;
1720+ hrn_res. register_post_queue_action ( Box :: new ( move || {
1721+ if let Ok ( guard) = pm_hook_clone. lock ( ) {
1722+ if let Some ( pm) = guard. as_ref ( ) . and_then ( |weak| weak. upgrade ( ) ) {
1723+ pm. process_events ( ) ;
1724+ }
1725+ }
1726+ } ) ) ;
1727+ hrn_res as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1728+ }
1729+ } ,
1730+ } ;
16551731
16561732 // Initialize the PeerManager
16571733 let onion_messenger: Arc < OnionMessenger > =
@@ -1664,7 +1740,7 @@ fn build_with_store_internal(
16641740 message_router,
16651741 Arc :: clone ( & channel_manager) ,
16661742 Arc :: clone ( & channel_manager) ,
1667- Arc :: clone ( & hrn_resolver ) ,
1743+ Arc :: clone ( & om_resolver ) ,
16681744 IgnoringMessageHandler { } ,
16691745 ) )
16701746 } else {
@@ -1676,7 +1752,7 @@ fn build_with_store_internal(
16761752 message_router,
16771753 Arc :: clone ( & channel_manager) ,
16781754 Arc :: clone ( & channel_manager) ,
1679- Arc :: clone ( & hrn_resolver ) ,
1755+ Arc :: clone ( & om_resolver ) ,
16801756 IgnoringMessageHandler { } ,
16811757 ) )
16821758 } ;
@@ -1808,12 +1884,7 @@ fn build_with_store_internal(
18081884 Arc :: clone ( & keys_manager) ,
18091885 ) ) ;
18101886
1811- let peer_manager_clone = Arc :: downgrade ( & peer_manager) ;
1812- hrn_resolver. register_post_queue_action ( Box :: new ( move || {
1813- if let Some ( upgraded_pointer) = peer_manager_clone. upgrade ( ) {
1814- upgraded_pointer. process_events ( ) ;
1815- }
1816- } ) ) ;
1887+ * peer_manager_hook. lock ( ) . unwrap ( ) = Some ( Arc :: downgrade ( & peer_manager) ) ;
18171888
18181889 liquidity_source. as_ref ( ) . map ( |l| l. set_peer_manager ( Arc :: downgrade ( & peer_manager) ) ) ;
18191890
@@ -1927,7 +1998,7 @@ fn build_with_store_internal(
19271998 node_metrics,
19281999 om_mailbox,
19292000 async_payments_role,
1930- hrn_resolver,
2001+ hrn_resolver : Arc :: new ( hrn_resolver ) ,
19312002 #[ cfg( cycle_tests) ]
19322003 _leak_checker,
19332004 } )
0 commit comments