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

lightningnetwork / lnd / 12986279612

27 Jan 2025 09:51AM UTC coverage: 57.652% (-1.1%) from 58.788%
12986279612

Pull #9447

github

yyforyongyu
sweep: rename methods for clarity

We now rename "third party" to "unknown" as the inputs can be spent via
an older sweeping tx, a third party (anchor), or a remote party (pin).
In fee bumper we don't have the info to distinguish the above cases, and
leave them to be further handled by the sweeper as it has more context.
Pull Request #9447: sweep: start tracking input spending status in the fee bumper

83 of 87 new or added lines in 2 files covered. (95.4%)

19578 existing lines in 256 files now uncovered.

103448 of 179434 relevant lines covered (57.65%)

24884.58 hits per line

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

72.92
/routing/router.go
1
package routing
2

3
import (
4
        "bytes"
5
        "context"
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/davecgh/go-spew/spew"
17
        "github.com/go-errors/errors"
18
        sphinx "github.com/lightningnetwork/lightning-onion"
19
        "github.com/lightningnetwork/lnd/amp"
20
        "github.com/lightningnetwork/lnd/channeldb"
21
        "github.com/lightningnetwork/lnd/clock"
22
        "github.com/lightningnetwork/lnd/fn/v2"
23
        "github.com/lightningnetwork/lnd/graph/db/models"
24
        "github.com/lightningnetwork/lnd/htlcswitch"
25
        "github.com/lightningnetwork/lnd/lntypes"
26
        "github.com/lightningnetwork/lnd/lnutils"
27
        "github.com/lightningnetwork/lnd/lnwallet"
28
        "github.com/lightningnetwork/lnd/lnwire"
29
        "github.com/lightningnetwork/lnd/record"
30
        "github.com/lightningnetwork/lnd/routing/route"
31
        "github.com/lightningnetwork/lnd/routing/shards"
32
        "github.com/lightningnetwork/lnd/tlv"
33
        "github.com/lightningnetwork/lnd/zpay32"
34
)
35

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

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

63
        // MaxCLTVDelta is the maximum CLTV value accepted by LND for all
64
        // timelock deltas.
65
        MaxCLTVDelta = math.MaxUint16
66
)
67

68
var (
69
        // ErrRouterShuttingDown is returned if the router is in the process of
70
        // shutting down.
71
        ErrRouterShuttingDown = fmt.Errorf("router shutting down")
72

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

218
        // TimeLockDelta is the required HTLC timelock delta to be used
219
        // when forwarding payments.
220
        TimeLockDelta uint32
221

222
        // MaxHTLC is the maximum HTLC size including fees we are allowed to
223
        // forward over this channel.
224
        MaxHTLC lnwire.MilliSatoshi
225

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

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

239
        // RoutingGraph is a graph source that will be used for pathfinding.
240
        RoutingGraph Graph
241

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

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

252
        // Control keeps track of the status of ongoing payments, ensuring we
253
        // can properly resume them across restarts.
254
        Control ControlTower
255

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

265
        // SessionSource defines a source for the router to retrieve new payment
266
        // sessions.
267
        SessionSource PaymentSessionSource
268

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

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

283
        // PathFindingConfig defines global path finding parameters.
284
        PathFindingConfig PathFindingConfig
285

286
        // Clock is mockable time provider.
287
        Clock clock.Clock
288

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

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

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

303
// EdgeLocator is a struct used to identify a specific edge.
304
type EdgeLocator struct {
305
        // ChannelID is the channel of this edge.
306
        ChannelID uint64
307

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

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

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

330
        // cfg is a copy of the configuration struct that the ChannelRouter was
331
        // initialized with.
332
        cfg *Config
333

334
        quit chan struct{}
335
        wg   sync.WaitGroup
336
}
337

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

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

358
        log.Info("Channel Router starting")
17✔
359

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

366
        return nil
17✔
367
}
368

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

377
        log.Info("Channel Router shutting down...")
17✔
378
        defer log.Debug("Channel Router shutdown complete")
17✔
379

17✔
380
        close(r.quit)
17✔
381
        r.wg.Wait()
17✔
382

17✔
383
        return nil
17✔
384
}
385

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

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

398
        // Amount is the Amount in millisatoshis to be delivered to the target
399
        // node.
400
        Amount lnwire.MilliSatoshi
401

402
        // TimePreference expresses the caller's time preference for
403
        // pathfinding.
404
        TimePreference float64
405

406
        // Restrictions provides a set of additional Restrictions that the
407
        // route must adhere to.
408
        Restrictions *RestrictParams
409

410
        // CustomRecords is a set of custom tlv records to include for the
411
        // final hop.
412
        CustomRecords record.CustomSet
413

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

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

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

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

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

12✔
444
        var (
12✔
445
                // Assume that we're starting off with a regular payment.
12✔
446
                requestHints  = routeHints
12✔
447
                requestExpiry = finalExpiry
12✔
448
                err           error
12✔
449
        )
12✔
450

12✔
451
        if blindedPathSet != nil {
18✔
452
                if blindedPathSet.IsIntroNode(source) {
7✔
453
                        return nil, ErrSelfIntro
1✔
454
                }
1✔
455

456
                // Check that the values for a clear path have not been set,
457
                // as this is an ambiguous signal from the caller.
458
                if routeHints != nil {
6✔
459
                        return nil, ErrHintsAndBlinded
1✔
460
                }
1✔
461

462
                if finalExpiry != 0 {
5✔
463
                        return nil, ErrExpiryAndBlinded
1✔
464
                }
1✔
465

466
                requestExpiry = blindedPathSet.FinalCLTVDelta()
3✔
467

3✔
468
                requestHints, err = blindedPathSet.ToRouteHints()
3✔
469
                if err != nil {
3✔
470
                        return nil, err
×
471
                }
×
472
        }
473

474
        requestTarget, err := getTargetNode(target, blindedPathSet)
9✔
475
        if err != nil {
10✔
476
                return nil, err
1✔
477
        }
1✔
478

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

492
func getTargetNode(target *route.Vertex,
493
        blindedPathSet *BlindedPaymentPathSet) (route.Vertex, error) {
9✔
494

9✔
495
        var (
9✔
496
                blinded   = blindedPathSet != nil
9✔
497
                targetSet = target != nil
9✔
498
        )
9✔
499

9✔
500
        switch {
9✔
501
        case blinded && targetSet:
1✔
502
                return route.Vertex{}, ErrTargetAndBlinded
1✔
503

504
        case blinded:
2✔
505
                return route.NewVertex(blindedPathSet.TargetPubKey()), nil
2✔
506

507
        case targetSet:
6✔
508
                return *target, nil
6✔
509

510
        default:
×
511
                return route.Vertex{}, ErrNoTarget
×
512
        }
513
}
514

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

5✔
521
        log.Debugf("Searching for path to %v, sending %v", req.Target,
5✔
522
                req.Amount)
5✔
523

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

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

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

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

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

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

579
        go log.Tracef("Obtained path to send %v to %x: %v",
5✔
580
                req.Amount, req.Target, lnutils.SpewLogClosure(route))
5✔
581

5✔
582
        return route, probability, nil
5✔
583
}
584

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

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

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

609
        // MaxNumPaths is the maximum number of blinded paths to select.
610
        MaxNumPaths uint8
611

612
        // NodeOmissionSet is a set of nodes that should not be used within any
613
        // of the blinded paths that we generate.
614
        NodeOmissionSet fn.Set[route.Vertex]
615
}
616

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

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

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

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

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

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

34✔
671
                        totalRouteProbability *= probability
34✔
672

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

34✔
678
                        prevNode = path[j].vertex
34✔
679
                }
34✔
680

681
                // Don't bother adding a route if its success probability less
682
                // minimum that can be assigned to any single pair.
683
                if totalRouteProbability <= DefaultMinRouteProbability {
20✔
684
                        continue
2✔
685
                }
686

687
                routes = append(routes, &routeWithProbability{
16✔
688
                        route: &route.Route{
16✔
689
                                SourcePubKey: introNode,
16✔
690
                                Hops:         hops,
16✔
691
                        },
16✔
692
                        probability: totalRouteProbability,
16✔
693
                })
16✔
694
        }
695

696
        // Sort the routes based on probability.
697
        sort.Slice(routes, func(i, j int) bool {
18✔
698
                return routes[i].probability > routes[j].probability
11✔
699
        })
11✔
700

701
        // Now just choose the best paths up until the maximum number of allowed
702
        // paths.
703
        bestRoutes := make([]*route.Route, 0, restrictions.MaxNumPaths)
7✔
704
        for _, route := range routes {
22✔
705
                if len(bestRoutes) >= int(restrictions.MaxNumPaths) {
16✔
706
                        break
1✔
707
                }
708

709
                bestRoutes = append(bestRoutes, route.route)
14✔
710
        }
711

712
        return bestRoutes, nil
7✔
713
}
714

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

