@@ -333,7 +333,7 @@ mod test {
333333 use bitcoin_hashes:: sha256:: Hash as Sha256 ;
334334 use lightning:: chain:: keysinterface:: PhantomKeysManager ;
335335 use lightning:: ln:: { PaymentPreimage , PaymentHash } ;
336- use lightning:: ln:: channelmanager:: MIN_FINAL_CLTV_EXPIRY ;
336+ use lightning:: ln:: channelmanager:: { PhantomRouteHints , MIN_FINAL_CLTV_EXPIRY } ;
337337 use lightning:: ln:: functional_test_utils:: * ;
338338 use lightning:: ln:: features:: InitFeatures ;
339339 use lightning:: ln:: msgs:: ChannelMessageHandler ;
@@ -687,4 +687,332 @@ mod test {
687687 _ => panic ! ( "Unexpected event" )
688688 }
689689 }
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( ) , "Unmatched short channel ids: {:?}" , chan_ids_to_match) ;
1017+ }
6901018}
0 commit comments