Add missing import path in ser macro
[rust-lightning] / lightning / src / ln / outbound_payment.rs
index 2e2dc6b400802ebcfc1f6aa073bb2a40a9e3ce76..a851c8eda1267b1ff04140cf64c16748c604ed15 100644 (file)
@@ -17,7 +17,6 @@ use crate::chain::keysinterface::{EntropySource, NodeSigner, Recipient};
 use crate::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
 use crate::ln::channelmanager::{ChannelDetails, HTLCSource, IDEMPOTENCY_TIMEOUT_TICKS, PaymentId};
 use crate::ln::channelmanager::MIN_FINAL_CLTV_EXPIRY_DELTA as LDK_DEFAULT_MIN_FINAL_CLTV_EXPIRY_DELTA;
-use crate::ln::msgs::DecodeError;
 use crate::ln::onion_utils::HTLCFailReason;
 use crate::routing::router::{InFlightHtlcs, PaymentParameters, Route, RouteHop, RouteParameters, RoutePath, Router};
 use crate::util::errors::APIError;
@@ -64,13 +63,8 @@ pub(crate) enum PendingOutboundPayment {
                payment_hash: Option<PaymentHash>,
                timer_ticks_without_htlcs: u8,
        },
-       /// When a payer gives up trying to retry a payment, they inform us, letting us generate a
-       /// `PaymentFailed` event when all HTLCs have irrevocably failed. This avoids a number of race
-       /// conditions in MPP-aware payment retriers (1), where the possibility of multiple
-       /// `PaymentPathFailed` events with `all_paths_failed` can be pending at once, confusing a
-       /// downstream event handler as to when a payment has actually failed.
-       ///
-       /// (1) <https://github.com/lightningdevkit/rust-lightning/issues/1164>
+       /// When we've decided to give up retrying a payment, we mark it as abandoned so we can eventually
+       /// generate a `PaymentFailed` event when all HTLCs have irrevocably failed.
        Abandoned {
                session_privs: HashSet<[u8; 32]>,
                payment_hash: PaymentHash,
@@ -240,7 +234,10 @@ pub enum Retry {
        /// were retried along a route from a single call to [`Router::find_route`].
        Attempts(usize),
        #[cfg(not(feature = "no-std"))]
-       /// Time elapsed before abandoning retries for a payment.
+       /// Time elapsed before abandoning retries for a payment. At least one attempt at payment is made;
+       /// see [`PaymentParameters::expiry_time`] to avoid any attempt at payment after a specific time.
+       ///
+       /// [`PaymentParameters::expiry_time`]: crate::routing::router::PaymentParameters::expiry_time
        Timeout(core::time::Duration),
 }
 
@@ -735,8 +732,8 @@ impl OutboundPayments {
 
        fn handle_pay_route_err<R: Deref, NS: Deref, ES: Deref, IH, SP, L: Deref>(
                &self, err: PaymentSendFailure, payment_id: PaymentId, payment_hash: PaymentHash, route: Route,
-               route_params: RouteParameters, router: &R, first_hops: Vec<ChannelDetails>, inflight_htlcs: &IH,
-               entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L,
+               mut route_params: RouteParameters, router: &R, first_hops: Vec<ChannelDetails>,
+               inflight_htlcs: &IH, entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L,
                pending_events: &Mutex<Vec<events::Event>>, send_payment_along_path: &SP,
        )
        where
@@ -750,11 +747,11 @@ impl OutboundPayments {
        {
                match err {
                        PaymentSendFailure::AllFailedResendSafe(errs) => {
-                               Self::push_payment_path_failed_evs(payment_id, payment_hash, route.paths, errs.into_iter().map(|e| Err(e)), pending_events);
+                               Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut route_params, route.paths, errs.into_iter().map(|e| Err(e)), pending_events);
                                self.retry_payment_internal(payment_id, route_params, router, first_hops, inflight_htlcs, entropy_source, node_signer, best_block_height, logger, pending_events, send_payment_along_path);
                        },
-                       PaymentSendFailure::PartialFailure { failed_paths_retry: Some(retry), results, .. } => {
-                               Self::push_payment_path_failed_evs(payment_id, payment_hash, route.paths, results.into_iter(), pending_events);
+                       PaymentSendFailure::PartialFailure { failed_paths_retry: Some(mut retry), results, .. } => {
+                               Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut retry, route.paths, results.into_iter(), pending_events);
                                // Some paths were sent, even if we failed to send the full MPP value our recipient may
                                // misbehave and claim the funds, at which point we have to consider the payment sent, so
                                // return `Ok()` here, ignoring any retry errors.
@@ -766,7 +763,7 @@ impl OutboundPayments {
                                // initial HTLC-Add messages yet.
                        },
                        PaymentSendFailure::PathParameterError(results) => {
-                               Self::push_payment_path_failed_evs(payment_id, payment_hash, route.paths, results.into_iter(), pending_events);
+                               Self::push_path_failed_evs_and_scids(payment_id, payment_hash, &mut route_params, route.paths, results.into_iter(), pending_events);
                                self.abandon_payment(payment_id, pending_events);
                        },
                        PaymentSendFailure::ParameterError(e) => {
@@ -777,9 +774,9 @@ impl OutboundPayments {
                }
        }
 
-       fn push_payment_path_failed_evs<I: ExactSizeIterator + Iterator<Item = Result<(), APIError>>>(
-               payment_id: PaymentId, payment_hash: PaymentHash, paths: Vec<Vec<RouteHop>>, path_results: I,
-               pending_events: &Mutex<Vec<events::Event>>
+       fn push_path_failed_evs_and_scids<I: ExactSizeIterator + Iterator<Item = Result<(), APIError>>>(
+               payment_id: PaymentId, payment_hash: PaymentHash, route_params: &mut RouteParameters,
+               paths: Vec<Vec<RouteHop>>, path_results: I, pending_events: &Mutex<Vec<events::Event>>
        ) {
                let mut events = pending_events.lock().unwrap();
                debug_assert_eq!(paths.len(), path_results.len());
@@ -788,7 +785,9 @@ impl OutboundPayments {
                                let failed_scid = if let APIError::InvalidRoute { .. } = e {
                                        None
                                } else {
-                                       Some(path[0].short_channel_id)
+                                       let scid = path[0].short_channel_id;
+                                       route_params.payment_params.previously_failed_channels.push(scid);
+                                       Some(scid)
                                };
                                events.push(events::Event::PaymentPathFailed {
                                        payment_id: Some(payment_id),