/// The reason the payment failed. Used in [`Event::PaymentFailed`].
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum PaymentFailureReason {
- /// The intended recipient rejected our payment.
+ /// The intended recipient rejected our payment or invoice request.
RecipientRejected,
/// The user chose to abandon this payment by calling [`ChannelManager::abandon_payment`].
///
/// This error should generally never happen. This likely means that there is a problem with
/// your router.
UnexpectedError,
+ /// An invoice was received that required unknown features.
+ UnknownRequiredFeatures,
}
impl_writeable_tlv_based_enum!(PaymentFailureReason,
(0, RecipientRejected) => {},
+ (1, UnknownRequiredFeatures) => {},
(2, UserAbandoned) => {},
(4, RetriesExhausted) => {},
(6, PaymentExpired) => {},
///
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
pub fn abandon_payment(&self, payment_id: PaymentId) {
+ self.abandon_payment_with_reason(payment_id, PaymentFailureReason::UserAbandoned)
+ }
+
+ fn abandon_payment_with_reason(&self, payment_id: PaymentId, reason: PaymentFailureReason) {
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
- self.pending_outbound_payments.abandon_payment(payment_id, PaymentFailureReason::UserAbandoned, &self.pending_events);
+ self.pending_outbound_payments.abandon_payment(payment_id, reason, &self.pending_events);
}
/// Send a spontaneous payment, which is a payment that does not require the recipient to have
let secp_ctx = &self.secp_ctx;
let expanded_key = &self.inbound_payment_key;
- let abandon_if_payment = |context| {
- match context {
- Some(OffersContext::OutboundPayment { payment_id, nonce, hmac }) => {
- if signer::verify_payment_id(payment_id, hmac, nonce, expanded_key) {
- self.abandon_payment(payment_id);
- }
- },
- _ => {},
- }
- };
-
match message {
OffersMessage::InvoiceRequest(invoice_request) => {
let responder = match responder {
logger, "Invoice requires unknown features: {:?}",
invoice.invoice_features(),
);
- abandon_if_payment(context);
+ self.abandon_payment_with_reason(
+ payment_id, PaymentFailureReason::UnknownRequiredFeatures,
+ );
let error = InvoiceError::from(Bolt12SemanticError::UnknownRequiredFeatures);
let response = match responder {
Some(OffersContext::InboundPayment { payment_hash }) => Some(payment_hash),
_ => None,
};
+
let logger = WithContext::from(&self.logger, None, None, payment_hash);
log_trace!(logger, "Received invoice_error: {}", invoice_error);
- abandon_if_payment(context);
+ match context {
+ Some(OffersContext::OutboundPayment { payment_id, nonce, hmac }) => {
+ if signer::verify_payment_id(payment_id, hmac, nonce, expanded_key) {
+ self.abandon_payment_with_reason(
+ payment_id, PaymentFailureReason::RecipientRejected,
+ );
+ }
+ },
+ _ => {},
+ }
+
ResponseInstruction::NoResponse
},
}