X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Foutbound_payment.rs;h=a851c8eda1267b1ff04140cf64c16748c604ed15;hb=f361aa62a42551be0de722ba4c886c1ebdcb13cd;hp=2e2dc6b400802ebcfc1f6aa073bb2a40a9e3ce76;hpb=b826d1735d4fdfb162bc46d87deee495f4fb3363;p=rust-lightning diff --git a/lightning/src/ln/outbound_payment.rs b/lightning/src/ln/outbound_payment.rs index 2e2dc6b4..a851c8ed 100644 --- a/lightning/src/ln/outbound_payment.rs +++ b/lightning/src/ln/outbound_payment.rs @@ -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, 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) + /// 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( &self, err: PaymentSendFailure, payment_id: PaymentId, payment_hash: PaymentHash, route: Route, - route_params: RouteParameters, router: &R, first_hops: Vec, inflight_htlcs: &IH, - entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L, + mut route_params: RouteParameters, router: &R, first_hops: Vec, + inflight_htlcs: &IH, entropy_source: &ES, node_signer: &NS, best_block_height: u32, logger: &L, pending_events: &Mutex>, 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>>( - payment_id: PaymentId, payment_hash: PaymentHash, paths: Vec>, path_results: I, - pending_events: &Mutex> + fn push_path_failed_evs_and_scids>>( + payment_id: PaymentId, payment_hash: PaymentHash, route_params: &mut RouteParameters, + paths: Vec>, path_results: I, pending_events: &Mutex> ) { 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),