@@ -851,7 +851,7 @@ impl OutboundPayments {
851
851
entropy_source : & ES , node_signer : & NS , node_id_lookup : & NL ,
852
852
secp_ctx : & Secp256k1 < secp256k1:: All > , best_block_height : u32 , logger : & L ,
853
853
pending_events : & Mutex < VecDeque < ( events:: Event , Option < EventCompletionAction > ) > > ,
854
- send_payment_along_path : SP ,
854
+ send_payment_along_path : SP , with_manual_handling : bool
855
855
) -> Result < ( ) , Bolt12PaymentError >
856
856
where
857
857
R :: Target : Router ,
@@ -862,26 +862,15 @@ impl OutboundPayments {
862
862
IH : Fn ( ) -> InFlightHtlcs ,
863
863
SP : Fn ( SendAlongPathArgs ) -> Result < ( ) , APIError > ,
864
864
{
865
- let payment_hash = invoice. payment_hash ( ) ;
866
- let params_config;
867
- let retry_strategy;
868
- match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
869
- hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
870
- PendingOutboundPayment :: AwaitingInvoice {
871
- retry_strategy : retry, route_params_config, ..
872
- } => {
873
- retry_strategy = * retry;
874
- params_config = * route_params_config;
875
- * entry. into_mut ( ) = PendingOutboundPayment :: InvoiceReceived {
876
- payment_hash,
877
- retry_strategy : * retry,
878
- route_params_config : * route_params_config,
879
- } ;
880
- } ,
881
- _ => return Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
882
- } ,
883
- hash_map:: Entry :: Vacant ( _) => return Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
884
- }
865
+ // When manual invoice handling is enabled, the corresponding `PendingOutboundPayment` entry
866
+ // is already updated at the time the invoice is received. This ensures that `InvoiceReceived`
867
+ // event generation remains idempotent, even if the same invoice is received again before the
868
+ // event is handled by the user.
869
+ let ( payment_hash, retry_strategy, params_config) = if with_manual_handling {
870
+ self . received_invoice_details ( invoice, payment_id) ?
871
+ } else {
872
+ self . mark_invoice_received_and_get_details ( invoice, payment_id) ?
873
+ } ;
885
874
886
875
if invoice. invoice_features ( ) . requires_unknown_bits_from ( & features) {
887
876
self . abandon_payment (
@@ -1789,6 +1778,53 @@ impl OutboundPayments {
1789
1778
}
1790
1779
}
1791
1780
1781
+ pub ( super ) fn mark_invoice_received (
1782
+ & self , invoice : & Bolt12Invoice , payment_id : PaymentId
1783
+ ) -> Result < ( ) , Bolt12PaymentError > {
1784
+ self . mark_invoice_received_and_get_details ( invoice, payment_id) . map ( |_| ( ) )
1785
+ }
1786
+
1787
+ fn mark_invoice_received_and_get_details (
1788
+ & self , invoice : & Bolt12Invoice , payment_id : PaymentId
1789
+ ) -> Result < ( PaymentHash , Retry , RouteParametersConfig ) , Bolt12PaymentError > {
1790
+ match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
1791
+ hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
1792
+ PendingOutboundPayment :: AwaitingInvoice {
1793
+ retry_strategy : retry, route_params_config, ..
1794
+ } => {
1795
+ let payment_hash = invoice. payment_hash ( ) ;
1796
+ let retry = * retry;
1797
+ let config = * route_params_config;
1798
+ * entry. into_mut ( ) = PendingOutboundPayment :: InvoiceReceived {
1799
+ payment_hash,
1800
+ retry_strategy : retry,
1801
+ route_params_config : config,
1802
+ } ;
1803
+
1804
+ Ok ( ( payment_hash, retry, config) )
1805
+ } ,
1806
+ _ => Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
1807
+ } ,
1808
+ hash_map:: Entry :: Vacant ( _) => Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
1809
+ }
1810
+ }
1811
+
1812
+ fn received_invoice_details (
1813
+ & self , invoice : & Bolt12Invoice , payment_id : PaymentId ,
1814
+ ) -> Result < ( PaymentHash , Retry , RouteParametersConfig ) , Bolt12PaymentError > {
1815
+ match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
1816
+ hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
1817
+ PendingOutboundPayment :: InvoiceReceived {
1818
+ retry_strategy, route_params_config, ..
1819
+ } => {
1820
+ Ok ( ( invoice. payment_hash ( ) , * retry_strategy, * route_params_config) )
1821
+ } ,
1822
+ _ => Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
1823
+ } ,
1824
+ hash_map:: Entry :: Vacant ( _) => Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
1825
+ }
1826
+ }
1827
+
1792
1828
fn pay_route_internal < NS : Deref , F > (
1793
1829
& self , route : & Route , payment_hash : PaymentHash , recipient_onion : & RecipientOnionFields ,
1794
1830
keysend_preimage : Option < PaymentPreimage > , invoice_request : Option < & InvoiceRequest > ,
@@ -2868,7 +2904,7 @@ mod tests {
2868
2904
outbound_payments. send_payment_for_bolt12_invoice(
2869
2905
& invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
2870
2906
|| InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
2871
- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
2907
+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
2872
2908
) ,
2873
2909
Err ( Bolt12PaymentError :: SendingFailed ( RetryableSendFailure :: PaymentExpired ) ) ,
2874
2910
) ;
@@ -2930,7 +2966,7 @@ mod tests {
2930
2966
outbound_payments. send_payment_for_bolt12_invoice(
2931
2967
& invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
2932
2968
|| InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
2933
- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
2969
+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
2934
2970
) ,
2935
2971
Err ( Bolt12PaymentError :: SendingFailed ( RetryableSendFailure :: RouteNotFound ) ) ,
2936
2972
) ;
@@ -3005,7 +3041,7 @@ mod tests {
3005
3041
outbound_payments. send_payment_for_bolt12_invoice(
3006
3042
& invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
3007
3043
|| InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
3008
- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
3044
+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
3009
3045
) ,
3010
3046
Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
3011
3047
) ;
@@ -3025,7 +3061,7 @@ mod tests {
3025
3061
outbound_payments. send_payment_for_bolt12_invoice(
3026
3062
& invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
3027
3063
|| InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
3028
- & secp_ctx, 0 , &&logger, & pending_events, |_| Ok ( ( ) )
3064
+ & secp_ctx, 0 , &&logger, & pending_events, |_| Ok ( ( ) ) , false
3029
3065
) ,
3030
3066
Ok ( ( ) ) ,
3031
3067
) ;
@@ -3036,7 +3072,7 @@ mod tests {
3036
3072
outbound_payments. send_payment_for_bolt12_invoice(
3037
3073
& invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
3038
3074
|| InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
3039
- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
3075
+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
3040
3076
) ,
3041
3077
Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
3042
3078
) ;
0 commit comments