@@ -56,23 +56,51 @@ impl Readable for BlindedMessagePath {
5656impl BlindedMessagePath {
5757 /// Create a one-hop blinded path for a message.
5858 pub fn one_hop < ES : Deref , T : secp256k1:: Signing + secp256k1:: Verification > (
59- recipient_node_id : PublicKey , context : MessageContext , entropy_source : ES ,
60- secp_ctx : & Secp256k1 < T > ,
59+ recipient_node_id : PublicKey , context : MessageContext ,
60+ expanded_key : inbound_payment :: ExpandedKey , entropy_source : ES , secp_ctx : & Secp256k1 < T > ,
6161 ) -> Result < Self , ( ) >
6262 where
6363 ES :: Target : EntropySource ,
6464 {
65- Self :: new ( & [ ] , recipient_node_id, context, entropy_source, secp_ctx)
65+ Self :: new ( & [ ] , recipient_node_id, context, entropy_source, expanded_key , secp_ctx)
6666 }
6767
6868 /// Create a path for an onion message, to be forwarded along `node_pks`. The last node
6969 /// pubkey in `node_pks` will be the destination node.
7070 ///
7171 /// Errors if no hops are provided or if `node_pk`(s) are invalid.
72- // TODO: make all payloads the same size with padding + add dummy hops
7372 pub fn new < ES : Deref , T : secp256k1:: Signing + secp256k1:: Verification > (
7473 intermediate_nodes : & [ MessageForwardNode ] , recipient_node_id : PublicKey ,
75- context : MessageContext , entropy_source : ES , secp_ctx : & Secp256k1 < T > ,
74+ context : MessageContext , entropy_source : ES , expanded_key : inbound_payment:: ExpandedKey ,
75+ secp_ctx : & Secp256k1 < T > ,
76+ ) -> Result < Self , ( ) >
77+ where
78+ ES :: Target : EntropySource ,
79+ {
80+ BlindedMessagePath :: new_with_dummy_hops (
81+ intermediate_nodes,
82+ 0 ,
83+ recipient_node_id,
84+ context,
85+ entropy_source,
86+ expanded_key,
87+ secp_ctx,
88+ )
89+ }
90+
91+ /// Create a path for an onion message, to be forwarded along `node_pks`.
92+ ///
93+ /// Additionally allows appending a number of dummy hops before the final hop,
94+ /// increasing the total path length and enhancing privacy by obscuring the true
95+ /// distance between sender and recipient.
96+ ///
97+ /// The last node pubkey in `node_pks` will be the destination node.
98+ ///
99+ /// Errors if no hops are provided or if `node_pk`(s) are invalid.
100+ pub fn new_with_dummy_hops < ES : Deref , T : secp256k1:: Signing + secp256k1:: Verification > (
101+ intermediate_nodes : & [ MessageForwardNode ] , dummy_hops_count : u8 ,
102+ recipient_node_id : PublicKey , context : MessageContext , entropy_source : ES ,
103+ expanded_key : inbound_payment:: ExpandedKey , secp_ctx : & Secp256k1 < T > ,
76104 ) -> Result < Self , ( ) >
77105 where
78106 ES :: Target : EntropySource ,
@@ -89,9 +117,12 @@ impl BlindedMessagePath {
89117 blinding_point : PublicKey :: from_secret_key ( secp_ctx, & blinding_secret) ,
90118 blinded_hops : blinded_hops (
91119 secp_ctx,
120+ entropy_source,
121+ expanded_key,
92122 intermediate_nodes,
93123 recipient_node_id,
94124 context,
125+ dummy_hops_count,
95126 & blinding_secret,
96127 )
97128 . map_err ( |_| ( ) ) ?,
@@ -545,13 +576,18 @@ impl_writeable_tlv_based!(DNSResolverContext, {
545576pub ( crate ) const MESSAGE_PADDING_ROUND_OFF : usize = 100 ;
546577
547578/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
548- pub ( super ) fn blinded_hops < T : secp256k1:: Signing + secp256k1:: Verification > (
549- secp_ctx : & Secp256k1 < T > , intermediate_nodes : & [ MessageForwardNode ] ,
550- recipient_node_id : PublicKey , context : MessageContext , session_priv : & SecretKey ,
551- ) -> Result < Vec < BlindedHop > , secp256k1:: Error > {
579+ pub ( super ) fn blinded_hops < ES : Deref , T : secp256k1:: Signing + secp256k1:: Verification > (
580+ secp_ctx : & Secp256k1 < T > , entropy_source : ES , expanded_key : inbound_payment:: ExpandedKey ,
581+ intermediate_nodes : & [ MessageForwardNode ] , recipient_node_id : PublicKey ,
582+ context : MessageContext , dummy_hops_count : u8 , session_priv : & SecretKey ,
583+ ) -> Result < Vec < BlindedHop > , secp256k1:: Error >
584+ where
585+ ES :: Target : EntropySource ,
586+ {
552587 let pks = intermediate_nodes
553588 . iter ( )
554589 . map ( |node| node. node_id )
590+ . chain ( ( 0 ..dummy_hops_count) . map ( |_| recipient_node_id) )
555591 . chain ( core:: iter:: once ( recipient_node_id) ) ;
556592 let is_compact = intermediate_nodes. iter ( ) . any ( |node| node. short_channel_id . is_some ( ) ) ;
557593
@@ -566,6 +602,12 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
566602 . map ( |next_hop| {
567603 ControlTlvs :: Forward ( ForwardTlvs { next_hop, next_blinding_override : None } )
568604 } )
605+ . chain ( ( 0 ..dummy_hops_count) . map ( |_| {
606+ let dummy_tlvs = UnauthenticatedDummyTlvs { } ;
607+ let nonce = Nonce :: from_entropy_source ( & * entropy_source) ;
608+ let hmac = dummy_tlvs. hmac_data ( nonce, & expanded_key) ;
609+ ControlTlvs :: Dummy ( DummyTlvs { dummy_tlvs, authentication : ( hmac, nonce) } )
610+ } ) )
569611 . chain ( core:: iter:: once ( ControlTlvs :: Receive ( ReceiveTlvs { context : Some ( context) } ) ) ) ;
570612
571613 if is_compact {
0 commit comments