@@ -946,7 +946,16 @@ pub enum PaymentSendFailure {
946
946
/// as they will result in over-/re-payment. These HTLCs all either successfully sent (in the
947
947
/// case of Ok(())) or will send once channel_monitor_updated is called on the next-hop channel
948
948
/// with the latest update_id.
949
- PartialFailure ( Vec < Result < ( ) , APIError > > ) ,
949
+ PartialFailure {
950
+ /// The errors themselves, in the same order as the route hops.
951
+ results : Vec < Result < ( ) , APIError > > ,
952
+ /// If some paths failed without irrevocably committing to the new HTLC(s), this will
953
+ /// contain a [`RouteParameters`] object which can be used to calculate a new route that
954
+ /// will pay all remaining unpaid balance.
955
+ failed_paths_retry : Option < RouteParameters > ,
956
+ /// The payment id for the payment, which is now at least partially pending.
957
+ payment_id : PaymentId ,
958
+ } ,
950
959
}
951
960
952
961
macro_rules! handle_error {
@@ -2236,19 +2245,35 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
2236
2245
}
2237
2246
let mut has_ok = false ;
2238
2247
let mut has_err = false ;
2239
- for res in results. iter ( ) {
2248
+ let mut pending_amt_unsent = 0 ;
2249
+ let mut max_unsent_cltv_delta = 0 ;
2250
+ for ( res, path) in results. iter ( ) . zip ( route. paths . iter ( ) ) {
2240
2251
if res. is_ok ( ) { has_ok = true ; }
2241
2252
if res. is_err ( ) { has_err = true ; }
2242
2253
if let & Err ( APIError :: MonitorUpdateFailed ) = res {
2243
2254
// MonitorUpdateFailed is inherently unsafe to retry, so we call it a
2244
2255
// PartialFailure.
2245
2256
has_err = true ;
2246
2257
has_ok = true ;
2247
- break ;
2258
+ } else if res. is_err ( ) {
2259
+ pending_amt_unsent += path. last ( ) . unwrap ( ) . fee_msat ;
2260
+ max_unsent_cltv_delta = cmp:: max ( max_unsent_cltv_delta, path. last ( ) . unwrap ( ) . cltv_expiry_delta ) ;
2248
2261
}
2249
2262
}
2250
2263
if has_err && has_ok {
2251
- Err ( PaymentSendFailure :: PartialFailure ( results) )
2264
+ Err ( PaymentSendFailure :: PartialFailure {
2265
+ results,
2266
+ payment_id,
2267
+ failed_paths_retry : if pending_amt_unsent != 0 {
2268
+ if let Some ( payee) = & route. payee {
2269
+ Some ( RouteParameters {
2270
+ payee : payee. clone ( ) ,
2271
+ final_value_msat : pending_amt_unsent,
2272
+ final_cltv_expiry_delta : max_unsent_cltv_delta,
2273
+ } )
2274
+ } else { None }
2275
+ } else { None } ,
2276
+ } )
2252
2277
} else if has_err {
2253
2278
Err ( PaymentSendFailure :: AllFailedRetrySafe ( results. drain ( ..) . map ( |r| r. unwrap_err ( ) ) . collect ( ) ) )
2254
2279
} else {
0 commit comments