• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 19027031130

03 Nov 2025 07:27AM UTC coverage: 56.922% (-9.7%) from 66.639%
19027031130

Pull #9334

github

web-flow
Merge b9be11a16 into f938e40af
Pull Request #9334: Use all valid routes during blinded path construction

9 of 11 new or added lines in 3 files covered. (81.82%)

29175 existing lines in 461 files now uncovered.

99696 of 175144 relevant lines covered (56.92%)

1.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

60.32
/routing/router.go
1
package routing
2

3
import (
4
        "context"
5
        "errors"
6
        "fmt"
7
        "math"
8
        "math/big"
9
        "sort"
10
        "sync"
11
        "sync/atomic"
12
        "time"
13

14
        "github.com/btcsuite/btcd/btcec/v2"
15
        "github.com/btcsuite/btcd/btcutil"
16
        "github.com/lightningnetwork/lnd/amp"
17
        "github.com/lightningnetwork/lnd/clock"
18
        "github.com/lightningnetwork/lnd/fn/v2"
19
        "github.com/lightningnetwork/lnd/graph/db/models"
20
        "github.com/lightningnetwork/lnd/htlcswitch"
21
        "github.com/lightningnetwork/lnd/lntypes"
22
        "github.com/lightningnetwork/lnd/lnutils"
23
        "github.com/lightningnetwork/lnd/lnwallet"
24
        "github.com/lightningnetwork/lnd/lnwire"
25
        paymentsdb "github.com/lightningnetwork/lnd/payments/db"
26
        "github.com/lightningnetwork/lnd/record"
27
        "github.com/lightningnetwork/lnd/routing/route"
28
        "github.com/lightningnetwork/lnd/routing/shards"
29
        "github.com/lightningnetwork/lnd/tlv"
30
        "github.com/lightningnetwork/lnd/zpay32"
31
)
32

33
const (
34
        // DefaultPayAttemptTimeout is the default payment attempt timeout. The
35
        // payment attempt timeout defines the duration after which we stop
36
        // trying more routes for a payment.
37
        DefaultPayAttemptTimeout = time.Second * 60
38

39
        // MinCLTVDelta is the minimum CLTV value accepted by LND for all
40
        // timelock deltas. This includes both forwarding CLTV deltas set on
41
        // channel updates, as well as final CLTV deltas used to create BOLT 11
42
        // payment requests.
43
        //
44
        // NOTE: For payment requests, BOLT 11 stipulates that a final CLTV
45
        // delta of 9 should be used when no value is decoded. This however
46
        // leads to inflexibility in upgrading this default parameter, since it
47
        // can create inconsistencies around the assumed value between sender
48
        // and receiver. Specifically, if the receiver assumes a higher value
49
        // than the sender, the receiver will always see the received HTLCs as
50
        // invalid due to their timelock not meeting the required delta.
51
        //
52
        // We skirt this by always setting an explicit CLTV delta when creating
53
        // invoices. This allows LND nodes to freely update the minimum without
54
        // creating incompatibilities during the upgrade process. For some time
55
        // LND has used an explicit default final CLTV delta of 40 blocks for
56
        // bitcoin, though we now clamp the lower end of this
57
        // range for user-chosen deltas to 18 blocks to be conservative.
58
        MinCLTVDelta = 18
59

60
        // MaxCLTVDelta is the maximum CLTV value accepted by LND for all
61
        // timelock deltas.
62
        MaxCLTVDelta = math.MaxUint16
63
)
64

65
var (
66
        // ErrRouterShuttingDown is returned if the router is in the process of
67
        // shutting down.
68
        ErrRouterShuttingDown = fmt.Errorf("router shutting down")
69

70
        // ErrSelfIntro is a failure returned when the source node of a
71
        // route request is also the introduction node. This is not yet
72
        // supported because LND does not support blinded forwardingg.
73
        ErrSelfIntro = errors.New("introduction point as own node not " +
74
                "supported")
75

76
        // ErrHintsAndBlinded is returned if a route request has both
77
        // bolt 11 route hints and a blinded path set.
78
        ErrHintsAndBlinded = errors.New("bolt 11 route hints and blinded " +
79
                "paths are mutually exclusive")
80

81
        // ErrExpiryAndBlinded is returned if a final cltv and a blinded path
82
        // are provided, as the cltv should be provided within the blinded
83
        // path.
84
        ErrExpiryAndBlinded = errors.New("final cltv delta and blinded " +
85
                "paths are mutually exclusive")
86

87
        // ErrTargetAndBlinded is returned is a target destination and a
88
        // blinded path are both set (as the target is inferred from the
89
        // blinded path).
90
        ErrTargetAndBlinded = errors.New("target node and blinded paths " +
91
                "are mutually exclusive")
92

93
        // ErrNoTarget is returned when the target node for a route is not
94
        // provided by either a blinded route or a cleartext pubkey.
95
        ErrNoTarget = errors.New("destination not set in target or blinded " +
96
                "path")
97

98
        // ErrSkipTempErr is returned when a non-MPP is made yet the
99
        // skipTempErr flag is set.
100
        ErrSkipTempErr = errors.New("cannot skip temp error for non-MPP")
101
)
102

103
// PaymentAttemptDispatcher is used by the router to send payment attempts onto
104
// the network, and receive their results.
105
type PaymentAttemptDispatcher interface {
106
        // SendHTLC is a function that directs a link-layer switch to
107
        // forward a fully encoded payment to the first hop in the route
108
        // denoted by its public key. A non-nil error is to be returned if the
109
        // payment was unsuccessful.
110
        SendHTLC(firstHop lnwire.ShortChannelID,
111
                attemptID uint64,
112
                htlcAdd *lnwire.UpdateAddHTLC) error
113

114
        // GetAttemptResult returns the result of the payment attempt with
115
        // the given attemptID. The paymentHash should be set to the payment's
116
        // overall hash, or in case of AMP payments the payment's unique
117
        // identifier.
118
        //
119
        // The method returns a channel where the payment result will be sent
120
        // when available, or an error is encountered during forwarding. When a
121
        // result is received on the channel, the HTLC is guaranteed to no
122
        // longer be in flight.  The switch shutting down is signaled by
123
        // closing the channel. If the attemptID is unknown,
124
        // ErrPaymentIDNotFound will be returned.
125
        GetAttemptResult(attemptID uint64, paymentHash lntypes.Hash,
126
                deobfuscator htlcswitch.ErrorDecrypter) (
127
                <-chan *htlcswitch.PaymentResult, error)
128

129
        // CleanStore calls the underlying result store, telling it is safe to
130
        // delete all entries except the ones in the keepPids map. This should
131
        // be called periodically to let the switch clean up payment results
132
        // that we have handled.
133
        // NOTE: New payment attempts MUST NOT be made after the keepPids map
134
        // has been created and this method has returned.
135
        CleanStore(keepPids map[uint64]struct{}) error
136

137
        // HasAttemptResult reads the network result store to fetch the
138
        // specified attempt. Returns true if the attempt result exists.
139
        //
140
        // NOTE: This method is used and should only be used by the router to
141
        // resume payments during startup. It can be viewed as a subset of
142
        // `GetAttemptResult` in terms of its functionality, and can be removed
143
        // once we move the construction of `UpdateAddHTLC` and
144
        // `ErrorDecrypter` into `htlcswitch`.
145
        HasAttemptResult(attemptID uint64) (bool, error)
146
}
147

148
// PaymentSessionSource is an interface that defines a source for the router to
149
// retrieve new payment sessions.
150
type PaymentSessionSource interface {
151
        // NewPaymentSession creates a new payment session that will produce
152
        // routes to the given target. An optional set of routing hints can be
153
        // provided in order to populate additional edges to explore when
154
        // finding a path to the payment's destination.
155
        NewPaymentSession(p *LightningPayment,
156
                firstHopBlob fn.Option[tlv.Blob],
157
                ts fn.Option[htlcswitch.AuxTrafficShaper]) (PaymentSession,
158
                error)
159

160
        // NewPaymentSessionEmpty creates a new paymentSession instance that is
161
        // empty, and will be exhausted immediately. Used for failure reporting
162
        // to missioncontrol for resumed payment we don't want to make more
163
        // attempts for.
164
        NewPaymentSessionEmpty() PaymentSession
165
}
166

167
// MissionControlQuerier is an interface that exposes failure reporting and
168
// probability estimation.
169
type MissionControlQuerier interface {
170
        // ReportPaymentFail reports a failed payment to mission control as
171
        // input for future probability estimates. It returns a bool indicating
172
        // whether this error is a final error and no further payment attempts
173
        // need to be made.
174
        ReportPaymentFail(attemptID uint64, rt *route.Route,
175
                failureSourceIdx *int, failure lnwire.FailureMessage) (
176
                *paymentsdb.FailureReason, error)
177

178
        // ReportPaymentSuccess reports a successful payment to mission control
179
        // as input for future probability estimates.
180
        ReportPaymentSuccess(attemptID uint64, rt *route.Route) error
181

182
        // GetProbability is expected to return the success probability of a
183
        // payment from fromNode along edge.
184
        GetProbability(fromNode, toNode route.Vertex,
185
                amt lnwire.MilliSatoshi, capacity btcutil.Amount) float64
186
}
187

188
// FeeSchema is the set fee configuration for a Lightning Node on the network.
189
// Using the coefficients described within the schema, the required fee to
190
// forward outgoing payments can be derived.
191
type FeeSchema struct {
192
        // BaseFee is the base amount of milli-satoshis that will be chained
193
        // for ANY payment forwarded.
194
        BaseFee lnwire.MilliSatoshi
195

196
        // FeeRate is the rate that will be charged for forwarding payments.
197
        // This value should be interpreted as the numerator for a fraction
198
        // (fixed point arithmetic) whose denominator is 1 million. As a result
199
        // the effective fee rate charged per mSAT will be: (amount *
200
        // FeeRate/1,000,000).
201
        FeeRate uint32
202

203
        // InboundFee is the inbound fee schedule that applies to forwards
204
        // coming in through a channel to which this FeeSchema pertains.
205
        InboundFee fn.Option[models.InboundFee]
206
}
207

208
// ChannelPolicy holds the parameters that determine the policy we enforce
209
// when forwarding payments on a channel. These parameters are communicated
210
// to the rest of the network in ChannelUpdate messages.
211
type ChannelPolicy struct {
212
        // FeeSchema holds the fee configuration for a channel.
213
        FeeSchema
214

215
        // TimeLockDelta is the required HTLC timelock delta to be used
216
        // when forwarding payments.
217
        TimeLockDelta uint32
218

219
        // MaxHTLC is the maximum HTLC size including fees we are allowed to
220
        // forward over this channel.
221
        MaxHTLC lnwire.MilliSatoshi
222

223
        // MinHTLC is the minimum HTLC size including fees we are allowed to
224
        // forward over this channel.
225
        MinHTLC *lnwire.MilliSatoshi
226
}
227

