Skip to content

Commit c60d305

Browse files
authored
Merge pull request #2371 from jkczyz/2023-06-offer-message-handling
BOLT 12 Invoice payments
2 parents 2e113b5 + 44b9c54 commit c60d305

File tree

8 files changed

+627
-95
lines changed

8 files changed

+627
-95
lines changed

lightning/src/events/mod.rs

+25
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,14 @@ pub enum Event {
508508
/// serialized prior to LDK version 0.0.117.
509509
sender_intended_total_msat: Option<u64>,
510510
},
511+
/// Indicates a request for an invoice failed to yield a response in a reasonable amount of time
512+
/// or was explicitly abandoned by [`ChannelManager::abandon_payment`].
513+
///
514+
/// [`ChannelManager::abandon_payment`]: crate::ln::channelmanager::ChannelManager::abandon_payment
515+
InvoiceRequestFailed {
516+
/// The `payment_id` to have been associated with payment for the requested invoice.
517+
payment_id: PaymentId,
518+
},
511519
/// Indicates an outbound payment we made succeeded (i.e. it made it all the way to its target
512520
/// and we got back the payment preimage for it).
513521
///
@@ -1148,6 +1156,12 @@ impl Writeable for Event {
11481156
(8, funding_txo, required),
11491157
});
11501158
},
1159+
&Event::InvoiceRequestFailed { ref payment_id } => {
1160+
33u8.write(writer)?;
1161+
write_tlv_fields!(writer, {
1162+
(0, payment_id, required),
1163+
})
1164+
},
11511165
// Note that, going forward, all new events must only write data inside of
11521166
// `write_tlv_fields`. Versions 0.0.101+ will ignore odd-numbered events that write
11531167
// data via `write_tlv_fields`.
@@ -1535,6 +1549,17 @@ impl MaybeReadable for Event {
15351549
};
15361550
f()
15371551
},
1552+
33u8 => {
1553+
let f = || {
1554+
_init_and_read_len_prefixed_tlv_fields!(reader, {
1555+
(0, payment_id, required),
1556+
});
1557+
Ok(Some(Event::InvoiceRequestFailed {
1558+
payment_id: payment_id.0.unwrap(),
1559+
}))
1560+
};
1561+
f()
1562+
},
15381563
// Versions prior to 0.0.100 did not ignore odd types, instead returning InvalidValue.
15391564
// Version 0.0.100 failed to properly ignore odd types, possibly resulting in corrupt
15401565
// reads.

lightning/src/ln/channelmanager.rs

+31-12
Original file line numberDiff line numberDiff line change
@@ -1341,11 +1341,6 @@ const CHECK_CLTV_EXPIRY_SANITY_2: u32 = MIN_CLTV_EXPIRY_DELTA as u32 - LATENCY_G
13411341
/// The number of ticks of [`ChannelManager::timer_tick_occurred`] until expiry of incomplete MPPs
13421342
pub(crate) const MPP_TIMEOUT_TICKS: u8 = 3;
13431343

