@@ -356,7 +356,9 @@ mod test {
356
356
use lightning:: util:: enforcing_trait_impls:: EnforcingSigner ;
357
357
use lightning:: util:: events:: { MessageSendEvent , MessageSendEventsProvider , Event } ;
358
358
use lightning:: util:: test_utils;
359
+ use lightning:: util:: config:: UserConfig ;
359
360
use utils:: create_invoice_from_channelmanager_and_duration_since_epoch;
361
+ use std:: collections:: HashSet ;
360
362
361
363
#[ test]
362
364
fn test_from_channelmanager ( ) {
@@ -411,6 +413,148 @@ mod test {
411
413
assert_eq ! ( events. len( ) , 2 ) ;
412
414
}
413
415
416
+ #[ test]
417
+ fn test_hints_includes_single_public_channels_to_nodes ( ) {
418
+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
419
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
420
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
421
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
422
+ let chan_1_0 = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 0 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
423
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_1_0. 0 ) ;
424
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_1_0. 1 ) ;
425
+ let chan_2_0 = create_announced_chan_between_nodes_with_value ( & nodes, 2 , 0 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
426
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 2 ] . node . get_our_node_id ( ) , & chan_2_0. 0 ) ;
427
+ nodes[ 2 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_2_0. 1 ) ;
428
+
429
+ let mut short_chan_ids = HashSet :: new ( ) ;
430
+ short_chan_ids. insert ( chan_1_0. 0 . contents . short_channel_id . clone ( ) ) ;
431
+ short_chan_ids. insert ( chan_2_0. 0 . contents . short_channel_id . clone ( ) ) ;
432
+
433
+ match_invoice_routes (
434
+ Some ( 5000 ) ,
435
+ & nodes[ 0 ] ,
436
+ short_chan_ids. clone ( ) ,
437
+ ) ;
438
+ }
439
+
440
+ #[ test]
441
+ fn test_hints_has_only_highest_inbound_capacity_channel ( ) {
442
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
443
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
444
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
445
+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
446
+ let chan_1_0_low_inbound_capacity = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 0 , 100_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
447
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_1_0_low_inbound_capacity. 0 ) ;
448
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_1_0_low_inbound_capacity. 1 ) ;
449
+ let chan_1_0_high_inbound_capacity = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 0 , 10_000_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
450
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_1_0_high_inbound_capacity. 0 ) ;
451
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_1_0_high_inbound_capacity. 1 ) ;
452
+ let chan_1_0_medium_inbound_capacity = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 0 , 1_000_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
453
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_1_0_medium_inbound_capacity. 0 ) ;
454
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_1_0_medium_inbound_capacity. 1 ) ;
455
+
456
+ let mut short_chan_ids = HashSet :: new ( ) ;
457
+ short_chan_ids. insert ( chan_1_0_high_inbound_capacity. 0 . contents . short_channel_id . clone ( ) ) ;
458
+
459
+ match_invoice_routes (
460
+ Some ( 5000 ) ,
461
+ & nodes[ 0 ] ,
462
+ short_chan_ids. clone ( ) ,
463
+ ) ;
464
+ }
465
+
466
+ #[ test]
467
+ fn test_no_hints_if_any_private_channels_exists ( ) {
468
+ let mut nodes_2_priv_channels_conf = UserConfig :: default ( ) ;
469
+ nodes_2_priv_channels_conf. channel_options . announced_channel = false ;
470
+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
471
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
472
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , Some ( nodes_2_priv_channels_conf) ] ) ;
473
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
474
+ let chan_1_0 = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 0 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
475
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_1_0. 0 ) ;
476
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_1_0. 1 ) ;
477
+
478
+ let chan_2_0 = create_private_chan_between_nodes_with_value ( & nodes, 2 , 0 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
479
+ nodes[ 2 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_2_0. 1 ) ;
480
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 2 ] . node . get_our_node_id ( ) , & chan_2_0. 0 ) ;
481
+
482
+ // Ensure that the invoice doesn't include any route hints for any of `nodes[0]` channels,
483
+ // even though all channels between `nodes[1]` and `nodes[0]` are public, as there is a
484
+ // private channel between `nodes[2]` and `nodes[0]`
485
+ let invoice = create_invoice_from_channelmanager_and_duration_since_epoch (
486
+ & nodes[ 0 ] . node , nodes[ 0 ] . keys_manager , Currency :: BitcoinTestnet , Some ( 5000 ) , "test" . to_string ( ) ,
487
+ Duration :: from_secs ( 1234567 ) ) . unwrap ( ) ;
488
+ let hints = invoice. private_routes ( ) ;
489
+
490
+ assert ! ( hints. is_empty( ) ) ;
491
+ }
492
+
493
+ #[ test]
494
+ fn test_hints_has_no_channels_with_lower_inbound_capacity_than_invoice_amt ( ) {
495
+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
496
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
497
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
498
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
499
+ let chan_1_0 = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 0 , 100_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
500
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_1_0. 0 ) ;
501
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_1_0. 1 ) ;
502
+ let chan_2_0 = create_announced_chan_between_nodes_with_value ( & nodes, 2 , 0 , 1_000_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
503
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 2 ] . node . get_our_node_id ( ) , & chan_2_0. 0 ) ;
504
+ nodes[ 2 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_2_0. 1 ) ;
505
+
506
+ // 1 msat above chan_1_0's inbound capacity
507
+ let mut short_chan_ids_99_000_001_msat = HashSet :: new ( ) ;
508
+ short_chan_ids_99_000_001_msat. insert ( chan_2_0. 0 . contents . short_channel_id . clone ( ) ) ;
509
+
510
+ match_invoice_routes (
511
+ Some ( 99_000_001 ) ,
512
+ & nodes[ 0 ] ,
513
+ short_chan_ids_99_000_001_msat. clone ( ) ,
514
+ ) ;
515
+
516
+ // Exactly at chan_1_0's inbound capacity
517
+ let mut short_chan_ids_99_000_000_msat = HashSet :: new ( ) ;
518
+ short_chan_ids_99_000_000_msat. insert ( chan_1_0. 0 . contents . short_channel_id . clone ( ) ) ;
519
+ short_chan_ids_99_000_000_msat. insert ( chan_2_0. 0 . contents . short_channel_id . clone ( ) ) ;
520
+
521
+ match_invoice_routes (
522
+ Some ( 99_000_000 ) ,
523
+ & nodes[ 0 ] ,
524
+ short_chan_ids_99_000_000_msat. clone ( ) ,
525
+ ) ;
526
+
527
+ // An invoice with no specified amount should include all route hints.
528
+ let mut short_chan_ids_no_specified_amount = HashSet :: new ( ) ;
529
+ short_chan_ids_no_specified_amount. insert ( chan_1_0. 0 . contents . short_channel_id . clone ( ) ) ;
530
+ short_chan_ids_no_specified_amount. insert ( chan_2_0. 0 . contents . short_channel_id . clone ( ) ) ;
531
+
532
+ match_invoice_routes (
533
+ None ,
534
+ & nodes[ 0 ] ,
535
+ short_chan_ids_no_specified_amount. clone ( ) ,
536
+ ) ;
537
+ }
538
+
539
+ fn match_invoice_routes < ' a , ' b : ' a , ' c : ' b > (
540
+ invoice_amt : Option < u64 > ,
541
+ invoice_node : & Node < ' a , ' b , ' c > ,
542
+ mut chan_ids_to_match : HashSet < u64 >
543
+ ) {
544
+ let invoice = create_invoice_from_channelmanager_and_duration_since_epoch (
545
+ & invoice_node. node , invoice_node. keys_manager , Currency :: BitcoinTestnet , invoice_amt, "test" . to_string ( ) ,
546
+ Duration :: from_secs ( 1234567 ) ) . unwrap ( ) ;
547
+ let hints = invoice. private_routes ( ) ;
548
+
549
+ assert_eq ! ( hints. len( ) , chan_ids_to_match. len( ) ) ;
550
+
551
+ for hint in hints {
552
+ let hint_short_chan_id = ( hint. 0 ) . 0 [ 0 ] . short_channel_id ;
553
+ assert ! ( chan_ids_to_match. contains( & hint_short_chan_id) ) ;
554
+ chan_ids_to_match. remove ( & hint_short_chan_id) ;
555
+ }
556
+ }
557
+
414
558
#[ test]
415
559
#[ cfg( feature = "std" ) ]
416
560
fn test_multi_node_receive ( ) {
0 commit comments