228
// Config defines the configuration for the ChannelRouter. ALL elements within
229
// the configuration MUST be non-nil for the ChannelRouter to carry out its
230
// duties.
231
type Config struct {
232
        // SelfNode is the public key of the node that this channel router
233
        // belongs to.
234
        SelfNode route.Vertex
235

236
        // RoutingGraph is a graph source that will be used for pathfinding.
237
        RoutingGraph Graph
238

239
        // Chain is the router's source to the most up-to-date blockchain data.
240
        // All incoming advertised channels will be checked against the chain
241
        // to ensure that the channels advertised are still open.
242
        Chain lnwallet.BlockChainIO
243

244
        // Payer is an instance of a PaymentAttemptDispatcher and is used by
245
        // the router to send payment attempts onto the network, and receive
246
        // their results.
247
        Payer PaymentAttemptDispatcher
248

249
        // Control keeps track of the status of ongoing payments, ensuring we
250
        // can properly resume them across restarts.
251
        Control ControlTower
252

253
        // MissionControl is a shared memory of sorts that executions of
254
        // payment path finding use in order to remember which vertexes/edges
255
        // were pruned from prior attempts. During SendPayment execution,
256
        // errors sent by nodes are mapped into a vertex or edge to be pruned.
257
        // Each run will then take into account this set of pruned
258
        // vertexes/edges to reduce route failure and pass on graph information
259
        // gained to the next execution.
260
        MissionControl MissionControlQuerier
261

262
        // SessionSource defines a source for the router to retrieve new payment
263
        // sessions.
264
        SessionSource PaymentSessionSource
265

266
        // GetLink is a method that allows the router to query the lower link
267
        // layer to determine the up-to-date available bandwidth at a
268
        // prospective link to be traversed. If the link isn't available, then
269
        // a value of zero should be returned. Otherwise, the current up-to-
270
        // date knowledge of the available bandwidth of the link should be
271
        // returned.
272
        GetLink getLinkQuery
273

274
        // NextPaymentID is a method that guarantees to return a new, unique ID
275
        // each time it is called. This is used by the router to generate a
276
        // unique payment ID for each payment it attempts to send, such that
277
        // the switch can properly handle the HTLC.
278
        NextPaymentID func() (uint64, error)
279

280
        // PathFindingConfig defines global path finding parameters.
281
        PathFindingConfig PathFindingConfig
282

283
        // Clock is mockable time provider.
284
        Clock clock.Clock
285

286
        // ApplyChannelUpdate can be called to apply a new channel update to the
287
        // graph that we received from a payment failure.
288
        ApplyChannelUpdate func(msg *lnwire.ChannelUpdate1) bool
289

290
        // ClosedSCIDs is used by the router to fetch closed channels.
291
        //
292
        // TODO(yy): remove it once the root cause of stuck payments is found.
293
        ClosedSCIDs map[lnwire.ShortChannelID]struct{}
294

295
        // TrafficShaper is an optional traffic shaper that can be used to
296
        // control the outgoing channel of a payment.
297
        TrafficShaper fn.Option[htlcswitch.AuxTrafficShaper]
298
}
299

300
// EdgeLocator is a struct used to identify a specific edge.
301
type EdgeLocator struct {
302
        // ChannelID is the channel of this edge.
303
        ChannelID uint64
304

305
        // Direction takes the value of 0 or 1 and is identical in definition to
306
        // the channel direction flag. A value of 0 means the direction from the
307
        // lower node pubkey to the higher.
308
        Direction uint8
309
}
310

311
// String returns a human-readable version of the edgeLocator values.
312
func (e *EdgeLocator) String() string {
×
313
        return fmt.Sprintf("%v:%v", e.ChannelID, e.Direction)
×
314
}
×
315

316
// ChannelRouter is the layer 3 router within the Lightning stack. Below the
317
// ChannelRouter is the HtlcSwitch, and below that is the Bitcoin blockchain
318
// itself. The primary role of the ChannelRouter is to respond to queries for
319
// potential routes that can support a payment amount, and also general graph
320
// reachability questions. The router will prune the channel graph
321
// automatically as new blocks are discovered which spend certain known funding
322
// outpoints, thereby closing their respective channels.
323
type ChannelRouter struct {
324
        started uint32 // To be used atomically.
325
        stopped uint32 // To be used atomically.
326

327
        // cfg is a copy of the configuration struct that the ChannelRouter was
328
        // initialized with.
329
        cfg *Config
330

331
        quit chan struct{}
332
        wg   sync.WaitGroup
333
}
334

335
// New creates a new instance of the ChannelRouter with the specified
336
// configuration parameters. As part of initialization, if the router detects
337
// that the channel graph isn't fully in sync with the latest UTXO (since the
338
// channel graph is a subset of the UTXO set) set, then the router will proceed
339
// to fully sync to the latest state of the UTXO set.
340
func New(cfg Config) (*ChannelRouter, error) {
3✔
341
        return &ChannelRouter{
3✔
342
                cfg:  &cfg,
3✔
343
                quit: make(chan struct{}),
3✔
344
        }, nil
3✔
345
}
3✔
346

347
// Start launches all the goroutines the ChannelRouter requires to carry out
348
// its duties. If the router has already been started, then this method is a
349
// noop.
350
func (r *ChannelRouter) Start() error {
3✔
351
        if !atomic.CompareAndSwapUint32(&r.started, 0, 1) {
3✔
352
                return nil
×
353
        }
×
354

355
        log.Info("Channel Router starting")
3✔
356

3✔
357
        // If any payments are still in flight, we resume, to make sure their
3✔
358
        // results are properly handled.
3✔
359
        if err := r.resumePayments(); err != nil {
3✔
360
                log.Error("Failed to resume payments during startup")
×
361
        }
×
362

363
        return nil
3✔
364
}
365

366
// Stop signals the ChannelRouter to gracefully halt all routines. This method
367
// will *block* until all goroutines have excited. If the channel router has
368
// already stopped then this method will return immediately.
369
func (r *ChannelRouter) Stop() error {
3✔
370
        if !atomic.CompareAndSwapUint32(&r.stopped, 0, 1) {
3✔
371
                return nil
×
372
        }
×
373

374
        log.Info("Channel Router shutting down...")
3✔
375
        defer log.Debug("Channel Router shutdown complete")
3✔
376

3✔
377
        close(r.quit)
3✔
378
        r.wg.Wait()
3✔
379

3✔
380
        return nil
3✔
381
}
382

383
// RouteRequest contains the parameters for a pathfinding request. It may
384
// describe a request to make a regular payment or one to a blinded path
385
// (incdicated by a non-nil BlindedPayment field).
386
type RouteRequest struct {
387
        // Source is the node that the path originates from.
388
        Source route.Vertex
389

390
        // Target is the node that the path terminates at. If the route
391
        // includes a blinded path, target will be the blinded node id of the
392
        // final hop in the blinded route.
393
        Target route.Vertex
394

395
        // Amount is the Amount in millisatoshis to be delivered to the target
396
        // node.
397
        Amount lnwire.MilliSatoshi
398

399
        // TimePreference expresses the caller's time preference for
400
        // pathfinding.
401
        TimePreference float64
402

403
        // Restrictions provides a set of additional Restrictions that the
404
        // route must adhere to.
405
        Restrictions *RestrictParams
406

407
        // CustomRecords is a set of custom tlv records to include for the
408
        // final hop.
409
        CustomRecords record.CustomSet
410

411
        // RouteHints contains an additional set of edges to include in our
412
        // view of the graph. This may either be a set of hints for private
413
        // channels or a "virtual" hop hint that represents a blinded route.
414
        RouteHints RouteHints
415

416
        // FinalExpiry is the cltv delta for the final hop. If paying to a
417
        // blinded path, this value is a duplicate of the delta provided
418
        // in blinded payment.
419
        FinalExpiry uint16
420

421
        // BlindedPathSet contains a set of optional blinded paths and
422
        // parameters used to reach a target node blinded paths. This field is
423
        // mutually exclusive with the Target field.
424
        BlindedPathSet *BlindedPaymentPathSet
425
}
426

427
// RouteHints is an alias type for a set of route hints, with the source node
428
// as the map's key and the details of the hint(s) in the edge policy.
429
type RouteHints map[route.Vertex][]AdditionalEdge
430

431
// NewRouteRequest produces a new route request for a regular payment or one
432
// to a blinded route, validating that the target, routeHints and finalExpiry
433
// parameters are mutually exclusive with the blindedPayment parameter (which
434
// contains these values for blinded payments).
435
func NewRouteRequest(source route.Vertex, target *route.Vertex,
436
        amount lnwire.MilliSatoshi, timePref float64,
437
        restrictions *RestrictParams, customRecords record.CustomSet,
438
        routeHints RouteHints, blindedPathSet *BlindedPaymentPathSet,
439
        finalExpiry uint16) (*RouteRequest, error) {
3✔
440

3✔
441
        var (
3✔
442
                // Assume that we're starting off with a regular payment.
3✔
443
                requestHints  = routeHints
3✔
444
                requestExpiry = finalExpiry
3✔
445
                err           error
3✔
446
        )
3✔
447

3✔
448
        if blindedPathSet != nil {
6✔
449
                if blindedPathSet.IsIntroNode(source) {
3✔
UNCOV
450
                        return nil, ErrSelfIntro
×
UNCOV
451
                }
×
452

453
                // Check that the values for a clear path have not been set,
454
                // as this is an ambiguous signal from the caller.
455
                if routeHints != nil {
3✔
UNCOV
456
                        return nil, ErrHintsAndBlinded
×
UNCOV
457
                }
×
458

459
                if finalExpiry != 0 {
3✔
UNCOV
460
                        return nil, ErrExpiryAndBlinded
×
UNCOV
461
                }
×
462

463
                requestExpiry = blindedPathSet.FinalCLTVDelta()
3✔
464

3✔
465
                requestHints, err = blindedPathSet.ToRouteHints()
3✔
466
                if err != nil {
3✔
467
                        return nil, err
×
468
                }
×
469
        }
470

471
        requestTarget, err := getTargetNode(target, blindedPathSet)
3✔
472
        if err != nil {
3✔
UNCOV
473
                return nil, err
×
UNCOV
474
        }
×
475

476
        return &RouteRequest{
3✔
477
                Source:         source,
3✔
478
                Target:         requestTarget,
3✔
479
                Amount:         amount,
3✔
480
                TimePreference: timePref,
3✔
481
                Restrictions:   restrictions,
3✔
482
                CustomRecords:  customRecords,
3✔
483
                RouteHints:     requestHints,
3✔
484
                FinalExpiry:    requestExpiry,
3✔
485
                BlindedPathSet: blindedPathSet,
3✔
486
        }, nil
3✔
487
}
488

489
func getTargetNode(target *route.Vertex,
490
        blindedPathSet *BlindedPaymentPathSet) (route.Vertex, error) {
3✔
491

3✔
492
        var (
3✔
493
                blinded   = blindedPathSet != nil
3✔
494
                targetSet = target != nil
3✔
495
        )
3✔
496

3✔
497
        switch {
3✔
UNCOV
498
        case blinded && targetSet:
×
UNCOV
499
                return route.Vertex{}, ErrTargetAndBlinded
×
500

501
        case blinded:
3✔
502
                return route.NewVertex(blindedPathSet.TargetPubKey()), nil
3✔
503

504
        case targetSet:
3✔
505
                return *target, nil
3✔
506

507
        default:
×
508
                return route.Vertex{}, ErrNoTarget
×
509
        }
510
}
511

512
// FindRoute attempts to query the ChannelRouter for the optimum path to a
513
// particular target destination to which it is able to send `amt` after
514
// factoring in channel capacities and cumulative fees along the route.
515
func (r *ChannelRouter) FindRoute(req *RouteRequest) (*route.Route, float64,
516
        error) {
3✔
517

3✔
518
        log.Debugf("Searching for path to %v, sending %v", req.Target,
3✔
519
                req.Amount)
3✔
520

3✔
521
        // We'll attempt to obtain a set of bandwidth hints that can help us
3✔
522
        // eliminate certain routes early on in the path finding process.
3✔
523
        bandwidthHints, err := newBandwidthManager(
3✔
524
                r.cfg.RoutingGraph, r.cfg.SelfNode, r.cfg.GetLink,
3✔
525
                fn.None[tlv.Blob](), r.cfg.TrafficShaper,
3✔
526
        )
3✔
527
        if err != nil {
3✔
528
                return nil, 0, err
×
529
        }
×
530

531
        // We'll fetch the current block height, so we can properly calculate
532
        // the required HTLC time locks within the route.
533
        _, currentHeight, err := r.cfg.Chain.GetBestBlock()
3✔
534
        if err != nil {
3✔
535
                return nil, 0, err
×
536
        }
×
537

538
        // Now that we know the destination is reachable within the graph, we'll
539
        // execute our path finding algorithm.
540
        finalHtlcExpiry := currentHeight + int32(req.FinalExpiry)
3✔
541

3✔
542
        // Validate time preference.
3✔
543
        timePref := req.TimePreference
3✔
544
        if timePref < -1 || timePref > 1 {
3✔
545
                return nil, 0, errors.New("time preference out of range")
×
546
        }
×
547

548
        path, probability, err := findPath(
3✔
549
                &graphParams{
3✔
550
                        additionalEdges: req.RouteHints,
3✔
551
                        bandwidthHints:  bandwidthHints,
3✔
552
                        graph:           r.cfg.RoutingGraph,
3✔
553
                },
3✔
554
                req.Restrictions, &r.cfg.PathFindingConfig,
3✔
555
                r.cfg.SelfNode, req.Source, req.Target, req.Amount,
3✔
556
                req.TimePreference, finalHtlcExpiry,
3✔
557
        )
3✔
558
        if err != nil {
6✔
559
                return nil, 0, err
3✔
560
        }
3✔
561

562
        // Create the route with absolute time lock values.
563
        route, err := newRoute(
3✔
564
                req.Source, path, uint32(currentHeight),
3✔
565
                finalHopParams{
3✔
566
                        amt:       req.Amount,
3✔
567
                        totalAmt:  req.Amount,
3✔
568
                        cltvDelta: req.FinalExpiry,
3✔
569
                        records:   req.CustomRecords,
3✔
570
                }, req.BlindedPathSet,
3✔
571
        )
3✔
572
        if err != nil {
3✔
573
                return nil, 0, err
×
574
        }
×
575

576
        go log.Tracef("Obtained path to send %v to %x: %v",
3✔
577
                req.Amount, req.Target, lnutils.SpewLogClosure(route))
3✔
578

3✔
579
        return route, probability, nil
3✔
580
}
581

