@@ -356,7 +356,7 @@ mod test {
356
356
use bitcoin_hashes:: sha256:: Hash as Sha256 ;
357
357
use lightning:: chain:: keysinterface:: PhantomKeysManager ;
358
358
use lightning:: ln:: { PaymentPreimage , PaymentHash } ;
359
- use lightning:: ln:: channelmanager:: MIN_FINAL_CLTV_EXPIRY ;
359
+ use lightning:: ln:: channelmanager:: { PhantomRouteHints , MIN_FINAL_CLTV_EXPIRY } ;
360
360
use lightning:: ln:: functional_test_utils:: * ;
361
361
use lightning:: ln:: features:: InitFeatures ;
362
362
use lightning:: ln:: msgs:: ChannelMessageHandler ;
@@ -748,4 +748,333 @@ mod test {
748
748
_ => panic ! ( "Unexpected event" )
749
749
}
750
750
}
751
+
752
+ #[ test]
753
+ #[ cfg( feature = "std" ) ]
754
+ fn test_multi_node_hints_includes_single_channels_to_participating_nodes ( ) {
755
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
756
+ let seed_1 = [ 42 as u8 ; 32 ] ;
757
+ let seed_2 = [ 43 as u8 ; 32 ] ;
758
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
759
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
760
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
761
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
762
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
763
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
764
+
765
+ let chan_0_1 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
766
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
767
+
768
+ let mut scid_aliases = HashSet :: new ( ) ;
769
+ scid_aliases. insert ( chan_0_1. 0 . short_channel_id_alias . unwrap ( ) ) ;
770
+ scid_aliases. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
771
+
772
+ match_multi_node_invoice_routes (
773
+ Some ( 10_000 ) ,
774
+ & nodes[ 1 ] ,
775
+ vec ! [ & nodes[ 1 ] , & nodes[ 2 ] , ] ,
776
+ scid_aliases,
777
+ false
778
+ ) ;
779
+ }
780
+
781
+ #[ test]
782
+ #[ cfg( feature = "std" ) ]
783
+ fn test_multi_node_hints_includes_one_channel_of_each_counterparty_nodes_per_participating_node ( ) {
784
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
785
+ let seed_1 = [ 42 as u8 ; 32 ] ;
786
+ let seed_2 = [ 43 as u8 ; 32 ] ;
787
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
788
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
789
+ chanmon_cfgs[ 3 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
790
+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
791
+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , None ] ) ;
792
+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
793
+
794
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
795
+ let chan_0_3 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 3 , 1000000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
796
+ let chan_1_3 = create_unannounced_chan_between_nodes_with_value ( & nodes, 1 , 3 , 3_000_000 , 10005 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
797
+
798
+ let mut scid_aliases = HashSet :: new ( ) ;
799
+ scid_aliases. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
800
+ scid_aliases. insert ( chan_0_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
801
+ scid_aliases. insert ( chan_1_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
802
+
803
+ match_multi_node_invoice_routes (
804
+ Some ( 10_000 ) ,
805
+ & nodes[ 2 ] ,
806
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
807
+ scid_aliases,
808
+ false
809
+ ) ;
810
+ }
811
+
812
+ #[ test]
813
+ #[ cfg( feature = "std" ) ]
814
+ fn test_multi_node_forwarding_info_not_assigned_channel_excluded_from_hints ( ) {
815
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
816
+ let seed_1 = [ 42 as u8 ; 32 ] ;
817
+ let seed_2 = [ 43 as u8 ; 32 ] ;
818
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
819
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
820
+ chanmon_cfgs[ 3 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
821
+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
822
+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , None ] ) ;
823
+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
824
+
825
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
826
+ let chan_0_3 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 3 , 1000000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
827
+
828
+ // Create an unannonced channel between `nodes[1]` and `nodes[3]`, for which the
829
+ // `msgs::ChannelUpdate` is never handled for the node(s). As the `msgs::ChannelUpdate`
830
+ // is never handled, the `channel.counterparty.forwarding_info` is never assigned.
831
+ let mut private_chan_cfg = UserConfig :: default ( ) ;
832
+ private_chan_cfg. channel_options . announced_channel = false ;
833
+ 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 ( ) ;
834
+ let open_channel = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendOpenChannel , nodes[ 3 ] . node. get_our_node_id( ) ) ;
835
+ nodes[ 3 ] . node . handle_open_channel ( & nodes[ 1 ] . node . get_our_node_id ( ) , InitFeatures :: known ( ) , & open_channel) ;
836
+ let accept_channel = get_event_msg ! ( nodes[ 3 ] , MessageSendEvent :: SendAcceptChannel , nodes[ 1 ] . node. get_our_node_id( ) ) ;
837
+ nodes[ 1 ] . node . handle_accept_channel ( & nodes[ 3 ] . node . get_our_node_id ( ) , InitFeatures :: known ( ) , & accept_channel) ;
838
+
839
+ let tx = sign_funding_transaction ( & nodes[ 1 ] , & nodes[ 3 ] , 1_000_000 , temporary_channel_id) ;
840
+
841
+ let conf_height = core:: cmp:: max ( nodes[ 1 ] . best_block_info ( ) . 1 + 1 , nodes[ 3 ] . best_block_info ( ) . 1 + 1 ) ;
842
+ confirm_transaction_at ( & nodes[ 1 ] , & tx, conf_height) ;
843
+ connect_blocks ( & nodes[ 1 ] , CHAN_CONFIRM_DEPTH - 1 ) ;
844
+ confirm_transaction_at ( & nodes[ 3 ] , & tx, conf_height) ;
845
+ connect_blocks ( & nodes[ 3 ] , CHAN_CONFIRM_DEPTH - 1 ) ;
846
+ let as_funding_locked = get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendFundingLocked , nodes[ 3 ] . node. get_our_node_id( ) ) ;
847
+ 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( ) ) ) ;
848
+ get_event_msg ! ( nodes[ 1 ] , MessageSendEvent :: SendChannelUpdate , nodes[ 3 ] . node. get_our_node_id( ) ) ;
849
+ nodes[ 3 ] . node . handle_funding_locked ( & nodes[ 1 ] . node . get_our_node_id ( ) , & as_funding_locked) ;
850
+ get_event_msg ! ( nodes[ 3 ] , MessageSendEvent :: SendChannelUpdate , nodes[ 1 ] . node. get_our_node_id( ) ) ;
851
+
852
+ // As `msgs::ChannelUpdate` was never handled for the participating node(s) of the third
853
+ // channel, the channel will never be assigned any `counterparty.forwarding_info`.
854
+ // Therefore only `chan_0_3` should be included in the hints for `nodes[3]`.
855
+ let mut scid_aliases = HashSet :: new ( ) ;
856
+ scid_aliases. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
857
+ scid_aliases. insert ( chan_0_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
858
+
859
+ match_multi_node_invoice_routes (
860
+ Some ( 10_000 ) ,
861
+ & nodes[ 2 ] ,
862
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
863
+ scid_aliases,
864
+ false
865
+ ) ;
866
+ }
867
+
868
+ #[ test]
869
+ #[ cfg( feature = "std" ) ]
870
+ fn test_multi_node_with_only_public_channels_hints_includes_only_phantom_route ( ) {
871
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
872
+ let seed_1 = [ 42 as u8 ; 32 ] ;
873
+ let seed_2 = [ 43 as u8 ; 32 ] ;
874
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
875
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
876
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
877
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
878
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
879
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
880
+
881
+ let chan_0_1 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
882
+
883
+ let chan_2_0 = create_announced_chan_between_nodes_with_value ( & nodes, 2 , 0 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
884
+ nodes[ 2 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_2_0. 1 ) ;
885
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 2 ] . node . get_our_node_id ( ) , & chan_2_0. 0 ) ;
886
+
887
+ // Hints should include `chan_0_1` from as `nodes[1]` only have private channels, but not
888
+ // `chan_0_2` as `nodes[2]` only has public channels.
889
+ let mut scid_aliases = HashSet :: new ( ) ;
890
+ scid_aliases. insert ( chan_0_1. 0 . short_channel_id_alias . unwrap ( ) ) ;
891
+
892
+ match_multi_node_invoice_routes (
893
+ Some ( 10_000 ) ,
894
+ & nodes[ 1 ] ,
895
+ vec ! [ & nodes[ 1 ] , & nodes[ 2 ] , ] ,
896
+ scid_aliases,
897
+ true
898
+ ) ;
899
+ }
900
+
901
+ #[ test]
902
+ #[ cfg( feature = "std" ) ]
903
+ fn test_multi_node_with_mixed_public_and_private_channel_hints_includes_only_phantom_route ( ) {
904
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
905
+ let seed_1 = [ 42 as u8 ; 32 ] ;
906
+ let seed_2 = [ 43 as u8 ; 32 ] ;
907
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
908
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
909
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
910
+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
911
+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , None ] ) ;
912
+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
913
+
914
+ let chan_0_2 = create_announced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
915
+ nodes[ 0 ] . node . handle_channel_update ( & nodes[ 2 ] . node . get_our_node_id ( ) , & chan_0_2. 1 ) ;
916
+ nodes[ 2 ] . node . handle_channel_update ( & nodes[ 0 ] . node . get_our_node_id ( ) , & chan_0_2. 0 ) ;
917
+ let _chan_1_2 = create_unannounced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
918
+
919
+ let chan_0_3 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 3 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
920
+
921
+ // Hints should include `chan_0_3` from as `nodes[3]` only have private channels, and no
922
+ // channels for `nodes[2]` as it contains a mix of public and private channels.
923
+ let mut scid_aliases = HashSet :: new ( ) ;
924
+ scid_aliases. insert ( chan_0_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
925
+
926
+ match_multi_node_invoice_routes (
927
+ Some ( 10_000 ) ,
928
+ & nodes[ 2 ] ,
929
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
930
+ scid_aliases,
931
+ true
932
+ ) ;
933
+ }
934
+
935
+ #[ test]
936
+ #[ cfg( feature = "std" ) ]
937
+ fn test_multi_node_hints_has_only_highest_inbound_capacity_channel ( ) {
938
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
939
+ let seed_1 = [ 42 as u8 ; 32 ] ;
940
+ let seed_2 = [ 43 as u8 ; 32 ] ;
941
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
942
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
943
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
944
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
945
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
946
+ let nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
947
+
948
+ let _chan_0_1_low_inbound_capacity = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 100_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
949
+ 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 ( ) ) ;
950
+ 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 ( ) ) ;
951
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 100000 , 10001 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
952
+
953
+ let mut scid_aliases = HashSet :: new ( ) ;
954
+ scid_aliases. insert ( chan_0_1_high_inbound_capacity. 0 . short_channel_id_alias . unwrap ( ) ) ;
955
+ scid_aliases. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
956
+
957
+ match_multi_node_invoice_routes (
958
+ Some ( 10_000 ) ,
959
+ & nodes[ 1 ] ,
960
+ vec ! [ & nodes[ 1 ] , & nodes[ 2 ] , ] ,
961
+ scid_aliases,
962
+ false
963
+ ) ;
964
+ }
965
+
966
+ #[ test]
967
+ #[ cfg( feature = "std" ) ]
968
+ fn test_multi_node_channels_inbound_capacity_lower_than_invoice_amt_filtering ( ) {
969
+ let mut chanmon_cfgs = create_chanmon_cfgs ( 4 ) ;
970
+ let seed_1 = [ 42 as u8 ; 32 ] ;
971
+ let seed_2 = [ 43 as u8 ; 32 ] ;
972
+ let cross_node_seed = [ 44 as u8 ; 32 ] ;
973
+ chanmon_cfgs[ 1 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_1, 43 , 44 , & cross_node_seed) ;
974
+ chanmon_cfgs[ 2 ] . keys_manager . backing = PhantomKeysManager :: new ( & seed_2, 43 , 44 , & cross_node_seed) ;
975
+ let node_cfgs = create_node_cfgs ( 4 , & chanmon_cfgs) ;
976
+ let node_chanmgrs = create_node_chanmgrs ( 4 , & node_cfgs, & [ None , None , None , None ] ) ;
977
+ let nodes = create_network ( 4 , & node_cfgs, & node_chanmgrs) ;
978
+
979
+ let chan_0_2 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 2 , 1_000_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
980
+ let chan_0_3 = create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 3 , 100_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
981
+ let chan_1_3 = create_unannounced_chan_between_nodes_with_value ( & nodes, 1 , 3 , 200_000 , 0 , InitFeatures :: known ( ) , InitFeatures :: known ( ) ) ;
982
+
983
+ // Since the invoice 1 msat above chan_0_3's inbound capacity, it should be filtered out.
984
+ let mut scid_aliases_99_000_001_msat = HashSet :: new ( ) ;
985
+ scid_aliases_99_000_001_msat. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
986
+ scid_aliases_99_000_001_msat. insert ( chan_1_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
987
+
988
+ match_multi_node_invoice_routes (
989
+ Some ( 99_000_001 ) ,
990
+ & nodes[ 2 ] ,
991
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
992
+ scid_aliases_99_000_001_msat,
993
+ false
994
+ ) ;
995
+
996
+ // Since the invoice is exactly at chan_0_3's inbound capacity, it should be included.
997
+ let mut scid_aliases_99_000_000_msat = HashSet :: new ( ) ;
998
+ scid_aliases_99_000_000_msat. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
999
+ scid_aliases_99_000_000_msat. insert ( chan_0_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
1000
+ scid_aliases_99_000_000_msat. insert ( chan_1_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
1001
+
1002
+ match_multi_node_invoice_routes (
1003
+ Some ( 99_000_000 ) ,
1004
+ & nodes[ 2 ] ,
1005
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
1006
+ scid_aliases_99_000_000_msat,
1007
+ false
1008
+ ) ;
1009
+
1010
+ // Since the invoice is above all of `nodes[2]` channels' inbound capacity, all of
1011
+ // `nodes[2]` them should be included.
1012
+ let mut scid_aliases_300_000_000_msat = HashSet :: new ( ) ;
1013
+ scid_aliases_300_000_000_msat. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
1014
+ scid_aliases_300_000_000_msat. insert ( chan_0_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
1015
+ scid_aliases_300_000_000_msat. insert ( chan_1_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
1016
+
1017
+ match_multi_node_invoice_routes (
1018
+ Some ( 300_000_000 ) ,
1019
+ & nodes[ 2 ] ,
1020
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
1021
+ scid_aliases_300_000_000_msat,
1022
+ false
1023
+ ) ;
1024
+
1025
+ // Since the no specified amount, all channels should included.
1026
+ let mut scid_aliases_no_specified_amount = HashSet :: new ( ) ;
1027
+ scid_aliases_no_specified_amount. insert ( chan_0_2. 0 . short_channel_id_alias . unwrap ( ) ) ;
1028
+ scid_aliases_no_specified_amount. insert ( chan_0_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
1029
+ scid_aliases_no_specified_amount. insert ( chan_1_3. 0 . short_channel_id_alias . unwrap ( ) ) ;
1030
+
1031
+ match_multi_node_invoice_routes (
1032
+ None ,
1033
+ & nodes[ 2 ] ,
1034
+ vec ! [ & nodes[ 2 ] , & nodes[ 3 ] , ] ,
1035
+ scid_aliases_no_specified_amount,
1036
+ false
1037
+ ) ;
1038
+ }
1039
+
1040
+ #[ cfg( feature = "std" ) ]
1041
+ fn match_multi_node_invoice_routes < ' a , ' b : ' a , ' c : ' b > (
1042
+ invoice_amt : Option < u64 > ,
1043
+ invoice_node : & Node < ' a , ' b , ' c > ,
1044
+ network_multi_nodes : Vec < & Node < ' a , ' b , ' c > > ,
1045
+ mut chan_ids_to_match : HashSet < u64 > ,
1046
+ nodes_contains_public_channels : bool
1047
+ ) {
1048
+ let ( payment_hash, payment_secret) = invoice_node. node . create_inbound_payment ( invoice_amt, 3600 ) . unwrap ( ) ;
1049
+ let phantom_route_hints = network_multi_nodes. iter ( )
1050
+ . map ( |node| node. node . get_phantom_route_hints ( ) )
1051
+ . collect :: < Vec < PhantomRouteHints > > ( ) ;
1052
+ let phantom_scids = phantom_route_hints. iter ( )
1053
+ . map ( |route_hint| route_hint. phantom_scid )
1054
+ . collect :: < HashSet < u64 > > ( ) ;
1055
+
1056
+ 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 ( ) ;
1057
+
1058
+ let invoice_hints = invoice. private_routes ( ) ;
1059
+
1060
+ for hint in invoice_hints {
1061
+ let hints = & ( hint. 0 ) . 0 ;
1062
+ match hints. len ( ) {
1063
+ 1 => {
1064
+ assert ! ( nodes_contains_public_channels) ;
1065
+ let phantom_scid = hints[ 0 ] . short_channel_id ;
1066
+ assert ! ( phantom_scids. contains( & phantom_scid) ) ;
1067
+ } ,
1068
+ 2 => {
1069
+ let hint_short_chan_id = hints[ 0 ] . short_channel_id ;
1070
+ assert ! ( chan_ids_to_match. contains( & hint_short_chan_id) ) ;
1071
+ chan_ids_to_match. remove ( & hint_short_chan_id) ;
1072
+ let phantom_scid = hints[ 1 ] . short_channel_id ;
1073
+ assert ! ( phantom_scids. contains( & phantom_scid) ) ;
1074
+ } ,
1075
+ _ => panic ! ( "Incorrect hint length generated" )
1076
+ }
1077
+ }
1078
+ assert ! ( chan_ids_to_match. is_empty( ) ) ;
1079
+ }
751
1080
}
0 commit comments