@@ -368,7 +368,9 @@ mod test {
368
368
use lightning:: util:: enforcing_trait_impls:: EnforcingSigner ;
369
369
use lightning:: util:: events:: { MessageSendEvent , MessageSendEventsProvider , Event } ;
370
370
use lightning:: util:: test_utils;
371
+ use lightning:: util:: config:: UserConfig ;
371
372
use utils:: create_invoice_from_channelmanager_and_duration_since_epoch;
373
+ use std:: collections:: HashSet ;
372
374
373
375
#[ test]
374
376
fn test_from_channelmanager ( ) {
@@ -423,6 +425,171 @@ mod test {
423
425
assert_eq ! ( events. len( ) , 2 ) ;
424
426
}
425
427
428
+ #[ test]
429
+ fn test_hints_includes_single_public_channels_to_nodes ( ) {
430
+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
431
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
432
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
433
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
434
+ let chan_1_0 = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 0 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
435
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_1_0. 0 ) ;
436
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_1_0. 1 ) ;
437
+ let chan_2_0 = create_announced_chan_between_nodes_with_value ( & nodes, 2 , 0 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
438
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 2 ] . node . get_our_node_id ( ) , & chan_2_0. 0 ) ;
439
+ nodes[ 2 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_2_0. 1 ) ;
440
+
441
+ let mut short_chan_ids = HashSet :: new ( ) ;
442
+ short_chan_ids. insert ( chan_1_0. 0 . contents . short_channel_id . clone ( ) ) ;
443
+ short_chan_ids. insert ( chan_2_0. 0 . contents . short_channel_id . clone ( ) ) ;
444
+
445
+ match_invoice_routes (
446
+ Some ( 5000 ) ,
447
+ & nodes[ 0 ] ,
448
+ short_chan_ids. clone ( ) ,
449
+ ) ;
450
+ }
451
+
452
+ #[ test]
453
+ fn test_hints_has_only_highest_inbound_capacity_channel ( ) {
454
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
455
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
456
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
457
+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
458
+ let chan_1_0_low_inbound_capacity = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 0 , 100_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
459
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_1_0_low_inbound_capacity. 0 ) ;
460
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_1_0_low_inbound_capacity. 1 ) ;
461
+ 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 ( ) ) ;
462
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_1_0_high_inbound_capacity. 0 ) ;
463
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_1_0_high_inbound_capacity. 1 ) ;
464
+ 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 ( ) ) ;
465
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_1_0_medium_inbound_capacity. 0 ) ;
466
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_1_0_medium_inbound_capacity. 1 ) ;
467
+
468
+ let mut short_chan_ids = HashSet :: new ( ) ;
469
+ short_chan_ids. insert ( chan_1_0_high_inbound_capacity. 0 . contents . short_channel_id . clone ( ) ) ;
470
+
471
+ match_invoice_routes (
472
+ Some ( 5000 ) ,
473
+ & nodes[ 0 ] ,
474
+ short_chan_ids. clone ( ) ,
475
+ ) ;
476
+ }
477
+
478
+ #[ test]
479
+ fn test_no_hints_if_any_private_channels_exists ( ) {
480
+ let mut nodes_2_priv_channels_conf = UserConfig :: default ( ) ;
481
+ nodes_2_priv_channels_conf. channel_options . announced_channel = false ;
482
+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
483
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
484
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , Some ( nodes_2_priv_channels_conf) ] ) ;
485
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
486
+ let chan_1_0 = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 0 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
487
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_1_0. 0 ) ;
488
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_1_0. 1 ) ;
489
+
490
+ // Creates a private channel between `nodes[2]` and `nodes[0]`. Note that create_*_chan
491
+ // functions in utils can't be used, as they require announcement_signatures.
492
+ nodes[ 2 ] . node . create_channel ( nodes[ 0 ] . node . get_our_node_id ( ) , 100000 , 10001 , 42 , None ) . unwrap ( ) ;
493
+ let open_channel = get_event_msg ! ( nodes[ 2 ] , MessageSendEvent :: SendOpenChannel , nodes[ 0 ] . node. get_our_node_id( ) ) ;
494
+ nodes[ 0 ] . node . handle_open_channel ( & nodes[ 2 ] . node . get_our_node_id ( ) , InitFeatures :: known ( ) , & open_channel) ;
495
+ let accept_channel = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendAcceptChannel , nodes[ 2 ] . node. get_our_node_id( ) ) ;
496
+ nodes[ 2 ] . node . handle_accept_channel ( & nodes[ 0 ] . node . get_our_node_id ( ) , InitFeatures :: known ( ) , & accept_channel) ;
497
+
498
+ let ( temporary_channel_id, tx, _) = create_funding_transaction ( & nodes[ 2 ] , 100000 , 42 ) ;
499
+ nodes[ 2 ] . node . funding_transaction_generated ( & temporary_channel_id, tx. clone ( ) ) . unwrap ( ) ;
500
+ nodes[ 0 ] . node . handle_funding_created ( & nodes[ 2 ] . node . get_our_node_id ( ) , & get_event_msg ! ( nodes[ 2 ] , MessageSendEvent :: SendFundingCreated , nodes[ 0 ] . node. get_our_node_id( ) ) ) ;
501
+ check_added_monitors ! ( nodes[ 0 ] , 1 ) ;
502
+
503
+ let cs_funding_signed = get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendFundingSigned , nodes[ 2 ] . node. get_our_node_id( ) ) ;
504
+ nodes[ 2 ] . node . handle_funding_signed ( & nodes[ 0 ] . node . get_our_node_id ( ) , & cs_funding_signed) ;
505
+ check_added_monitors ! ( nodes[ 2 ] , 1 ) ;
506
+
507
+ let conf_height = core:: cmp:: max ( nodes[ 2 ] . best_block_info ( ) . 1 + 1 , nodes[ 0 ] . best_block_info ( ) . 1 + 1 ) ;
508
+ confirm_transaction_at ( & nodes[ 2 ] , & tx, conf_height) ;
509
+ connect_blocks ( & nodes[ 2 ] , CHAN_CONFIRM_DEPTH - 1 ) ;
510
+ confirm_transaction_at ( & nodes[ 0 ] , & tx, conf_height) ;
511
+ connect_blocks ( & nodes[ 0 ] , CHAN_CONFIRM_DEPTH - 1 ) ;
512
+ let as_funding_locked = get_event_msg ! ( nodes[ 2 ] , MessageSendEvent :: SendFundingLocked , nodes[ 0 ] . node. get_our_node_id( ) ) ;
513
+ nodes[ 2 ] . node . handle_funding_locked ( & nodes[ 0 ] . node . get_our_node_id ( ) , & get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendFundingLocked , nodes[ 2 ] . node. get_our_node_id( ) ) ) ;
514
+ get_event_msg ! ( nodes[ 2 ] , MessageSendEvent :: SendChannelUpdate , nodes[ 0 ] . node. get_our_node_id( ) ) ;
515
+ nodes[ 0 ] . node . handle_funding_locked ( & nodes[ 2 ] . node . get_our_node_id ( ) , & as_funding_locked) ;
516
+ get_event_msg ! ( nodes[ 0 ] , MessageSendEvent :: SendChannelUpdate , nodes[ 2 ] . node. get_our_node_id( ) ) ;
517
+
518
+ // Ensure that the invoice doesn't include any route hints for any of `nodes[0]` channels,
519
+ // even though all channels between `nodes[1]` and `nodes[0]` are public.
520
+ let invoice = create_invoice_from_channelmanager_and_duration_since_epoch (
521
+ & nodes[ 0 ] . node , nodes[ 0 ] . keys_manager , Currency :: BitcoinTestnet , Some ( 5000 ) , "test" . to_string ( ) ,
522
+ Duration :: from_secs ( 1234567 ) ) . unwrap ( ) ;
523
+ let hints = invoice. private_routes ( ) ;
524
+
525
+ assert ! ( hints. is_empty( ) ) ;
526
+ }
527
+
528
+ #[ test]
529
+ fn test_hints_has_no_channels_with_lower_inbound_capacity_than_invoice_amt ( ) {
530
+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
531
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
532
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
533
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
534
+ let chan_1_0 = create_announced_chan_between_nodes_with_value ( & nodes, 1 , 0 , 100_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
535
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_1_0. 0 ) ;
536
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_1_0. 1 ) ;
537
+ let chan_2_0 = create_announced_chan_between_nodes_with_value ( & nodes, 2 , 0 , 1_000_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
538
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 2 ] . node . get_our_node_id ( ) , & chan_2_0. 0 ) ;
539
+ nodes[ 2 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_2_0. 1 ) ;
540
+
541
+ // 1 msat above chan_1_0's inbound capacity
542
+ let mut short_chan_ids_99_000_001_msat = HashSet :: new ( ) ;
543
+ short_chan_ids_99_000_001_msat. insert ( chan_2_0. 0 . contents . short_channel_id . clone ( ) ) ;
544
+
545
+ match_invoice_routes (
546
+ Some ( 99_000_001 ) ,
547
+ & nodes[ 0 ] ,
548
+ short_chan_ids_99_000_001_msat. clone ( ) ,
549
+ ) ;
550
+
551
+ // Exactly at chan_1_0's inbound capacity
552
+ let mut short_chan_ids_99_000_000_msat = HashSet :: new ( ) ;
553
+ short_chan_ids_99_000_000_msat. insert ( chan_1_0. 0 . contents . short_channel_id . clone ( ) ) ;
554
+ short_chan_ids_99_000_000_msat. insert ( chan_2_0. 0 . contents . short_channel_id . clone ( ) ) ;
555
+
556
+ match_invoice_routes (
557
+ Some ( 99_000_000 ) ,
558
+ & nodes[ 0 ] ,
559
+ short_chan_ids_99_000_000_msat. clone ( ) ,
560
+ ) ;
561
+
562
+ // An invoice with no specified amount should include all route hints.
563
+ let mut short_chan_ids_no_specified_amount = HashSet :: new ( ) ;
564
+ short_chan_ids_no_specified_amount. insert ( chan_1_0. 0 . contents . short_channel_id . clone ( ) ) ;
565
+ short_chan_ids_no_specified_amount. insert ( chan_2_0. 0 . contents . short_channel_id . clone ( ) ) ;
566
+
567
+ match_invoice_routes (
568
+ None ,
569
+ & nodes[ 0 ] ,
570
+ short_chan_ids_no_specified_amount. clone ( ) ,
571
+ ) ;
572
+ }
573
+
574
+ fn match_invoice_routes < ' a , ' b : ' a , ' c : ' b > (
575
+ invoice_amt : Option < u64 > ,
576
+ invoice_node : & Node < ' a , ' b , ' c > ,
577
+ mut chan_ids_to_match : HashSet < u64 >
578
+ ) {
579
+ let invoice = create_invoice_from_channelmanager_and_duration_since_epoch (
580
+ & invoice_node. node , invoice_node. keys_manager , Currency :: BitcoinTestnet , invoice_amt, "test" . to_string ( ) ,
581
+ Duration :: from_secs ( 1234567 ) ) . unwrap ( ) ;
582
+ let hints = invoice. private_routes ( ) ;
583
+
584
+ assert_eq ! ( hints. len( ) , chan_ids_to_match. len( ) ) ;
585
+
586
+ for hint in hints {
587
+ let hint_short_chan_id = ( hint. 0 ) . 0 [ 0 ] . short_channel_id ;
588
+ assert ! ( chan_ids_to_match. contains( & hint_short_chan_id) ) ;
589
+ chan_ids_to_match. remove ( & hint_short_chan_id) ;
590
+ }
591
+ }
592
+
426
593
#[ test]
427
594
#[ cfg( feature = "std" ) ]
428
595
fn test_multi_node_receive ( ) {
0 commit comments