@@ -58,6 +58,15 @@ pub(crate) enum PendingOutboundPayment {
58
58
Legacy {
59
59
session_privs : HashSet < [ u8 ; 32 ] > ,
60
60
} ,
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
+ } ,
61
70
AwaitingInvoice {
62
71
expiration : StaleExpiration ,
63
72
retry_strategy : Retry ,
@@ -201,6 +210,7 @@ impl PendingOutboundPayment {
201
210
fn payment_hash ( & self ) -> Option < PaymentHash > {
202
211
match self {
203
212
PendingOutboundPayment :: Legacy { .. } => None ,
213
+ PendingOutboundPayment :: AwaitingOffer { .. } => None ,
204
214
PendingOutboundPayment :: AwaitingInvoice { .. } => None ,
205
215
PendingOutboundPayment :: InvoiceReceived { payment_hash, .. } => Some ( * payment_hash) ,
206
216
PendingOutboundPayment :: StaticInvoiceReceived { payment_hash, .. } => Some ( * payment_hash) ,
@@ -217,7 +227,8 @@ impl PendingOutboundPayment {
217
227
PendingOutboundPayment :: Retryable { session_privs, .. } |
218
228
PendingOutboundPayment :: Fulfilled { session_privs, .. } |
219
229
PendingOutboundPayment :: Abandoned { session_privs, .. } => session_privs,
220
- PendingOutboundPayment :: AwaitingInvoice { .. } |
230
+ PendingOutboundPayment :: AwaitingOffer { .. } |
231
+ PendingOutboundPayment :: AwaitingInvoice { .. } |
221
232
PendingOutboundPayment :: InvoiceReceived { .. } |
222
233
PendingOutboundPayment :: StaticInvoiceReceived { .. } => { debug_assert ! ( false ) ; return ; } ,
223
234
} ) ;
@@ -258,7 +269,8 @@ impl PendingOutboundPayment {
258
269
PendingOutboundPayment :: Abandoned { session_privs, .. } => {
259
270
session_privs. remove ( session_priv)
260
271
} ,
261
- PendingOutboundPayment :: AwaitingInvoice { .. } |
272
+ PendingOutboundPayment :: AwaitingOffer { .. } |
273
+ PendingOutboundPayment :: AwaitingInvoice { .. } |
262
274
PendingOutboundPayment :: InvoiceReceived { .. } |
263
275
PendingOutboundPayment :: StaticInvoiceReceived { .. } => { debug_assert ! ( false ) ; false } ,
264
276
} ;
@@ -288,7 +300,8 @@ impl PendingOutboundPayment {
288
300
PendingOutboundPayment :: Retryable { session_privs, .. } => {
289
301
session_privs. insert ( session_priv)
290
302
} ,
291
- PendingOutboundPayment :: AwaitingInvoice { .. } |
303
+ PendingOutboundPayment :: AwaitingOffer { .. } |
304
+ PendingOutboundPayment :: AwaitingInvoice { .. } |
292
305
PendingOutboundPayment :: InvoiceReceived { .. } |
293
306
PendingOutboundPayment :: StaticInvoiceReceived { .. } => { debug_assert ! ( false ) ; false } ,
294
307
PendingOutboundPayment :: Fulfilled { .. } => false ,
@@ -322,6 +335,7 @@ impl PendingOutboundPayment {
322
335
session_privs. len ( )
323
336
} ,
324
337
PendingOutboundPayment :: AwaitingInvoice { .. } => 0 ,
338
+ PendingOutboundPayment :: AwaitingOffer { .. } => 0 ,
325
339
PendingOutboundPayment :: InvoiceReceived { .. } => 0 ,
326
340
PendingOutboundPayment :: StaticInvoiceReceived { .. } => 0 ,
327
341
}
@@ -416,8 +430,9 @@ impl Display for PaymentAttempts {
416
430
}
417
431
}
418
432
419
- /// How long before a [`PendingOutboundPayment::AwaitingInvoice`] should be considered stale and
420
- /// candidate for removal in [`OutboundPayments::remove_stale_payments`].
433
+ /// How long before a [`PendingOutboundPayment::AwaitingInvoice`] or
434
+ /// [`PendingOutboundPayment::AwaitingOffer`] should be considered stale and candidate for removal
435
+ /// in [`OutboundPayments::remove_stale_payments`].
421
436
#[ derive( Clone , Copy ) ]
422
437
pub ( crate ) enum StaleExpiration {
423
438
/// Number of times [`OutboundPayments::remove_stale_payments`] is called.
@@ -1388,7 +1403,9 @@ impl OutboundPayments {
1388
1403
log_error ! ( logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102" ) ;
1389
1404
return
1390
1405
} ,
1391
- PendingOutboundPayment :: AwaitingInvoice { .. } => {
1406
+ PendingOutboundPayment :: AwaitingInvoice { .. }
1407
+ | PendingOutboundPayment :: AwaitingOffer { .. } =>
1408
+ {
1392
1409
log_error ! ( logger, "Payment not yet sent" ) ;
1393
1410
debug_assert ! ( false ) ;
1394
1411
return
@@ -1910,7 +1927,9 @@ impl OutboundPayments {
1910
1927
true
1911
1928
}
1912
1929
} ,
1913
- PendingOutboundPayment :: AwaitingInvoice { expiration, .. } => {
1930
+ PendingOutboundPayment :: AwaitingInvoice { expiration, .. }
1931
+ | PendingOutboundPayment :: AwaitingOffer { expiration, .. } =>
1932
+ {
1914
1933
let is_stale = match expiration {
1915
1934
StaleExpiration :: AbsoluteTimeout ( absolute_expiry) => {
1916
1935
* absolute_expiry <= duration_since_epoch
@@ -2096,22 +2115,28 @@ impl OutboundPayments {
2096
2115
let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
2097
2116
if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( payment_id) {
2098
2117
payment. get_mut ( ) . mark_abandoned ( reason) ;
2099
- if let PendingOutboundPayment :: Abandoned { payment_hash, reason, .. } = payment. get ( ) {
2100
- if payment. get ( ) . remaining_parts ( ) == 0 {
2118
+ match payment. get ( ) {
2119
+ PendingOutboundPayment :: Abandoned { payment_hash, reason, .. } => {
2120
+ if payment. get ( ) . remaining_parts ( ) == 0 {
2121
+ pending_events. lock ( ) . unwrap ( ) . push_back ( ( events:: Event :: PaymentFailed {
2122
+ payment_id,
2123
+ payment_hash : Some ( * payment_hash) ,
2124
+ reason : * reason,
2125
+ } , None ) ) ;
2126
+ payment. remove ( ) ;
2127
+ }
2128
+ } ,
2129
+ PendingOutboundPayment :: AwaitingInvoice { .. }
2130
+ | PendingOutboundPayment :: AwaitingOffer { .. } =>
2131
+ {
2101
2132
pending_events. lock ( ) . unwrap ( ) . push_back ( ( events:: Event :: PaymentFailed {
2102
2133
payment_id,
2103
- payment_hash : Some ( * payment_hash ) ,
2104
- reason : * reason,
2134
+ payment_hash : None ,
2135
+ reason : Some ( reason) ,
2105
2136
} , None ) ) ;
2106
2137
payment. remove ( ) ;
2107
- }
2108
- } else if let PendingOutboundPayment :: AwaitingInvoice { .. } = payment. get ( ) {
2109
- pending_events. lock ( ) . unwrap ( ) . push_back ( ( events:: Event :: PaymentFailed {
2110
- payment_id,
2111
- payment_hash : None ,
2112
- reason : Some ( reason) ,
2113
- } , None ) ) ;
2114
- payment. remove ( ) ;
2138
+ } ,
2139
+ _ => { } ,
2115
2140
}
2116
2141
}
2117
2142
}
@@ -2183,7 +2208,8 @@ impl OutboundPayments {
2183
2208
match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
2184
2209
hash_map:: Entry :: Occupied ( mut entry) => {
2185
2210
let newly_added = match entry. get ( ) {
2186
- PendingOutboundPayment :: AwaitingInvoice { .. } |
2211
+ PendingOutboundPayment :: AwaitingOffer { .. } |
2212
+ PendingOutboundPayment :: AwaitingInvoice { .. } |
2187
2213
PendingOutboundPayment :: InvoiceReceived { .. } |
2188
2214
PendingOutboundPayment :: StaticInvoiceReceived { .. } =>
2189
2215
{
@@ -2285,6 +2311,14 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
2285
2311
( 6 , route_params, required) ,
2286
2312
( 8 , invoice_request, required) ,
2287
2313
} ,
2314
+ // Added in 0.1. Prior versions will drop these outbounds on downgrade, which is safe because
2315
+ // no HTLCs are in-flight.
2316
+ ( 11 , AwaitingOffer ) => {
2317
+ ( 0 , expiration, required) ,
2318
+ ( 2 , retry_strategy, required) ,
2319
+ ( 4 , max_total_routing_fee_msat, option) ,
2320
+ ( 6 , amount_msats, required) ,
2321
+ } ,
2288
2322
) ;
2289
2323
2290
2324
#[ cfg( test) ]
0 commit comments