582
// probabilitySource defines the signature of a function that can be used to
583
// query the success probability of sending a given amount between the two
584
// given vertices.
585
type probabilitySource func(route.Vertex, route.Vertex, lnwire.MilliSatoshi,
586
        btcutil.Amount) float64
587

588
// BlindedPathRestrictions are a set of constraints to adhere to when
589
// choosing a set of blinded paths to this node.
590
type BlindedPathRestrictions struct {
591
        // MinDistanceFromIntroNode is the minimum number of _real_ (non-dummy)
592
        // hops to include in a blinded path. Since we post-fix dummy hops, this
593
        // is the minimum distance between our node and the introduction node
594
        // of the path. This doesn't include our node, so if the minimum is 1,
595
        // then the path will contain at minimum our node along with an
596
        // introduction node hop.
597
        MinDistanceFromIntroNode uint8
598

599
        // NumHops is the number of hops that each blinded path should consist
600
        // of. If paths are found with a number of hops less that NumHops, then
601
        // dummy hops will be padded on to the route. This value doesn't
602
        // include our node, so if the maximum is 1, then the path will contain
603
        // our node along with an introduction node hop.
604
        NumHops uint8
605

606
        // NodeOmissionSet is a set of nodes that should not be used within any
607
        // of the blinded paths that we generate.
608
        NodeOmissionSet fn.Set[route.Vertex]
609

610
        // IncomingChainedChannels holds the chained channels list (specified
611
        // via channel id) starting from a channel which points to the receiver
612
        // node.
613
        IncomingChainedChannels []uint64
614
}
615

616
// FindBlindedPaths finds a selection of paths to the destination node that can
617
// be used in blinded payment paths.
618
func (r *ChannelRouter) FindBlindedPaths(destination route.Vertex,
619
        amt lnwire.MilliSatoshi, probabilitySrc probabilitySource,
620
        restrictions *BlindedPathRestrictions) ([]*route.Route, error) {
3✔
621

3✔
622
        // First, find a set of candidate paths given the destination node and
3✔
623
        // path length restrictions.
3✔
624
        incomingChainedChannels := restrictions.IncomingChainedChannels
3✔
625
        minDistanceFromIntroNode := restrictions.MinDistanceFromIntroNode
3✔
626
        paths, err := findBlindedPaths(
3✔
627
                r.cfg.RoutingGraph, destination, &blindedPathRestrictions{
3✔
628
                        minNumHops:              minDistanceFromIntroNode,
3✔
629
                        maxNumHops:              restrictions.NumHops,
3✔
630
                        nodeOmissionSet:         restrictions.NodeOmissionSet,
3✔
631
                        incomingChainedChannels: incomingChainedChannels,
3✔
632
                },
3✔
633
        )
3✔
634
        if err != nil {
6✔
635
                return nil, err
3✔
636
        }
3✔
637

638
        // routeWithProbability groups a route with the probability of a
639
        // payment of the given amount succeeding on that path.
640
        type routeWithProbability struct {
3✔
641
                route       *route.Route
3✔
642
                probability float64
3✔
643
        }
3✔
644

3✔
645
        // Iterate over all the candidate paths and determine the success
3✔
646
        // probability of each path given the data we have about forwards
3✔
647
        // between any two nodes on a path.
3✔
648
        routes := make([]*routeWithProbability, 0, len(paths))
3✔
649
        for _, path := range paths {
6✔
650
                if len(path) < 1 {
3✔
651
                        return nil, fmt.Errorf("a blinded path must have at " +
×
652
                                "least one hop")
×
653
                }
×
654

655
                var (
3✔
656
                        introNode = path[0].vertex
3✔
657
                        prevNode  = introNode
3✔
658
                        hops      = make(
3✔
659
                                []*route.Hop, 0, len(path)-1,
3✔
660
                        )
3✔
661
                        totalRouteProbability = float64(1)
3✔
662
                )
3✔
663

3✔
664
                // For each set of hops on the path, get the success probability
3✔
665
                // of a forward between those two vertices and use that to
3✔
666
                // update the overall route probability.
3✔
667
                for j := 1; j < len(path); j++ {
6✔
668
                        probability := probabilitySrc(
3✔
669
                                prevNode, path[j].vertex, amt,
3✔
670
                                path[j-1].edgeCapacity,
3✔
671
                        )
3✔
672

3✔
673
                        totalRouteProbability *= probability
3✔
674

3✔
675
                        hops = append(hops, &route.Hop{
3✔
676
                                PubKeyBytes: path[j].vertex,
3✔
677
                                ChannelID:   path[j-1].channelID,
3✔
678
                        })
3✔
679

3✔
680
                        prevNode = path[j].vertex
3✔
681
                }
3✔
682

683
                routeWithProbability := &routeWithProbability{
3✔
684
                        route: &route.Route{
3✔
685
                                SourcePubKey: introNode,
3✔
686
                                Hops:         hops,
3✔
687
                        },
3✔
688
                        probability: totalRouteProbability,
3✔
689
                }
3✔
690

3✔
691
                // Don't bother adding a route if its success probability less
3✔
692
                // minimum that can be assigned to any single pair.
3✔
693
                if totalRouteProbability <= DefaultMinRouteProbability {
3✔
UNCOV
694
                        log.Debugf("Not using route (%v) as a blinded "+
×
UNCOV
695
                                "path since it resulted in an low "+
×
UNCOV
696
                                "probability path(%.3f)",
×
UNCOV
697
                                route.ChanIDString(routeWithProbability.route),
×
UNCOV
698
                                routeWithProbability.probability)
×
UNCOV
699

×
UNCOV
700
                        continue
×
701
                }
702

703
                routes = append(routes, routeWithProbability)
3✔
704
        }
705

706
        // Sort the routes based on probability.
707
        sort.Slice(routes, func(i, j int) bool {
6✔
708
                return routes[i].probability > routes[j].probability
3✔
709
        })
3✔
710

711
        // Now just get all paths ordered by probability.
712
        allRoutes := make([]*route.Route, 0, len(routes))
3✔
713
        for _, route := range routes {
6✔
714
                allRoutes = append(allRoutes, route.route)
3✔
715
        }
3✔
716

717
        return allRoutes, nil
3✔
718
}
719

720
// generateNewSessionKey generates a new ephemeral private key to be used for a
721
// payment attempt.
722
func generateNewSessionKey() (*btcec.PrivateKey, error) {
3✔
723
        // Generate a new random session key to ensure that we don't trigger
3✔
724
        // any replay.
3✔
725
        //
3✔
726
        // TODO(roasbeef): add more sources of randomness?
3✔
727
        return btcec.NewPrivateKey()
3✔
728
}
3✔
729

730
// LightningPayment describes a payment to be sent through the network to the
731
// final destination.
732
type LightningPayment struct {
733
        // Target is the node in which the payment should be routed towards.
734
        Target route.Vertex
735

736
        // Amount is the value of the payment to send through the network in
737
        // milli-satoshis.
738
        Amount lnwire.MilliSatoshi
739

740
        // FeeLimit is the maximum fee in millisatoshis that the payment should
741
        // accept when sending it through the network. The payment will fail
742
        // if there isn't a route with lower fees than this limit.
743
        FeeLimit lnwire.MilliSatoshi
744

745
        // CltvLimit is the maximum time lock that is allowed for attempts to
746
        // complete this payment.
747
        CltvLimit uint32
748

749
        // paymentHash is the r-hash value to use within the HTLC extended to
750
        // the first hop. This won't be set for AMP payments.
751
        paymentHash *lntypes.Hash
752

753
        // amp is an optional field that is set if and only if this is am AMP
754
        // payment.
755
        amp *AMPOptions
756

757
        // FinalCLTVDelta is the CTLV expiry delta to use for the _final_ hop
758
        // in the route. This means that the final hop will have a CLTV delta
759
        // of at least: currentHeight + FinalCLTVDelta.
760
        FinalCLTVDelta uint16
761

762
        // PayAttemptTimeout is a timeout value that we'll use to determine
763
        // when we should should abandon the payment attempt after consecutive
764
        // payment failure. This prevents us from attempting to send a payment
765
        // indefinitely. A zero value means the payment will never time out.
766
        //
767
        // TODO(halseth): make wallclock time to allow resume after startup.
768
        PayAttemptTimeout time.Duration
769

770
        // RouteHints represents the different routing hints that can be used to
771
        // assist a payment in reaching its destination successfully. These
772
        // hints will act as intermediate hops along the route.
773
        //
774
        // NOTE: This is optional unless required by the payment. When providing
775
        // multiple routes, ensure the hop hints within each route are chained
776
        // together and sorted in forward order in order to reach the
777
        // destination successfully. This is mutually exclusive to the
778
        // BlindedPayment field.
779
        RouteHints [][]zpay32.HopHint
780

781
        // BlindedPathSet holds the information about a set of blinded paths to
782
        // the payment recipient. This is mutually exclusive to the RouteHints
783
        // field.
784
        BlindedPathSet *BlindedPaymentPathSet
785

786
        // OutgoingChannelIDs is the list of channels that are allowed for the
787
        // first hop. If nil, any channel may be used.
788
        OutgoingChannelIDs []uint64
789

790
        // LastHop is the pubkey of the last node before the final destination
791
        // is reached. If nil, any node may be used.
792
        LastHop *route.Vertex
793

794
        // DestFeatures specifies the set of features we assume the final node
795
        // has for pathfinding. Typically, these will be taken directly from an
796
        // invoice, but they can also be manually supplied or assumed by the
797
        // sender. If a nil feature vector is provided, the router will try to
798
        // fall back to the graph in order to load a feature vector for a node
799
        // in the public graph.
800
        DestFeatures *lnwire.FeatureVector
801

802
        // PaymentAddr is the payment address specified by the receiver. This
803
        // field should be a random 32-byte nonce presented in the receiver's
804
        // invoice to prevent probing of the destination.
805
        PaymentAddr fn.Option[[32]byte]
806

807
        // PaymentRequest is an optional payment request that this payment is
808
        // attempting to complete.
809
        PaymentRequest []byte
810

811
        // DestCustomRecords are TLV records that are to be sent to the final
812
        // hop in the new onion payload format. If the destination does not
813
        // understand this new onion payload format, then the payment will
814
        // fail.
815
        DestCustomRecords record.CustomSet
816

817
        // FirstHopCustomRecords are the TLV records that are to be sent to the
818
        // first hop of this payment. These records will be transmitted via the
819
        // wire message and therefore do not affect the onion payload size.
820
        FirstHopCustomRecords lnwire.CustomRecords
821

822
        // MaxParts is the maximum number of partial payments that may be used
823
        // to complete the full amount.
824
        MaxParts uint32
825

826
        // MaxShardAmt is the largest shard that we'll attempt to split using.
827
        // If this field is set, and we need to split, rather than attempting
828
        // half of the original payment amount, we'll use this value if half
829
        // the payment amount is greater than it.
830
        //
831
        // NOTE: This field is _optional_.
832
        MaxShardAmt *lnwire.MilliSatoshi
833

834
        // TimePref is the time preference for this payment. Set to -1 to
835
        // optimize for fees only, to 1 to optimize for reliability only or a
836
        // value in between for a mix.
837
        TimePref float64
838

839
        // Metadata is additional data that is sent along with the payment to
840
        // the payee.
841
        Metadata []byte
842
}
843