725
// generateSphinxPacket generates then encodes a sphinx packet which encodes
726
// the onion route specified by the passed layer 3 route. The blob returned
727
// from this function can immediately be included within an HTLC add packet to
728
// be sent to the first hop within the route.
729
func generateSphinxPacket(rt *route.Route, paymentHash []byte,
730
        sessionKey *btcec.PrivateKey) ([]byte, *sphinx.Circuit, error) {
70✔
731

70✔
732
        // Now that we know we have an actual route, we'll map the route into a
70✔
733
        // sphinx payment path which includes per-hop payloads for each hop
70✔
734
        // that give each node within the route the necessary information
70✔
735
        // (fees, CLTV value, etc.) to properly forward the payment.
70✔
736
        sphinxPath, err := rt.ToSphinxPath()
70✔
737
        if err != nil {
72✔
738
                return nil, nil, err
2✔
739
        }
2✔
740

741
        log.Tracef("Constructed per-hop payloads for payment_hash=%x: %v",
68✔
742
                paymentHash, lnutils.NewLogClosure(func() string {
68✔
743
                        path := make(
×
744
                                []sphinx.OnionHop, sphinxPath.TrueRouteLength(),
×
745
                        )
×
746
                        for i := range path {
×
747
                                hopCopy := sphinxPath[i]
×
748
                                path[i] = hopCopy
×
749
                        }
×
750

751
                        return spew.Sdump(path)
×
752
                }),
753
        )
754

755
        // Next generate the onion routing packet which allows us to perform
756
        // privacy preserving source routing across the network.
757
        sphinxPacket, err := sphinx.NewOnionPacket(
68✔
758
                sphinxPath, sessionKey, paymentHash,
68✔
759
                sphinx.DeterministicPacketFiller,
68✔
760
        )
68✔
761
        if err != nil {
68✔
762
                return nil, nil, err
×
763
        }
×
764

765
        // Finally, encode Sphinx packet using its wire representation to be
766
        // included within the HTLC add packet.
767
        var onionBlob bytes.Buffer
68✔
768
        if err := sphinxPacket.Encode(&onionBlob); err != nil {
68✔
769
                return nil, nil, err
×
770
        }
×
771

772
        log.Tracef("Generated sphinx packet: %v",
68✔
773
                lnutils.NewLogClosure(func() string {
68✔
774
                        // We make a copy of the ephemeral key and unset the
×
775
                        // internal curve here in order to keep the logs from
×
776
                        // getting noisy.
×
777
                        key := *sphinxPacket.EphemeralKey
×
778
                        packetCopy := *sphinxPacket
×
779
                        packetCopy.EphemeralKey = &key
×
780
                        return spew.Sdump(packetCopy)
×
781
                }),
×
782
        )
783

784
        return onionBlob.Bytes(), &sphinx.Circuit{
68✔
785
                SessionKey:  sessionKey,
68✔
786
                PaymentPath: sphinxPath.NodeKeys(),
68✔
787
        }, nil
68✔
788
}
789

790
// LightningPayment describes a payment to be sent through the network to the
791
// final destination.
792
type LightningPayment struct {
793
        // Target is the node in which the payment should be routed towards.
794
        Target route.Vertex
795

796
        // Amount is the value of the payment to send through the network in
797
        // milli-satoshis.
798
        Amount lnwire.MilliSatoshi
799

800
        // FeeLimit is the maximum fee in millisatoshis that the payment should
801
        // accept when sending it through the network. The payment will fail
802
        // if there isn't a route with lower fees than this limit.
803
        FeeLimit lnwire.MilliSatoshi
804

805
        // CltvLimit is the maximum time lock that is allowed for attempts to
806
        // complete this payment.
807
        CltvLimit uint32
808

809
        // paymentHash is the r-hash value to use within the HTLC extended to
810
        // the first hop. This won't be set for AMP payments.
811
        paymentHash *lntypes.Hash
812

813
        // amp is an optional field that is set if and only if this is am AMP
814
        // payment.
815
        amp *AMPOptions
816

817
        // FinalCLTVDelta is the CTLV expiry delta to use for the _final_ hop
818
        // in the route. This means that the final hop will have a CLTV delta
819
        // of at least: currentHeight + FinalCLTVDelta.
820
        FinalCLTVDelta uint16
821

822
        // PayAttemptTimeout is a timeout value that we'll use to determine
823
        // when we should should abandon the payment attempt after consecutive
824
        // payment failure. This prevents us from attempting to send a payment
825
        // indefinitely. A zero value means the payment will never time out.
826
        //
827
        // TODO(halseth): make wallclock time to allow resume after startup.
828
        PayAttemptTimeout time.Duration
829

830
        // RouteHints represents the different routing hints that can be used to
831
        // assist a payment in reaching its destination successfully. These
832
        // hints will act as intermediate hops along the route.
833
        //
834
        // NOTE: This is optional unless required by the payment. When providing
835
        // multiple routes, ensure the hop hints within each route are chained
836
        // together and sorted in forward order in order to reach the
837
        // destination successfully. This is mutually exclusive to the
838
        // BlindedPayment field.
839
        RouteHints [][]zpay32.HopHint
840

841
        // BlindedPathSet holds the information about a set of blinded paths to
842
        // the payment recipient. This is mutually exclusive to the RouteHints
843
        // field.
844
        BlindedPathSet *BlindedPaymentPathSet
845

846
        // OutgoingChannelIDs is the list of channels that are allowed for the
847
        // first hop. If nil, any channel may be used.
848
        OutgoingChannelIDs []uint64
849

850
        // LastHop is the pubkey of the last node before the final destination
851
        // is reached. If nil, any node may be used.
852
        LastHop *route.Vertex
853

854
        // DestFeatures specifies the set of features we assume the final node
855
        // has for pathfinding. Typically, these will be taken directly from an
856
        // invoice, but they can also be manually supplied or assumed by the
857
        // sender. If a nil feature vector is provided, the router will try to
858
        // fall back to the graph in order to load a feature vector for a node
859
        // in the public graph.
860
        DestFeatures *lnwire.FeatureVector
861

862
        // PaymentAddr is the payment address specified by the receiver. This
863
        // field should be a random 32-byte nonce presented in the receiver's
864
        // invoice to prevent probing of the destination.
865
        PaymentAddr fn.Option[[32]byte]
866

867
        // PaymentRequest is an optional payment request that this payment is
868
        // attempting to complete.
869
        PaymentRequest []byte
870

871
        // DestCustomRecords are TLV records that are to be sent to the final
872
        // hop in the new onion payload format. If the destination does not
873
        // understand this new onion payload format, then the payment will
874
        // fail.
875
        DestCustomRecords record.CustomSet
876

877
        // FirstHopCustomRecords are the TLV records that are to be sent to the
878
        // first hop of this payment. These records will be transmitted via the
879
        // wire message and therefore do not affect the onion payload size.
880
        FirstHopCustomRecords lnwire.CustomRecords
881

882
        // MaxParts is the maximum number of partial payments that may be used
883
        // to complete the full amount.
884
        MaxParts uint32
885

886
        // MaxShardAmt is the largest shard that we'll attempt to split using.
887
        // If this field is set, and we need to split, rather than attempting
888
        // half of the original payment amount, we'll use this value if half
889
        // the payment amount is greater than it.
890
        //
891
        // NOTE: This field is _optional_.
892
        MaxShardAmt *lnwire.MilliSatoshi
893

894
        // TimePref is the time preference for this payment. Set to -1 to
895
        // optimize for fees only, to 1 to optimize for reliability only or a
896
        // value in between for a mix.
897
        TimePref float64
898

899
        // Metadata is additional data that is sent along with the payment to
900
        // the payee.
901
        Metadata []byte
902
}
903

904
// AMPOptions houses information that must be known in order to send an AMP
905
// payment.
906
type AMPOptions struct {
907
        SetID     [32]byte
908
        RootShare [32]byte
909
}
910

911
// SetPaymentHash sets the given hash as the payment's overall hash. This
912
// should only be used for non-AMP payments.
913
func (l *LightningPayment) SetPaymentHash(hash lntypes.Hash) error {
10✔
914
        if l.amp != nil {
10✔
915
                return fmt.Errorf("cannot set payment hash for AMP payment")
×
916
        }
×
917

918
        l.paymentHash = &hash
10✔
919
        return nil
10✔
920
}
921

922
// SetAMP sets the given AMP options for the payment.
UNCOV
923
func (l *LightningPayment) SetAMP(amp *AMPOptions) error {
×
UNCOV
924
        if l.paymentHash != nil {
×
925
                return fmt.Errorf("cannot set amp options for payment " +
×
926
                        "with payment hash")
×
927
        }
×
928

UNCOV
929
        l.amp = amp
×
UNCOV
930
        return nil
×
931
}
932

933
// Identifier returns a 32-byte slice that uniquely identifies this single
934
// payment. For non-AMP payments this will be the payment hash, for AMP
935
// payments this will be the used SetID.
936
func (l *LightningPayment) Identifier() [32]byte {
71✔
937
        if l.amp != nil {
71✔
UNCOV
938
                return l.amp.SetID
×
UNCOV
939
        }
×
940

941
        return *l.paymentHash
71✔
942
}
943

944
// SendPayment attempts to send a payment as described within the passed
945
// LightningPayment. This function is blocking and will return either: when the
946
// payment is successful, or all candidates routes have been attempted and
947
// resulted in a failed payment. If the payment succeeds, then a non-nil Route
948
// will be returned which describes the path the successful payment traversed
949
// within the network to reach the destination. Additionally, the payment
950
// preimage will also be returned.
951
func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte,
952
        *route.Route, error) {
12✔
953

12✔
954
        paySession, shardTracker, err := r.PreparePayment(payment)
12✔
955
        if err != nil {
12✔
956
                return [32]byte{}, nil, err
×
957
        }
×
958

959
        log.Tracef("Dispatching SendPayment for lightning payment: %v",
12✔
960
                spewPayment(payment))
12✔
961

12✔
962
        return r.sendPayment(
12✔
963
                context.Background(), payment.FeeLimit, payment.Identifier(),
12✔
964
                payment.PayAttemptTimeout, paySession, shardTracker,
12✔
965
                payment.FirstHopCustomRecords,
12✔
966
        )
12✔
967
}
968

