@@ -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_LEN : usize = 1300 ;
32
+ pub ( crate ) const BIG_PACKET_LEN : usize = 32768 ;
33
+
31
34
#[ derive( Clone , Debug , PartialEq ) ]
32
35
pub ( crate ) struct Packet {
33
36
pub ( crate ) version : u8 ,
@@ -79,6 +82,59 @@ impl ReadableArgs<u16> for Packet {
79
82
}
80
83
}
81
84
85
+ /// The payload of an onion message.
86
+ pub ( crate ) struct Payload {
87
+ /// Onion message payloads contain an encrypted TLV stream, containing both "control" TLVs and
88
+ /// sometimes user-provided custom "data" TLVs. See [`EncryptedTlvs`] for more information.
89
+ encrypted_tlvs : EncryptedTlvs ,
90
+ // Coming soon:
91
+ // * custom TLVs
92
+ // * `message: Message` field
93
+ // * `reply_path: Option<BlindedRoute>` field
94
+ }
95
+
96
+ // Coming soon:
97
+ // enum Message {
98
+ // InvoiceRequest(InvoiceRequest),
99
+ // Invoice(Invoice),
100
+ // InvoiceError(InvoiceError),
101
+ // CustomMessage<T>,
102
+ // }
103
+
104
+ /// We want to avoid encoding and encrypting separately in order to avoid an intermediate Vec, thus
105
+ /// we encode and encrypt at the same time using the `SharedSecret` here.
106
+ impl Writeable for ( Payload , SharedSecret ) {
107
+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
108
+ match & self . 0 . encrypted_tlvs {
109
+ EncryptedTlvs :: Blinded ( encrypted_bytes) => {
110
+ encode_varint_length_prefixed_tlv ! ( w, {
111
+ ( 4 , encrypted_bytes, vec_type)
112
+ } )
113
+ } ,
114
+ EncryptedTlvs :: Unblinded ( control_tlvs) => {
115
+ encode_varint_length_prefixed_tlv ! ( w, {
116
+ ( 4 , control_tlvs, ( chacha, self . 1 ) )
117
+ } )
118
+ }
119
+ }
120
+ Ok ( ( ) )
121
+ }
122
+ }
123
+
124
+ /// Onion messages contain an encrypted TLV stream. This can be supplied by someone else, in the
125
+ /// case that we're sending to a blinded route, or created by us if we're constructing payloads for
126
+ /// unblinded hops in the onion message's path.
127
+ pub ( crate ) enum EncryptedTlvs {
128
+ /// If we're sending to a blinded route, the node that constructed the blinded route has provided
129
+ /// our onion message's `EncryptedTlvs`, already encrypted and encoded into bytes.
130
+ Blinded ( Vec < u8 > ) ,
131
+ /// If we're receiving an onion message or constructing an onion message to send through any
132
+ /// unblinded nodes, we'll need to construct the onion message's `EncryptedTlvs` in their
133
+ /// unblinded state to avoid encoding them into an intermediate `Vec`.
134
+ // Below will later have an additional Vec<CustomTlv>
135
+ Unblinded ( ControlTlvs ) ,
136
+ }
137
+
82
138
/// Onion messages have "control" TLVs and "data" TLVs. Control TLVs are used to control the
83
139
/// direction and routing of an onion message from hop to hop, whereas data TLVs contain the onion
84
140
/// message content itself.
@@ -250,6 +306,23 @@ impl BlindedRoute {
250
306
}
251
307
}
252
308
309
+ /// The destination of an onion message.
310
+ pub enum Destination {
311
+ /// We're sending this onion message to a node.
312
+ Node ( PublicKey ) ,
313
+ /// We're sending this onion message to a blinded route.
314
+ BlindedRoute ( BlindedRoute ) ,
315
+ }
316
+
317
+ impl Destination {
318
+ fn num_hops ( & self ) -> usize {
319
+ match self {
320
+ Destination :: Node ( _) => 1 ,
321
+ Destination :: BlindedRoute ( BlindedRoute { blinded_hops, .. } ) => blinded_hops. len ( ) ,
322
+ }
323
+ }
324
+ }
325
+
253
326
/// A sender, receiver and forwarder of onion messages. In upcoming releases, this object will be
254
327
/// used to retrieve invoices and fulfill invoice requests from offers.
255
328
pub struct OnionMessenger < Signer : Sign , K : Deref , L : Deref >
@@ -281,6 +354,39 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
281
354
logger,
282
355
}
283
356
}
357
+
358
+ /// Send an empty onion message to `destination`, routing it through `intermediate_nodes`.
359
+ pub fn send_onion_message ( & self , intermediate_nodes : Vec < PublicKey > , destination : Destination ) -> Result < ( ) , secp256k1:: Error > {
360
+ let blinding_secret_bytes = self . keys_manager . get_secure_random_bytes ( ) ;
361
+ let blinding_secret = SecretKey :: from_slice ( & blinding_secret_bytes[ ..] ) . expect ( "RNG is busted" ) ;
362
+ let ( introduction_node_id, blinding_point) = if intermediate_nodes. len ( ) != 0 {
363
+ ( intermediate_nodes[ 0 ] . clone ( ) , PublicKey :: from_secret_key ( & self . secp_ctx , & blinding_secret) )
364
+ } else {
365
+ match destination {
366
+ Destination :: Node ( pk) => ( pk. clone ( ) , PublicKey :: from_secret_key ( & self . secp_ctx , & blinding_secret) ) ,
367
+ Destination :: BlindedRoute ( BlindedRoute { introduction_node_id, blinding_point, .. } ) =>
368
+ ( introduction_node_id. clone ( ) , blinding_point. clone ( ) ) ,
369
+ }
370
+ } ;
371
+ let ( encrypted_data_keys, onion_packet_keys) = construct_sending_keys (
372
+ & self . secp_ctx , & intermediate_nodes, & destination, & blinding_secret) ?;
373
+ let payloads = build_payloads ( intermediate_nodes, destination, encrypted_data_keys) ;
374
+
375
+ let prng_seed = self . keys_manager . get_secure_random_bytes ( ) ;
376
+ let onion_packet = onion_utils:: construct_onion_message_packet ( payloads, onion_packet_keys, prng_seed) ;
377
+
378
+ // TODO route_size_insane check
379
+ let mut pending_msg_events = self . pending_msg_events . lock ( ) . unwrap ( ) ;
380
+ pending_msg_events. push ( MessageSendEvent :: SendOnionMessage {
381
+ node_id : introduction_node_id,
382
+ msg : msgs:: OnionMessage {
383
+ blinding_point,
384
+ len : 1366 ,
385
+ onion_routing_packet : onion_packet,
386
+ }
387
+ } ) ;
388
+ Ok ( ( ) )
389
+ }
284
390
}
285
391
286
392
impl < Signer : Sign , K : Deref , L : Deref > OnionMessageHandler for OnionMessenger < Signer , K , L >
@@ -302,9 +408,59 @@ impl<Signer: Sign, K: Deref, L: Deref> MessageSendEventsProvider for OnionMessen
302
408
}
303
409
}
304
410
411
+ /// Build an onion message's payloads for encoding in the onion packet.
412
+ fn build_payloads ( intermediate_nodes : Vec < PublicKey > , destination : Destination , mut encrypted_tlvs_keys : Vec < SharedSecret > ) -> Vec < ( Payload , SharedSecret ) > {
413
+ let num_intermediate_nodes = intermediate_nodes. len ( ) ;
414
+ let num_payloads = num_intermediate_nodes + destination. num_hops ( ) ;
415
+ assert_eq ! ( encrypted_tlvs_keys. len( ) , num_payloads) ;
416
+ let mut payloads = Vec :: with_capacity ( num_payloads) ;
417
+ let mut enc_tlv_keys = encrypted_tlvs_keys. drain ( ..) ;
418
+ for pk in intermediate_nodes. into_iter ( ) . skip ( 1 ) {
419
+ payloads. push ( ( Payload {
420
+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Forward {
421
+ next_node_id : pk,
422
+ next_blinding_override : None ,
423
+ } )
424
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
425
+ }
426
+ match destination {
427
+ Destination :: Node ( pk) => {
428
+ if num_intermediate_nodes != 0 {
429
+ payloads. push ( ( Payload {
430
+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Forward {
431
+ next_node_id : pk,
432
+ next_blinding_override : None ,
433
+ } )
434
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
435
+ }
436
+ payloads. push ( ( Payload {
437
+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Receive {
438
+ path_id : None ,
439
+ } )
440
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
441
+ } ,
442
+ Destination :: BlindedRoute ( BlindedRoute { introduction_node_id, blinding_point, blinded_hops } ) => {
443
+ if num_intermediate_nodes != 0 {
444
+ payloads. push ( ( Payload {
445
+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Forward {
446
+ next_node_id : introduction_node_id,
447
+ next_blinding_override : Some ( blinding_point) ,
448
+ } )
449
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
450
+ }
451
+ for hop in blinded_hops {
452
+ payloads. push ( ( Payload {
453
+ encrypted_tlvs : EncryptedTlvs :: Blinded ( hop. encrypted_payload ) ,
454
+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
455
+ }
456
+ }
457
+ }
458
+ payloads
459
+ }
460
+
305
461
#[ allow( unused_assignments) ]
306
462
#[ inline]
307
- 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 > {
463
+ 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 > {
308
464
let mut msg_blinding_point_priv = session_priv. clone ( ) ;
309
465
let mut msg_blinding_point = PublicKey :: from_secret_key ( secp_ctx, & msg_blinding_point_priv) ;
310
466
let mut onion_packet_pubkey_priv = msg_blinding_point_priv. clone ( ) ;
@@ -352,6 +508,18 @@ fn construct_keys_callback<T: secp256k1::Signing + secp256k1::Verification, FTyp
352
508
for pk in unblinded_path {
353
509
build_keys ! ( pk, false ) ;
354
510
}
511
+ if let Some ( dest) = destination {
512
+ match dest {
513
+ Destination :: Node ( pk) => {
514
+ build_keys ! ( pk, false ) ;
515
+ } ,
516
+ Destination :: BlindedRoute ( BlindedRoute { blinded_hops, .. } ) => {
517
+ for hop in blinded_hops {
518
+ build_keys ! ( hop. blinded_node_id, true ) ;
519
+ }
520
+ } ,
521
+ }
522
+ }
355
523
Ok ( ( ) )
356
524
}
357
525
@@ -366,14 +534,44 @@ fn construct_blinded_route_keys<T: secp256k1::Signing + secp256k1::Verification>
366
534
let mut encrypted_data_keys = Vec :: with_capacity ( unblinded_path. len ( ) ) ;
367
535
let mut blinded_node_pks = Vec :: with_capacity ( unblinded_path. len ( ) ) ;
368
536
369
- construct_keys_callback ( secp_ctx, unblinded_path, session_priv, |blinded_hop_pubkey, _, _, _, encrypted_data_ss| {
537
+ construct_keys_callback ( secp_ctx, unblinded_path, None , session_priv, |blinded_hop_pubkey, _, _, _, encrypted_data_ss| {
370
538
blinded_node_pks. push ( blinded_hop_pubkey) ;
371
539
encrypted_data_keys. push ( encrypted_data_ss) ;
372
540
} ) ?;
373
541
374
542
Ok ( ( encrypted_data_keys, blinded_node_pks) )
375
543
}
376
544
545
+ /// Construct keys for sending an onion message along the given `path`.
546
+ ///
547
+ /// Returns: `(encrypted_tlvs_keys, onion_packet_keys)`
548
+ /// where the encrypted tlvs keys are used to encrypt the [`EncryptedTlvs`] of the onion message and the
549
+ /// onion packet keys are used to encrypt the onion packet.
550
+ fn construct_sending_keys < T : secp256k1:: Signing + secp256k1:: Verification > (
551
+ secp_ctx : & Secp256k1 < T > , unblinded_path : & Vec < PublicKey > , destination : & Destination , session_priv : & SecretKey
552
+ ) -> Result < ( Vec < SharedSecret > , Vec < onion_utils:: OnionKeys > ) , secp256k1:: Error > {
553
+ let num_hops = unblinded_path. len ( ) + destination. num_hops ( ) ;
554
+ let mut encrypted_data_keys = Vec :: with_capacity ( num_hops) ;
555
+ let mut onion_packet_keys = Vec :: with_capacity ( num_hops) ;
556
+
557
+ construct_keys_callback ( secp_ctx, unblinded_path, Some ( destination) , session_priv, |_, onion_packet_ss, _blinding_factor, ephemeral_pubkey, encrypted_data_ss| {
558
+ encrypted_data_keys. push ( encrypted_data_ss) ;
559
+
560
+ let ( rho, mu) = onion_utils:: gen_rho_mu_from_shared_secret ( onion_packet_ss. as_ref ( ) ) ;
561
+ onion_packet_keys. push ( onion_utils:: OnionKeys {
562
+ #[ cfg( test) ]
563
+ shared_secret : onion_packet_ss,
564
+ #[ cfg( test) ]
565
+ blinding_factor : _blinding_factor,
566
+ ephemeral_pubkey,
567
+ rho,
568
+ mu,
569
+ } ) ;
570
+ } ) ?;
571
+
572
+ Ok ( ( encrypted_data_keys, onion_packet_keys) )
573
+ }
574
+
377
575
/// Useful for simplifying the parameters of [`SimpleArcChannelManager`] and
378
576
/// [`SimpleArcPeerManager`]. See their docs for more details.
379
577
pub type SimpleArcOnionMessenger < L > = OnionMessenger < InMemorySigner , Arc < KeysManager > , Arc < L > > ;
0 commit comments