@@ -56,23 +56,51 @@ impl Readable for BlindedMessagePath {
56
56
impl BlindedMessagePath {
57
57
/// Create a one-hop blinded path for a message.
58
58
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 > ,
61
61
) -> Result < Self , ( ) >
62
62
where
63
63
ES :: Target : EntropySource ,
64
64
{
65
- Self :: new ( & [ ] , recipient_node_id, context, entropy_source, secp_ctx)
65
+ Self :: new ( & [ ] , recipient_node_id, context, entropy_source, expanded_key , secp_ctx)
66
66
}
67
67
68
68
/// Create a path for an onion message, to be forwarded along `node_pks`. The last node
69
69
/// pubkey in `node_pks` will be the destination node.
70
70
///
71
71
/// 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
73
72
pub fn new < ES : Deref , T : secp256k1:: Signing + secp256k1:: Verification > (
74
73
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 > ,
76
104
) -> Result < Self , ( ) >
77
105
where
78
106
ES :: Target : EntropySource ,
@@ -89,9 +117,12 @@ impl BlindedMessagePath {
89
117
blinding_point : PublicKey :: from_secret_key ( secp_ctx, & blinding_secret) ,
90
118
blinded_hops : blinded_hops (
91
119
secp_ctx,
120
+ entropy_source,
121
+ expanded_key,
92
122
intermediate_nodes,
93
123
recipient_node_id,
94
124
context,
125
+ dummy_hops_count,
95
126
& blinding_secret,
96
127
)
97
128
. map_err ( |_| ( ) ) ?,
@@ -545,13 +576,18 @@ impl_writeable_tlv_based!(DNSResolverContext, {
545
576
pub ( crate ) const MESSAGE_PADDING_ROUND_OFF : usize = 100 ;
546
577
547
578
/// 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
+ {
552
587
let pks = intermediate_nodes
553
588
. iter ( )
554
589
. map ( |node| node. node_id )
590
+ . chain ( ( 0 ..dummy_hops_count) . map ( |_| recipient_node_id) )
555
591
. chain ( core:: iter:: once ( recipient_node_id) ) ;
556
592
let is_compact = intermediate_nodes. iter ( ) . any ( |node| node. short_channel_id . is_some ( ) ) ;
557
593
@@ -566,6 +602,12 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
566
602
. map ( |next_hop| {
567
603
ControlTlvs :: Forward ( ForwardTlvs { next_hop, next_blinding_override : None } )
568
604
} )
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
+ } ) )
569
611
. chain ( core:: iter:: once ( ControlTlvs :: Receive ( ReceiveTlvs { context : Some ( context) } ) ) ) ;
570
612
571
613
if is_compact {
0 commit comments