@@ -64,6 +64,18 @@ struct AsyncReceiveOffer {
64
64
update_static_invoice_path : Responder ,
65
65
}
66
66
67
+ impl AsyncReceiveOffer {
68
+ /// An offer needs to be refreshed if it is unused and has been cached longer than
69
+ /// `OFFER_REFRESH_THRESHOLD`.
70
+ fn needs_refresh ( & self , duration_since_epoch : Duration ) -> bool {
71
+ let awhile_ago = duration_since_epoch. saturating_sub ( OFFER_REFRESH_THRESHOLD ) ;
72
+ match self . status {
73
+ OfferStatus :: Ready { .. } => self . created_at < awhile_ago,
74
+ _ => false ,
75
+ }
76
+ }
77
+ }
78
+
67
79
impl_writeable_tlv_based_enum ! ( OfferStatus ,
68
80
( 0 , Used ) => {
69
81
( 0 , invoice_created_at, required) ,
@@ -283,9 +295,9 @@ impl AsyncReceiveOfferCache {
283
295
/// to build a new offer.
284
296
pub ( super ) fn should_build_offer_with_paths (
285
297
& self , offer_paths : & [ BlindedMessagePath ] , offer_paths_absolute_expiry_secs : Option < u64 > ,
286
- duration_since_epoch : Duration ,
298
+ slot : u16 , duration_since_epoch : Duration ,
287
299
) -> bool {
288
- if self . needs_new_offer_idx ( duration_since_epoch) . is_none ( ) {
300
+ if ! self . slot_needs_offer ( slot , duration_since_epoch) {
289
301
return false ;
290
302
}
291
303
@@ -307,37 +319,51 @@ impl AsyncReceiveOfferCache {
307
319
/// until it succeeds, see [`AsyncReceiveOfferCache`] docs.
308
320
pub ( super ) fn cache_pending_offer (
309
321
& mut self , offer : Offer , offer_paths_absolute_expiry_secs : Option < u64 > , offer_nonce : Nonce ,
310
- update_static_invoice_path : Responder , duration_since_epoch : Duration ,
311
- ) -> Result < u16 , ( ) > {
322
+ update_static_invoice_path : Responder , duration_since_epoch : Duration , slot : u16 ,
323
+ ) -> Result < ( ) , ( ) > {
312
324
self . prune_expired_offers ( duration_since_epoch, false ) ;
313
325
314
326
if !self . should_build_offer_with_paths (
315
327
offer. paths ( ) ,
316
328
offer_paths_absolute_expiry_secs,
329
+ slot,
317
330
duration_since_epoch,
318
331
) {
319
332
return Err ( ( ) ) ;
320
333
}
321
334
322
- let idx = match self . needs_new_offer_idx ( duration_since_epoch) {
323
- Some ( idx) => idx,
324
- None => return Err ( ( ) ) ,
325
- } ;
326
-
327
- match self . offers . get_mut ( idx) {
328
- Some ( offer_opt) => {
329
- * offer_opt = Some ( AsyncReceiveOffer {
335
+ match self . offers . get_mut ( slot as usize ) {
336
+ Some ( slot) => {
337
+ * slot = Some ( AsyncReceiveOffer {
330
338
offer,
331
339
created_at : duration_since_epoch,
332
340
offer_nonce,
333
341
status : OfferStatus :: Pending ,
334
342
update_static_invoice_path,
335
- } ) ;
343
+ } )
344
+ } ,
345
+ None => {
346
+ debug_assert ! ( false , "Slot in cache was invalid but should'be been checked above" ) ;
347
+ return Err ( ( ) ) ;
336
348
} ,
337
- None => return Err ( ( ) ) ,
338
349
}
339
350
340
- Ok ( idx. try_into ( ) . map_err ( |_| ( ) ) ?)
351
+ Ok ( ( ) )
352
+ }
353
+
354
+ fn slot_needs_offer ( & self , slot : u16 , duration_since_epoch : Duration ) -> bool {
355
+ match self . offers . get ( slot as usize ) {
356
+ Some ( Some ( offer) ) => offer. needs_refresh ( duration_since_epoch) ,
357
+ // This slot in the cache was pre-allocated as needing an offer in
358
+ // `set_paths_to_static_invoice_server` and is currently vacant
359
+ Some ( None ) => true ,
360
+ // `slot` is out-of-range. Note that the cache only has `MAX_CACHED_OFFERS_TARGET` slots
361
+ // total, so any slots outside of that range are invalid.
362
+ None => {
363
+ debug_assert ! ( false , "Got offer paths for a non-existent slot in the cache" ) ;
364
+ false
365
+ } ,
366
+ }
341
367
}
342
368
343
369
/// If we have any empty slots in the cache or offers that can and should be replaced with a fresh
@@ -377,12 +403,11 @@ impl AsyncReceiveOfferCache {
377
403
378
404
// Filter for unused offers where longer than OFFER_REFRESH_THRESHOLD time has passed since they
379
405
// were last updated, so they are stale enough to warrant replacement.
380
- let awhile_ago = duration_since_epoch. saturating_sub ( OFFER_REFRESH_THRESHOLD ) ;
381
- self . unused_ready_offers ( )
382
- . filter ( |( _, offer, _) | offer. created_at < awhile_ago)
406
+ self . offers_with_idx ( )
407
+ . filter ( |( _, offer) | offer. needs_refresh ( duration_since_epoch) )
383
408
// Get the stalest offer and return its index
384
- . min_by ( |( _, offer_a, _ ) , ( _, offer_b, _ ) | offer_a. created_at . cmp ( & offer_b. created_at ) )
385
- . map ( |( idx, _, _ ) | idx)
409
+ . min_by ( |( _, offer_a) , ( _, offer_b) | offer_a. created_at . cmp ( & offer_b. created_at ) )
410
+ . map ( |( idx, _) | idx)
386
411
}
387
412
388
413
/// Returns an iterator over (offer_idx, offer)
0 commit comments