Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exploring the Integration of Dummy Hops into Blinded Paths #3252

Open
shaavan opened this issue Aug 19, 2024 · 1 comment
Open

Exploring the Integration of Dummy Hops into Blinded Paths #3252

shaavan opened this issue Aug 19, 2024 · 1 comment

Comments

@shaavan
Copy link
Member

shaavan commented Aug 19, 2024

This issue is a brainstorming session on why and how we should incorporate an interface for adding dummy hops to blinded paths.

Why Dummy Hops?

Dummy hops function as a privacy enhancement for network nodes. Currently, the MessageRouter can only construct one-hop or two-hop blinded paths. Although this limit could be increased in the future, it is still constrained by the number of actual peers connected to the node.

Introducing the ability to create blinded paths with dummy hops offers several key improvements:

  1. Increased Path Length: The length of the blinded path itself increases, expanding the potential end-points of the blinded path and making de-anonymization more difficult.
  2. Enhanced Utility for Less-Connected Nodes: The benefits of a longer blinded path are not limited by the number of actual peers connected to the node, making this feature valuable even for nodes that are not well-connected.
  3. Obfuscation of the Final Node: The final "true" node is obscured, meaning any of the nodes in the path could potentially be the recipient, adding another layer of privacy.

<><>

  • Technical Analysis:

    In more technical terms, consider a blinded path that is n hops long, where each peer is connected to k other peers.

    • Traditional Case: The potential number of final nodes is k^(n-1).
    • Dummy Hops Case: The potential number of final nodes becomes k^0 + k^1 + ... + k^(n-1) = (k^n - 1)/(k - 1).

    For example, with k=3 and n=4:

    • Traditional case: 27 searchable nodes.
    • Dummy hops case: 40 searchable nodes.

Interface Design

After discussions with @jkczyz, we identified two key decision points for implementing dummy hops:

  1. Responsibility: Should the MessageRouter or ChannelManager be responsible for adding dummy hops?
  2. Parameter Design: Should users specify the number of dummy hops directly, or should they define the total number of hops in the blinded path?

Responsibility: MessageRouter vs ChannelManager

Dummy hops can be interspersed with real hops to achieve the desired path length. This responsibility can be handled by either the MessageRouter or the ChannelManager.

  • MessageRouter Approach:
    • The MessageRouter works on a best-effort basis and can be limited in its capabilities. For example, the current DefaultMessageRouter implementation can return a blinded path with at most two hops.
    • With this approach, if we request a longer path than it can find, it can pad the remaining path length with dummy hops.
    • The main advantage here is easier integration with the existing codebase, keeping the responsibility of creating blinded paths cleanly within the MessageRouter.
    • However, this method might introduce ambiguity, as we won’t know how many hops are real versus dummy.
    • Despite this, given that blinded paths with dummy hops offer similar privacy benefits to those with real hops, this approach could be a valid initial step.
  • ChannelManager Approach:
    • Alternatively, the MessageRouter could return the "Node for Path" instead of a complete BlindedPath, and then the ChannelManager would handle padding the path with dummy hops.
    • This offers more control and transparency over dummy hop addition, but it also increases the complexity of the interface and shifts the burden of blinded path creation onto the ChannelManager.
    • This approach requires a careful trade-off analysis to determine if the added control justifies the increased complexity.

Trade-off Analysis:

With the current codebase, the ChannelManager approach would require significant modifications, which might not justify the added control over dummy hops. A simpler middle-ground solution could be to enable the MessageRouter to back-propagate information about how many dummy nodes it has appended.

Here’s an incomplete branch that explores the ChannelManager approach: [dummy_hops_cm branch](https://github.com/shaavan/rust-lightning/commits/dummy_hops_cm).

  1. The processes of filtering out potential forward nodes and creating blinded paths using them are closely interlinked. For example, many of the variables used in the first part of code are reutilize in the second part. Separating the process would require either recalculation, reallocation, or passing the variable as a parameter to the new function.
  2. Some variables and functions in the blinded path creation part of the code require access to the network_graph (e.g., recipient_announced and path.use_compact_introduction_node(&network_graph)).
  3. Since the network graph is not directly accessible to the ChannelManager, this would lead to a complicated interface design where the ChannelManager and MessageRouter become unnecessarily coupled.

Parameter Design: Total Path Length vs. Number of Dummy Hops

The design of the interface for adding dummy hops can take two primary forms: allowing users to specify either the total length of the blinded path or the number of dummy hops.

Option 1: Specify Total Path Length

In this approach, users define the desired total length of the blinded path. This method offers several benefits:

  • Consistency:
    • Users receive exactly what they ask for—a blinded path of a specific length. This is particularly advantageous in scenarios where consistency of path length is critical, such as in QR code generation for payments, where the maximum path length is constrained by the size of the QR code.

Option 2: Specify the Number of Dummy Hops

Alternatively, the interface could allow users to directly specify the number of dummy hops to be added to the path. This approach offers distinct advantages:

  • Granular Control:
    • Users have precise control over the number of dummy hops, allowing for tailored privacy configurations.

However, this approach also comes with significant disadvantages:

  • Inconsistent Path Lengths:
    • Allowing users to specify only the number of dummy hops can lead to variability in the total path length. This inconsistency might complicate scenarios where a fixed path length is required, such as in QR codes for offers and refunds, where space is a constraint.
  • Increased Complexity:
    • Users might find this approach more complex, as they need to understand the implications of adding specific numbers of dummy hops.

After discussions with @jkczyz, we are leaning toward the first approach (specifying total path length), but we wanted to document our thoughts and keep the discussion open for further input.

Test Branch

I’ve created a test branch to experiment with integrating dummy hops as a parameter during blinded path creation in the MessageRouter.

This branch is rebased over two key PRs: #3177 (which enables padding with dummy hops) and #3246 (which introduces the BlindedPathParameter setup for the new hops parameter).

The branch offers a foundational implementation, providing a clear visualization of how dummy hops could be incorporated.

Conclusion

This issue is still in its early stages, and we welcome any feedback or additional ideas for refinement.

Thank you, everyone, for your thoughts and suggestions!

@TheBlueMatt
Copy link
Collaborator

In general I prefer that we let the MessageRouter decide the kind of blinded paths it wants the ChannelManager to use. This is for a few reasons, (a) it is configurable without needing knobs - the MessageRouter interface is already an interface so users can override it and do whatever they want with it, (b) it seems like the right separation of concerns - the ChannelManager doesn't have a NetworkGraph and is responsible for channel and payment operations, its not responsible for building blinded paths that's the MessageRouter's job.

Instead ChannelManager should give the MessageRouter the context it has - the expiry time of the path, what its being used for, etc (maybe just as a single boolean for if the path is to be included in something that fits in a QR code, maybe more details, I dunno) and let the MessageRouter return a fully-formed BlindedMessagePath for us.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants