@@ -13,6 +13,7 @@ use bitcoin::hashes::Hash;
13
13
use bitcoin:: hashes:: sha256:: Hash as Sha256 ;
14
14
use bitcoin:: secp256k1:: { self , Secp256k1 , SecretKey } ;
15
15
16
+ use crate :: blinded_path:: message:: OffersContext ;
16
17
use crate :: blinded_path:: { IntroductionNode , NodeIdLookUp } ;
17
18
use crate :: blinded_path:: payment:: advance_path_by_one;
18
19
use crate :: events:: { self , PaymentFailureReason } ;
@@ -22,6 +23,7 @@ use crate::ln::channelmanager::{EventCompletionAction, HTLCSource, PaymentId};
22
23
use crate :: ln:: onion_utils;
23
24
use crate :: ln:: onion_utils:: { DecodedOnionFailure , HTLCFailReason } ;
24
25
use crate :: offers:: invoice:: Bolt12Invoice ;
26
+ use crate :: offers:: invoice_request:: InvoiceRequest ;
25
27
use crate :: routing:: router:: { BlindedTail , InFlightHtlcs , Path , PaymentParameters , Route , RouteParameters , Router } ;
26
28
use crate :: sign:: { EntropySource , NodeSigner , Recipient } ;
27
29
use crate :: util:: errors:: APIError ;
@@ -33,6 +35,7 @@ use crate::util::ser::ReadableArgs;
33
35
34
36
use core:: fmt:: { self , Display , Formatter } ;
35
37
use core:: ops:: Deref ;
38
+ use core:: sync:: atomic:: { AtomicBool , Ordering } ;
36
39
use core:: time:: Duration ;
37
40
38
41
use crate :: prelude:: * ;
@@ -54,6 +57,8 @@ pub(crate) enum PendingOutboundPayment {
54
57
expiration : StaleExpiration ,
55
58
retry_strategy : Retry ,
56
59
max_total_routing_fee_msat : Option < u64 > ,
60
+ invoice_request : Option < InvoiceRequest > ,
61
+ context : OffersContext ,
57
62
} ,
58
63
InvoiceReceived {
59
64
payment_hash : PaymentHash ,
@@ -684,13 +689,19 @@ pub(super) struct SendAlongPathArgs<'a> {
684
689
685
690
pub ( super ) struct OutboundPayments {
686
691
pub ( super ) pending_outbound_payments : Mutex < HashMap < PaymentId , PendingOutboundPayment > > ,
687
- pub ( super ) retry_lock : Mutex < ( ) > ,
692
+ awaiting_invoice : AtomicBool ,
693
+ retry_lock : Mutex < ( ) > ,
688
694
}
689
695
690
696
impl OutboundPayments {
691
- pub ( super ) fn new ( ) -> Self {
697
+ pub ( super ) fn new ( pending_outbound_payments : HashMap < PaymentId , PendingOutboundPayment > ) -> Self {
698
+ let has_invoice_requests = pending_outbound_payments. values ( ) . any ( |payment| {
699
+ matches ! ( payment, PendingOutboundPayment :: AwaitingInvoice { invoice_request: Some ( _) , .. } )
700
+ } ) ;
701
+
692
702
Self {
693
- pending_outbound_payments : Mutex :: new ( new_hash_map ( ) ) ,
703
+ pending_outbound_payments : Mutex :: new ( pending_outbound_payments) ,
704
+ awaiting_invoice : AtomicBool :: new ( has_invoice_requests) ,
694
705
retry_lock : Mutex :: new ( ( ) ) ,
695
706
}
696
707
}
@@ -1351,7 +1362,8 @@ impl OutboundPayments {
1351
1362
1352
1363
pub ( super ) fn add_new_awaiting_invoice (
1353
1364
& self , payment_id : PaymentId , expiration : StaleExpiration , retry_strategy : Retry ,
1354
- max_total_routing_fee_msat : Option < u64 >
1365
+ max_total_routing_fee_msat : Option < u64 > , invoice_request : Option < InvoiceRequest > ,
1366
+ context : OffersContext ,
1355
1367
) -> Result < ( ) , ( ) > {
1356
1368
let mut pending_outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
1357
1369
match pending_outbounds. entry ( payment_id) {
@@ -1361,7 +1373,10 @@ impl OutboundPayments {
1361
1373
expiration,
1362
1374
retry_strategy,
1363
1375
max_total_routing_fee_msat,
1376
+ invoice_request,
1377
+ context,
1364
1378
} ) ;
1379
+ self . awaiting_invoice . store ( true , Ordering :: Release ) ;
1365
1380
1366
1381
Ok ( ( ) )
1367
1382
} ,
@@ -1827,6 +1842,25 @@ impl OutboundPayments {
1827
1842
pub fn clear_pending_payments ( & self ) {
1828
1843
self . pending_outbound_payments . lock ( ) . unwrap ( ) . clear ( )
1829
1844
}
1845
+
1846
+ pub fn release_invoice_request_awaiting_invoice ( & self ) -> Vec < ( OffersContext , InvoiceRequest ) > {
1847
+ if !self . awaiting_invoice . load ( Ordering :: Acquire ) {
1848
+ return vec ! [ ] ;
1849
+ }
1850
+
1851
+ let mut pending_outbound_payments = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
1852
+ let invoice_requests = pending_outbound_payments. iter_mut ( )
1853
+ . filter_map ( |( _, payment) | match payment {
1854
+ PendingOutboundPayment :: AwaitingInvoice { invoice_request, context, ..} => {
1855
+ invoice_request. take ( ) . map ( |req| ( context. clone ( ) , req) )
1856
+ }
1857
+ _ => None ,
1858
+ } )
1859
+ . collect ( ) ;
1860
+
1861
+ self . awaiting_invoice . store ( false , Ordering :: Release ) ;
1862
+ invoice_requests
1863
+ }
1830
1864
}
1831
1865
1832
1866
/// Returns whether a payment with the given [`PaymentHash`] and [`PaymentId`] is, in fact, a
@@ -1882,6 +1916,8 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
1882
1916
( 0 , expiration, required) ,
1883
1917
( 2 , retry_strategy, required) ,
1884
1918
( 4 , max_total_routing_fee_msat, option) ,
1919
+ ( 5 , invoice_request, option) ,
1920
+ ( 6 , context, required) ,
1885
1921
} ,
1886
1922
( 7 , InvoiceReceived ) => {
1887
1923
( 0 , payment_hash, required) ,
@@ -1897,6 +1933,7 @@ mod tests {
1897
1933
1898
1934
use core:: time:: Duration ;
1899
1935
1936
+ use crate :: blinded_path:: message:: OffersContext ;
1900
1937
use crate :: blinded_path:: EmptyNodeIdLookUp ;
1901
1938
use crate :: events:: { Event , PathFailure , PaymentFailureReason } ;
1902
1939
use crate :: ln:: types:: PaymentHash ;
@@ -1912,6 +1949,7 @@ mod tests {
1912
1949
use crate :: routing:: router:: { InFlightHtlcs , Path , PaymentParameters , Route , RouteHop , RouteParameters } ;
1913
1950
use crate :: sync:: { Arc , Mutex , RwLock } ;
1914
1951
use crate :: util:: errors:: APIError ;
1952
+ use crate :: util:: hash_tables:: new_hash_map;
1915
1953
use crate :: util:: test_utils;
1916
1954
1917
1955
use alloc:: collections:: VecDeque ;
@@ -1946,7 +1984,7 @@ mod tests {
1946
1984
}
1947
1985
#[ cfg( feature = "std" ) ]
1948
1986
fn do_fails_paying_after_expiration ( on_retry : bool ) {
1949
- let outbound_payments = OutboundPayments :: new ( ) ;
1987
+ let outbound_payments = OutboundPayments :: new ( new_hash_map ( ) ) ;
1950
1988
let logger = test_utils:: TestLogger :: new ( ) ;
1951
1989
let network_graph = Arc :: new ( NetworkGraph :: new ( Network :: Testnet , & logger) ) ;
1952
1990
let scorer = RwLock :: new ( test_utils:: TestScorer :: new ( ) ) ;
@@ -1990,7 +2028,7 @@ mod tests {
1990
2028
do_find_route_error ( true ) ;
1991
2029
}
1992
2030
fn do_find_route_error ( on_retry : bool ) {
1993
- let outbound_payments = OutboundPayments :: new ( ) ;
2031
+ let outbound_payments = OutboundPayments :: new ( new_hash_map ( ) ) ;
1994
2032
let logger = test_utils:: TestLogger :: new ( ) ;
1995
2033
let network_graph = Arc :: new ( NetworkGraph :: new ( Network :: Testnet , & logger) ) ;
1996
2034
let scorer = RwLock :: new ( test_utils:: TestScorer :: new ( ) ) ;
@@ -2029,7 +2067,7 @@ mod tests {
2029
2067
2030
2068
#[ test]
2031
2069
fn initial_send_payment_path_failed_evs ( ) {
2032
- let outbound_payments = OutboundPayments :: new ( ) ;
2070
+ let outbound_payments = OutboundPayments :: new ( new_hash_map ( ) ) ;
2033
2071
let logger = test_utils:: TestLogger :: new ( ) ;
2034
2072
let network_graph = Arc :: new ( NetworkGraph :: new ( Network :: Testnet , & logger) ) ;
2035
2073
let scorer = RwLock :: new ( test_utils:: TestScorer :: new ( ) ) ;
@@ -2111,7 +2149,7 @@ mod tests {
2111
2149
#[ test]
2112
2150
fn removes_stale_awaiting_invoice_using_absolute_timeout ( ) {
2113
2151
let pending_events = Mutex :: new ( VecDeque :: new ( ) ) ;
2114
- let outbound_payments = OutboundPayments :: new ( ) ;
2152
+ let outbound_payments = OutboundPayments :: new ( new_hash_map ( ) ) ;
2115
2153
let payment_id = PaymentId ( [ 0 ; 32 ] ) ;
2116
2154
let absolute_expiry = 100 ;
2117
2155
let tick_interval = 10 ;
@@ -2120,7 +2158,7 @@ mod tests {
2120
2158
assert ! ( !outbound_payments. has_pending_payments( ) ) ;
2121
2159
assert ! (
2122
2160
outbound_payments. add_new_awaiting_invoice(
2123
- payment_id, expiration, Retry :: Attempts ( 0 ) , None
2161
+ payment_id, expiration, Retry :: Attempts ( 0 ) , None , None , OffersContext :: Unknown { }
2124
2162
) . is_ok( )
2125
2163
) ;
2126
2164
assert ! ( outbound_payments. has_pending_payments( ) ) ;
@@ -2146,30 +2184,30 @@ mod tests {
2146
2184
2147
2185
assert ! (
2148
2186
outbound_payments. add_new_awaiting_invoice(
2149
- payment_id, expiration, Retry :: Attempts ( 0 ) , None
2187
+ payment_id, expiration, Retry :: Attempts ( 0 ) , None , None , OffersContext :: Unknown { }
2150
2188
) . is_ok( )
2151
2189
) ;
2152
2190
assert ! ( outbound_payments. has_pending_payments( ) ) ;
2153
2191
2154
2192
assert ! (
2155
2193
outbound_payments. add_new_awaiting_invoice(
2156
- payment_id, expiration, Retry :: Attempts ( 0 ) , None
2194
+ payment_id, expiration, Retry :: Attempts ( 0 ) , None , None , OffersContext :: Unknown { }
2157
2195
) . is_err( )
2158
2196
) ;
2159
2197
}
2160
2198
2161
2199
#[ test]
2162
2200
fn removes_stale_awaiting_invoice_using_timer_ticks ( ) {
2163
2201
let pending_events = Mutex :: new ( VecDeque :: new ( ) ) ;
2164
- let outbound_payments = OutboundPayments :: new ( ) ;
2202
+ let outbound_payments = OutboundPayments :: new ( new_hash_map ( ) ) ;
2165
2203
let payment_id = PaymentId ( [ 0 ; 32 ] ) ;
2166
2204
let timer_ticks = 3 ;
2167
2205
let expiration = StaleExpiration :: TimerTicks ( timer_ticks) ;
2168
2206
2169
2207
assert ! ( !outbound_payments. has_pending_payments( ) ) ;
2170
2208
assert ! (
2171
2209
outbound_payments. add_new_awaiting_invoice(
2172
- payment_id, expiration, Retry :: Attempts ( 0 ) , None
2210
+ payment_id, expiration, Retry :: Attempts ( 0 ) , None , None , OffersContext :: Unknown { }
2173
2211
) . is_ok( )
2174
2212
) ;
2175
2213
assert ! ( outbound_payments. has_pending_payments( ) ) ;
@@ -2195,29 +2233,29 @@ mod tests {
2195
2233
2196
2234
assert ! (
2197
2235
outbound_payments. add_new_awaiting_invoice(
2198
- payment_id, expiration, Retry :: Attempts ( 0 ) , None
2236
+ payment_id, expiration, Retry :: Attempts ( 0 ) , None , None , OffersContext :: Unknown { }
2199
2237
) . is_ok( )
2200
2238
) ;
2201
2239
assert ! ( outbound_payments. has_pending_payments( ) ) ;
2202
2240
2203
2241
assert ! (
2204
2242
outbound_payments. add_new_awaiting_invoice(
2205
- payment_id, expiration, Retry :: Attempts ( 0 ) , None
2243
+ payment_id, expiration, Retry :: Attempts ( 0 ) , None , None , OffersContext :: Unknown { }
2206
2244
) . is_err( )
2207
2245
) ;
2208
2246
}
2209
2247
2210
2248
#[ test]
2211
2249
fn removes_abandoned_awaiting_invoice ( ) {
2212
2250
let pending_events = Mutex :: new ( VecDeque :: new ( ) ) ;
2213
- let outbound_payments = OutboundPayments :: new ( ) ;
2251
+ let outbound_payments = OutboundPayments :: new ( new_hash_map ( ) ) ;
2214
2252
let payment_id = PaymentId ( [ 0 ; 32 ] ) ;
2215
2253
let expiration = StaleExpiration :: AbsoluteTimeout ( Duration :: from_secs ( 100 ) ) ;
2216
2254
2217
2255
assert ! ( !outbound_payments. has_pending_payments( ) ) ;
2218
2256
assert ! (
2219
2257
outbound_payments. add_new_awaiting_invoice(
2220
- payment_id, expiration, Retry :: Attempts ( 0 ) , None
2258
+ payment_id, expiration, Retry :: Attempts ( 0 ) , None , None , OffersContext :: Unknown { }
2221
2259
) . is_ok( )
2222
2260
) ;
2223
2261
assert ! ( outbound_payments. has_pending_payments( ) ) ;
@@ -2245,13 +2283,13 @@ mod tests {
2245
2283
let keys_manager = test_utils:: TestKeysInterface :: new ( & [ 0 ; 32 ] , Network :: Testnet ) ;
2246
2284
2247
2285
let pending_events = Mutex :: new ( VecDeque :: new ( ) ) ;
2248
- let outbound_payments = OutboundPayments :: new ( ) ;
2286
+ let outbound_payments = OutboundPayments :: new ( new_hash_map ( ) ) ;
2249
2287
let payment_id = PaymentId ( [ 0 ; 32 ] ) ;
2250
2288
let expiration = StaleExpiration :: AbsoluteTimeout ( Duration :: from_secs ( 100 ) ) ;
2251
2289
2252
2290
assert ! (
2253
2291
outbound_payments. add_new_awaiting_invoice(
2254
- payment_id, expiration, Retry :: Attempts ( 0 ) , None
2292
+ payment_id, expiration, Retry :: Attempts ( 0 ) , None , None , OffersContext :: Unknown { }
2255
2293
) . is_ok( )
2256
2294
) ;
2257
2295
assert ! ( outbound_payments. has_pending_payments( ) ) ;
@@ -2298,7 +2336,7 @@ mod tests {
2298
2336
let keys_manager = test_utils:: TestKeysInterface :: new ( & [ 0 ; 32 ] , Network :: Testnet ) ;
2299
2337
2300
2338
let pending_events = Mutex :: new ( VecDeque :: new ( ) ) ;
2301
- let outbound_payments = OutboundPayments :: new ( ) ;
2339
+ let outbound_payments = OutboundPayments :: new ( new_hash_map ( ) ) ;
2302
2340
let payment_id = PaymentId ( [ 0 ; 32 ] ) ;
2303
2341
let expiration = StaleExpiration :: AbsoluteTimeout ( Duration :: from_secs ( 100 ) ) ;
2304
2342
@@ -2315,7 +2353,7 @@ mod tests {
2315
2353
assert ! (
2316
2354
outbound_payments. add_new_awaiting_invoice(
2317
2355
payment_id, expiration, Retry :: Attempts ( 0 ) ,
2318
- Some ( invoice. amount_msats( ) / 100 + 50_000 )
2356
+ Some ( invoice. amount_msats( ) / 100 + 50_000 ) , None , OffersContext :: Unknown { }
2319
2357
) . is_ok( )
2320
2358
) ;
2321
2359
assert ! ( outbound_payments. has_pending_payments( ) ) ;
@@ -2359,7 +2397,7 @@ mod tests {
2359
2397
let keys_manager = test_utils:: TestKeysInterface :: new ( & [ 0 ; 32 ] , Network :: Testnet ) ;
2360
2398
2361
2399
let pending_events = Mutex :: new ( VecDeque :: new ( ) ) ;
2362
- let outbound_payments = OutboundPayments :: new ( ) ;
2400
+ let outbound_payments = OutboundPayments :: new ( new_hash_map ( ) ) ;
2363
2401
let payment_id = PaymentId ( [ 0 ; 32 ] ) ;
2364
2402
let expiration = StaleExpiration :: AbsoluteTimeout ( Duration :: from_secs ( 100 ) ) ;
2365
2403
@@ -2415,7 +2453,7 @@ mod tests {
2415
2453
2416
2454
assert ! (
2417
2455
outbound_payments. add_new_awaiting_invoice(
2418
- payment_id, expiration, Retry :: Attempts ( 0 ) , Some ( 1234 )
2456
+ payment_id, expiration, Retry :: Attempts ( 0 ) , Some ( 1234 ) , None , OffersContext :: Unknown { }
2419
2457
) . is_ok( )
2420
2458
) ;
2421
2459
assert ! ( outbound_payments. has_pending_payments( ) ) ;
0 commit comments