mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-24 15:02:20 +01:00
Make PaymentFailureReason downgradable
The PaymentFailureReason variants for invoice request failures will cause downgrades to break. Instead, use a new TLV for the reason and continue to write the old TLV, only use None for the new reasons.
This commit is contained in:
parent
bb94320e40
commit
075a2e36b9
2 changed files with 41 additions and 4 deletions
|
@ -502,6 +502,12 @@ impl_writeable_tlv_based_enum!(InterceptNextHop,
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum PaymentFailureReason {
|
pub enum PaymentFailureReason {
|
||||||
/// The intended recipient rejected our payment.
|
/// The intended recipient rejected our payment.
|
||||||
|
///
|
||||||
|
/// Also used for [`UnknownRequiredFeatures`] and [`InvoiceRequestRejected`] when downgrading to
|
||||||
|
/// version prior to 0.0.124.
|
||||||
|
///
|
||||||
|
/// [`UnknownRequiredFeatures`]: Self::UnknownRequiredFeatures
|
||||||
|
/// [`InvoiceRequestRejected`]: Self::InvoiceRequestRejected
|
||||||
RecipientRejected,
|
RecipientRejected,
|
||||||
/// The user chose to abandon this payment by calling [`ChannelManager::abandon_payment`].
|
/// The user chose to abandon this payment by calling [`ChannelManager::abandon_payment`].
|
||||||
///
|
///
|
||||||
|
@ -517,7 +523,10 @@ pub enum PaymentFailureReason {
|
||||||
/// The payment expired while retrying, based on the provided
|
/// The payment expired while retrying, based on the provided
|
||||||
/// [`PaymentParameters::expiry_time`].
|
/// [`PaymentParameters::expiry_time`].
|
||||||
///
|
///
|
||||||
|
/// Also used for [`InvoiceRequestExpired`] when downgrading to version prior to 0.0.124.
|
||||||
|
///
|
||||||
/// [`PaymentParameters::expiry_time`]: crate::routing::router::PaymentParameters::expiry_time
|
/// [`PaymentParameters::expiry_time`]: crate::routing::router::PaymentParameters::expiry_time
|
||||||
|
/// [`InvoiceRequestExpired`]: Self::InvoiceRequestExpired
|
||||||
PaymentExpired,
|
PaymentExpired,
|
||||||
/// We failed to find a route while retrying the payment.
|
/// We failed to find a route while retrying the payment.
|
||||||
///
|
///
|
||||||
|
@ -878,8 +887,8 @@ pub enum Event {
|
||||||
/// [`Offer`]: crate::offers::offer::Offer
|
/// [`Offer`]: crate::offers::offer::Offer
|
||||||
payment_hash: Option<PaymentHash>,
|
payment_hash: Option<PaymentHash>,
|
||||||
/// The reason the payment failed. This is only `None` for events generated or serialized
|
/// The reason the payment failed. This is only `None` for events generated or serialized
|
||||||
/// by versions prior to 0.0.115, or when downgrading to 0.0.124 or later with a reason that
|
/// by versions prior to 0.0.115, or when downgrading to a version with a reason that was
|
||||||
/// was added after.
|
/// added after.
|
||||||
reason: Option<PaymentFailureReason>,
|
reason: Option<PaymentFailureReason>,
|
||||||
},
|
},
|
||||||
/// Indicates that a path for an outbound payment was successful.
|
/// Indicates that a path for an outbound payment was successful.
|
||||||
|
@ -1554,11 +1563,30 @@ impl Writeable for Event {
|
||||||
Some(payment_hash) => (payment_hash, true),
|
Some(payment_hash) => (payment_hash, true),
|
||||||
None => (&PaymentHash([0; 32]), false),
|
None => (&PaymentHash([0; 32]), false),
|
||||||
};
|
};
|
||||||
|
let legacy_reason = match reason {
|
||||||
|
None => &None,
|
||||||
|
// Variants available prior to version 0.0.124.
|
||||||
|
Some(PaymentFailureReason::RecipientRejected)
|
||||||
|
| Some(PaymentFailureReason::UserAbandoned)
|
||||||
|
| Some(PaymentFailureReason::RetriesExhausted)
|
||||||
|
| Some(PaymentFailureReason::PaymentExpired)
|
||||||
|
| Some(PaymentFailureReason::RouteNotFound)
|
||||||
|
| Some(PaymentFailureReason::UnexpectedError) => reason,
|
||||||
|
// Variants introduced at version 0.0.124 or later. Prior versions fail to parse
|
||||||
|
// unknown variants, while versions 0.0.124 or later will use None.
|
||||||
|
Some(PaymentFailureReason::UnknownRequiredFeatures) =>
|
||||||
|
&Some(PaymentFailureReason::RecipientRejected),
|
||||||
|
Some(PaymentFailureReason::InvoiceRequestExpired) =>
|
||||||
|
&Some(PaymentFailureReason::RetriesExhausted),
|
||||||
|
Some(PaymentFailureReason::InvoiceRequestRejected) =>
|
||||||
|
&Some(PaymentFailureReason::RecipientRejected),
|
||||||
|
};
|
||||||
write_tlv_fields!(writer, {
|
write_tlv_fields!(writer, {
|
||||||
(0, payment_id, required),
|
(0, payment_id, required),
|
||||||
(1, reason, option),
|
(1, legacy_reason, option),
|
||||||
(2, payment_hash, required),
|
(2, payment_hash, required),
|
||||||
(3, invoice_received, required),
|
(3, invoice_received, required),
|
||||||
|
(5, reason, option),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
&Event::OpenChannelRequest { .. } => {
|
&Event::OpenChannelRequest { .. } => {
|
||||||
|
@ -1926,17 +1954,20 @@ impl MaybeReadable for Event {
|
||||||
let mut payment_hash = PaymentHash([0; 32]);
|
let mut payment_hash = PaymentHash([0; 32]);
|
||||||
let mut payment_id = PaymentId([0; 32]);
|
let mut payment_id = PaymentId([0; 32]);
|
||||||
let mut reason = None;
|
let mut reason = None;
|
||||||
|
let mut legacy_reason = None;
|
||||||
let mut invoice_received: Option<bool> = None;
|
let mut invoice_received: Option<bool> = None;
|
||||||
read_tlv_fields!(reader, {
|
read_tlv_fields!(reader, {
|
||||||
(0, payment_id, required),
|
(0, payment_id, required),
|
||||||
(1, reason, upgradable_option),
|
(1, legacy_reason, upgradable_option),
|
||||||
(2, payment_hash, required),
|
(2, payment_hash, required),
|
||||||
(3, invoice_received, option),
|
(3, invoice_received, option),
|
||||||
|
(5, reason, upgradable_option),
|
||||||
});
|
});
|
||||||
let payment_hash = match invoice_received {
|
let payment_hash = match invoice_received {
|
||||||
Some(invoice_received) => invoice_received.then(|| payment_hash),
|
Some(invoice_received) => invoice_received.then(|| payment_hash),
|
||||||
None => (payment_hash != PaymentHash([0; 32])).then(|| payment_hash),
|
None => (payment_hash != PaymentHash([0; 32])).then(|| payment_hash),
|
||||||
};
|
};
|
||||||
|
let reason = reason.or(legacy_reason);
|
||||||
Ok(Some(Event::PaymentFailed {
|
Ok(Some(Event::PaymentFailed {
|
||||||
payment_id,
|
payment_id,
|
||||||
payment_hash,
|
payment_hash,
|
||||||
|
|
|
@ -10,3 +10,9 @@
|
||||||
* Any `Event::PaymentFailed` generated without a payment hash will deserialize
|
* Any `Event::PaymentFailed` generated without a payment hash will deserialize
|
||||||
with `PaymentHash([0; 32])` when downgrading. This can be treated like an
|
with `PaymentHash([0; 32])` when downgrading. This can be treated like an
|
||||||
`Event::InvoiceRequestFailed` (#3192).
|
`Event::InvoiceRequestFailed` (#3192).
|
||||||
|
* An `Event::PaymentFailed` generated with one of the following
|
||||||
|
`PaymentFailureReason`s will deserialize with the corresponding reason after
|
||||||
|
downgrading to a version prior to 0.0.124:
|
||||||
|
- `UnknownRequiredFeatures` to `RecipientRejected`,
|
||||||
|
- `InvoiceRequestExpired` to `RetriesExhausted`, and
|
||||||
|
- `InvoiceRequestRejected` to `RecipientRejected` (#3192).
|
||||||
|
|
Loading…
Add table
Reference in a new issue