@@ -14,7 +14,9 @@ use crate::blinded_path::message::{
14
14
BlindedMessagePath , MessageContext , MessageForwardNode , OffersContext ,
15
15
} ;
16
16
use crate :: blinded_path:: payment:: BlindedPaymentPath ;
17
- use crate :: ln:: channelmanager:: PaymentId ;
17
+ use crate :: ln:: channelmanager:: {
18
+ PaymentId , MAX_SHORT_LIVED_RELATIVE_EXPIRY , OFFERS_MESSAGE_REQUEST_LIMIT ,
19
+ } ;
18
20
use crate :: ln:: inbound_payment;
19
21
use crate :: offers:: invoice:: { Bolt12Invoice , DerivedSigningPubkey , InvoiceBuilder } ;
20
22
use crate :: offers:: invoice_request:: { InvoiceRequest , InvoiceRequestBuilder } ;
@@ -163,4 +165,266 @@ where
163
165
pub fn get_our_node_id ( & self ) -> PublicKey {
164
166
self . our_network_pubkey
165
167
}
168
+
169
+ fn duration_since_epoch ( & self ) -> Duration {
170
+ #[ cfg( not( feature = "std" ) ) ]
171
+ let now = Duration :: from_secs ( self . highest_seen_timestamp . load ( Ordering :: Acquire ) as u64 ) ;
172
+ #[ cfg( feature = "std" ) ]
173
+ let now = std:: time:: SystemTime :: now ( )
174
+ . duration_since ( std:: time:: SystemTime :: UNIX_EPOCH )
175
+ . expect ( "SystemTime::now() should come after SystemTime::UNIX_EPOCH" ) ;
176
+
177
+ now
178
+ }
179
+ }
180
+
181
+ impl < ES : Deref , MR : Deref > Flow for OffersMessageFlow < ES , MR >
182
+ where
183
+ ES :: Target : EntropySource ,
184
+ MR :: Target : MessageRouter ,
185
+ {
186
+ fn create_offer_builder (
187
+ & self , nonce : Nonce ,
188
+ ) -> Result < OfferBuilder < DerivedMetadata , secp256k1:: All > , Bolt12SemanticError > {
189
+ let node_id = self . get_our_node_id ( ) ;
190
+ let expanded_key = & self . inbound_payment_key ;
191
+ let secp_ctx = & self . secp_ctx ;
192
+
193
+ let builder = OfferBuilder :: deriving_signing_pubkey ( node_id, expanded_key, nonce, secp_ctx)
194
+ . chain_hash ( self . chain_hash ) ;
195
+
196
+ Ok ( builder)
197
+ }
198
+
199
+ fn create_refund_builder (
200
+ & self , amount_msats : u64 , absolute_expiry : Duration , payment_id : PaymentId , nonce : Nonce ,
201
+ ) -> Result < RefundBuilder < secp256k1:: All > , Bolt12SemanticError > {
202
+ let node_id = self . get_our_node_id ( ) ;
203
+ let expanded_key = & self . inbound_payment_key ;
204
+ let secp_ctx = & self . secp_ctx ;
205
+
206
+ let builder = RefundBuilder :: deriving_signing_pubkey (
207
+ node_id,
208
+ expanded_key,
209
+ nonce,
210
+ secp_ctx,
211
+ amount_msats,
212
+ payment_id,
213
+ ) ?
214
+ . chain_hash ( self . chain_hash )
215
+ . absolute_expiry ( absolute_expiry) ;
216
+
217
+ Ok ( builder)
218
+ }
219
+
220
+ fn create_invoice_request_builder < ' a > (
221
+ & ' a self , offer : & ' a Offer , nonce : Nonce , quantity : Option < u64 > , amount_msats : Option < u64 > ,
222
+ payer_note : Option < String > , human_readable_name : Option < HumanReadableName > ,
223
+ payment_id : PaymentId ,
224
+ ) -> Result < InvoiceRequestBuilder < ' a , ' a , secp256k1:: All > , Bolt12SemanticError > {
225
+ let expanded_key = & self . inbound_payment_key ;
226
+ let secp_ctx = & self . secp_ctx ;
227
+
228
+ let builder = offer
229
+ . request_invoice ( expanded_key, nonce, secp_ctx, payment_id) ?
230
+ . chain_hash ( self . chain_hash ) ?;
231
+
232
+ let builder = match quantity {
233
+ None => builder,
234
+ Some ( quantity) => builder. quantity ( quantity) ?,
235
+ } ;
236
+ let builder = match amount_msats {
237
+ None => builder,
238
+ Some ( amount_msats) => builder. amount_msats ( amount_msats) ?,
239
+ } ;
240
+ let builder = match payer_note {
241
+ None => builder,
242
+ Some ( payer_note) => builder. payer_note ( payer_note) ,
243
+ } ;
244
+ let builder = match human_readable_name {
245
+ None => builder,
246
+ Some ( hrn) => builder. sourced_from_human_readable_name ( hrn) ,
247
+ } ;
248
+
249
+ Ok ( builder. into ( ) )
250
+ }
251
+
252
+ fn create_invoice_builder < ' a > (
253
+ & ' a self , refund : & ' a Refund , payment_paths : Vec < BlindedPaymentPath > ,
254
+ payment_hash : PaymentHash ,
255
+ ) -> Result < InvoiceBuilder < ' a , DerivedSigningPubkey > , Bolt12SemanticError > {
256
+ let expanded_key = & self . inbound_payment_key ;
257
+ let entropy = & * self . entropy_source ;
258
+
259
+ #[ cfg( feature = "std" ) ]
260
+ let builder = refund. respond_using_derived_keys (
261
+ payment_paths,
262
+ payment_hash,
263
+ expanded_key,
264
+ entropy,
265
+ ) ?;
266
+ #[ cfg( not( feature = "std" ) ) ]
267
+ let created_at = Duration :: from_secs ( self . highest_seen_timestamp . load ( Ordering :: Acquire ) as u64 ) ;
268
+ #[ cfg( not( feature = "std" ) ) ]
269
+ let builder = refund. respond_using_derived_keys_no_std (
270
+ payment_paths,
271
+ payment_hash,
272
+ created_at,
273
+ expanded_key,
274
+ entropy,
275
+ ) ?;
276
+ let builder: InvoiceBuilder < DerivedSigningPubkey > = builder. into ( ) ;
277
+
278
+ Ok ( builder)
279
+ }
280
+
281
+ fn create_blinded_paths (
282
+ & self , peers : Vec < MessageForwardNode > , context : MessageContext ,
283
+ ) -> Result < Vec < BlindedMessagePath > , ( ) > {
284
+ let recipient = self . get_our_node_id ( ) ;
285
+ let secp_ctx = & self . secp_ctx ;
286
+
287
+ let peers = peers. iter ( ) . map ( |node| node. node_id ) . collect :: < Vec < _ > > ( ) ;
288
+
289
+ self . message_router
290
+ . create_blinded_paths ( recipient, context, peers, secp_ctx)
291
+ . and_then ( |paths| ( !paths. is_empty ( ) ) . then ( || paths) . ok_or ( ( ) ) )
292
+ }
293
+
294
+ fn create_compact_blinded_paths (
295
+ & self , peers : Vec < MessageForwardNode > , context : OffersContext ,
296
+ ) -> Result < Vec < BlindedMessagePath > , ( ) > {
297
+ let recipient = self . get_our_node_id ( ) ;
298
+ let secp_ctx = & self . secp_ctx ;
299
+
300
+ self . message_router
301
+ . create_compact_blinded_paths (
302
+ recipient,
303
+ MessageContext :: Offers ( context) ,
304
+ peers,
305
+ secp_ctx,
306
+ )
307
+ . and_then ( |paths| ( !paths. is_empty ( ) ) . then ( || paths) . ok_or ( ( ) ) )
308
+ }
309
+
310
+ fn create_blinded_paths_using_absolute_expiry (
311
+ & self , peers : Vec < MessageForwardNode > , context : OffersContext ,
312
+ absolute_expiry : Option < Duration > ,
313
+ ) -> Result < Vec < BlindedMessagePath > , ( ) > {
314
+ let now = self . duration_since_epoch ( ) ;
315
+ let max_short_lived_absolute_expiry = now. saturating_add ( MAX_SHORT_LIVED_RELATIVE_EXPIRY ) ;
316
+
317
+ if absolute_expiry. unwrap_or ( Duration :: MAX ) <= max_short_lived_absolute_expiry {
318
+ self . create_compact_blinded_paths ( peers, context)
319
+ } else {
320
+ self . create_blinded_paths ( peers, MessageContext :: Offers ( context) )
321
+ }
322
+ }
323
+
324
+ fn enqueue_invoice_request (
325
+ & self , invoice_request : InvoiceRequest , reply_paths : Vec < BlindedMessagePath > ,
326
+ ) -> Result < ( ) , Bolt12SemanticError > {
327
+ let mut pending_offers_messages = self . pending_offers_messages . lock ( ) . unwrap ( ) ;
328
+ if !invoice_request. paths ( ) . is_empty ( ) {
329
+ reply_paths
330
+ . iter ( )
331
+ . flat_map ( |reply_path| {
332
+ invoice_request. paths ( ) . iter ( ) . map ( move |path| ( path, reply_path) )
333
+ } )
334
+ . take ( OFFERS_MESSAGE_REQUEST_LIMIT )
335
+ . for_each ( |( path, reply_path) | {
336
+ let instructions = MessageSendInstructions :: WithSpecifiedReplyPath {
337
+ destination : Destination :: BlindedPath ( path. clone ( ) ) ,
338
+ reply_path : reply_path. clone ( ) ,
339
+ } ;
340
+ let message = OffersMessage :: InvoiceRequest ( invoice_request. clone ( ) ) ;
341
+ pending_offers_messages. push ( ( message, instructions) ) ;
342
+ } ) ;
343
+ } else if let Some ( node_id) = invoice_request. issuer_signing_pubkey ( ) {
344
+ for reply_path in reply_paths {
345
+ let instructions = MessageSendInstructions :: WithSpecifiedReplyPath {
346
+ destination : Destination :: Node ( node_id) ,
347
+ reply_path,
348
+ } ;
349
+ let message = OffersMessage :: InvoiceRequest ( invoice_request. clone ( ) ) ;
350
+ pending_offers_messages. push ( ( message, instructions) ) ;
351
+ }
352
+ } else {
353
+ debug_assert ! ( false ) ;
354
+ return Err ( Bolt12SemanticError :: MissingIssuerSigningPubkey ) ;
355
+ }
356
+
357
+ Ok ( ( ) )
358
+ }
359
+
360
+ fn enqueue_invoice (
361
+ & self , invoice : Bolt12Invoice , refund : & Refund , reply_paths : Vec < BlindedMessagePath > ,
362
+ ) -> Result < ( ) , Bolt12SemanticError > {
363
+ let mut pending_offers_messages = self . pending_offers_messages . lock ( ) . unwrap ( ) ;
364
+ if refund. paths ( ) . is_empty ( ) {
365
+ for reply_path in reply_paths {
366
+ let instructions = MessageSendInstructions :: WithSpecifiedReplyPath {
367
+ destination : Destination :: Node ( refund. payer_signing_pubkey ( ) ) ,
368
+ reply_path,
369
+ } ;
370
+ let message = OffersMessage :: Invoice ( invoice. clone ( ) ) ;
371
+ pending_offers_messages. push ( ( message, instructions) ) ;
372
+ }
373
+ } else {
374
+ reply_paths
375
+ . iter ( )
376
+ . flat_map ( |reply_path| refund. paths ( ) . iter ( ) . map ( move |path| ( path, reply_path) ) )
377
+ . take ( OFFERS_MESSAGE_REQUEST_LIMIT )
378
+ . for_each ( |( path, reply_path) | {
379
+ let instructions = MessageSendInstructions :: WithSpecifiedReplyPath {
380
+ destination : Destination :: BlindedPath ( path. clone ( ) ) ,
381
+ reply_path : reply_path. clone ( ) ,
382
+ } ;
383
+ let message = OffersMessage :: Invoice ( invoice. clone ( ) ) ;
384
+ pending_offers_messages. push ( ( message, instructions) ) ;
385
+ } ) ;
386
+ }
387
+
388
+ Ok ( ( ) )
389
+ }
390
+
391
+ fn enqueue_dns_onion_message (
392
+ & self , message : DNSSECQuery , dns_resolvers : Vec < Destination > ,
393
+ reply_paths : Vec < BlindedMessagePath > ,
394
+ ) -> Result < ( ) , Bolt12SemanticError > {
395
+ let message_params = dns_resolvers
396
+ . iter ( )
397
+ . flat_map ( |destination| reply_paths. iter ( ) . map ( move |path| ( path, destination) ) )
398
+ . take ( OFFERS_MESSAGE_REQUEST_LIMIT ) ;
399
+ for ( reply_path, destination) in message_params {
400
+ self . pending_dns_onion_messages . lock ( ) . unwrap ( ) . push ( (
401
+ DNSResolverMessage :: DNSSECQuery ( message. clone ( ) ) ,
402
+ MessageSendInstructions :: WithSpecifiedReplyPath {
403
+ destination : destination. clone ( ) ,
404
+ reply_path : reply_path. clone ( ) ,
405
+ } ,
406
+ ) ) ;
407
+ }
408
+
409
+ Ok ( ( ) )
410
+ }
411
+
412
+ fn get_and_clear_pending_offers_messages (
413
+ & self ,
414
+ ) -> Vec < ( OffersMessage , MessageSendInstructions ) > {
415
+ core:: mem:: take ( & mut self . pending_offers_messages . lock ( ) . unwrap ( ) )
416
+ }
417
+
418
+ fn get_and_clear_pending_async_messages (
419
+ & self ,
420
+ ) -> Vec < ( AsyncPaymentsMessage , MessageSendInstructions ) > {
421
+ core:: mem:: take ( & mut self . pending_async_payments_messages . lock ( ) . unwrap ( ) )
422
+ }
423
+
424
+ #[ cfg( feature = "dnssec" ) ]
425
+ fn get_and_clear_pending_dns_messages (
426
+ & self ,
427
+ ) -> Vec < ( DNSResolverMessage , MessageSendInstructions ) > {
428
+ core:: mem:: take ( & mut self . pending_dns_onion_messages . lock ( ) . unwrap ( ) )
429
+ }
166
430
}
0 commit comments