Skip to content

Commit 0d9ef1f

Browse files
committed
Add a new AwaitingOffer outbound payment state for BIP 353
1 parent 41627c6 commit 0d9ef1f

File tree

2 files changed

+56
-21
lines changed

2 files changed

+56
-21
lines changed

lightning/src/ln/channelmanager.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3329,11 +3329,11 @@ where
33293329
pub fn list_recent_payments(&self) -> Vec<RecentPaymentDetails> {
33303330
self.pending_outbound_payments.pending_outbound_payments.lock().unwrap().iter()
33313331
.filter_map(|(payment_id, pending_outbound_payment)| match pending_outbound_payment {
3332-
PendingOutboundPayment::AwaitingInvoice { .. } => {
3333-
Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
3334-
},
3335-
// InvoiceReceived is an intermediate state and doesn't need to be exposed
3336-
PendingOutboundPayment::InvoiceReceived { .. } => {
3332+
PendingOutboundPayment::AwaitingInvoice { .. }
3333+
| PendingOutboundPayment::AwaitingOffer { .. }
3334+
// InvoiceReceived is an intermediate state and doesn't need to be exposed
3335+
| PendingOutboundPayment::InvoiceReceived { .. } =>
3336+
{
33373337
Some(RecentPaymentDetails::AwaitingInvoice { payment_id: *payment_id })
33383338
},
33393339
PendingOutboundPayment::Retryable { payment_hash, total_msat, .. } => {
@@ -11620,6 +11620,7 @@ where
1162011620
}
1162111621
}
1162211622
PendingOutboundPayment::AwaitingInvoice { .. } => {},
11623+
PendingOutboundPayment::AwaitingOffer { .. } => {},
1162311624
PendingOutboundPayment::InvoiceReceived { .. } => {},
1162411625
PendingOutboundPayment::Fulfilled { .. } => {},
1162511626
PendingOutboundPayment::Abandoned { .. } => {},

lightning/src/ln/outbound_payment.rs

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use crate::ln::features::Bolt12InvoiceFeatures;
2222
use crate::ln::onion_utils;
2323
use crate::ln::onion_utils::{DecodedOnionFailure, HTLCFailReason};
2424
use crate::offers::invoice::Bolt12Invoice;
25+
use crate::onion_message::dns_resolution::HumanReadableName;
2526
use crate::routing::router::{BlindedTail, InFlightHtlcs, Path, PaymentParameters, Route, RouteParameters, Router};
2627
use crate::sign::{EntropySource, NodeSigner, Recipient};
2728
use crate::util::errors::APIError;
@@ -49,6 +50,16 @@ pub(crate) enum PendingOutboundPayment {
4950
Legacy {
5051
session_privs: HashSet<[u8; 32]>,
5152
},
53+
/// Used when we are waiting for an Offer to come back from a BIP 353 resolution
54+
AwaitingOffer {
55+
expiration: StaleExpiration,
56+
retry_strategy: Retry,
57+
max_total_routing_fee_msat: Option<u64>,
58+
/// Human Readable Names-originated payments should always specify an explicit amount to
59+
/// send up-front, which we track here and enforce once we receive the offer.
60+
amount_msats: u64,
61+
resolving_hrn: HumanReadableName,
62+
},
5263
AwaitingInvoice {
5364
expiration: StaleExpiration,
5465
retry_strategy: Retry,
@@ -166,6 +177,7 @@ impl PendingOutboundPayment {
166177
fn payment_hash(&self) -> Option<PaymentHash> {
167178
match self {
168179
PendingOutboundPayment::Legacy { .. } => None,
180+
PendingOutboundPayment::AwaitingOffer { .. } => None,
169181
PendingOutboundPayment::AwaitingInvoice { .. } => None,
170182
PendingOutboundPayment::InvoiceReceived { payment_hash, .. } => Some(*payment_hash),
171183
PendingOutboundPayment::Retryable { payment_hash, .. } => Some(*payment_hash),
@@ -182,6 +194,7 @@ impl PendingOutboundPayment {
182194
PendingOutboundPayment::Fulfilled { session_privs, .. } |
183195
PendingOutboundPayment::Abandoned { session_privs, .. } => session_privs,
184196
PendingOutboundPayment::AwaitingInvoice { .. } |
197+
PendingOutboundPayment::AwaitingOffer { .. } |
185198
PendingOutboundPayment::InvoiceReceived { .. } => { debug_assert!(false); return; },
186199
});
187200
let payment_hash = self.payment_hash();
@@ -216,6 +229,7 @@ impl PendingOutboundPayment {
216229
session_privs.remove(session_priv)
217230
},
218231
PendingOutboundPayment::AwaitingInvoice { .. } |
232+
PendingOutboundPayment::AwaitingOffer { .. } |
219233
PendingOutboundPayment::InvoiceReceived { .. } => { debug_assert!(false); false },
220234
};
221235
if remove_res {
@@ -245,6 +259,7 @@ impl PendingOutboundPayment {
245259
session_privs.insert(session_priv)
246260
},
247261
PendingOutboundPayment::AwaitingInvoice { .. } |
262+
PendingOutboundPayment::AwaitingOffer { .. } |
248263
PendingOutboundPayment::InvoiceReceived { .. } => { debug_assert!(false); false },
249264
PendingOutboundPayment::Fulfilled { .. } => false,
250265
PendingOutboundPayment::Abandoned { .. } => false,
@@ -277,6 +292,7 @@ impl PendingOutboundPayment {
277292
session_privs.len()
278293
},
279294
PendingOutboundPayment::AwaitingInvoice { .. } => 0,
295+
PendingOutboundPayment::AwaitingOffer { .. } => 0,
280296
PendingOutboundPayment::InvoiceReceived { .. } => 0,
281297
}
282298
}
@@ -370,8 +386,9 @@ impl Display for PaymentAttempts {
370386
}
371387
}
372388

373-
/// How long before a [`PendingOutboundPayment::AwaitingInvoice`] should be considered stale and
374-
/// candidate for removal in [`OutboundPayments::remove_stale_payments`].
389+
/// How long before a [`PendingOutboundPayment::AwaitingInvoice`] or
390+
/// [`PendingOutboundPayment::AwaitingOffer`] should be considered stale and candidate for removal
391+
/// in [`OutboundPayments::remove_stale_payments`].
375392
#[derive(Clone, Copy)]
376393
pub(crate) enum StaleExpiration {
377394
/// Number of times [`OutboundPayments::remove_stale_payments`] is called.
@@ -1165,7 +1182,9 @@ impl OutboundPayments {
11651182
log_error!(logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102");
11661183
return
11671184
},
1168-
PendingOutboundPayment::AwaitingInvoice { .. } => {
1185+
PendingOutboundPayment::AwaitingInvoice { .. }
1186+
| PendingOutboundPayment::AwaitingOffer { .. } =>
1187+
{
11691188
log_error!(logger, "Payment not yet sent");
11701189
debug_assert!(false);
11711190
return
@@ -1675,7 +1694,9 @@ impl OutboundPayments {
16751694
true
16761695
}
16771696
},
1678-
PendingOutboundPayment::AwaitingInvoice { expiration, .. } => {
1697+
PendingOutboundPayment::AwaitingInvoice { expiration, .. }
1698+
| PendingOutboundPayment::AwaitingOffer { expiration, .. } =>
1699+
{
16791700
let is_stale = match expiration {
16801701
StaleExpiration::AbsoluteTimeout(absolute_expiry) => {
16811702
*absolute_expiry <= duration_since_epoch
@@ -1845,22 +1866,28 @@ impl OutboundPayments {
18451866
let mut outbounds = self.pending_outbound_payments.lock().unwrap();
18461867
if let hash_map::Entry::Occupied(mut payment) = outbounds.entry(payment_id) {
18471868
payment.get_mut().mark_abandoned(reason);
1848-
if let PendingOutboundPayment::Abandoned { payment_hash, reason, .. } = payment.get() {
1849-
if payment.get().remaining_parts() == 0 {
1869+
match payment.get() {
1870+
PendingOutboundPayment::Abandoned { payment_hash, reason, .. } => {
1871+
if payment.get().remaining_parts() == 0 {
1872+
pending_events.lock().unwrap().push_back((events::Event::PaymentFailed {
1873+
payment_id,
1874+
payment_hash: Some(*payment_hash),
1875+
reason: *reason,
1876+
}, None));
1877+
payment.remove();
1878+
}
1879+
},
1880+
PendingOutboundPayment::AwaitingInvoice { .. }
1881+
| PendingOutboundPayment::AwaitingOffer { .. } =>
1882+
{
18501883
pending_events.lock().unwrap().push_back((events::Event::PaymentFailed {
18511884
payment_id,
1852-
payment_hash: Some(*payment_hash),
1853-
reason: *reason,
1885+
payment_hash: None,
1886+
reason: Some(reason),
18541887
}, None));
18551888
payment.remove();
1856-
}
1857-
} else if let PendingOutboundPayment::AwaitingInvoice { .. } = payment.get() {
1858-
pending_events.lock().unwrap().push_back((events::Event::PaymentFailed {
1859-
payment_id,
1860-
payment_hash: None,
1861-
reason: Some(reason),
1862-
}, None));
1863-
payment.remove();
1889+
},
1890+
_ => {},
18641891
}
18651892
}
18661893
}
@@ -1935,6 +1962,13 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
19351962
(2, retry_strategy, required),
19361963
(4, max_total_routing_fee_msat, option),
19371964
},
1965+
(9, AwaitingOffer) => {
1966+
(0, expiration, required),
1967+
(2, retry_strategy, required),
1968+
(4, max_total_routing_fee_msat, option),
1969+
(6, amount_msats, required),
1970+
(8, resolving_hrn, required),
1971+
},
19381972
);
19391973

19401974
#[cfg(test)]

0 commit comments

Comments
 (0)