@@ -361,7 +361,7 @@ mod test {
361
361
use bitcoin_hashes:: sha256:: Hash as Sha256 ;
362
362
use lightning:: chain:: keysinterface:: PhantomKeysManager ;
363
363
use lightning:: ln:: { PaymentPreimage , PaymentHash } ;
364
- use lightning:: ln:: channelmanager:: MIN_FINAL_CLTV_EXPIRY ;
364
+ use lightning:: ln:: channelmanager:: { PhantomRouteHints , MIN_FINAL_CLTV_EXPIRY } ;
365
365
use lightning:: ln:: functional_test_utils:: * ;
366
366
use lightning:: ln:: features:: InitFeatures ;
367
367
use lightning:: ln:: msgs:: ChannelMessageHandler ;
@@ -707,4 +707,156 @@ mod test {
707
707
_ => panic ! ( "Unexpected event" )
708
708
}
709
709
}
710
+
711
+ #[ test]
712
+ #[ cfg( feature = "std" ) ]
713
+ fn test_multi_node_hints_includes_single_public_channels_to_participating_nodes ( ) {
714
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
715
+ let seed_1 = [ 42 as u8 ; 32 ] ;
716
+ let seed_2 = [ 43 as u8 ; 32 ] ;
717
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
718
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
719
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
720
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
721
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
722
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
723
+ let chan_0_1 = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
724
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_0_1. 1 ) ;
725
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_0_1. 0 ) ;
726
+ let chan_0_2 = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
727
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 2 ] . node . get_our_node_id ( ) , & chan_0_2. 1 ) ;
728
+ nodes[ 2 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_0_2. 0 ) ;
729
+
730
+ let mut short_chan_ids = HashSet :: new ( ) ;
731
+ short_chan_ids. insert ( chan_0_1. 0 . contents . short_channel_id . clone ( ) ) ;
732
+ short_chan_ids. insert ( chan_0_2. 0 . contents . short_channel_id . clone ( ) ) ;
733
+
734
+ match_multi_node_invoice_routes (
735
+ Some ( 10_000 ) ,
736
+ & nodes[ 1 ] ,
737
+ vec ! [ & nodes[ 1 ] , & nodes[ 2 ] , ] ,
738
+ short_chan_ids. clone ( ) ,
739
+ ) ;
740
+ }
741
+
742
+ #[ test]
743
+ #[ cfg( feature = "std" ) ]
744
+ fn test_multi_node_hints_has_only_highest_inbound_capacity_channel ( ) {
745
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
746
+ let seed_1 = [ 42 as u8 ; 32 ] ;
747
+ let seed_2 = [ 43 as u8 ; 32 ] ;
748
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
749
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
750
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
751
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
752
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
753
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
754
+ let chan_0_1_low_inbound_capacity = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 100_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
755
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_0_1_low_inbound_capacity. 1 ) ;
756
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_0_1_low_inbound_capacity. 0 ) ;
757
+ let chan_0_1_high_inbound_capacity = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
758
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_0_1_high_inbound_capacity. 1 ) ;
759
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_0_1_high_inbound_capacity. 0 ) ;
760
+ let chan_0_1_medium_inbound_capacity = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
761
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_0_1_medium_inbound_capacity. 1 ) ;
762
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_0_1_medium_inbound_capacity. 0 ) ;
763
+ let chan_0_2 = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
764
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 2 ] . node . get_our_node_id ( ) , & chan_0_2. 1 ) ;
765
+ nodes[ 2 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_0_2. 0 ) ;
766
+
767
+ let mut short_chan_ids = HashSet :: new ( ) ;
768
+ short_chan_ids. insert ( chan_0_1_high_inbound_capacity. 0 . contents . short_channel_id . clone ( ) ) ;
769
+ short_chan_ids. insert ( chan_0_2. 0 . contents . short_channel_id . clone ( ) ) ;
770
+
771
+ match_multi_node_invoice_routes (
772
+ Some ( 10_000 ) ,
773
+ & nodes[ 1 ] ,
774
+ vec ! [ & nodes[ 1 ] , & nodes[ 2 ] , ] ,
775
+ short_chan_ids. clone ( ) ,
776
+ ) ;
777
+ }
778
+
779
+ #[ test]
780
+ #[ cfg( feature = "std" ) ]
781
+ fn test_multi_node_hints_has_no_channels_with_lower_inbound_capacity_than_invoice_amt ( ) {
782
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
783
+ let seed_1 = [ 42 as u8 ; 32 ] ;
784
+ let seed_2 = [ 43 as u8 ; 32 ] ;
785
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
786
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
787
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
788
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
789
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
790
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
791
+ let chan_0_1 = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 100_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
792
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 1 ] . node . get_our_node_id ( ) , & chan_0_1. 1 ) ;
793
+ nodes[ 1 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_0_1. 0 ) ;
794
+ let chan_0_2 = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 1_000_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
795
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 2 ] . node . get_our_node_id ( ) , & chan_0_2. 1 ) ;
796
+ nodes[ 2 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_0_2. 0 ) ;
797
+
798
+ // 1 msat above chan_0_1's inbound capacity
799
+ let mut short_chan_ids_99_000_001_msat = HashSet :: new ( ) ;
800
+ short_chan_ids_99_000_001_msat. insert ( chan_0_2. 0 . contents . short_channel_id . clone ( ) ) ;
801
+
802
+ match_multi_node_invoice_routes (
803
+ Some ( 99_000_001 ) ,
804
+ & nodes[ 1 ] ,
805
+ vec ! [ & nodes[ 1 ] , & nodes[ 2 ] , ] ,
806
+ short_chan_ids_99_000_001_msat. clone ( ) ,
807
+ ) ;
808
+
809
+ // Exactly at chan_0_1's inbound capacity
810
+ let mut short_chan_ids_99_000_000_msat = HashSet :: new ( ) ;
811
+ short_chan_ids_99_000_000_msat. insert ( chan_0_1. 0 . contents . short_channel_id . clone ( ) ) ;
812
+ short_chan_ids_99_000_000_msat. insert ( chan_0_2. 0 . contents . short_channel_id . clone ( ) ) ;
813
+
814
+
815
+ match_multi_node_invoice_routes (
816
+ Some ( 99_000_000 ) ,
817
+ & nodes[ 1 ] ,
818
+ vec ! [ & nodes[ 1 ] , & nodes[ 2 ] , ] ,
819
+ short_chan_ids_99_000_000_msat. clone ( ) ,
820
+ ) ;
821
+
822
+ // An invoice with no specified amount should include all participating nodes in the hints.
823
+ let mut short_chan_ids_no_specified_amount = HashSet :: new ( ) ;
824
+ short_chan_ids_no_specified_amount. insert ( chan_0_1. 0 . contents . short_channel_id . clone ( ) ) ;
825
+ short_chan_ids_no_specified_amount. insert ( chan_0_2. 0 . contents . short_channel_id . clone ( ) ) ;
826
+
827
+ match_multi_node_invoice_routes (
828
+ None ,
829
+ & nodes[ 1 ] ,
830
+ vec ! [ & nodes[ 1 ] , & nodes[ 2 ] , ] ,
831
+ short_chan_ids_no_specified_amount. clone ( ) ,
832
+ ) ;
833
+ }
834
+
835
+ #[ cfg( feature = "std" ) ]
836
+ fn match_multi_node_invoice_routes < ' a , ' b : ' a , ' c : ' b > (
837
+ invoice_amt : Option < u64 > ,
838
+ invoice_node : & Node < ' a , ' b , ' c > ,
839
+ network_multi_nodes : Vec < & Node < ' a , ' b , ' c > > ,
840
+ mut chan_ids_to_match : HashSet < u64 >
841
+ ) {
842
+ let ( _, payment_hash, payment_secret) = {
843
+ let ( payment_hash, payment_secret) = invoice_node. node . create_inbound_payment ( invoice_amt, 3600 ) . unwrap ( ) ;
844
+ let payment_preimage = invoice_node. node . get_payment_preimage ( payment_hash, payment_secret) . unwrap ( ) ;
845
+ ( payment_preimage, payment_hash, payment_secret)
846
+ } ;
847
+ let phantom_route_hints = network_multi_nodes. iter ( )
848
+ . map ( |node| node. node . get_phantom_route_hints ( ) )
849
+ . collect :: < Vec < PhantomRouteHints > > ( ) ;
850
+
851
+ let invoice = :: utils:: create_phantom_invoice :: < EnforcingSigner , & test_utils:: TestKeysInterface > ( invoice_amt, "test" . to_string ( ) , payment_hash, payment_secret, phantom_route_hints, & invoice_node. keys_manager , Currency :: BitcoinTestnet ) . unwrap ( ) ;
852
+
853
+ let invoice_hints = invoice. private_routes ( ) ;
854
+ assert_eq ! ( invoice_hints. len( ) , chan_ids_to_match. len( ) ) ;
855
+
856
+ for hint in invoice_hints {
857
+ let hint_short_chan_id = ( hint. 0 ) . 0 [ 0 ] . short_channel_id ;
858
+ assert ! ( chan_ids_to_match. contains( & hint_short_chan_id) ) ;
859
+ chan_ids_to_match. remove ( & hint_short_chan_id) ;
860
+ }
861
+ }
710
862
}
0 commit comments