@@ -15,7 +15,7 @@ use bitcoin::secp256k1::{self, Secp256k1, SecretKey};
1515
1616use crate :: chain:: keysinterface:: { EntropySource , NodeSigner , Recipient } ;
1717use crate :: ln:: { PaymentHash , PaymentPreimage , PaymentSecret } ;
18- use crate :: ln:: channelmanager:: { ChannelDetails , HTLCSource , IDEMPOTENCY_TIMEOUT_TICKS , MIN_HTLC_RELAY_HOLDING_CELL_MILLIS , PaymentId } ;
18+ use crate :: ln:: channelmanager:: { ChannelDetails , HTLCSource , IDEMPOTENCY_TIMEOUT_TICKS , PaymentId } ;
1919use crate :: ln:: channelmanager:: MIN_FINAL_CLTV_EXPIRY_DELTA as LDK_DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA ;
2020use crate :: ln:: msgs:: DecodeError ;
2121use crate :: ln:: onion_utils:: HTLCFailReason ;
@@ -30,7 +30,6 @@ use crate::util::time::tests::SinceEpoch;
3030use core:: cmp;
3131use core:: fmt:: { self , Display , Formatter } ;
3232use core:: ops:: Deref ;
33- use core:: time:: Duration ;
3433
3534use crate :: prelude:: * ;
3635use crate :: sync:: Mutex ;
@@ -546,6 +545,12 @@ impl OutboundPayments {
546545 } ) ;
547546 }
548547
548+ pub ( super ) fn needs_abandon ( & self ) -> bool {
549+ let outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
550+ outbounds. iter ( ) . any ( |( _, pmt) |
551+ !pmt. is_auto_retryable_now ( ) && pmt. remaining_parts ( ) == 0 && !pmt. is_fulfilled ( ) )
552+ }
553+
549554 /// Will return `Ok(())` iff at least one HTLC is sent for the payment.
550555 fn pay_internal < R : Deref , NS : Deref , ES : Deref , IH , SP , L : Deref > (
551556 & self , payment_id : PaymentId ,
@@ -1006,12 +1011,13 @@ impl OutboundPayments {
10061011 } ) ;
10071012 }
10081013
1014+ // Returns a bool indicating whether a PendingHTLCsForwardable event should be generated.
10091015 pub ( super ) fn fail_htlc < L : Deref > (
10101016 & self , source : & HTLCSource , payment_hash : & PaymentHash , onion_error : & HTLCFailReason ,
10111017 path : & Vec < RouteHop > , session_priv : & SecretKey , payment_id : & PaymentId ,
10121018 payment_params : & Option < PaymentParameters > , probing_cookie_secret : [ u8 ; 32 ] ,
10131019 secp_ctx : & Secp256k1 < secp256k1:: All > , pending_events : & Mutex < Vec < events:: Event > > , logger : & L
1014- ) where L :: Target : Logger {
1020+ ) -> bool where L :: Target : Logger {
10151021 #[ cfg( test) ]
10161022 let ( network_update, short_channel_id, payment_retryable, onion_error_code, onion_error_data) = onion_error. decode_onion_failure ( secp_ctx, logger, & source) ;
10171023 #[ cfg( not( test) ) ]
@@ -1021,18 +1027,33 @@ impl OutboundPayments {
10211027 let mut session_priv_bytes = [ 0 ; 32 ] ;
10221028 session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
10231029 let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
1030+
1031+ // If any payments already need retry, there's no need to generate a redundant
1032+ // `PendingHTLCsForwardable`.
1033+ let already_awaiting_retry = outbounds. iter ( ) . any ( |( _, pmt) | {
1034+ let mut awaiting_retry = false ;
1035+ if pmt. is_auto_retryable_now ( ) {
1036+ if let PendingOutboundPayment :: Retryable { pending_amt_msat, total_msat, .. } = pmt {
1037+ if pending_amt_msat < total_msat {
1038+ awaiting_retry = true ;
1039+ }
1040+ }
1041+ }
1042+ awaiting_retry
1043+ } ) ;
1044+
10241045 let mut all_paths_failed = false ;
10251046 let mut full_failure_ev = None ;
1026- let mut pending_retry_ev = None ;
1047+ let mut pending_retry_ev = false ;
10271048 let mut retry = None ;
10281049 let attempts_remaining = if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( * payment_id) {
10291050 if !payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( & path) ) {
10301051 log_trace ! ( logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
1031- return
1052+ return false
10321053 }
10331054 if payment. get ( ) . is_fulfilled ( ) {
10341055 log_trace ! ( logger, "Received failure of HTLC with payment_hash {} after payment completion" , log_bytes!( payment_hash. 0 ) ) ;
1035- return
1056+ return false
10361057 }
10371058 let mut is_retryable_now = payment. get ( ) . is_auto_retryable_now ( ) ;
10381059 if let Some ( scid) = short_channel_id {
@@ -1084,7 +1105,7 @@ impl OutboundPayments {
10841105 is_retryable_now
10851106 } else {
10861107 log_trace ! ( logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
1087- return
1108+ return false
10881109 } ;
10891110 core:: mem:: drop ( outbounds) ;
10901111 log_trace ! ( logger, "Failing outbound payment HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -1114,11 +1135,9 @@ impl OutboundPayments {
11141135 }
11151136 // If we miss abandoning the payment above, we *must* generate an event here or else the
11161137 // payment will sit in our outbounds forever.
1117- if attempts_remaining {
1138+ if attempts_remaining && !already_awaiting_retry {
11181139 debug_assert ! ( full_failure_ev. is_none( ) ) ;
1119- pending_retry_ev = Some ( events:: Event :: PendingHTLCsForwardable {
1120- time_forwardable : Duration :: from_millis ( MIN_HTLC_RELAY_HOLDING_CELL_MILLIS ) ,
1121- } ) ;
1140+ pending_retry_ev = true ;
11221141 }
11231142 events:: Event :: PaymentPathFailed {
11241143 payment_id : Some ( * payment_id) ,
@@ -1139,7 +1158,7 @@ impl OutboundPayments {
11391158 let mut pending_events = pending_events. lock ( ) . unwrap ( ) ;
11401159 pending_events. push ( path_failure) ;
11411160 if let Some ( ev) = full_failure_ev { pending_events. push ( ev) ; }
1142- if let Some ( ev ) = pending_retry_ev { pending_events . push ( ev ) ; }
1161+ pending_retry_ev
11431162 }
11441163
11451164 pub ( super ) fn abandon_payment (
0 commit comments