@@ -72,9 +72,9 @@ pub(crate) enum PendingOutboundPayment {
72
72
route_params_config : RouteParametersConfig ,
73
73
retryable_invoice_request : Option < RetryableInvoiceRequest >
74
74
} ,
75
- // This state will never be persisted to disk because we transition from `AwaitingInvoice` to
76
- // `Retryable` atomically within the `ChannelManager::total_consistency_lock`. Useful to avoid
77
- // holding the `OutboundPayments::pending_outbound_payments` lock during pathfinding.
75
+ // Represents the state after the invoice has been received, transitioning from the corresponding
76
+ // `AwaitingInvoice` state.
77
+ // Helps avoid holding the `OutboundPayments::pending_outbound_payments` lock during pathfinding.
78
78
InvoiceReceived {
79
79
payment_hash : PaymentHash ,
80
80
retry_strategy : Retry ,
@@ -931,26 +931,9 @@ impl OutboundPayments {
931
931
IH : Fn ( ) -> InFlightHtlcs ,
932
932
SP : Fn ( SendAlongPathArgs ) -> Result < ( ) , APIError > ,
933
933
{
934
- let payment_hash = invoice. payment_hash ( ) ;
935
- let params_config;
936
- let retry_strategy;
937
- match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
938
- hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
939
- PendingOutboundPayment :: AwaitingInvoice {
940
- retry_strategy : retry, route_params_config, ..
941
- } => {
942
- retry_strategy = * retry;
943
- params_config = * route_params_config;
944
- * entry. into_mut ( ) = PendingOutboundPayment :: InvoiceReceived {
945
- payment_hash,
946
- retry_strategy : * retry,
947
- route_params_config : * route_params_config,
948
- } ;
949
- } ,
950
- _ => return Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
951
- } ,
952
- hash_map:: Entry :: Vacant ( _) => return Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
953
- }
934
+
935
+ let ( payment_hash, retry_strategy, params_config, _) = self
936
+ . mark_invoice_received_and_get_details ( invoice, payment_id) ?;
954
937
955
938
if invoice. invoice_features ( ) . requires_unknown_bits_from ( & features) {
956
939
self . abandon_payment (
@@ -1863,6 +1846,51 @@ impl OutboundPayments {
1863
1846
}
1864
1847
}
1865
1848
1849
+ pub ( super ) fn mark_invoice_received (
1850
+ & self , invoice : & Bolt12Invoice , payment_id : PaymentId
1851
+ ) -> Result < ( ) , Bolt12PaymentError > {
1852
+ self . mark_invoice_received_and_get_details ( invoice, payment_id)
1853
+ . and_then ( |( _, _, _, is_newly_marked) | {
1854
+ is_newly_marked
1855
+ . then_some ( ( ) )
1856
+ . ok_or ( Bolt12PaymentError :: DuplicateInvoice )
1857
+ } )
1858
+ }
1859
+
1860
+ fn mark_invoice_received_and_get_details (
1861
+ & self , invoice : & Bolt12Invoice , payment_id : PaymentId
1862
+ ) -> Result < ( PaymentHash , Retry , RouteParametersConfig , bool ) , Bolt12PaymentError > {
1863
+ match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
1864
+ hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
1865
+ PendingOutboundPayment :: AwaitingInvoice {
1866
+ retry_strategy : retry, route_params_config, ..
1867
+ } => {
1868
+ let payment_hash = invoice. payment_hash ( ) ;
1869
+ let retry = * retry;
1870
+ let config = * route_params_config;
1871
+ * entry. into_mut ( ) = PendingOutboundPayment :: InvoiceReceived {
1872
+ payment_hash,
1873
+ retry_strategy : retry,
1874
+ route_params_config : config,
1875
+ } ;
1876
+
1877
+ Ok ( ( payment_hash, retry, config, true ) )
1878
+ } ,
1879
+ // When manual invoice handling is enabled, the corresponding `PendingOutboundPayment` entry
1880
+ // is already updated at the time the invoice is received. This ensures that `InvoiceReceived`
1881
+ // event generation remains idempotent, even if the same invoice is received again before the
1882
+ // event is handled by the user.
1883
+ PendingOutboundPayment :: InvoiceReceived {
1884
+ retry_strategy, route_params_config, ..
1885
+ } => {
1886
+ Ok ( ( invoice. payment_hash ( ) , * retry_strategy, * route_params_config, false ) )
1887
+ } ,
1888
+ _ => Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
1889
+ } ,
1890
+ hash_map:: Entry :: Vacant ( _) => Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
1891
+ }
1892
+ }
1893
+
1866
1894
fn pay_route_internal < NS : Deref , F > (
1867
1895
& self , route : & Route , payment_hash : PaymentHash , recipient_onion : & RecipientOnionFields ,
1868
1896
keysend_preimage : Option < PaymentPreimage > , invoice_request : Option < & InvoiceRequest > ,
0 commit comments