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

lightningnetwork / lnd / 11216766535

07 Oct 2024 01:37PM UTC coverage: 57.817% (-1.0%) from 58.817%
11216766535

Pull #9148

github

ProofOfKeags
lnwire: remove kickoff feerate from propose/commit
Pull Request #9148: DynComms [2/n]: lnwire: add authenticated wire messages for Dyn*

571 of 879 new or added lines in 16 files covered. (64.96%)

23253 existing lines in 251 files now uncovered.

99022 of 171268 relevant lines covered (57.82%)

38420.67 hits per line

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

72.74
/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/channeldb/models"
22
        "github.com/lightningnetwork/lnd/clock"
23
        "github.com/lightningnetwork/lnd/fn"
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
                trafficShaper fn.Option[TlvTrafficShaper]) (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[TlvTrafficShaper]
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):
×
UNCOV
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 {
8✔
1843

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

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

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

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

1857
        return netAmount + lnwire.MilliSatoshi(inboundFee)
5✔
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 {
17✔
1865

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

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

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

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

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

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

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

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

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

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

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

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

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

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

17✔
1956
        // Since we compare to 0, we can multiply by PPM*PPM to avoid the
17✔
1957
        // division.
17✔
1958
        if m.Int64() <= 0 {
19✔
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)
15✔
1972
        t2 := new(big.Int).Mul(A, Ro)
15✔
1973
        t3 := new(big.Int).Mul(Ro, Ri)
15✔
1974

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

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

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

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

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

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

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

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

12✔
2016
                var numerator big.Int
12✔
2017

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

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

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

12✔
2030
                var denominator big.Int
12✔
2031

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

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

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

12✔
2051
                return lnwire.MilliSatoshi(ceil.Int64())
12✔
2052
        }
12✔
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
3✔
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