@@ -58,6 +58,15 @@ pub(crate) enum PendingOutboundPayment {
5858 Legacy {
5959 session_privs : HashSet < [ u8 ; 32 ] > ,
6060 } ,
61+ /// Used when we are waiting for an Offer to come back from a BIP 353 resolution
62+ AwaitingOffer {
63+ expiration : StaleExpiration ,
64+ retry_strategy : Retry ,
65+ max_total_routing_fee_msat : Option < u64 > ,
66+ /// Human Readable Names-originated payments should always specify an explicit amount to
67+ /// send up-front, which we track here and enforce once we receive the offer.
68+ amount_msats : u64 ,
69+ } ,
6170 AwaitingInvoice {
6271 expiration : StaleExpiration ,
6372 retry_strategy : Retry ,
@@ -199,6 +208,7 @@ impl PendingOutboundPayment {
199208 fn payment_hash ( & self ) -> Option < PaymentHash > {
200209 match self {
201210 PendingOutboundPayment :: Legacy { .. } => None ,
211+ PendingOutboundPayment :: AwaitingOffer { .. } => None ,
202212 PendingOutboundPayment :: AwaitingInvoice { .. } => None ,
203213 PendingOutboundPayment :: InvoiceReceived { payment_hash, .. } => Some ( * payment_hash) ,
204214 PendingOutboundPayment :: StaticInvoiceReceived { payment_hash, .. } => Some ( * payment_hash) ,
@@ -215,7 +225,8 @@ impl PendingOutboundPayment {
215225 PendingOutboundPayment :: Retryable { session_privs, .. } |
216226 PendingOutboundPayment :: Fulfilled { session_privs, .. } |
217227 PendingOutboundPayment :: Abandoned { session_privs, .. } => session_privs,
218- PendingOutboundPayment :: AwaitingInvoice { .. } |
228+ PendingOutboundPayment :: AwaitingOffer { .. } |
229+ PendingOutboundPayment :: AwaitingInvoice { .. } |
219230 PendingOutboundPayment :: InvoiceReceived { .. } |
220231 PendingOutboundPayment :: StaticInvoiceReceived { .. } => { debug_assert ! ( false ) ; return ; } ,
221232 } ) ;
@@ -256,7 +267,8 @@ impl PendingOutboundPayment {
256267 PendingOutboundPayment :: Abandoned { session_privs, .. } => {
257268 session_privs. remove ( session_priv)
258269 } ,
259- PendingOutboundPayment :: AwaitingInvoice { .. } |
270+ PendingOutboundPayment :: AwaitingOffer { .. } |
271+ PendingOutboundPayment :: AwaitingInvoice { .. } |
260272 PendingOutboundPayment :: InvoiceReceived { .. } |
261273 PendingOutboundPayment :: StaticInvoiceReceived { .. } => { debug_assert ! ( false ) ; false } ,
262274 } ;
@@ -286,7 +298,8 @@ impl PendingOutboundPayment {
286298 PendingOutboundPayment :: Retryable { session_privs, .. } => {
287299 session_privs. insert ( session_priv)
288300 } ,
289- PendingOutboundPayment :: AwaitingInvoice { .. } |
301+ PendingOutboundPayment :: AwaitingOffer { .. } |
302+ PendingOutboundPayment :: AwaitingInvoice { .. } |
290303 PendingOutboundPayment :: InvoiceReceived { .. } |
291304 PendingOutboundPayment :: StaticInvoiceReceived { .. } => { debug_assert ! ( false ) ; false } ,
292305 PendingOutboundPayment :: Fulfilled { .. } => false ,
@@ -320,6 +333,7 @@ impl PendingOutboundPayment {
320333 session_privs. len ( )
321334 } ,
322335 PendingOutboundPayment :: AwaitingInvoice { .. } => 0 ,
336+ PendingOutboundPayment :: AwaitingOffer { .. } => 0 ,
323337 PendingOutboundPayment :: InvoiceReceived { .. } => 0 ,
324338 PendingOutboundPayment :: StaticInvoiceReceived { .. } => 0 ,
325339 }
@@ -414,8 +428,9 @@ impl Display for PaymentAttempts {
414428 }
415429}
416430
417- /// How long before a [`PendingOutboundPayment::AwaitingInvoice`] should be considered stale and
418- /// candidate for removal in [`OutboundPayments::remove_stale_payments`].
431+ /// How long before a [`PendingOutboundPayment::AwaitingInvoice`] or
432+ /// [`PendingOutboundPayment::AwaitingOffer`] should be considered stale and candidate for removal
433+ /// in [`OutboundPayments::remove_stale_payments`].
419434#[ derive( Clone , Copy ) ]
420435pub ( crate ) enum StaleExpiration {
421436 /// Number of times [`OutboundPayments::remove_stale_payments`] is called.
@@ -1363,7 +1378,9 @@ impl OutboundPayments {
13631378 log_error ! ( logger, "Unable to retry payments that were initially sent on LDK versions prior to 0.0.102" ) ;
13641379 return
13651380 } ,
1366- PendingOutboundPayment :: AwaitingInvoice { .. } => {
1381+ PendingOutboundPayment :: AwaitingInvoice { .. }
1382+ | PendingOutboundPayment :: AwaitingOffer { .. } =>
1383+ {
13671384 log_error ! ( logger, "Payment not yet sent" ) ;
13681385 debug_assert ! ( false ) ;
13691386 return
@@ -1882,7 +1899,9 @@ impl OutboundPayments {
18821899 true
18831900 }
18841901 } ,
1885- PendingOutboundPayment :: AwaitingInvoice { expiration, .. } => {
1902+ PendingOutboundPayment :: AwaitingInvoice { expiration, .. }
1903+ | PendingOutboundPayment :: AwaitingOffer { expiration, .. } =>
1904+ {
18861905 let is_stale = match expiration {
18871906 StaleExpiration :: AbsoluteTimeout ( absolute_expiry) => {
18881907 * absolute_expiry <= duration_since_epoch
@@ -2068,22 +2087,28 @@ impl OutboundPayments {
20682087 let mut outbounds = self . pending_outbound_payments . lock ( ) . unwrap ( ) ;
20692088 if let hash_map:: Entry :: Occupied ( mut payment) = outbounds. entry ( payment_id) {
20702089 payment. get_mut ( ) . mark_abandoned ( reason) ;
2071- if let PendingOutboundPayment :: Abandoned { payment_hash, reason, .. } = payment. get ( ) {
2072- if payment. get ( ) . remaining_parts ( ) == 0 {
2090+ match payment. get ( ) {
2091+ PendingOutboundPayment :: Abandoned { payment_hash, reason, .. } => {
2092+ if payment. get ( ) . remaining_parts ( ) == 0 {
2093+ pending_events. lock ( ) . unwrap ( ) . push_back ( ( events:: Event :: PaymentFailed {
2094+ payment_id,
2095+ payment_hash : Some ( * payment_hash) ,
2096+ reason : * reason,
2097+ } , None ) ) ;
2098+ payment. remove ( ) ;
2099+ }
2100+ } ,
2101+ PendingOutboundPayment :: AwaitingInvoice { .. }
2102+ | PendingOutboundPayment :: AwaitingOffer { .. } =>
2103+ {
20732104 pending_events. lock ( ) . unwrap ( ) . push_back ( ( events:: Event :: PaymentFailed {
20742105 payment_id,
2075- payment_hash : Some ( * payment_hash ) ,
2076- reason : * reason,
2106+ payment_hash : None ,
2107+ reason : Some ( reason) ,
20772108 } , None ) ) ;
20782109 payment. remove ( ) ;
2079- }
2080- } else if let PendingOutboundPayment :: AwaitingInvoice { .. } = payment. get ( ) {
2081- pending_events. lock ( ) . unwrap ( ) . push_back ( ( events:: Event :: PaymentFailed {
2082- payment_id,
2083- payment_hash : None ,
2084- reason : Some ( reason) ,
2085- } , None ) ) ;
2086- payment. remove ( ) ;
2110+ } ,
2111+ _ => { } ,
20872112 }
20882113 }
20892114 }
@@ -2154,7 +2179,8 @@ impl OutboundPayments {
21542179 match self . pending_outbound_payments . lock ( ) . unwrap ( ) . entry ( payment_id) {
21552180 hash_map:: Entry :: Occupied ( mut entry) => {
21562181 let newly_added = match entry. get ( ) {
2157- PendingOutboundPayment :: AwaitingInvoice { .. } |
2182+ PendingOutboundPayment :: AwaitingOffer { .. } |
2183+ PendingOutboundPayment :: AwaitingInvoice { .. } |
21582184 PendingOutboundPayment :: InvoiceReceived { .. } |
21592185 PendingOutboundPayment :: StaticInvoiceReceived { .. } =>
21602186 {
@@ -2254,6 +2280,14 @@ impl_writeable_tlv_based_enum_upgradable!(PendingOutboundPayment,
22542280 ( 4 , retry_strategy, required) ,
22552281 ( 6 , route_params, required) ,
22562282 } ,
2283+ // Added in 0.1. Prior versions will drop these outbounds on downgrade, which is safe because
2284+ // no HTLCs are in-flight.
2285+ ( 11 , AwaitingOffer ) => {
2286+ ( 0 , expiration, required) ,
2287+ ( 2 , retry_strategy, required) ,
2288+ ( 4 , max_total_routing_fee_msat, option) ,
2289+ ( 6 , amount_msats, required) ,
2290+ } ,
22572291) ;
22582292
22592293#[ cfg( test) ]
0 commit comments