1344-
/// The number of ticks of [`ChannelManager::timer_tick_occurred`] until we time-out the
1345-
/// idempotency of payments by [`PaymentId`]. See
1346-
/// [`OutboundPayments::remove_stale_resolved_payments`].
1347-
pub(crate) const IDEMPOTENCY_TIMEOUT_TICKS: u8 = 7;
1348-
13491344
/// The number of ticks of [`ChannelManager::timer_tick_occurred`] where a peer is disconnected
13501345
/// until we mark the channel disabled and gossip the update.
13511346
pub(crate) const DISABLE_GOSSIP_TICKS: u8 = 10;
@@ -1688,6 +1683,11 @@ pub enum ChannelShutdownState {
16881683
/// These include payments that have yet to find a successful path, or have unresolved HTLCs.
16891684
#[derive(Debug, PartialEq)]
16901685
pub enum RecentPaymentDetails {
1686+
/// When an invoice was requested and thus a payment has not yet been sent.
1687+
AwaitingInvoice {
1688+
/// Identifier for the payment to ensure idempotency.
1689+
payment_id: PaymentId,
1690+
},
16911691
/// When a payment is still being sent and awaiting successful delivery.
16921692
Pending {
16931693
/// Hash of the payment that is currently being sent but has yet to be fulfilled or
@@ -2419,7 +2419,14 @@ where
24192419
/// [`Event::PaymentSent`]: events::Event::PaymentSent
24202420
pub fn list_recent_payments(&self) -> Vec<RecentPaymentDetails> {
24212421
self.pending_outbound_payments.pending_outbound_payments.lock().unwrap().iter()
2422-
.filter_map(|(_, pending_outbound_payment)| match pending_outbound_payment {
2422+
.filter_map(|(payment_id, pending_outbound_payment)| match pending_outbound_payment {
2423+
PendingOutboundPayment::AwaitingInvoice { .. } => {
2424+
Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
2425+
},
2426+
// InvoiceReceived is an intermediate state and doesn't need to be exposed
2427+
PendingOutboundPayment::InvoiceReceived { .. } => {
2428+
Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
2429+
},
24232430
PendingOutboundPayment::Retryable { payment_hash, total_msat, .. } => {
24242431
Some(RecentPaymentDetails::Pending {
24252432
payment_hash: *payment_hash,
@@ -3381,22 +3388,32 @@ where
33813388
}
33823389

33833390

3384-
/// Signals that no further retries for the given payment should occur. Useful if you have a
3391+
/// Signals that no further attempts for the given payment should occur. Useful if you have a
33853392
/// pending outbound payment with retries remaining, but wish to stop retrying the payment before
33863393
/// retries are exhausted.
33873394
///
3395+
/// # Event Generation
3396+
///
33883397
/// If no [`Event::PaymentFailed`] event had been generated before, one will be generated as soon
33893398
/// as there are no remaining pending HTLCs for this payment.
33903399
///
33913400
/// Note that calling this method does *not* prevent a payment from succeeding. You must still
33923401
/// wait until you receive either a [`Event::PaymentFailed`] or [`Event::PaymentSent`] event to
33933402
/// determine the ultimate status of a payment.
33943403
///
3395-
/// If an [`Event::PaymentFailed`] event is generated and we restart without this
3396-
/// [`ChannelManager`] having been persisted, another [`Event::PaymentFailed`] may be generated.
3404+
/// # Requested Invoices
33973405
///
3398-
/// [`Event::PaymentFailed`]: events::Event::PaymentFailed
3399-
/// [`Event::PaymentSent`]: events::Event::PaymentSent
3406+
/// In the case of paying a [`Bolt12Invoice`], abandoning the payment prior to receiving the
3407+
/// invoice will result in an [`Event::InvoiceRequestFailed`] and prevent any attempts at paying
3408+
/// it once received. The other events may only be generated once the invoice has been received.
3409+
///
3410+
/// # Restart Behavior
3411+
///
3412+
/// If an [`Event::PaymentFailed`] is generated and we restart without first persisting the
3413+
/// [`ChannelManager`], another [`Event::PaymentFailed`] may be generated; likewise for
3414+
/// [`Event::InvoiceRequestFailed`].
3415+
///
3416+
/// [`Bolt12Invoice`]: crate::offers::invoice::Bolt12Invoice
34003417
pub fn abandon_payment(&self, payment_id: PaymentId) {
34013418
let _persistence_guard = PersistenceNotifierGuard::notify_on_drop(self);
34023419
self.pending_outbound_payments.abandon_payment(payment_id, PaymentFailureReason::UserAbandoned, &self.pending_events);
@@ -4655,7 +4672,7 @@ where
46554672
let _ = handle_error!(self, err, counterparty_node_id);
46564673
}
46574674

4658-
self.pending_outbound_payments.remove_stale_resolved_payments(&self.pending_events);
4675+
self.pending_outbound_payments.remove_stale_payments(&self.pending_events);
46594676

46604677
// Technically we don't need to do this here, but if we have holding cell entries in a
46614678
// channel that need freeing, it's better to do that here and block a background task
@@ -8347,6 +8364,8 @@ where
83478364
session_priv.write(writer)?;
83488365
}
83498366
}
8367+
PendingOutboundPayment::AwaitingInvoice { .. } => {},
8368+
PendingOutboundPayment::InvoiceReceived { .. } => {},
83508369
PendingOutboundPayment::Fulfilled { .. } => {},
83518370
PendingOutboundPayment::Abandoned { .. } => {},
83528371
}

0 commit comments

Comments
 (0)