@@ -851,7 +851,7 @@ impl OutboundPayments {
851851 entropy_source : & ES , node_signer : & NS , node_id_lookup : & NL ,
852852 secp_ctx : & Secp256k1 < secp256k1:: All > , best_block_height : u32 , logger : & L ,
853853 pending_events : & Mutex < VecDeque < ( events:: Event , Option < EventCompletionAction > ) > > ,
854- send_payment_along_path : SP ,
854+ send_payment_along_path : SP , with_manual_handling : bool
855855 ) -> Result < ( ) , Bolt12PaymentError >
856856 where
857857 R :: Target : Router ,
@@ -863,25 +863,8 @@ impl OutboundPayments {
863863 SP : Fn ( SendAlongPathArgs ) -> Result < ( ) , APIError > ,
864864 {
865865 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- }
866+ let ( retry_strategy, params_config) = self
867+ . mark_invoice_received ( payment_id, payment_hash, with_manual_handling) ?;
885868
886869 if invoice. invoice_features ( ) . requires_unknown_bits_from ( & features) {
887870 self . abandon_payment (
@@ -1789,6 +1772,54 @@ impl OutboundPayments {
17891772 }
17901773 }
17911774
1775+ fn mark_invoice_received (
1776+ & self , payment_id : PaymentId , payment_hash : PaymentHash , with_manual_handling : bool
1777+ ) -> Result < ( Retry , RouteParametersConfig ) , Bolt12PaymentError > {
1778+ let retry_strategy;
1779+ let params_config;
1780+
1781+ if with_manual_handling {
1782+ // When manual invoice handling is enabled, the corresponding `PendingOutboundPayment` entry
1783+ // is already updated at the time the invoice is received. This ensures that `InvoiceReceived`
1784+ // event generation remains idempotent, even if the same invoice is received again before the
1785+ // current one is handled by the user.
1786+ match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
1787+ hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
1788+ PendingOutboundPayment :: InvoiceReceived {
1789+ retry_strategy : retry, route_params_config, ..
1790+ } => {
1791+ retry_strategy = * retry;
1792+ params_config = * route_params_config;
1793+ } ,
1794+ _ => return Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
1795+ } ,
1796+ hash_map:: Entry :: Vacant ( _) => return Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
1797+ }
1798+ } else {
1799+ match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
1800+ hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
1801+ PendingOutboundPayment :: AwaitingInvoice {
1802+ retry_strategy : retry, route_params_config, ..
1803+ } => {
1804+ retry_strategy = * retry;
1805+ params_config = * route_params_config;
1806+
1807+ * entry. into_mut ( ) = PendingOutboundPayment :: InvoiceReceived {
1808+ payment_hash,
1809+ retry_strategy : * retry,
1810+ route_params_config : * route_params_config,
1811+ } ;
1812+ } ,
1813+ _ => return Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
1814+ } ,
1815+ hash_map:: Entry :: Vacant ( _) => return Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
1816+ }
1817+ }
1818+
1819+ Ok ( ( retry_strategy, params_config) )
1820+
1821+ }
1822+
17921823 fn pay_route_internal < NS : Deref , F > (
17931824 & self , route : & Route , payment_hash : PaymentHash , recipient_onion : & RecipientOnionFields ,
17941825 keysend_preimage : Option < PaymentPreimage > , invoice_request : Option < & InvoiceRequest > ,
@@ -2868,7 +2899,7 @@ mod tests {
28682899 outbound_payments. send_payment_for_bolt12_invoice(
28692900 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
28702901 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
2871- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
2902+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
28722903 ) ,
28732904 Err ( Bolt12PaymentError :: SendingFailed ( RetryableSendFailure :: PaymentExpired ) ) ,
28742905 ) ;
@@ -2930,7 +2961,7 @@ mod tests {
29302961 outbound_payments. send_payment_for_bolt12_invoice(
29312962 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
29322963 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
2933- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
2964+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
29342965 ) ,
29352966 Err ( Bolt12PaymentError :: SendingFailed ( RetryableSendFailure :: RouteNotFound ) ) ,
29362967 ) ;
@@ -3005,7 +3036,7 @@ mod tests {
30053036 outbound_payments. send_payment_for_bolt12_invoice(
30063037 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
30073038 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
3008- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
3039+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
30093040 ) ,
30103041 Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
30113042 ) ;
@@ -3025,7 +3056,7 @@ mod tests {
30253056 outbound_payments. send_payment_for_bolt12_invoice(
30263057 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
30273058 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
3028- & secp_ctx, 0 , &&logger, & pending_events, |_| Ok ( ( ) )
3059+ & secp_ctx, 0 , &&logger, & pending_events, |_| Ok ( ( ) ) , false
30293060 ) ,
30303061 Ok ( ( ) ) ,
30313062 ) ;
@@ -3036,7 +3067,7 @@ mod tests {
30363067 outbound_payments. send_payment_for_bolt12_invoice(
30373068 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
30383069 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
3039- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
3070+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
30403071 ) ,
30413072 Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
30423073 ) ;
0 commit comments