@@ -54,6 +54,15 @@ use crate::sync::Mutex;
54
54
/// [`ChannelManager::timer_tick_occurred`]: crate::ln::channelmanager::ChannelManager::timer_tick_occurred
55
55
pub ( crate ) const IDEMPOTENCY_TIMEOUT_TICKS : u8 = 7 ;
56
56
57
+ #[ cfg( async_payments) ]
58
+ /// The default relative expiration to wait for a pending outbound HTLC to a often-offline
59
+ /// payee to fulfill.
60
+ const ASYNC_PAYMENT_TIMEOUT_RELATIVE_EXPIRY : Duration = Duration :: from_secs ( 60 * 60 * 24 * 7 ) ;
61
+
62
+ #[ cfg( all( async_payments, test) ) ]
63
+ pub ( crate ) const TEST_ASYNC_PAYMENT_TIMEOUT_RELATIVE_EXPIRY : Duration =
64
+ ASYNC_PAYMENT_TIMEOUT_RELATIVE_EXPIRY ;
65
+
57
66
/// Stores the session_priv for each part of a payment that is still pending. For versions 0.0.102
58
67
/// and later, also stores information for retrying the payment.
59
68
pub ( crate ) enum PendingOutboundPayment {
@@ -98,6 +107,11 @@ pub(crate) enum PendingOutboundPayment {
98
107
route_params : RouteParameters ,
99
108
invoice_request : InvoiceRequest ,
100
109
static_invoice : StaticInvoice ,
110
+ // The deadline as duration since the Unix epoch for the async recipient to come online,
111
+ // after which we'll fail the payment.
112
+ //
113
+ // Defaults to [`ASYNC_PAYMENT_TIMEOUT_RELATIVE_EXPIRY`].
114
+ expiry_time : Duration ,
101
115
} ,
102
116
Retryable {
103
117
retry_strategy : Option < Retry > ,
@@ -1164,6 +1178,7 @@ impl OutboundPayments {
1164
1178
abandon_with_entry ! ( entry, PaymentFailureReason :: RouteNotFound ) ;
1165
1179
return Err ( Bolt12PaymentError :: SendingFailed ( RetryableSendFailure :: OnionPacketSizeExceeded ) )
1166
1180
}
1181
+ let absolute_expiry = duration_since_epoch. saturating_add ( ASYNC_PAYMENT_TIMEOUT_RELATIVE_EXPIRY ) ;
1167
1182
1168
1183
* entry. into_mut ( ) = PendingOutboundPayment :: StaticInvoiceReceived {
1169
1184
payment_hash,
@@ -1176,6 +1191,7 @@ impl OutboundPayments {
1176
1191
. ok_or ( Bolt12PaymentError :: UnexpectedInvoice ) ?
1177
1192
. invoice_request ,
1178
1193
static_invoice : invoice. clone ( ) ,
1194
+ expiry_time : absolute_expiry,
1179
1195
} ;
1180
1196
return Ok ( ( ) )
1181
1197
} ,
@@ -2278,11 +2294,12 @@ impl OutboundPayments {
2278
2294
true
2279
2295
}
2280
2296
} ,
2281
- PendingOutboundPayment :: StaticInvoiceReceived { route_params, payment_hash, .. } => {
2282
- let is_stale =
2297
+ PendingOutboundPayment :: StaticInvoiceReceived { route_params, payment_hash, expiry_time, .. } => {
2298
+ let is_stale = * expiry_time < duration_since_epoch;
2299
+ let is_static_invoice_stale =
2283
2300
route_params. payment_params . expiry_time . unwrap_or ( u64:: MAX ) <
2284
2301
duration_since_epoch. as_secs ( ) ;
2285
- if is_stale {
2302
+ if is_stale || is_static_invoice_stale {
2286
2303
let fail_ev = events:: Event :: PaymentFailed {
2287
2304
payment_id : * payment_id,
2288
2305
payment_hash : Some ( * payment_hash) ,
@@ -2697,6 +2714,9 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
2697
2714
( 6 , route_params, required) ,
2698
2715
( 8 , invoice_request, required) ,
2699
2716
( 10 , static_invoice, required) ,
2717
+ // Added in 0.2. Prior versions would have this TLV type defaulted to 0, which is safe because
2718
+ // the type is not used.
2719
+ ( 11 , expiry_time, ( default_value, Duration :: from_secs( 0 ) ) ) ,
2700
2720
} ,
2701
2721
// Added in 0.1. Prior versions will drop these outbounds on downgrade, which is safe because
2702
2722
// no HTLCs are in-flight.
@@ -3347,6 +3367,7 @@ mod tests {
3347
3367
route_params,
3348
3368
invoice_request : dummy_invoice_request ( ) ,
3349
3369
static_invoice : dummy_static_invoice ( ) ,
3370
+ expiry_time : Duration :: from_secs ( absolute_expiry + 2 ) ,
3350
3371
} ;
3351
3372
outbounds. insert ( payment_id, outbound) ;
3352
3373
core:: mem:: drop ( outbounds) ;
@@ -3396,6 +3417,7 @@ mod tests {
3396
3417
route_params,
3397
3418
invoice_request : dummy_invoice_request ( ) ,
3398
3419
static_invoice : dummy_static_invoice ( ) ,
3420
+ expiry_time : now ( ) ,
3399
3421
} ;
3400
3422
outbounds. insert ( payment_id, outbound) ;
3401
3423
core:: mem:: drop ( outbounds) ;
0 commit comments