969
// SendPaymentAsync is the non-blocking version of SendPayment. The payment
970
// result needs to be retrieved via the control tower.
971
func (r *ChannelRouter) SendPaymentAsync(ctx context.Context,
UNCOV
972
        payment *LightningPayment, ps PaymentSession, st shards.ShardTracker) {
×
UNCOV
973

×
UNCOV
974
        // Since this is the first time this payment is being made, we pass nil
×
UNCOV
975
        // for the existing attempt.
×
UNCOV
976
        r.wg.Add(1)
×
UNCOV
977
        go func() {
×
UNCOV
978
                defer r.wg.Done()
×
UNCOV
979

×
UNCOV
980
                log.Tracef("Dispatching SendPayment for lightning payment: %v",
×
UNCOV
981
                        spewPayment(payment))
×
UNCOV
982

×
UNCOV
983
                _, _, err := r.sendPayment(
×
UNCOV
984
                        ctx, payment.FeeLimit, payment.Identifier(),
×
UNCOV
985
                        payment.PayAttemptTimeout, ps, st,
×
UNCOV
986
                        payment.FirstHopCustomRecords,
×
UNCOV
987
                )
×
UNCOV
988
                if err != nil {
×
UNCOV
989
                        log.Errorf("Payment %x failed: %v",
×
UNCOV
990
                                payment.Identifier(), err)
×
UNCOV
991
                }
×
992
        }()
993
}
994

995
// spewPayment returns a log closures that provides a spewed string
996
// representation of the passed payment.
997
func spewPayment(payment *LightningPayment) lnutils.LogClosure {
12✔
998
        return lnutils.NewLogClosure(func() string {
12✔
999
                // Make a copy of the payment with a nilled Curve
×
1000
                // before spewing.
×
1001
                var routeHints [][]zpay32.HopHint
×
1002
                for _, routeHint := range payment.RouteHints {
×
1003
                        var hopHints []zpay32.HopHint
×
1004
                        for _, hopHint := range routeHint {
×
1005
                                h := hopHint.Copy()
×
1006
                                hopHints = append(hopHints, h)
×
1007
                        }
×
1008
                        routeHints = append(routeHints, hopHints)
×
1009
                }
1010
                p := *payment
×
1011
                p.RouteHints = routeHints
×
1012
                return spew.Sdump(p)
×
1013
        })
1014
}
1015

1016
// PreparePayment creates the payment session and registers the payment with the
1017
// control tower.
1018
func (r *ChannelRouter) PreparePayment(payment *LightningPayment) (
1019
        PaymentSession, shards.ShardTracker, error) {
12✔
1020

12✔
1021
        // Assemble any custom data we want to send to the first hop only.
12✔
1022
        var firstHopData fn.Option[tlv.Blob]
12✔
1023
        if len(payment.FirstHopCustomRecords) > 0 {
12✔
UNCOV
1024
                if err := payment.FirstHopCustomRecords.Validate(); err != nil {
×
1025
                        return nil, nil, fmt.Errorf("invalid first hop custom "+
×
1026
                                "records: %w", err)
×
1027
                }
×
1028

UNCOV
1029
                firstHopBlob, err := payment.FirstHopCustomRecords.Serialize()
×
UNCOV
1030
                if err != nil {
×
1031
                        return nil, nil, fmt.Errorf("unable to serialize "+
×
1032
                                "first hop custom records: %w", err)
×
1033
                }
×
1034

UNCOV
1035
                firstHopData = fn.Some(firstHopBlob)
×
1036
        }
1037

1038
        // Before starting the HTLC routing attempt, we'll create a fresh
1039
        // payment session which will report our errors back to mission
1040
        // control.
1041
        paySession, err := r.cfg.SessionSource.NewPaymentSession(
12✔
1042
                payment, firstHopData, r.cfg.TrafficShaper,
12✔
1043
        )
12✔
1044
        if err != nil {
12✔
1045
                return nil, nil, err
×
1046
        }
×
1047

1048
        // Record this payment hash with the ControlTower, ensuring it is not
1049
        // already in-flight.
1050
        //
1051
        // TODO(roasbeef): store records as part of creation info?
1052
        info := &channeldb.PaymentCreationInfo{
12✔
1053
                PaymentIdentifier:     payment.Identifier(),
12✔
1054
                Value:                 payment.Amount,
12✔
1055
                CreationTime:          r.cfg.Clock.Now(),
12✔
1056
                PaymentRequest:        payment.PaymentRequest,
12✔
1057
                FirstHopCustomRecords: payment.FirstHopCustomRecords,
12✔
1058
        }
12✔
1059

12✔
1060
        // Create a new ShardTracker that we'll use during the life cycle of
12✔
1061
        // this payment.
12✔
1062
        var shardTracker shards.ShardTracker
12✔
1063
        switch {
12✔
1064
        // If this is an AMP payment, we'll use the AMP shard tracker.
UNCOV
1065
        case payment.amp != nil:
×
UNCOV
1066
                addr := payment.PaymentAddr.UnwrapOr([32]byte{})
×
UNCOV
1067
                shardTracker = amp.NewShardTracker(
×
UNCOV
1068
                        payment.amp.RootShare, payment.amp.SetID, addr,
×
UNCOV
1069
                        payment.Amount,
×
UNCOV
1070
                )
×
1071

1072
        // Otherwise we'll use the simple tracker that will map each attempt to
1073
        // the same payment hash.
1074
        default:
12✔
1075
                shardTracker = shards.NewSimpleShardTracker(
12✔
1076
                        payment.Identifier(), nil,
12✔
1077
                )
12✔
1078
        }
1079

1080
        err = r.cfg.Control.InitPayment(payment.Identifier(), info)
12✔
1081
        if err != nil {
12✔
1082
                return nil, nil, err
×
1083
        }
×
1084

1085
        return paySession, shardTracker, nil
12✔
1086
}
1087

1088
// SendToRoute sends a payment using the provided route and fails the payment
1089
// when an error is returned from the attempt.
1090
func (r *ChannelRouter) SendToRoute(htlcHash lntypes.Hash, rt *route.Route,
1091
        firstHopCustomRecords lnwire.CustomRecords) (*channeldb.HTLCAttempt,
1092
        error) {
6✔
1093

6✔
1094
        return r.sendToRoute(htlcHash, rt, false, firstHopCustomRecords)
6✔
1095
}
6✔
1096

1097
// SendToRouteSkipTempErr sends a payment using the provided route and fails
1098
// the payment ONLY when a terminal error is returned from the attempt.
1099
func (r *ChannelRouter) SendToRouteSkipTempErr(htlcHash lntypes.Hash,
1100
        rt *route.Route,
1101
        firstHopCustomRecords lnwire.CustomRecords) (*channeldb.HTLCAttempt,
1102
        error) {
4✔
1103

4✔
1104
        return r.sendToRoute(htlcHash, rt, true, firstHopCustomRecords)
4✔
1105
}
4✔
1106

1107
// sendToRoute attempts to send a payment with the given hash through the
1108
// provided route. This function is blocking and will return the attempt
1109
// information as it is stored in the database. For a successful htlc, this
1110
// information will contain the preimage. If an error occurs after the attempt
1111
// was initiated, both return values will be non-nil. If skipTempErr is true,
1112
// the payment won't be failed unless a terminal error has occurred.
1113
func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route,
1114
        skipTempErr bool,
