@@ -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
} ,
@@ -2279,11 +2295,12 @@ impl OutboundPayments {
2279
2295
true
2280
2296
}
2281
2297
} ,
2282
- PendingOutboundPayment :: StaticInvoiceReceived { route_params, payment_hash, .. } => {
2283
- let is_stale =
2298
+ PendingOutboundPayment :: StaticInvoiceReceived { route_params, payment_hash, expiry_time, .. } => {
2299
+ let is_stale = * expiry_time < duration_since_epoch;
2300
+ let is_static_invoice_stale =
2284
2301
route_params. payment_params . expiry_time . unwrap_or ( u64:: MAX ) <
2285
2302
duration_since_epoch. as_secs ( ) ;
2286
- if is_stale {
2303
+ if is_stale || is_static_invoice_stale {
2287
2304
let fail_ev = events:: Event :: PaymentFailed {
2288
2305
payment_id : * payment_id,
2289
2306
payment_hash : Some ( * payment_hash) ,
@@ -2698,6 +2715,9 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
2698
2715
( 6 , route_params, required) ,
2699
2716
( 8 , invoice_request, required) ,
2700
2717
( 10 , static_invoice, required) ,
2718
+ // Added in 0.2. Prior versions would have this TLV type defaulted to 0, which is safe because
2719
+ // the type is not used.
2720
+ ( 11 , expiry_time, ( default_value, Duration :: from_secs( 0 ) ) ) ,
2701
2721
} ,
2702
2722
// Added in 0.1. Prior versions will drop these outbounds on downgrade, which is safe because
2703
2723
// no HTLCs are in-flight.
@@ -3348,6 +3368,7 @@ mod tests {
3348
3368
route_params,
3349
3369
invoice_request : dummy_invoice_request ( ) ,
3350
3370
static_invoice : dummy_static_invoice ( ) ,
3371
+ expiry_time : Duration :: from_secs ( absolute_expiry + 2 ) ,
3351
3372
} ;
3352
3373
outbounds. insert ( payment_id, outbound) ;
3353
3374
core:: mem:: drop ( outbounds) ;
@@ -3397,6 +3418,7 @@ mod tests {
3397
3418
route_params,
3398
3419
invoice_request : dummy_invoice_request ( ) ,
3399
3420
static_invoice : dummy_static_invoice ( ) ,
3421
+ expiry_time : now ( ) ,
3400
3422
} ;
3401
3423
outbounds. insert ( payment_id, outbound) ;
3402
3424
core:: mem:: drop ( outbounds) ;
0 commit comments