@@ -73,9 +73,9 @@ pub(crate) enum PendingOutboundPayment {
7373 route_params_config : RouteParametersConfig ,
7474 retryable_invoice_request : Option < RetryableInvoiceRequest >
7575 } ,
76- // This state will never be persisted to disk because we transition from `AwaitingInvoice` to
77- // `Retryable` atomically within the `ChannelManager::total_consistency_lock`. Useful to avoid
78- // holding the `OutboundPayments::pending_outbound_payments` lock during pathfinding.
76+ // Represents the state after the invoice has been received, transitioning from the corresponding
77+ // `AwaitingInvoice` state.
78+ // Helps avoid holding the `OutboundPayments::pending_outbound_payments` lock during pathfinding.
7979 InvoiceReceived {
8080 payment_hash : PaymentHash ,
8181 retry_strategy : Retry ,
@@ -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 , with_manual_handling : bool
854+ send_payment_along_path : SP ,
855855 ) -> Result < ( ) , Bolt12PaymentError >
856856 where
857857 R :: Target : Router ,
@@ -862,15 +862,9 @@ impl OutboundPayments {
862862 IH : Fn ( ) -> InFlightHtlcs ,
863863 SP : Fn ( SendAlongPathArgs ) -> Result < ( ) , APIError > ,
864864 {
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- } ;
865+
866+ let ( payment_hash, retry_strategy, params_config, _) = self
867+ . get_received_invoice_details ( invoice, payment_id) ?;
874868
875869 if invoice. invoice_features ( ) . requires_unknown_bits_from ( & features) {
876870 self . abandon_payment (
@@ -1781,12 +1775,17 @@ impl OutboundPayments {
17811775 pub ( super ) fn mark_invoice_received (
17821776 & self , invoice : & Bolt12Invoice , payment_id : PaymentId
17831777 ) -> Result < ( ) , Bolt12PaymentError > {
1784- self . mark_invoice_received_and_get_details ( invoice, payment_id) . map ( |_| ( ) )
1778+ self . get_received_invoice_details ( invoice, payment_id)
1779+ . and_then ( |( _, _, _, invoice_marked_received) | {
1780+ invoice_marked_received
1781+ . then_some ( ( ) )
1782+ . ok_or ( Bolt12PaymentError :: DuplicateInvoice )
1783+ } )
17851784 }
17861785
1787- fn mark_invoice_received_and_get_details (
1786+ fn get_received_invoice_details (
17881787 & self , invoice : & Bolt12Invoice , payment_id : PaymentId
1789- ) -> Result < ( PaymentHash , Retry , RouteParametersConfig ) , Bolt12PaymentError > {
1788+ ) -> Result < ( PaymentHash , Retry , RouteParametersConfig , bool ) , Bolt12PaymentError > {
17901789 match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
17911790 hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
17921791 PendingOutboundPayment :: AwaitingInvoice {
@@ -1801,23 +1800,16 @@ impl OutboundPayments {
18011800 route_params_config : config,
18021801 } ;
18031802
1804- Ok ( ( payment_hash, retry, config) )
1803+ Ok ( ( payment_hash, retry, config, true ) )
18051804 } ,
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 ( ) {
1805+ // When manual invoice handling is enabled, the corresponding `PendingOutboundPayment` entry
1806+ // is already updated at the time the invoice is received. This ensures that `InvoiceReceived`
1807+ // event generation remains idempotent, even if the same invoice is received again before the
1808+ // event is handled by the user.
18171809 PendingOutboundPayment :: InvoiceReceived {
18181810 retry_strategy, route_params_config, ..
18191811 } => {
1820- Ok ( ( invoice. payment_hash ( ) , * retry_strategy, * route_params_config) )
1812+ Ok ( ( invoice. payment_hash ( ) , * retry_strategy, * route_params_config, false ) )
18211813 } ,
18221814 _ => Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
18231815 } ,
@@ -2904,7 +2896,7 @@ mod tests {
29042896 outbound_payments. send_payment_for_bolt12_invoice(
29052897 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
29062898 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
2907- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
2899+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
29082900 ) ,
29092901 Err ( Bolt12PaymentError :: SendingFailed ( RetryableSendFailure :: PaymentExpired ) ) ,
29102902 ) ;
@@ -2966,7 +2958,7 @@ mod tests {
29662958 outbound_payments. send_payment_for_bolt12_invoice(
29672959 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
29682960 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
2969- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
2961+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
29702962 ) ,
29712963 Err ( Bolt12PaymentError :: SendingFailed ( RetryableSendFailure :: RouteNotFound ) ) ,
29722964 ) ;
@@ -3041,7 +3033,7 @@ mod tests {
30413033 outbound_payments. send_payment_for_bolt12_invoice(
30423034 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
30433035 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
3044- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
3036+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
30453037 ) ,
30463038 Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
30473039 ) ;
@@ -3061,7 +3053,7 @@ mod tests {
30613053 outbound_payments. send_payment_for_bolt12_invoice(
30623054 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
30633055 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
3064- & secp_ctx, 0 , &&logger, & pending_events, |_| Ok ( ( ) ) , false
3056+ & secp_ctx, 0 , &&logger, & pending_events, |_| Ok ( ( ) )
30653057 ) ,
30663058 Ok ( ( ) ) ,
30673059 ) ;
@@ -3072,7 +3064,7 @@ mod tests {
30723064 outbound_payments. send_payment_for_bolt12_invoice(
30733065 & invoice, payment_id, &&router, vec![ ] , Bolt12InvoiceFeatures :: empty( ) ,
30743066 || InFlightHtlcs :: new( ) , &&keys_manager, &&keys_manager, & EmptyNodeIdLookUp { } ,
3075- & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( ) , false
3067+ & secp_ctx, 0 , &&logger, & pending_events, |_| panic!( )
30763068 ) ,
30773069 Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
30783070 ) ;
0 commit comments