88use std:: collections:: HashMap ;
99use std:: convert:: TryInto ;
1010use std:: default:: Default ;
11+ use std:: net:: ToSocketAddrs ;
1112use std:: path:: PathBuf ;
12- use std:: sync:: { Arc , Mutex , Once , RwLock } ;
13+ use std:: sync:: { Arc , Mutex , Once , RwLock , Weak } ;
1314use std:: time:: SystemTime ;
1415use std:: { fmt, fs} ;
1516
@@ -19,12 +20,14 @@ use bitcoin::bip32::{ChildNumber, Xpriv};
1920use bitcoin:: key:: Secp256k1 ;
2021use bitcoin:: secp256k1:: PublicKey ;
2122use bitcoin:: { BlockHash , Network } ;
23+ use bitcoin_payment_instructions:: dns_resolver:: DNSHrnResolver ;
2224use bitcoin_payment_instructions:: onion_message_resolver:: LDKOnionMessageDNSSECHrnResolver ;
2325use lightning:: chain:: { chainmonitor, BestBlock } ;
2426use lightning:: ln:: channelmanager:: { self , ChainParameters , ChannelManagerReadArgs } ;
2527use lightning:: ln:: msgs:: { RoutingMessageHandler , SocketAddress } ;
2628use lightning:: ln:: peer_handler:: { IgnoringMessageHandler , MessageHandler } ;
2729use lightning:: log_trace;
30+ use lightning:: onion_message:: dns_resolution:: DNSResolverMessageHandler ;
2831use lightning:: routing:: gossip:: NodeAlias ;
2932use lightning:: routing:: router:: DefaultRouter ;
3033use lightning:: routing:: scoring:: {
@@ -39,14 +42,15 @@ use lightning::util::persist::{
3942} ;
4043use lightning:: util:: ser:: ReadableArgs ;
4144use lightning:: util:: sweep:: OutputSweeper ;
45+ use lightning_dns_resolver:: OMDomainResolver ;
4246use lightning_persister:: fs_store:: v1:: FilesystemStore ;
4347use vss_client:: headers:: VssHeaderProvider ;
4448
4549use crate :: chain:: ChainSource ;
4650use crate :: config:: {
4751 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 ,
52+ BitcoindRestClientConfig , Config , ElectrumSyncConfig , EsploraSyncConfig , HRNResolverConfig ,
53+ TorConfig , DEFAULT_ESPLORA_SERVER_URL , DEFAULT_LOG_FILENAME , DEFAULT_LOG_LEVEL ,
5054} ;
5155use crate :: connection:: ConnectionManager ;
5256use crate :: entropy:: NodeEntropy ;
@@ -77,8 +81,8 @@ use crate::runtime::{Runtime, RuntimeSpawner};
7781use crate :: tx_broadcaster:: TransactionBroadcaster ;
7882use crate :: types:: {
7983 AsyncPersister , ChainMonitor , ChannelManager , DynStore , DynStoreRef , DynStoreWrapper ,
80- GossipSync , Graph , KeysManager , MessageRouter , OnionMessenger , PaymentStore , PeerManager ,
81- PendingPaymentStore , SyncAndAsyncKVStore ,
84+ GossipSync , Graph , HRNResolver , KeysManager , MessageRouter , OnionMessenger , PaymentStore ,
85+ PeerManager , PendingPaymentStore , SyncAndAsyncKVStore ,
8286} ;
8387use crate :: wallet:: persist:: KVStoreWalletPersister ;
8488use crate :: wallet:: Wallet ;
@@ -195,6 +199,8 @@ pub enum BuildError {
195199 NetworkMismatch ,
196200 /// The role of the node in an asynchronous payments context is not compatible with the current configuration.
197201 AsyncPaymentsConfigMismatch ,
202+ /// An attempt to setup a DNS Resolver failed.
203+ DNSResolverSetupFailed ,
198204}
199205
200206impl fmt:: Display for BuildError {
@@ -229,6 +235,9 @@ impl fmt::Display for BuildError {
229235 "The async payments role is not compatible with the current configuration."
230236 )
231237 } ,
238+ Self :: DNSResolverSetupFailed => {
239+ write ! ( f, "An attempt to setup a DNS resolver has failed." )
240+ } ,
232241 }
233242 }
234243}
@@ -1726,7 +1735,71 @@ fn build_with_store_internal(
17261735 } ) ?;
17271736 }
17281737
1729- let hrn_resolver = Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1738+ // This hook resolves a circular dependency:
1739+ // 1. PeerManager requires OnionMessenger (via MessageHandler).
1740+ // 2. OnionMessenger (via HRN resolver) needs to call PeerManager::process_events.
1741+ //
1742+ // We provide the resolver with a Weak pointer via this Mutex-protected "hook."
1743+ // This allows us to initialize the resolver before the PeerManager exists,
1744+ // and prevents a reference cycle (memory leak).
1745+ let peer_manager_hook: Arc < Mutex < Option < Weak < PeerManager > > > > = Arc :: new ( Mutex :: new ( None ) ) ;
1746+ let hrn_resolver;
1747+
1748+ let runtime_handle = runtime. handle ( ) ;
1749+
1750+ let om_resolver: Arc < dyn DNSResolverMessageHandler + Send + Sync > = match & config
1751+ . hrn_config
1752+ . resolution_config
1753+ {
1754+ HRNResolverConfig :: Blip32 => {
1755+ let hrn_res =
1756+ Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1757+ hrn_resolver = HRNResolver :: Onion ( Arc :: clone ( & hrn_res) ) ;
1758+
1759+ // We clone the hook because it's moved into a Send + Sync closure that outlives this scope.
1760+ let pm_hook_clone = Arc :: clone ( & peer_manager_hook) ;
1761+ hrn_res. register_post_queue_action ( Box :: new ( move || {
1762+ if let Ok ( guard) = pm_hook_clone. lock ( ) {
1763+ if let Some ( pm) = guard. as_ref ( ) . and_then ( |weak| weak. upgrade ( ) ) {
1764+ pm. process_events ( ) ;
1765+ }
1766+ }
1767+ } ) ) ;
1768+ hrn_res as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1769+ } ,
1770+ HRNResolverConfig :: Dns { dns_server_address, enable_hrn_resolution_service, .. } => {
1771+ let addr = dns_server_address
1772+ . to_socket_addrs ( )
1773+ . map_err ( |_| BuildError :: DNSResolverSetupFailed ) ?
1774+ . next ( )
1775+ . ok_or ( {
1776+ log_error ! ( logger, "No valid address found for: {}" , dns_server_address) ;
1777+ BuildError :: DNSResolverSetupFailed
1778+ } ) ?;
1779+ let hrn_res = Arc :: new ( DNSHrnResolver ( addr) ) ;
1780+ hrn_resolver = HRNResolver :: Local ( hrn_res) ;
1781+
1782+ if * enable_hrn_resolution_service {
1783+ if let Err ( _) = may_announce_channel ( & config) {
1784+ log_error ! (
1785+ logger,
1786+ "HRN resolution service enabled, but node is not announceable."
1787+ ) ;
1788+ return Err ( BuildError :: DNSResolverSetupFailed ) ;
1789+ }
1790+
1791+ Arc :: new ( OMDomainResolver :: < IgnoringMessageHandler > :: with_runtime (
1792+ addr,
1793+ None ,
1794+ Some ( runtime_handle. clone ( ) ) ,
1795+ ) ) as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1796+ } else {
1797+ // The user wants to use DNS to pay others, but NOT provide a service to others.
1798+ Arc :: new ( IgnoringMessageHandler { } )
1799+ as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1800+ }
1801+ } ,
1802+ } ;
17301803
17311804 // Initialize the PeerManager
17321805 let onion_messenger: Arc < OnionMessenger > =
@@ -1739,7 +1812,7 @@ fn build_with_store_internal(
17391812 message_router,
17401813 Arc :: clone ( & channel_manager) ,
17411814 Arc :: clone ( & channel_manager) ,
1742- Arc :: clone ( & hrn_resolver ) ,
1815+ Arc :: clone ( & om_resolver ) ,
17431816 IgnoringMessageHandler { } ,
17441817 ) )
17451818 } else {
@@ -1751,7 +1824,7 @@ fn build_with_store_internal(
17511824 message_router,
17521825 Arc :: clone ( & channel_manager) ,
17531826 Arc :: clone ( & channel_manager) ,
1754- Arc :: clone ( & hrn_resolver ) ,
1827+ Arc :: clone ( & om_resolver ) ,
17551828 IgnoringMessageHandler { } ,
17561829 ) )
17571830 } ;
@@ -1882,12 +1955,9 @@ fn build_with_store_internal(
18821955 Arc :: clone ( & keys_manager) ,
18831956 ) ) ;
18841957
1885- let peer_manager_clone = Arc :: downgrade ( & peer_manager) ;
1886- hrn_resolver. register_post_queue_action ( Box :: new ( move || {
1887- if let Some ( upgraded_pointer) = peer_manager_clone. upgrade ( ) {
1888- upgraded_pointer. process_events ( ) ;
1889- }
1890- } ) ) ;
1958+ if let Ok ( mut guard) = peer_manager_hook. lock ( ) {
1959+ * guard = Some ( Arc :: downgrade ( & peer_manager) ) ;
1960+ }
18911961
18921962 liquidity_source. as_ref ( ) . map ( |l| l. set_peer_manager ( Arc :: downgrade ( & peer_manager) ) ) ;
18931963
@@ -2001,7 +2071,7 @@ fn build_with_store_internal(
20012071 node_metrics,
20022072 om_mailbox,
20032073 async_payments_role,
2004- hrn_resolver,
2074+ hrn_resolver : Arc :: new ( hrn_resolver ) ,
20052075 #[ cfg( cycle_tests) ]
20062076 _leak_checker,
20072077 } )
0 commit comments