PaymentSendFailure::PartialFailure { results, .. } => {
for res in results { if let Err(api_err) = res { check_api_err(api_err); } }
},
+ PaymentSendFailure::DuplicatePayment => panic!(),
}
}
Err(e) => match e {
PaymentSendFailure::ParameterError(_) => Err(e),
PaymentSendFailure::PathParameterError(_) => Err(e),
+ PaymentSendFailure::DuplicatePayment => Err(e),
PaymentSendFailure::AllFailedResendSafe(_) => {
let mut payment_cache = self.payment_cache.lock().unwrap();
let payment_info = payment_cache.get_mut(&payment_hash).unwrap();
Err(PaymentSendFailure::AllFailedResendSafe(_)) => {
self.retry_payment(payment_id, payment_hash, params)
},
+ Err(PaymentSendFailure::DuplicatePayment) => {
+ log_error!(self.logger, "Got a DuplicatePayment error when attempting to retry a payment, this shouldn't happen.");
+ Err(())
+ }
Err(PaymentSendFailure::PartialFailure { failed_paths_retry, results, .. }) => {
// If a `PartialFailure` error contains a result that is an `Ok()`, it means that
// part of our payment is retried. When we receive `MonitorUpdateInProgress`, it
#[derive(Clone, Debug)]
pub enum PaymentSendFailure {
/// A parameter which was passed to send_payment was invalid, preventing us from attempting to
- /// send the payment at all. No channel state has been changed or messages sent to peers, and
- /// once you've changed the parameter at error, you can freely retry the payment in full.
+ /// send the payment at all.
+ ///
+ /// You can freely resend the payment in full (with the parameter error fixed).
+ ///
+ /// Because the payment failed outright, no payment tracking is done, you do not need to call
+ /// [`ChannelManager::abandon_payment`] and [`ChannelManager::retry_payment`] will *not* work
+ /// for this payment.
ParameterError(APIError),
/// A parameter in a single path which was passed to send_payment was invalid, preventing us
- /// from attempting to send the payment at all. No channel state has been changed or messages
- /// sent to peers, and once you've changed the parameter at error, you can freely retry the
- /// payment in full.
+ /// from attempting to send the payment at all.
+ ///
+ /// You can freely resend the payment in full (with the parameter error fixed).
///
/// The results here are ordered the same as the paths in the route object which was passed to
/// send_payment.
+ ///
+ /// Because the payment failed outright, no payment tracking is done, you do not need to call
+ /// [`ChannelManager::abandon_payment`] and [`ChannelManager::retry_payment`] will *not* work
+ /// for this payment.
PathParameterError(Vec<Result<(), APIError>>),
/// All paths which were attempted failed to send, with no channel state change taking place.
/// You can freely resend the payment in full (though you probably want to do so over different
/// [`ChannelManager::abandon_payment`] and [`ChannelManager::retry_payment`] will *not* work
/// for this payment.
AllFailedResendSafe(Vec<APIError>),
+ /// Indicates that a payment for the provided [`PaymentId`] is already in-flight and has not
+ /// yet completed (i.e. generated an [`Event::PaymentSent`]) or been abandoned (via
+ /// [`ChannelManager::abandon_payment`]).
+ ///
+ /// [`Event::PaymentSent`]: events::Event::PaymentSent
+ DuplicatePayment,
/// Some paths which were attempted failed to send, though possibly not all. At least some
/// paths have irrevocably committed to the HTLC and retrying the payment in full would result
/// in over-/re-payment.
let mut pending_outbounds = self.pending_outbound_payments.lock().unwrap();
match pending_outbounds.entry(payment_id) {
- hash_map::Entry::Occupied(_) => Err(PaymentSendFailure::ParameterError(APIError::RouteError {
- err: "Payment already in progress"
- })),
+ hash_map::Entry::Occupied(_) => Err(PaymentSendFailure::DuplicatePayment),
hash_map::Entry::Vacant(entry) => {
let payment = entry.insert(PendingOutboundPayment::Retryable {
session_privs: HashSet::new(),
// payment_id, it should be rejected.
let send_result = nodes[0].node.send_payment(&route, second_payment_hash, &Some(second_payment_secret), payment_id);
match send_result {
- Err(PaymentSendFailure::ParameterError(APIError::RouteError { err: "Payment already in progress" })) => {},
+ Err(PaymentSendFailure::DuplicatePayment) => {},
_ => panic!("Unexpected send result: {:?}", send_result),
}
// also be rejected.
let send_result = nodes[0].node.send_spontaneous_payment(&route, None, payment_id);
match send_result {
- Err(PaymentSendFailure::ParameterError(APIError::RouteError { err: "Payment already in progress" })) => {},
+ Err(PaymentSendFailure::DuplicatePayment) => {},
_ => panic!("Unexpected send result: {:?}", send_result),
}
}
// payment_id, it should be rejected.
let send_result = nodes[0].node.send_payment(&route, second_payment_hash, &Some(second_payment_secret), payment_id);
match send_result {
- Err(PaymentSendFailure::ParameterError(APIError::RouteError { err: "Payment already in progress" })) => {},
+ Err(PaymentSendFailure::DuplicatePayment) => {},
_ => panic!("Unexpected send result: {:?}", send_result),
}
// also be rejected.
let send_result = nodes[0].node.send_spontaneous_payment(&route, None, payment_id);
match send_result {
- Err(PaymentSendFailure::ParameterError(APIError::RouteError { err: "Payment already in progress" })) => {},
+ Err(PaymentSendFailure::DuplicatePayment) => {},
_ => panic!("Unexpected send result: {:?}", send_result),
}
}