@@ -29,6 +29,7 @@ use crate::util::ser::ReadableArgs;
29
29
30
30
use core:: fmt:: { self , Display , Formatter } ;
31
31
use core:: ops:: Deref ;
32
+ use core:: time:: Duration ;
32
33
33
34
use crate :: prelude:: * ;
34
35
use crate :: sync:: Mutex ;
@@ -39,20 +40,14 @@ use crate::sync::Mutex;
39
40
/// [`ChannelManager::timer_tick_occurred`]: crate::ln::channelmanager::ChannelManager::timer_tick_occurred
40
41
pub ( crate ) const IDEMPOTENCY_TIMEOUT_TICKS : u8 = 7 ;
41
42
42
- /// The number of ticks of [`ChannelManager::timer_tick_occurred`] until an invoice request without
43
- /// a response is timed out.
44
- ///
45
- /// [`ChannelManager::timer_tick_occurred`]: crate::ln::channelmanager::ChannelManager::timer_tick_occurred
46
- const INVOICE_REQUEST_TIMEOUT_TICKS : Option < u64 > = Some ( 3 ) ;
47
-
48
43
/// Stores the session_priv for each part of a payment that is still pending. For versions 0.0.102
49
44
/// and later, also stores information for retrying the payment.
50
45
pub ( crate ) enum PendingOutboundPayment {
51
46
Legacy {
52
47
session_privs : HashSet < [ u8 ; 32 ] > ,
53
48
} ,
54
49
AwaitingInvoice {
55
- timer_ticks_without_response_remaining : Option < u64 > ,
50
+ absolute_expiry : Duration ,
56
51
retry_strategy : Retry ,
57
52
max_total_routing_fee_msat : Option < u64 > ,
58
53
} ,
@@ -1273,36 +1268,17 @@ impl OutboundPayments {
1273
1268
( payment, onion_session_privs)
1274
1269
}
1275
1270
1276
- #[ allow( unused) ]
1277
- pub ( super ) fn add_new_awaiting_invoice_for_offer (
1278
- & self , payment_id : PaymentId , retry_strategy : Retry , max_total_routing_fee_msat : Option < u64 >
1279
- ) -> Result < ( ) , ( ) > {
1280
- self . add_new_awaiting_invoice (
1281
- payment_id, retry_strategy, max_total_routing_fee_msat, INVOICE_REQUEST_TIMEOUT_TICKS
1282
- )
1283
- }
1284
-
1285
- #[ allow( unused) ]
1286
- pub ( super ) fn add_new_awaiting_invoice_for_refund (
1287
- & self , payment_id : PaymentId , retry_strategy : Retry ,
1288
- max_total_routing_fee_msat : Option < u64 > , timer_ticks_before_expiration : Option < u64 >
1289
- ) -> Result < ( ) , ( ) > {
1290
- self . add_new_awaiting_invoice (
1291
- payment_id, retry_strategy, max_total_routing_fee_msat, timer_ticks_before_expiration
1292
- )
1293
- }
1294
-
1295
1271
#[ allow( unused) ]
1296
1272
fn add_new_awaiting_invoice (
1297
- & self , payment_id : PaymentId , retry_strategy : Retry ,
1298
- max_total_routing_fee_msat : Option < u64 > , timer_ticks_before_expiration : Option < u64 >
1273
+ & self , payment_id : PaymentId , absolute_expiry : Duration , retry_strategy : Retry ,
1274
+ max_total_routing_fee_msat : Option < u64 >
1299
1275
) -> Result < ( ) , ( ) > {
1300
1276
let mut pending_outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
1301
1277
match pending_outbounds. entry ( payment_id) {
1302
1278
hash_map:: Entry :: Occupied ( _) => Err ( ( ) ) ,
1303
1279
hash_map:: Entry :: Vacant ( entry) => {
1304
1280
entry. insert ( PendingOutboundPayment :: AwaitingInvoice {
1305
- timer_ticks_without_response_remaining : timer_ticks_before_expiration ,
1281
+ absolute_expiry ,
1306
1282
retry_strategy,
1307
1283
max_total_routing_fee_msat,
1308
1284
} ) ;
@@ -1531,22 +1507,23 @@ impl OutboundPayments {
1531
1507
}
1532
1508
1533
1509
pub ( super ) fn remove_stale_payments (
1534
- & self , pending_events : & Mutex < VecDeque < ( events:: Event , Option < EventCompletionAction > ) > > )
1510
+ & self , duration_since_epoch : Duration ,
1511
+ pending_events : & Mutex < VecDeque < ( events:: Event , Option < EventCompletionAction > ) > > )
1535
1512
{
1536
1513
let mut pending_outbound_payments = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
1537
1514
#[ cfg( not( invreqfailed) ) ]
1538
1515
let pending_events = pending_events. lock ( ) . unwrap ( ) ;
1539
1516
#[ cfg( invreqfailed) ]
1540
1517
let mut pending_events = pending_events. lock ( ) . unwrap ( ) ;
1541
- pending_outbound_payments. retain ( |payment_id, payment| {
1518
+ pending_outbound_payments. retain ( |payment_id, payment| match payment {
1542
1519
// If an outbound payment was completed, and no pending HTLCs remain, we should remove it
1543
1520
// from the map. However, if we did that immediately when the last payment HTLC is claimed,
1544
1521
// this could race the user making a duplicate send_payment call and our idempotency
1545
1522
// guarantees would be violated. Instead, we wait a few timer ticks to do the actual
1546
1523
// removal. This should be more than sufficient to ensure the idempotency of any
1547
1524
// `send_payment` calls that were made at the same time the `PaymentSent` event was being
1548
1525
// processed.
1549
- if let PendingOutboundPayment :: Fulfilled { session_privs, timer_ticks_without_htlcs, .. } = payment {
1526
+ PendingOutboundPayment :: Fulfilled { session_privs, timer_ticks_without_htlcs, .. } => {
1550
1527
let mut no_remaining_entries = session_privs. is_empty ( ) ;
1551
1528
if no_remaining_entries {
1552
1529
for ( ev, _) in pending_events. iter ( ) {
@@ -1570,11 +1547,9 @@ impl OutboundPayments {
1570
1547
* timer_ticks_without_htlcs = 0 ;
1571
1548
true
1572
1549
}
1573
- } else if let PendingOutboundPayment :: AwaitingInvoice {
1574
- timer_ticks_without_response_remaining : Some ( timer_ticks_remaining) , ..
1575
- } = payment {
1576
- if * timer_ticks_remaining > 0 {
1577
- * timer_ticks_remaining -= 1 ;
1550
+ } ,
1551
+ PendingOutboundPayment :: AwaitingInvoice { absolute_expiry, .. } => {
1552
+ if duration_since_epoch < * absolute_expiry {
1578
1553
true
1579
1554
} else {
1580
1555
#[ cfg( invreqfailed) ]
@@ -1583,7 +1558,8 @@ impl OutboundPayments {
1583
1558
) ;
1584
1559
false
1585
1560
}
1586
- } else { true }
1561
+ } ,
1562
+ _ => true ,
1587
1563
} ) ;
1588
1564
}
1589
1565
@@ -1800,7 +1776,7 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
1800
1776
( 2 , payment_hash, required) ,
1801
1777
} ,
1802
1778
( 5 , AwaitingInvoice ) => {
1803
- ( 0 , timer_ticks_without_response_remaining , option ) ,
1779
+ ( 0 , absolute_expiry , required ) ,
1804
1780
( 2 , retry_strategy, required) ,
1805
1781
( 4 , max_total_routing_fee_msat, option) ,
1806
1782
} ,
@@ -1816,14 +1792,14 @@ mod tests {
1816
1792
use bitcoin:: network:: constants:: Network ;
1817
1793
use bitcoin:: secp256k1:: { PublicKey , Secp256k1 , SecretKey } ;
1818
1794
1795
+ use core:: time:: Duration ;
1796
+
1819
1797
use crate :: events:: { Event , PathFailure , PaymentFailureReason } ;
1820
1798
use crate :: ln:: PaymentHash ;
1821
1799
use crate :: ln:: channelmanager:: { PaymentId , RecipientOnionFields } ;
1822
1800
use crate :: ln:: features:: { ChannelFeatures , NodeFeatures } ;
1823
1801
use crate :: ln:: msgs:: { ErrorAction , LightningError } ;
1824
1802
use crate :: ln:: outbound_payment:: { Bolt12PaymentError , OutboundPayments , Retry , RetryableSendFailure } ;
1825
- #[ cfg( invreqfailed) ]
1826
- use crate :: ln:: outbound_payment:: INVOICE_REQUEST_TIMEOUT_TICKS ;
1827
1803
use crate :: offers:: invoice:: DEFAULT_RELATIVE_EXPIRY ;
1828
1804
use crate :: offers:: offer:: OfferBuilder ;
1829
1805
use crate :: offers:: test_utils:: * ;
@@ -2033,22 +2009,28 @@ mod tests {
2033
2009
let pending_events = Mutex :: new ( VecDeque :: new ( ) ) ;
2034
2010
let outbound_payments = OutboundPayments :: new ( ) ;
2035
2011
let payment_id = PaymentId ( [ 0 ; 32 ] ) ;
2012
+ let absolute_expiry = 100 ;
2013
+ let tick_interval = 10 ;
2036
2014
2037
2015
assert ! ( !outbound_payments. has_pending_payments( ) ) ;
2038
2016
assert ! (
2039
2017
outbound_payments. add_new_awaiting_invoice(
2040
- payment_id, Retry :: Attempts ( 0 ) , None , INVOICE_REQUEST_TIMEOUT_TICKS
2018
+ payment_id, Duration :: from_secs ( absolute_expiry ) , Retry :: Attempts ( 0 ) , None
2041
2019
) . is_ok( )
2042
2020
) ;
2043
2021
assert ! ( outbound_payments. has_pending_payments( ) ) ;
2044
2022
2045
- for _ in 0 ..INVOICE_REQUEST_TIMEOUT_TICKS . unwrap ( ) {
2046
- outbound_payments. remove_stale_payments ( & pending_events) ;
2023
+ for seconds_since_epoch in ( 0 ..absolute_expiry) . step_by ( tick_interval) {
2024
+ let duration_since_epoch = Duration :: from_secs ( seconds_since_epoch) ;
2025
+ outbound_payments. remove_stale_payments ( duration_since_epoch, & pending_events) ;
2026
+
2047
2027
assert ! ( outbound_payments. has_pending_payments( ) ) ;
2048
2028
assert ! ( pending_events. lock( ) . unwrap( ) . is_empty( ) ) ;
2049
2029
}
2050
2030
2051
- outbound_payments. remove_stale_payments ( & pending_events) ;
2031
+ let duration_since_epoch = Duration :: from_secs ( absolute_expiry) ;
2032
+ outbound_payments. remove_stale_payments ( duration_since_epoch, & pending_events) ;
2033
+
2052
2034
assert ! ( !outbound_payments. has_pending_payments( ) ) ;
2053
2035
assert ! ( !pending_events. lock( ) . unwrap( ) . is_empty( ) ) ;
2054
2036
assert_eq ! (
@@ -2059,14 +2041,14 @@ mod tests {
2059
2041
2060
2042
assert ! (
2061
2043
outbound_payments. add_new_awaiting_invoice(
2062
- payment_id, Retry :: Attempts ( 0 ) , None , INVOICE_REQUEST_TIMEOUT_TICKS
2044
+ payment_id, Duration :: from_secs ( absolute_expiry + 1 ) , Retry :: Attempts ( 0 ) , None
2063
2045
) . is_ok( )
2064
2046
) ;
2065
2047
assert ! ( outbound_payments. has_pending_payments( ) ) ;
2066
2048
2067
2049
assert ! (
2068
2050
outbound_payments. add_new_awaiting_invoice(
2069
- payment_id, Retry :: Attempts ( 0 ) , None , INVOICE_REQUEST_TIMEOUT_TICKS
2051
+ payment_id, Duration :: from_secs ( absolute_expiry + 1 ) , Retry :: Attempts ( 0 ) , None
2070
2052
) . is_err( )
2071
2053
) ;
2072
2054
}
@@ -2077,11 +2059,12 @@ mod tests {
2077
2059
let pending_events = Mutex :: new ( VecDeque :: new ( ) ) ;
2078
2060
let outbound_payments = OutboundPayments :: new ( ) ;
2079
2061
let payment_id = PaymentId ( [ 0 ; 32 ] ) ;
2062
+ let absolute_expiry = 100 ;
2080
2063
2081
2064
assert ! ( !outbound_payments. has_pending_payments( ) ) ;
2082
2065
assert ! (
2083
2066
outbound_payments. add_new_awaiting_invoice(
2084
- payment_id, Retry :: Attempts ( 0 ) , None , INVOICE_REQUEST_TIMEOUT_TICKS
2067
+ payment_id, Duration :: from_secs ( absolute_expiry ) , Retry :: Attempts ( 0 ) , None
2085
2068
) . is_ok( )
2086
2069
) ;
2087
2070
assert ! ( outbound_payments. has_pending_payments( ) ) ;
@@ -2110,10 +2093,11 @@ mod tests {
2110
2093
let pending_events = Mutex :: new ( VecDeque :: new ( ) ) ;
2111
2094
let outbound_payments = OutboundPayments :: new ( ) ;
2112
2095
let payment_id = PaymentId ( [ 0 ; 32 ] ) ;
2096
+ let absolute_expiry = 100 ;
2113
2097
2114
2098
assert ! (
2115
2099
outbound_payments. add_new_awaiting_invoice(
2116
- payment_id, Retry :: Attempts ( 0 ) , None , INVOICE_REQUEST_TIMEOUT_TICKS
2100
+ payment_id, Duration :: from_secs ( absolute_expiry ) , Retry :: Attempts ( 0 ) , None
2117
2101
) . is_ok( )
2118
2102
) ;
2119
2103
assert ! ( outbound_payments. has_pending_payments( ) ) ;
@@ -2160,6 +2144,7 @@ mod tests {
2160
2144
let pending_events = Mutex :: new ( VecDeque :: new ( ) ) ;
2161
2145
let outbound_payments = OutboundPayments :: new ( ) ;
2162
2146
let payment_id = PaymentId ( [ 0 ; 32 ] ) ;
2147
+ let absolute_expiry = 100 ;
2163
2148
2164
2149
let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
2165
2150
. amount_msats ( 1000 )
@@ -2173,8 +2158,8 @@ mod tests {
2173
2158
2174
2159
assert ! (
2175
2160
outbound_payments. add_new_awaiting_invoice(
2176
- payment_id, Retry :: Attempts ( 0 ) , Some ( invoice . amount_msats ( ) / 100 + 50_000 ) ,
2177
- INVOICE_REQUEST_TIMEOUT_TICKS
2161
+ payment_id, Duration :: from_secs ( absolute_expiry ) , Retry :: Attempts ( 0 ) ,
2162
+ Some ( invoice . amount_msats ( ) / 100 + 50_000 )
2178
2163
) . is_ok( )
2179
2164
) ;
2180
2165
assert ! ( outbound_payments. has_pending_payments( ) ) ;
@@ -2218,6 +2203,7 @@ mod tests {
2218
2203
let pending_events = Mutex :: new ( VecDeque :: new ( ) ) ;
2219
2204
let outbound_payments = OutboundPayments :: new ( ) ;
2220
2205
let payment_id = PaymentId ( [ 0 ; 32 ] ) ;
2206
+ let absolute_expiry = 100 ;
2221
2207
2222
2208
let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
2223
2209
. amount_msats ( 1000 )
@@ -2231,8 +2217,8 @@ mod tests {
2231
2217
2232
2218
assert ! (
2233
2219
outbound_payments. add_new_awaiting_invoice(
2234
- payment_id, Retry :: Attempts ( 0 ) , Some ( invoice . amount_msats ( ) / 100 + 50_000 ) ,
2235
- INVOICE_REQUEST_TIMEOUT_TICKS
2220
+ payment_id, Duration :: from_secs ( absolute_expiry ) , Retry :: Attempts ( 0 ) ,
2221
+ Some ( invoice . amount_msats ( ) / 100 + 50_000 )
2236
2222
) . is_ok( )
2237
2223
) ;
2238
2224
assert ! ( outbound_payments. has_pending_payments( ) ) ;
@@ -2276,6 +2262,7 @@ mod tests {
2276
2262
let pending_events = Mutex :: new ( VecDeque :: new ( ) ) ;
2277
2263
let outbound_payments = OutboundPayments :: new ( ) ;
2278
2264
let payment_id = PaymentId ( [ 0 ; 32 ] ) ;
2265
+ let absolute_expiry = 100 ;
2279
2266
2280
2267
let invoice = OfferBuilder :: new ( "foo" . into ( ) , recipient_pubkey ( ) )
2281
2268
. amount_msats ( 1000 )
@@ -2328,7 +2315,7 @@ mod tests {
2328
2315
2329
2316
assert ! (
2330
2317
outbound_payments. add_new_awaiting_invoice(
2331
- payment_id, Retry :: Attempts ( 0 ) , Some ( 1234 ) , INVOICE_REQUEST_TIMEOUT_TICKS
2318
+ payment_id, Duration :: from_secs ( absolute_expiry ) , Retry :: Attempts ( 0 ) , Some ( 1234 )
2332
2319
) . is_ok( )
2333
2320
) ;
2334
2321
assert ! ( outbound_payments. has_pending_payments( ) ) ;
0 commit comments