1115
        firstHopCustomRecords lnwire.CustomRecords) (*channeldb.HTLCAttempt,
1116
        error) {
10✔
1117

10✔
1118
        log.Debugf("SendToRoute for payment %v with skipTempErr=%v",
10✔
1119
                htlcHash, skipTempErr)
10✔
1120

10✔
1121
        // Calculate amount paid to receiver.
10✔
1122
        amt := rt.ReceiverAmt()
10✔
1123

10✔
1124
        // If this is meant as an MP payment shard, we set the amount for the
10✔
1125
        // creating info to the total amount of the payment.
10✔
1126
        finalHop := rt.Hops[len(rt.Hops)-1]
10✔
1127
        mpp := finalHop.MPP
10✔
1128
        if mpp != nil {
14✔
1129
                amt = mpp.TotalMsat()
4✔
1130
        }
4✔
1131

1132
        // For non-MPP, there's no such thing as temp error as there's only one
1133
        // HTLC attempt being made. When this HTLC is failed, the payment is
1134
        // failed hence cannot be retried.
1135
        if skipTempErr && mpp == nil {
11✔
1136
                return nil, ErrSkipTempErr
1✔
1137
        }
1✔
1138

1139
        // For non-AMP payments the overall payment identifier will be the same
1140
        // hash as used for this HTLC.
1141
        paymentIdentifier := htlcHash
9✔
1142

9✔
1143
        // For AMP-payments, we'll use the setID as the unique ID for the
9✔
1144
        // overall payment.
9✔
1145
        amp := finalHop.AMP
9✔
1146
        if amp != nil {
9✔
UNCOV
1147
                paymentIdentifier = amp.SetID()
×
UNCOV
1148
        }
×
1149

1150
        // Record this payment hash with the ControlTower, ensuring it is not
1151
        // already in-flight.
1152
        info := &channeldb.PaymentCreationInfo{
9✔
1153
                PaymentIdentifier:     paymentIdentifier,
9✔
1154
                Value:                 amt,
9✔
1155
                CreationTime:          r.cfg.Clock.Now(),
9✔
1156
                PaymentRequest:        nil,
9✔
1157
                FirstHopCustomRecords: firstHopCustomRecords,
9✔
1158
        }
9✔
1159

9✔
1160
        err := r.cfg.Control.InitPayment(paymentIdentifier, info)
9✔
1161
        switch {
9✔
1162
        // If this is an MPP attempt and the hash is already registered with
1163
        // the database, we can go on to launch the shard.
UNCOV
1164
        case mpp != nil && errors.Is(err, channeldb.ErrPaymentInFlight):
×
1165
        case mpp != nil && errors.Is(err, channeldb.ErrPaymentExists):
×
1166

1167
        // Any other error is not tolerated.
1168
        case err != nil:
×
1169
                return nil, err
×
1170
        }
1171

1172
        log.Tracef("Dispatching SendToRoute for HTLC hash %v: %v", htlcHash,
9✔
1173
                lnutils.SpewLogClosure(rt))
9✔
1174

9✔
1175
        // Since the HTLC hashes and preimages are specified manually over the
9✔
1176
        // RPC for SendToRoute requests, we don't have to worry about creating
9✔
1177
        // a ShardTracker that can generate hashes for AMP payments. Instead, we
9✔
1178
        // create a simple tracker that can just return the hash for the single
9✔
1179
        // shard we'll now launch.
9✔
1180
        shardTracker := shards.NewSimpleShardTracker(htlcHash, nil)
9✔
1181

9✔
1182
        // Create a payment lifecycle using the given route with,
9✔
1183
        // - zero fee limit as we are not requesting routes.
9✔
1184
        // - nil payment session (since we already have a route).
9✔
1185
        // - no payment timeout.
9✔
1186
        // - no current block height.
9✔
1187
        p := newPaymentLifecycle(
9✔
1188
                r, 0, paymentIdentifier, nil, shardTracker, 0,
9✔
1189
                firstHopCustomRecords,
9✔
1190
        )
9✔
1191

9✔
1192
        // Allow the traffic shaper to add custom records to the outgoing HTLC
9✔
1193
        // and also adjust the amount if needed.
9✔
1194
        err = p.amendFirstHopData(rt)
9✔
1195
        if err != nil {
9✔
1196
                return nil, err
×
1197
        }
×
1198

1199
        // We found a route to try, create a new HTLC attempt to try.
1200
        //
1201
        // NOTE: we use zero `remainingAmt` here to simulate the same effect of
1202
        // setting the lastShard to be false, which is used by previous
1203
        // implementation.
1204
        attempt, err := p.registerAttempt(rt, 0)
9✔
1205
        if err != nil {
9✔
1206
                return nil, err
×
1207
        }
×
1208

1209
        // Once the attempt is created, send it to the htlcswitch. Notice that
1210
        // the `err` returned here has already been processed by
1211
        // `handleSwitchErr`, which means if there's a terminal failure, the
1212
        // payment has been failed.
1213
        result, err := p.sendAttempt(attempt)
9✔
1214
        if err != nil {
9✔
1215
                return nil, err
×
1216
        }
×
1217

1218
        // We now look up the payment to see if it's already failed.
1219
        payment, err := p.router.cfg.Control.FetchPayment(p.identifier)
9✔
1220
        if err != nil {
9✔
1221
                return result.attempt, err
×
1222
        }
×
1223

1224
        // Exit if the above error has caused the payment to be failed, we also
1225
        // return the error from sending attempt to mimic the old behavior of
1226
        // this method.
1227
        _, failedReason := payment.TerminalInfo()
9✔
1228
        if failedReason != nil {
10✔
1229
                return result.attempt, result.err
1✔
1230
        }
1✔
1231

1232
        // Since for SendToRoute we won't retry in case the shard fails, we'll
1233
        // mark the payment failed with the control tower immediately if the
1234
        // skipTempErr is false.
1235
        reason := channeldb.FailureReasonError
8✔
1236

8✔
1237
        // If we failed to send the HTLC, we need to further decide if we want
8✔
1238
        // to fail the payment.
8✔
1239
        if result.err != nil {
11✔
1240
                // If skipTempErr, we'll return the attempt and the temp error.
3✔
1241
                if skipTempErr {
4✔
1242
                        return result.attempt, result.err
1✔
1243
                }
1✔
1244

1245
                // Otherwise we need to fail the payment.
1246
                err := r.cfg.Control.FailPayment(paymentIdentifier, reason)
2✔
1247
                if err != nil {
2✔
1248
                        return nil, err
×
1249
                }
×
1250

1251
                return result.attempt, result.err
2✔
1252
        }
1253

1254
        // The attempt was successfully sent, wait for the result to be
1255
        // available.
1256
        result, err = p.collectResult(attempt)
5✔
1257
        if err != nil {
5✔
1258
                return nil, err
×
1259
        }
×
1260

1261
        // We got a successful result.
1262
        if result.err == nil {
6✔
1263
                return result.attempt, nil
1✔
1264
        }
1✔
1265

1266
        // An error returned from collecting the result, we'll mark the payment
1267
        // as failed if we don't skip temp error.
1268
        if !skipTempErr {
8✔
1269
                err := r.cfg.Control.FailPayment(paymentIdentifier, reason)
4✔
1270
                if err != nil {
4✔
1271
                        return nil, err
×
1272
                }
×
1273
        }
1274

1275
        return result.attempt, result.err
4✔
1276
}
1277

1278
// sendPayment attempts to send a payment to the passed payment hash. This
1279
// function is blocking and will return either: when the payment is successful,
1280
// or all candidates routes have been attempted and resulted in a failed
1281
// payment. If the payment succeeds, then a non-nil Route will be returned
1282
// which describes the path the successful payment traversed within the network
1283
// to reach the destination. Additionally, the payment preimage will also be
1284
// returned.
1285
//
1286
// This method relies on the ControlTower's internal payment state machine to
1287
// carry out its execution. After restarts, it is safe, and assumed, that the
1288
// router will call this method for every payment still in-flight according to
1289
// the ControlTower.
1290
func (r *ChannelRouter) sendPayment(ctx context.Context,
1291
        feeLimit lnwire.MilliSatoshi, identifier lntypes.Hash,
1292
        paymentAttemptTimeout time.Duration, paySession PaymentSession,
1293
        shardTracker shards.ShardTracker,
1294
        firstHopCustomRecords lnwire.CustomRecords) ([32]byte, *route.Route,
1295
        error) {
12✔
1296

12✔
1297
        // If the user provides a timeout, we will additionally wrap the context
12✔
1298
        // in a deadline.
12✔
1299
        cancel := func() {}
24✔
1300
        if paymentAttemptTimeout > 0 {
12✔
UNCOV
1301
                ctx, cancel = context.WithTimeout(ctx, paymentAttemptTimeout)
×
UNCOV
1302
        }
×
1303

1304
        // Since resumePayment is a blocking call, we'll cancel this
1305
        // context if the payment completes before the optional
1306
        // deadline.
1307
        defer cancel()
12✔
1308

12✔
1309
        // We'll also fetch the current block height, so we can properly
12✔
1310
        // calculate the required HTLC time locks within the route.
12✔
1311
        _, currentHeight, err := r.cfg.Chain.GetBestBlock()
12✔
1312
        if err != nil {
12✔
1313
                return [32]byte{}, nil, err
×
1314
        }
×
1315

1316
        // Validate the custom records before we attempt to send the payment.
1317
        if err := firstHopCustomRecords.Validate(); err != nil {
12✔
1318
                return [32]byte{}, nil, err
×
1319
        }
×
1320

1321
        // Now set up a paymentLifecycle struct with these params, such that we
1322
        // can resume the payment from the current state.
1323
        p := newPaymentLifecycle(
12✔
1324
                r, feeLimit, identifier, paySession, shardTracker,
12✔
1325
                currentHeight, firstHopCustomRecords,
12✔
1326
        )
12✔
1327

12✔
1328
        return p.resumePayment(ctx)
12✔
1329
}
1330

1331
// extractChannelUpdate examines the error and extracts the channel update.
1332
func (r *ChannelRouter) extractChannelUpdate(
1333
        failure lnwire.FailureMessage) *lnwire.ChannelUpdate1 {
17✔
1334

17✔
1335
        var update *lnwire.ChannelUpdate1
17✔
1336
        switch onionErr := failure.(type) {
17✔
1337
        case *lnwire.FailExpiryTooSoon:
1✔
1338
                update = &onionErr.Update
1✔
UNCOV
1339
        case *lnwire.FailAmountBelowMinimum:
×
UNCOV
1340
                update = &onionErr.Update
×
1341
        case *lnwire.FailFeeInsufficient:
7✔
1342
                update = &onionErr.Update
7✔
1343
        case *lnwire.FailIncorrectCltvExpiry:
×
1344
                update = &onionErr.Update
×
UNCOV
1345
        case *lnwire.FailChannelDisabled:
×
UNCOV
1346
                update = &onionErr.Update
×
1347
        case *lnwire.FailTemporaryChannelFailure:
5✔
1348
                update = onionErr.Update
5✔
1349
        }
1350

1351
        return update
17✔
1352
}
1353

