@@ -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:: { HTLCSource , IDEMPOTENCY_TIMEOUT_TICKS , PaymentId } ;
18
+ use crate :: ln:: channelmanager:: { HTLCSource , IDEMPOTENCY_TIMEOUT_TICKS , MIN_HTLC_RELAY_HOLDING_CELL_MILLIS , PaymentId } ;
19
19
use crate :: ln:: msgs:: DecodeError ;
20
20
use crate :: ln:: onion_utils:: HTLCFailReason ;
21
21
use crate :: routing:: router:: { PaymentParameters , Route , RouteHop , RouteParameters , RoutePath } ;
@@ -29,6 +29,7 @@ use crate::util::time::tests::SinceEpoch;
29
29
use core:: cmp;
30
30
use core:: fmt:: { self , Display , Formatter } ;
31
31
use core:: ops:: Deref ;
32
+ use core:: time:: Duration ;
32
33
33
34
use crate :: prelude:: * ;
34
35
use crate :: sync:: Mutex ;
@@ -87,6 +88,11 @@ impl PendingOutboundPayment {
87
88
}
88
89
false
89
90
}
91
+ pub fn insert_previously_failed_scid ( & mut self , scid : u64 ) {
92
+ if let PendingOutboundPayment :: Retryable { route_params : Some ( params) , .. } = self {
93
+ params. payment_params . previously_failed_channels . push ( scid) ;
94
+ }
95
+ }
90
96
pub ( super ) fn is_fulfilled ( & self ) -> bool {
91
97
match self {
92
98
PendingOutboundPayment :: Fulfilled { .. } => true ,
@@ -788,7 +794,8 @@ impl OutboundPayments {
788
794
let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
789
795
let mut all_paths_failed = false ;
790
796
let mut full_failure_ev = None ;
791
- if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( * payment_id) {
797
+ let mut pending_retry_ev = None ;
798
+ let attempts_remaining = if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( * payment_id) {
792
799
if !payment. get_mut ( ) . remove ( & session_priv_bytes, Some ( & path) ) {
793
800
log_trace ! ( logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
794
801
return
@@ -797,6 +804,7 @@ impl OutboundPayments {
797
804
log_trace ! ( logger, "Received failure of HTLC with payment_hash {} after payment completion" , log_bytes!( payment_hash. 0 ) ) ;
798
805
return
799
806
}
807
+ let is_retryable = payment. get ( ) . is_retryable ( ) ;
800
808
if payment. get ( ) . remaining_parts ( ) == 0 {
801
809
all_paths_failed = true ;
802
810
if payment. get ( ) . abandoned ( ) {
@@ -807,10 +815,11 @@ impl OutboundPayments {
807
815
payment. remove ( ) ;
808
816
}
809
817
}
818
+ is_retryable
810
819
} else {
811
820
log_trace ! ( logger, "Received duplicative fail for HTLC with payment_hash {}" , log_bytes!( payment_hash. 0 ) ) ;
812
821
return
813
- }
822
+ } ;
814
823
let mut retry = if let Some ( payment_params_data) = payment_params {
815
824
let path_last_hop = path. last ( ) . expect ( "Outbound payments must have had a valid path" ) ;
816
825
Some ( RouteParameters {
@@ -847,8 +856,15 @@ impl OutboundPayments {
847
856
// process_onion_failure we should close that channel as it implies our
848
857
// next-hop is needlessly blaming us!
849
858
if let Some ( scid) = short_channel_id {
859
+ outbounds. get_mut ( & payment_id) . map ( |pmt| pmt. insert_previously_failed_scid ( scid) ) ;
850
860
retry. as_mut ( ) . map ( |r| r. payment_params . previously_failed_channels . push ( scid) ) ;
851
861
}
862
+ if payment_retryable && attempts_remaining && retry. is_some ( ) {
863
+ debug_assert ! ( full_failure_ev. is_none( ) ) ;
864
+ pending_retry_ev = Some ( events:: Event :: PendingHTLCsForwardable {
865
+ time_forwardable : Duration :: from_millis ( MIN_HTLC_RELAY_HOLDING_CELL_MILLIS ) ,
866
+ } ) ;
867
+ }
852
868
events:: Event :: PaymentPathFailed {
853
869
payment_id : Some ( * payment_id) ,
854
870
payment_hash : payment_hash. clone ( ) ,
@@ -868,6 +884,7 @@ impl OutboundPayments {
868
884
let mut pending_events = pending_events. lock ( ) . unwrap ( ) ;
869
885
pending_events. push ( path_failure) ;
870
886
if let Some ( ev) = full_failure_ev { pending_events. push ( ev) ; }
887
+ if let Some ( ev) = pending_retry_ev { pending_events. push ( ev) ; }
871
888
}
872
889
873
890
pub ( super ) fn abandon_payment ( & self , payment_id : PaymentId ) -> Option < events:: Event > {
0 commit comments