@@ -73,9 +73,9 @@ pub(crate) enum PendingOutboundPayment {
73
73
max_total_routing_fee_msat : Option < u64 > ,
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 ,
@@ -833,26 +833,8 @@ impl OutboundPayments {
833
833
IH : Fn ( ) -> InFlightHtlcs ,
834
834
SP : Fn ( SendAlongPathArgs ) -> Result < ( ) , APIError > ,
835
835
{
836
- let payment_hash = invoice. payment_hash ( ) ;
837
- let max_total_routing_fee_msat;
838
- let retry_strategy;
839
- match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
840
- hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
841
- PendingOutboundPayment :: AwaitingInvoice {
842
- retry_strategy : retry, max_total_routing_fee_msat : max_total_fee, ..
843
- } => {
844
- retry_strategy = * retry;
845
- max_total_routing_fee_msat = * max_total_fee;
846
- * entry. into_mut ( ) = PendingOutboundPayment :: InvoiceReceived {
847
- payment_hash,
848
- retry_strategy : * retry,
849
- max_total_routing_fee_msat,
850
- } ;
851
- } ,
852
- _ => return Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
853
- } ,
854
- hash_map:: Entry :: Vacant ( _) => return Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
855
- }
836
+ let ( payment_hash, retry_strategy, max_total_routing_fee_msat, _) = self
837
+ . mark_invoice_received_and_get_details ( invoice, payment_id) ?;
856
838
857
839
if invoice. invoice_features ( ) . requires_unknown_bits_from ( & features) {
858
840
self . abandon_payment (
@@ -1754,6 +1736,51 @@ impl OutboundPayments {
1754
1736
}
1755
1737
}
1756
1738
1739
+ pub ( super ) fn mark_invoice_received (
1740
+ & self , invoice : & Bolt12Invoice , payment_id : PaymentId
1741
+ ) -> Result < ( ) , Bolt12PaymentError > {
1742
+ self . mark_invoice_received_and_get_details ( invoice, payment_id)
1743
+ . and_then ( |( _, _, _, is_newly_marked) | {
1744
+ is_newly_marked
1745
+ . then_some ( ( ) )
1746
+ . ok_or ( Bolt12PaymentError :: DuplicateInvoice )
1747
+ } )
1748
+ }
1749
+
1750
+ fn mark_invoice_received_and_get_details (
1751
+ & self , invoice : & Bolt12Invoice , payment_id : PaymentId
1752
+ ) -> Result < ( PaymentHash , Retry , Option < u64 > , bool ) , Bolt12PaymentError > {
1753
+ match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
1754
+ hash_map:: Entry :: Occupied ( entry) => match entry. get ( ) {
1755
+ PendingOutboundPayment :: AwaitingInvoice {
1756
+ retry_strategy : retry, max_total_routing_fee_msat : max_total_fee, ..
1757
+ } => {
1758
+ let payment_hash = invoice. payment_hash ( ) ;
1759
+ let retry = * retry;
1760
+ let max_total_fee = * max_total_fee;
1761
+ * entry. into_mut ( ) = PendingOutboundPayment :: InvoiceReceived {
1762
+ payment_hash,
1763
+ retry_strategy : retry,
1764
+ max_total_routing_fee_msat : max_total_fee,
1765
+ } ;
1766
+
1767
+ Ok ( ( payment_hash, retry, max_total_fee, true ) )
1768
+ } ,
1769
+ // When manual invoice handling is enabled, the corresponding `PendingOutboundPayment` entry
1770
+ // is already updated at the time the invoice is received. This ensures that `InvoiceReceived`
1771
+ // event generation remains idempotent, even if the same invoice is received again before the
1772
+ // event is handled by the user.
1773
+ PendingOutboundPayment :: InvoiceReceived {
1774
+ retry_strategy, max_total_routing_fee_msat, ..
1775
+ } => {
1776
+ Ok ( ( invoice. payment_hash ( ) , * retry_strategy, * max_total_routing_fee_msat, false ) )
1777
+ } ,
1778
+ _ => Err ( Bolt12PaymentError :: DuplicateInvoice ) ,
1779
+ } ,
1780
+ hash_map:: Entry :: Vacant ( _) => Err ( Bolt12PaymentError :: UnexpectedInvoice ) ,
1781
+ }
1782
+ }
1783
+
1757
1784
fn pay_route_internal < NS : Deref , F > (
1758
1785
& self , route : & Route , payment_hash : PaymentHash , recipient_onion : & RecipientOnionFields ,
1759
1786
keysend_preimage : Option < PaymentPreimage > , invoice_request : Option < & InvoiceRequest > ,
0 commit comments