@@ -28,6 +28,11 @@ use io::{self, Read};
28
28
use prelude:: * ;
29
29
use sync:: { Arc , Mutex } ;
30
30
31
+ // Per the spec, an onion message packet's `hop_data` field length should be
32
+ // SMALL_PACKET_HOP_DATA_LEN if it fits, else BIG_PACKET_HOP_DATA_LEN if it fits.
33
+ pub ( crate ) const SMALL_PACKET_HOP_DATA_LEN : usize = 1300 ;
34
+ pub ( crate ) const BIG_PACKET_HOP_DATA_LEN : usize = 32768 ;
35
+
31
36
#[ derive( Clone , Debug , PartialEq ) ]
32
37
pub ( crate ) struct Packet {
33
38
pub ( crate ) version : u8 ,
@@ -37,6 +42,13 @@ pub(crate) struct Packet {
37
42
pub ( crate ) hmac : [ u8 ; 32 ] ,
38
43
}
39
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
+
40
52
impl Writeable for Packet {
41
53
fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
42
54
self . version . write ( w) ?;
@@ -74,6 +86,59 @@ impl LengthReadable for Packet {
74
86
}
75
87
}
76
88
89
+ /// The payload of an onion message.
90
+ pub ( crate ) struct Payload {
91
+ /// Onion message payloads contain an encrypted TLV stream, containing both "control" TLVs and
92
+ /// sometimes user-provided custom "data" TLVs. See [`EncryptedTlvs`] for more information.
93
+ encrypted_tlvs : EncryptedTlvs ,
94
+ // Coming soon:
95
+ // * `message: Message` field
96
+ // * `reply_path: Option<BlindedRoute>` field
97
+ }
98
+
99
+ // Coming soon:
100
+ // enum Message {
101
+ // InvoiceRequest(InvoiceRequest),
102
+ // Invoice(Invoice),
103
+ // InvoiceError(InvoiceError),
104
+ // CustomMessage<T>,
105
+ // }
106
+
107
+ /// We want to avoid encoding and encrypting separately in order to avoid an intermediate Vec, thus
108
+ /// we encode and encrypt at the same time using the secret provided as the second parameter here.
109
+ impl Writeable for ( Payload , [ u8 ; 32 ] ) {
110
+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
111
+ match & self . 0 . encrypted_tlvs {
112
+ EncryptedTlvs :: Blinded ( encrypted_bytes) => {
113
+ encode_varint_length_prefixed_tlv ! ( w, {
114
+ ( 4 , encrypted_bytes, vec_type)
115
+ } )
116
+ } ,
117
+ EncryptedTlvs :: Unblinded ( control_tlvs) => {
118
+ let write_adapter = ChaChaPolyWriteAdapter :: new ( self . 1 , & control_tlvs) ;
119
+ encode_varint_length_prefixed_tlv ! ( w, {
120
+ ( 4 , write_adapter, required)
121
+ } )
122
+ }
123
+ }
124
+ Ok ( ( ) )
125
+ }
126
+ }
127
+
128
+ /// Onion messages contain an encrypted TLV stream. This can be supplied by someone else, in the
129
+ /// case that we're sending to a blinded route, or created by us if we're constructing payloads for
130
+ /// unblinded hops in the onion message's path.
131
+ pub ( crate ) enum EncryptedTlvs {
132
+ /// If we're sending to a blinded route, the node that constructed the blinded route has provided
133
+ /// our onion message's `EncryptedTlvs`, already encrypted and encoded into bytes.
134
+ Blinded ( Vec < u8 > ) ,
135
+ /// If we're receiving an onion message or constructing an onion message to send through any
136
+ /// unblinded nodes, we'll need to construct the onion message's `EncryptedTlvs` in their
137
+ /// unblinded state to avoid encoding them into an intermediate `Vec`.
138
+ // Below will later have an additional Vec<CustomTlv>
139
+ Unblinded ( ControlTlvs ) ,
140
+ }
141
+
77
142
/// Onion messages have "control" TLVs and "data" TLVs. Control TLVs are used to control the
78
143
/// direction and routing of an onion message from hop to hop, whereas data TLVs contain the onion
79
144
/// message content itself.
@@ -231,6 +296,23 @@ impl BlindedRoute {
231
296
}
232
297
}
233
298
299
+ /// The destination of an onion message.
300
+ pub enum Destination {
301
+ /// We're sending this onion message to a node.
302
+ Node ( PublicKey ) ,
303
+ /// We're sending this onion message to a blinded route.
304
+ BlindedRoute ( BlindedRoute ) ,
305
+ }
306
+
307
+ impl Destination {
308
+ fn num_hops ( & self ) -> usize {
309
+ match self {
310
+ Destination :: Node ( _) => 1 ,
311
+ Destination :: BlindedRoute ( BlindedRoute { blinded_hops, .. } ) => blinded_hops. len ( ) ,
312
+ }
313
+ }
314
+ }
315
+
234
316
/// A sender, receiver and forwarder of onion messages. In upcoming releases, this object will be
235
317
/// used to retrieve invoices and fulfill invoice requests from [offers].
236
318
///
@@ -264,6 +346,38 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
264
346
logger,
265
347
}
266
348
}
349
+
350
+ /// Send an empty onion message to `destination`, routing it through `intermediate_nodes`.
351
+ pub fn send_onion_message ( & self , intermediate_nodes : Vec < PublicKey > , destination : Destination ) -> Result < ( ) , secp256k1:: Error > {
352
+ let blinding_secret_bytes = self . keys_manager . get_secure_random_bytes ( ) ;
353
+ let blinding_secret = SecretKey :: from_slice ( & blinding_secret_bytes[ ..] ) . expect ( "RNG is busted" ) ;
354
+ let ( introduction_node_id, blinding_point) = if intermediate_nodes. len ( ) != 0 {
355
+ ( intermediate_nodes[ 0 ] . clone ( ) , PublicKey :: from_secret_key ( & self . secp_ctx , & blinding_secret) )
356
+ } else {
357
+ match destination {
358
+ Destination :: Node ( pk) => ( pk. clone ( ) , PublicKey :: from_secret_key ( & self . secp_ctx , & blinding_secret) ) ,
359
+ Destination :: BlindedRoute ( BlindedRoute { introduction_node_id, blinding_point, .. } ) =>
360
+ ( introduction_node_id. clone ( ) , blinding_point. clone ( ) ) ,
361
+ }
362
+ } ;
363
+ let ( encrypted_data_keys, onion_packet_keys) = construct_sending_keys (
364
+ & self . secp_ctx , & intermediate_nodes, & destination, & blinding_secret) ?;
365
+ let payloads = build_payloads ( intermediate_nodes, destination, encrypted_data_keys) ;
366
+
367
+ let prng_seed = self . keys_manager . get_secure_random_bytes ( ) ;
368
+ let onion_packet = onion_utils:: construct_onion_message_packet ( payloads, onion_packet_keys, prng_seed) ;
369
+
370
+ let mut pending_msg_events = self . pending_msg_events . lock ( ) . unwrap ( ) ;
371
+ pending_msg_events. push ( MessageSendEvent :: SendOnionMessage {
372
+ node_id : introduction_node_id,
373
+ msg : msgs:: OnionMessage {
374
+ blinding_point,
375
+ len : onion_packet. len ( ) ,
376
+ onion_routing_packet : onion_packet,
377
+ }
378
+ } ) ;
379
+ Ok ( ( ) )
380
+ }
267
381
}
268
382
269
383
impl < Signer : Sign , K : Deref , L : Deref > OnionMessageHandler for OnionMessenger < Signer , K , L >
@@ -285,19 +399,69 @@ impl<Signer: Sign, K: Deref, L: Deref> MessageSendEventsProvider for OnionMessen
285
399
}
286
400
}
287
401
402
+ /// Build an onion message's payloads for encoding in the onion packet.
403
+ fn build_payloads ( intermediate_nodes : Vec < PublicKey > , destination : Destination , mut encrypted_tlvs_keys : Vec < [ u8 ; 32 ] > ) -> Vec < ( Payload , [ u8 ; 32 ] ) > {
404
+ let num_intermediate_nodes = intermediate_nodes. len ( ) ;
405
+ let num_payloads = num_intermediate_nodes + destination. num_hops ( ) ;
406
+ assert_eq ! ( encrypted_tlvs_keys. len( ) , num_payloads) ;
407
+ let mut payloads = Vec :: with_capacity ( num_payloads) ;
408
+ let mut enc_tlv_keys = encrypted_tlvs_keys. drain ( ..) ;
409
+ for pk in intermediate_nodes. into_iter ( ) . skip ( 1 ) {
410
+ payloads. push ( ( Payload {
411
+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Forward {
412
+ next_node_id : pk,
413
+ next_blinding_override : None ,
414
+ } )
415
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
416
+ }
417
+ match destination {
418
+ Destination :: Node ( pk) => {
419
+ if num_intermediate_nodes != 0 {
420
+ payloads. push ( ( Payload {
421
+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Forward {
422
+ next_node_id : pk,
423
+ next_blinding_override : None ,
424
+ } )
425
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
426
+ }
427
+ payloads. push ( ( Payload {
428
+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Receive {
429
+ path_id : None ,
430
+ } )
431
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
432
+ } ,
433
+ Destination :: BlindedRoute ( BlindedRoute { introduction_node_id, blinding_point, blinded_hops } ) => {
434
+ if num_intermediate_nodes != 0 {
435
+ payloads. push ( ( Payload {
436
+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Forward {
437
+ next_node_id : introduction_node_id,
438
+ next_blinding_override : Some ( blinding_point) ,
439
+ } )
440
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
441
+ }
442
+ for hop in blinded_hops {
443
+ payloads. push ( ( Payload {
444
+ encrypted_tlvs : EncryptedTlvs :: Blinded ( hop. encrypted_payload ) ,
445
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
446
+ }
447
+ }
448
+ }
449
+ payloads
450
+ }
451
+
288
452
#[ inline]
289
453
fn construct_keys_callback <
290
454
T : secp256k1:: Signing + secp256k1:: Verification ,
291
455
FType : FnMut ( PublicKey , SharedSecret , [ u8 ; 32 ] , PublicKey , [ u8 ; 32 ] ) >
292
- ( secp_ctx : & Secp256k1 < T > , unblinded_path : & Vec < PublicKey > , session_priv : & SecretKey , mut callback : FType )
456
+ ( secp_ctx : & Secp256k1 < T > , unblinded_path : & Vec < PublicKey > , destination : Option < & Destination > , session_priv : & SecretKey , mut callback : FType )
293
457
-> Result < ( ) , secp256k1:: Error > {
294
458
let mut msg_blinding_point_priv = session_priv. clone ( ) ;
295
459
let mut msg_blinding_point = PublicKey :: from_secret_key ( secp_ctx, & msg_blinding_point_priv) ;
296
460
let mut onion_packet_pubkey_priv = msg_blinding_point_priv. clone ( ) ;
297
461
let mut onion_packet_pubkey = msg_blinding_point. clone ( ) ;
298
462
299
463
macro_rules! build_keys {
300
- ( $pk: expr, $blinded: expr) => {
464
+ ( $pk: expr, $blinded: expr) => { {
301
465
let encrypted_data_ss = SharedSecret :: new( & $pk, & msg_blinding_point_priv) ;
302
466
303
467
let hop_pk_blinding_factor = {
@@ -314,6 +478,13 @@ fn construct_keys_callback<
314
478
315
479
let ( rho, _) = onion_utils:: gen_rho_mu_from_shared_secret( encrypted_data_ss. as_ref( ) ) ;
316
480
callback( blinded_hop_pk, onion_packet_ss, hop_pk_blinding_factor, onion_packet_pubkey, rho) ;
481
+ ( encrypted_data_ss, onion_packet_ss)
482
+ } }
483
+ }
484
+
485
+ macro_rules! build_keys_in_loop {
486
+ ( $pk: expr, $blinded: expr) => {
487
+ let ( encrypted_data_ss, onion_packet_ss) = build_keys!( $pk, $blinded) ;
317
488
318
489
let msg_blinding_point_blinding_factor = {
319
490
let mut sha = Sha256 :: engine( ) ;
@@ -337,7 +508,19 @@ fn construct_keys_callback<
337
508
}
338
509
339
510
for pk in unblinded_path {
340
- build_keys ! ( pk, false ) ;
511
+ build_keys_in_loop ! ( pk, false ) ;
512
+ }
513
+ if let Some ( dest) = destination {
514
+ match dest {
515
+ Destination :: Node ( pk) => {
516
+ build_keys ! ( pk, false ) ;
517
+ } ,
518
+ Destination :: BlindedRoute ( BlindedRoute { blinded_hops, .. } ) => {
519
+ for hop in blinded_hops {
520
+ build_keys_in_loop ! ( hop. blinded_node_id, true ) ;
521
+ }
522
+ } ,
523
+ }
341
524
}
342
525
Ok ( ( ) )
343
526
}
@@ -353,14 +536,44 @@ fn construct_blinded_route_keys<T: secp256k1::Signing + secp256k1::Verification>
353
536
let mut encrypted_data_keys = Vec :: with_capacity ( unblinded_path. len ( ) ) ;
354
537
let mut blinded_node_pks = Vec :: with_capacity ( unblinded_path. len ( ) ) ;
355
538
356
- construct_keys_callback ( secp_ctx, unblinded_path, session_priv, |blinded_hop_pubkey, _, _, _, encrypted_data_ss| {
539
+ construct_keys_callback ( secp_ctx, unblinded_path, None , session_priv, |blinded_hop_pubkey, _, _, _, encrypted_data_ss| {
357
540
blinded_node_pks. push ( blinded_hop_pubkey) ;
358
541
encrypted_data_keys. push ( encrypted_data_ss) ;
359
542
} ) ?;
360
543
361
544
Ok ( ( encrypted_data_keys, blinded_node_pks) )
362
545
}
363
546
547
+ /// Construct keys for sending an onion message along the given `path`.
548
+ ///
549
+ /// Returns: `(encrypted_tlvs_keys, onion_packet_keys)`
550
+ /// where the encrypted tlvs keys are used to encrypt the [`EncryptedTlvs`] of the onion message and the
551
+ /// onion packet keys are used to encrypt the onion packet.
552
+ fn construct_sending_keys < T : secp256k1:: Signing + secp256k1:: Verification > (
553
+ secp_ctx : & Secp256k1 < T > , unblinded_path : & Vec < PublicKey > , destination : & Destination , session_priv : & SecretKey
554
+ ) -> Result < ( Vec < [ u8 ; 32 ] > , Vec < onion_utils:: OnionKeys > ) , secp256k1:: Error > {
555
+ let num_hops = unblinded_path. len ( ) + destination. num_hops ( ) ;
556
+ let mut encrypted_data_keys = Vec :: with_capacity ( num_hops) ;
557
+ let mut onion_packet_keys = Vec :: with_capacity ( num_hops) ;
558
+
559
+ construct_keys_callback ( secp_ctx, unblinded_path, Some ( destination) , session_priv, |_, onion_packet_ss, _blinding_factor, ephemeral_pubkey, encrypted_data_ss| {
560
+ encrypted_data_keys. push ( encrypted_data_ss) ;
561
+
562
+ let ( rho, mu) = onion_utils:: gen_rho_mu_from_shared_secret ( onion_packet_ss. as_ref ( ) ) ;
563
+ onion_packet_keys. push ( onion_utils:: OnionKeys {
564
+ #[ cfg( test) ]
565
+ shared_secret : onion_packet_ss,
566
+ #[ cfg( test) ]
567
+ blinding_factor : _blinding_factor,
568
+ ephemeral_pubkey,
569
+ rho,
570
+ mu,
571
+ } ) ;
572
+ } ) ?;
573
+
574
+ Ok ( ( encrypted_data_keys, onion_packet_keys) )
575
+ }
576
+
364
577
/// Useful for simplifying the parameters of [`SimpleArcChannelManager`] and
365
578
/// [`SimpleArcPeerManager`]. See their docs for more details.
366
579
///
0 commit comments