1354
// ErrNoChannel is returned when a route cannot be built because there are no
1355
// channels that satisfy all requirements.
1356
type ErrNoChannel struct {
1357
        position int
1358
}
1359

1360
// Error returns a human-readable string describing the error.
1361
func (e ErrNoChannel) Error() string {
1✔
1362
        return fmt.Sprintf("no matching outgoing channel available for "+
1✔
1363
                "node index %v", e.position)
1✔
1364
}
1✔
1365

1366
// BuildRoute returns a fully specified route based on a list of pubkeys. If
1367
// amount is nil, the minimum routable amount is used. To force a specific
1368
// outgoing channel, use the outgoingChan parameter.
1369
func (r *ChannelRouter) BuildRoute(amt fn.Option[lnwire.MilliSatoshi],
1370
        hops []route.Vertex, outgoingChan *uint64, finalCltvDelta int32,
1371
        payAddr fn.Option[[32]byte], firstHopBlob fn.Option[[]byte]) (
1372
        *route.Route, error) {
8✔
1373

8✔
1374
        log.Tracef("BuildRoute called: hopsCount=%v, amt=%v", len(hops), amt)
8✔
1375

8✔
1376
        var outgoingChans map[uint64]struct{}
8✔
1377
        if outgoingChan != nil {
8✔
1378
                outgoingChans = map[uint64]struct{}{
×
1379
                        *outgoingChan: {},
×
1380
                }
×
1381
        }
×
1382

1383
        // We'll attempt to obtain a set of bandwidth hints that helps us select
1384
        // the best outgoing channel to use in case no outgoing channel is set.
1385
        bandwidthHints, err := newBandwidthManager(
8✔
1386
                r.cfg.RoutingGraph, r.cfg.SelfNode, r.cfg.GetLink, firstHopBlob,
8✔
1387
                r.cfg.TrafficShaper,
8✔
1388
        )
8✔
1389
        if err != nil {
8✔
1390
                return nil, err
×
1391
        }
×
1392

1393
        sourceNode := r.cfg.SelfNode
8✔
1394

8✔
1395
        // We check that each node in the route has a connection to others that
8✔
1396
        // can forward in principle.
8✔
1397
        unifiers, err := getEdgeUnifiers(
8✔
1398
                r.cfg.SelfNode, hops, outgoingChans, r.cfg.RoutingGraph,
8✔
1399
        )
8✔
1400
        if err != nil {
9✔
1401
                return nil, err
1✔
1402
        }
1✔
1403

1404
        var (
7✔
1405
                receiverAmt lnwire.MilliSatoshi
7✔
1406
                senderAmt   lnwire.MilliSatoshi
7✔
1407
                pathEdges   []*unifiedEdge
7✔
1408
        )
7✔
1409

7✔
1410
        // We determine the edges compatible with the requested amount, as well
7✔
1411
        // as the amount to send, which can be used to determine the final
7✔
1412
        // receiver amount, if a minimal amount was requested.
7✔
1413
        pathEdges, senderAmt, err = senderAmtBackwardPass(
7✔
1414
                unifiers, amt, bandwidthHints,
7✔
1415
        )
7✔
1416
        if err != nil {
9✔
1417
                return nil, err
2✔
1418
        }
2✔
1419

1420
        // For the minimal amount search, we need to do a forward pass to find a
1421
        // larger receiver amount due to possible min HTLC bumps, otherwise we
1422
        // just use the requested amount.
1423
        receiverAmt, err = fn.ElimOption(
5✔
1424
                amt,
5✔
1425
                func() fn.Result[lnwire.MilliSatoshi] {
8✔
1426
                        return fn.NewResult(
3✔
1427
                                receiverAmtForwardPass(senderAmt, pathEdges),
3✔
1428
                        )
3✔
1429
                },
3✔
1430
                fn.Ok[lnwire.MilliSatoshi],
1431
        ).Unpack()
1432
        if err != nil {
5✔
1433
                return nil, err
×
1434
        }
×
1435

1436
        // Fetch the current block height outside the routing transaction, to
1437
        // prevent the rpc call blocking the database.
1438
        _, height, err := r.cfg.Chain.GetBestBlock()
5✔
1439
        if err != nil {
5✔
1440
                return nil, err
×
1441
        }
×
1442

1443
        // Build and return the final route.
1444
        return newRoute(
5✔
1445
                sourceNode, pathEdges, uint32(height),
5✔
1446
                finalHopParams{
5✔
1447
                        amt:         receiverAmt,
5✔
1448
                        totalAmt:    receiverAmt,
5✔
1449
                        cltvDelta:   uint16(finalCltvDelta),
5✔
1450
                        records:     nil,
5✔
1451
                        paymentAddr: payAddr,
5✔
1452
                }, nil,
5✔
1453
        )
5✔
1454
}
1455

1456
// resumePayments fetches inflight payments and resumes their payment
1457
// lifecycles.
1458
func (r *ChannelRouter) resumePayments() error {
17✔
1459
        // Get all payments that are inflight.
17✔
1460
        payments, err := r.cfg.Control.FetchInFlightPayments()
17✔
1461
        if err != nil {
17✔
1462
                return err
×
1463
        }
×
1464

1465
        // Before we restart existing payments and start accepting more
1466
        // payments to be made, we clean the network result store of the
1467
        // Switch. We do this here at startup to ensure no more payments can be
1468
        // made concurrently, so we know the toKeep map will be up-to-date
1469
        // until the cleaning has finished.
1470
        toKeep := make(map[uint64]struct{})
17✔
1471
        for _, p := range payments {
17✔
UNCOV
1472
                for _, a := range p.HTLCs {
×
UNCOV
1473
                        toKeep[a.AttemptID] = struct{}{}
×
UNCOV
1474

×
UNCOV
1475
                        // Try to fail the attempt if the route contains a dead
×
UNCOV
1476
                        // channel.
×
UNCOV
1477
                        r.failStaleAttempt(a, p.Info.PaymentIdentifier)
×
UNCOV
1478
                }
×
1479
        }
1480

1481
        log.Debugf("Cleaning network result store.")
17✔
1482
        if err := r.cfg.Payer.CleanStore(toKeep); err != nil {
17✔
1483
                return err
×
1484
        }
×
1485

1486
        // launchPayment is a helper closure that handles resuming the payment.
1487
        launchPayment := func(payment *channeldb.MPPayment) {
17✔
UNCOV
1488
                defer r.wg.Done()
×
UNCOV
1489

×
UNCOV
1490
                // Get the hashes used for the outstanding HTLCs.
×
UNCOV
1491
                htlcs := make(map[uint64]lntypes.Hash)
×
UNCOV
1492
                for _, a := range payment.HTLCs {
×
UNCOV
1493
                        a := a
×
UNCOV
1494

×
UNCOV
1495
                        // We check whether the individual attempts have their
×
UNCOV
1496
                        // HTLC hash set, if not we'll fall back to the overall
×
UNCOV
1497
                        // payment hash.
×
UNCOV
1498
                        hash := payment.Info.PaymentIdentifier
×
UNCOV
1499
                        if a.Hash != nil {
×
UNCOV
1500
                                hash = *a.Hash
×
UNCOV
1501
                        }
×
1502

UNCOV
1503
                        htlcs[a.AttemptID] = hash
×
1504
                }
1505

UNCOV
1506
                payHash := payment.Info.PaymentIdentifier
×
UNCOV
1507

×
UNCOV
1508
                // Since we are not supporting creating more shards after a
×
UNCOV
1509
                // restart (only receiving the result of the shards already
×
UNCOV
1510
                // outstanding), we create a simple shard tracker that will map
×
UNCOV
1511
                // the attempt IDs to hashes used for the HTLCs. This will be
×
UNCOV
1512
                // enough also for AMP payments, since we only need the hashes
×
UNCOV
1513
                // for the individual HTLCs to regenerate the circuits, and we
×
UNCOV
1514
                // don't currently persist the root share necessary to
×
UNCOV
1515
                // re-derive them.
×
UNCOV
1516
                shardTracker := shards.NewSimpleShardTracker(payHash, htlcs)
×
UNCOV
1517

×
UNCOV
1518
                // We create a dummy, empty payment session such that we won't
×
UNCOV
1519
                // make another payment attempt when the result for the
×
UNCOV
1520
                // in-flight attempt is received.
×
UNCOV
1521
                paySession := r.cfg.SessionSource.NewPaymentSessionEmpty()
×
UNCOV
1522

×
UNCOV
1523
                // We pass in a non-timeout context, to indicate we don't need
×
UNCOV
1524
                // it to timeout. It will stop immediately after the existing
×
UNCOV
1525
                // attempt has finished anyway. We also set a zero fee limit,
×
UNCOV
1526
                // as no more routes should be tried.
×
UNCOV
1527
                noTimeout := time.Duration(0)
×
UNCOV
1528
                _, _, err := r.sendPayment(
×
UNCOV
1529
                        context.Background(), 0, payHash, noTimeout, paySession,
×
UNCOV
1530
                        shardTracker, payment.Info.FirstHopCustomRecords,
×
UNCOV
1531
                )
×
UNCOV
1532
                if err != nil {
×
UNCOV
1533
                        log.Errorf("Resuming payment %v failed: %v", payHash,
×
UNCOV
1534
                                err)
×
UNCOV
1535

×
UNCOV
1536
                        return
×
UNCOV
1537
                }
×
1538

UNCOV
1539
                log.Infof("Resumed payment %v completed", payHash)
×
1540
        }
1541

1542
        for _, payment := range payments {
17✔
UNCOV
1543
                log.Infof("Resuming payment %v", payment.Info.PaymentIdentifier)
×
UNCOV
1544

×
UNCOV
1545
                r.wg.Add(1)
×
UNCOV
1546
                go launchPayment(payment)
×
UNCOV
1547
        }
×
1548

1549
        return nil
17✔
1550
}
1551

1552
// failStaleAttempt will fail an HTLC attempt if it's using an unknown channel
1553
// in its route. It first consults the switch to see if there's already a
1554
// network result stored for this attempt. If not, it will check whether the
1555
// first hop of this attempt is using an active channel known to us. If
1556
// inactive, this attempt will be failed.
1557
//
1558
// NOTE: there's an unknown bug that caused the network result for a particular
1559
// attempt to NOT be saved, resulting a payment being stuck forever. More info:
1560
// - https://github.com/lightningnetwork/lnd/issues/8146
1561
// - https://github.com/lightningnetwork/lnd/pull/8174
1562
func (r *ChannelRouter) failStaleAttempt(a channeldb.HTLCAttempt,
UNCOV
1563
        payHash lntypes.Hash) {
×
UNCOV
1564

×
UNCOV
1565
        // We can only fail inflight HTLCs so we skip the settled/failed ones.
×
UNCOV
1566
        if a.Failure != nil || a.Settle != nil {
×
1567
                return
×
1568
        }
×
1569

1570
        // First, check if we've already had a network result for this attempt.
1571
        // If no result is found, we'll check whether the reference link is
1572
        // still known to us.
UNCOV
1573
        ok, err := r.cfg.Payer.HasAttemptResult(a.AttemptID)
×
UNCOV
1574
        if err != nil {
×
1575
                log.Errorf("Failed to fetch network result for attempt=%v",
×
1576
                        a.AttemptID)
×
1577
                return
×
1578
        }
×
1579

1580
        // There's already a network result, no need to fail it here as the
1581
        // payment lifecycle will take care of it, so we can exit early.
UNCOV
1582
        if ok {
×
1583
                log.Debugf("Already have network result for attempt=%v",
×
1584
                        a.AttemptID)
×
1585
                return
×
1586
        }
×
1587

1588
        // We now need to decide whether this attempt should be failed here.
1589
        // For very old payments, it's possible that the network results were
1590
        // never saved, causing the payments to be stuck inflight. We now check
1591
        // whether the first hop is referencing an active channel ID and, if
1592
        // not, we will fail the attempt as it has no way to be retried again.
UNCOV
1593
        var shouldFail bool
×
UNCOV
1594

×
UNCOV
1595
        // Validate that the attempt has hop info. If this attempt has no hop
×
UNCOV
1596
        // info it indicates an error in our db.
×
UNCOV
1597
        if len(a.Route.Hops) == 0 {
×
1598
                log.Errorf("Found empty hop for attempt=%v", a.AttemptID)
×
1599

×
1600
                shouldFail = true
×
UNCOV
1601
        } else {
×
UNCOV
1602
                // Get the short channel ID.
×
UNCOV
1603
                chanID := a.Route.Hops[0].ChannelID
×
UNCOV
1604
                scid := lnwire.NewShortChanIDFromInt(chanID)
×
UNCOV
1605

×
UNCOV
1606
                // Check whether this link is active. If so, we won't fail the
×
UNCOV
1607
                // attempt but keep waiting for its result.
×
UNCOV
1608
                _, err := r.cfg.GetLink(scid)
×
UNCOV
1609
                if err == nil {
×
1610
                        return
×
1611
                }
×
1612

1613
                // We should get the link not found err. If not, we will log an
1614
                // error and skip failing this attempt since an unknown error
1615
                // occurred.
UNCOV
1616
                if !errors.Is(err, htlcswitch.ErrChannelLinkNotFound) {
×
1617
                        log.Errorf("Failed to get link for attempt=%v for "+
×
1618
                                "payment=%v: %v", a.AttemptID, payHash, err)
×
1619

×
1620
                        return
×
1621
                }
×
1622

1623
                // The channel link is not active, we now check whether this
1624
                // channel is already closed. If so, we fail the HTLC attempt
1625
                // as there's no need to wait for its network result because
1626
                // there's no link. If the channel is still pending, we'll keep
1627
                // waiting for the result as we may get a contract resolution
1628
                // for this HTLC.
UNCOV
1629
                if _, ok := r.cfg.ClosedSCIDs[scid]; ok {
×
1630
                        shouldFail = true
×
1631
                }
×
1632
        }
1633

1634
        // Exit if there's no need to fail.
UNCOV
1635
        if !shouldFail {
×
UNCOV
1636
                return
×
UNCOV
1637
        }
×
1638

1639
        log.Errorf("Failing stale attempt=%v for payment=%v", a.AttemptID,
×
1640
                payHash)
×
1641

×
1642
        // Fail the attempt in db. If there's an error, there's nothing we can
×
1643
        // do here but logging it.
×
1644
        failInfo := &channeldb.HTLCFailInfo{
×
1645
                Reason:   channeldb.HTLCFailUnknown,
×
1646
                FailTime: r.cfg.Clock.Now(),
×
1647
        }
×
1648
        _, err = r.cfg.Control.FailAttempt(payHash, a.AttemptID, failInfo)
×
1649
        if err != nil {
×
1650
                log.Errorf("Fail attempt=%v got error: %v", a.AttemptID, err)
×
1651
        }
×
1652
}
1653

1654
// getEdgeUnifiers returns a list of edge unifiers for the given route.
1655
func getEdgeUnifiers(source route.Vertex, hops []route.Vertex,
1656
        outgoingChans map[uint64]struct{},
1657
        graph Graph) ([]*edgeUnifier, error) {
8✔
1658

8✔
1659
        // Allocate a list that will contain the edge unifiers for this route.
8✔
1660
        unifiers := make([]*edgeUnifier, len(hops))
8✔
1661

8✔
1662
        // Traverse hops backwards to accumulate fees in the running amounts.
8✔
1663
        for i := len(hops) - 1; i >= 0; i-- {
21✔
1664
                toNode := hops[i]
13✔
1665

13✔
1666
                var fromNode route.Vertex
13✔
1667
                if i == 0 {
19✔
1668
                        fromNode = source
6✔
1669
                } else {
13✔
1670
                        fromNode = hops[i-1]
7✔
1671
                }
7✔
1672

1673
                // Build unified policies for this hop based on the channels
1674
                // known in the graph. Inbound fees are only active if the edge
1675
                // is not the last hop.
1676
                isExitHop := i == len(hops)-1
13✔
1677
                u := newNodeEdgeUnifier(
13✔
1678
                        source, toNode, !isExitHop, outgoingChans,
13✔
1679
                )
13✔
1680

13✔
1681
                err := u.addGraphPolicies(graph)
13✔
1682
                if err != nil {
13✔
1683
                        return nil, err
×
1684
                }
×
1685

1686
                // Exit if there are no channels.
1687
                edgeUnifier, ok := u.edgeUnifiers[fromNode]
13✔
1688
                if !ok {
14✔
1689
                        log.Errorf("Cannot find policy for node %v", fromNode)
1✔
1690
                        return nil, ErrNoChannel{position: i}
1✔
1691
                }
1✔
1692

1693
                unifiers[i] = edgeUnifier
12✔
1694
        }
1695

1696
        return unifiers, nil
7✔
1697
}
1698

1699
// senderAmtBackwardPass returns a list of unified edges for the given route and
1700
// determines the amount that should be sent to fulfill min HTLC requirements.
1701
// The minimal sender amount can be searched for by using amt=None.
1702
func senderAmtBackwardPass(unifiers []*edgeUnifier,
1703
        amt fn.Option[lnwire.MilliSatoshi],
1704
        bandwidthHints bandwidthHints) ([]*unifiedEdge, lnwire.MilliSatoshi,
1705
        error) {
11✔
1706

11✔
1707
        if len(unifiers) == 0 {
12✔
1708
                return nil, 0, fmt.Errorf("no unifiers provided")
1✔
1709
        }
1✔
1710

1711
        var unifiedEdges = make([]*unifiedEdge, len(unifiers))
10✔
1712

10✔
1713
        // We traverse the route backwards and handle the last hop separately.
10✔
1714
        edgeUnifier := unifiers[len(unifiers)-1]
10✔
1715

10✔
1716
        // incomingAmt tracks the amount that is forwarded on the edges of a
10✔
1717
        // route. The last hop only forwards the amount that the receiver should
10✔
1718
        // receive, as there are no fees paid to the last node.
10✔
1719
        // For minimum amount routes, aim to deliver at least 1 msat to
10✔
1720
        // the destination. There are nodes in the wild that have a
10✔
1721
        // min_htlc channel policy of zero, which could lead to a zero
10✔
1722
        // amount payment being made.
10✔
1723
        incomingAmt := amt.UnwrapOr(1)
10✔
1724

10✔
1725
        // If using min amt, increase the amount if needed to fulfill min HTLC
10✔
1726
        // requirements.
10✔
1727
        if amt.IsNone() {
15✔
1728
                min := edgeUnifier.minAmt()
5✔
1729
                if min > incomingAmt {
10✔
1730
                        incomingAmt = min
5✔
1731
                }
5✔
1732
        }
1733

1734
        // Get an edge for the specific amount that we want to forward.
1735
        edge := edgeUnifier.getEdge(incomingAmt, bandwidthHints, 0)
10✔
1736
        if edge == nil {
11✔
1737
                log.Errorf("Cannot find policy with amt=%v "+
1✔
1738
                        "for hop %v", incomingAmt, len(unifiers)-1)
1✔
1739

1✔
1740
                return nil, 0, ErrNoChannel{position: len(unifiers) - 1}
1✔
1741
        }
1✔
1742

1743
        unifiedEdges[len(unifiers)-1] = edge
9✔
1744

9✔
1745
        // Handle the rest of the route except the last hop.
9✔
1746
        for i := len(unifiers) - 2; i >= 0; i-- {
21✔
1747
                edgeUnifier = unifiers[i]
12✔
1748

12✔
1749
                // If using min amt, increase the amount if needed to fulfill
12✔
1750
                // min HTLC requirements.
12✔
1751
                if amt.IsNone() {
18✔
1752
                        min := edgeUnifier.minAmt()
6✔
1753
                        if min > incomingAmt {
6✔
1754
                                incomingAmt = min
×
1755
                        }
×
1756
                }
1757

1758
                // A --current hop-- B --next hop: incomingAmt-- C
1759
                // The outbound fee paid to the current end node B is based on
1760
                // the amount that the next hop forwards and B's policy for that
1761
                // hop.
1762
                outboundFee := unifiedEdges[i+1].policy.ComputeFee(
12✔
1763
                        incomingAmt,
12✔
1764
                )
12✔
1765

12✔
1766
                netAmount := incomingAmt + outboundFee
12✔
1767

12✔
1768
                // We need to select an edge that can forward the requested
12✔
1769
                // amount.
12✔
1770
                edge = edgeUnifier.getEdge(
12✔
1771
                        netAmount, bandwidthHints, outboundFee,
12✔
1772
                )
12✔
1773
                if edge == nil {
13✔
1774
                        return nil, 0, ErrNoChannel{position: i}
1✔
1775
                }
1✔
1776

1777
                // The fee paid to B depends on the current hop's inbound fee
1778
                // policy and on the outbound fee for the next hop as any
1779
                // inbound fee discount is capped by the outbound fee such that
1780
                // the total fee for B can't become negative.
1781
                inboundFee := calcCappedInboundFee(edge, netAmount, outboundFee)
11✔
1782

11✔
1783
                fee := lnwire.MilliSatoshi(int64(outboundFee) + inboundFee)
11✔
1784

11✔
1785
                log.Tracef("Select channel %v at position %v",
11✔
1786
                        edge.policy.ChannelID, i)
11✔
1787

11✔
1788
                // Finally, we update the amount that needs to flow into node B
11✔
1789
                // from A, which is the next hop's forwarding amount plus the
11✔
1790
                // fee for B: A --current hop: incomingAmt-- B --next hop-- C
11✔
1791
                incomingAmt += fee
11✔
1792

11✔
1793
                unifiedEdges[i] = edge
11✔
1794
        }
1795

1796
        return unifiedEdges, incomingAmt, nil
8✔
1797
}
1798

1799
// receiverAmtForwardPass returns the amount that a receiver will receive after
1800
// deducting all fees from the sender amount.
1801
func receiverAmtForwardPass(runningAmt lnwire.MilliSatoshi,
1802
        unifiedEdges []*unifiedEdge) (lnwire.MilliSatoshi, error) {
10✔
1803

10✔
1804
        if len(unifiedEdges) == 0 {
11✔
1805
                return 0, fmt.Errorf("no edges to forward through")
1✔
1806
        }
1✔
1807

1808
        inEdge := unifiedEdges[0]
9✔
1809
        if !inEdge.amtInRange(runningAmt) {
10✔
1810
                log.Errorf("Amount %v not in range for hop index %v",
1✔
1811
                        runningAmt, 0)
1✔
1812

1✔
1813
                return 0, ErrNoChannel{position: 0}
1✔
1814
        }
1✔
1815

1816
        // Now that we arrived at the start of the route and found out the route
1817
        // total amount, we make a forward pass. Because the amount may have
1818
        // been increased in the backward pass, fees need to be recalculated and
1819
        // amount ranges re-checked.
1820
        for i := 1; i < len(unifiedEdges); i++ {
17✔
1821
                inEdge := unifiedEdges[i-1]
9✔
1822
                outEdge := unifiedEdges[i]
9✔
1823

9✔
1824
                // Decrease the amount to send while going forward.
9✔
1825
                runningAmt = outgoingFromIncoming(runningAmt, inEdge, outEdge)
9✔
1826

9✔
1827
                if !outEdge.amtInRange(runningAmt) {
9✔
1828
                        log.Errorf("Amount %v not in range for hop index %v",
×
1829
                                runningAmt, i)
×
1830

×
1831
                        return 0, ErrNoChannel{position: i}
×
1832
                }
×
1833
        }
1834

1835
        return runningAmt, nil
8✔
1836
}
1837

1838
// incomingFromOutgoing computes the incoming amount based on the outgoing
1839
// amount by adding fees to the outgoing amount, replicating the path finding
1840
// and routing process, see also CheckHtlcForward.
1841
func incomingFromOutgoing(outgoingAmt lnwire.MilliSatoshi,
1842
        incoming, outgoing *unifiedEdge) lnwire.MilliSatoshi {
31✔
1843

31✔
1844
        outgoingFee := outgoing.policy.ComputeFee(outgoingAmt)
31✔
1845

31✔
1846
        // Net amount is the amount the inbound fees are calculated with.
31✔
1847
        netAmount := outgoingAmt + outgoingFee
31✔
1848

31✔
1849
        inboundFee := incoming.inboundFees.CalcFee(netAmount)
31✔
1850

31✔
1851
        // The inbound fee is not allowed to reduce the incoming amount below
31✔
1852
        // the outgoing amount.
31✔
1853
        if int64(outgoingFee)+inboundFee < 0 {
40✔
1854
                return outgoingAmt
9✔
1855
        }
9✔
1856

1857
        return netAmount + lnwire.MilliSatoshi(inboundFee)
22✔
1858
}
1859

