Skip to content

Stop using an introduction node in blinded message paths#4647

Open
TheBlueMatt wants to merge 1 commit into
lightningdevkit:mainfrom
TheBlueMatt:2026-06-no-bolt12-privacy
Open

Stop using an introduction node in blinded message paths#4647
TheBlueMatt wants to merge 1 commit into
lightningdevkit:mainfrom
TheBlueMatt:2026-06-no-bolt12-privacy

Conversation

@TheBlueMatt
Copy link
Copy Markdown
Collaborator

lnd is preparing to ship a release with opt-in onion messages without support for forwarding onion messages from non-channel peers. This breaks the common BOLT 12 OM flow today where we direct-connect to the blinded path introduction point and send the invoice_request without a channel. For CLN it turns out this is fine as they never select a peer for their introduction point at all. However, for LDK this would break existing nodes as nodes might now pick an lnd peer as an introduction node but it won't forward the onion message.

For now, we just drop the separate introduction point selection and just always use ourselves as an introduction point (assuming we're an announced node).

This should also have the side-effect of making offers marginally more robust, which may be worth it, even if it sucks to drop any pretense of privacy.

lnd is preparing to ship a release with opt-in onion messages
without support for forwarding onion messages from non-channel
peers. This breaks the common BOLT 12 OM flow today where we
direct-connect to the blinded path introduction point and send the
`invoice_request` without a channel. For CLN it turns out this is
fine as they never select a peer for their introduction point at
all. However, for LDK this would break existing nodes as nodes
might now pick an lnd peer as an introduction node but it won't
forward the onion message.

For now, we just drop the separate introduction point selection and
just always use ourselves as an introduction point (assuming we're
an announced node).

This should also have the side-effect of making offers marginally
more robust, which may be worth it, even if it sucks to drop any
pretense of privacy.
@ldk-reviews-bot
Copy link
Copy Markdown

ldk-reviews-bot commented May 29, 2026

I've assigned @jkczyz as a reviewer!
I'll wait for their review and will help manage the review process.
Once they submit their review, I'll check if a second reviewer would be helpful.

@TheBlueMatt TheBlueMatt added this to the 0.3 milestone May 29, 2026
Comment on lines +625 to +626
// Exclude Tor-only nodes when the recipient is announced.
.filter(|(_, is_tor_only, _)| !(*is_tor_only && is_recipient_announced))
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This filter and its comment are dead code. Since we're inside the if !is_recipient_announced branch (line 612), is_recipient_announced is always false here, so !(*is_tor_only && false) is always true — the filter never excludes anything.

The comment "Exclude Tor-only nodes when the recipient is announced" is also misleading since this branch is specifically for unannounced recipients.

Either remove the filter entirely (since it's a no-op), or if the intent is to exclude Tor-only introduction nodes for unannounced recipients too, change it to .filter(|(_, is_tor_only, _)| !*is_tor_only).


// Prefer using non-Tor nodes with the most channels as the introduction node.
peer_info.sort_unstable_by(|(_, a_tor_only, a_channels), (_, b_tor_only, b_channels)| {
a_tor_only.cmp(b_tor_only).then(a_channels.cmp(b_channels).reverse())
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, the Tor-only component of this sort is now effectively dead — since the Tor-only filter above is a no-op (see comment there), Tor-only nodes do still get sorted to the back, but they're never excluded. If excluding Tor-only nodes for unannounced recipients isn't intended, the is_tor_only tracking and sorting could be cleaned up for clarity (just sort by channel count).

@ldk-claude-review-bot
Copy link
Copy Markdown
Collaborator

Review Summary

Found one substantive issue (dead code / misleading comment) in the refactored blinded path logic:

Inline comments posted:

  1. lightning/src/onion_message/messenger.rs:625-626 — The Tor-only filter .filter(|(_, is_tor_only, _)| !(*is_tor_only && is_recipient_announced)) is dead code. It's inside the if !is_recipient_announced branch, so is_recipient_announced is always false, making the filter a no-op. The comment is also misleading ("Exclude Tor-only nodes when the recipient is announced" in a branch that only runs for unannounced recipients).

  2. lightning/src/onion_message/messenger.rs:631 — The Tor-only sorting component is similarly vestigial since the filter it supports is dead. Could be simplified to just sort by channel count.

Cross-cutting notes:

  • The import cleanup in offers_tests.rs is correct — all removed imports (NodeAnnouncement, RoutingMessageHandler, SocketAddress, UnsignedGossipMessage, UnsignedNodeAnnouncement, NodeAlias, NodeId, Recipient) were only used by the removed announce_node_address helper and deleted tests.
  • The removed tests (prefers_non_tor_nodes_in_blinded_paths, prefers_more_connected_nodes_in_blinded_paths) tested behavior that no longer exists (peer-based introduction node selection for announced recipients), so their removal is appropriate.
  • Existing tests (creates_and_pays_for_offer_using_one_hop_blinded_path, creates_long_lived_offer, etc.) cover the new build_path(&[]) code path for announced recipients.

@ldk-reviews-bot ldk-reviews-bot requested a review from jkczyz May 29, 2026 15:56
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

Successfully merging this pull request may close these issues.

3 participants