@@ -57,6 +57,7 @@ use std::ops::Deref;
57
57
pub struct BackgroundProcessor {
58
58
stop_thread : Arc < AtomicBool > ,
59
59
thread_handle : Option < JoinHandle < Result < ( ) , std:: io:: Error > > > ,
60
+ is_awaiting_graph_sync_completion : Arc < AtomicBool >
60
61
}
61
62
62
63
#[ cfg( not( test) ) ]
@@ -151,6 +152,12 @@ impl BackgroundProcessor {
151
152
/// [`Persister::persist_graph`]: lightning::util::persist::Persister::persist_graph
152
153
/// [`NetworkGraph`]: lightning::routing::network_graph::NetworkGraph
153
154
/// [`NetworkGraph::write`]: lightning::routing::network_graph::NetworkGraph#impl-Writeable
155
+ ///
156
+ /// # Graph Sync
157
+ ///
158
+ /// If a rapid graph sync is meant to run at startup, set `await_graph_sync_completion` to true
159
+ /// to indicate to [`BackgroundProcessor`] not to prune the [`NetworkGraph`] instance until
160
+ /// [`graph_sync_complete`] is called.
154
161
pub fn start <
155
162
' a ,
156
163
Signer : ' static + Sign ,
@@ -177,7 +184,7 @@ impl BackgroundProcessor {
177
184
SC : WriteableScore < ' a > ,
178
185
> (
179
186
persister : PS , event_handler : EH , chain_monitor : M , channel_manager : CM ,
180
- net_graph_msg_handler : Option < NG > , peer_manager : PM , logger : L , scorer : Option < S >
187
+ net_graph_msg_handler : Option < NG > , peer_manager : PM , await_graph_sync_completion : bool , logger : L , scorer : Option < S >
181
188
) -> Self
182
189
where
183
190
CA :: Target : ' static + chain:: Access ,
@@ -195,6 +202,8 @@ impl BackgroundProcessor {
195
202
{
196
203
let stop_thread = Arc :: new ( AtomicBool :: new ( false ) ) ;
197
204
let stop_thread_clone = stop_thread. clone ( ) ;
205
+ let is_awaiting_graph_sync_completion = Arc :: new ( AtomicBool :: new ( await_graph_sync_completion) ) ;
206
+ let is_awaiting_graph_sync_completion_clone = is_awaiting_graph_sync_completion. clone ( ) ;
198
207
let handle = thread:: spawn ( move || -> Result < ( ) , std:: io:: Error > {
199
208
let event_handler = DecoratingEventHandler { event_handler, net_graph_msg_handler : net_graph_msg_handler. as_ref ( ) . map ( |t| t. deref ( ) ) } ;
200
209
@@ -273,6 +282,13 @@ impl BackgroundProcessor {
273
282
// continuing our normal cadence.
274
283
if last_prune_call. elapsed ( ) . as_secs ( ) > if have_pruned { NETWORK_PRUNE_TIMER } else { FIRST_NETWORK_PRUNE_TIMER } {
275
284
if let Some ( ref handler) = net_graph_msg_handler {
285
+ log_trace ! ( logger, "Assessing prunability of network graph" ) ;
286
+ // The network graph must not be pruned while graph sync completion is pending
287
+ let is_currently_awaiting_graph_sync = is_awaiting_graph_sync_completion_clone. load ( Ordering :: Acquire ) ;
288
+ if is_currently_awaiting_graph_sync {
289
+ log_trace ! ( logger, "Not pruning network graph due to pending graph sync" ) ;
290
+ continue ;
291
+ }
276
292
log_trace ! ( logger, "Pruning network graph of stale entries" ) ;
277
293
handler. network_graph ( ) . remove_stale_channels ( ) ;
278
294
if let Err ( e) = persister. persist_graph ( handler. network_graph ( ) ) {
@@ -308,7 +324,7 @@ impl BackgroundProcessor {
308
324
309
325
Ok ( ( ) )
310
326
} ) ;
311
- Self { stop_thread : stop_thread_clone, thread_handle : Some ( handle) }
327
+ Self { stop_thread : stop_thread_clone, thread_handle : Some ( handle) , is_awaiting_graph_sync_completion }
312
328
}
313
329
314
330
/// Join `BackgroundProcessor`'s thread, returning any error that occurred while persisting
@@ -339,6 +355,14 @@ impl BackgroundProcessor {
339
355
self . stop_and_join_thread ( )
340
356
}
341
357
358
+ /// Signal to [`BackgroundProcessor`] that the initial rapid graph sync has completed.
359
+ ///
360
+ /// This function can only be called usefully once, so there is an implicit understanding
361
+ /// that running graph sync multiple times after startup is API misuse.
362
+ pub fn graph_sync_complete ( & self ) {
363
+ self . is_awaiting_graph_sync_completion . store ( false , Ordering :: Release )
364
+ }
365
+
342
366
fn stop_and_join_thread ( & mut self ) -> Result < ( ) , std:: io:: Error > {
343
367
self . stop_thread . store ( true , Ordering :: Release ) ;
344
368
self . join_thread ( )
@@ -370,7 +394,7 @@ mod tests {
370
394
use lightning:: chain:: transaction:: OutPoint ;
371
395
use lightning:: get_event_msg;
372
396
use lightning:: ln:: channelmanager:: { BREAKDOWN_TIMEOUT , ChainParameters , ChannelManager , SimpleArcChannelManager } ;
373
- use lightning:: ln:: features:: InitFeatures ;
397
+ use lightning:: ln:: features:: { ChannelFeatures , InitFeatures } ;
374
398
use lightning:: ln:: msgs:: { ChannelMessageHandler , Init } ;
375
399
use lightning:: ln:: peer_handler:: { PeerManager , MessageHandler , SocketDescriptor , IgnoringMessageHandler } ;
376
400
use lightning:: routing:: network_graph:: { NetworkGraph , NetGraphMsgHandler } ;
@@ -385,6 +409,7 @@ mod tests {
385
409
use std:: fs;
386
410
use std:: path:: PathBuf ;
387
411
use std:: sync:: { Arc , Mutex } ;
412
+ use std:: sync:: mpsc:: SyncSender ;
388
413
use std:: time:: Duration ;
389
414
use lightning:: routing:: scoring:: { FixedPenaltyScorer } ;
390
415
use super :: { BackgroundProcessor , FRESHNESS_TIMER } ;
@@ -428,6 +453,7 @@ mod tests {
428
453
429
454
struct Persister {
430
455
graph_error : Option < ( std:: io:: ErrorKind , & ' static str ) > ,
456
+ graph_persistence_notifier : Option < SyncSender < ( ) > > ,
431
457
manager_error : Option < ( std:: io:: ErrorKind , & ' static str ) > ,
432
458
scorer_error : Option < ( std:: io:: ErrorKind , & ' static str ) > ,
433
459
filesystem_persister : FilesystemPersister ,
@@ -436,13 +462,17 @@ mod tests {
436
462
impl Persister {
437
463
fn new ( data_dir : String ) -> Self {
438
464
let filesystem_persister = FilesystemPersister :: new ( data_dir. clone ( ) ) ;
439
- Self { graph_error : None , manager_error : None , scorer_error : None , filesystem_persister }
465
+ Self { graph_error : None , graph_persistence_notifier : None , manager_error : None , scorer_error : None , filesystem_persister }
440
466
}
441
467
442
468
fn with_graph_error ( self , error : std:: io:: ErrorKind , message : & ' static str ) -> Self {
443
469
Self { graph_error : Some ( ( error, message) ) , ..self }
444
470
}
445
471
472
+ fn with_graph_persistence_notifier ( self , sender : SyncSender < ( ) > ) -> Self {
473
+ Self { graph_persistence_notifier : Some ( sender) , ..self }
474
+ }
475
+
446
476
fn with_manager_error ( self , error : std:: io:: ErrorKind , message : & ' static str ) -> Self {
447
477
Self { manager_error : Some ( ( error, message) ) , ..self }
448
478
}
@@ -461,6 +491,10 @@ mod tests {
461
491
}
462
492
463
493
if key == "network_graph" {
494
+ if let Some ( sender) = & self . graph_persistence_notifier {
495
+ sender. send ( ( ) ) . unwrap ( ) ;
496
+ } ;
497
+
464
498
if let Some ( ( error, message) ) = self . graph_error {
465
499
return Err ( std:: io:: Error :: new ( error, message) )
466
500
}
@@ -602,7 +636,7 @@ mod tests {
602
636
let data_dir = nodes[ 0 ] . persister . get_data_dir ( ) ;
603
637
let persister = Arc :: new ( Persister :: new ( data_dir) ) ;
604
638
let event_handler = |_: & _ | { } ;
605
- let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
639
+ let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , false , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
606
640
607
641
macro_rules! check_persisted_data {
608
642
( $node: expr, $filepath: expr) => {
@@ -667,7 +701,7 @@ mod tests {
667
701
let data_dir = nodes[ 0 ] . persister . get_data_dir ( ) ;
668
702
let persister = Arc :: new ( Persister :: new ( data_dir) ) ;
669
703
let event_handler = |_: & _ | { } ;
670
- let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
704
+ let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , false , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
671
705
loop {
672
706
let log_entries = nodes[ 0 ] . logger . lines . lock ( ) . unwrap ( ) ;
673
707
let desired_log = "Calling ChannelManager's timer_tick_occurred" . to_string ( ) ;
@@ -690,7 +724,7 @@ mod tests {
690
724
let data_dir = nodes[ 0 ] . persister . get_data_dir ( ) ;
691
725
let persister = Arc :: new ( Persister :: new ( data_dir) . with_manager_error ( std:: io:: ErrorKind :: Other , "test" ) ) ;
692
726
let event_handler = |_: & _ | { } ;
693
- let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
727
+ let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , false , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
694
728
match bg_processor. join ( ) {
695
729
Ok ( _) => panic ! ( "Expected error persisting manager" ) ,
696
730
Err ( e) => {
@@ -707,7 +741,7 @@ mod tests {
707
741
let data_dir = nodes[ 0 ] . persister . get_data_dir ( ) ;
708
742
let persister = Arc :: new ( Persister :: new ( data_dir) . with_graph_error ( std:: io:: ErrorKind :: Other , "test" ) ) ;
709
743
let event_handler = |_: & _ | { } ;
710
- let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
744
+ let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , false , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
711
745
712
746
match bg_processor. stop ( ) {
713
747
Ok ( _) => panic ! ( "Expected error persisting network graph" ) ,
@@ -725,7 +759,7 @@ mod tests {
725
759
let data_dir = nodes[ 0 ] . persister . get_data_dir ( ) ;
726
760
let persister = Arc :: new ( Persister :: new ( data_dir) . with_scorer_error ( std:: io:: ErrorKind :: Other , "test" ) ) ;
727
761
let event_handler = |_: & _ | { } ;
728
- let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
762
+ let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , false , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
729
763
730
764
match bg_processor. stop ( ) {
731
765
Ok ( _) => panic ! ( "Expected error persisting scorer" ) ,
@@ -748,7 +782,7 @@ mod tests {
748
782
let event_handler = move |event : & Event | {
749
783
sender. send ( handle_funding_generation_ready ! ( event, channel_value) ) . unwrap ( ) ;
750
784
} ;
751
- let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
785
+ let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , false , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
752
786
753
787
// Open a channel and check that the FundingGenerationReady event was handled.
754
788
begin_open_channel ! ( nodes[ 0 ] , nodes[ 1 ] , channel_value) ;
@@ -773,7 +807,7 @@ mod tests {
773
807
let ( sender, receiver) = std:: sync:: mpsc:: sync_channel ( 1 ) ;
774
808
let event_handler = move |event : & Event | sender. send ( event. clone ( ) ) . unwrap ( ) ;
775
809
let persister = Arc :: new ( Persister :: new ( data_dir) ) ;
776
- let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
810
+ let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , false , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
777
811
778
812
// Force close the channel and check that the SpendableOutputs event was handled.
779
813
nodes[ 0 ] . node . force_close_channel ( & nodes[ 0 ] . node . list_channels ( ) [ 0 ] . channel_id , & nodes[ 1 ] . node . get_our_node_id ( ) ) . unwrap ( ) ;
@@ -791,6 +825,44 @@ mod tests {
791
825
assert ! ( bg_processor. stop( ) . is_ok( ) ) ;
792
826
}
793
827
828
+ #[ test]
829
+ fn test_not_pruning_network_graph_until_graph_sync_completion ( ) {
830
+ let nodes = create_nodes ( 2 , "test_not_pruning_network_graph_until_graph_sync_completion" . to_string ( ) ) ;
831
+ let data_dir = nodes[ 0 ] . persister . get_data_dir ( ) ;
832
+ let ( sender, receiver) = std:: sync:: mpsc:: sync_channel ( 1 ) ;
833
+ let persister = Arc :: new ( Persister :: new ( data_dir. clone ( ) ) . with_graph_persistence_notifier ( sender) ) ;
834
+ let network_graph = nodes[ 0 ] . network_graph . clone ( ) ;
835
+ let features = ChannelFeatures :: empty ( ) ;
836
+ network_graph. add_channel_from_partial_announcement ( 42 , 53 , features, nodes[ 0 ] . node . get_our_node_id ( ) , nodes[ 1 ] . node . get_our_node_id ( ) )
837
+ . expect ( "Failed to update channel from partial announcement" ) ;
838
+ let original_graph_description = network_graph. to_string ( ) ;
839
+ assert ! ( original_graph_description. contains( "42: features: 0000, node_one:" ) ) ;
840
+
841
+ let event_handler = |_: & _ | { } ;
842
+ let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , true , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
843
+
844
+ loop {
845
+ let log_entries = nodes[ 0 ] . logger . lines . lock ( ) . unwrap ( ) ;
846
+ let expected_log_a = "Assessing prunability of network graph" . to_string ( ) ;
847
+ let expected_log_b = "Not pruning network graph due to pending graph sync" . to_string ( ) ;
848
+ if log_entries. get ( & ( "lightning_background_processor" . to_string ( ) , expected_log_a) ) . is_some ( ) &&
849
+ log_entries. get ( & ( "lightning_background_processor" . to_string ( ) , expected_log_b) ) . is_some ( ) {
850
+ break
851
+ }
852
+ }
853
+
854
+ bg_processor. graph_sync_complete ( ) ;
855
+
856
+ let _ = receiver
857
+ . recv_timeout ( Duration :: from_secs ( super :: FIRST_NETWORK_PRUNE_TIMER * 2 ) )
858
+ . expect ( "Network graph not pruned within deadline" ) ;
859
+ let current_graph_description = network_graph. to_string ( ) ;
860
+ assert_ne ! ( current_graph_description, original_graph_description) ;
861
+ assert_eq ! ( current_graph_description. len( ) , 31 ) ;
862
+ assert ! ( !current_graph_description. contains( "node_one:" ) ) ;
863
+ assert ! ( !current_graph_description. contains( "node_two:" ) ) ;
864
+ }
865
+
794
866
#[ test]
795
867
fn test_invoice_payer ( ) {
796
868
let keys_manager = test_utils:: TestKeysInterface :: new ( & [ 0u8 ; 32 ] , Network :: Testnet ) ;
@@ -803,7 +875,7 @@ mod tests {
803
875
let router = DefaultRouter :: new ( Arc :: clone ( & nodes[ 0 ] . network_graph ) , Arc :: clone ( & nodes[ 0 ] . logger ) , random_seed_bytes) ;
804
876
let invoice_payer = Arc :: new ( InvoicePayer :: new ( Arc :: clone ( & nodes[ 0 ] . node ) , router, Arc :: clone ( & nodes[ 0 ] . scorer ) , Arc :: clone ( & nodes[ 0 ] . logger ) , |_: & _ | { } , Retry :: Attempts ( 2 ) ) ) ;
805
877
let event_handler = Arc :: clone ( & invoice_payer) ;
806
- let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
878
+ let bg_processor = BackgroundProcessor :: start ( persister, event_handler, nodes[ 0 ] . chain_monitor . clone ( ) , nodes[ 0 ] . node . clone ( ) , nodes[ 0 ] . net_graph_msg_handler . clone ( ) , nodes[ 0 ] . peer_manager . clone ( ) , false , nodes[ 0 ] . logger . clone ( ) , Some ( nodes[ 0 ] . scorer . clone ( ) ) ) ;
807
879
assert ! ( bg_processor. stop( ) . is_ok( ) ) ;
808
880
}
809
881
}
0 commit comments