Skip to content

Commit 463cc94

Browse files
Introduce Dummy Hop support in Blinded Path Constructor
Adds a new constructor for blinded paths that allows specifying the number of dummy hops. This enables users to insert arbitrary hops before the real destination, enhancing privacy by making it harder to infer the sender–receiver distance or identify the final destination. Lays the groundwork for future use of dummy hops in blinded path construction. Co-authored-by: valentinewallace <[email protected]>
1 parent 8b3f6cc commit 463cc94

File tree

1 file changed

+37
-2
lines changed

1 file changed

+37
-2
lines changed

lightning/src/blinded_path/message.rs

+37-2
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,37 @@ impl BlindedMessagePath {
6868
/// pubkey in `node_pks` will be the destination node.
6969
///
7070
/// 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
7271
pub fn new<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
7372
intermediate_nodes: &[MessageForwardNode], recipient_node_id: PublicKey,
7473
context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>,
7574
) -> 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, ()>
76102
where
77103
ES::Target: EntropySource,
78104
{
@@ -91,6 +117,7 @@ impl BlindedMessagePath {
91117
intermediate_nodes,
92118
recipient_node_id,
93119
context,
120+
dummy_hops_count,
94121
&blinding_secret,
95122
)
96123
.map_err(|_| ())?,
@@ -507,11 +534,13 @@ pub(crate) const MESSAGE_PADDING_ROUND_OFF: usize = 100;
507534
/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
508535
pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
509536
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,
511539
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
512540
let pks = intermediate_nodes
513541
.iter()
514542
.map(|node| node.node_id)
543+
.chain((0..dummy_hops_count).map(|_| recipient_node_id))
515544
.chain(core::iter::once(recipient_node_id));
516545
let is_compact = intermediate_nodes.iter().any(|node| node.short_channel_id.is_some());
517546

@@ -526,6 +555,12 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
526555
.map(|next_hop| {
527556
ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override: None })
528557
})
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+
}))
529564
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { context: Some(context) })));
530565

531566
if is_compact {

0 commit comments

Comments
 (0)