@@ -15,7 +15,7 @@ use bitcoin::secp256k1::{self, Secp256k1, SecretKey};
15
15
16
16
use crate :: chain:: keysinterface:: { EntropySource , NodeSigner , Recipient } ;
17
17
use 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 } ;
19
19
use crate :: ln:: channelmanager:: MIN_FINAL_CLTV_EXPIRY_DELTA as LDK_DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA ;
20
20
use crate :: ln:: msgs:: DecodeError ;
21
21
use crate :: ln:: onion_utils:: HTLCFailReason ;
@@ -30,7 +30,6 @@ use crate::util::time::tests::SinceEpoch;
30
30
use core:: cmp;
31
31
use core:: fmt:: { self , Display , Formatter } ;
32
32
use core:: ops:: Deref ;
33
- use core:: time:: Duration ;
34
33
35
34
use crate :: prelude:: * ;
36
35
use crate :: sync:: Mutex ;
@@ -546,6 +545,12 @@ impl OutboundPayments {
546
545
} ) ;
547
546
}
548
547
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
+
549
554
/// Will return `Ok(())` iff at least one HTLC is sent for the payment.
550
555
fn pay_internal < R : Deref , NS : Deref , ES : Deref , IH , SP , L : Deref > (
551
556
& self , payment_id : PaymentId ,
@@ -1006,12 +1011,13 @@ impl OutboundPayments {
1006
1011
} ) ;
1007
1012
}
1008
1013
1014
+ // Returns a bool indicating whether a PendingHTLCsForwardable event should be generated.
1009
1015
pub ( super ) fn fail_htlc < L : Deref > (
1010
1016
& self , source : & HTLCSource , payment_hash : & PaymentHash , onion_error : & HTLCFailReason ,
1011
1017
path : & Vec < RouteHop > , session_priv : & SecretKey , payment_id : & PaymentId ,
1012
1018
payment_params : & Option < PaymentParameters > , probing_cookie_secret : [ u8 ; 32 ] ,
1013
1019
secp_ctx : & Secp256k1 < secp256k1:: All > , pending_events : & Mutex < Vec < events:: Event > > , logger : & L
1014
- ) where L :: Target : Logger {
1020
+ ) -> bool where L :: Target : Logger {
1015
1021
#[ cfg( test) ]
1016
1022
let ( network_update, short_channel_id, payment_retryable, onion_error_code, onion_error_data) = onion_error. decode_onion_failure ( secp_ctx, logger, & source) ;
1017
1023
#[ cfg( not( test) ) ]
@@ -1021,18 +1027,33 @@ impl OutboundPayments {
1021
1027
let mut session_priv_bytes = [ 0 ; 32 ] ;
1022
1028
session_priv_bytes. copy_from_slice ( & session_priv[ ..] ) ;
1023
1029
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
+
1024
1045
let mut all_paths_failed = false ;
1025
1046
let mut full_failure_ev = None ;
1026
- let mut pending_retry_ev = None ;
1047
+ let mut pending_retry_ev = false ;
1027
1048
let mut retry = None ;
1028
1049
let attempts_remaining = if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( * payment_id) {
1029
1050
if !payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( & path) ) {
1030
1051
log_trace ! ( logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
1031
- return
1052
+ return false
1032
1053
}
1033
1054
if payment. get ( ) . is_fulfilled ( ) {
1034
1055
log_trace ! ( logger, "Received failure of HTLC with payment_hash {} after payment completion" , log_bytes!( payment_hash. 0 ) ) ;
1035
- return
1056
+ return false
1036
1057
}
1037
1058
let mut is_retryable_now = payment. get ( ) . is_auto_retryable_now ( ) ;
1038
1059
if let Some ( scid) = short_channel_id {
@@ -1084,7 +1105,7 @@ impl OutboundPayments {
1084
1105
is_retryable_now
1085
1106
} else {
1086
1107
log_trace ! ( logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
1087
- return
1108
+ return false
1088
1109
} ;
1089
1110
core:: mem:: drop ( outbounds) ;
1090
1111
log_trace ! ( logger, "Failing outbound payment HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
@@ -1114,11 +1135,9 @@ impl OutboundPayments {
1114
1135
}
1115
1136
// If we miss abandoning the payment above, we *must* generate an event here or else the
1116
1137
// payment will sit in our outbounds forever.
1117
- if attempts_remaining {
1138
+ if attempts_remaining && !already_awaiting_retry {
1118
1139
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 ;
1122
1141
}
1123
1142
events:: Event :: PaymentPathFailed {
1124
1143
payment_id : Some ( * payment_id) ,
@@ -1139,7 +1158,7 @@ impl OutboundPayments {
1139
1158
let mut pending_events = pending_events. lock ( ) . unwrap ( ) ;
1140
1159
pending_events. push ( path_failure) ;
1141
1160
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
1143
1162
}
1144
1163
1145
1164
pub ( super ) fn abandon_payment (
0 commit comments