@@ -727,6 +727,81 @@ fn creates_and_pays_for_offer_using_one_hop_blinded_path() {
727
727
expect_recent_payment ! ( bob, RecentPaymentDetails :: Fulfilled , payment_id) ;
728
728
}
729
729
730
+ /// Verifies that the invoice request message can be retried if it fails to reach the
731
+ /// payee on the first attempt.
732
+ #[ test]
733
+ fn creates_and_pays_for_offer_with_retry ( ) {
734
+ let chanmon_cfgs = create_chanmon_cfgs ( 2 ) ;
735
+ let node_cfgs = create_node_cfgs ( 2 , & chanmon_cfgs) ;
736
+ let node_chanmgrs = create_node_chanmgrs ( 2 , & node_cfgs, & [ None , None ] ) ;
737
+ let nodes = create_network ( 2 , & node_cfgs, & node_chanmgrs) ;
738
+
739
+ create_announced_chan_between_nodes_with_value ( & nodes, 0 , 1 , 10_000_000 , 1_000_000_000 ) ;
740
+
741
+ let alice = & nodes[ 0 ] ;
742
+ let alice_id = alice. node . get_our_node_id ( ) ;
743
+ let bob = & nodes[ 1 ] ;
744
+ let bob_id = bob. node . get_our_node_id ( ) ;
745
+
746
+ let offer = alice. node
747
+ . create_offer_builder ( None ) . unwrap ( )
748
+ . amount_msats ( 10_000_000 )
749
+ . build ( ) . unwrap ( ) ;
750
+ assert_ne ! ( offer. signing_pubkey( ) , Some ( alice_id) ) ;
751
+ assert ! ( !offer. paths( ) . is_empty( ) ) ;
752
+ for path in offer. paths ( ) {
753
+ assert_eq ! ( path. introduction_node, IntroductionNode :: NodeId ( alice_id) ) ;
754
+ }
755
+ let payment_id = PaymentId ( [ 1 ; 32 ] ) ;
756
+ bob. node . pay_for_offer ( & offer, None , None , None , payment_id, Retry :: Attempts ( 0 ) , None ) . unwrap ( ) ;
757
+ expect_recent_payment ! ( bob, RecentPaymentDetails :: AwaitingInvoice , payment_id) ;
758
+
759
+ let _lost_onion_message = bob. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
760
+
761
+ // Simulate a scenario where the original onion_message is lost before reaching Alice.
762
+ // Use handle_message_received to regenerate the message.
763
+ bob. node . handle_message_received ( ) ;
764
+ let onion_message = bob. onion_messenger . next_onion_message_for_peer ( alice_id) . unwrap ( ) ;
765
+
766
+ alice. onion_messenger . handle_onion_message ( & bob_id, & onion_message) ;
767
+
768
+ let ( invoice_request, reply_path) = extract_invoice_request ( alice, & onion_message) ;
769
+ let payment_context = PaymentContext :: Bolt12Offer ( Bolt12OfferContext {
770
+ offer_id : offer. id ( ) ,
771
+ invoice_request : InvoiceRequestFields {
772
+ payer_id : invoice_request. payer_id ( ) ,
773
+ quantity : None ,
774
+ payer_note_truncated : None ,
775
+ } ,
776
+ } ) ;
777
+ assert_eq ! ( invoice_request. amount_msats( ) , None ) ;
778
+ assert_ne ! ( invoice_request. payer_id( ) , bob_id) ;
779
+ assert_eq ! ( reply_path. introduction_node, IntroductionNode :: NodeId ( bob_id) ) ;
780
+ let onion_message = alice. onion_messenger . next_onion_message_for_peer ( bob_id) . unwrap ( ) ;
781
+ bob. onion_messenger . handle_onion_message ( & alice_id, & onion_message) ;
782
+
783
+ // Expect no more OffersMessage to be enqueued by this point, even after calling
784
+ // handle_message_received.
785
+ bob. node . handle_message_received ( ) ;
786
+
787
+ match bob. onion_messenger . next_onion_message_for_peer ( alice_id) {
788
+ Some ( _) => panic ! ( "Unexpected message enqueued after retry tick." ) ,
789
+ None => { } ,
790
+ } ;
791
+
792
+ let ( invoice, _) = extract_invoice ( bob, & onion_message) ;
793
+ assert_eq ! ( invoice. amount_msats( ) , 10_000_000 ) ;
794
+ assert_ne ! ( invoice. signing_pubkey( ) , alice_id) ;
795
+ assert ! ( !invoice. payment_paths( ) . is_empty( ) ) ;
796
+ for ( _, path) in invoice. payment_paths ( ) {
797
+ assert_eq ! ( path. introduction_node, IntroductionNode :: NodeId ( alice_id) ) ;
798
+ }
799
+ route_bolt12_payment ( bob, & [ alice] , & invoice) ;
800
+ expect_recent_payment ! ( bob, RecentPaymentDetails :: Pending , payment_id) ;
801
+ claim_bolt12_payment ( bob, & [ alice] , payment_context) ;
802
+ expect_recent_payment ! ( bob, RecentPaymentDetails :: Fulfilled , payment_id) ;
803
+ }
804
+
730
805
/// Checks that a refund can be paid through a one-hop blinded path and that ephemeral pubkeys are
731
806
/// used rather than exposing a node's pubkey. However, the node's pubkey is still used as the
732
807
/// introduction node of the blinded path.
0 commit comments