@@ -14,19 +14,31 @@ use core::ops::Deref;
14
14
use core:: sync:: atomic:: { AtomicUsize , Ordering } ;
15
15
use core:: time:: Duration ;
16
16
17
- use bitcoin:: block:: Header ;
18
- use bitcoin:: constants:: ChainHash ;
19
- use bitcoin:: secp256k1:: { self , PublicKey , Secp256k1 } ;
20
-
17
+ use crate :: blinded_path:: message:: {
18
+ BlindedMessagePath , MessageContext , MessageForwardNode , OffersContext ,
19
+ } ;
20
+ use crate :: blinded_path:: payment:: {
21
+ BlindedPaymentPath , PaymentConstraints , PaymentContext , UnauthenticatedReceiveTlvs ,
22
+ } ;
23
+ use crate :: chain:: channelmonitor:: LATENCY_GRACE_PERIOD_BLOCKS ;
21
24
use crate :: chain:: transaction:: TransactionData ;
22
25
use crate :: chain:: { self , BestBlock } ;
26
+ use crate :: ln:: channel_state:: ChannelDetails ;
27
+ use crate :: ln:: channelmanager:: {
28
+ ChainParameters , CLTV_FAR_FAR_AWAY , MAX_SHORT_LIVED_RELATIVE_EXPIRY ,
29
+ } ;
23
30
use crate :: ln:: inbound_payment;
31
+ use crate :: offers:: nonce:: Nonce ;
24
32
use crate :: onion_message:: async_payments:: AsyncPaymentsMessage ;
25
33
use crate :: onion_message:: messenger:: { MessageRouter , MessageSendInstructions } ;
26
34
use crate :: onion_message:: offers:: OffersMessage ;
27
35
use crate :: routing:: router:: Router ;
28
36
use crate :: sign:: EntropySource ;
29
37
use crate :: sync:: { Mutex , RwLock } ;
38
+ use bitcoin:: block:: Header ;
39
+ use bitcoin:: constants:: ChainHash ;
40
+ use bitcoin:: secp256k1:: { self , PublicKey , Secp256k1 } ;
41
+ use lightning_invoice:: PaymentSecret ;
30
42
31
43
#[ cfg( feature = "dnssec" ) ]
32
44
use crate :: onion_message:: dns_resolution:: DNSResolverMessage ;
@@ -144,6 +156,110 @@ where
144
156
}
145
157
}
146
158
159
+ impl < ES : Deref , MR : Deref , R : Deref > OffersMessageFlow < ES , MR , R >
160
+ where
161
+ ES :: Target : EntropySource ,
162
+ MR :: Target : MessageRouter ,
163
+ R :: Target : Router ,
164
+ {
165
+ /// Creates a collection of blinded paths by delegating to [`MessageRouter`] based on
166
+ /// the path's intended lifetime.
167
+ ///
168
+ /// Whether or not the path is compact depends on whether the path is short-lived or long-lived,
169
+ /// respectively, based on the given `absolute_expiry` as seconds since the Unix epoch. See
170
+ /// [`MAX_SHORT_LIVED_RELATIVE_EXPIRY`].
171
+ fn create_blinded_paths_using_absolute_expiry (
172
+ & self , context : OffersContext , absolute_expiry : Option < Duration > ,
173
+ peers : Vec < MessageForwardNode > ,
174
+ ) -> Result < Vec < BlindedMessagePath > , ( ) > {
175
+ let now = self . duration_since_epoch ( ) ;
176
+ let max_short_lived_absolute_expiry = now. saturating_add ( MAX_SHORT_LIVED_RELATIVE_EXPIRY ) ;
177
+
178
+ if absolute_expiry. unwrap_or ( Duration :: MAX ) <= max_short_lived_absolute_expiry {
179
+ self . create_compact_blinded_paths ( peers, context)
180
+ } else {
181
+ self . create_blinded_paths ( peers, MessageContext :: Offers ( context) )
182
+ }
183
+ }
184
+
185
+ /// Creates a collection of blinded paths by delegating to
186
+ /// [`MessageRouter::create_blinded_paths`].
187
+ ///
188
+ /// Errors if the `MessageRouter` errors.
189
+ fn create_blinded_paths (
190
+ & self , peers : Vec < MessageForwardNode > , context : MessageContext ,
191
+ ) -> Result < Vec < BlindedMessagePath > , ( ) > {
192
+ let recipient = self . get_our_node_id ( ) ;
193
+ let secp_ctx = & self . secp_ctx ;
194
+
195
+ let peers = peers. into_iter ( ) . map ( |node| node. node_id ) . collect ( ) ;
196
+
197
+ self . message_router
198
+ . create_blinded_paths ( recipient, context, peers, secp_ctx)
199
+ . and_then ( |paths| ( !paths. is_empty ( ) ) . then ( || paths) . ok_or ( ( ) ) )
200
+ }
201
+
202
+ /// Creates a collection of blinded paths by delegating to
203
+ /// [`MessageRouter::create_compact_blinded_paths`].
204
+ ///
205
+ /// Errors if the `MessageRouter` errors.
206
+ fn create_compact_blinded_paths (
207
+ & self , peers : Vec < MessageForwardNode > , context : OffersContext ,
208
+ ) -> Result < Vec < BlindedMessagePath > , ( ) > {
209
+ let recipient = self . get_our_node_id ( ) ;
210
+ let secp_ctx = & self . secp_ctx ;
211
+
212
+ let peers = peers;
213
+
214
+ self . message_router
215
+ . create_compact_blinded_paths (
216
+ recipient,
217
+ MessageContext :: Offers ( context) ,
218
+ peers,
219
+ secp_ctx,
220
+ )
221
+ . and_then ( |paths| ( !paths. is_empty ( ) ) . then ( || paths) . ok_or ( ( ) ) )
222
+ }
223
+
224
+ /// Creates multi-hop blinded payment paths for the given `amount_msats` by delegating to
225
+ /// [`Router::create_blinded_payment_paths`].
226
+ fn create_blinded_payment_paths (
227
+ & self , usable_channels : Vec < ChannelDetails > , amount_msats : Option < u64 > ,
228
+ payment_secret : PaymentSecret , payment_context : PaymentContext ,
229
+ relative_expiry_seconds : u32 ,
230
+ ) -> Result < Vec < BlindedPaymentPath > , ( ) > {
231
+ let expanded_key = & self . inbound_payment_key ;
232
+ let entropy = & * self . entropy_source ;
233
+ let secp_ctx = & self . secp_ctx ;
234
+
235
+ let first_hops = usable_channels;
236
+ let payee_node_id = self . get_our_node_id ( ) ;
237
+
238
+ // Assume shorter than usual block times to avoid spuriously failing payments too early.
239
+ const SECONDS_PER_BLOCK : u32 = 9 * 60 ;
240
+ let relative_expiry_blocks = relative_expiry_seconds / SECONDS_PER_BLOCK ;
241
+ let max_cltv_expiry = core:: cmp:: max ( relative_expiry_blocks, CLTV_FAR_FAR_AWAY )
242
+ . saturating_add ( LATENCY_GRACE_PERIOD_BLOCKS )
243
+ . saturating_add ( self . best_block . read ( ) . unwrap ( ) . height ) ;
244
+
245
+ let payee_tlvs = UnauthenticatedReceiveTlvs {
246
+ payment_secret,
247
+ payment_constraints : PaymentConstraints { max_cltv_expiry, htlc_minimum_msat : 1 } ,
248
+ payment_context,
249
+ } ;
250
+ let nonce = Nonce :: from_entropy_source ( entropy) ;
251
+ let payee_tlvs = payee_tlvs. authenticate ( nonce, expanded_key) ;
252
+
253
+ self . router . create_blinded_payment_paths (
254
+ payee_node_id,
255
+ first_hops,
256
+ payee_tlvs,
257
+ amount_msats,
258
+ secp_ctx,
259
+ )
260
+ }
261
+ }
262
+
147
263
impl < ES : Deref , MR : Deref , R : Deref > chain:: Listen for OffersMessageFlow < ES , MR , R >
148
264
where
149
265
ES :: Target : EntropySource ,
0 commit comments