@@ -68,11 +68,37 @@ impl BlindedMessagePath {
68
68
/// pubkey in `node_pks` will be the destination node.
69
69
///
70
70
/// Errors if no hops are provided or if `node_pk`(s) are invalid.
71
- // TODO: make all payloads the same size with padding + add dummy hops
72
71
pub fn new < ES : Deref , T : secp256k1:: Signing + secp256k1:: Verification > (
73
72
intermediate_nodes : & [ MessageForwardNode ] , recipient_node_id : PublicKey ,
74
73
context : MessageContext , entropy_source : ES , secp_ctx : & Secp256k1 < T > ,
75
74
) -> Result < Self , ( ) >
75
+ where
76
+ ES :: Target : EntropySource ,
77
+ {
78
+ BlindedMessagePath :: new_with_dummy_hops (
79
+ intermediate_nodes,
80
+ 0 ,
81
+ recipient_node_id,
82
+ context,
83
+ entropy_source,
84
+ secp_ctx,
85
+ )
86
+ }
87
+
88
+ /// Create a path for an onion message, to be forwarded along `node_pks`.
89
+ ///
90
+ /// Additionally allows appending a number of dummy hops before the final hop,
91
+ /// increasing the total path length and enhancing privacy by obscuring the true
92
+ /// distance between sender and recipient.
93
+ ///
94
+ /// The last node pubkey in `node_pks` will be the destination node.
95
+ ///
96
+ /// Errors if no hops are provided or if `node_pk`(s) are invalid.
97
+ pub fn new_with_dummy_hops < ES : Deref , T : secp256k1:: Signing + secp256k1:: Verification > (
98
+ intermediate_nodes : & [ MessageForwardNode ] , dummy_hops_count : u8 ,
99
+ recipient_node_id : PublicKey , context : MessageContext , entropy_source : ES ,
100
+ secp_ctx : & Secp256k1 < T > ,
101
+ ) -> Result < Self , ( ) >
76
102
where
77
103
ES :: Target : EntropySource ,
78
104
{
@@ -91,6 +117,7 @@ impl BlindedMessagePath {
91
117
intermediate_nodes,
92
118
recipient_node_id,
93
119
context,
120
+ dummy_hops_count,
94
121
& blinding_secret,
95
122
)
96
123
. map_err ( |_| ( ) ) ?,
@@ -507,11 +534,13 @@ pub(crate) const MESSAGE_PADDING_ROUND_OFF: usize = 100;
507
534
/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
508
535
pub ( super ) fn blinded_hops < T : secp256k1:: Signing + secp256k1:: Verification > (
509
536
secp_ctx : & Secp256k1 < T > , intermediate_nodes : & [ MessageForwardNode ] ,
510
- recipient_node_id : PublicKey , context : MessageContext , session_priv : & SecretKey ,
537
+ recipient_node_id : PublicKey , context : MessageContext , dummy_hops_count : u8 ,
538
+ session_priv : & SecretKey ,
511
539
) -> Result < Vec < BlindedHop > , secp256k1:: Error > {
512
540
let pks = intermediate_nodes
513
541
. iter ( )
514
542
. map ( |node| node. node_id )
543
+ . chain ( ( 0 ..dummy_hops_count) . map ( |_| recipient_node_id) )
515
544
. chain ( core:: iter:: once ( recipient_node_id) ) ;
516
545
let is_compact = intermediate_nodes. iter ( ) . any ( |node| node. short_channel_id . is_some ( ) ) ;
517
546
@@ -526,6 +555,12 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
526
555
. map ( |next_hop| {
527
556
ControlTlvs :: Forward ( ForwardTlvs { next_hop, next_blinding_override : None } )
528
557
} )
558
+ . chain ( ( 0 ..dummy_hops_count) . map ( |_| {
559
+ ControlTlvs :: Forward ( ForwardTlvs {
560
+ next_hop : NextMessageHop :: NodeId ( recipient_node_id) ,
561
+ next_blinding_override : None ,
562
+ } )
563
+ } ) )
529
564
. chain ( core:: iter:: once ( ControlTlvs :: Receive ( ReceiveTlvs { context : Some ( context) } ) ) ) ;
530
565
531
566
if is_compact {
0 commit comments