@@ -333,7 +333,7 @@ mod test {
333
333
use bitcoin_hashes:: sha256:: Hash as Sha256 ;
334
334
use lightning:: chain:: keysinterface:: PhantomKeysManager ;
335
335
use lightning:: ln:: { PaymentPreimage , PaymentHash } ;
336
- use lightning:: ln:: channelmanager:: MIN_FINAL_CLTV_EXPIRY ;
336
+ use lightning:: ln:: channelmanager:: { PhantomRouteHints , MIN_FINAL_CLTV_EXPIRY } ;
337
337
use lightning:: ln:: functional_test_utils:: * ;
338
338
use lightning:: ln:: features:: InitFeatures ;
339
339
use lightning:: ln:: msgs:: ChannelMessageHandler ;
@@ -687,4 +687,332 @@ mod test {
687
687
_ => panic ! ( "Unexpected event" )
688
688
}
689
689
}
690
+
691
+ #[ test]
692
+ #[ cfg( feature = "std" ) ]
693
+ fn test_multi_node_hints_includes_single_channels_to_participating_nodes ( ) {
694
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
695
+ let seed_1 = [ 42 as u8 ; 32 ] ;
696
+ let seed_2 = [ 43 as u8 ; 32 ] ;
697
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
698
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
699
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
700
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
701
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
702
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
703
+
704
+ let chan_0_1 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
705
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
706
+
707
+ let mut scid_aliases = HashSet :: new ( ) ;
708
+ scid_aliases. insert ( chan_0_1. 0 . short_channel_id_alias . unwrap ( ) ) ;
709
+ scid_aliases. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
710
+
711
+ match_multi_node_invoice_routes (
712
+ Some ( 10_000 ) ,
713
+ & nodes[ 1 ] ,
714
+ vec ! [ & nodes[ 1 ] , & nodes[ 2 ] , ] ,
715
+ scid_aliases,
716
+ false
717
+ ) ;
718
+ }
719
+
720
+ #[ test]
721
+ #[ cfg( feature = "std" ) ]
722
+ fn test_multi_node_hints_includes_one_channel_of_each_counterparty_nodes_per_participating_node ( ) {
723
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
724
+ let seed_1 = [ 42 as u8 ; 32 ] ;
725
+ let seed_2 = [ 43 as u8 ; 32 ] ;
726
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
727
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
728
+ chanmon_cfgs[ 3 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
729
+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
730
+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , None ] ) ;
731
+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
732
+
733
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
734
+ let chan_0_3 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 3 , 1000000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
735
+ let chan_1_3 = create_unannounced_chan_between_nodes_with_value ( & nodes, 1 , 3 , 3_000_000 , 10005 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
736
+
737
+ let mut scid_aliases = HashSet :: new ( ) ;
738
+ scid_aliases. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
739
+ scid_aliases. insert ( chan_0_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
740
+ scid_aliases. insert ( chan_1_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
741
+
742
+ match_multi_node_invoice_routes (
743
+ Some ( 10_000 ) ,
744
+ & nodes[ 2 ] ,
745
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
746
+ scid_aliases,
747
+ false
748
+ ) ;
749
+ }
750
+
751
+ #[ test]
752
+ #[ cfg( feature = "std" ) ]
753
+ fn test_multi_node_forwarding_info_not_assigned_channel_excluded_from_hints ( ) {
754
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
755
+ let seed_1 = [ 42 as u8 ; 32 ] ;
756
+ let seed_2 = [ 43 as u8 ; 32 ] ;
757
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
758
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
759
+ chanmon_cfgs[ 3 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
760
+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
761
+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , None ] ) ;
762
+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
763
+
764
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
765
+ let chan_0_3 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 3 , 1000000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
766
+
767
+ // Create an unannonced channel between `nodes[1]` and `nodes[3]`, for which the
768
+ // `msgs::ChannelUpdate` is never handled for the node(s). As the `msgs::ChannelUpdate`
769
+ // is never handled, the `channel.counterparty.forwarding_info` is never assigned.
770
+ let mut private_chan_cfg = UserConfig :: default ( ) ;
771
+ private_chan_cfg. channel_options . announced_channel = false ;
772
+ let temporary_channel_id = nodes[ 1 ] . node . create_channel ( nodes[ 3 ] . node . get_our_node_id ( ) , 1_000_000 , 500_000_000 , 42 , Some ( private_chan_cfg) ) . unwrap ( ) ;
773
+ let open_channel = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendOpenChannel , nodes[ 3 ] . node. get_our_node_id( ) ) ;
774
+ nodes[ 3 ] . node . handle_open_channel ( & nodes[ 1 ] . node . get_our_node_id ( ) , InitFeatures :: known ( ) , & open_channel) ;
775
+ let accept_channel = get_event_msg ! ( nodes[ 3 ] , MessageSendEvent :: SendAcceptChannel , nodes[ 1 ] . node. get_our_node_id( ) ) ;
776
+ nodes[ 1 ] . node . handle_accept_channel ( & nodes[ 3 ] . node . get_our_node_id ( ) , InitFeatures :: known ( ) , & accept_channel) ;
777
+
778
+ let tx = sign_funding_transaction ( & nodes[ 1 ] , & nodes[ 3 ] , 1_000_000 , temporary_channel_id) ;
779
+
780
+ let conf_height = core:: cmp:: max ( nodes[ 1 ] . best_block_info ( ) . 1 + 1 , nodes[ 3 ] . best_block_info ( ) . 1 + 1 ) ;
781
+ confirm_transaction_at ( & nodes[ 1 ] , & tx, conf_height) ;
782
+ connect_blocks ( & nodes[ 1 ] , CHAN_CONFIRM_DEPTH - 1 ) ;
783
+ confirm_transaction_at ( & nodes[ 3 ] , & tx, conf_height) ;
784
+ connect_blocks ( & nodes[ 3 ] , CHAN_CONFIRM_DEPTH - 1 ) ;
785
+ let as_funding_locked = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendFundingLocked , nodes[ 3 ] . node. get_our_node_id( ) ) ;
786
+ nodes[ 1 ] . node . handle_funding_locked ( & nodes[ 3 ] . node . get_our_node_id ( ) , & get_event_msg ! ( nodes[ 3 ] , MessageSendEvent :: SendFundingLocked , nodes[ 1 ] . node. get_our_node_id( ) ) ) ;
787
+ get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendChannelUpdate , nodes[ 3 ] . node. get_our_node_id( ) ) ;
788
+ nodes[ 3 ] . node . handle_funding_locked ( & nodes[ 1 ] . node . get_our_node_id ( ) , & as_funding_locked) ;
789
+ get_event_msg ! ( nodes[ 3 ] , MessageSendEvent :: SendChannelUpdate , nodes[ 1 ] . node. get_our_node_id( ) ) ;
790
+
791
+ // As `msgs::ChannelUpdate` was never handled for the participating node(s) of the third
792
+ // channel, the channel will never be assigned any `counterparty.forwarding_info`.
793
+ // Therefore only `chan_0_3` should be included in the hints for `nodes[3]`.
794
+ let mut scid_aliases = HashSet :: new ( ) ;
795
+ scid_aliases. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
796
+ scid_aliases. insert ( chan_0_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
797
+
798
+ match_multi_node_invoice_routes (
799
+ Some ( 10_000 ) ,
800
+ & nodes[ 2 ] ,
801
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
802
+ scid_aliases,
803
+ false
804
+ ) ;
805
+ }
806
+
807
+ #[ test]
808
+ #[ cfg( feature = "std" ) ]
809
+ fn test_multi_node_with_only_public_channels_hints_includes_only_phantom_route ( ) {
810
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
811
+ let seed_1 = [ 42 as u8 ; 32 ] ;
812
+ let seed_2 = [ 43 as u8 ; 32 ] ;
813
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
814
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
815
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
816
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
817
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
818
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
819
+
820
+ let chan_0_1 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
821
+
822
+ let chan_2_0 = create_announced_chan_between_nodes_with_value ( & nodes, 2 , 0 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
823
+ nodes[ 2 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_2_0. 1 ) ;
824
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 2 ] . node . get_our_node_id ( ) , & chan_2_0. 0 ) ;
825
+
826
+ // Hints should include `chan_0_1` from as `nodes[1]` only have private channels, but not
827
+ // `chan_0_2` as `nodes[2]` only has public channels.
828
+ let mut scid_aliases = HashSet :: new ( ) ;
829
+ scid_aliases. insert ( chan_0_1. 0 . short_channel_id_alias . unwrap ( ) ) ;
830
+
831
+ match_multi_node_invoice_routes (
832
+ Some ( 10_000 ) ,
833
+ & nodes[ 1 ] ,
834
+ vec ! [ & nodes[ 1 ] , & nodes[ 2 ] , ] ,
835
+ scid_aliases,
836
+ true
837
+ ) ;
838
+ }
839
+
840
+ #[ test]
841
+ #[ cfg( feature = "std" ) ]
842
+ fn test_multi_node_with_mixed_public_and_private_channel_hints_includes_only_phantom_route ( ) {
843
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
844
+ let seed_1 = [ 42 as u8 ; 32 ] ;
845
+ let seed_2 = [ 43 as u8 ; 32 ] ;
846
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
847
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
848
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
849
+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
850
+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , None ] ) ;
851
+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
852
+
853
+ let chan_0_2 = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
854
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 2 ] . node . get_our_node_id ( ) , & chan_0_2. 1 ) ;
855
+ nodes[ 2 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_0_2. 0 ) ;
856
+ let _chan_1_2 = create_unannounced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
857
+
858
+ let chan_0_3 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 3 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
859
+
860
+ // Hints should include `chan_0_3` from as `nodes[3]` only have private channels, and no
861
+ // channels for `nodes[2]` as it contains a mix of public and private channels.
862
+ let mut scid_aliases = HashSet :: new ( ) ;
863
+ scid_aliases. insert ( chan_0_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
864
+
865
+ match_multi_node_invoice_routes (
866
+ Some ( 10_000 ) ,
867
+ & nodes[ 2 ] ,
868
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
869
+ scid_aliases,
870
+ true
871
+ ) ;
872
+ }
873
+
874
+ #[ test]
875
+ #[ cfg( feature = "std" ) ]
876
+ fn test_multi_node_hints_has_only_highest_inbound_capacity_channel ( ) {
877
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
878
+ let seed_1 = [ 42 as u8 ; 32 ] ;
879
+ let seed_2 = [ 43 as u8 ; 32 ] ;
880
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
881
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
882
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
883
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
884
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
885
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
886
+
887
+ let _chan_0_1_low_inbound_capacity = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 100_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
888
+ let chan_0_1_high_inbound_capacity = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
889
+ let _chan_0_1_medium_inbound_capacity = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 1_000_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
890
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
891
+
892
+ let mut scid_aliases = HashSet :: new ( ) ;
893
+ scid_aliases. insert ( chan_0_1_high_inbound_capacity. 0 . short_channel_id_alias . unwrap ( ) ) ;
894
+ scid_aliases. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
895
+
896
+ match_multi_node_invoice_routes (
897
+ Some ( 10_000 ) ,
898
+ & nodes[ 1 ] ,
899
+ vec ! [ & nodes[ 1 ] , & nodes[ 2 ] , ] ,
900
+ scid_aliases,
901
+ false
902
+ ) ;
903
+ }
904
+
905
+ #[ test]
906
+ #[ cfg( feature = "std" ) ]
907
+ fn test_multi_node_channels_inbound_capacity_lower_than_invoice_amt_filtering ( ) {
908
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
909
+ let seed_1 = [ 42 as u8 ; 32 ] ;
910
+ let seed_2 = [ 43 as u8 ; 32 ] ;
911
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
912
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
913
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
914
+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
915
+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , None ] ) ;
916
+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
917
+
918
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 1_000_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
919
+ let chan_0_3 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 3 , 100_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
920
+ let chan_1_3 = create_unannounced_chan_between_nodes_with_value ( & nodes, 1 , 3 , 200_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
921
+
922
+ // Since the invoice 1 msat above chan_0_3's inbound capacity, it should be filtered out.
923
+ let mut scid_aliases_99_000_001_msat = HashSet :: new ( ) ;
924
+ scid_aliases_99_000_001_msat. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
925
+ scid_aliases_99_000_001_msat. insert ( chan_1_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
926
+
927
+ match_multi_node_invoice_routes (
928
+ Some ( 99_000_001 ) ,
929
+ & nodes[ 2 ] ,
930
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
931
+ scid_aliases_99_000_001_msat,
932
+ false
933
+ ) ;
934
+
935
+ // Since the invoice is exactly at chan_0_3's inbound capacity, it should be included.
936
+ let mut scid_aliases_99_000_000_msat = HashSet :: new ( ) ;
937
+ scid_aliases_99_000_000_msat. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
938
+ scid_aliases_99_000_000_msat. insert ( chan_0_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
939
+ scid_aliases_99_000_000_msat. insert ( chan_1_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
940
+
941
+ match_multi_node_invoice_routes (
942
+ Some ( 99_000_000 ) ,
943
+ & nodes[ 2 ] ,
944
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
945
+ scid_aliases_99_000_000_msat,
946
+ false
947
+ ) ;
948
+
949
+ // Since the invoice is above all of `nodes[2]` channels' inbound capacity, all of
950
+ // `nodes[2]` them should be included.
951
+ let mut scid_aliases_300_000_000_msat = HashSet :: new ( ) ;
952
+ scid_aliases_300_000_000_msat. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
953
+ scid_aliases_300_000_000_msat. insert ( chan_0_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
954
+ scid_aliases_300_000_000_msat. insert ( chan_1_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
955
+
956
+ match_multi_node_invoice_routes (
957
+ Some ( 300_000_000 ) ,
958
+ & nodes[ 2 ] ,
959
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
960
+ scid_aliases_300_000_000_msat,
961
+ false
962
+ ) ;
963
+
964
+ // Since the no specified amount, all channels should included.
965
+ let mut scid_aliases_no_specified_amount = HashSet :: new ( ) ;
966
+ scid_aliases_no_specified_amount. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
967
+ scid_aliases_no_specified_amount. insert ( chan_0_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
968
+ scid_aliases_no_specified_amount. insert ( chan_1_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
969
+
970
+ match_multi_node_invoice_routes (
971
+ None ,
972
+ & nodes[ 2 ] ,
973
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
974
+ scid_aliases_no_specified_amount,
975
+ false
976
+ ) ;
977
+ }
978
+
979
+ #[ cfg( feature = "std" ) ]
980
+ fn match_multi_node_invoice_routes < ' a , ' b : ' a , ' c : ' b > (
981
+ invoice_amt : Option < u64 > ,
982
+ invoice_node : & Node < ' a , ' b , ' c > ,
983
+ network_multi_nodes : Vec < & Node < ' a , ' b , ' c > > ,
984
+ mut chan_ids_to_match : HashSet < u64 > ,
985
+ nodes_contains_public_channels : bool
986
+ ) {
987
+ let ( payment_hash, payment_secret) = invoice_node. node . create_inbound_payment ( invoice_amt, 3600 ) . unwrap ( ) ;
988
+ let phantom_route_hints = network_multi_nodes. iter ( )
989
+ . map ( |node| node. node . get_phantom_route_hints ( ) )
990
+ . collect :: < Vec < PhantomRouteHints > > ( ) ;
991
+ let phantom_scids = phantom_route_hints. iter ( )
992
+ . map ( |route_hint| route_hint. phantom_scid )
993
+ . collect :: < HashSet < u64 > > ( ) ;
994
+
995
+ 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 ( ) ;
996
+
997
+ let invoice_hints = invoice. private_routes ( ) ;
998
+
999
+ for hint in invoice_hints {
1000
+ let hints = & ( hint. 0 ) . 0 ;
1001
+ match hints. len ( ) {
1002
+ 1 => {
1003
+ assert ! ( nodes_contains_public_channels) ;
1004
+ let phantom_scid = hints[ 0 ] . short_channel_id ;
1005
+ assert ! ( phantom_scids. contains( & phantom_scid) ) ;
1006
+ } ,
1007
+ 2 => {
1008
+ let hint_short_chan_id = hints[ 0 ] . short_channel_id ;
1009
+ assert ! ( chan_ids_to_match. remove( & hint_short_chan_id) ) ;
1010
+ let phantom_scid = hints[ 1 ] . short_channel_id ;
1011
+ assert ! ( phantom_scids. contains( & phantom_scid) ) ;
1012
+ } ,
1013
+ _ => panic ! ( "Incorrect hint length generated" )
1014
+ }
1015
+ }
1016
+ assert ! ( chan_ids_to_match. is_empty( ) ) ;
1017
+ }
690
1018
}
0 commit comments