@@ -878,6 +878,170 @@ fn pays_for_refund_without_blinded_paths() {
878
878
expect_recent_payment ! ( bob, RecentPaymentDetails :: Fulfilled , payment_id) ;
879
879
}
880
880
881
+ /// This test checks that when multiple potential introduction nodes are available for the payer,
882
+ /// multiple `invoice_request` messages are sent for the offer, each with a different `reply_path`.
883
+ #[ test]
884
+ fn send_invoice_requests_with_distinct_reply_path ( ) {
885
+ let mut accept_forward_cfg = test_default_channel_config ( ) ;
886
+ accept_forward_cfg. accept_forwards_to_priv_channels = true ;
887
+
888
+ let mut features = channelmanager:: provided_init_features ( & accept_forward_cfg) ;
889
+ features. set_onion_messages_optional ( ) ;
890
+ features. set_route_blinding_optional ( ) ;
891
+
892
+ let chanmon_cfgs = create_chanmon_cfgs ( 7 ) ;
893
+ let node_cfgs = create_node_cfgs ( 7 , & chanmon_cfgs) ;
894
+
895
+ * node_cfgs[ 1 ] . override_init_features . borrow_mut ( ) = Some ( features) ;
896
+
897
+ let node_chanmgrs = create_node_chanmgrs (
898
+ 7 , & node_cfgs, & [ None , Some ( accept_forward_cfg) , None , None , None , None , None ]
899
+ ) ;
900
+ let nodes = create_network ( 7 , & node_cfgs, & node_chanmgrs) ;
901
+
902
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) ;
903
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 10_000_000 , 1_000_000_000 ) ;
904
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 1_000_000_000 ) ;
905
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 4 , 10_000_000 , 1_000_000_000 ) ;
906
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 5 , 10_000_000 , 1_000_000_000 ) ;
907
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 4 , 10_000_000 , 1_000_000_000 ) ;
908
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 5 , 10_000_000 , 1_000_000_000 ) ;
909
+
910
+ // Introduce another potential introduction node, node[6], as a candidate
911
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 3 , 6 , 10_000_000 , 1_000_000_000 ) ;
912
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 6 , 10_000_000 , 1_000_000_000 ) ;
913
+ create_announced_chan_between_nodes_with_value ( & nodes, 4 , 6 , 10_000_000 , 1_000_000_000 ) ;
914
+ create_announced_chan_between_nodes_with_value ( & nodes, 5 , 6 , 10_000_000 , 1_000_000_000 ) ;
915
+
916
+ let ( alice, bob, charlie, david) = ( & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ) ;
917
+ let alice_id = alice. node . get_our_node_id ( ) ;
918
+ let bob_id = bob. node . get_our_node_id ( ) ;
919
+ let charlie_id = charlie. node . get_our_node_id ( ) ;
920
+ let david_id = david. node . get_our_node_id ( ) ;
921
+
922
+ disconnect_peers ( alice, & [ charlie, david, & nodes[ 4 ] , & nodes[ 5 ] , & nodes[ 6 ] ] ) ;
923
+ disconnect_peers ( david, & [ bob, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
924
+
925
+ let offer = alice. node
926
+ . create_offer_builder ( None )
927
+ . unwrap ( )
928
+ . amount_msats ( 10_000_000 )
929
+ . build ( ) . unwrap ( ) ;
930
+ assert_ne ! ( offer. signing_pubkey( ) , Some ( alice_id) ) ;
931
+ assert ! ( !offer. paths( ) . is_empty( ) ) ;
932
+ for path in offer. paths ( ) {
933
+ assert_eq ! ( path. introduction_node, IntroductionNode :: NodeId ( bob_id) ) ;
934
+ }
935
+
936
+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
937
+ david. node . pay_for_offer ( & offer, None , None , None , payment_id, Retry :: Attempts ( 0 ) , None )
938
+ . unwrap ( ) ;
939
+ expect_recent_payment ! ( david, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
940
+ connect_peers ( david, bob) ;
941
+
942
+ // Send, extract and verify the first Invoice Request message
943
+ let onion_message = david. onion_messenger . next_onion_message_for_peer ( bob_id) . unwrap ( ) ;
944
+ bob. onion_messenger . handle_onion_message ( & david_id, & onion_message) ;
945
+
946
+ connect_peers ( alice, charlie) ;
947
+
948
+ let onion_message = bob. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
949
+ alice. onion_messenger . handle_onion_message ( & bob_id, & onion_message) ;
950
+
951
+ let ( _, reply_path) = extract_invoice_request ( alice, & onion_message) ;
952
+ assert_eq ! ( reply_path. introduction_node, IntroductionNode :: NodeId ( charlie_id) ) ;
953
+
954
+ // Send, extract and verify the second Invoice Request message
955
+ let onion_message = david. onion_messenger . next_onion_message_for_peer ( bob_id) . unwrap ( ) ;
956
+ bob. onion_messenger . handle_onion_message ( & david_id, & onion_message) ;
957
+
958
+ let onion_message = bob. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
959
+ alice. onion_messenger . handle_onion_message ( & bob_id, & onion_message) ;
960
+
961
+ let ( _, reply_path) = extract_invoice_request ( alice, & onion_message) ;
962
+ assert_eq ! ( reply_path. introduction_node, IntroductionNode :: NodeId ( nodes[ 6 ] . node. get_our_node_id( ) ) ) ;
963
+ }
964
+
965
+ /// This test checks that when multiple potential introduction nodes are available for the payee,
966
+ /// multiple `Invoice` messages are sent for the Refund, each with a different `reply_path`.
967
+ #[ test]
968
+ fn send_invoice_for_refund_with_distinct_reply_path ( ) {
969
+ let mut accept_forward_cfg = test_default_channel_config ( ) ;
970
+ accept_forward_cfg. accept_forwards_to_priv_channels = true ;
971
+
972
+ let mut features = channelmanager:: provided_init_features ( & accept_forward_cfg) ;
973
+ features. set_onion_messages_optional ( ) ;
974
+ features. set_route_blinding_optional ( ) ;
975
+
976
+ let chanmon_cfgs = create_chanmon_cfgs ( 7 ) ;
977
+ let node_cfgs = create_node_cfgs ( 7 , & chanmon_cfgs) ;
978
+
979
+ * node_cfgs[ 1 ] . override_init_features . borrow_mut ( ) = Some ( features) ;
980
+
981
+ let node_chanmgrs = create_node_chanmgrs (
982
+ 7 , & node_cfgs, & [ None , Some ( accept_forward_cfg) , None , None , None , None , None ]
983
+ ) ;
984
+ let nodes = create_network ( 7 , & node_cfgs, & node_chanmgrs) ;
985
+
986
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) ;
987
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 10_000_000 , 1_000_000_000 ) ;
988
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 1_000_000_000 ) ;
989
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 4 , 10_000_000 , 1_000_000_000 ) ;
990
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 5 , 10_000_000 , 1_000_000_000 ) ;
991
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 4 , 10_000_000 , 1_000_000_000 ) ;
992
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 5 , 10_000_000 , 1_000_000_000 ) ;
993
+
994
+ // Introduce another potential introduction node, node[6], as a candidate
995
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 3 , 6 , 10_000_000 , 1_000_000_000 ) ;
996
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 6 , 10_000_000 , 1_000_000_000 ) ;
997
+ create_announced_chan_between_nodes_with_value ( & nodes, 4 , 6 , 10_000_000 , 1_000_000_000 ) ;
998
+ create_announced_chan_between_nodes_with_value ( & nodes, 5 , 6 , 10_000_000 , 1_000_000_000 ) ;
999
+
1000
+ let ( alice, bob, charlie, david) = ( & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ) ;
1001
+ let alice_id = alice. node . get_our_node_id ( ) ;
1002
+ let bob_id = bob. node . get_our_node_id ( ) ;
1003
+ let charlie_id = charlie. node . get_our_node_id ( ) ;
1004
+ let david_id = david. node . get_our_node_id ( ) ;
1005
+
1006
+ disconnect_peers ( alice, & [ charlie, david, & nodes[ 4 ] , & nodes[ 5 ] , & nodes[ 6 ] ] ) ;
1007
+ disconnect_peers ( david, & [ bob, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
1008
+
1009
+ let absolute_expiry = Duration :: from_secs ( u64:: MAX ) ;
1010
+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
1011
+ let refund = alice. node
1012
+ . create_refund_builder ( 10_000_000 , absolute_expiry, payment_id, Retry :: Attempts ( 0 ) , None )
1013
+ . unwrap ( )
1014
+ . build ( ) . unwrap ( ) ;
1015
+ assert_ne ! ( refund. payer_id( ) , alice_id) ;
1016
+ for path in refund. paths ( ) {
1017
+ assert_eq ! ( path. introduction_node, IntroductionNode :: NodeId ( bob_id) ) ;
1018
+ }
1019
+ expect_recent_payment ! ( alice, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
1020
+
1021
+ let _expected_invoice = david. node . request_refund_payment ( & refund) . unwrap ( ) ;
1022
+
1023
+ connect_peers ( david, bob) ;
1024
+
1025
+ let onion_message = david. onion_messenger . next_onion_message_for_peer ( bob_id) . unwrap ( ) ;
1026
+ bob. onion_messenger . handle_onion_message ( & david_id, & onion_message) ;
1027
+
1028
+ connect_peers ( alice, charlie) ;
1029
+
1030
+ let onion_message = bob. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
1031
+
1032
+ let ( _, reply_path) = extract_invoice ( alice, & onion_message) ;
1033
+ assert_eq ! ( reply_path. unwrap( ) . introduction_node, IntroductionNode :: NodeId ( charlie_id) ) ;
1034
+
1035
+ // Send, extract and verify the second Invoice Request message
1036
+ let onion_message = david. onion_messenger . next_onion_message_for_peer ( bob_id) . unwrap ( ) ;
1037
+ bob. onion_messenger . handle_onion_message ( & david_id, & onion_message) ;
1038
+
1039
+ let onion_message = bob. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
1040
+
1041
+ let ( _, reply_path) = extract_invoice ( alice, & onion_message) ;
1042
+ assert_eq ! ( reply_path. unwrap( ) . introduction_node, IntroductionNode :: NodeId ( nodes[ 6 ] . node. get_our_node_id( ) ) ) ;
1043
+ }
1044
+
881
1045
/// Checks that a deferred invoice can be paid asynchronously from an Event::InvoiceReceived.
882
1046
#[ test]
883
1047
fn pays_bolt12_invoice_asynchronously ( ) {
0 commit comments