@@ -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 , DynStoreRef , DynStoreWrapper ,
80- GossipSync , Graph , KeysManager , MessageRouter , OnionMessenger , PaymentStore , PeerManager ,
81- PendingPaymentStore , SyncAndAsyncKVStore ,
83+ GossipSync , Graph , HRNResolver , KeysManager , MessageRouter , OnionMessenger , PaymentStore ,
84+ PeerManager , PendingPaymentStore , 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}
@@ -1717,7 +1725,75 @@ fn build_with_store_internal(
17171725 } ) ?;
17181726 }
17191727
1720- let hrn_resolver = Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1728+ // This hook resolves a circular dependency:
1729+ // 1. PeerManager requires OnionMessenger (via MessageHandler).
1730+ // 2. OnionMessenger (via HRN resolver) needs to call PeerManager::process_events.
1731+ //
1732+ // We provide the resolver with a Weak pointer via this Mutex-protected "hook."
1733+ // This allows us to initialize the resolver before the PeerManager exists,
1734+ // and prevents a reference cycle (memory leak).
1735+ let peer_manager_hook: Arc < Mutex < Option < Weak < PeerManager > > > > = Arc :: new ( Mutex :: new ( None ) ) ;
1736+ let hrn_resolver;
1737+
1738+ let runtime_handle = runtime. handle ( ) ;
1739+
1740+ let om_resolver: Arc < dyn DNSResolverMessageHandler + Send + Sync > = match & config
1741+ . hrn_config
1742+ . resolution_config
1743+ {
1744+ HRNResolverConfig :: Blip32 => {
1745+ let hrn_res =
1746+ Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1747+ hrn_resolver = HRNResolver :: Onion ( Arc :: clone ( & hrn_res) ) ;
1748+
1749+ // We clone the hook because it's moved into a Send + Sync closure that outlives this scope.
1750+ let pm_hook_clone = Arc :: clone ( & peer_manager_hook) ;
1751+ hrn_res. register_post_queue_action ( Box :: new ( move || {
1752+ if let Ok ( guard) = pm_hook_clone. lock ( ) {
1753+ if let Some ( pm) = guard. as_ref ( ) . and_then ( |weak| weak. upgrade ( ) ) {
1754+ pm. process_events ( ) ;
1755+ }
1756+ }
1757+ } ) ) ;
1758+ hrn_res as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1759+ } ,
1760+ HRNResolverConfig :: Dns { dns_server_address, enable_hrn_resolution_service, .. } => {
1761+ let addr = dns_server_address. parse ( ) . map_err ( |_| {
1762+ log_error ! ( logger, "Failed to parse DNS server address: {}" , dns_server_address) ;
1763+ BuildError :: DNSResolverSetupFailed
1764+ } ) ?;
1765+
1766+ if * enable_hrn_resolution_service && may_announce_channel ( & config) . is_ok ( ) {
1767+ let hrn_res = Arc :: new ( DNSHrnResolver ( addr) ) ;
1768+ hrn_resolver = HRNResolver :: Local ( hrn_res) ;
1769+
1770+ Arc :: new ( OMDomainResolver :: < IgnoringMessageHandler > :: with_runtime (
1771+ addr,
1772+ None ,
1773+ Some ( runtime_handle. clone ( ) ) ,
1774+ ) ) as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1775+ } else {
1776+ if * enable_hrn_resolution_service {
1777+ 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." ) ;
1778+ }
1779+
1780+ // Fallback/Default: Onion resolver
1781+ let hrn_res =
1782+ Arc :: new ( LDKOnionMessageDNSSECHrnResolver :: new ( Arc :: clone ( & network_graph) ) ) ;
1783+ hrn_resolver = HRNResolver :: Onion ( Arc :: clone ( & hrn_res) ) ;
1784+
1785+ let pm_hook_clone = Arc :: clone ( & peer_manager_hook) ;
1786+ hrn_res. register_post_queue_action ( Box :: new ( move || {
1787+ if let Ok ( guard) = pm_hook_clone. lock ( ) {
1788+ if let Some ( pm) = guard. as_ref ( ) . and_then ( |weak| weak. upgrade ( ) ) {
1789+ pm. process_events ( ) ;
1790+ }
1791+ }
1792+ } ) ) ;
1793+ hrn_res as Arc < dyn DNSResolverMessageHandler + Send + Sync >
1794+ }
1795+ } ,
1796+ } ;
17211797
17221798 // Initialize the PeerManager
17231799 let onion_messenger: Arc < OnionMessenger > =
@@ -1730,7 +1806,7 @@ fn build_with_store_internal(
17301806 message_router,
17311807 Arc :: clone ( & channel_manager) ,
17321808 Arc :: clone ( & channel_manager) ,
1733- Arc :: clone ( & hrn_resolver ) ,
1809+ Arc :: clone ( & om_resolver ) ,
17341810 IgnoringMessageHandler { } ,
17351811 ) )
17361812 } else {
@@ -1742,7 +1818,7 @@ fn build_with_store_internal(
17421818 message_router,
17431819 Arc :: clone ( & channel_manager) ,
17441820 Arc :: clone ( & channel_manager) ,
1745- Arc :: clone ( & hrn_resolver ) ,
1821+ Arc :: clone ( & om_resolver ) ,
17461822 IgnoringMessageHandler { } ,
17471823 ) )
17481824 } ;
@@ -1873,12 +1949,7 @@ fn build_with_store_internal(
18731949 Arc :: clone ( & keys_manager) ,
18741950 ) ) ;
18751951
1876- let peer_manager_clone = Arc :: downgrade ( & peer_manager) ;
1877- hrn_resolver. register_post_queue_action ( Box :: new ( move || {
1878- if let Some ( upgraded_pointer) = peer_manager_clone. upgrade ( ) {
1879- upgraded_pointer. process_events ( ) ;
1880- }
1881- } ) ) ;
1952+ * peer_manager_hook. lock ( ) . unwrap ( ) = Some ( Arc :: downgrade ( & peer_manager) ) ;
18821953
18831954 liquidity_source. as_ref ( ) . map ( |l| l. set_peer_manager ( Arc :: downgrade ( & peer_manager) ) ) ;
18841955
@@ -1992,7 +2063,7 @@ fn build_with_store_internal(
19922063 node_metrics,
19932064 om_mailbox,
19942065 async_payments_role,
1995- hrn_resolver,
2066+ hrn_resolver : Arc :: new ( hrn_resolver ) ,
19962067 #[ cfg( cycle_tests) ]
19972068 _leak_checker,
19982069 } )
0 commit comments