@@ -28,6 +28,9 @@ use io::{self, Read};
28
28
use prelude:: * ;
29
29
use sync:: { Arc , Mutex } ;
30
30
31
+ pub ( crate ) const SMALL_PACKET_HOP_DATA_LEN : usize = 1300 ;
32
+ pub ( crate ) const BIG_PACKET_HOP_DATA_LEN : usize = 32768 ;
33
+
31
34
#[ derive( Clone , Debug , PartialEq ) ]
32
35
pub ( crate ) struct Packet {
33
36
pub ( crate ) version : u8 ,
@@ -39,6 +42,13 @@ pub(crate) struct Packet {
39
42
pub ( crate ) hmac : [ u8 ; 32 ] ,
40
43
}
41
44
45
+ impl Packet {
46
+ fn len ( & self ) -> u16 {
47
+ // 32 (hmac) + 33 (public_key) + 1 (version) = 66
48
+ self . hop_data . len ( ) as u16 + 66
49
+ }
50
+ }
51
+
42
52
impl Writeable for Packet {
43
53
fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
44
54
self . version . write ( w) ?;
@@ -79,6 +89,61 @@ impl ReadableArgs<u16> for Packet {
79
89
}
80
90
}
81
91
92
+ /// The payload of an onion message.
93
+ pub ( crate ) struct Payload {
94
+ /// Onion message payloads contain an encrypted TLV stream, containing both "control" TLVs and
95
+ /// sometimes user-provided custom "data" TLVs. See [`EncryptedTlvs`] for more information.
96
+ encrypted_tlvs : EncryptedTlvs ,
97
+ // Coming soon:
98
+ // * custom TLVs
99
+ // * `message: Message` field
100
+ // * `reply_path: Option<BlindedRoute>` field
101
+ }
102
+
103
+ // Coming soon:
104
+ // enum Message {
105
+ // InvoiceRequest(InvoiceRequest),
106
+ // Invoice(Invoice),
107
+ // InvoiceError(InvoiceError),
108
+ // CustomMessage<T>,
109
+ // }
110
+
111
+ /// We want to avoid encoding and encrypting separately in order to avoid an intermediate Vec, thus
112
+ /// we encode and encrypt at the same time using the `SharedSecret` here.
113
+ impl Writeable for ( Payload , SharedSecret ) {
114
+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
115
+ match & self . 0 . encrypted_tlvs {
116
+ EncryptedTlvs :: Blinded ( encrypted_bytes) => {
117
+ encode_varint_length_prefixed_tlv ! ( w, {
118
+ ( 4 , encrypted_bytes, vec_type)
119
+ } )
120
+ } ,
121
+ EncryptedTlvs :: Unblinded ( control_tlvs) => {
122
+ let ( rho, _) = onion_utils:: gen_rho_mu_from_shared_secret ( self . 1 . as_ref ( ) ) ;
123
+ let write_adapter = ChaChaPolyWriteAdapter :: new ( rho, & control_tlvs) ;
124
+ encode_varint_length_prefixed_tlv ! ( w, {
125
+ ( 4 , write_adapter, required)
126
+ } )
127
+ }
128
+ }
129
+ Ok ( ( ) )
130
+ }
131
+ }
132
+
133
+ /// Onion messages contain an encrypted TLV stream. This can be supplied by someone else, in the
134
+ /// case that we're sending to a blinded route, or created by us if we're constructing payloads for
135
+ /// unblinded hops in the onion message's path.
136
+ pub ( crate ) enum EncryptedTlvs {
137
+ /// If we're sending to a blinded route, the node that constructed the blinded route has provided
138
+ /// our onion message's `EncryptedTlvs`, already encrypted and encoded into bytes.
139
+ Blinded ( Vec < u8 > ) ,
140
+ /// If we're receiving an onion message or constructing an onion message to send through any
141
+ /// unblinded nodes, we'll need to construct the onion message's `EncryptedTlvs` in their
142
+ /// unblinded state to avoid encoding them into an intermediate `Vec`.
143
+ // Below will later have an additional Vec<CustomTlv>
144
+ Unblinded ( ControlTlvs ) ,
145
+ }
146
+
82
147
/// Onion messages have "control" TLVs and "data" TLVs. Control TLVs are used to control the
83
148
/// direction and routing of an onion message from hop to hop, whereas data TLVs contain the onion
84
149
/// message content itself.
@@ -237,6 +302,23 @@ impl BlindedRoute {
237
302
}
238
303
}
239
304
305
+ /// The destination of an onion message.
306
+ pub enum Destination {
307
+ /// We're sending this onion message to a node.
308
+ Node ( PublicKey ) ,
309
+ /// We're sending this onion message to a blinded route.
310
+ BlindedRoute ( BlindedRoute ) ,
311
+ }
312
+
313
+ impl Destination {
314
+ fn num_hops ( & self ) -> usize {
315
+ match self {
316
+ Destination :: Node ( _) => 1 ,
317
+ Destination :: BlindedRoute ( BlindedRoute { blinded_hops, .. } ) => blinded_hops. len ( ) ,
318
+ }
319
+ }
320
+ }
321
+
240
322
/// A sender, receiver and forwarder of onion messages. In upcoming releases, this object will be
241
323
/// used to retrieve invoices and fulfill invoice requests from offers.
242
324
pub struct OnionMessenger < Signer : Sign , K : Deref , L : Deref >
@@ -268,6 +350,38 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
268
350
logger,
269
351
}
270
352
}
353
+
354
+ /// Send an empty onion message to `destination`, routing it through `intermediate_nodes`.
355
+ pub fn send_onion_message ( & self , intermediate_nodes : Vec < PublicKey > , destination : Destination ) -> Result < ( ) , secp256k1:: Error > {
356
+ let blinding_secret_bytes = self . keys_manager . get_secure_random_bytes ( ) ;
357
+ let blinding_secret = SecretKey :: from_slice ( & blinding_secret_bytes[ ..] ) . expect ( "RNG is busted" ) ;
358
+ let ( introduction_node_id, blinding_point) = if intermediate_nodes. len ( ) != 0 {
359
+ ( intermediate_nodes[ 0 ] . clone ( ) , PublicKey :: from_secret_key ( & self . secp_ctx , & blinding_secret) )
360
+ } else {
361
+ match destination {
362
+ Destination :: Node ( pk) => ( pk. clone ( ) , PublicKey :: from_secret_key ( & self . secp_ctx , & blinding_secret) ) ,
363
+ Destination :: BlindedRoute ( BlindedRoute { introduction_node_id, blinding_point, .. } ) =>
364
+ ( introduction_node_id. clone ( ) , blinding_point. clone ( ) ) ,
365
+ }
366
+ } ;
367
+ let ( encrypted_data_keys, onion_packet_keys) = construct_sending_keys (
368
+ & self . secp_ctx , & intermediate_nodes, & destination, & blinding_secret) ?;
369
+ let payloads = build_payloads ( intermediate_nodes, destination, encrypted_data_keys) ;
370
+
371
+ let prng_seed = self . keys_manager . get_secure_random_bytes ( ) ;
372
+ let onion_packet = onion_utils:: construct_onion_message_packet ( payloads, onion_packet_keys, prng_seed) ;
373
+
374
+ let mut pending_msg_events = self . pending_msg_events . lock ( ) . unwrap ( ) ;
375
+ pending_msg_events. push ( MessageSendEvent :: SendOnionMessage {
376
+ node_id : introduction_node_id,
377
+ msg : msgs:: OnionMessage {
378
+ blinding_point,
379
+ len : onion_packet. len ( ) ,
380
+ onion_routing_packet : onion_packet,
381
+ }
382
+ } ) ;
383
+ Ok ( ( ) )
384
+ }
271
385
}
272
386
273
387
impl < Signer : Sign , K : Deref , L : Deref > OnionMessageHandler for OnionMessenger < Signer , K , L >
@@ -289,9 +403,59 @@ impl<Signer: Sign, K: Deref, L: Deref> MessageSendEventsProvider for OnionMessen
289
403
}
290
404
}
291
405
406
+ /// Build an onion message's payloads for encoding in the onion packet.
407
+ fn build_payloads ( intermediate_nodes : Vec < PublicKey > , destination : Destination , mut encrypted_tlvs_keys : Vec < SharedSecret > ) -> Vec < ( Payload , SharedSecret ) > {
408
+ let num_intermediate_nodes = intermediate_nodes. len ( ) ;
409
+ let num_payloads = num_intermediate_nodes + destination. num_hops ( ) ;
410
+ assert_eq ! ( encrypted_tlvs_keys. len( ) , num_payloads) ;
411
+ let mut payloads = Vec :: with_capacity ( num_payloads) ;
412
+ let mut enc_tlv_keys = encrypted_tlvs_keys. drain ( ..) ;
413
+ for pk in intermediate_nodes. into_iter ( ) . skip ( 1 ) {
414
+ payloads. push ( ( Payload {
415
+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Forward {
416
+ next_node_id : pk,
417
+ next_blinding_override : None ,
418
+ } )
419
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
420
+ }
421
+ match destination {
422
+ Destination :: Node ( pk) => {
423
+ if num_intermediate_nodes != 0 {
424
+ payloads. push ( ( Payload {
425
+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Forward {
426
+ next_node_id : pk,
427
+ next_blinding_override : None ,
428
+ } )
429
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
430
+ }
431
+ payloads. push ( ( Payload {
432
+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Receive {
433
+ path_id : None ,
434
+ } )
435
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
436
+ } ,
437
+ Destination :: BlindedRoute ( BlindedRoute { introduction_node_id, blinding_point, blinded_hops } ) => {
438
+ if num_intermediate_nodes != 0 {
439
+ payloads. push ( ( Payload {
440
+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Forward {
441
+ next_node_id : introduction_node_id,
442
+ next_blinding_override : Some ( blinding_point) ,
443
+ } )
444
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
445
+ }
446
+ for hop in blinded_hops {
447
+ payloads. push ( ( Payload {
448
+ encrypted_tlvs : EncryptedTlvs :: Blinded ( hop. encrypted_payload ) ,
449
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
450
+ }
451
+ }
452
+ }
453
+ payloads
454
+ }
455
+
292
456
#[ allow( unused_assignments) ]
293
457
#[ inline]
294
- fn construct_keys_callback < T : secp256k1:: Signing + secp256k1:: Verification , FType : FnMut ( PublicKey , SharedSecret , [ u8 ; 32 ] , PublicKey , SharedSecret ) > ( secp_ctx : & Secp256k1 < T > , unblinded_path : & Vec < PublicKey > , session_priv : & SecretKey , mut callback : FType ) -> Result < ( ) , secp256k1:: Error > {
458
+ fn construct_keys_callback < T : secp256k1:: Signing + secp256k1:: Verification , FType : FnMut ( PublicKey , SharedSecret , [ u8 ; 32 ] , PublicKey , SharedSecret ) > ( secp_ctx : & Secp256k1 < T > , unblinded_path : & Vec < PublicKey > , destination : Option < & Destination > , session_priv : & SecretKey , mut callback : FType ) -> Result < ( ) , secp256k1:: Error > {
295
459
let mut msg_blinding_point_priv = session_priv. clone ( ) ;
296
460
let mut msg_blinding_point = PublicKey :: from_secret_key ( secp_ctx, & msg_blinding_point_priv) ;
297
461
let mut onion_packet_pubkey_priv = msg_blinding_point_priv. clone ( ) ;
@@ -339,6 +503,18 @@ fn construct_keys_callback<T: secp256k1::Signing + secp256k1::Verification, FTyp
339
503
for pk in unblinded_path {
340
504
build_keys ! ( pk, false ) ;
341
505
}
506
+ if let Some ( dest) = destination {
507
+ match dest {
508
+ Destination :: Node ( pk) => {
509
+ build_keys ! ( pk, false ) ;
510
+ } ,
511
+ Destination :: BlindedRoute ( BlindedRoute { blinded_hops, .. } ) => {
512
+ for hop in blinded_hops {
513
+ build_keys ! ( hop. blinded_node_id, true ) ;
514
+ }
515
+ } ,
516
+ }
517
+ }
342
518
Ok ( ( ) )
343
519
}
344
520
@@ -353,14 +529,44 @@ fn construct_blinded_route_keys<T: secp256k1::Signing + secp256k1::Verification>
353
529
let mut encrypted_data_keys = Vec :: with_capacity ( unblinded_path. len ( ) ) ;
354
530
let mut blinded_node_pks = Vec :: with_capacity ( unblinded_path. len ( ) ) ;
355
531
356
- construct_keys_callback ( secp_ctx, unblinded_path, session_priv, |blinded_hop_pubkey, _, _, _, encrypted_data_ss| {
532
+ construct_keys_callback ( secp_ctx, unblinded_path, None , session_priv, |blinded_hop_pubkey, _, _, _, encrypted_data_ss| {
357
533
blinded_node_pks. push ( blinded_hop_pubkey) ;
358
534
encrypted_data_keys. push ( encrypted_data_ss) ;
359
535
} ) ?;
360
536
361
537
Ok ( ( encrypted_data_keys, blinded_node_pks) )
362
538
}
363
539
540
+ /// Construct keys for sending an onion message along the given `path`.
541
+ ///
542
+ /// Returns: `(encrypted_tlvs_keys, onion_packet_keys)`
543
+ /// where the encrypted tlvs keys are used to encrypt the [`EncryptedTlvs`] of the onion message and the
544
+ /// onion packet keys are used to encrypt the onion packet.
545
+ fn construct_sending_keys < T : secp256k1:: Signing + secp256k1:: Verification > (
546
+ secp_ctx : & Secp256k1 < T > , unblinded_path : & Vec < PublicKey > , destination : & Destination , session_priv : & SecretKey
547
+ ) -> Result < ( Vec < SharedSecret > , Vec < onion_utils:: OnionKeys > ) , secp256k1:: Error > {
548
+ let num_hops = unblinded_path. len ( ) + destination. num_hops ( ) ;
549
+ let mut encrypted_data_keys = Vec :: with_capacity ( num_hops) ;
550
+ let mut onion_packet_keys = Vec :: with_capacity ( num_hops) ;
551
+
552
+ construct_keys_callback ( secp_ctx, unblinded_path, Some ( destination) , session_priv, |_, onion_packet_ss, _blinding_factor, ephemeral_pubkey, encrypted_data_ss| {
553
+ encrypted_data_keys. push ( encrypted_data_ss) ;
554
+
555
+ let ( rho, mu) = onion_utils:: gen_rho_mu_from_shared_secret ( onion_packet_ss. as_ref ( ) ) ;
556
+ onion_packet_keys. push ( onion_utils:: OnionKeys {
557
+ #[ cfg( test) ]
558
+ shared_secret : onion_packet_ss,
559
+ #[ cfg( test) ]
560
+ blinding_factor : _blinding_factor,
561
+ ephemeral_pubkey,
562
+ rho,
563
+ mu,
564
+ } ) ;
565
+ } ) ?;
566
+
567
+ Ok ( ( encrypted_data_keys, onion_packet_keys) )
568
+ }
569
+
364
570
/// Useful for simplifying the parameters of [`SimpleArcChannelManager`] and
365
571
/// [`SimpleArcPeerManager`]. See their docs for more details.
366
572
///
0 commit comments