Skip to content

Commit ea4fb77

Browse files
committed
Add a new AwaitingOffer outbound payment state for BIP 353
1 parent 95e45f1 commit ea4fb77

File tree

2 files changed

+60
-25
lines changed

2 files changed

+60
-25
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3470,11 +3470,11 @@ where
34703470
pub fn list_recent_payments(&self) -> Vec<RecentPaymentDetails> {
34713471
self.pending_outbound_payments.pending_outbound_payments.lock().unwrap().iter()
34723472
.filter_map(|(payment_id, pending_outbound_payment)| match pending_outbound_payment {
3473-
PendingOutboundPayment::AwaitingInvoice { .. } => {
3474-
Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
3475-
},
3476-
// InvoiceReceived is an intermediate state and doesn't need to be exposed
3477-
PendingOutboundPayment::InvoiceReceived { .. } => {
3473+
PendingOutboundPayment::AwaitingInvoice { .. }
3474+
| PendingOutboundPayment::AwaitingOffer { .. }
3475+
// InvoiceReceived is an intermediate state and doesn't need to be exposed
3476+
| PendingOutboundPayment::InvoiceReceived { .. } =>
3477+
{
34783478
Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
34793479
},
34803480
PendingOutboundPayment::StaticInvoiceReceived { .. } => {
@@ -11959,6 +11959,7 @@ where
1195911959
}
1196011960
}
1196111961
PendingOutboundPayment::AwaitingInvoice { .. } => {},
11962+
PendingOutboundPayment::AwaitingOffer { .. } => {},
1196211963
PendingOutboundPayment::InvoiceReceived { .. } => {},
1196311964
PendingOutboundPayment::StaticInvoiceReceived { .. } => {},
1196411965
PendingOutboundPayment::Fulfilled { .. } => {},

lightning/src/ln/outbound_payment.rs

Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,15 @@ pub(crate) enum PendingOutboundPayment {
5858
Legacy {
5959
session_privs: HashSet<[u8; 32]>,
6060
},
61+
/// Used when we are waiting for an Offer to come back from a BIP 353 resolution
62+
AwaitingOffer {
63+
expiration: StaleExpiration,
64+
retry_strategy: Retry,
65+
max_total_routing_fee_msat: Option<u64>,
66+
/// Human Readable Names-originated payments should always specify an explicit amount to
67+
/// send up-front, which we track here and enforce once we receive the offer.
68+
amount_msats: u64,
69+
},
6170
AwaitingInvoice {
6271
expiration: StaleExpiration,
6372
retry_strategy: Retry,
@@ -199,6 +208,7 @@ impl PendingOutboundPayment {
199208
fn payment_hash(&self) -> Option<PaymentHash> {
200209
match self {
201210
PendingOutboundPayment::Legacy { .. } => None,
211+
PendingOutboundPayment::AwaitingOffer { .. } => None,
202212
PendingOutboundPayment::AwaitingInvoice { .. } => None,
203213
PendingOutboundPayment::InvoiceReceived { payment_hash, .. } => Some(*payment_hash),
204214
PendingOutboundPayment::StaticInvoiceReceived { payment_hash, .. } => Some(*payment_hash),
@@ -215,7 +225,8 @@ impl PendingOutboundPayment {
215225
PendingOutboundPayment::Retryable { session_privs, .. } |
216226
PendingOutboundPayment::Fulfilled { session_privs, .. } |
217227
PendingOutboundPayment::Abandoned { session_privs, .. } => session_privs,
218-
PendingOutboundPayment::AwaitingInvoice { .. } |
228+
PendingOutboundPayment::AwaitingOffer { .. } |
229+
PendingOutboundPayment::AwaitingInvoice { .. } |
219230
PendingOutboundPayment::InvoiceReceived { .. } |
220231
PendingOutboundPayment::StaticInvoiceReceived { .. } => { debug_assert!(false); return; },
221232
});
@@ -256,7 +267,8 @@ impl PendingOutboundPayment {
256267
PendingOutboundPayment::Abandoned { session_privs, .. } => {
257268
session_privs.remove(session_priv)
258269
},
259-
PendingOutboundPayment::AwaitingInvoice { .. } |
270+
PendingOutboundPayment::AwaitingOffer { .. } |
271+
PendingOutboundPayment::AwaitingInvoice { .. } |
260272
PendingOutboundPayment::InvoiceReceived { .. } |
261273
PendingOutboundPayment::StaticInvoiceReceived { .. } => { debug_assert!(false); false },
262274
};
@@ -286,7 +298,8 @@ impl PendingOutboundPayment {
286298
PendingOutboundPayment::Retryable { session_privs, .. } => {
287299
session_privs.insert(session_priv)
288300
},
289-
PendingOutboundPayment::AwaitingInvoice { .. } |
301+
PendingOutboundPayment::AwaitingOffer { .. } |
302+
PendingOutboundPayment::AwaitingInvoice { .. } |
290303
PendingOutboundPayment::InvoiceReceived { .. } |
291304
PendingOutboundPayment::StaticInvoiceReceived { .. } => { debug_assert!(false); false },
292305
PendingOutboundPayment::Fulfilled { .. } => false,
@@ -320,6 +333,7 @@ impl PendingOutboundPayment {
320333
session_privs.len()
321334
},
322335
PendingOutboundPayment::AwaitingInvoice { .. } => 0,
336+
PendingOutboundPayment::AwaitingOffer { .. } => 0,
323337
PendingOutboundPayment::InvoiceReceived { .. } => 0,
324338
PendingOutboundPayment::StaticInvoiceReceived { .. } => 0,
325339
}
@@ -414,8 +428,9 @@ impl Display for PaymentAttempts {
414428
}
415429
}
416430

417-
/// How long before a [`PendingOutboundPayment::AwaitingInvoice`] should be considered stale and
418-
/// candidate for removal in [`OutboundPayments::remove_stale_payments`].
431+
/// How long before a [`PendingOutboundPayment::AwaitingInvoice`] or
432+
/// [`PendingOutboundPayment::AwaitingOffer`] should be considered stale and candidate for removal
433+
/// in [`OutboundPayments::remove_stale_payments`].
419434
#[derive(Clone, Copy)]
420435
pub(crate) enum StaleExpiration {
421436
/// Number of times [`OutboundPayments::remove_stale_payments`] is called.
@@ -1363,7 +1378,9 @@ impl OutboundPayments {
13631378
log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102");
13641379
return
13651380
},
1366-
PendingOutboundPayment::AwaitingInvoice { .. } => {
1381+
PendingOutboundPayment::AwaitingInvoice { .. }
1382+
| PendingOutboundPayment::AwaitingOffer { .. } =>
1383+
{
13671384
log_error!(logger, "Payment not yet sent");
13681385
debug_assert!(false);
13691386
return
@@ -1882,7 +1899,9 @@ impl OutboundPayments {
18821899
true
18831900
}
18841901
},
1885-
PendingOutboundPayment::AwaitingInvoice { expiration, .. } => {
1902+
PendingOutboundPayment::AwaitingInvoice { expiration, .. }
1903+
| PendingOutboundPayment::AwaitingOffer { expiration, .. } =>
1904+
{
18861905
let is_stale = match expiration {
18871906
StaleExpiration::AbsoluteTimeout(absolute_expiry) => {
18881907
*absolute_expiry <= duration_since_epoch
@@ -2068,22 +2087,28 @@ impl OutboundPayments {
20682087
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
20692088
if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) {
20702089
payment.get_mut().mark_abandoned(reason);
2071-
if let PendingOutboundPayment::Abandoned { payment_hash, reason, .. } = payment.get() {
2072-
if payment.get().remaining_parts() == 0 {
2090+
match payment.get() {
2091+
PendingOutboundPayment::Abandoned { payment_hash, reason, .. } => {
2092+
if payment.get().remaining_parts() == 0 {
2093+
pending_events.lock().unwrap().push_back((events::Event::PaymentFailed {
2094+
payment_id,
2095+
payment_hash: Some(*payment_hash),
2096+
reason: *reason,
2097+
}, None));
2098+
payment.remove();
2099+
}
2100+
},
2101+
PendingOutboundPayment::AwaitingInvoice { .. }
2102+
| PendingOutboundPayment::AwaitingOffer { .. } =>
2103+
{
20732104
pending_events.lock().unwrap().push_back((events::Event::PaymentFailed {
20742105
payment_id,
2075-
payment_hash: Some(*payment_hash),
2076-
reason: *reason,
2106+
payment_hash: None,
2107+
reason: Some(reason),
20772108
}, None));
20782109
payment.remove();
2079-
}
2080-
} else if let PendingOutboundPayment::AwaitingInvoice { .. } = payment.get() {
2081-
pending_events.lock().unwrap().push_back((events::Event::PaymentFailed {
2082-
payment_id,
2083-
payment_hash: None,
2084-
reason: Some(reason),
2085-
}, None));
2086-
payment.remove();
2110+
},
2111+
_ => {},
20872112
}
20882113
}
20892114
}
@@ -2154,7 +2179,8 @@ impl OutboundPayments {
21542179
match self.pending_outbound_payments.lock().unwrap().entry(payment_id) {
21552180
hash_map::Entry::Occupied(mut entry) => {
21562181
let newly_added = match entry.get() {
2157-
PendingOutboundPayment::AwaitingInvoice { .. } |
2182+
PendingOutboundPayment::AwaitingOffer { .. } |
2183+
PendingOutboundPayment::AwaitingInvoice { .. } |
21582184
PendingOutboundPayment::InvoiceReceived { .. } |
21592185
PendingOutboundPayment::StaticInvoiceReceived { .. } =>
21602186
{
@@ -2254,6 +2280,14 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
22542280
(4, retry_strategy, required),
22552281
(6, route_params, required),
22562282
},
2283+
// Added in 0.1. Prior versions will drop these outbounds on downgrade, which is safe because
2284+
// no HTLCs are in-flight.
2285+
(11, AwaitingOffer) => {
2286+
(0, expiration, required),
2287+
(2, retry_strategy, required),
2288+
(4, max_total_routing_fee_msat, option),
2289+
(6, amount_msats, required),
2290+
},
22572291
);
22582292

22592293
#[cfg(test)]

0 commit comments

Comments
 (0)