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