@@ -35,12 +35,7 @@ enum OfferStatus {
3535 /// have a maximally fresh offer. We always want to have at least 1 offer in this state,
3636 /// preferably a few so we can respond to user requests for new offers without returning the same
3737 /// one multiple times. Returning a new offer each time is better for privacy.
38- Ready {
39- /// If this offer's invoice has been persisted for some time, it's safe to replace to ensure we
40- /// always have the freshest possible offer available when the user goes to pull an offer from
41- /// the cache.
42- invoice_confirmed_persisted_at : Duration ,
43- } ,
38+ Ready ,
4439 /// This offer's invoice is not yet confirmed as persisted by the static invoice server, so it is
4540 /// not yet ready to receive payments.
4641 Pending ,
@@ -49,6 +44,9 @@ enum OfferStatus {
4944#[ derive( Clone ) ]
5045struct AsyncReceiveOffer {
5146 offer : Offer ,
47+ /// The time as duration since the Unix epoch at which this offer was created. Useful when
48+ /// refreshing unused offers.
49+ created_at : Duration ,
5250 /// Whether this offer is used, ready for use, or pending invoice persistence with the static
5351 /// invoice server.
5452 status : OfferStatus ,
@@ -63,9 +61,7 @@ struct AsyncReceiveOffer {
6361
6462impl_writeable_tlv_based_enum ! ( OfferStatus ,
6563 ( 0 , Used ) => { } ,
66- ( 1 , Ready ) => {
67- ( 0 , invoice_confirmed_persisted_at, required) ,
68- } ,
64+ ( 1 , Ready ) => { } ,
6965 ( 2 , Pending ) => { } ,
7066) ;
7167
@@ -74,6 +70,7 @@ impl_writeable_tlv_based!(AsyncReceiveOffer, {
7470 ( 2 , offer_nonce, required) ,
7571 ( 4 , status, required) ,
7672 ( 6 , update_static_invoice_path, required) ,
73+ ( 8 , created_at, required) ,
7774} ) ;
7875
7976/// If we are an often-offline recipient, we'll want to interactively build offers and static
@@ -179,9 +176,9 @@ const MAX_CACHED_OFFERS_TARGET: usize = 10;
179176#[ cfg( async_payments) ]
180177const MAX_UPDATE_ATTEMPTS : u8 = 3 ;
181178
182- // If we have an offer that is replaceable and its invoice was confirmed as persisted more than 2
183- // hours ago, we can go ahead and refresh it because we always want to have the freshest offer
184- // possible when a user goes to retrieve a cached offer.
179+ // If we have an offer that is replaceable and is more than 2 hours old, we can go ahead and refresh
180+ // it because we always want to have the freshest offer possible when a user goes to retrieve a
181+ // cached offer.
185182//
186183// We avoid replacing unused offers too quickly -- this prevents the case where we send multiple
187184// invoices from different offers competing for the same slot to the server, messages are received
@@ -216,14 +213,11 @@ impl AsyncReceiveOfferCache {
216213 ) -> Result < ( Offer , bool ) , ( ) > {
217214 self . prune_expired_offers ( duration_since_epoch, false ) ;
218215
219- // Find the freshest unused offer, where "freshness" is based on when the invoice was confirmed
220- // persisted by the server. See `OfferStatus::Ready`.
216+ // Find the freshest unused offer. See `OfferStatus::Ready`.
221217 let newest_unused_offer_opt = self
222- . unused_offers ( )
223- . max_by ( |( _, _, persisted_at_a) , ( _, _, persisted_at_b) | {
224- persisted_at_a. cmp ( & persisted_at_b)
225- } )
226- . map ( |( idx, offer, _) | ( idx, offer. offer . clone ( ) ) ) ;
218+ . unused_ready_offers ( )
219+ . max_by ( |( _, offer_a) , ( _, offer_b) | offer_a. created_at . cmp ( & offer_b. created_at ) )
220+ . map ( |( idx, offer) | ( idx, offer. offer . clone ( ) ) ) ;
227221 if let Some ( ( idx, newest_ready_offer) ) = newest_unused_offer_opt {
228222 self . offers [ idx] . as_mut ( ) . map ( |offer| offer. status = OfferStatus :: Used ) ;
229223 return Ok ( ( newest_ready_offer, true ) ) ;
@@ -316,6 +310,7 @@ impl AsyncReceiveOfferCache {
316310 Some ( offer_opt) => {
317311 * offer_opt = Some ( AsyncReceiveOffer {
318312 offer,
313+ created_at : duration_since_epoch,
319314 offer_nonce,
320315 status : OfferStatus :: Pending ,
321316 update_static_invoice_path,
@@ -365,15 +360,11 @@ impl AsyncReceiveOfferCache {
365360 // Filter for unused offers where longer than OFFER_REFRESH_THRESHOLD time has passed since they
366361 // were last updated, so they are stale enough to warrant replacement.
367362 let awhile_ago = duration_since_epoch. saturating_sub ( OFFER_REFRESH_THRESHOLD ) ;
368- self . unused_offers ( )
369- . filter ( |( _, _, invoice_confirmed_persisted_at) | {
370- * invoice_confirmed_persisted_at < awhile_ago
371- } )
363+ self . unused_ready_offers ( )
364+ . filter ( |( _, offer) | offer. created_at < awhile_ago)
372365 // Get the stalest offer and return its index
373- . min_by ( |( _, _, persisted_at_a) , ( _, _, persisted_at_b) | {
374- persisted_at_a. cmp ( & persisted_at_b)
375- } )
376- . map ( |( idx, _, _) | idx)
366+ . min_by ( |( _, offer_a) , ( _, offer_b) | offer_a. created_at . cmp ( & offer_b. created_at ) )
367+ . map ( |( idx, _) | idx)
377368 }
378369
379370 /// Returns an iterator over (offer_idx, offer)
@@ -387,13 +378,11 @@ impl AsyncReceiveOfferCache {
387378 } )
388379 }
389380
390- /// Returns an iterator over (offer_idx, offer, invoice_confirmed_persisted_at)
391- /// where all returned offers are [`OfferStatus::Ready`]
392- fn unused_offers ( & self ) -> impl Iterator < Item = ( usize , & AsyncReceiveOffer , Duration ) > {
381+ /// Returns an iterator over (offer_idx, offer) where all returned offers are
382+ /// [`OfferStatus::Ready`]
383+ fn unused_ready_offers ( & self ) -> impl Iterator < Item = ( usize , & AsyncReceiveOffer ) > {
393384 self . offers_with_idx ( ) . filter_map ( |( idx, offer) | match offer. status {
394- OfferStatus :: Ready { invoice_confirmed_persisted_at } => {
395- Some ( ( idx, offer, invoice_confirmed_persisted_at) )
396- } ,
385+ OfferStatus :: Ready => Some ( ( idx, offer) ) ,
397386 _ => None ,
398387 } )
399388 }
@@ -464,8 +453,7 @@ impl AsyncReceiveOfferCache {
464453 return false ;
465454 }
466455
467- offer. status =
468- OfferStatus :: Ready { invoice_confirmed_persisted_at : duration_since_epoch } ;
456+ offer. status = OfferStatus :: Ready ;
469457 return true ;
470458 }
471459
0 commit comments