@@ -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 ,
@@ -862,26 +862,15 @@ impl OutboundPayments {
862862 IH : Fn ( ) -> InFlightHtlcs ,
863863 SP : Fn ( SendAlongPathArgs ) -> Result < ( ) , APIError > ,
864864 {
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+ } ;
885874
886875 if invoice. invoice_features ( ) . requires_unknown_bits_from ( & features) {
887876 self . abandon_payment (
@@ -1789,6 +1778,53 @@ impl OutboundPayments {
17891778 }
17901779 }
17911780
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+
17921828 fn pay_route_internal < NS : Deref , F > (
17931829 & self , route : & Route , payment_hash : PaymentHash , recipient_onion : & RecipientOnionFields ,
17941830 keysend_preimage : Option < PaymentPreimage > , invoice_request : Option < & InvoiceRequest > ,
@@ -2868,7 +2904,7 @@ mod tests {
28682904 outbound_payments. send_payment_for_bolt12_invoice(
28692905 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
28702906 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
2871- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
2907+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
28722908 ) ,
28732909 Err ( Bolt12PaymentError :: SendingFailed ( RetryableSendFailure :: PaymentExpired ) ) ,
28742910 ) ;
@@ -2930,7 +2966,7 @@ mod tests {
29302966 outbound_payments. send_payment_for_bolt12_invoice(
29312967 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
29322968 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
2933- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
2969+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
29342970 ) ,
29352971 Err ( Bolt12PaymentError :: SendingFailed ( RetryableSendFailure :: RouteNotFound ) ) ,
29362972 ) ;
@@ -3005,7 +3041,7 @@ mod tests {
30053041 outbound_payments. send_payment_for_bolt12_invoice(
30063042 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
30073043 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
3008- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
3044+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
30093045 ) ,
30103046 Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
30113047 ) ;
@@ -3025,7 +3061,7 @@ mod tests {
30253061 outbound_payments. send_payment_for_bolt12_invoice(
30263062 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
30273063 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
3028- & secp_ctx, 0 , &&logger, & pending_events, |_| Ok ( ( ) )
3064+ & secp_ctx, 0 , &&logger, & pending_events, |_| Ok ( ( ) ) , false
30293065 ) ,
30303066 Ok ( ( ) ) ,
30313067 ) ;
@@ -3036,7 +3072,7 @@ mod tests {
30363072 outbound_payments. send_payment_for_bolt12_invoice(
30373073 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
30383074 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
3039- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
3075+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
30403076 ) ,
30413077 Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
30423078 ) ;
0 commit comments