@@ -568,6 +568,95 @@ fn creates_and_pays_for_offer_using_two_hop_blinded_path() {
568
568
expect_recent_payment ! ( david, RecentPaymentDetails :: Fulfilled , payment_id) ;
569
569
}
570
570
571
+ /// This test checks that when multiple potential introduction nodes are available for the payer,
572
+ /// multiple `invoice_request` messages are sent for the offer, each with a different `reply_path`.
573
+ #[ test]
574
+ fn send_invoice_requests_with_distinct_reply_path ( ) {
575
+ let mut accept_forward_cfg = test_default_channel_config ( ) ;
576
+ accept_forward_cfg. accept_forwards_to_priv_channels = true ;
577
+
578
+ let mut features = channelmanager:: provided_init_features ( & accept_forward_cfg) ;
579
+ features. set_onion_messages_optional ( ) ;
580
+ features. set_route_blinding_optional ( ) ;
581
+
582
+ let chanmon_cfgs = create_chanmon_cfgs ( 7 ) ;
583
+ let node_cfgs = create_node_cfgs ( 7 , & chanmon_cfgs) ;
584
+
585
+ * node_cfgs[ 1 ] . override_init_features . borrow_mut ( ) = Some ( features) ;
586
+
587
+ let node_chanmgrs = create_node_chanmgrs (
588
+ 7 , & node_cfgs, & [ None , Some ( accept_forward_cfg) , None , None , None , None , None ]
589
+ ) ;
590
+ let nodes = create_network ( 7 , & node_cfgs, & node_chanmgrs) ;
591
+
592
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) ;
593
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 2 , 3 , 10_000_000 , 1_000_000_000 ) ;
594
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 2 , 10_000_000 , 1_000_000_000 ) ;
595
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 4 , 10_000_000 , 1_000_000_000 ) ;
596
+ create_announced_chan_between_nodes_with_value ( & nodes, 1 , 5 , 10_000_000 , 1_000_000_000 ) ;
597
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 4 , 10_000_000 , 1_000_000_000 ) ;
598
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 5 , 10_000_000 , 1_000_000_000 ) ;
599
+
600
+ // Introduce another potential introduction node, node[6], as a candidate
601
+ create_unannounced_chan_between_nodes_with_value ( & nodes, 3 , 6 , 10_000_000 , 1_000_000_000 ) ;
602
+ create_announced_chan_between_nodes_with_value ( & nodes, 2 , 6 , 10_000_000 , 1_000_000_000 ) ;
603
+ create_announced_chan_between_nodes_with_value ( & nodes, 4 , 6 , 10_000_000 , 1_000_000_000 ) ;
604
+ create_announced_chan_between_nodes_with_value ( & nodes, 5 , 6 , 10_000_000 , 1_000_000_000 ) ;
605
+
606
+ let ( alice, bob, charlie, david) = ( & nodes[ 0 ] , & nodes[ 1 ] , & nodes[ 2 ] , & nodes[ 3 ] ) ;
607
+ let alice_id = alice. node . get_our_node_id ( ) ;
608
+ let bob_id = bob. node . get_our_node_id ( ) ;
609
+ let charlie_id = charlie. node . get_our_node_id ( ) ;
610
+ let david_id = david. node . get_our_node_id ( ) ;
611
+
612
+ disconnect_peers ( alice, & [ charlie, david, & nodes[ 4 ] , & nodes[ 5 ] , & nodes[ 6 ] ] ) ;
613
+ disconnect_peers ( david, & [ bob, & nodes[ 4 ] , & nodes[ 5 ] ] ) ;
614
+
615
+ let offer = alice. node
616
+ . create_offer_builder ( None )
617
+ . unwrap ( )
618
+ . amount_msats ( 10_000_000 )
619
+ . build ( ) . unwrap ( ) ;
620
+ assert_ne ! ( offer. signing_pubkey( ) , Some ( alice_id) ) ;
621
+ assert ! ( !offer. paths( ) . is_empty( ) ) ;
622
+ for path in offer. paths ( ) {
623
+ assert_eq ! ( path. introduction_node, IntroductionNode :: NodeId ( bob_id) ) ;
624
+ }
625
+
626
+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
627
+ david. node . pay_for_offer ( & offer, None , None , None , payment_id, Retry :: Attempts ( 0 ) , None )
628
+ . unwrap ( ) ;
629
+ expect_recent_payment ! ( david, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
630
+ connect_peers ( david, bob) ;
631
+
632
+ // Send, extract and verify the first Invoice Request message
633
+ let onion_message = david. onion_messenger . next_onion_message_for_peer ( bob_id) . unwrap ( ) ;
634
+ bob. onion_messenger . handle_onion_message ( & david_id, & onion_message) ;
635
+
636
+ connect_peers ( alice, charlie) ;
637
+
638
+ let onion_message = bob. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
639
+ alice. onion_messenger . handle_onion_message ( & bob_id, & onion_message) ;
640
+
641
+ let ( invoice_request, reply_path) = extract_invoice_request ( alice, & onion_message) ;
642
+ assert_eq ! ( invoice_request. amount_msats( ) , None ) ;
643
+ assert_ne ! ( invoice_request. payer_id( ) , david_id) ;
644
+ assert_eq ! ( reply_path. introduction_node, IntroductionNode :: NodeId ( charlie_id) ) ;
645
+
646
+ // Send, extract and verify the second Invoice Request message
647
+ let onion_message = david. onion_messenger . next_onion_message_for_peer ( bob_id) . unwrap ( ) ;
648
+ bob. onion_messenger . handle_onion_message ( & david_id, & onion_message) ;
649
+
650
+ let onion_message = bob. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
651
+ alice. onion_messenger . handle_onion_message ( & bob_id, & onion_message) ;
652
+
653
+ let ( invoice_request, reply_path) = extract_invoice_request ( alice, & onion_message) ;
654
+
655
+ assert_eq ! ( invoice_request. amount_msats( ) , None ) ;
656
+ assert_ne ! ( invoice_request. payer_id( ) , david_id) ;
657
+ assert_eq ! ( reply_path. introduction_node, IntroductionNode :: NodeId ( nodes[ 6 ] . node. get_our_node_id( ) ) ) ;
658
+ }
659
+
571
660
/// Checks that a refund can be paid through blinded paths and that ephemeral pubkeys are used
572
661
/// rather than exposing a node's pubkey.
573
662
#[ test]
0 commit comments