844
// AMPOptions houses information that must be known in order to send an AMP
845
// payment.
846
type AMPOptions struct {
847
        SetID     [32]byte
848
        RootShare [32]byte
849
}
850

851
// SetPaymentHash sets the given hash as the payment's overall hash. This
852
// should only be used for non-AMP payments.
853
func (l *LightningPayment) SetPaymentHash(hash lntypes.Hash) error {
3✔
854
        if l.amp != nil {
3✔
855
                return fmt.Errorf("cannot set payment hash for AMP payment")
×
856
        }
×
857

858
        l.paymentHash = &hash
3✔
859
        return nil
3✔
860
}
861

862
// SetAMP sets the given AMP options for the payment.
863
func (l *LightningPayment) SetAMP(amp *AMPOptions) error {
3✔
864
        if l.paymentHash != nil {
3✔
865
                return fmt.Errorf("cannot set amp options for payment " +
×
866
                        "with payment hash")
×
867
        }
×
868

869
        l.amp = amp
3✔
870
        return nil
3✔
871
}
872

873
// Identifier returns a 32-byte slice that uniquely identifies this single
874
// payment. For non-AMP payments this will be the payment hash, for AMP
875
// payments this will be the used SetID.
876
func (l *LightningPayment) Identifier() [32]byte {
3✔
877
        if l.amp != nil {
6✔
878
                return l.amp.SetID
3✔
879
        }
3✔
880

881
        return *l.paymentHash
3✔
882
}
883

884
// SendPayment attempts to send a payment as described within the passed
885
// LightningPayment. This function is blocking and will return either: when the
886
// payment is successful, or all candidates routes have been attempted and
887
// resulted in a failed payment. If the payment succeeds, then a non-nil Route
888
// will be returned which describes the path the successful payment traversed
889
// within the network to reach the destination. Additionally, the payment
890
// preimage will also be returned.
891
func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte,
UNCOV
892
        *route.Route, error) {
×
UNCOV
893

×
UNCOV
894
        paySession, shardTracker, err := r.PreparePayment(payment)
×
UNCOV
895
        if err != nil {
×
896
                return [32]byte{}, nil, err
×
897
        }
×
898

UNCOV
899
        log.Tracef("Dispatching SendPayment for lightning payment: %v",
×
UNCOV
900
                spewPayment(payment))
×
UNCOV
901

×
UNCOV
902
        return r.sendPayment(
×
UNCOV
903
                context.Background(), payment.FeeLimit, payment.Identifier(),
×
UNCOV
904
                payment.PayAttemptTimeout, paySession, shardTracker,
×
UNCOV
905
                payment.FirstHopCustomRecords,
×
UNCOV
906
        )
×
907
}
908

909
// SendPaymentAsync is the non-blocking version of SendPayment. The payment
910
// result needs to be retrieved via the control tower.
911
func (r *ChannelRouter) SendPaymentAsync(ctx context.Context,
912
        payment *LightningPayment, ps PaymentSession, st shards.ShardTracker) {
3✔
913

3✔
914
        // Since this is the first time this payment is being made, we pass nil
3✔
915
        // for the existing attempt.
3✔
916
        r.wg.Add(1)
3✔
917
        go func() {
6✔
918
                defer r.wg.Done()
3✔
919

3✔
920
                log.Tracef("Dispatching SendPayment for lightning payment: %v",
3✔
921
                        spewPayment(payment))
3✔
922

3✔
923
                _, _, err := r.sendPayment(
3✔
924
                        ctx, payment.FeeLimit, payment.Identifier(),
3✔
925
                        payment.PayAttemptTimeout, ps, st,
3✔
926
                        payment.FirstHopCustomRecords,
3✔
927
                )
3✔
928
                if err != nil {
6✔
929
                        log.Errorf("Payment %x failed: %v",
3✔
930
                                payment.Identifier(), err)
3✔
931
                }
3✔
932
        }()
933
}
934

935
// spewPayment returns a log closures that provides a spewed string
936
// representation of the passed payment.
937
func spewPayment(payment *LightningPayment) lnutils.LogClosure {
3✔
938
        return lnutils.NewLogClosure(func() string {
3✔
939
                // Make a copy of the payment with a nilled Curve
×
940
                // before spewing.
×
941
                var routeHints [][]zpay32.HopHint
×
942
                for _, routeHint := range payment.RouteHints {
×
943
                        var hopHints []zpay32.HopHint
×
944
                        for _, hopHint := range routeHint {
×
945
                                h := hopHint.Copy()
×
946
                                hopHints = append(hopHints, h)
×
947
                        }
×
948
                        routeHints = append(routeHints, hopHints)
×
949
                }
950
                p := *payment
×
951
                p.RouteHints = routeHints
×
952

×
953
                return lnutils.SpewLogClosure(p)()
×
954
        })
955
}
956

957
// PreparePayment creates the payment session and registers the payment with the
958
// control tower.
959
func (r *ChannelRouter) PreparePayment(payment *LightningPayment) (
960
        PaymentSession, shards.ShardTracker, error) {
3✔
961

3✔
962
        // Assemble any custom data we want to send to the first hop only.
3✔
963
        var firstHopData fn.Option[tlv.Blob]
3✔
964
        if len(payment.FirstHopCustomRecords) > 0 {
6✔
965
                if err := payment.FirstHopCustomRecords.Validate(); err != nil {
3✔
966
                        return nil, nil, fmt.Errorf("invalid first hop custom "+
×
967
                                "records: %w", err)
×
968
                }
×
969

970
                firstHopBlob, err := payment.FirstHopCustomRecords.Serialize()
3✔
971
                if err != nil {
3✔
972
                        return nil, nil, fmt.Errorf("unable to serialize "+
×
973
                                "first hop custom records: %w", err)
×
974
                }
×
975

976
                firstHopData = fn.Some(firstHopBlob)
3✔
977
        }
978

979
        // Before starting the HTLC routing attempt, we'll create a fresh
980
        // payment session which will report our errors back to mission
981
        // control.
982
        paySession, err := r.cfg.SessionSource.NewPaymentSession(
3✔
983
                payment, firstHopData, r.cfg.TrafficShaper,
3✔
984
        )
3✔
985
        if err != nil {
3✔
986
                return nil, nil, err
×
987
        }
×
988

989
        // Record this payment hash with the ControlTower, ensuring it is not
990
        // already in-flight.
991
        //
992
        // TODO(roasbeef): store records as part of creation info?
993
        info := &paymentsdb.PaymentCreationInfo{
3✔
994
                PaymentIdentifier:     payment.Identifier(),
3✔
995
                Value:                 payment.Amount,
3✔
996
                CreationTime:          r.cfg.Clock.Now(),
3✔
997
                PaymentRequest:        payment.PaymentRequest,
3✔
998
                FirstHopCustomRecords: payment.FirstHopCustomRecords,
3✔
999
        }
3✔
1000

3✔
1001
        // Create a new ShardTracker that we'll use during the life cycle of
3✔
1002
        // this payment.
3✔
1003
        var shardTracker shards.ShardTracker
3✔
1004
        switch {
3✔
1005
        // If this is an AMP payment, we'll use the AMP shard tracker.
1006
        case payment.amp != nil:
3✔
1007
                addr := payment.PaymentAddr.UnwrapOr([32]byte{})
3✔
1008
                shardTracker = amp.NewShardTracker(
3✔
1009
                        payment.amp.RootShare, payment.amp.SetID, addr,
3✔
1010
                        payment.Amount,
3✔
1011
                )
3✔
1012

1013
        // Otherwise we'll use the simple tracker that will map each attempt to
1014
        // the same payment hash.
1015
        default:
3✔
1016
                shardTracker = shards.NewSimpleShardTracker(
3✔
1017
                        payment.Identifier(), nil,
3✔
1018
                )
3✔
1019
        }
1020

1021
        err = r.cfg.Control.InitPayment(payment.Identifier(), info)
3✔
1022
        if err != nil {
3✔
1023
                return nil, nil, err
×
1024
        }
×
1025

1026
        return paySession, shardTracker, nil
3✔
1027
}
1028

1029
// SendToRoute sends a payment using the provided route and fails the payment
1030
// when an error is returned from the attempt.
1031
func (r *ChannelRouter) SendToRoute(htlcHash lntypes.Hash, rt *route.Route,
1032
        firstHopCustomRecords lnwire.CustomRecords) (*paymentsdb.HTLCAttempt,
1033
        error) {
3✔
1034

3✔
1035
        return r.sendToRoute(htlcHash, rt, false, firstHopCustomRecords)
3✔
1036
}
3✔
1037

1038
// SendToRouteSkipTempErr sends a payment using the provided route and fails
1039
// the payment ONLY when a terminal error is returned from the attempt.
1040
func (r *ChannelRouter) SendToRouteSkipTempErr(htlcHash lntypes.Hash,
1041
        rt *route.Route,
1042
        firstHopCustomRecords lnwire.CustomRecords) (*paymentsdb.HTLCAttempt,
UNCOV
1043
        error) {
×
UNCOV
1044

×
UNCOV
1045
        return r.sendToRoute(htlcHash, rt, true, firstHopCustomRecords)
×
UNCOV
1046
}
×
1047

1048
// sendToRoute attempts to send a payment with the given hash through the
1049
// provided route. This function is blocking and will return the attempt
1050
// information as it is stored in the database. For a successful htlc, this
1051
// information will contain the preimage. If an error occurs after the attempt
1052
// was initiated, both return values will be non-nil. If skipTempErr is true,
1053
// the payment won't be failed unless a terminal error has occurred.
1054
func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route,
1055
        skipTempErr bool,
