Skip to content

Commit 1c0c4b7

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 1c0c4b7

File tree

1 file changed

+47
-2
lines changed

1 file changed

+47
-2
lines changed

lightning/src/blinded_path/message.rs

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ 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>,
@@ -91,6 +90,45 @@ impl BlindedMessagePath {
9190
intermediate_nodes,
9291
recipient_node_id,
9392
context,
93+
0,
94+
&blinding_secret,
95+
)
96+
.map_err(|_| ())?,
97+
}))
98+
}
99+
100+
/// Create a path for an onion message, to be forwarded along `node_pks`.
101+
///
102+
/// Additionally allows appending a number of dummy hops before the final hop,
103+
/// increasing the total path length and enhancing privacy by obscuring the true
104+
/// distance between sender and recipient.
105+
///
106+
/// The last node pubkey in `node_pks` will be the destination node.
107+
///
108+
/// Errors if no hops are provided or if `node_pk`(s) are invalid.
109+
pub fn new_with_dummy_hops<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
110+
intermediate_nodes: &[MessageForwardNode], dummy_hops_count: u8, recipient_node_id: PublicKey,
111+
context: MessageContext, entropy_source: ES, secp_ctx: &Secp256k1<T>,
112+
) -> Result<Self, ()>
113+
where
114+
ES::Target: EntropySource,
115+
{
116+
let introduction_node = IntroductionNode::NodeId(
117+
intermediate_nodes.first().map_or(recipient_node_id, |n| n.node_id),
118+
);
119+
let blinding_secret_bytes = entropy_source.get_secure_random_bytes();
120+
let blinding_secret =
121+
SecretKey::from_slice(&blinding_secret_bytes[..]).expect("RNG is busted");
122+
123+
Ok(Self(BlindedPath {
124+
introduction_node,
125+
blinding_point: PublicKey::from_secret_key(secp_ctx, &blinding_secret),
126+
blinded_hops: blinded_hops(
127+
secp_ctx,
128+
intermediate_nodes,
129+
recipient_node_id,
130+
context,
131+
dummy_hops_count,
94132
&blinding_secret,
95133
)
96134
.map_err(|_| ())?,
@@ -507,11 +545,12 @@ pub(crate) const MESSAGE_PADDING_ROUND_OFF: usize = 100;
507545
/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
508546
pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
509547
secp_ctx: &Secp256k1<T>, intermediate_nodes: &[MessageForwardNode],
510-
recipient_node_id: PublicKey, context: MessageContext, session_priv: &SecretKey,
548+
recipient_node_id: PublicKey, context: MessageContext, dummy_hops_count: u8, session_priv: &SecretKey,
511549
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
512550
let pks = intermediate_nodes
513551
.iter()
514552
.map(|node| node.node_id)
553+
.chain((0..dummy_hops_count).map(|_| recipient_node_id))
515554
.chain(core::iter::once(recipient_node_id));
516555
let is_compact = intermediate_nodes.iter().any(|node| node.short_channel_id.is_some());
517556

@@ -526,6 +565,12 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
526565
.map(|next_hop| {
527566
ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override: None })
528567
})
568+
.chain((0..dummy_hops_count).map(|_| {
569+
ControlTlvs::Forward(ForwardTlvs {
570+
next_hop: NextMessageHop::NodeId(recipient_node_id),
571+
next_blinding_override: None,
572+
})
573+
}))
529574
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { context: Some(context) })));
530575

531576
if is_compact {

0 commit comments

Comments
 (0)