1860
// outgoingFromIncoming computes the outgoing amount based on the incoming
1861
// amount by subtracting fees from the incoming amount. Note that this is not
1862
// exactly the inverse of incomingFromOutgoing, because of some rounding.
1863
func outgoingFromIncoming(incomingAmt lnwire.MilliSatoshi,
1864
        incoming, outgoing *unifiedEdge) lnwire.MilliSatoshi {
40✔
1865

40✔
1866
        // Convert all quantities to big.Int to be able to hande negative
40✔
1867
        // values. The formulas to compute the outgoing amount involve terms
40✔
1868
        // with PPM*PPM*A, which can easily overflow an int64.
40✔
1869
        A := big.NewInt(int64(incomingAmt))
40✔
1870
        Ro := big.NewInt(int64(outgoing.policy.FeeProportionalMillionths))
40✔
1871
        Bo := big.NewInt(int64(outgoing.policy.FeeBaseMSat))
40✔
1872
        Ri := big.NewInt(int64(incoming.inboundFees.Rate))
40✔
1873
        Bi := big.NewInt(int64(incoming.inboundFees.Base))
40✔
1874
        PPM := big.NewInt(1_000_000)
40✔
1875

40✔
1876
        // The following discussion was contributed by user feelancer21, see
40✔
1877
        //nolint:ll
40✔
1878
        // https://github.com/feelancer21/lnd/commit/f6f05fa930985aac0d27c3f6681aada1b599162a.
40✔
1879

40✔
1880
        // The incoming amount Ai based on the outgoing amount Ao is computed by
40✔
1881
        // Ai = max(Ai(Ao), Ao), which caps the incoming amount such that the
40✔
1882
        // total node fee (Ai - Ao) is non-negative. This is commonly enforced
40✔
1883
        // by routing nodes.
40✔
1884

40✔
1885
        // The function Ai(Ao) is given by:
40✔
1886
        // Ai(Ao) = (Ao + Bo + Ro/PPM) + (Bi + (Ao + Ro/PPM + Bo)*Ri/PPM), where
40✔
1887
        // the first term is the net amount (the outgoing amount plus the
40✔
1888
        // outbound fee), and the second is the inbound fee computed based on
40✔
1889
        // the net amount.
40✔
1890

40✔
1891
        // Ai(Ao) can potentially become more negative in absolute value than
40✔
1892
        // Ao, which is why the above mentioned capping is needed. We can
40✔
1893
        // abbreviate Ai(Ao) with Ai(Ao) = m*Ao + n, where m and n are:
40✔
1894
        // m := (1 + Ro/PPM) * (1 + Ri/PPM)
40✔
1895
        // n := Bi + Bo*(1 + Ri/PPM)
40✔
1896

40✔
1897
        // If we know that m > 0, this is equivalent of Ri/PPM > -1, because Ri
40✔
1898
        // is the only factor that can become negative. A value or Ri/PPM = -1,
40✔
1899
        // means that the routing node is willing to give up on 100% of the
40✔
1900
        // net amount (based on the fee rate), which is likely to not happen in
40✔
1901
        // practice. This condition will be important for a later trick.
40✔
1902

40✔
1903
        // If we want to compute the incoming amount based on the outgoing
40✔
1904
        // amount, which is the reverse problem, we need to solve Ai =
40✔
1905
        // max(Ai(Ao), Ao) for Ao(Ai). Given an incoming amount A,
40✔
1906
        // we look for an Ao such that A = max(Ai(Ao), Ao).
40✔
1907

40✔
1908
        // The max function separates this into two cases. The case to take is
40✔
1909
        // not clear yet, because we don't know Ao, but later we see a trick
40✔
1910
        // how to determine which case is the one to take.
40✔
1911

40✔
1912
        // first case: Ai(Ao) <= Ao:
40✔
1913
        // Therefore, A = max(Ai(Ao), Ao) = Ao, we find Ao = A.
40✔
1914
        // This also leads to Ai(A) <= A by substitution into the condition.
40✔
1915

40✔
1916
        // second case: Ai(Ao) > Ao:
40✔
1917
        // Therefore, A = max(Ai(Ao), Ao) = Ai(Ao) = m*Ao + n. Solving for Ao
40✔
1918
        // gives Ao = (A - n)/m.
40✔
1919
        //
40✔
1920
        // We know
40✔
1921
        // Ai(Ao) > Ao  <=>  A = Ai(Ao) > Ao = (A - n)/m,
40✔
1922
        // so A > (A - n)/m.
40✔
1923
        //
40✔
1924
        // **Assuming m > 0**, by multiplying with m, we can transform this to
40✔
1925
        // A * m + n > A.
40✔
1926
        //
40✔
1927
        // We know Ai(A) = A*m + n, therefore Ai(A) > A.
40✔
1928
        //
40✔
1929
        // This means that if we apply the incoming amount calculation to the
40✔
1930
        // **incoming** amount, and this condition holds, then we know that we
40✔
1931
        // deal with the second case, being able to compute the outgoing amount
40✔
1932
        // based off the formula Ao = (A - n)/m, otherwise we will just return
40✔
1933
        // the incoming amount.
40✔
1934

40✔
1935
        // In case the inbound fee rate is less than -1 (-100%), we fail to
40✔
1936
        // compute the outbound amount and return the incoming amount. This also
40✔
1937
        // protects against zero division later.
40✔
1938

40✔
1939
        // We compute m in terms of big.Int to be safe from overflows and to be
40✔
1940
        // consistent with later calculations.
40✔
1941
        // m := (PPM*PPM + Ri*PPM + Ro*PPM + Ro*Ri)/(PPM*PPM)
40✔
1942

40✔
1943
        // Compute terms in (PPM*PPM + Ri*PPM + Ro*PPM + Ro*Ri).
40✔
1944
        m1 := new(big.Int).Mul(PPM, PPM)
40✔
1945
        m2 := new(big.Int).Mul(Ri, PPM)
40✔
1946
        m3 := new(big.Int).Mul(Ro, PPM)
40✔
1947
        m4 := new(big.Int).Mul(Ro, Ri)
40✔
1948

40✔
1949
        // Add up terms m1..m4.
40✔
1950
        m := big.NewInt(0)
40✔
1951
        m.Add(m, m1)
40✔
1952
        m.Add(m, m2)
40✔
1953
        m.Add(m, m3)
40✔
1954
        m.Add(m, m4)
40✔
1955

40✔
1956
        // Since we compare to 0, we can multiply by PPM*PPM to avoid the
40✔
1957
        // division.
40✔
1958
        if m.Int64() <= 0 {
42✔
1959
                return incomingAmt
2✔
1960
        }
2✔
1961

1962
        // In order to decide if the total fee is negative, we apply the fee
1963
        // to the *incoming* amount as mentioned before.
1964

1965
        // We compute the test amount in terms of big.Int to be safe from
1966
        // overflows and to be consistent later calculations.
1967
        // testAmtF := A*m + n =
1968
        // = A + Bo + Bi + (PPM*(A*Ri + A*Ro + Ro*Ri) + A*Ri*Ro)/(PPM*PPM)
1969

1970
        // Compute terms in (A*Ri + A*Ro + Ro*Ri).
1971
        t1 := new(big.Int).Mul(A, Ri)
38✔
1972
        t2 := new(big.Int).Mul(A, Ro)
38✔
1973
        t3 := new(big.Int).Mul(Ro, Ri)
38✔
1974

38✔
1975
        // Sum up terms t1-t3.
38✔
1976
        t4 := big.NewInt(0)
38✔
1977
        t4.Add(t4, t1)
38✔
1978
        t4.Add(t4, t2)
38✔
1979
        t4.Add(t4, t3)
38✔
1980

38✔
1981
        // Compute PPM*(A*Ri + A*Ro + Ro*Ri).
38✔
1982
        t6 := new(big.Int).Mul(PPM, t4)
38✔
1983

38✔
1984
        // Compute A*Ri*Ro.
38✔
1985
        t7 := new(big.Int).Mul(A, Ri)
38✔
1986
        t7.Mul(t7, Ro)
38✔
1987

38✔
1988
        // Compute (PPM*(A*Ri + A*Ro + Ro*Ri) + A*Ri*Ro)/(PPM*PPM).
38✔
1989
        num := new(big.Int).Add(t6, t7)
38✔
1990
        denom := new(big.Int).Mul(PPM, PPM)
38✔
1991
        fraction := new(big.Int).Div(num, denom)
38✔
1992

38✔
1993
        // Sum up all terms.
38✔
1994
        testAmt := big.NewInt(0)
38✔
1995
        testAmt.Add(testAmt, A)
38✔
1996
        testAmt.Add(testAmt, Bo)
38✔
1997
        testAmt.Add(testAmt, Bi)
38✔
1998
        testAmt.Add(testAmt, fraction)
38✔
1999

38✔
2000
        // Protect against negative values for the integer cast to Msat.
38✔
2001
        if testAmt.Int64() < 0 {
42✔
2002
                return incomingAmt
4✔
2003
        }
4✔
2004

2005
        // If the second case holds, we have to compute the outgoing amount.
2006
        if lnwire.MilliSatoshi(testAmt.Int64()) > incomingAmt {
62✔
2007
                // Compute the outgoing amount by integer ceiling division. This
28✔
2008
                // precision is needed because PPM*PPM*A and other terms can
28✔
2009
                // easily overflow with int64, which happens with about
28✔
2010
                // A = 10_000 sat.
28✔
2011

28✔
2012
                // out := (A - n) / m = numerator / denominator
28✔
2013
                // numerator := PPM*(PPM*(A - Bo - Bi) - Bo*Ri)
28✔
2014
                // denominator := PPM*(PPM + Ri + Ro) + Ri*Ro
28✔
2015

28✔
2016
                var numerator big.Int
28✔
2017

28✔
2018
                // Compute (A - Bo - Bi).
28✔
2019
                temp1 := new(big.Int).Sub(A, Bo)
28✔
2020
                temp2 := new(big.Int).Sub(temp1, Bi)
28✔
2021

28✔
2022
                // Compute terms in (PPM*(A - Bo - Bi) - Bo*Ri).
28✔
2023
                temp3 := new(big.Int).Mul(PPM, temp2)
28✔
2024
                temp4 := new(big.Int).Mul(Bo, Ri)
28✔
2025

28✔
2026
                // Compute PPM*(PPM*(A - Bo - Bi) - Bo*Ri)
28✔
2027
                temp5 := new(big.Int).Sub(temp3, temp4)
28✔
2028
                numerator.Mul(PPM, temp5)
28✔
2029

28✔
2030
                var denominator big.Int
28✔
2031

28✔
2032
                // Compute (PPM + Ri + Ro).
28✔
2033
                temp1 = new(big.Int).Add(PPM, Ri)
28✔
2034
                temp2 = new(big.Int).Add(temp1, Ro)
28✔
2035

28✔
2036
                // Compute PPM*(PPM + Ri + Ro) + Ri*Ro.
28✔
2037
                temp3 = new(big.Int).Mul(PPM, temp2)
28✔
2038
                temp4 = new(big.Int).Mul(Ri, Ro)
28✔
2039
                denominator.Add(temp3, temp4)
28✔
2040

28✔
2041
                // We overestimate the outgoing amount by taking the ceiling of
28✔
2042
                // the division. This means that we may round slightly up by a
28✔
2043
                // MilliSatoshi, but this helps to ensure that we don't hit min
28✔
2044
                // HTLC constrains in the context of finding the minimum amount
28✔
2045
                // of a route.
28✔
2046
                // ceil = floor((numerator + denominator - 1) / denominator)
28✔
2047
                ceil := new(big.Int).Add(&numerator, &denominator)
28✔
2048
                ceil.Sub(ceil, big.NewInt(1))
28✔
2049
                ceil.Div(ceil, &denominator)
28✔
2050

28✔
2051
                return lnwire.MilliSatoshi(ceil.Int64())
28✔
2052
        }
28✔
2053

2054
        // Otherwise the inbound fee made up for the outbound fee, which is why
2055
        // we just return the incoming amount.
2056
        return incomingAmt
6✔
2057
}
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