Skip to content

Commit 688d782

Browse files
committed
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.
1 parent b9b092e commit 688d782

File tree

1 file changed

+34
-3
lines changed

1 file changed

+34
-3
lines changed

lightning/src/blinded_path/message.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ use crate::types::payment::PaymentHash;
3131
use crate::util::scid_utils;
3232
use crate::util::ser::{FixedLengthReader, LengthReadableArgs, Readable, Writeable, Writer};
3333

34-
use core::mem;
3534
use core::ops::Deref;
3635
use core::time::Duration;
36+
use core::{cmp, mem};
3737

3838
/// A blinded path to be used for sending or receiving a message, hiding the identity of the
3939
/// recipient.
@@ -74,6 +74,26 @@ impl BlindedMessagePath {
7474
local_node_receive_key: ReceiveAuthKey, context: MessageContext, entropy_source: ES,
7575
secp_ctx: &Secp256k1<T>,
7676
) -> Result<Self, ()>
77+
where
78+
ES::Target: EntropySource,
79+
{
80+
BlindedMessagePath::new_with_dummy_hops(
81+
intermediate_nodes,
82+
recipient_node_id,
83+
0,
84+
local_node_receive_key,
85+
context,
86+
entropy_source,
87+
secp_ctx,
88+
)
89+
}
90+
91+
/// Same as [`BlindedMessagePath::new`] but allow specifying a number of dummy hops
92+
pub fn new_with_dummy_hops<ES: Deref, T: secp256k1::Signing + secp256k1::Verification>(
93+
intermediate_nodes: &[MessageForwardNode], recipient_node_id: PublicKey,
94+
dummy_hop_count: usize, local_node_receive_key: ReceiveAuthKey, context: MessageContext,
95+
entropy_source: ES, secp_ctx: &Secp256k1<T>,
96+
) -> Result<Self, ()>
7797
where
7898
ES::Target: EntropySource,
7999
{
@@ -91,6 +111,7 @@ impl BlindedMessagePath {
91111
secp_ctx,
92112
intermediate_nodes,
93113
recipient_node_id,
114+
dummy_hop_count,
94115
context,
95116
&blinding_secret,
96117
local_node_receive_key,
@@ -638,15 +659,24 @@ impl_writeable_tlv_based!(DNSResolverContext, {
638659
/// to pad message blinded path's [`BlindedHop`]
639660
pub(crate) const MESSAGE_PADDING_ROUND_OFF: usize = 100;
640661

662+
/// The maximum number of dummy hops that can be added to a blinded path.
663+
/// This is to prevent paths from becoming too long and potentially causing
664+
/// issues with message processing or routing.
665+
pub(crate) const MAX_DUMMY_HOPS_COUNT: usize = 10;
666+
641667
/// Construct blinded onion message hops for the given `intermediate_nodes` and `recipient_node_id`.
642668
pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
643669
secp_ctx: &Secp256k1<T>, intermediate_nodes: &[MessageForwardNode],
644-
recipient_node_id: PublicKey, context: MessageContext, session_priv: &SecretKey,
645-
local_node_receive_key: ReceiveAuthKey,
670+
recipient_node_id: PublicKey, dummy_hop_count: usize, context: MessageContext,
671+
session_priv: &SecretKey, local_node_receive_key: ReceiveAuthKey,
646672
) -> Result<Vec<BlindedHop>, secp256k1::Error> {
673+
let dummy_count = cmp::min(dummy_hop_count, MAX_DUMMY_HOPS_COUNT);
647674
let pks = intermediate_nodes
648675
.iter()
649676
.map(|node| (node.node_id, None))
677+
.chain(
678+
core::iter::repeat((recipient_node_id, Some(local_node_receive_key))).take(dummy_count),
679+
)
650680
.chain(core::iter::once((recipient_node_id, Some(local_node_receive_key))));
651681
let is_compact = intermediate_nodes.iter().any(|node| node.short_channel_id.is_some());
652682

@@ -661,6 +691,7 @@ pub(super) fn blinded_hops<T: secp256k1::Signing + secp256k1::Verification>(
661691
.map(|next_hop| {
662692
ControlTlvs::Forward(ForwardTlvs { next_hop, next_blinding_override: None })
663693
})
694+
.chain((0..dummy_count).map(|_| ControlTlvs::Dummy(DummyTlv {})))
664695
.chain(core::iter::once(ControlTlvs::Receive(ReceiveTlvs { context: Some(context) })));
665696

666697
if is_compact {

0 commit comments

Comments
 (0)