@@ -107,7 +107,7 @@ pub use error::Error as NodeError;
107
107
use error:: Error ;
108
108
109
109
pub use event:: Event ;
110
- pub use types:: ChannelConfig ;
110
+ pub use types:: { BestBlock , ChannelConfig } ;
111
111
112
112
pub use io:: utils:: generate_entropy_mnemonic;
113
113
@@ -167,8 +167,9 @@ use rand::Rng;
167
167
168
168
use std:: default:: Default ;
169
169
use std:: net:: ToSocketAddrs ;
170
+ use std:: sync:: atomic:: { AtomicBool , Ordering } ;
170
171
use std:: sync:: { Arc , Mutex , RwLock } ;
171
- use std:: time:: { Duration , Instant , SystemTime } ;
172
+ use std:: time:: { Duration , Instant , SystemTime , UNIX_EPOCH } ;
172
173
173
174
#[ cfg( feature = "uniffi" ) ]
174
175
uniffi:: include_scaffolding!( "ldk_node" ) ;
@@ -199,6 +200,12 @@ pub struct Node<K: KVStore + Sync + Send + 'static> {
199
200
scorer : Arc < Mutex < Scorer > > ,
200
201
peer_store : Arc < PeerStore < K , Arc < FilesystemLogger > > > ,
201
202
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 > > > ,
202
209
}
203
210
204
211
impl < K : KVStore + Sync + Send + ' static > Node < K > {
@@ -222,6 +229,8 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
222
229
// Block to ensure we update our fee rate cache once on startup
223
230
let fee_estimator = Arc :: clone ( & self . fee_estimator ) ;
224
231
let sync_logger = Arc :: clone ( & self . logger ) ;
232
+ let sync_fee_rate_update_timestamp =
233
+ Arc :: clone ( & self . latest_fee_rate_cache_update_timestamp ) ;
225
234
let runtime_ref = & runtime;
226
235
tokio:: task:: block_in_place ( move || {
227
236
runtime_ref. block_on ( async move {
@@ -233,6 +242,9 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
233
242
"Initial fee rate cache update finished in {}ms." ,
234
243
now. elapsed( ) . as_millis( )
235
244
) ;
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;
236
248
Ok ( ( ) )
237
249
} ,
238
250
Err ( e) => {
@@ -246,6 +258,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
246
258
// Setup wallet sync
247
259
let wallet = Arc :: clone ( & self . wallet ) ;
248
260
let sync_logger = Arc :: clone ( & self . logger ) ;
261
+ let sync_onchain_wallet_timestamp = Arc :: clone ( & self . latest_onchain_wallet_sync_timestamp ) ;
249
262
let mut stop_sync = self . stop_sender . subscribe ( ) ;
250
263
let onchain_wallet_sync_interval_secs = self
251
264
. config
@@ -267,11 +280,16 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
267
280
_ = onchain_wallet_sync_interval. tick( ) => {
268
281
let now = Instant :: now( ) ;
269
282
match wallet. sync( ) . await {
270
- Ok ( ( ) ) => log_trace!(
283
+ Ok ( ( ) ) => {
284
+ log_trace!(
271
285
sync_logger,
272
286
"Background sync of on-chain wallet finished in {}ms." ,
273
287
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
+ }
275
293
Err ( err) => {
276
294
log_error!(
277
295
sync_logger,
@@ -289,6 +307,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
289
307
290
308
let mut stop_fee_updates = self . stop_sender . subscribe ( ) ;
291
309
let fee_update_logger = Arc :: clone ( & self . logger ) ;
310
+ let fee_update_timestamp = Arc :: clone ( & self . latest_fee_rate_cache_update_timestamp ) ;
292
311
let fee_estimator = Arc :: clone ( & self . fee_estimator ) ;
293
312
let fee_rate_cache_update_interval_secs =
294
313
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> {
307
326
_ = fee_rate_update_interval. tick( ) => {
308
327
let now = Instant :: now( ) ;
309
328
match fee_estimator. update_fee_estimates( ) . await {
310
- Ok ( ( ) ) => log_trace!(
329
+ Ok ( ( ) ) => {
330
+ log_trace!(
311
331
fee_update_logger,
312
332
"Background update of fee rate cache finished in {}ms." ,
313
333
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
+ }
315
339
Err ( err) => {
316
340
log_error!(
317
341
fee_update_logger,
@@ -330,6 +354,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
330
354
let sync_cmon = Arc :: clone ( & self . chain_monitor ) ;
331
355
let sync_sweeper = Arc :: clone ( & self . output_sweeper ) ;
332
356
let sync_logger = Arc :: clone ( & self . logger ) ;
357
+ let sync_wallet_timestamp = Arc :: clone ( & self . latest_wallet_sync_timestamp ) ;
333
358
let mut stop_sync = self . stop_sender . subscribe ( ) ;
334
359
let wallet_sync_interval_secs =
335
360
self . config . wallet_sync_interval_secs . max ( WALLET_SYNC_INTERVAL_MINIMUM_SECS ) ;
@@ -350,11 +375,16 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
350
375
] ;
351
376
let now = Instant :: now( ) ;
352
377
match tx_sync. sync( confirmables) . await {
353
- Ok ( ( ) ) => log_trace!(
378
+ Ok ( ( ) ) => {
379
+ log_trace!(
354
380
sync_logger,
355
381
"Background sync of Lightning wallet finished in {}ms." ,
356
382
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
+ }
358
388
Err ( e) => {
359
389
log_error!( sync_logger, "Background sync of Lightning wallet failed: {}" , e)
360
390
}
@@ -368,6 +398,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
368
398
let gossip_source = Arc :: clone ( & self . gossip_source ) ;
369
399
let gossip_sync_store = Arc :: clone ( & self . kv_store ) ;
370
400
let gossip_sync_logger = Arc :: clone ( & self . logger ) ;
401
+ let gossip_rgs_sync_timestamp = Arc :: clone ( & self . latest_rgs_snapshot_timestamp ) ;
371
402
let mut stop_gossip_sync = self . stop_sender . subscribe ( ) ;
372
403
runtime. spawn ( async move {
373
404
let mut interval = tokio:: time:: interval ( RGS_SYNC_INTERVAL ) ;
@@ -395,6 +426,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
395
426
log_error!( gossip_sync_logger, "Persistence failed: {}" , e) ;
396
427
panic!( "Persistence failed" ) ;
397
428
} ) ;
429
+ * gossip_rgs_sync_timestamp. write( ) . unwrap( ) = Some ( updated_timestamp as u64 ) ;
398
430
}
399
431
Err ( e) => log_error!(
400
432
gossip_sync_logger,
@@ -413,6 +445,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
413
445
let peer_manager_connection_handler = Arc :: clone ( & self . peer_manager ) ;
414
446
let mut stop_listen = self . stop_sender . subscribe ( ) ;
415
447
let listening_logger = Arc :: clone ( & self . logger ) ;
448
+ let listening_indicator = Arc :: clone ( & self . is_listening ) ;
416
449
417
450
let mut bind_addrs = Vec :: with_capacity ( listening_addresses. len ( ) ) ;
418
451
@@ -431,6 +464,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
431
464
}
432
465
433
466
runtime. spawn ( async move {
467
+ {
434
468
let listener =
435
469
tokio:: net:: TcpListener :: bind ( & * bind_addrs) . await
436
470
. unwrap_or_else ( |e| {
@@ -440,11 +474,13 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
440
474
) ;
441
475
} ) ;
442
476
477
+ listening_indicator. store ( true , Ordering :: Release ) ;
478
+
443
479
loop {
444
480
let peer_mgr = Arc :: clone ( & peer_manager_connection_handler) ;
445
481
tokio:: select! {
446
482
_ = stop_listen. changed( ) => {
447
- return ;
483
+ break ;
448
484
}
449
485
res = listener. accept( ) => {
450
486
let tcp_stream = res. unwrap( ) . 0 ;
@@ -458,6 +494,9 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
458
494
}
459
495
}
460
496
}
497
+ }
498
+
499
+ listening_indicator. store ( false , Ordering :: Release ) ;
461
500
} ) ;
462
501
}
463
502
@@ -508,6 +547,7 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
508
547
let bcast_config = Arc :: clone ( & self . config ) ;
509
548
let bcast_store = Arc :: clone ( & self . kv_store ) ;
510
549
let bcast_logger = Arc :: clone ( & self . logger ) ;
550
+ let bcast_ann_timestamp = Arc :: clone ( & self . latest_node_announcement_broadcast_timestamp ) ;
511
551
let mut stop_bcast = self . stop_sender . subscribe ( ) ;
512
552
runtime. spawn ( async move {
513
553
// 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> {
553
593
554
594
bcast_pm. broadcast_node_announcement( [ 0 ; 3 ] , [ 0 ; 32 ] , addresses) ;
555
595
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
+ }
562
607
}
563
608
}
564
609
}
@@ -662,11 +707,6 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
662
707
Ok ( ( ) )
663
708
}
664
709
665
- /// Returns whether the [`Node`] is running.
666
- pub fn is_running ( & self ) -> bool {
667
- self . runtime . read ( ) . unwrap ( ) . is_some ( )
668
- }
669
-
670
710
/// Disconnects all peers, stops all running background tasks, and shuts down [`Node`].
671
711
///
672
712
/// After this returns most API methods will return [`Error::NotRunning`].
@@ -697,6 +737,37 @@ impl<K: KVStore + Sync + Send + 'static> Node<K> {
697
737
Ok ( ( ) )
698
738
}
699
739
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
+
700
771
/// Returns the next event in the event queue, if currently available.
701
772
///
702
773
/// 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> {
1746
1817
}
1747
1818
}
1748
1819
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
+
1749
1857
async fn connect_peer_if_necessary < K : KVStore + Sync + Send + ' static > (
1750
1858
node_id : PublicKey , addr : SocketAddress , peer_manager : Arc < PeerManager < K > > ,
1751
1859
logger : Arc < FilesystemLogger > ,
0 commit comments