1056
        firstHopCustomRecords lnwire.CustomRecords) (*paymentsdb.HTLCAttempt,
1057
        error) {
3✔
1058

3✔
1059
        // Helper function to fail a payment. It makes sure the payment is only
3✔
1060
        // failed once so that the failure reason is not overwritten.
3✔
1061
        failPayment := func(paymentIdentifier lntypes.Hash,
3✔
1062
                reason paymentsdb.FailureReason) error {
6✔
1063

3✔
1064
                payment, fetchErr := r.cfg.Control.FetchPayment(
3✔
1065
                        paymentIdentifier,
3✔
1066
                )
3✔
1067
                if fetchErr != nil {
3✔
1068
                        return fetchErr
×
1069
                }
×
1070

1071
                // NOTE: We cannot rely on the payment status to be failed here
1072
                // because it can still be in-flight although the payment is
1073
                // already failed.
1074
                _, failedReason := payment.TerminalInfo()
3✔
1075
                if failedReason != nil {
6✔
1076
                        return nil
3✔
1077
                }
3✔
1078

1079
                return r.cfg.Control.FailPayment(paymentIdentifier, reason)
3✔
1080
        }
1081

1082
        log.Debugf("SendToRoute for payment %v with skipTempErr=%v",
3✔
1083
                htlcHash, skipTempErr)
3✔
1084

3✔
1085
        // Calculate amount paid to receiver.
3✔
1086
        amt := rt.ReceiverAmt()
3✔
1087

3✔
1088
        // If this is meant as an MP payment shard, we set the amount for the
3✔
1089
        // creating info to the total amount of the payment.
3✔
1090
        finalHop := rt.Hops[len(rt.Hops)-1]
3✔
1091
        mpp := finalHop.MPP
3✔
1092
        if mpp != nil {
6✔
1093
                amt = mpp.TotalMsat()
3✔
1094
        }
3✔
1095

1096
        // For non-MPP, there's no such thing as temp error as there's only one
1097
        // HTLC attempt being made. When this HTLC is failed, the payment is
1098
        // failed hence cannot be retried.
1099
        if skipTempErr && mpp == nil {
3✔
UNCOV
1100
                return nil, ErrSkipTempErr
×
UNCOV
1101
        }
×
1102

1103
        // For non-AMP payments the overall payment identifier will be the same
1104
        // hash as used for this HTLC.
1105
        paymentIdentifier := htlcHash
3✔
1106

3✔
1107
        // For AMP-payments, we'll use the setID as the unique ID for the
3✔
1108
        // overall payment.
3✔
1109
        amp := finalHop.AMP
3✔
1110
        if amp != nil {
6✔
1111
                paymentIdentifier = amp.SetID()
3✔
1112
        }
3✔
1113

1114
        // Record this payment hash with the ControlTower, ensuring it is not
1115
        // already in-flight.
1116
        info := &paymentsdb.PaymentCreationInfo{
3✔
1117
                PaymentIdentifier:     paymentIdentifier,
3✔
1118
                Value:                 amt,
3✔
1119
                CreationTime:          r.cfg.Clock.Now(),
3✔
1120
                PaymentRequest:        nil,
3✔
1121
                FirstHopCustomRecords: firstHopCustomRecords,
3✔
1122
        }
3✔
1123

3✔
1124
        err := r.cfg.Control.InitPayment(paymentIdentifier, info)
3✔
1125
        switch {
3✔
1126
        // If this is an MPP attempt and the hash is already registered with
1127
        // the database, we can go on to launch the shard.
1128
        case mpp != nil && errors.Is(err, paymentsdb.ErrPaymentInFlight):
3✔
1129
        case mpp != nil && errors.Is(err, paymentsdb.ErrPaymentExists):
×
1130

1131
        // Any other error is not tolerated.
1132
        case err != nil:
×
1133
                return nil, err
×
1134
        }
1135

1136
        log.Tracef("Dispatching SendToRoute for HTLC hash %v: %v", htlcHash,
3✔
1137
                lnutils.SpewLogClosure(rt))
3✔
1138

3✔
1139
        // Since the HTLC hashes and preimages are specified manually over the
3✔
1140
        // RPC for SendToRoute requests, we don't have to worry about creating
3✔
1141
        // a ShardTracker that can generate hashes for AMP payments. Instead, we
3✔
1142
        // create a simple tracker that can just return the hash for the single
3✔
1143
        // shard we'll now launch.
3✔
1144
        shardTracker := shards.NewSimpleShardTracker(htlcHash, nil)
3✔
1145

3✔
1146
        // Create a payment lifecycle using the given route with,
3✔
1147
        // - zero fee limit as we are not requesting routes.
3✔
1148
        // - nil payment session (since we already have a route).
3✔
1149
        // - no payment timeout.
3✔
1150
        // - no current block height.
3✔
1151
        p := newPaymentLifecycle(
3✔
1152
                r, 0, paymentIdentifier, nil, shardTracker, 0,
3✔
1153
                firstHopCustomRecords,
3✔
1154
        )
3✔
1155

3✔
1156
        // Allow the traffic shaper to add custom records to the outgoing HTLC
3✔
1157
        // and also adjust the amount if needed.
3✔
1158
        err = p.amendFirstHopData(rt)
3✔
1159
        if err != nil {
3✔
1160
                return nil, err
×
1161
        }
×
1162

1163
        // We found a route to try, create a new HTLC attempt to try.
1164
        //
1165
        // NOTE: we use zero `remainingAmt` here to simulate the same effect of
1166
        // setting the lastShard to be false, which is used by previous
1167
        // implementation.
1168
        attempt, err := p.registerAttempt(rt, 0)
3✔
1169
        if err != nil {
3✔
UNCOV
1170
                return nil, err
×
UNCOV
1171
        }
×
1172

1173
        // Once the attempt is created, send it to the htlcswitch. Notice that
1174
        // the `err` returned here has already been processed by
1175
        // `handleSwitchErr`, which means if there's a terminal failure, the
1176
        // payment has been failed.
1177
        result, err := p.sendAttempt(attempt)
3✔
1178
        if err != nil {
3✔
1179
                return nil, err
×
1180
        }
×
1181

1182
        // Since for SendToRoute we won't retry in case the shard fails, we'll
1183
        // mark the payment failed with the control tower immediately if the
1184
        // skipTempErr is false.
1185
        reason := paymentsdb.FailureReasonError
3✔
1186

3✔
1187
        // If we failed to send the HTLC, we need to further decide if we want
3✔
1188
        // to fail the payment.
3✔
1189
        if result.err != nil {
6✔
1190
                // If skipTempErr, we'll return the attempt and the temp error.
3✔
1191
                if skipTempErr {
3✔
UNCOV
1192
                        return result.attempt, result.err
×
UNCOV
1193
                }
×
1194

1195
                err := failPayment(paymentIdentifier, reason)
3✔
1196
                if err != nil {
3✔
1197
                        return nil, err
×
1198
                }
×
1199

1200
                return result.attempt, result.err
3✔
1201
        }
1202

1203
        // The attempt was successfully sent, wait for the result to be
1204
        // available.
1205
        result, err = p.collectAndHandleResult(attempt)
3✔
1206
        if err != nil {
3✔
1207
                return nil, err
×
1208
        }
×
1209

1210
        // We got a successful result.
1211
        if result.err == nil {
6✔
1212
                return result.attempt, nil
3✔
1213
        }
3✔
1214

1215
        // An error returned from collecting the result, we'll mark the payment
1216
        // as failed if we don't skip temp error.
1217
        if !skipTempErr {
6✔
1218
                err := failPayment(paymentIdentifier, reason)
3✔
1219
                if err != nil {
3✔
1220
                        return nil, err
×
1221
                }
×
1222
        }
1223

1224
        return result.attempt, result.err
3✔
1225
}
1226

1227
// sendPayment attempts to send a payment to the passed payment hash. This
1228
// function is blocking and will return either: when the payment is successful,
1229
// or all candidates routes have been attempted and resulted in a failed
1230
// payment. If the payment succeeds, then a non-nil Route will be returned
1231
// which describes the path the successful payment traversed within the network
1232
// to reach the destination. Additionally, the payment preimage will also be
1233
// returned.
1234
//
1235
// This method relies on the ControlTower's internal payment state machine to
1236
// carry out its execution. After restarts, it is safe, and assumed, that the
1237
// router will call this method for every payment still in-flight according to
1238
// the ControlTower.
1239
func (r *ChannelRouter) sendPayment(ctx context.Context,
1240
        feeLimit lnwire.MilliSatoshi, identifier lntypes.Hash,
1241
        paymentAttemptTimeout time.Duration, paySession PaymentSession,
1242
        shardTracker shards.ShardTracker,
1243
        firstHopCustomRecords lnwire.CustomRecords) ([32]byte, *route.Route,
1244
        error) {
3✔
1245

3✔
1246
        // If the user provides a timeout, we will additionally wrap the context
3✔
1247
        // in a deadline.
3✔
1248
        cancel := func() {}
6✔
1249
        if paymentAttemptTimeout > 0 {
6✔
1250
                ctx, cancel = context.WithTimeout(ctx, paymentAttemptTimeout)
3✔
1251
        }
3✔
1252

1253
        // Since resumePayment is a blocking call, we'll cancel this
1254
        // context if the payment completes before the optional
1255
        // deadline.
1256
        defer cancel()
3✔
1257

3✔
1258
        // We'll also fetch the current block height, so we can properly
3✔
1259
        // calculate the required HTLC time locks within the route.
3✔
1260
        _, currentHeight, err := r.cfg.Chain.GetBestBlock()
3✔
1261
        if err != nil {
3✔
1262
                return [32]byte{}, nil, err
×
1263
        }
×
1264

1265
        // Validate the custom records before we attempt to send the payment.
1266
        // TODO(ziggie): Move this check before registering the payment in the
1267
        // db (InitPayment).
1268
        if err := firstHopCustomRecords.Validate(); err != nil {
3✔
1269
                return [32]byte{}, nil, err
×
1270
        }
×
1271

1272
        // Now set up a paymentLifecycle struct with these params, such that we
1273
        // can resume the payment from the current state.
1274
        p := newPaymentLifecycle(
3✔
1275
                r, feeLimit, identifier, paySession, shardTracker,
3✔
1276
                currentHeight, firstHopCustomRecords,
3✔
1277
        )
3✔
1278

3✔
1279
        return p.resumePayment(ctx)
3✔
1280
}
1281

1282
// extractChannelUpdate examines the error and extracts the channel update.
1283
func (r *ChannelRouter) extractChannelUpdate(
1284
        failure lnwire.FailureMessage) *lnwire.ChannelUpdate1 {
3✔
1285

3✔
1286
        var update *lnwire.ChannelUpdate1
3✔
1287
        switch onionErr := failure.(type) {
3✔
UNCOV
1288
        case *lnwire.FailExpiryTooSoon:
×
UNCOV
1289
                update = &onionErr.Update
×
1290
        case *lnwire.FailAmountBelowMinimum:
3✔
1291
                update = &onionErr.Update
3✔
1292
        case *lnwire.FailFeeInsufficient:
3✔
1293
                update = &onionErr.Update
3✔
1294
        case *lnwire.FailIncorrectCltvExpiry:
×
1295
                update = &onionErr.Update
×
1296
        case *lnwire.FailChannelDisabled:
3✔
1297
                update = &onionErr.Update
3✔
1298
        case *lnwire.FailTemporaryChannelFailure:
3✔
1299
                update = onionErr.Update
3✔
1300
        }
1301

1302
        return update
3✔
1303
}
1304

1305
// ErrNoChannel is returned when a route cannot be built because there are no
1306
// channels that satisfy all requirements.
1307
type ErrNoChannel struct {
1308
        position int
1309
}
1310

1311
// Error returns a human-readable string describing the error.
UNCOV
1312
func (e ErrNoChannel) Error() string {
×
UNCOV
1313
        return fmt.Sprintf("no matching outgoing channel available for "+
×
UNCOV
1314
                "node index %v", e.position)
×
UNCOV
1315
}
×
1316

