@@ -73,9 +73,9 @@ pub(crate) enum PendingOutboundPayment {
73
73
route_params_config : RouteParametersConfig ,
74
74
retryable_invoice_request : Option < RetryableInvoiceRequest >
75
75
} ,
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.
79
79
InvoiceReceived {
80
80
payment_hash : PaymentHash ,
81
81
retry_strategy : Retry ,
@@ -862,26 +862,9 @@ 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
+
866
+ let ( payment_hash, retry_strategy, params_config, _) = self
867
+ . mark_invoice_received_and_get_details ( invoice, payment_id) ?;
885
868
886
869
if invoice. invoice_features ( ) . requires_unknown_bits_from ( & features) {
887
870
self . abandon_payment (
@@ -1789,6 +1772,51 @@ impl OutboundPayments {
1789
1772
}
1790
1773
}
1791
1774
1775
+ pub ( super ) fn mark_invoice_received (
1776
+ & self , invoice : & Bolt12Invoice , payment_id : PaymentId
1777
+ ) -> Result < ( ) , Bolt12PaymentError > {
1778
+ self . mark_invoice_received_and_get_details ( invoice, payment_id)
1779
+ . and_then ( |( _, _, _, is_newly_marked) | {
1780
+ is_newly_marked
1781
+ . then_some ( ( ) )
1782
+ . ok_or ( Bolt12PaymentError :: DuplicateInvoice )
1783
+ } )
1784
+ }
1785
+
1786
+ fn mark_invoice_received_and_get_details (
1787
+ & self , invoice : & Bolt12Invoice , payment_id : PaymentId
1788
+ ) -> Result < ( PaymentHash , Retry , RouteParametersConfig , bool ) , Bolt12PaymentError > {
1789
+ match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
1790
+ hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
1791
+ PendingOutboundPayment :: AwaitingInvoice {
1792
+ retry_strategy : retry, route_params_config, ..
1793
+ } => {
1794
+ let payment_hash = invoice. payment_hash ( ) ;
1795
+ let retry = * retry;
1796
+ let config = * route_params_config;
1797
+ * entry. into_mut ( ) = PendingOutboundPayment :: InvoiceReceived {
1798
+ payment_hash,
1799
+ retry_strategy : retry,
1800
+ route_params_config : config,
1801
+ } ;
1802
+
1803
+ Ok ( ( payment_hash, retry, config, true ) )
1804
+ } ,
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.
1809
+ PendingOutboundPayment :: InvoiceReceived {
1810
+ retry_strategy, route_params_config, ..
1811
+ } => {
1812
+ Ok ( ( invoice. payment_hash ( ) , * retry_strategy, * route_params_config, false ) )
1813
+ } ,
1814
+ _ => Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
1815
+ } ,
1816
+ hash_map:: Entry :: Vacant ( _) => Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
1817
+ }
1818
+ }
1819
+
1792
1820
fn pay_route_internal < NS : Deref , F > (
1793
1821
& self , route : & Route , payment_hash : PaymentHash , recipient_onion : & RecipientOnionFields ,
1794
1822
keysend_preimage : Option < PaymentPreimage > , invoice_request : Option < & InvoiceRequest > ,
0 commit comments