mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-09-20 13:04:28 +02:00
466 lines
19 KiB
Markdown
466 lines
19 KiB
Markdown
# `EstimateRouteFee`: A Guide for Wallet Developers
|
|
|
|
## Table of Contents
|
|
|
|
- [Overview](#overview)
|
|
- [Operation Modes](#operation-modes)
|
|
- [Graph-Based Estimation](#graph-based-estimation)
|
|
- [Probe-Based Estimation](#probe-based-estimation)
|
|
- [Private Channel and Hop Hint Handling](#private-channel-and-hop-hint-handling)
|
|
- [Hop Hint Processing](#hop-hint-processing)
|
|
- [Integration with Pathfinding](#integration-with-pathfinding)
|
|
- [LSP Detection and Special Handling](#lsp-detection-and-special-handling)
|
|
- [The LSP Detection Heuristic](#the-lsp-detection-heuristic)
|
|
- [How Probing Differs When an LSP is Detected](#how-probing-differs-when-an-lsp-is-detected)
|
|
- [Route Hint Transformation for LSP Probing](#route-hint-transformation-for-lsp-probing)
|
|
- [Relationship to Zero-Conf Channels](#relationship-to-zero-conf-channels)
|
|
- [Fee Assembly After LSP Probing](#fee-assembly-after-lsp-probing)
|
|
- [Known Limitations and Edge Cases](#known-limitations-and-edge-cases)
|
|
- [Best Practices for Wallet Integration](#best-practices-for-wallet-integration)
|
|
- [Choosing the Appropriate Mode](#choosing-the-appropriate-mode)
|
|
- [Handling Timeouts](#handling-timeouts)
|
|
- [Error Handling](#error-handling)
|
|
- [Fee Presentation](#fee-presentation)
|
|
- [Implementation Examples](#implementation-examples)
|
|
- [Basic Graph-Based Estimation](#basic-graph-based-estimation)
|
|
- [Invoice-Based Estimation with Timeout](#invoice-based-estimation-with-timeout)
|
|
- [Future Improvements](#future-improvements)
|
|
- [Conclusion](#conclusion)
|
|
|
|
## Overview
|
|
|
|
The `EstimateRouteFee` RPC call provides wallet applications with fee estimates
|
|
for Lightning Network payments. Understanding its operation modes and heuristics
|
|
is essential for building reliable payment experiences, particularly when
|
|
dealing with private channels and Lightning Service Providers (LSPs).
|
|
|
|
This document explains the behavioral characteristics, assumptions, and best
|
|
practices for integrating `EstimateRouteFee` into wallet applications, whether
|
|
you're building directly on LND or developing third-party wallet software.
|
|
|
|
## Operation Modes
|
|
|
|
`EstimateRouteFee` operates in two distinct modes, each optimized for different
|
|
use cases and accuracy requirements.
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
Start([EstimateRouteFee Called]) --> Check{Input Type?}
|
|
Check -->|Destination + Amount| Graph[Graph-Based Estimation]
|
|
Check -->|Payment Request/Invoice| Invoice[Invoice Processing]
|
|
|
|
Graph --> LocalPath[Use Local Channel Graph]
|
|
LocalPath --> Mission[Apply Mission Control Data]
|
|
Mission --> CalcFee[Calculate Route & Fee]
|
|
CalcFee --> ReturnFast([Return Fee Estimate<br/>~100ms])
|
|
|
|
Invoice --> HasHints{Has Route Hints?}
|
|
HasHints -->|No| StandardProbe[Standard Probe to Destination]
|
|
HasHints -->|Yes| CheckLSP{Check LSP Heuristic}
|
|
|
|
CheckLSP -->|Not LSP| StandardProbe
|
|
CheckLSP -->|Is LSP| LSPProbe[LSP-Aware Probe]
|
|
|
|
StandardProbe --> SendProbe1[Send Probe with Random Hash]
|
|
LSPProbe --> ModifyHints[Transform Route Hints]
|
|
ModifyHints --> SendProbe2[Probe to LSP Node]
|
|
|
|
SendProbe1 --> ProbeResult1[Wait for Probe Result]
|
|
SendProbe2 --> ProbeResult2[Calculate LSP Fees]
|
|
|
|
ProbeResult1 --> ReturnProbe([Return Fee Estimate<br/>1-60s])
|
|
ProbeResult2 --> ReturnProbe
|
|
```
|
|
|
|
### Graph-Based Estimation
|
|
|
|
When provided with a destination public key and amount, `EstimateRouteFee`
|
|
performs local pathfinding using the in-memory channel graph. This mode executes
|
|
entirely locally without network interaction, making it fast but potentially
|
|
less accurate for complex routing scenarios.
|
|
|
|
This approach uses your node's view of the network topology and mission control
|
|
data (historical payment success rates) to calculate the most economical route.
|
|
A 1 BTC maximum fee limit prevents unreasonable calculations. The estimate
|
|
represents the difference between sent and received amounts.
|
|
|
|
Best for well-connected public nodes with sufficient routing information in the
|
|
public graph. Response times are typically sub-second.
|
|
|
|
### Probe-Based Estimation
|
|
|
|
When provided with an invoice, `EstimateRouteFee` sends probe payments through
|
|
the network using a random payment hash. This ensures the payment fails with
|
|
"incorrect payment details" at the destination, confirming route viability
|
|
without transferring funds.
|
|
|
|
More accurate than graph-based estimation as it tests actual network conditions
|
|
(liquidity, availability, current fees). May take seconds to minutes, especially
|
|
for private channels or LSPs.
|
|
|
|
## Private Channel and Hop Hint Handling
|
|
|
|
Private channels present unique challenges for fee estimation since they don't
|
|
exist in the public channel graph. `EstimateRouteFee` handles these through hop
|
|
hints provided in BOLT11 invoices.
|
|
|
|
### Hop Hint Processing
|
|
|
|
When an invoice contains route hints, `EstimateRouteFee` treats them as
|
|
additional routing information that extends the known network graph. Each hop
|
|
hint describes a private channel that can be used to reach the destination,
|
|
including the channel's routing policies such as fees and timelock requirements.
|
|
|
|
The system makes several important assumptions about hop hints:
|
|
|
|
- **Capacity assumptions**: Private channels are assumed to have sufficient
|
|
capacity for pathfinding calculations. This high capacity assumption
|
|
prevents the pathfinding algorithm from prematurely rejecting routes based
|
|
on amount constraints, as the receiver is expected to have adequate inbound
|
|
liquidity when they include a hop hint for that channel.
|
|
|
|
- **Policy trust**: Routing policies in hop hints (base fee, proportional
|
|
fee, CLTV delta) are trusted without verification, as there's no way to
|
|
independently validate private channel information.
|
|
|
|
### Integration with Pathfinding
|
|
|
|
Hop hints are treated as legitimate routing options alongside public channels,
|
|
enabling paths through both public and private channels. The pathfinding
|
|
algorithm works backward from destination to source, making hop hints critical
|
|
for reaching private destinations.
|
|
|
|
Private edges bypass normal validation and capacity checks. The system trusts
|
|
invoice creators to provide accurate routing information, as incorrect hints
|
|
prevent payment receipt.
|
|
|
|
## LSP Detection and Special Handling
|
|
|
|
Lightning Service Providers require special handling due to their role as
|
|
intermediaries for nodes without direct channel connectivity. `EstimateRouteFee`
|
|
implements sophisticated heuristics to detect LSP scenarios and fundamentally
|
|
modifies its probing behavior when an LSP configuration is identified.
|
|
|
|
### The LSP Detection Heuristic
|
|
|
|
`EstimateRouteFee` employs a pattern-matching algorithm to identify when a
|
|
payment destination is likely behind an LSP. This detection is crucial because
|
|
probing through an LSP requires different handling than standard payment
|
|
probing.
|
|
|
|
The heuristic examines the structure of route hints provided in the invoice to
|
|
identify characteristic LSP patterns. The detection operates on the principle
|
|
that LSPs typically maintain private channels to their users and appear as the
|
|
penultimate hop in payment routing.
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
Start([Route Hints Received]) --> Empty{Empty Hints?}
|
|
Empty -->|Yes| NotLSP([Not LSP])
|
|
Empty -->|No| GetFirst[Get First Hint's Last Hop]
|
|
|
|
GetFirst --> CheckPub1{Is Channel<br/>Public?}
|
|
CheckPub1 -->|Yes| NotLSP
|
|
CheckPub1 -->|No| SaveNode[Save Node ID]
|
|
|
|
SaveNode --> MoreHints{More Hints?}
|
|
MoreHints -->|No| IsLSP([Detected as LSP])
|
|
MoreHints -->|Yes| NextHint[Check Next Hint]
|
|
|
|
NextHint --> GetLast[Get Last Hop]
|
|
GetLast --> CheckPub2{Is Channel<br/>Public?}
|
|
CheckPub2 -->|Yes| NotLSP
|
|
CheckPub2 -->|No| SameNode{Same Node ID<br/>as First?}
|
|
|
|
SameNode -->|No| NotLSP
|
|
SameNode -->|Yes| MoreHints
|
|
```
|
|
|
|
The detection criteria are:
|
|
|
|
- **All route hints must terminate at the same node ID** - This indicates a
|
|
single destination behind potentially multiple LSP entry points
|
|
|
|
- **Final hop channels must be private** - The channels in the last hop of
|
|
each route hint must not exist in the public channel graph
|
|
|
|
- **No public channels in final hops** - If any route hint contains a public
|
|
channel in its final hop, LSP detection is disabled entirely
|
|
|
|
- **Multiple route hints strengthen detection** - While not required,
|
|
multiple hints converging on the same destination strongly suggest an LSP
|
|
configuration
|
|
|
|
This pattern effectively distinguishes LSP configurations from other routing
|
|
scenarios. For instance, some Lightning implementations like CLN include route
|
|
hints even for public nodes to signal liquidity availability or preferred
|
|
routing paths. The heuristic correctly identifies these as non-LSP scenarios by
|
|
detecting the presence of public channels.
|
|
|
|
### How Probing Differs When an LSP is Detected
|
|
|
|
When the LSP detection heuristic identifies an LSP configuration,
|
|
`EstimateRouteFee` fundamentally changes its probing strategy. Understanding
|
|
these differences is crucial for wallet developers to correctly interpret fee
|
|
estimates.
|
|
|
|
#### Standard Probing Behavior
|
|
|
|
When no LSP is detected, the probe targets the invoice's actual destination
|
|
using complete route hints. The probe amount matches the invoice amount with
|
|
standard timelock requirements. Works well for directly reachable destinations.
|
|
|
|
#### LSP-Aware Probing Behavior
|
|
|
|
When an LSP configuration is detected, the probing strategy undergoes several
|
|
fundamental changes that reflect the unique characteristics of LSP-mediated
|
|
payments:
|
|
|
|
- **Probe destination changes to the LSP node** - Instead of targeting the
|
|
final payment recipient, the probe targets the LSP itself, recognizing that
|
|
the service provider handles the final hop independently
|
|
|
|
- **Route hints are modified via prepareLspRouteHints** - The final hop is
|
|
stripped from all route hints, removing the LSP-to-destination segment
|
|
while preserving intermediate hops that help reach the LSP
|
|
|
|
- **Probe amount increases by the LSP's maximum fee** - The system calculates
|
|
the worst-case fee across all route hints and adds it to the probe amount,
|
|
ensuring the estimate accounts for the LSP's forwarding charges
|
|
|
|
- **Timelock requirements switch to LSP's CLTV delta** - The probe uses the
|
|
LSP's timelock requirements instead of the invoice's, with the final
|
|
destination's CLTV added to the estimate after probing
|
|
|
|
- **Modified hints prevent traversal past the LSP** - By removing the final
|
|
hop, the probe cannot attempt to reach the actual destination, which would
|
|
likely fail due to the possible non-existence of LSP-to-user channels in
|
|
the public graph
|
|
|
|
These modifications ensure that fee estimation accurately reflects the two-stage
|
|
nature of LSP-mediated payments: first reaching the LSP through the public
|
|
network, then the LSP's own hop to the final destination.
|
|
|
|
### Route Hint Transformation for LSP Probing
|
|
|
|
When an LSP is detected, the system performs a sophisticated transformation of
|
|
the route hints to enable accurate fee estimation. This transformation, handled
|
|
by the prepareLspRouteHints function, serves three critical purposes.
|
|
|
|
```mermaid
|
|
flowchart LR
|
|
subgraph "Original Route Hints"
|
|
H1[Hop A → Hop B → LSP → Destination]
|
|
H2[Hop C → LSP → Destination]
|
|
H3[Hop D → Hop E → LSP → Destination]
|
|
end
|
|
|
|
Transform[prepareLspRouteHints<br/>Transformation]
|
|
|
|
subgraph "Modified for Probing"
|
|
M1[Hop A → Hop B → LSP]
|
|
M2[Hop C → LSP]
|
|
M3[Hop D → Hop E → LSP]
|
|
end
|
|
|
|
LSPHint[Synthetic LSP Hint<br/>Max Fees & CLTV]
|
|
|
|
H1 --> Transform
|
|
H2 --> Transform
|
|
H3 --> Transform
|
|
|
|
Transform --> M1
|
|
Transform --> M2
|
|
Transform --> M3
|
|
Transform --> LSPHint
|
|
|
|
style LSPHint fill:#f9f,stroke:#333,stroke-width:2px
|
|
```
|
|
|
|
The transformation serves three purposes:
|
|
|
|
1. **Creates a synthetic LSP hop hint** with worst-case fees and CLTV across
|
|
all route hints, ensuring conservative but reliable estimates
|
|
|
|
2. **Strips the final hop** from all route hints, removing the
|
|
LSP-to-destination segment that would cause probe failure
|
|
|
|
3. **Preserves intermediate hops** that help reach the LSP
|
|
|
|
This worst-case approach prioritizes reliability over optimism, particularly
|
|
important for mobile wallets where payment success matters more than minimal
|
|
fees.
|
|
|
|
### Relationship to Zero-Conf Channels
|
|
|
|
LSP detection has important interactions with zero-conf channels, which are
|
|
commonly used in LSP deployments for instant liquidity provision.
|
|
|
|
#### Why LSPs Use Zero-Conf Channels
|
|
|
|
LSPs use zero-conf channels for instant liquidity provision to new users. These
|
|
channels enable immediate routing using SCID aliases, remain private/unconfirmed
|
|
in the public graph, and rely on LSP-user trust relationships.
|
|
|
|
#### Impact on LSP Detection
|
|
|
|
Zero-conf channels align with LSP detection patterns since SCID aliases don't
|
|
appear in the public graph, always appearing as private channels. This alignment
|
|
reflects real-world LSP deployment patterns and strengthens the heuristic's
|
|
effectiveness.
|
|
|
|
#### Implications for Fee Estimation
|
|
|
|
Key considerations for zero-conf channels behind LSPs:
|
|
- Cannot verify channel existence (not in public graph)
|
|
- Capacity assumptions may be optimistic
|
|
- Route hint fees trusted without validation
|
|
- LSP handles liquidity management
|
|
|
|
### Fee Assembly After LSP Probing
|
|
|
|
After successful LSP probing, the system adds:
|
|
- LSP's worst-case fee for the final hop
|
|
- Invoice's final CLTV requirement
|
|
|
|
This two-stage calculation captures both the cost to reach the LSP and the
|
|
LSP's forwarding charges.
|
|
|
|
## Known Limitations and Edge Cases
|
|
|
|
### Probe Success Risk
|
|
|
|
Theoretical risk of probe completion if destination has bugs or non-standard
|
|
behavior. Funds would be lost with only a warning logged. Additionally, probes
|
|
may get stuck in the network, which is why setting appropriate timeouts is
|
|
crucial. Note that liquidity may shift between the probe and the actual payment
|
|
attempt. For larger payments, Multi-Path Payments (MPP) might find better routes
|
|
than the single-path probe, potentially resulting in lower actual fees.
|
|
|
|
### LSP Heuristic Accuracy
|
|
|
|
Can produce false positives (CLN nodes with liquidity hints) and false negatives
|
|
(magic routing hints from services like Boltz). Recent improvements check public
|
|
graph existence to reduce false positives.
|
|
|
|
### Route Hint Validation
|
|
|
|
Route hints trusted without validation. Assumes invoice creators have incentives
|
|
for accuracy (incorrect hints prevent payment receipt).
|
|
|
|
### Capacity and Liquidity Assumptions
|
|
|
|
Capacity assumptions may exceed actual availability. Payments may fail despite
|
|
successful estimation—handle failures gracefully.
|
|
|
|
## Best Practices for Wallet Integration
|
|
|
|
### Choosing the Appropriate Mode
|
|
|
|
**Graph-based**: Quick estimates for well-connected public nodes when you
|
|
have the destination key.
|
|
|
|
**Probe-based**: Accurate estimates for invoices, especially:
|
|
- Private or poorly connected destinations
|
|
- Large payments requiring fee accuracy
|
|
- LSP or complex routing scenarios
|
|
|
|
### Handling Timeouts
|
|
|
|
Set timeouts based on UX needs: 30s standard, 60s for important payments, 15s
|
|
for responsive UIs. Show progress indicators and provide cancel options.
|
|
Consider graph-based fallback for consistent timeouts.
|
|
|
|
### Error Handling
|
|
|
|
Common failures:
|
|
- **NO_ROUTE**: Destination offline, no liquidity, or unreachable
|
|
- **INSUFFICIENT_BALANCE**: Insufficient funds for payment + fees
|
|
- **TIMEOUT**: Probe exceeded timeout (congestion or poor connectivity)
|
|
|
|
Translate errors to user-friendly messages with suggested actions.
|
|
|
|
### Fee Presentation
|
|
|
|
Consider showing fee ranges or confidence levels since estimates may be
|
|
conservative (especially for LSPs using worst-case fees). Probe-based estimates
|
|
reflect current conditions but may change before actual payment.
|
|
|
|
## Implementation Examples
|
|
|
|
### Basic Graph-Based Estimation
|
|
|
|
For graph-based estimation, provide the destination public key and payment
|
|
amount. The response will include the routing fee in millisatoshis and an
|
|
estimated timelock delay. This mode is ideal for quick estimates where you have
|
|
the destination's node ID.
|
|
|
|
```shell
|
|
# Estimate fee for 100,000 satoshi payment to a specific node
|
|
lncli estimateroutefee --dest 0266a18ed969ef95c8a5aa314b443b2b3b8d91ed1d9f8e95476f5f4647efdec079 --amt 100000
|
|
```
|
|
|
|
The typical flow involves calling `EstimateRouteFee` with just the destination
|
|
and amount parameters. The response arrives quickly (usually under 100ms) since
|
|
it uses only local data. Convert the returned fee from millisatoshis to satoshis
|
|
for display, and consider showing the timelock delay to inform users about the
|
|
maximum time their funds might be locked.
|
|
|
|
### Invoice-Based Estimation with Timeout
|
|
|
|
For invoice-based estimation, provide the full payment request string and
|
|
optionally specify a timeout. This mode sends actual probe payments, so timeouts
|
|
are important to prevent long waits for poorly connected destinations.
|
|
|
|
```shell
|
|
# Estimate fee for an invoice with 60-second timeout
|
|
lncli estimateroutefee --pay_req lnbc100n1p3e... --timeout 60s
|
|
|
|
# Shorter timeout for responsive UIs
|
|
lncli estimateroutefee --pay_req lnbc100n1p3e... --timeout 15s
|
|
```
|
|
|
|
When calling `EstimateRouteFee` with a payment request, always set a reasonable
|
|
timeout (30-60 seconds is typical). The response includes not just the fee but
|
|
also a failure reason if the probe fails. Common failure reasons include
|
|
NO_ROUTE (destination unreachable), INSUFFICIENT_BALANCE (not enough funds), or
|
|
TIMEOUT (probe took too long). Handle these gracefully in your UI to guide users
|
|
appropriately.
|
|
|
|
## Future Improvements
|
|
|
|
The `EstimateRouteFee` implementation continues to evolve based on real-world
|
|
usage patterns. Ongoing discussions in the LND community focus on:
|
|
|
|
**Improved LSP Detection**: Developing more sophisticated heuristics that
|
|
accurately identify LSP configurations while avoiding false positives for
|
|
regular private channels.
|
|
|
|
**Multi-Path Payment Support**: Extending fee estimation to support MPP
|
|
scenarios where payments split across multiple routes.
|
|
|
|
**Trampoline Routing Compatibility**: Adapting fee estimation for future
|
|
trampoline routing implementations where intermediate nodes handle pathfinding.
|
|
|
|
**Blinded Path Integration**: Ensuring fee estimation works correctly with
|
|
blinded paths as they become more prevalent in the network.
|
|
|
|
Wallet developers should monitor LND releases and participate in community
|
|
discussions to stay informed about improvements and changes to fee estimation
|
|
behavior.
|
|
|
|
## Conclusion
|
|
|
|
`EstimateRouteFee` provides essential functionality for wallet applications to
|
|
present accurate fee information to users. By understanding its dual-mode
|
|
operation, hop hint processing, and LSP detection heuristics, developers can
|
|
build robust payment experiences that handle both simple public node payments
|
|
and complex private channel scenarios.
|
|
|
|
The key to successful integration lies in choosing the appropriate estimation
|
|
mode for each use case, handling edge cases gracefully, and presenting fee
|
|
information in a way that helps users make informed payment decisions. As the
|
|
Lightning Network evolves, staying informed about `EstimateRouteFee`
|
|
improvements will ensure wallets continue to provide accurate and reliable fee
|
|
estimates.
|