1317
// BuildRoute returns a fully specified route based on a list of pubkeys. If
1318
// amount is nil, the minimum routable amount is used. To force a specific
1319
// outgoing channel, use the outgoingChan parameter.
1320
func (r *ChannelRouter) BuildRoute(amt fn.Option[lnwire.MilliSatoshi],
1321
        hops []route.Vertex, outgoingChan *uint64, finalCltvDelta int32,
1322
        payAddr fn.Option[[32]byte], firstHopBlob fn.Option[[]byte]) (
1323
        *route.Route, error) {
3✔
1324

3✔
1325
        log.Tracef("BuildRoute called: hopsCount=%v, amt=%v", len(hops), amt)
3✔
1326

3✔
1327
        var outgoingChans map[uint64]struct{}
3✔
1328
        if outgoingChan != nil {
3✔
1329
                outgoingChans = map[uint64]struct{}{
×
1330
                        *outgoingChan: {},
×
1331
                }
×
1332
        }
×
1333

1334
        // We'll attempt to obtain a set of bandwidth hints that helps us select
1335
        // the best outgoing channel to use in case no outgoing channel is set.
1336
        bandwidthHints, err := newBandwidthManager(
3✔
1337
                r.cfg.RoutingGraph, r.cfg.SelfNode, r.cfg.GetLink, firstHopBlob,
3✔
1338
                r.cfg.TrafficShaper,
3✔
1339
        )
3✔
1340
        if err != nil {
3✔
1341
                return nil, err
×
1342
        }
×
1343

1344
        sourceNode := r.cfg.SelfNode
3✔
1345

3✔
1346
        // We check that each node in the route has a connection to others that
3✔
1347
        // can forward in principle.
3✔
1348
        unifiers, err := getEdgeUnifiers(
3✔
1349
                r.cfg.SelfNode, hops, outgoingChans, r.cfg.RoutingGraph,
3✔
1350
        )
3✔
1351
        if err != nil {
3✔
UNCOV
1352
                return nil, err
×
UNCOV
1353
        }
×
1354

1355
        var (
3✔
1356
                receiverAmt lnwire.MilliSatoshi
3✔
1357
                senderAmt   lnwire.MilliSatoshi
3✔
1358
                pathEdges   []*unifiedEdge
3✔
1359
        )
3✔
1360

3✔
1361
        // We determine the edges compatible with the requested amount, as well
3✔
1362
        // as the amount to send, which can be used to determine the final
3✔
1363
        // receiver amount, if a minimal amount was requested.
3✔
1364
        pathEdges, senderAmt, err = senderAmtBackwardPass(
3✔
1365
                unifiers, amt, bandwidthHints,
3✔
1366
        )
3✔
1367
        if err != nil {
3✔
UNCOV
1368
                return nil, err
×
UNCOV
1369
        }
×
1370

1371
        // For the minimal amount search, we need to do a forward pass to find a
1372
        // larger receiver amount due to possible min HTLC bumps, otherwise we
1373
        // just use the requested amount.
1374
        receiverAmt, err = fn.ElimOption(
3✔
1375
                amt,
3✔
1376
                func() fn.Result[lnwire.MilliSatoshi] {
3✔
UNCOV
1377
                        return fn.NewResult(
×
UNCOV
1378
                                receiverAmtForwardPass(senderAmt, pathEdges),
×
UNCOV
1379
                        )
×
UNCOV
1380
                },
×
1381
                fn.Ok[lnwire.MilliSatoshi],
1382
        ).Unpack()
1383
        if err != nil {
3✔
1384
                return nil, err
×
1385
        }
×
1386

1387
        // Fetch the current block height outside the routing transaction, to
1388
        // prevent the rpc call blocking the database.
1389
        _, height, err := r.cfg.Chain.GetBestBlock()
3✔
1390
        if err != nil {
3✔
1391
                return nil, err
×
1392
        }
×
1393

1394
        // Build and return the final route.
1395
        return newRoute(
3✔
1396
                sourceNode, pathEdges, uint32(height),
3✔
1397
                finalHopParams{
3✔
1398
                        amt:         receiverAmt,
3✔
1399
                        totalAmt:    receiverAmt,
3✔
1400
                        cltvDelta:   uint16(finalCltvDelta),
3✔
1401
                        records:     nil,
3✔
1402
                        paymentAddr: payAddr,
3✔
1403
                }, nil,
3✔
1404
        )
3✔
1405
}
1406

1407
// resumePayments fetches inflight payments and resumes their payment
1408
// lifecycles.
1409
func (r *ChannelRouter) resumePayments() error {
3✔
1410
        // Get all payments that are inflight.
3✔
1411
        log.Debugf("Scanning for inflight payments")
3✔
1412
        payments, err := r.cfg.Control.FetchInFlightPayments()
3✔
1413
        if err != nil {
3✔
1414
                return err
×
1415
        }
×
1416

1417
        log.Debugf("Scanning finished, found %d inflight payments",
3✔
1418
                len(payments))
3✔
1419

3✔
1420
        // Before we restart existing payments and start accepting more
3✔
1421
        // payments to be made, we clean the network result store of the
3✔
1422
        // Switch. We do this here at startup to ensure no more payments can be
3✔
1423
        // made concurrently, so we know the toKeep map will be up-to-date
3✔
1424
        // until the cleaning has finished.
3✔
1425
        toKeep := make(map[uint64]struct{})
3✔
1426
        for _, p := range payments {
6✔
1427
                for _, a := range p.HTLCs {
6✔
1428
                        toKeep[a.AttemptID] = struct{}{}
3✔
1429

3✔
1430
                        // Try to fail the attempt if the route contains a dead
3✔
1431
                        // channel.
3✔
1432
                        r.failStaleAttempt(a, p.Info.PaymentIdentifier)
3✔
1433
                }
3✔
1434
        }
1435

1436
        log.Debugf("Cleaning network result store.")
3✔
1437
        if err := r.cfg.Payer.CleanStore(toKeep); err != nil {
3✔
1438
                return err
×
1439
        }
×
1440

1441
        // launchPayment is a helper closure that handles resuming the payment.
1442
        launchPayment := func(payment *paymentsdb.MPPayment) {
6✔
1443
                defer r.wg.Done()
3✔
1444

3✔
1445
                // Get the hashes used for the outstanding HTLCs.
3✔
1446
                htlcs := make(map[uint64]lntypes.Hash)
3✔
1447
                for _, a := range payment.HTLCs {
6✔
1448
                        a := a
3✔
1449

3✔
1450
                        // We check whether the individual attempts have their
3✔
1451
                        // HTLC hash set, if not we'll fall back to the overall
3✔
1452
                        // payment hash.
3✔
1453
                        hash := payment.Info.PaymentIdentifier
3✔
1454
                        if a.Hash != nil {
6✔
1455
                                hash = *a.Hash
3✔
1456
                        }
3✔
1457

1458
                        htlcs[a.AttemptID] = hash
3✔
1459
                }
1460

1461
                payHash := payment.Info.PaymentIdentifier
3✔
1462

3✔
1463
                // Since we are not supporting creating more shards after a
3✔
1464
                // restart (only receiving the result of the shards already
3✔
1465
                // outstanding), we create a simple shard tracker that will map
3✔
1466
                // the attempt IDs to hashes used for the HTLCs. This will be
3✔
1467
                // enough also for AMP payments, since we only need the hashes
3✔
1468
                // for the individual HTLCs to regenerate the circuits, and we
3✔
1469
                // don't currently persist the root share necessary to
3✔
1470
                // re-derive them.
3✔
1471
                shardTracker := shards.NewSimpleShardTracker(payHash, htlcs)
3✔
1472

3✔
1473
                // We create a dummy, empty payment session such that we won't
3✔
1474
                // make another payment attempt when the result for the
3✔
1475
                // in-flight attempt is received.
3✔
1476
                paySession := r.cfg.SessionSource.NewPaymentSessionEmpty()
3✔
1477

3✔
1478
                // We pass in a non-timeout context, to indicate we don't need
3✔
1479
                // it to timeout. It will stop immediately after the existing
3✔
1480
                // attempt has finished anyway. We also set a zero fee limit,
3✔
1481
                // as no more routes should be tried.
3✔
1482
                noTimeout := time.Duration(0)
3✔
1483
                _, _, err := r.sendPayment(
3✔
1484
                        context.Background(), 0, payHash, noTimeout, paySession,
3✔
1485
                        shardTracker, payment.Info.FirstHopCustomRecords,
3✔
1486
                )
3✔
1487
                if err != nil {
6✔
1488
                        log.Errorf("Resuming payment %v failed: %v", payHash,
3✔
1489
                                err)
3✔
1490

3✔
1491
                        return
3✔
1492
                }
3✔
1493

1494
                log.Infof("Resumed payment %v completed", payHash)
3✔
1495
        }
1496

1497
        for _, payment := range payments {
6✔
1498
                log.Infof("Resuming payment %v", payment.Info.PaymentIdentifier)
3✔
1499

3✔
1500
                r.wg.Add(1)
3✔
1501
                go launchPayment(payment)
3✔
1502
        }
3✔
1503

1504
        return nil
3✔
1505
}
1506

1507
// failStaleAttempt will fail an HTLC attempt if it's using an unknown channel
1508
// in its route. It first consults the switch to see if there's already a
1509
// network result stored for this attempt. If not, it will check whether the
1510
// first hop of this attempt is using an active channel known to us. If
1511
// inactive, this attempt will be failed.
1512
//
1513
// NOTE: there's an unknown bug that caused the network result for a particular
1514
// attempt to NOT be saved, resulting a payment being stuck forever. More info:
1515
// - https://github.com/lightningnetwork/lnd/issues/8146
1516
// - https://github.com/lightningnetwork/lnd/pull/8174
1517
func (r *ChannelRouter) failStaleAttempt(a paymentsdb.HTLCAttempt,
1518
        payHash lntypes.Hash) {
3✔
1519

3✔
1520
        // We can only fail inflight HTLCs so we skip the settled/failed ones.
3✔
1521
        if a.Failure != nil || a.Settle != nil {
3✔
1522
                return
×
1523
        }
×
1524

1525
        // First, check if we've already had a network result for this attempt.
1526
        // If no result is found, we'll check whether the reference link is
1527
        // still known to us.
1528
        ok, err := r.cfg.Payer.HasAttemptResult(a.AttemptID)
3✔
1529
        if err != nil {
3✔
1530
                log.Errorf("Failed to fetch network result for attempt=%v",
×
1531
                        a.AttemptID)
×
1532
                return
×
1533
        }
×
1534

1535
        // There's already a network result, no need to fail it here as the
1536
        // payment lifecycle will take care of it, so we can exit early.
1537
        if ok {
3✔
1538
                log.Debugf("Already have network result for attempt=%v",
×
1539
                        a.AttemptID)
×
1540
                return
×
1541
        }
×
1542

1543
        // We now need to decide whether this attempt should be failed here.
1544
        // For very old payments, it's possible that the network results were
1545
        // never saved, causing the payments to be stuck inflight. We now check
1546
        // whether the first hop is referencing an active channel ID and, if
1547
        // not, we will fail the attempt as it has no way to be retried again.
1548
        var shouldFail bool
3✔
1549

3✔
1550
        // Validate that the attempt has hop info. If this attempt has no hop
3✔
1551
        // info it indicates an error in our db.
3✔
1552
        if len(a.Route.Hops) == 0 {
3✔
1553
                log.Errorf("Found empty hop for attempt=%v", a.AttemptID)
×
1554

×
1555
                shouldFail = true
×
1556
        } else {
3✔
1557
                // Get the short channel ID.
3✔
1558
                chanID := a.Route.Hops[0].ChannelID
3✔
1559
                scid := lnwire.NewShortChanIDFromInt(chanID)
3✔
1560

3✔
1561
                // Check whether this link is active. If so, we won't fail the
3✔
1562
                // attempt but keep waiting for its result.
3✔
1563
                _, err := r.cfg.GetLink(scid)
3✔
1564
                if err == nil {
3✔
1565
                        return
×
1566
                }
×
1567

1568
                // We should get the link not found err. If not, we will log an
1569
                // error and skip failing this attempt since an unknown error
1570
                // occurred.
1571
                if !errors.Is(err, htlcswitch.ErrChannelLinkNotFound) {
3✔
1572
                        log.Errorf("Failed to get link for attempt=%v for "+
×
1573
                                "payment=%v: %v", a.AttemptID, payHash, err)
×
1574

×
1575
                        return
×
1576
                }
×
1577

1578
                // The channel link is not active, we now check whether this
1579
                // channel is already closed. If so, we fail the HTLC attempt
1580
                // as there's no need to wait for its network result because
1581
                // there's no link. If the channel is still pending, we'll keep
1582
                // waiting for the result as we may get a contract resolution
1583
                // for this HTLC.
1584
                if _, ok := r.cfg.ClosedSCIDs[scid]; ok {
3✔
1585
                        shouldFail = true
×
1586
                }
×
1587
        }
1588

1589
        // Exit if there's no need to fail.
1590
        if !shouldFail {
6✔
1591
                return
3✔
1592
        }
3✔
1593

1594
        log.Errorf("Failing stale attempt=%v for payment=%v", a.AttemptID,
×
1595
                payHash)
×
1596

×
1597
        // Fail the attempt in db. If there's an error, there's nothing we can
×
1598
        // do here but logging it.
×
1599
        failInfo := &paymentsdb.HTLCFailInfo{
×
1600
                Reason:   paymentsdb.HTLCFailUnknown,
×
1601
                FailTime: r.cfg.Clock.Now(),
×
1602
        }
×
1603
        _, err = r.cfg.Control.FailAttempt(payHash, a.AttemptID, failInfo)
×
1604
        if err != nil {
×
1605
                log.Errorf("Fail attempt=%v got error: %v", a.AttemptID, err)
×
1606
        }
×
1607
}
1608

