@@ -107,7 +107,7 @@ pub use error::Error as NodeError;
107107use error:: Error ;
108108
109109pub use event:: Event ;
110- pub use types:: ChannelConfig ;
110+ pub use types:: { BestBlock , ChannelConfig } ;
111111
112112pub use io:: utils:: generate_entropy_mnemonic;
113113
@@ -167,8 +167,9 @@ use rand::Rng;
167167
168168use std:: default:: Default ;
169169use std:: net:: ToSocketAddrs ;
170+ use std:: sync:: atomic:: { AtomicBool , Ordering } ;
170171use std:: sync:: { Arc , Mutex , RwLock } ;
171- use std:: time:: { Duration , Instant , SystemTime } ;
172+ use std:: time:: { Duration , Instant , SystemTime , UNIX_EPOCH } ;
172173
173174#[ cfg( feature = "uniffi" ) ]
174175uniffi:: include_scaffolding!( "ldk_node" ) ;
@@ -199,6 +200,12 @@ pub struct Node<K: KVStore + Sync + Send + 'static> {
199200 scorer : Arc < Mutex < Scorer > > ,
200201 peer_store : Arc < PeerStore < K , Arc < FilesystemLogger > > > ,
201202 payment_store : Arc < PaymentStore < K , Arc < FilesystemLogger > > > ,
203+ is_listening : Arc < AtomicBool > ,
204+ latest_wallet_sync_timestamp : Arc < RwLock < Option < u64 > > > ,
205+ latest_onchain_wallet_sync_timestamp : Arc < RwLock < Option < u64 > > > ,
206+ latest_fee_rate_cache_update_timestamp : Arc < RwLock < Option < u64 > > > ,
207+ latest_rgs_snapshot_timestamp : Arc < RwLock < Option < u64 > > > ,
208+ latest_node_announcement_broadcast_timestamp : Arc < RwLock < Option < u64 > > > ,
202209}
203210
204211impl < K : KVStore + Sync + Send + ' static > Node < K > {
@@ -222,6 +229,8 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
222229 // Block to ensure we update our fee rate cache once on startup
223230 let fee_estimator = Arc :: clone ( & self . fee_estimator ) ;
224231 let sync_logger = Arc :: clone ( & self . logger ) ;
232+ let sync_fee_rate_update_timestamp =
233+ Arc :: clone ( & self . latest_fee_rate_cache_update_timestamp ) ;
225234 let runtime_ref = & runtime;
226235 tokio:: task:: block_in_place ( move || {
227236 runtime_ref. block_on ( async move {
@@ -233,6 +242,9 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
233242 "Initial fee rate cache update finished in {}ms." ,
234243 now. elapsed( ) . as_millis( )
235244 ) ;
245+ let unix_time_secs_opt =
246+ SystemTime :: now ( ) . duration_since ( UNIX_EPOCH ) . ok ( ) . map ( |d| d. as_secs ( ) ) ;
247+ * sync_fee_rate_update_timestamp. write ( ) . unwrap ( ) = unix_time_secs_opt;
236248 Ok ( ( ) )
237249 } ,
238250 Err ( e) => {
@@ -246,6 +258,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
246258 // Setup wallet sync
247259 let wallet = Arc :: clone ( & self . wallet ) ;
248260 let sync_logger = Arc :: clone ( & self . logger ) ;
261+ let sync_onchain_wallet_timestamp = Arc :: clone ( & self . latest_onchain_wallet_sync_timestamp ) ;
249262 let mut stop_sync = self . stop_sender . subscribe ( ) ;
250263 let onchain_wallet_sync_interval_secs = self
251264 . config
@@ -267,11 +280,16 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
267280 _ = onchain_wallet_sync_interval. tick( ) => {
268281 let now = Instant :: now( ) ;
269282 match wallet. sync( ) . await {
270- Ok ( ( ) ) => log_trace!(
283+ Ok ( ( ) ) => {
284+ log_trace!(
271285 sync_logger,
272286 "Background sync of on-chain wallet finished in {}ms." ,
273287 now. elapsed( ) . as_millis( )
274- ) ,
288+ ) ;
289+ let unix_time_secs_opt =
290+ SystemTime :: now( ) . duration_since( UNIX_EPOCH ) . ok( ) . map( |d| d. as_secs( ) ) ;
291+ * sync_onchain_wallet_timestamp. write( ) . unwrap( ) = unix_time_secs_opt;
292+ }
275293 Err ( err) => {
276294 log_error!(
277295 sync_logger,
@@ -289,6 +307,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
289307
290308 let mut stop_fee_updates = self . stop_sender . subscribe ( ) ;
291309 let fee_update_logger = Arc :: clone ( & self . logger ) ;
310+ let fee_update_timestamp = Arc :: clone ( & self . latest_fee_rate_cache_update_timestamp ) ;
292311 let fee_estimator = Arc :: clone ( & self . fee_estimator ) ;
293312 let fee_rate_cache_update_interval_secs =
294313 self . config . fee_rate_cache_update_interval_secs . max ( WALLET_SYNC_INTERVAL_MINIMUM_SECS ) ;
@@ -307,11 +326,16 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
307326 _ = fee_rate_update_interval. tick( ) => {
308327 let now = Instant :: now( ) ;
309328 match fee_estimator. update_fee_estimates( ) . await {
310- Ok ( ( ) ) => log_trace!(
329+ Ok ( ( ) ) => {
330+ log_trace!(
311331 fee_update_logger,
312332 "Background update of fee rate cache finished in {}ms." ,
313333 now. elapsed( ) . as_millis( )
314- ) ,
334+ ) ;
335+ let unix_time_secs_opt =
336+ SystemTime :: now( ) . duration_since( UNIX_EPOCH ) . ok( ) . map( |d| d. as_secs( ) ) ;
337+ * fee_update_timestamp. write( ) . unwrap( ) = unix_time_secs_opt;
338+ }
315339 Err ( err) => {
316340 log_error!(
317341 fee_update_logger,
@@ -330,6 +354,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
330354 let sync_cmon = Arc :: clone ( & self . chain_monitor ) ;
331355 let sync_sweeper = Arc :: clone ( & self . output_sweeper ) ;
332356 let sync_logger = Arc :: clone ( & self . logger ) ;
357+ let sync_wallet_timestamp = Arc :: clone ( & self . latest_wallet_sync_timestamp ) ;
333358 let mut stop_sync = self . stop_sender . subscribe ( ) ;
334359 let wallet_sync_interval_secs =
335360 self . config . wallet_sync_interval_secs . max ( WALLET_SYNC_INTERVAL_MINIMUM_SECS ) ;
@@ -350,11 +375,16 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
350375 ] ;
351376 let now = Instant :: now( ) ;
352377 match tx_sync. sync( confirmables) . await {
353- Ok ( ( ) ) => log_trace!(
378+ Ok ( ( ) ) => {
379+ log_trace!(
354380 sync_logger,
355381 "Background sync of Lightning wallet finished in {}ms." ,
356382 now. elapsed( ) . as_millis( )
357- ) ,
383+ ) ;
384+ let unix_time_secs_opt =
385+ SystemTime :: now( ) . duration_since( UNIX_EPOCH ) . ok( ) . map( |d| d. as_secs( ) ) ;
386+ * sync_wallet_timestamp. write( ) . unwrap( ) = unix_time_secs_opt;
387+ }
358388 Err ( e) => {
359389 log_error!( sync_logger, "Background sync of Lightning wallet failed: {}" , e)
360390 }
@@ -368,6 +398,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
368398 let gossip_source = Arc :: clone ( & self . gossip_source ) ;
369399 let gossip_sync_store = Arc :: clone ( & self . kv_store ) ;
370400 let gossip_sync_logger = Arc :: clone ( & self . logger ) ;
401+ let gossip_rgs_sync_timestamp = Arc :: clone ( & self . latest_rgs_snapshot_timestamp ) ;
371402 let mut stop_gossip_sync = self . stop_sender . subscribe ( ) ;
372403 runtime. spawn ( async move {
373404 let mut interval = tokio:: time:: interval ( RGS_SYNC_INTERVAL ) ;
@@ -395,6 +426,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
395426 log_error!( gossip_sync_logger, "Persistence failed: {}" , e) ;
396427 panic!( "Persistence failed" ) ;
397428 } ) ;
429+ * gossip_rgs_sync_timestamp. write( ) . unwrap( ) = Some ( updated_timestamp as u64 ) ;
398430 }
399431 Err ( e) => log_error!(
400432 gossip_sync_logger,
@@ -413,6 +445,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
413445 let peer_manager_connection_handler = Arc :: clone ( & self . peer_manager ) ;
414446 let mut stop_listen = self . stop_sender . subscribe ( ) ;
415447 let listening_logger = Arc :: clone ( & self . logger ) ;
448+ let listening_indicator = Arc :: clone ( & self . is_listening ) ;
416449
417450 let mut bind_addrs = Vec :: with_capacity ( listening_addresses. len ( ) ) ;
418451
@@ -431,6 +464,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
431464 }
432465
433466 runtime. spawn ( async move {
467+ {
434468 let listener =
435469 tokio:: net:: TcpListener :: bind ( & * bind_addrs) . await
436470 . unwrap_or_else ( |e| {
@@ -440,11 +474,13 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
440474 ) ;
441475 } ) ;
442476
477+ listening_indicator. store ( true , Ordering :: Release ) ;
478+
443479 loop {
444480 let peer_mgr = Arc :: clone ( & peer_manager_connection_handler) ;
445481 tokio:: select! {
446482 _ = stop_listen. changed( ) => {
447- return ;
483+ break ;
448484 }
449485 res = listener. accept( ) => {
450486 let tcp_stream = res. unwrap( ) . 0 ;
@@ -458,6 +494,9 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
458494 }
459495 }
460496 }
497+ }
498+
499+ listening_indicator. store ( false , Ordering :: Release ) ;
461500 } ) ;
462501 }
463502
@@ -508,6 +547,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
508547 let bcast_config = Arc :: clone ( & self . config ) ;
509548 let bcast_store = Arc :: clone ( & self . kv_store ) ;
510549 let bcast_logger = Arc :: clone ( & self . logger ) ;
550+ let bcast_ann_timestamp = Arc :: clone ( & self . latest_node_announcement_broadcast_timestamp ) ;
511551 let mut stop_bcast = self . stop_sender . subscribe ( ) ;
512552 runtime. spawn ( async move {
513553 // We check every 30 secs whether our last broadcast is NODE_ANN_BCAST_INTERVAL away.
@@ -553,12 +593,17 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
553593
554594 bcast_pm. broadcast_node_announcement( [ 0 ; 3 ] , [ 0 ; 32 ] , addresses) ;
555595
556- let unix_time_secs = SystemTime :: now( ) . duration_since( SystemTime :: UNIX_EPOCH ) . unwrap( ) . as_secs( ) ;
557- io:: utils:: write_latest_node_ann_bcast_timestamp( unix_time_secs, Arc :: clone( & bcast_store) , Arc :: clone( & bcast_logger) )
558- . unwrap_or_else( |e| {
559- log_error!( bcast_logger, "Persistence failed: {}" , e) ;
560- panic!( "Persistence failed" ) ;
561- } ) ;
596+ let unix_time_secs_opt =
597+ SystemTime :: now( ) . duration_since( UNIX_EPOCH ) . ok( ) . map( |d| d. as_secs( ) ) ;
598+ * bcast_ann_timestamp. write( ) . unwrap( ) = unix_time_secs_opt;
599+
600+ if let Some ( unix_time_secs) = unix_time_secs_opt {
601+ io:: utils:: write_latest_node_ann_bcast_timestamp( unix_time_secs, Arc :: clone( & bcast_store) , Arc :: clone( & bcast_logger) )
602+ . unwrap_or_else( |e| {
603+ log_error!( bcast_logger, "Persistence failed: {}" , e) ;
604+ panic!( "Persistence failed" ) ;
605+ } ) ;
606+ }
562607 }
563608 }
564609 }
@@ -662,11 +707,6 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
662707 Ok ( ( ) )
663708 }
664709
665- /// Returns whether the [`Node`] is running.
666- pub fn is_running ( & self ) -> bool {
667- self . runtime . read ( ) . unwrap ( ) . is_some ( )
668- }
669-
670710 /// Disconnects all peers, stops all running background tasks, and shuts down [`Node`].
671711 ///
672712 /// After this returns most API methods will return [`Error::NotRunning`].
@@ -697,6 +737,37 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
697737 Ok ( ( ) )
698738 }
699739
740+ /// Returns the status of the [`Node`].
741+ pub fn status ( & self ) -> NodeStatus {
742+ let is_running = self . runtime . read ( ) . unwrap ( ) . is_some ( ) ;
743+ let is_listening = self . is_listening . load ( Ordering :: Acquire ) ;
744+ let current_best_block = self . channel_manager . current_best_block ( ) . into ( ) ;
745+ let latest_wallet_sync_timestamp = * self . latest_wallet_sync_timestamp . read ( ) . unwrap ( ) ;
746+ let latest_onchain_wallet_sync_timestamp =
747+ * self . latest_onchain_wallet_sync_timestamp . read ( ) . unwrap ( ) ;
748+ let latest_fee_rate_cache_update_timestamp =
749+ * self . latest_fee_rate_cache_update_timestamp . read ( ) . unwrap ( ) ;
750+ let latest_rgs_snapshot_timestamp = * self . latest_rgs_snapshot_timestamp . read ( ) . unwrap ( ) ;
751+ let latest_node_announcement_broadcast_timestamp =
752+ * self . latest_node_announcement_broadcast_timestamp . read ( ) . unwrap ( ) ;
753+
754+ NodeStatus {
755+ is_running,
756+ is_listening,
757+ current_best_block,
758+ latest_wallet_sync_timestamp,
759+ latest_onchain_wallet_sync_timestamp,
760+ latest_fee_rate_cache_update_timestamp,
761+ latest_rgs_snapshot_timestamp,
762+ latest_node_announcement_broadcast_timestamp,
763+ }
764+ }
765+
766+ /// Returns the config with which the [`Node`] was initialized.
767+ pub fn config ( & self ) -> Config {
768+ self . config . as_ref ( ) . clone ( )
769+ }
770+
700771 /// Returns the next event in the event queue, if currently available.
701772 ///
702773 /// Will return `Some(..)` if an event is available and `None` otherwise.
@@ -1746,6 +1817,43 @@ impl<K: KVStore + Sync + Send + 'static> Drop for Node<K> {
17461817 }
17471818}
17481819
1820+ /// Represents the status of the [`Node`].
1821+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
1822+ pub struct NodeStatus {
1823+ /// Indicates whether the [`Node`] is running.
1824+ pub is_running : bool ,
1825+ /// Indicates whether the [`Node`] is listening for incoming connections on the addresses
1826+ /// configured via [`Config::listening_addresses`].
1827+ pub is_listening : bool ,
1828+ /// The best block to which our Lightning wallet is currently synced.
1829+ pub current_best_block : BestBlock ,
1830+ /// The timestamp, in seconds since start of the UNIX epoch, when we last successfully synced
1831+ /// our Lightning wallet to the chain tip.
1832+ ///
1833+ /// Will be `None` if the wallet hasn't been synced since the [`Node`] was initialized.
1834+ pub latest_wallet_sync_timestamp : Option < u64 > ,
1835+ /// The timestamp, in seconds since start of the UNIX epoch, when we last successfully synced
1836+ /// our on-chain wallet to the chain tip.
1837+ ///
1838+ /// Will be `None` if the wallet hasn't been synced since the [`Node`] was initialized.
1839+ pub latest_onchain_wallet_sync_timestamp : Option < u64 > ,
1840+ /// The timestamp, in seconds since start of the UNIX epoch, when we last successfully update
1841+ /// our fee rate cache.
1842+ ///
1843+ /// Will be `None` if the cache hasn't been updated since the [`Node`] was initialized.
1844+ pub latest_fee_rate_cache_update_timestamp : Option < u64 > ,
1845+ /// The timestamp, in seconds since start of the UNIX epoch, when the last rapid gossip sync
1846+ /// (RGS) snapshot we successfully applied was generated.
1847+ ///
1848+ /// Will be `None` if RGS isn't configured or the snapshot hasn't been updated since the [`Node`] was initialized.
1849+ pub latest_rgs_snapshot_timestamp : Option < u64 > ,
1850+ /// The timestamp, in seconds since start of the UNIX epoch, when we last broadcasted a node
1851+ /// announcement.
1852+ ///
1853+ /// Will be `None` if we have no public channels or we haven't broadcasted since the [`Node`] was initialized.
1854+ pub latest_node_announcement_broadcast_timestamp : Option < u64 > ,
1855+ }
1856+
17491857async fn connect_peer_if_necessary < K : KVStore + Sync + Send + ' static > (
17501858 node_id : PublicKey , addr : SocketAddress , peer_manager : Arc < PeerManager < K > > ,
17511859 logger : Arc < FilesystemLogger > ,
0 commit comments