Skip to content

Conversation

@ziggie1984
Copy link
Collaborator

@ziggie1984 ziggie1984 commented Nov 26, 2025

Fixes #9994

@saubyk saubyk added this to the v0.20.1 milestone Nov 27, 2025
@saubyk saubyk added this to lnd v0.20 Nov 27, 2025
@saubyk saubyk moved this to In progress in lnd v0.20 Nov 27, 2025
@ziggie1984 ziggie1984 requested a review from hieblmi November 27, 2025 17:48
// three rules:
// 1. If the invoice target is a public node (exists in graph) => isLsp = false
// (can route directly to the target)
// 2. If all destination hop hints are private nodes => isLsp = false
Copy link

Choose a reason for hiding this comment

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

"destination hop hint" is a bit ambiguous. Would "If for each route hint the last node before the target is a private node, then isLSP returns false" be more clear?

Copy link

Choose a reason for hiding this comment

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

Although this is not a problem for Muun, I'm making a note that if there was a single route hint that looked like:

Public Node ---> Private Node ---> Target Node

then isLSP would return False (as the node immediately before the target node is private).

Ideally we would probe the last public node of each route hint (which might not be the one before last).

I don't know of any LSP that provides invoices with route hints like the one above though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yeah I think it's ok to assume LSP will always provide a routehint slice with the last entry being public.

@btochi
Copy link

btochi commented Nov 28, 2025

lgtm!

@ziggie1984 ziggie1984 marked this pull request as ready for review November 28, 2025 23:24
@ziggie1984
Copy link
Collaborator Author

We limit the probing of different LSPs to 3 to prevent any griefing and inconvenience for the user of the rpc probe command.

The comment was incorrectly referring to HasLightningNode but the
function is named HasNode. Update the comment to match the actual
function name.
This commit adds the HasNode function to the RouterBackend struct,
which checks if a node exists in the graph (i.e., has public channels).
This function is needed by the LSP detection heuristic to determine
if a node is publicly reachable.

The function is wired up in rpcserver.go to query the graph database.
This commit implements a comprehensive LSP (Lightning Service Provider)
detection heuristic and updates the payment probing logic to handle
multiple LSPs with worst-case fee estimation.

Key changes:

1. LSP Detection Heuristic (isLSP function):
   Implements three rules to detect LSP setups:
   - Rule 1: If invoice target is public → NOT an LSP (route directly)
   - Rule 2: If at least one destination hop is public → IS an LSP
   - Rule 3: If all destination hops are private → NOT an LSP

2. LSP Route Preparation (prepareLspRouteHints function):
   - Groups route hints by unique public LSP nodes
   - Filters out non-LSP routes based on the heuristic
   - Tracks worst-case fees and CLTV delays for each LSP
   - Returns adjusted route hints with LSP hop stripped

3. Multi-LSP Probing (probePaymentRequest updates):
   - Probes up to 3 unique LSPs maximum (griefing protection)
   - Selects the WORST-CASE (most expensive) route for conservative
     fee estimation
   - Adds comprehensive debug logging for worst-case selection process
   - Properly formats vertex logging using %v (calls Vertex.String())

The worst-case approach ensures users won't be surprised by higher fees
when the actual payment is sent, providing a more conservative and
reliable fee estimate.

This commit also  adds extensive unit test coverage for the LSP detection
heuristic and route preparation logic.

TestIsLsp:
- Edge cases: empty route hints, nil scenarios
- Rule 1: Public invoice target (3 tests)
- Rule 2: All private destination hops (4 tests)
- Rule 3: At least one public destination hop (6 tests)

TestPrepareLspRouteHints:
- LSP grouping and filtering logic
- Worst-case fee selection across route hints
- Worst-case CLTV delta tracking
- Adjusted route hints validation (LSP hop stripped)
- Multi-LSP scenarios with different fees
This commit enhances the integration test to validate the LSP heuristic
end-to-end with real network topology and payment probing.

Network topology additions:
- Added Frank node as a private destination
- Created multi-LSP test scenario with Bob, Eve, and Dave as LSPs

New test cases:

1. "probe based estimate, public target with public hop hints"
   - Validates Rule 1: public invoice target routes directly
   - Even with public hop hints, direct routing is used
   - Expected: standard single-hop fees

2. "probe based estimate, multiple different public LSPs"
   - Validates multi-LSP worst-case selection
   - Frank has routes through Bob (low fee), Eve (HIGH fee), Dave (medium)
   - Expected: Eve's worst-case fees (most expensive)
   - Tests griefing protection (max 3 LSP probes)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

Consider enhancing LSP heuristic when probing a payment

3 participants