@@ -28,6 +28,9 @@ use io::{self, Read};
2828use prelude:: * ;
2929use sync:: { Arc , Mutex } ;
3030
31+ pub ( crate ) const SMALL_PACKET_HOP_DATA_LEN : usize = 1300 ;
32+ pub ( crate ) const BIG_PACKET_HOP_DATA_LEN : usize = 32768 ;
33+
3134#[ derive( Clone , Debug , PartialEq ) ]
3235pub ( crate ) struct Packet {
3336 pub ( crate ) version : u8 ,
@@ -37,6 +40,13 @@ pub(crate) struct Packet {
3740 pub ( crate ) hmac : [ u8 ; 32 ] ,
3841}
3942
43+ impl Packet {
44+ fn len ( & self ) -> u16 {
45+ // 32 (hmac) + 33 (public_key) + 1 (version) = 66
46+ self . hop_data . len ( ) as u16 + 66
47+ }
48+ }
49+
4050impl Writeable for Packet {
4151 fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
4252 self . version . write ( w) ?;
@@ -74,6 +84,59 @@ impl LengthReadable for Packet {
7484 }
7585}
7686
87+ /// The payload of an onion message.
88+ pub ( crate ) struct Payload {
89+ /// Onion message payloads contain an encrypted TLV stream, containing both "control" TLVs and
90+ /// sometimes user-provided custom "data" TLVs. See [`EncryptedTlvs`] for more information.
91+ encrypted_tlvs : EncryptedTlvs ,
92+ // Coming soon:
93+ // * `message: Message` field
94+ // * `reply_path: Option<BlindedRoute>` field
95+ }
96+
97+ // Coming soon:
98+ // enum Message {
99+ // InvoiceRequest(InvoiceRequest),
100+ // Invoice(Invoice),
101+ // InvoiceError(InvoiceError),
102+ // CustomMessage<T>,
103+ // }
104+
105+ /// We want to avoid encoding and encrypting separately in order to avoid an intermediate Vec, thus
106+ /// we encode and encrypt at the same time using the secret provided as the second parameter here.
107+ impl Writeable for ( Payload , [ u8 ; 32 ] ) {
108+ fn write < W : Writer > ( & self , w : & mut W ) -> Result < ( ) , io:: Error > {
109+ match & self . 0 . encrypted_tlvs {
110+ EncryptedTlvs :: Blinded ( encrypted_bytes) => {
111+ encode_varint_length_prefixed_tlv ! ( w, {
112+ ( 4 , encrypted_bytes, vec_type)
113+ } )
114+ } ,
115+ EncryptedTlvs :: Unblinded ( control_tlvs) => {
116+ let write_adapter = ChaChaPolyWriteAdapter :: new ( self . 1 , & control_tlvs) ;
117+ encode_varint_length_prefixed_tlv ! ( w, {
118+ ( 4 , write_adapter, required)
119+ } )
120+ }
121+ }
122+ Ok ( ( ) )
123+ }
124+ }
125+
126+ /// Onion messages contain an encrypted TLV stream. This can be supplied by someone else, in the
127+ /// case that we're sending to a blinded route, or created by us if we're constructing payloads for
128+ /// unblinded hops in the onion message's path.
129+ pub ( crate ) enum EncryptedTlvs {
130+ /// If we're sending to a blinded route, the node that constructed the blinded route has provided
131+ /// our onion message's `EncryptedTlvs`, already encrypted and encoded into bytes.
132+ Blinded ( Vec < u8 > ) ,
133+ /// If we're receiving an onion message or constructing an onion message to send through any
134+ /// unblinded nodes, we'll need to construct the onion message's `EncryptedTlvs` in their
135+ /// unblinded state to avoid encoding them into an intermediate `Vec`.
136+ // Below will later have an additional Vec<CustomTlv>
137+ Unblinded ( ControlTlvs ) ,
138+ }
139+
77140/// Onion messages have "control" TLVs and "data" TLVs. Control TLVs are used to control the
78141/// direction and routing of an onion message from hop to hop, whereas data TLVs contain the onion
79142/// message content itself.
@@ -231,6 +294,23 @@ impl BlindedRoute {
231294 }
232295}
233296
297+ /// The destination of an onion message.
298+ pub enum Destination {
299+ /// We're sending this onion message to a node.
300+ Node ( PublicKey ) ,
301+ /// We're sending this onion message to a blinded route.
302+ BlindedRoute ( BlindedRoute ) ,
303+ }
304+
305+ impl Destination {
306+ fn num_hops ( & self ) -> usize {
307+ match self {
308+ Destination :: Node ( _) => 1 ,
309+ Destination :: BlindedRoute ( BlindedRoute { blinded_hops, .. } ) => blinded_hops. len ( ) ,
310+ }
311+ }
312+ }
313+
234314/// A sender, receiver and forwarder of onion messages. In upcoming releases, this object will be
235315/// used to retrieve invoices and fulfill invoice requests from offers.
236316pub struct OnionMessenger < Signer : Sign , K : Deref , L : Deref >
@@ -262,6 +342,38 @@ impl<Signer: Sign, K: Deref, L: Deref> OnionMessenger<Signer, K, L>
262342 logger,
263343 }
264344 }
345+
346+ /// Send an empty onion message to `destination`, routing it through `intermediate_nodes`.
347+ pub fn send_onion_message ( & self , intermediate_nodes : Vec < PublicKey > , destination : Destination ) -> Result < ( ) , secp256k1:: Error > {
348+ let blinding_secret_bytes = self . keys_manager . get_secure_random_bytes ( ) ;
349+ let blinding_secret = SecretKey :: from_slice ( & blinding_secret_bytes[ ..] ) . expect ( "RNG is busted" ) ;
350+ let ( introduction_node_id, blinding_point) = if intermediate_nodes. len ( ) != 0 {
351+ ( intermediate_nodes[ 0 ] . clone ( ) , PublicKey :: from_secret_key ( & self . secp_ctx , & blinding_secret) )
352+ } else {
353+ match destination {
354+ Destination :: Node ( pk) => ( pk. clone ( ) , PublicKey :: from_secret_key ( & self . secp_ctx , & blinding_secret) ) ,
355+ Destination :: BlindedRoute ( BlindedRoute { introduction_node_id, blinding_point, .. } ) =>
356+ ( introduction_node_id. clone ( ) , blinding_point. clone ( ) ) ,
357+ }
358+ } ;
359+ let ( encrypted_data_keys, onion_packet_keys) = construct_sending_keys (
360+ & self . secp_ctx , & intermediate_nodes, & destination, & blinding_secret) ?;
361+ let payloads = build_payloads ( intermediate_nodes, destination, encrypted_data_keys) ;
362+
363+ let prng_seed = self . keys_manager . get_secure_random_bytes ( ) ;
364+ let onion_packet = onion_utils:: construct_onion_message_packet ( payloads, onion_packet_keys, prng_seed) ;
365+
366+ let mut pending_msg_events = self . pending_msg_events . lock ( ) . unwrap ( ) ;
367+ pending_msg_events. push ( MessageSendEvent :: SendOnionMessage {
368+ node_id : introduction_node_id,
369+ msg : msgs:: OnionMessage {
370+ blinding_point,
371+ len : onion_packet. len ( ) ,
372+ onion_routing_packet : onion_packet,
373+ }
374+ } ) ;
375+ Ok ( ( ) )
376+ }
265377}
266378
267379impl < Signer : Sign , K : Deref , L : Deref > OnionMessageHandler for OnionMessenger < Signer , K , L >
@@ -283,19 +395,69 @@ impl<Signer: Sign, K: Deref, L: Deref> MessageSendEventsProvider for OnionMessen
283395 }
284396}
285397
398+ /// Build an onion message's payloads for encoding in the onion packet.
399+ fn build_payloads ( intermediate_nodes : Vec < PublicKey > , destination : Destination , mut encrypted_tlvs_keys : Vec < [ u8 ; 32 ] > ) -> Vec < ( Payload , [ u8 ; 32 ] ) > {
400+ let num_intermediate_nodes = intermediate_nodes. len ( ) ;
401+ let num_payloads = num_intermediate_nodes + destination. num_hops ( ) ;
402+ assert_eq ! ( encrypted_tlvs_keys. len( ) , num_payloads) ;
403+ let mut payloads = Vec :: with_capacity ( num_payloads) ;
404+ let mut enc_tlv_keys = encrypted_tlvs_keys. drain ( ..) ;
405+ for pk in intermediate_nodes. into_iter ( ) . skip ( 1 ) {
406+ payloads. push ( ( Payload {
407+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Forward {
408+ next_node_id : pk,
409+ next_blinding_override : None ,
410+ } )
411+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
412+ }
413+ match destination {
414+ Destination :: Node ( pk) => {
415+ if num_intermediate_nodes != 0 {
416+ payloads. push ( ( Payload {
417+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Forward {
418+ next_node_id : pk,
419+ next_blinding_override : None ,
420+ } )
421+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
422+ }
423+ payloads. push ( ( Payload {
424+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Receive {
425+ path_id : None ,
426+ } )
427+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
428+ } ,
429+ Destination :: BlindedRoute ( BlindedRoute { introduction_node_id, blinding_point, blinded_hops } ) => {
430+ if num_intermediate_nodes != 0 {
431+ payloads. push ( ( Payload {
432+ encrypted_tlvs : EncryptedTlvs :: Unblinded ( ControlTlvs :: Forward {
433+ next_node_id : introduction_node_id,
434+ next_blinding_override : Some ( blinding_point) ,
435+ } )
436+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
437+ }
438+ for hop in blinded_hops {
439+ payloads. push ( ( Payload {
440+ encrypted_tlvs : EncryptedTlvs :: Blinded ( hop. encrypted_payload ) ,
441+ } , enc_tlv_keys. next ( ) . unwrap ( ) ) ) ;
442+ }
443+ }
444+ }
445+ payloads
446+ }
447+
286448#[ inline]
287449fn construct_keys_callback <
288450 T : secp256k1:: Signing + secp256k1:: Verification ,
289451 FType : FnMut ( PublicKey , SharedSecret , [ u8 ; 32 ] , PublicKey , [ u8 ; 32 ] ) >
290- ( secp_ctx : & Secp256k1 < T > , unblinded_path : & Vec < PublicKey > , session_priv : & SecretKey , mut callback : FType )
452+ ( secp_ctx : & Secp256k1 < T > , unblinded_path : & Vec < PublicKey > , destination : Option < & Destination > , session_priv : & SecretKey , mut callback : FType )
291453 -> Result < ( ) , secp256k1:: Error > {
292454 let mut msg_blinding_point_priv = session_priv. clone ( ) ;
293455 let mut msg_blinding_point = PublicKey :: from_secret_key ( secp_ctx, & msg_blinding_point_priv) ;
294456 let mut onion_packet_pubkey_priv = msg_blinding_point_priv. clone ( ) ;
295457 let mut onion_packet_pubkey = msg_blinding_point. clone ( ) ;
296458
297459 macro_rules! build_keys {
298- ( $pk: expr, $blinded: expr) => {
460+ ( $pk: expr, $blinded: expr) => { {
299461 let encrypted_data_ss = SharedSecret :: new( & $pk, & msg_blinding_point_priv) ;
300462
301463 let hop_pk_blinding_factor = {
@@ -312,6 +474,13 @@ fn construct_keys_callback<
312474
313475 let ( rho, _) = onion_utils:: gen_rho_mu_from_shared_secret( encrypted_data_ss. as_ref( ) ) ;
314476 callback( blinded_hop_pk, onion_packet_ss, hop_pk_blinding_factor, onion_packet_pubkey, rho) ;
477+ ( encrypted_data_ss, onion_packet_ss)
478+ } }
479+ }
480+
481+ macro_rules! build_keys_in_loop {
482+ ( $pk: expr, $blinded: expr) => {
483+ let ( encrypted_data_ss, onion_packet_ss) = build_keys!( $pk, $blinded) ;
315484
316485 let msg_blinding_point_blinding_factor = {
317486 let mut sha = Sha256 :: engine( ) ;
@@ -335,7 +504,19 @@ fn construct_keys_callback<
335504 }
336505
337506 for pk in unblinded_path {
338- build_keys ! ( pk, false ) ;
507+ build_keys_in_loop ! ( pk, false ) ;
508+ }
509+ if let Some ( dest) = destination {
510+ match dest {
511+ Destination :: Node ( pk) => {
512+ build_keys ! ( pk, false ) ;
513+ } ,
514+ Destination :: BlindedRoute ( BlindedRoute { blinded_hops, .. } ) => {
515+ for hop in blinded_hops {
516+ build_keys_in_loop ! ( hop. blinded_node_id, true ) ;
517+ }
518+ } ,
519+ }
339520 }
340521 Ok ( ( ) )
341522}
@@ -351,14 +532,44 @@ fn construct_blinded_route_keys<T: secp256k1::Signing + secp256k1::Verification>
351532 let mut encrypted_data_keys = Vec :: with_capacity ( unblinded_path. len ( ) ) ;
352533 let mut blinded_node_pks = Vec :: with_capacity ( unblinded_path. len ( ) ) ;
353534
354- construct_keys_callback ( secp_ctx, unblinded_path, session_priv, |blinded_hop_pubkey, _, _, _, encrypted_data_ss| {
535+ construct_keys_callback ( secp_ctx, unblinded_path, None , session_priv, |blinded_hop_pubkey, _, _, _, encrypted_data_ss| {
355536 blinded_node_pks. push ( blinded_hop_pubkey) ;
356537 encrypted_data_keys. push ( encrypted_data_ss) ;
357538 } ) ?;
358539
359540 Ok ( ( encrypted_data_keys, blinded_node_pks) )
360541}
361542
543+ /// Construct keys for sending an onion message along the given `path`.
544+ ///
545+ /// Returns: `(encrypted_tlvs_keys, onion_packet_keys)`
546+ /// where the encrypted tlvs keys are used to encrypt the [`EncryptedTlvs`] of the onion message and the
547+ /// onion packet keys are used to encrypt the onion packet.
548+ fn construct_sending_keys < T : secp256k1:: Signing + secp256k1:: Verification > (
549+ secp_ctx : & Secp256k1 < T > , unblinded_path : & Vec < PublicKey > , destination : & Destination , session_priv : & SecretKey
550+ ) -> Result < ( Vec < [ u8 ; 32 ] > , Vec < onion_utils:: OnionKeys > ) , secp256k1:: Error > {
551+ let num_hops = unblinded_path. len ( ) + destination. num_hops ( ) ;
552+ let mut encrypted_data_keys = Vec :: with_capacity ( num_hops) ;
553+ let mut onion_packet_keys = Vec :: with_capacity ( num_hops) ;
554+
555+ construct_keys_callback ( secp_ctx, unblinded_path, Some ( destination) , session_priv, |_, onion_packet_ss, _blinding_factor, ephemeral_pubkey, encrypted_data_ss| {
556+ encrypted_data_keys. push ( encrypted_data_ss) ;
557+
558+ let ( rho, mu) = onion_utils:: gen_rho_mu_from_shared_secret ( onion_packet_ss. as_ref ( ) ) ;
559+ onion_packet_keys. push ( onion_utils:: OnionKeys {
560+ #[ cfg( test) ]
561+ shared_secret : onion_packet_ss,
562+ #[ cfg( test) ]
563+ blinding_factor : _blinding_factor,
564+ ephemeral_pubkey,
565+ rho,
566+ mu,
567+ } ) ;
568+ } ) ?;
569+
570+ Ok ( ( encrypted_data_keys, onion_packet_keys) )
571+ }
572+
362573/// Useful for simplifying the parameters of [`SimpleArcChannelManager`] and
363574/// [`SimpleArcPeerManager`]. See their docs for more details.
364575///
0 commit comments