1609
// getEdgeUnifiers returns a list of edge unifiers for the given route.
1610
func getEdgeUnifiers(source route.Vertex, hops []route.Vertex,
1611
        outgoingChans map[uint64]struct{},
1612
        graph Graph) ([]*edgeUnifier, error) {
3✔
1613

3✔
1614
        // Allocate a list that will contain the edge unifiers for this route.
3✔
1615
        unifiers := make([]*edgeUnifier, len(hops))
3✔
1616

3✔
1617
        // Traverse hops backwards to accumulate fees in the running amounts.
3✔
1618
        for i := len(hops) - 1; i >= 0; i-- {
6✔
1619
                toNode := hops[i]
3✔
1620

3✔
1621
                var fromNode route.Vertex
3✔
1622
                if i == 0 {
6✔
1623
                        fromNode = source
3✔
1624
                } else {
6✔
1625
                        fromNode = hops[i-1]
3✔
1626
                }
3✔
1627

1628
                // Build unified policies for this hop based on the channels
1629
                // known in the graph. Inbound fees are only active if the edge
1630
                // is not the last hop.
1631
                isExitHop := i == len(hops)-1
3✔
1632
                u := newNodeEdgeUnifier(
3✔
1633
                        source, toNode, !isExitHop, outgoingChans,
3✔
1634
                )
3✔
1635

3✔
1636
                err := u.addGraphPolicies(graph)
3✔
1637
                if err != nil {
3✔
1638
                        return nil, err
×
1639
                }
×
1640

1641
                // Exit if there are no channels.
1642
                edgeUnifier, ok := u.edgeUnifiers[fromNode]
3✔
1643
                if !ok {
3✔
UNCOV
1644
                        log.Errorf("Cannot find policy for node %v", fromNode)
×
UNCOV
1645
                        return nil, ErrNoChannel{position: i}
×
UNCOV
1646
                }
×
1647

1648
                unifiers[i] = edgeUnifier
3✔
1649
        }
1650

1651
        return unifiers, nil
3✔
1652
}
1653

1654
// senderAmtBackwardPass returns a list of unified edges for the given route and
1655
// determines the amount that should be sent to fulfill min HTLC requirements.
1656
// The minimal sender amount can be searched for by using amt=None.
1657
func senderAmtBackwardPass(unifiers []*edgeUnifier,
1658
        amt fn.Option[lnwire.MilliSatoshi],
1659
        bandwidthHints bandwidthHints) ([]*unifiedEdge, lnwire.MilliSatoshi,
1660
        error) {
3✔
1661

3✔
1662
        if len(unifiers) == 0 {
3✔
UNCOV
1663
                return nil, 0, fmt.Errorf("no unifiers provided")
×
UNCOV
1664
        }
×
1665

1666
        var unifiedEdges = make([]*unifiedEdge, len(unifiers))
3✔
1667

3✔
1668
        // We traverse the route backwards and handle the last hop separately.
3✔
1669
        edgeUnifier := unifiers[len(unifiers)-1]
3✔
1670

3✔
1671
        // incomingAmt tracks the amount that is forwarded on the edges of a
3✔
1672
        // route. The last hop only forwards the amount that the receiver should
3✔
1673
        // receive, as there are no fees paid to the last node.
3✔
1674
        // For minimum amount routes, aim to deliver at least 1 msat to
3✔
1675
        // the destination. There are nodes in the wild that have a
3✔
1676
        // min_htlc channel policy of zero, which could lead to a zero
3✔
1677
        // amount payment being made.
3✔
1678
        incomingAmt := amt.UnwrapOr(1)
3✔
1679

3✔
1680
        // If using min amt, increase the amount if needed to fulfill min HTLC
3✔
1681
        // requirements.
3✔
1682
        if amt.IsNone() {
3✔
UNCOV
1683
                min := edgeUnifier.minAmt()
×
UNCOV
1684
                if min > incomingAmt {
×
UNCOV
1685
                        incomingAmt = min
×
UNCOV
1686
                }
×
1687
        }
1688

1689
        // Get an edge for the specific amount that we want to forward.
1690
        edge := edgeUnifier.getEdge(incomingAmt, bandwidthHints, 0)
3✔
1691
        if edge == nil {
3✔
UNCOV
1692
                log.Errorf("Cannot find policy with amt=%v "+
×
UNCOV
1693
                        "for hop %v", incomingAmt, len(unifiers)-1)
×
UNCOV
1694

×
UNCOV
1695
                return nil, 0, ErrNoChannel{position: len(unifiers) - 1}
×
UNCOV
1696
        }
×
1697

1698
        unifiedEdges[len(unifiers)-1] = edge
3✔
1699

3✔
1700
        // Handle the rest of the route except the last hop.
3✔
1701
        for i := len(unifiers) - 2; i >= 0; i-- {
6✔
1702
                edgeUnifier = unifiers[i]
3✔
1703

3✔
1704
                // If using min amt, increase the amount if needed to fulfill
3✔
1705
                // min HTLC requirements.
3✔
1706
                if amt.IsNone() {
3✔
UNCOV
1707
                        min := edgeUnifier.minAmt()
×
UNCOV
1708
                        if min > incomingAmt {
×
1709
                                incomingAmt = min
×
1710
                        }
×
1711
                }
1712

1713
                // A --current hop-- B --next hop: incomingAmt-- C
1714
                // The outbound fee paid to the current end node B is based on
1715
                // the amount that the next hop forwards and B's policy for that
1716
                // hop.
1717
                outboundFee := unifiedEdges[i+1].policy.ComputeFee(
3✔
1718
                        incomingAmt,
3✔
1719
                )
3✔
1720

3✔
1721
                netAmount := incomingAmt + outboundFee
3✔
1722

3✔
1723
                // We need to select an edge that can forward the requested
3✔
1724
                // amount.
3✔
1725
                edge = edgeUnifier.getEdge(
3✔
1726
                        netAmount, bandwidthHints, outboundFee,
3✔
1727
                )
3✔
1728
                if edge == nil {
3✔
UNCOV
1729
                        return nil, 0, ErrNoChannel{position: i}
×
UNCOV
1730
                }
×
1731

1732
                // The fee paid to B depends on the current hop's inbound fee
1733
                // policy and on the outbound fee for the next hop as any
1734
                // inbound fee discount is capped by the outbound fee such that
1735
                // the total fee for B can't become negative.
1736
                inboundFee := calcCappedInboundFee(edge, netAmount, outboundFee)
3✔
1737

3✔
1738
                fee := lnwire.MilliSatoshi(int64(outboundFee) + inboundFee)
3✔
1739

3✔
1740
                log.Tracef("Select channel %v at position %v",
3✔
1741
                        edge.policy.ChannelID, i)
3✔
1742

3✔
1743
                // Finally, we update the amount that needs to flow into node B
3✔
1744
                // from A, which is the next hop's forwarding amount plus the
3✔
1745
                // fee for B: A --current hop: incomingAmt-- B --next hop-- C
3✔
1746
                incomingAmt += fee
3✔
1747

3✔
1748
                unifiedEdges[i] = edge
3✔
1749
        }
1750

1751
        return unifiedEdges, incomingAmt, nil
3✔
1752
}
1753

1754
// receiverAmtForwardPass returns the amount that a receiver will receive after
1755
// deducting all fees from the sender amount.
1756
func receiverAmtForwardPass(runningAmt lnwire.MilliSatoshi,
UNCOV
1757
        unifiedEdges []*unifiedEdge) (lnwire.MilliSatoshi, error) {
×
UNCOV
1758

×
UNCOV
1759
        if len(unifiedEdges) == 0 {
×
UNCOV
1760
                return 0, fmt.Errorf("no edges to forward through")
×
UNCOV
1761
        }
×
1762

UNCOV
1763
        inEdge := unifiedEdges[0]
×
UNCOV
1764
        if !inEdge.amtInRange(runningAmt) {
×
UNCOV
1765
                log.Errorf("Amount %v not in range for hop index %v",
×
UNCOV
1766
                        runningAmt, 0)
×
UNCOV
1767

×
UNCOV
1768
                return 0, ErrNoChannel{position: 0}
×
UNCOV
1769
        }
×
1770

1771
        // Now that we arrived at the start of the route and found out the route
1772
        // total amount, we make a forward pass. Because the amount may have
1773
        // been increased in the backward pass, fees need to be recalculated and
1774
        // amount ranges re-checked.
UNCOV
1775
        for i := 1; i < len(unifiedEdges); i++ {
×
UNCOV
1776
                inEdge := unifiedEdges[i-1]
×
UNCOV
1777
                outEdge := unifiedEdges[i]
×
UNCOV
1778

×
UNCOV
1779
                // Decrease the amount to send while going forward.
×
UNCOV
1780
                runningAmt = outgoingFromIncoming(runningAmt, inEdge, outEdge)
×
UNCOV
1781

×
UNCOV
1782
                if !outEdge.amtInRange(runningAmt) {
×
1783
                        log.Errorf("Amount %v not in range for hop index %v",
×
1784
                                runningAmt, i)
×
1785

×
1786
                        return 0, ErrNoChannel{position: i}
×
1787
                }
×
1788
        }
1789

UNCOV
1790
        return runningAmt, nil
×
1791
}
1792

1793
// incomingFromOutgoing computes the incoming amount based on the outgoing
1794
// amount by adding fees to the outgoing amount, replicating the path finding
1795
// and routing process, see also CheckHtlcForward.
1796
func incomingFromOutgoing(outgoingAmt lnwire.MilliSatoshi,
UNCOV
1797
        incoming, outgoing *unifiedEdge) lnwire.MilliSatoshi {
×
UNCOV
1798

×
UNCOV
1799
        outgoingFee := outgoing.policy.ComputeFee(outgoingAmt)
×
UNCOV
1800

×
UNCOV
1801
        // Net amount is the amount the inbound fees are calculated with.
×
UNCOV
1802
        netAmount := outgoingAmt + outgoingFee
×
UNCOV
1803

×
UNCOV
1804
        inboundFee := incoming.inboundFees.CalcFee(netAmount)
×
UNCOV
1805

×
UNCOV
1806
        // The inbound fee is not allowed to reduce the incoming amount below
×
UNCOV
1807
        // the outgoing amount.
×
UNCOV
1808
        if int64(outgoingFee)+inboundFee < 0 {
×
UNCOV
1809
                return outgoingAmt
×
UNCOV
1810
        }
×
1811

UNCOV
1812
        return netAmount + lnwire.MilliSatoshi(inboundFee)
×
1813
}
1814

