@@ -356,7 +356,9 @@ mod test {
356356 use lightning:: util:: enforcing_trait_impls:: EnforcingSigner ;
357357 use lightning:: util:: events:: { MessageSendEvent , MessageSendEventsProvider , Event } ;
358358 use lightning:: util:: test_utils;
359+ use lightning:: util:: config:: UserConfig ;
359360 use utils:: create_invoice_from_channelmanager_and_duration_since_epoch;
361+ use std:: collections:: HashSet ;
360362
361363 #[ test]
362364 fn test_from_channelmanager ( ) {
@@ -411,6 +413,148 @@ mod test {
411413 assert_eq ! ( events. len( ) , 2 ) ;
412414 }
413415
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+
414558 #[ test]
415559 #[ cfg( feature = "std" ) ]
416560 fn test_multi_node_receive ( ) {
0 commit comments