1815
// outgoingFromIncoming computes the outgoing amount based on the incoming
1816
// amount by subtracting fees from the incoming amount. Note that this is not
1817
// exactly the inverse of incomingFromOutgoing, because of some rounding.
1818
func outgoingFromIncoming(incomingAmt lnwire.MilliSatoshi,
UNCOV
1819
        incoming, outgoing *unifiedEdge) lnwire.MilliSatoshi {
×
UNCOV
1820

×
UNCOV
1821
        // Convert all quantities to big.Int to be able to hande negative
×
UNCOV
1822
        // values. The formulas to compute the outgoing amount involve terms
×
UNCOV
1823
        // with PPM*PPM*A, which can easily overflow an int64.
×
UNCOV
1824
        A := big.NewInt(int64(incomingAmt))
×
UNCOV
1825
        Ro := big.NewInt(int64(outgoing.policy.FeeProportionalMillionths))
×
UNCOV
1826
        Bo := big.NewInt(int64(outgoing.policy.FeeBaseMSat))
×
UNCOV
1827
        Ri := big.NewInt(int64(incoming.inboundFees.Rate))
×
UNCOV
1828
        Bi := big.NewInt(int64(incoming.inboundFees.Base))
×
UNCOV
1829
        PPM := big.NewInt(1_000_000)
×
UNCOV
1830

×
UNCOV
1831
        // The following discussion was contributed by user feelancer21, see
×
UNCOV
1832
        //nolint:ll
×
UNCOV
1833
        // https://github.com/feelancer21/lnd/commit/f6f05fa930985aac0d27c3f6681aada1b599162a.
×
UNCOV
1834

×
UNCOV
1835
        // The incoming amount Ai based on the outgoing amount Ao is computed by
×
UNCOV
1836
        // Ai = max(Ai(Ao), Ao), which caps the incoming amount such that the
×
UNCOV
1837
        // total node fee (Ai - Ao) is non-negative. This is commonly enforced
×
UNCOV
1838
        // by routing nodes.
×
UNCOV
1839

×
UNCOV
1840
        // The function Ai(Ao) is given by:
×
UNCOV
1841
        // Ai(Ao) = (Ao + Bo + Ro/PPM) + (Bi + (Ao + Ro/PPM + Bo)*Ri/PPM), where
×
UNCOV
1842
        // the first term is the net amount (the outgoing amount plus the
×
UNCOV
1843
        // outbound fee), and the second is the inbound fee computed based on
×
UNCOV
1844
        // the net amount.
×
UNCOV
1845

×
UNCOV
1846
        // Ai(Ao) can potentially become more negative in absolute value than
×
UNCOV
1847
        // Ao, which is why the above mentioned capping is needed. We can
×
UNCOV
1848
        // abbreviate Ai(Ao) with Ai(Ao) = m*Ao + n, where m and n are:
×
UNCOV
1849
        // m := (1 + Ro/PPM) * (1 + Ri/PPM)
×
UNCOV
1850
        // n := Bi + Bo*(1 + Ri/PPM)
×
UNCOV
1851

×
UNCOV
1852
        // If we know that m > 0, this is equivalent of Ri/PPM > -1, because Ri
×
UNCOV
1853
        // is the only factor that can become negative. A value or Ri/PPM = -1,
×
UNCOV
1854
        // means that the routing node is willing to give up on 100% of the
×
UNCOV
1855
        // net amount (based on the fee rate), which is likely to not happen in
×
UNCOV
1856
        // practice. This condition will be important for a later trick.
×
UNCOV
1857

×
UNCOV
1858
        // If we want to compute the incoming amount based on the outgoing
×
UNCOV
1859
        // amount, which is the reverse problem, we need to solve Ai =
×
UNCOV
1860
        // max(Ai(Ao), Ao) for Ao(Ai). Given an incoming amount A,
×
UNCOV
1861
        // we look for an Ao such that A = max(Ai(Ao), Ao).
×
UNCOV
1862

×
UNCOV
1863
        // The max function separates this into two cases. The case to take is
×
UNCOV
1864
        // not clear yet, because we don't know Ao, but later we see a trick
×
UNCOV
1865
        // how to determine which case is the one to take.
×
UNCOV
1866

×
UNCOV
1867
        // first case: Ai(Ao) <= Ao:
×
UNCOV
1868
        // Therefore, A = max(Ai(Ao), Ao) = Ao, we find Ao = A.
×
UNCOV
1869
        // This also leads to Ai(A) <= A by substitution into the condition.
×
UNCOV
1870

×
UNCOV
1871
        // second case: Ai(Ao) > Ao:
×
UNCOV
1872
        // Therefore, A = max(Ai(Ao), Ao) = Ai(Ao) = m*Ao + n. Solving for Ao
×
UNCOV
1873
        // gives Ao = (A - n)/m.
×
UNCOV
1874
        //
×
UNCOV
1875
        // We know
×
UNCOV
1876
        // Ai(Ao) > Ao  <=>  A = Ai(Ao) > Ao = (A - n)/m,
×
UNCOV
1877
        // so A > (A - n)/m.
×
UNCOV
1878
        //
×
UNCOV
1879
        // **Assuming m > 0**, by multiplying with m, we can transform this to
×
UNCOV
1880
        // A * m + n > A.
×
UNCOV
1881
        //
×
UNCOV
1882
        // We know Ai(A) = A*m + n, therefore Ai(A) > A.
×
UNCOV
1883
        //
×
UNCOV
1884
        // This means that if we apply the incoming amount calculation to the
×
UNCOV
1885
        // **incoming** amount, and this condition holds, then we know that we
×
UNCOV
1886
        // deal with the second case, being able to compute the outgoing amount
×
UNCOV
1887
        // based off the formula Ao = (A - n)/m, otherwise we will just return
×
UNCOV
1888
        // the incoming amount.
×
UNCOV
1889

×
UNCOV
1890
        // In case the inbound fee rate is less than -1 (-100%), we fail to
×
UNCOV
1891
        // compute the outbound amount and return the incoming amount. This also
×
UNCOV
1892
        // protects against zero division later.
×
UNCOV
1893

×
UNCOV
1894
        // We compute m in terms of big.Int to be safe from overflows and to be
×
UNCOV
1895
        // consistent with later calculations.
×
UNCOV
1896
        // m := (PPM*PPM + Ri*PPM + Ro*PPM + Ro*Ri)/(PPM*PPM)
×
UNCOV
1897

×
UNCOV
1898
        // Compute terms in (PPM*PPM + Ri*PPM + Ro*PPM + Ro*Ri).
×
UNCOV
1899
        m1 := new(big.Int).Mul(PPM, PPM)
×
UNCOV
1900
        m2 := new(big.Int).Mul(Ri, PPM)
×
UNCOV
1901
        m3 := new(big.Int).Mul(Ro, PPM)
×
UNCOV
1902
        m4 := new(big.Int).Mul(Ro, Ri)
×
UNCOV
1903

×
UNCOV
1904
        // Add up terms m1..m4.
×
UNCOV
1905
        m := big.NewInt(0)
×
UNCOV
1906
        m.Add(m, m1)
×
UNCOV
1907
        m.Add(m, m2)
×
UNCOV
1908
        m.Add(m, m3)
×
UNCOV
1909
        m.Add(m, m4)
×
UNCOV
1910

×
UNCOV
1911
        // Since we compare to 0, we can multiply by PPM*PPM to avoid the
×
UNCOV
1912
        // division.
×
UNCOV
1913
        if m.Int64() <= 0 {
×
UNCOV
1914
                return incomingAmt
×
UNCOV
1915
        }
×
1916

1917
        // In order to decide if the total fee is negative, we apply the fee
1918
        // to the *incoming* amount as mentioned before.
1919

1920
        // We compute the test amount in terms of big.Int to be safe from
1921
        // overflows and to be consistent later calculations.
1922
        // testAmtF := A*m + n =
1923
        // = A + Bo + Bi + (PPM*(A*Ri + A*Ro + Ro*Ri) + A*Ri*Ro)/(PPM*PPM)
1924

1925
        // Compute terms in (A*Ri + A*Ro + Ro*Ri).
UNCOV
1926
        t1 := new(big.Int).Mul(A, Ri)
×
UNCOV
1927
        t2 := new(big.Int).Mul(A, Ro)
×
UNCOV
1928
        t3 := new(big.Int).Mul(Ro, Ri)
×
UNCOV
1929

×
UNCOV
1930
        // Sum up terms t1-t3.
×
UNCOV
1931
        t4 := big.NewInt(0)
×
UNCOV
1932
        t4.Add(t4, t1)
×
UNCOV
1933
        t4.Add(t4, t2)
×
UNCOV
1934
        t4.Add(t4, t3)
×
UNCOV
1935

×
UNCOV
1936
        // Compute PPM*(A*Ri + A*Ro + Ro*Ri).
×
UNCOV
1937
        t6 := new(big.Int).Mul(PPM, t4)
×
UNCOV
1938

×
UNCOV
1939
        // Compute A*Ri*Ro.
×
UNCOV
1940
        t7 := new(big.Int).Mul(A, Ri)
×
UNCOV
1941
        t7.Mul(t7, Ro)
×
UNCOV
1942

×
UNCOV
1943
        // Compute (PPM*(A*Ri + A*Ro + Ro*Ri) + A*Ri*Ro)/(PPM*PPM).
×
UNCOV
1944
        num := new(big.Int).Add(t6, t7)
×
UNCOV
1945
        denom := new(big.Int).Mul(PPM, PPM)
×
UNCOV
1946
        fraction := new(big.Int).Div(num, denom)
×
UNCOV
1947

×
UNCOV
1948
        // Sum up all terms.
×
UNCOV
1949
        testAmt := big.NewInt(0)
×
UNCOV
1950
        testAmt.Add(testAmt, A)
×
UNCOV
1951
        testAmt.Add(testAmt, Bo)
×
UNCOV
1952
        testAmt.Add(testAmt, Bi)
×
UNCOV
1953
        testAmt.Add(testAmt, fraction)
×
UNCOV
1954

×
UNCOV
1955
        // Protect against negative values for the integer cast to Msat.
×
UNCOV
1956
        if testAmt.Int64() < 0 {
×
UNCOV
1957
                return incomingAmt
×
UNCOV
1958
        }
×
1959

1960
        // If the second case holds, we have to compute the outgoing amount.
UNCOV
1961
        if lnwire.MilliSatoshi(testAmt.Int64()) > incomingAmt {
×
UNCOV
1962
                // Compute the outgoing amount by integer ceiling division. This
×
UNCOV
1963
                // precision is needed because PPM*PPM*A and other terms can
×
UNCOV
1964
                // easily overflow with int64, which happens with about
×
UNCOV
1965
                // A = 10_000 sat.
×
UNCOV
1966

×
UNCOV
1967
                // out := (A - n) / m = numerator / denominator
×
UNCOV
1968
                // numerator := PPM*(PPM*(A - Bo - Bi) - Bo*Ri)
×
UNCOV
1969
                // denominator := PPM*(PPM + Ri + Ro) + Ri*Ro
×
UNCOV
1970

×
UNCOV
1971
                var numerator big.Int
×
UNCOV
1972

×
UNCOV
1973
                // Compute (A - Bo - Bi).
×
UNCOV
1974
                temp1 := new(big.Int).Sub(A, Bo)
×
UNCOV
1975
                temp2 := new(big.Int).Sub(temp1, Bi)
×
UNCOV
1976

×
UNCOV
1977
                // Compute terms in (PPM*(A - Bo - Bi) - Bo*Ri).
×
UNCOV
1978
                temp3 := new(big.Int).Mul(PPM, temp2)
×
UNCOV
1979
                temp4 := new(big.Int).Mul(Bo, Ri)
×
UNCOV
1980

×
UNCOV
1981
                // Compute PPM*(PPM*(A - Bo - Bi) - Bo*Ri)
×
UNCOV
1982
                temp5 := new(big.Int).Sub(temp3, temp4)
×
UNCOV
1983
                numerator.Mul(PPM, temp5)
×
UNCOV
1984

×
UNCOV
1985
                var denominator big.Int
×
UNCOV
1986

×
UNCOV
1987
                // Compute (PPM + Ri + Ro).
×
UNCOV
1988
                temp1 = new(big.Int).Add(PPM, Ri)
×
UNCOV
1989
                temp2 = new(big.Int).Add(temp1, Ro)
×
UNCOV
1990

×
UNCOV
1991
                // Compute PPM*(PPM + Ri + Ro) + Ri*Ro.
×
UNCOV
1992
                temp3 = new(big.Int).Mul(PPM, temp2)
×
UNCOV
1993
                temp4 = new(big.Int).Mul(Ri, Ro)
×
UNCOV
1994
                denominator.Add(temp3, temp4)
×
UNCOV
1995

×
UNCOV
1996
                // We overestimate the outgoing amount by taking the ceiling of
×
UNCOV
1997
                // the division. This means that we may round slightly up by a
×
UNCOV
1998
                // MilliSatoshi, but this helps to ensure that we don't hit min
×
UNCOV
1999
                // HTLC constrains in the context of finding the minimum amount
×
UNCOV
2000
                // of a route.
×
UNCOV
2001
                // ceil = floor((numerator + denominator - 1) / denominator)
×
UNCOV
2002
                ceil := new(big.Int).Add(&numerator, &denominator)
×
UNCOV
2003
                ceil.Sub(ceil, big.NewInt(1))
×
UNCOV
2004
                ceil.Div(ceil, &denominator)
×
UNCOV
2005

×
UNCOV
2006
                return lnwire.MilliSatoshi(ceil.Int64())
×
UNCOV
2007
        }
×
2008

2009
        // Otherwise the inbound fee made up for the outbound fee, which is why
2010
        // we just return the incoming amount.
UNCOV
2011
        return incomingAmt
×
2012
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc