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

lightningnetwork / lnd / 13440912774

20 Feb 2025 05:14PM UTC coverage: 57.697% (-1.1%) from 58.802%
13440912774

Pull #9535

github

guggero
GitHub: remove duplicate caching

Turns out that actions/setup-go starting with @v4 also adds caching.
With that, our cache size on disk has almost doubled, leading to the
GitHub runner running out of space in certain situation.
We fix that by disabling the automated caching since we already have our
own, custom-tailored version.
Pull Request #9535: GitHub: remove duplicate caching

103519 of 179417 relevant lines covered (57.7%)

24825.3 hits per line

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

73.88
/routing/router.go
1
package routing
2

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

356
        log.Info("Channel Router starting")
17✔
357

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

364
        return nil
17✔
365
}
366

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

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

17✔
378
        close(r.quit)
17✔
379
        r.wg.Wait()
17✔
380

17✔
381
        return nil
17✔
382
}
383

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

464
                requestExpiry = blindedPathSet.FinalCLTVDelta()
3✔
465

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

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

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

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

9✔
493
        var (
9✔
494
                blinded   = blindedPathSet != nil
9✔
495
                targetSet = target != nil
9✔
496
        )
9✔
497

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

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

505
        case targetSet:
6✔
506
                return *target, nil
6✔
507

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

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

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

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

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

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

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

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

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

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

5✔
580
        return route, probability, nil
5✔
581
}
582

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

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

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

607
        // MaxNumPaths is the maximum number of blinded paths to select.
608
        MaxNumPaths uint8
609

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

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

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

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

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

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

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

34✔
669
                        totalRouteProbability *= probability
34✔
670

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

34✔
676
                        prevNode = path[j].vertex
34✔
677
                }
34✔
678

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

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

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

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

707
                bestRoutes = append(bestRoutes, route.route)
14✔
708
        }
709

710
        return bestRoutes, nil
7✔
711
}
712

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

723
// LightningPayment describes a payment to be sent through the network to the
724
// final destination.
725
type LightningPayment struct {
726
        // Target is the node in which the payment should be routed towards.
727
        Target route.Vertex
728

729
        // Amount is the value of the payment to send through the network in
730
        // milli-satoshis.
731
        Amount lnwire.MilliSatoshi
732

733
        // FeeLimit is the maximum fee in millisatoshis that the payment should
734
        // accept when sending it through the network. The payment will fail
735
        // if there isn't a route with lower fees than this limit.
736
        FeeLimit lnwire.MilliSatoshi
737

738
        // CltvLimit is the maximum time lock that is allowed for attempts to
739
        // complete this payment.
740
        CltvLimit uint32
741

742
        // paymentHash is the r-hash value to use within the HTLC extended to
743
        // the first hop. This won't be set for AMP payments.
744
        paymentHash *lntypes.Hash
745

746
        // amp is an optional field that is set if and only if this is am AMP
747
        // payment.
748
        amp *AMPOptions
749

750
        // FinalCLTVDelta is the CTLV expiry delta to use for the _final_ hop
751
        // in the route. This means that the final hop will have a CLTV delta
752
        // of at least: currentHeight + FinalCLTVDelta.
753
        FinalCLTVDelta uint16
754

755
        // PayAttemptTimeout is a timeout value that we'll use to determine
756
        // when we should should abandon the payment attempt after consecutive
757
        // payment failure. This prevents us from attempting to send a payment
758
        // indefinitely. A zero value means the payment will never time out.
759
        //
760
        // TODO(halseth): make wallclock time to allow resume after startup.
761
        PayAttemptTimeout time.Duration
762

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

774
        // BlindedPathSet holds the information about a set of blinded paths to
775
        // the payment recipient. This is mutually exclusive to the RouteHints
776
        // field.
777
        BlindedPathSet *BlindedPaymentPathSet
778

779
        // OutgoingChannelIDs is the list of channels that are allowed for the
780
        // first hop. If nil, any channel may be used.
781
        OutgoingChannelIDs []uint64
782

783
        // LastHop is the pubkey of the last node before the final destination
784
        // is reached. If nil, any node may be used.
785
        LastHop *route.Vertex
786

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

795
        // PaymentAddr is the payment address specified by the receiver. This
796
        // field should be a random 32-byte nonce presented in the receiver's
797
        // invoice to prevent probing of the destination.
798
        PaymentAddr fn.Option[[32]byte]
799

800
        // PaymentRequest is an optional payment request that this payment is
801
        // attempting to complete.
802
        PaymentRequest []byte
803

804
        // DestCustomRecords are TLV records that are to be sent to the final
805
        // hop in the new onion payload format. If the destination does not
806
        // understand this new onion payload format, then the payment will
807
        // fail.
808
        DestCustomRecords record.CustomSet
809

810
        // FirstHopCustomRecords are the TLV records that are to be sent to the
811
        // first hop of this payment. These records will be transmitted via the
812
        // wire message and therefore do not affect the onion payload size.
813
        FirstHopCustomRecords lnwire.CustomRecords
814

815
        // MaxParts is the maximum number of partial payments that may be used
816
        // to complete the full amount.
817
        MaxParts uint32
818

819
        // MaxShardAmt is the largest shard that we'll attempt to split using.
820
        // If this field is set, and we need to split, rather than attempting
821
        // half of the original payment amount, we'll use this value if half
822
        // the payment amount is greater than it.
823
        //
824
        // NOTE: This field is _optional_.
825
        MaxShardAmt *lnwire.MilliSatoshi
826

827
        // TimePref is the time preference for this payment. Set to -1 to
828
        // optimize for fees only, to 1 to optimize for reliability only or a
829
        // value in between for a mix.
830
        TimePref float64
831

832
        // Metadata is additional data that is sent along with the payment to
833
        // the payee.
834
        Metadata []byte
835
}
836

837
// AMPOptions houses information that must be known in order to send an AMP
838
// payment.
839
type AMPOptions struct {
840
        SetID     [32]byte
841
        RootShare [32]byte
842
}
843

844
// SetPaymentHash sets the given hash as the payment's overall hash. This
845
// should only be used for non-AMP payments.
846
func (l *LightningPayment) SetPaymentHash(hash lntypes.Hash) error {
10✔
847
        if l.amp != nil {
10✔
848
                return fmt.Errorf("cannot set payment hash for AMP payment")
×
849
        }
×
850

851
        l.paymentHash = &hash
10✔
852
        return nil
10✔
853
}
854

855
// SetAMP sets the given AMP options for the payment.
856
func (l *LightningPayment) SetAMP(amp *AMPOptions) error {
×
857
        if l.paymentHash != nil {
×
858
                return fmt.Errorf("cannot set amp options for payment " +
×
859
                        "with payment hash")
×
860
        }
×
861

862
        l.amp = amp
×
863
        return nil
×
864
}
865

866
// Identifier returns a 32-byte slice that uniquely identifies this single
867
// payment. For non-AMP payments this will be the payment hash, for AMP
868
// payments this will be the used SetID.
869
func (l *LightningPayment) Identifier() [32]byte {
71✔
870
        if l.amp != nil {
71✔
871
                return l.amp.SetID
×
872
        }
×
873

874
        return *l.paymentHash
71✔
875
}
876

877
// SendPayment attempts to send a payment as described within the passed
878
// LightningPayment. This function is blocking and will return either: when the
879
// payment is successful, or all candidates routes have been attempted and
880
// resulted in a failed payment. If the payment succeeds, then a non-nil Route
881
// will be returned which describes the path the successful payment traversed
882
// within the network to reach the destination. Additionally, the payment
883
// preimage will also be returned.
884
func (r *ChannelRouter) SendPayment(payment *LightningPayment) ([32]byte,
885
        *route.Route, error) {
12✔
886

12✔
887
        paySession, shardTracker, err := r.PreparePayment(payment)
12✔
888
        if err != nil {
12✔
889
                return [32]byte{}, nil, err
×
890
        }
×
891

892
        log.Tracef("Dispatching SendPayment for lightning payment: %v",
12✔
893
                spewPayment(payment))
12✔
894

12✔
895
        return r.sendPayment(
12✔
896
                context.Background(), payment.FeeLimit, payment.Identifier(),
12✔
897
                payment.PayAttemptTimeout, paySession, shardTracker,
12✔
898
                payment.FirstHopCustomRecords,
12✔
899
        )
12✔
900
}
901

902
// SendPaymentAsync is the non-blocking version of SendPayment. The payment
903
// result needs to be retrieved via the control tower.
904
func (r *ChannelRouter) SendPaymentAsync(ctx context.Context,
905
        payment *LightningPayment, ps PaymentSession, st shards.ShardTracker) {
×
906

×
907
        // Since this is the first time this payment is being made, we pass nil
×
908
        // for the existing attempt.
×
909
        r.wg.Add(1)
×
910
        go func() {
×
911
                defer r.wg.Done()
×
912

×
913
                log.Tracef("Dispatching SendPayment for lightning payment: %v",
×
914
                        spewPayment(payment))
×
915

×
916
                _, _, err := r.sendPayment(
×
917
                        ctx, payment.FeeLimit, payment.Identifier(),
×
918
                        payment.PayAttemptTimeout, ps, st,
×
919
                        payment.FirstHopCustomRecords,
×
920
                )
×
921
                if err != nil {
×
922
                        log.Errorf("Payment %x failed: %v",
×
923
                                payment.Identifier(), err)
×
924
                }
×
925
        }()
926
}
927

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

949
// PreparePayment creates the payment session and registers the payment with the
950
// control tower.
951
func (r *ChannelRouter) PreparePayment(payment *LightningPayment) (
952
        PaymentSession, shards.ShardTracker, error) {
12✔
953

12✔
954
        // Assemble any custom data we want to send to the first hop only.
12✔
955
        var firstHopData fn.Option[tlv.Blob]
12✔
956
        if len(payment.FirstHopCustomRecords) > 0 {
12✔
957
                if err := payment.FirstHopCustomRecords.Validate(); err != nil {
×
958
                        return nil, nil, fmt.Errorf("invalid first hop custom "+
×
959
                                "records: %w", err)
×
960
                }
×
961

962
                firstHopBlob, err := payment.FirstHopCustomRecords.Serialize()
×
963
                if err != nil {
×
964
                        return nil, nil, fmt.Errorf("unable to serialize "+
×
965
                                "first hop custom records: %w", err)
×
966
                }
×
967

968
                firstHopData = fn.Some(firstHopBlob)
×
969
        }
970

971
        // Before starting the HTLC routing attempt, we'll create a fresh
972
        // payment session which will report our errors back to mission
973
        // control.
974
        paySession, err := r.cfg.SessionSource.NewPaymentSession(
12✔
975
                payment, firstHopData, r.cfg.TrafficShaper,
12✔
976
        )
12✔
977
        if err != nil {
12✔
978
                return nil, nil, err
×
979
        }
×
980

981
        // Record this payment hash with the ControlTower, ensuring it is not
982
        // already in-flight.
983
        //
984
        // TODO(roasbeef): store records as part of creation info?
985
        info := &channeldb.PaymentCreationInfo{
12✔
986
                PaymentIdentifier:     payment.Identifier(),
12✔
987
                Value:                 payment.Amount,
12✔
988
                CreationTime:          r.cfg.Clock.Now(),
12✔
989
                PaymentRequest:        payment.PaymentRequest,
12✔
990
                FirstHopCustomRecords: payment.FirstHopCustomRecords,
12✔
991
        }
12✔
992

12✔
993
        // Create a new ShardTracker that we'll use during the life cycle of
12✔
994
        // this payment.
12✔
995
        var shardTracker shards.ShardTracker
12✔
996
        switch {
12✔
997
        // If this is an AMP payment, we'll use the AMP shard tracker.
998
        case payment.amp != nil:
×
999
                addr := payment.PaymentAddr.UnwrapOr([32]byte{})
×
1000
                shardTracker = amp.NewShardTracker(
×
1001
                        payment.amp.RootShare, payment.amp.SetID, addr,
×
1002
                        payment.Amount,
×
1003
                )
×
1004

1005
        // Otherwise we'll use the simple tracker that will map each attempt to
1006
        // the same payment hash.
1007
        default:
12✔
1008
                shardTracker = shards.NewSimpleShardTracker(
12✔
1009
                        payment.Identifier(), nil,
12✔
1010
                )
12✔
1011
        }
1012

1013
        err = r.cfg.Control.InitPayment(payment.Identifier(), info)
12✔
1014
        if err != nil {
12✔
1015
                return nil, nil, err
×
1016
        }
×
1017

1018
        return paySession, shardTracker, nil
12✔
1019
}
1020

1021
// SendToRoute sends a payment using the provided route and fails the payment
1022
// when an error is returned from the attempt.
1023
func (r *ChannelRouter) SendToRoute(htlcHash lntypes.Hash, rt *route.Route,
1024
        firstHopCustomRecords lnwire.CustomRecords) (*channeldb.HTLCAttempt,
1025
        error) {
6✔
1026

6✔
1027
        return r.sendToRoute(htlcHash, rt, false, firstHopCustomRecords)
6✔
1028
}
6✔
1029

1030
// SendToRouteSkipTempErr sends a payment using the provided route and fails
1031
// the payment ONLY when a terminal error is returned from the attempt.
1032
func (r *ChannelRouter) SendToRouteSkipTempErr(htlcHash lntypes.Hash,
1033
        rt *route.Route,
1034
        firstHopCustomRecords lnwire.CustomRecords) (*channeldb.HTLCAttempt,
1035
        error) {
4✔
1036

4✔
1037
        return r.sendToRoute(htlcHash, rt, true, firstHopCustomRecords)
4✔
1038
}
4✔
1039

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

10✔
1051
        log.Debugf("SendToRoute for payment %v with skipTempErr=%v",
10✔
1052
                htlcHash, skipTempErr)
10✔
1053

10✔
1054
        // Calculate amount paid to receiver.
10✔
1055
        amt := rt.ReceiverAmt()
10✔
1056

10✔
1057
        // If this is meant as an MP payment shard, we set the amount for the
10✔
1058
        // creating info to the total amount of the payment.
10✔
1059
        finalHop := rt.Hops[len(rt.Hops)-1]
10✔
1060
        mpp := finalHop.MPP
10✔
1061
        if mpp != nil {
14✔
1062
                amt = mpp.TotalMsat()
4✔
1063
        }
4✔
1064

1065
        // For non-MPP, there's no such thing as temp error as there's only one
1066
        // HTLC attempt being made. When this HTLC is failed, the payment is
1067
        // failed hence cannot be retried.
1068
        if skipTempErr && mpp == nil {
11✔
1069
                return nil, ErrSkipTempErr
1✔
1070
        }
1✔
1071

1072
        // For non-AMP payments the overall payment identifier will be the same
1073
        // hash as used for this HTLC.
1074
        paymentIdentifier := htlcHash
9✔
1075

9✔
1076
        // For AMP-payments, we'll use the setID as the unique ID for the
9✔
1077
        // overall payment.
9✔
1078
        amp := finalHop.AMP
9✔
1079
        if amp != nil {
9✔
1080
                paymentIdentifier = amp.SetID()
×
1081
        }
×
1082

1083
        // Record this payment hash with the ControlTower, ensuring it is not
1084
        // already in-flight.
1085
        info := &channeldb.PaymentCreationInfo{
9✔
1086
                PaymentIdentifier:     paymentIdentifier,
9✔
1087
                Value:                 amt,
9✔
1088
                CreationTime:          r.cfg.Clock.Now(),
9✔
1089
                PaymentRequest:        nil,
9✔
1090
                FirstHopCustomRecords: firstHopCustomRecords,
9✔
1091
        }
9✔
1092

9✔
1093
        err := r.cfg.Control.InitPayment(paymentIdentifier, info)
9✔
1094
        switch {
9✔
1095
        // If this is an MPP attempt and the hash is already registered with
1096
        // the database, we can go on to launch the shard.
1097
        case mpp != nil && errors.Is(err, channeldb.ErrPaymentInFlight):
×
1098
        case mpp != nil && errors.Is(err, channeldb.ErrPaymentExists):
×
1099

1100
        // Any other error is not tolerated.
1101
        case err != nil:
×
1102
                return nil, err
×
1103
        }
1104

1105
        log.Tracef("Dispatching SendToRoute for HTLC hash %v: %v", htlcHash,
9✔
1106
                lnutils.SpewLogClosure(rt))
9✔
1107

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

9✔
1115
        // Create a payment lifecycle using the given route with,
9✔
1116
        // - zero fee limit as we are not requesting routes.
9✔
1117
        // - nil payment session (since we already have a route).
9✔
1118
        // - no payment timeout.
9✔
1119
        // - no current block height.
9✔
1120
        p := newPaymentLifecycle(
9✔
1121
                r, 0, paymentIdentifier, nil, shardTracker, 0,
9✔
1122
                firstHopCustomRecords,
9✔
1123
        )
9✔
1124

9✔
1125
        // Allow the traffic shaper to add custom records to the outgoing HTLC
9✔
1126
        // and also adjust the amount if needed.
9✔
1127
        err = p.amendFirstHopData(rt)
9✔
1128
        if err != nil {
9✔
1129
                return nil, err
×
1130
        }
×
1131

1132
        // We found a route to try, create a new HTLC attempt to try.
1133
        //
1134
        // NOTE: we use zero `remainingAmt` here to simulate the same effect of
1135
        // setting the lastShard to be false, which is used by previous
1136
        // implementation.
1137
        attempt, err := p.registerAttempt(rt, 0)
9✔
1138
        if err != nil {
10✔
1139
                return nil, err
1✔
1140
        }
1✔
1141

1142
        // Once the attempt is created, send it to the htlcswitch. Notice that
1143
        // the `err` returned here has already been processed by
1144
        // `handleSwitchErr`, which means if there's a terminal failure, the
1145
        // payment has been failed.
1146
        result, err := p.sendAttempt(attempt)
8✔
1147
        if err != nil {
8✔
1148
                return nil, err
×
1149
        }
×
1150

1151
        // We now look up the payment to see if it's already failed.
1152
        payment, err := p.router.cfg.Control.FetchPayment(p.identifier)
8✔
1153
        if err != nil {
8✔
1154
                return result.attempt, err
×
1155
        }
×
1156

1157
        // Exit if the above error has caused the payment to be failed, we also
1158
        // return the error from sending attempt to mimic the old behavior of
1159
        // this method.
1160
        _, failedReason := payment.TerminalInfo()
8✔
1161
        if failedReason != nil {
9✔
1162
                return result.attempt, result.err
1✔
1163
        }
1✔
1164

1165
        // Since for SendToRoute we won't retry in case the shard fails, we'll
1166
        // mark the payment failed with the control tower immediately if the
1167
        // skipTempErr is false.
1168
        reason := channeldb.FailureReasonError
7✔
1169

7✔
1170
        // If we failed to send the HTLC, we need to further decide if we want
7✔
1171
        // to fail the payment.
7✔
1172
        if result.err != nil {
9✔
1173
                // If skipTempErr, we'll return the attempt and the temp error.
2✔
1174
                if skipTempErr {
3✔
1175
                        return result.attempt, result.err
1✔
1176
                }
1✔
1177

1178
                // Otherwise we need to fail the payment.
1179
                err := r.cfg.Control.FailPayment(paymentIdentifier, reason)
1✔
1180
                if err != nil {
1✔
1181
                        return nil, err
×
1182
                }
×
1183

1184
                return result.attempt, result.err
1✔
1185
        }
1186

1187
        // The attempt was successfully sent, wait for the result to be
1188
        // available.
1189
        result, err = p.collectAndHandleResult(attempt)
5✔
1190
        if err != nil {
5✔
1191
                return nil, err
×
1192
        }
×
1193

1194
        // We got a successful result.
1195
        if result.err == nil {
6✔
1196
                return result.attempt, nil
1✔
1197
        }
1✔
1198

1199
        // An error returned from collecting the result, we'll mark the payment
1200
        // as failed if we don't skip temp error.
1201
        if !skipTempErr {
8✔
1202
                err := r.cfg.Control.FailPayment(paymentIdentifier, reason)
4✔
1203
                if err != nil {
4✔
1204
                        return nil, err
×
1205
                }
×
1206
        }
1207

1208
        return result.attempt, result.err
4✔
1209
}
1210

1211
// sendPayment attempts to send a payment to the passed payment hash. This
1212
// function is blocking and will return either: when the payment is successful,
1213
// or all candidates routes have been attempted and resulted in a failed
1214
// payment. If the payment succeeds, then a non-nil Route will be returned
1215
// which describes the path the successful payment traversed within the network
1216
// to reach the destination. Additionally, the payment preimage will also be
1217
// returned.
1218
//
1219
// This method relies on the ControlTower's internal payment state machine to
1220
// carry out its execution. After restarts, it is safe, and assumed, that the
1221
// router will call this method for every payment still in-flight according to
1222
// the ControlTower.
1223
func (r *ChannelRouter) sendPayment(ctx context.Context,
1224
        feeLimit lnwire.MilliSatoshi, identifier lntypes.Hash,
1225
        paymentAttemptTimeout time.Duration, paySession PaymentSession,
1226
        shardTracker shards.ShardTracker,
1227
        firstHopCustomRecords lnwire.CustomRecords) ([32]byte, *route.Route,
1228
        error) {
12✔
1229

12✔
1230
        // If the user provides a timeout, we will additionally wrap the context
12✔
1231
        // in a deadline.
12✔
1232
        cancel := func() {}
24✔
1233
        if paymentAttemptTimeout > 0 {
12✔
1234
                ctx, cancel = context.WithTimeout(ctx, paymentAttemptTimeout)
×
1235
        }
×
1236

1237
        // Since resumePayment is a blocking call, we'll cancel this
1238
        // context if the payment completes before the optional
1239
        // deadline.
1240
        defer cancel()
12✔
1241

12✔
1242
        // We'll also fetch the current block height, so we can properly
12✔
1243
        // calculate the required HTLC time locks within the route.
12✔
1244
        _, currentHeight, err := r.cfg.Chain.GetBestBlock()
12✔
1245
        if err != nil {
12✔
1246
                return [32]byte{}, nil, err
×
1247
        }
×
1248

1249
        // Validate the custom records before we attempt to send the payment.
1250
        if err := firstHopCustomRecords.Validate(); err != nil {
12✔
1251
                return [32]byte{}, nil, err
×
1252
        }
×
1253

1254
        // Now set up a paymentLifecycle struct with these params, such that we
1255
        // can resume the payment from the current state.
1256
        p := newPaymentLifecycle(
12✔
1257
                r, feeLimit, identifier, paySession, shardTracker,
12✔
1258
                currentHeight, firstHopCustomRecords,
12✔
1259
        )
12✔
1260

12✔
1261
        return p.resumePayment(ctx)
12✔
1262
}
1263

1264
// extractChannelUpdate examines the error and extracts the channel update.
1265
func (r *ChannelRouter) extractChannelUpdate(
1266
        failure lnwire.FailureMessage) *lnwire.ChannelUpdate1 {
17✔
1267

17✔
1268
        var update *lnwire.ChannelUpdate1
17✔
1269
        switch onionErr := failure.(type) {
17✔
1270
        case *lnwire.FailExpiryTooSoon:
1✔
1271
                update = &onionErr.Update
1✔
1272
        case *lnwire.FailAmountBelowMinimum:
×
1273
                update = &onionErr.Update
×
1274
        case *lnwire.FailFeeInsufficient:
7✔
1275
                update = &onionErr.Update
7✔
1276
        case *lnwire.FailIncorrectCltvExpiry:
×
1277
                update = &onionErr.Update
×
1278
        case *lnwire.FailChannelDisabled:
×
1279
                update = &onionErr.Update
×
1280
        case *lnwire.FailTemporaryChannelFailure:
5✔
1281
                update = onionErr.Update
5✔
1282
        }
1283

1284
        return update
17✔
1285
}
1286

1287
// ErrNoChannel is returned when a route cannot be built because there are no
1288
// channels that satisfy all requirements.
1289
type ErrNoChannel struct {
1290
        position int
1291
}
1292

1293
// Error returns a human-readable string describing the error.
1294
func (e ErrNoChannel) Error() string {
1✔
1295
        return fmt.Sprintf("no matching outgoing channel available for "+
1✔
1296
                "node index %v", e.position)
1✔
1297
}
1✔
1298

1299
// BuildRoute returns a fully specified route based on a list of pubkeys. If
1300
// amount is nil, the minimum routable amount is used. To force a specific
1301
// outgoing channel, use the outgoingChan parameter.
1302
func (r *ChannelRouter) BuildRoute(amt fn.Option[lnwire.MilliSatoshi],
1303
        hops []route.Vertex, outgoingChan *uint64, finalCltvDelta int32,
1304
        payAddr fn.Option[[32]byte], firstHopBlob fn.Option[[]byte]) (
1305
        *route.Route, error) {
8✔
1306

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

8✔
1309
        var outgoingChans map[uint64]struct{}
8✔
1310
        if outgoingChan != nil {
8✔
1311
                outgoingChans = map[uint64]struct{}{
×
1312
                        *outgoingChan: {},
×
1313
                }
×
1314
        }
×
1315

1316
        // We'll attempt to obtain a set of bandwidth hints that helps us select
1317
        // the best outgoing channel to use in case no outgoing channel is set.
1318
        bandwidthHints, err := newBandwidthManager(
8✔
1319
                r.cfg.RoutingGraph, r.cfg.SelfNode, r.cfg.GetLink, firstHopBlob,
8✔
1320
                r.cfg.TrafficShaper,
8✔
1321
        )
8✔
1322
        if err != nil {
8✔
1323
                return nil, err
×
1324
        }
×
1325

1326
        sourceNode := r.cfg.SelfNode
8✔
1327

8✔
1328
        // We check that each node in the route has a connection to others that
8✔
1329
        // can forward in principle.
8✔
1330
        unifiers, err := getEdgeUnifiers(
8✔
1331
                r.cfg.SelfNode, hops, outgoingChans, r.cfg.RoutingGraph,
8✔
1332
        )
8✔
1333
        if err != nil {
9✔
1334
                return nil, err
1✔
1335
        }
1✔
1336

1337
        var (
7✔
1338
                receiverAmt lnwire.MilliSatoshi
7✔
1339
                senderAmt   lnwire.MilliSatoshi
7✔
1340
                pathEdges   []*unifiedEdge
7✔
1341
        )
7✔
1342

7✔
1343
        // We determine the edges compatible with the requested amount, as well
7✔
1344
        // as the amount to send, which can be used to determine the final
7✔
1345
        // receiver amount, if a minimal amount was requested.
7✔
1346
        pathEdges, senderAmt, err = senderAmtBackwardPass(
7✔
1347
                unifiers, amt, bandwidthHints,
7✔
1348
        )
7✔
1349
        if err != nil {
9✔
1350
                return nil, err
2✔
1351
        }
2✔
1352

1353
        // For the minimal amount search, we need to do a forward pass to find a
1354
        // larger receiver amount due to possible min HTLC bumps, otherwise we
1355
        // just use the requested amount.
1356
        receiverAmt, err = fn.ElimOption(
5✔
1357
                amt,
5✔
1358
                func() fn.Result[lnwire.MilliSatoshi] {
8✔
1359
                        return fn.NewResult(
3✔
1360
                                receiverAmtForwardPass(senderAmt, pathEdges),
3✔
1361
                        )
3✔
1362
                },
3✔
1363
                fn.Ok[lnwire.MilliSatoshi],
1364
        ).Unpack()
1365
        if err != nil {
5✔
1366
                return nil, err
×
1367
        }
×
1368

1369
        // Fetch the current block height outside the routing transaction, to
1370
        // prevent the rpc call blocking the database.
1371
        _, height, err := r.cfg.Chain.GetBestBlock()
5✔
1372
        if err != nil {
5✔
1373
                return nil, err
×
1374
        }
×
1375

1376
        // Build and return the final route.
1377
        return newRoute(
5✔
1378
                sourceNode, pathEdges, uint32(height),
5✔
1379
                finalHopParams{
5✔
1380
                        amt:         receiverAmt,
5✔
1381
                        totalAmt:    receiverAmt,
5✔
1382
                        cltvDelta:   uint16(finalCltvDelta),
5✔
1383
                        records:     nil,
5✔
1384
                        paymentAddr: payAddr,
5✔
1385
                }, nil,
5✔
1386
        )
5✔
1387
}
1388

1389
// resumePayments fetches inflight payments and resumes their payment
1390
// lifecycles.
1391
func (r *ChannelRouter) resumePayments() error {
17✔
1392
        // Get all payments that are inflight.
17✔
1393
        payments, err := r.cfg.Control.FetchInFlightPayments()
17✔
1394
        if err != nil {
17✔
1395
                return err
×
1396
        }
×
1397

1398
        // Before we restart existing payments and start accepting more
1399
        // payments to be made, we clean the network result store of the
1400
        // Switch. We do this here at startup to ensure no more payments can be
1401
        // made concurrently, so we know the toKeep map will be up-to-date
1402
        // until the cleaning has finished.
1403
        toKeep := make(map[uint64]struct{})
17✔
1404
        for _, p := range payments {
17✔
1405
                for _, a := range p.HTLCs {
×
1406
                        toKeep[a.AttemptID] = struct{}{}
×
1407

×
1408
                        // Try to fail the attempt if the route contains a dead
×
1409
                        // channel.
×
1410
                        r.failStaleAttempt(a, p.Info.PaymentIdentifier)
×
1411
                }
×
1412
        }
1413

1414
        log.Debugf("Cleaning network result store.")
17✔
1415
        if err := r.cfg.Payer.CleanStore(toKeep); err != nil {
17✔
1416
                return err
×
1417
        }
×
1418

1419
        // launchPayment is a helper closure that handles resuming the payment.
1420
        launchPayment := func(payment *channeldb.MPPayment) {
17✔
1421
                defer r.wg.Done()
×
1422

×
1423
                // Get the hashes used for the outstanding HTLCs.
×
1424
                htlcs := make(map[uint64]lntypes.Hash)
×
1425
                for _, a := range payment.HTLCs {
×
1426
                        a := a
×
1427

×
1428
                        // We check whether the individual attempts have their
×
1429
                        // HTLC hash set, if not we'll fall back to the overall
×
1430
                        // payment hash.
×
1431
                        hash := payment.Info.PaymentIdentifier
×
1432
                        if a.Hash != nil {
×
1433
                                hash = *a.Hash
×
1434
                        }
×
1435

1436
                        htlcs[a.AttemptID] = hash
×
1437
                }
1438

1439
                payHash := payment.Info.PaymentIdentifier
×
1440

×
1441
                // Since we are not supporting creating more shards after a
×
1442
                // restart (only receiving the result of the shards already
×
1443
                // outstanding), we create a simple shard tracker that will map
×
1444
                // the attempt IDs to hashes used for the HTLCs. This will be
×
1445
                // enough also for AMP payments, since we only need the hashes
×
1446
                // for the individual HTLCs to regenerate the circuits, and we
×
1447
                // don't currently persist the root share necessary to
×
1448
                // re-derive them.
×
1449
                shardTracker := shards.NewSimpleShardTracker(payHash, htlcs)
×
1450

×
1451
                // We create a dummy, empty payment session such that we won't
×
1452
                // make another payment attempt when the result for the
×
1453
                // in-flight attempt is received.
×
1454
                paySession := r.cfg.SessionSource.NewPaymentSessionEmpty()
×
1455

×
1456
                // We pass in a non-timeout context, to indicate we don't need
×
1457
                // it to timeout. It will stop immediately after the existing
×
1458
                // attempt has finished anyway. We also set a zero fee limit,
×
1459
                // as no more routes should be tried.
×
1460
                noTimeout := time.Duration(0)
×
1461
                _, _, err := r.sendPayment(
×
1462
                        context.Background(), 0, payHash, noTimeout, paySession,
×
1463
                        shardTracker, payment.Info.FirstHopCustomRecords,
×
1464
                )
×
1465
                if err != nil {
×
1466
                        log.Errorf("Resuming payment %v failed: %v", payHash,
×
1467
                                err)
×
1468

×
1469
                        return
×
1470
                }
×
1471

1472
                log.Infof("Resumed payment %v completed", payHash)
×
1473
        }
1474

1475
        for _, payment := range payments {
17✔
1476
                log.Infof("Resuming payment %v", payment.Info.PaymentIdentifier)
×
1477

×
1478
                r.wg.Add(1)
×
1479
                go launchPayment(payment)
×
1480
        }
×
1481

1482
        return nil
17✔
1483
}
1484

1485
// failStaleAttempt will fail an HTLC attempt if it's using an unknown channel
1486
// in its route. It first consults the switch to see if there's already a
1487
// network result stored for this attempt. If not, it will check whether the
1488
// first hop of this attempt is using an active channel known to us. If
1489
// inactive, this attempt will be failed.
1490
//
1491
// NOTE: there's an unknown bug that caused the network result for a particular
1492
// attempt to NOT be saved, resulting a payment being stuck forever. More info:
1493
// - https://github.com/lightningnetwork/lnd/issues/8146
1494
// - https://github.com/lightningnetwork/lnd/pull/8174
1495
func (r *ChannelRouter) failStaleAttempt(a channeldb.HTLCAttempt,
1496
        payHash lntypes.Hash) {
×
1497

×
1498
        // We can only fail inflight HTLCs so we skip the settled/failed ones.
×
1499
        if a.Failure != nil || a.Settle != nil {
×
1500
                return
×
1501
        }
×
1502

1503
        // First, check if we've already had a network result for this attempt.
1504
        // If no result is found, we'll check whether the reference link is
1505
        // still known to us.
1506
        ok, err := r.cfg.Payer.HasAttemptResult(a.AttemptID)
×
1507
        if err != nil {
×
1508
                log.Errorf("Failed to fetch network result for attempt=%v",
×
1509
                        a.AttemptID)
×
1510
                return
×
1511
        }
×
1512

1513
        // There's already a network result, no need to fail it here as the
1514
        // payment lifecycle will take care of it, so we can exit early.
1515
        if ok {
×
1516
                log.Debugf("Already have network result for attempt=%v",
×
1517
                        a.AttemptID)
×
1518
                return
×
1519
        }
×
1520

1521
        // We now need to decide whether this attempt should be failed here.
1522
        // For very old payments, it's possible that the network results were
1523
        // never saved, causing the payments to be stuck inflight. We now check
1524
        // whether the first hop is referencing an active channel ID and, if
1525
        // not, we will fail the attempt as it has no way to be retried again.
1526
        var shouldFail bool
×
1527

×
1528
        // Validate that the attempt has hop info. If this attempt has no hop
×
1529
        // info it indicates an error in our db.
×
1530
        if len(a.Route.Hops) == 0 {
×
1531
                log.Errorf("Found empty hop for attempt=%v", a.AttemptID)
×
1532

×
1533
                shouldFail = true
×
1534
        } else {
×
1535
                // Get the short channel ID.
×
1536
                chanID := a.Route.Hops[0].ChannelID
×
1537
                scid := lnwire.NewShortChanIDFromInt(chanID)
×
1538

×
1539
                // Check whether this link is active. If so, we won't fail the
×
1540
                // attempt but keep waiting for its result.
×
1541
                _, err := r.cfg.GetLink(scid)
×
1542
                if err == nil {
×
1543
                        return
×
1544
                }
×
1545

1546
                // We should get the link not found err. If not, we will log an
1547
                // error and skip failing this attempt since an unknown error
1548
                // occurred.
1549
                if !errors.Is(err, htlcswitch.ErrChannelLinkNotFound) {
×
1550
                        log.Errorf("Failed to get link for attempt=%v for "+
×
1551
                                "payment=%v: %v", a.AttemptID, payHash, err)
×
1552

×
1553
                        return
×
1554
                }
×
1555

1556
                // The channel link is not active, we now check whether this
1557
                // channel is already closed. If so, we fail the HTLC attempt
1558
                // as there's no need to wait for its network result because
1559
                // there's no link. If the channel is still pending, we'll keep
1560
                // waiting for the result as we may get a contract resolution
1561
                // for this HTLC.
1562
                if _, ok := r.cfg.ClosedSCIDs[scid]; ok {
×
1563
                        shouldFail = true
×
1564
                }
×
1565
        }
1566

1567
        // Exit if there's no need to fail.
1568
        if !shouldFail {
×
1569
                return
×
1570
        }
×
1571

1572
        log.Errorf("Failing stale attempt=%v for payment=%v", a.AttemptID,
×
1573
                payHash)
×
1574

×
1575
        // Fail the attempt in db. If there's an error, there's nothing we can
×
1576
        // do here but logging it.
×
1577
        failInfo := &channeldb.HTLCFailInfo{
×
1578
                Reason:   channeldb.HTLCFailUnknown,
×
1579
                FailTime: r.cfg.Clock.Now(),
×
1580
        }
×
1581
        _, err = r.cfg.Control.FailAttempt(payHash, a.AttemptID, failInfo)
×
1582
        if err != nil {
×
1583
                log.Errorf("Fail attempt=%v got error: %v", a.AttemptID, err)
×
1584
        }
×
1585
}
1586

1587
// getEdgeUnifiers returns a list of edge unifiers for the given route.
1588
func getEdgeUnifiers(source route.Vertex, hops []route.Vertex,
1589
        outgoingChans map[uint64]struct{},
1590
        graph Graph) ([]*edgeUnifier, error) {
8✔
1591

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

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

13✔
1599
                var fromNode route.Vertex
13✔
1600
                if i == 0 {
19✔
1601
                        fromNode = source
6✔
1602
                } else {
13✔
1603
                        fromNode = hops[i-1]
7✔
1604
                }
7✔
1605

1606
                // Build unified policies for this hop based on the channels
1607
                // known in the graph. Inbound fees are only active if the edge
1608
                // is not the last hop.
1609
                isExitHop := i == len(hops)-1
13✔
1610
                u := newNodeEdgeUnifier(
13✔
1611
                        source, toNode, !isExitHop, outgoingChans,
13✔
1612
                )
13✔
1613

13✔
1614
                err := u.addGraphPolicies(graph)
13✔
1615
                if err != nil {
13✔
1616
                        return nil, err
×
1617
                }
×
1618

1619
                // Exit if there are no channels.
1620
                edgeUnifier, ok := u.edgeUnifiers[fromNode]
13✔
1621
                if !ok {
14✔
1622
                        log.Errorf("Cannot find policy for node %v", fromNode)
1✔
1623
                        return nil, ErrNoChannel{position: i}
1✔
1624
                }
1✔
1625

1626
                unifiers[i] = edgeUnifier
12✔
1627
        }
1628

1629
        return unifiers, nil
7✔
1630
}
1631

1632
// senderAmtBackwardPass returns a list of unified edges for the given route and
1633
// determines the amount that should be sent to fulfill min HTLC requirements.
1634
// The minimal sender amount can be searched for by using amt=None.
1635
func senderAmtBackwardPass(unifiers []*edgeUnifier,
1636
        amt fn.Option[lnwire.MilliSatoshi],
1637
        bandwidthHints bandwidthHints) ([]*unifiedEdge, lnwire.MilliSatoshi,
1638
        error) {
11✔
1639

11✔
1640
        if len(unifiers) == 0 {
12✔
1641
                return nil, 0, fmt.Errorf("no unifiers provided")
1✔
1642
        }
1✔
1643

1644
        var unifiedEdges = make([]*unifiedEdge, len(unifiers))
10✔
1645

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

10✔
1649
        // incomingAmt tracks the amount that is forwarded on the edges of a
10✔
1650
        // route. The last hop only forwards the amount that the receiver should
10✔
1651
        // receive, as there are no fees paid to the last node.
10✔
1652
        // For minimum amount routes, aim to deliver at least 1 msat to
10✔
1653
        // the destination. There are nodes in the wild that have a
10✔
1654
        // min_htlc channel policy of zero, which could lead to a zero
10✔
1655
        // amount payment being made.
10✔
1656
        incomingAmt := amt.UnwrapOr(1)
10✔
1657

10✔
1658
        // If using min amt, increase the amount if needed to fulfill min HTLC
10✔
1659
        // requirements.
10✔
1660
        if amt.IsNone() {
15✔
1661
                min := edgeUnifier.minAmt()
5✔
1662
                if min > incomingAmt {
10✔
1663
                        incomingAmt = min
5✔
1664
                }
5✔
1665
        }
1666

1667
        // Get an edge for the specific amount that we want to forward.
1668
        edge := edgeUnifier.getEdge(incomingAmt, bandwidthHints, 0)
10✔
1669
        if edge == nil {
11✔
1670
                log.Errorf("Cannot find policy with amt=%v "+
1✔
1671
                        "for hop %v", incomingAmt, len(unifiers)-1)
1✔
1672

1✔
1673
                return nil, 0, ErrNoChannel{position: len(unifiers) - 1}
1✔
1674
        }
1✔
1675

1676
        unifiedEdges[len(unifiers)-1] = edge
9✔
1677

9✔
1678
        // Handle the rest of the route except the last hop.
9✔
1679
        for i := len(unifiers) - 2; i >= 0; i-- {
21✔
1680
                edgeUnifier = unifiers[i]
12✔
1681

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

1691
                // A --current hop-- B --next hop: incomingAmt-- C
1692
                // The outbound fee paid to the current end node B is based on
1693
                // the amount that the next hop forwards and B's policy for that
1694
                // hop.
1695
                outboundFee := unifiedEdges[i+1].policy.ComputeFee(
12✔
1696
                        incomingAmt,
12✔
1697
                )
12✔
1698

12✔
1699
                netAmount := incomingAmt + outboundFee
12✔
1700

12✔
1701
                // We need to select an edge that can forward the requested
12✔
1702
                // amount.
12✔
1703
                edge = edgeUnifier.getEdge(
12✔
1704
                        netAmount, bandwidthHints, outboundFee,
12✔
1705
                )
12✔
1706
                if edge == nil {
13✔
1707
                        return nil, 0, ErrNoChannel{position: i}
1✔
1708
                }
1✔
1709

1710
                // The fee paid to B depends on the current hop's inbound fee
1711
                // policy and on the outbound fee for the next hop as any
1712
                // inbound fee discount is capped by the outbound fee such that
1713
                // the total fee for B can't become negative.
1714
                inboundFee := calcCappedInboundFee(edge, netAmount, outboundFee)
11✔
1715

11✔
1716
                fee := lnwire.MilliSatoshi(int64(outboundFee) + inboundFee)
11✔
1717

11✔
1718
                log.Tracef("Select channel %v at position %v",
11✔
1719
                        edge.policy.ChannelID, i)
11✔
1720

11✔
1721
                // Finally, we update the amount that needs to flow into node B
11✔
1722
                // from A, which is the next hop's forwarding amount plus the
11✔
1723
                // fee for B: A --current hop: incomingAmt-- B --next hop-- C
11✔
1724
                incomingAmt += fee
11✔
1725

11✔
1726
                unifiedEdges[i] = edge
11✔
1727
        }
1728

1729
        return unifiedEdges, incomingAmt, nil
8✔
1730
}
1731

1732
// receiverAmtForwardPass returns the amount that a receiver will receive after
1733
// deducting all fees from the sender amount.
1734
func receiverAmtForwardPass(runningAmt lnwire.MilliSatoshi,
1735
        unifiedEdges []*unifiedEdge) (lnwire.MilliSatoshi, error) {
10✔
1736

10✔
1737
        if len(unifiedEdges) == 0 {
11✔
1738
                return 0, fmt.Errorf("no edges to forward through")
1✔
1739
        }
1✔
1740

1741
        inEdge := unifiedEdges[0]
9✔
1742
        if !inEdge.amtInRange(runningAmt) {
10✔
1743
                log.Errorf("Amount %v not in range for hop index %v",
1✔
1744
                        runningAmt, 0)
1✔
1745

1✔
1746
                return 0, ErrNoChannel{position: 0}
1✔
1747
        }
1✔
1748

1749
        // Now that we arrived at the start of the route and found out the route
1750
        // total amount, we make a forward pass. Because the amount may have
1751
        // been increased in the backward pass, fees need to be recalculated and
1752
        // amount ranges re-checked.
1753
        for i := 1; i < len(unifiedEdges); i++ {
17✔
1754
                inEdge := unifiedEdges[i-1]
9✔
1755
                outEdge := unifiedEdges[i]
9✔
1756

9✔
1757
                // Decrease the amount to send while going forward.
9✔
1758
                runningAmt = outgoingFromIncoming(runningAmt, inEdge, outEdge)
9✔
1759

9✔
1760
                if !outEdge.amtInRange(runningAmt) {
9✔
1761
                        log.Errorf("Amount %v not in range for hop index %v",
×
1762
                                runningAmt, i)
×
1763

×
1764
                        return 0, ErrNoChannel{position: i}
×
1765
                }
×
1766
        }
1767

1768
        return runningAmt, nil
8✔
1769
}
1770

1771
// incomingFromOutgoing computes the incoming amount based on the outgoing
1772
// amount by adding fees to the outgoing amount, replicating the path finding
1773
// and routing process, see also CheckHtlcForward.
1774
func incomingFromOutgoing(outgoingAmt lnwire.MilliSatoshi,
1775
        incoming, outgoing *unifiedEdge) lnwire.MilliSatoshi {
31✔
1776

31✔
1777
        outgoingFee := outgoing.policy.ComputeFee(outgoingAmt)
31✔
1778

31✔
1779
        // Net amount is the amount the inbound fees are calculated with.
31✔
1780
        netAmount := outgoingAmt + outgoingFee
31✔
1781

31✔
1782
        inboundFee := incoming.inboundFees.CalcFee(netAmount)
31✔
1783

31✔
1784
        // The inbound fee is not allowed to reduce the incoming amount below
31✔
1785
        // the outgoing amount.
31✔
1786
        if int64(outgoingFee)+inboundFee < 0 {
40✔
1787
                return outgoingAmt
9✔
1788
        }
9✔
1789

1790
        return netAmount + lnwire.MilliSatoshi(inboundFee)
22✔
1791
}
1792

1793
// outgoingFromIncoming computes the outgoing amount based on the incoming
1794
// amount by subtracting fees from the incoming amount. Note that this is not
1795
// exactly the inverse of incomingFromOutgoing, because of some rounding.
1796
func outgoingFromIncoming(incomingAmt lnwire.MilliSatoshi,
1797
        incoming, outgoing *unifiedEdge) lnwire.MilliSatoshi {
40✔
1798

40✔
1799
        // Convert all quantities to big.Int to be able to hande negative
40✔
1800
        // values. The formulas to compute the outgoing amount involve terms
40✔
1801
        // with PPM*PPM*A, which can easily overflow an int64.
40✔
1802
        A := big.NewInt(int64(incomingAmt))
40✔
1803
        Ro := big.NewInt(int64(outgoing.policy.FeeProportionalMillionths))
40✔
1804
        Bo := big.NewInt(int64(outgoing.policy.FeeBaseMSat))
40✔
1805
        Ri := big.NewInt(int64(incoming.inboundFees.Rate))
40✔
1806
        Bi := big.NewInt(int64(incoming.inboundFees.Base))
40✔
1807
        PPM := big.NewInt(1_000_000)
40✔
1808

40✔
1809
        // The following discussion was contributed by user feelancer21, see
40✔
1810
        //nolint:ll
40✔
1811
        // https://github.com/feelancer21/lnd/commit/f6f05fa930985aac0d27c3f6681aada1b599162a.
40✔
1812

40✔
1813
        // The incoming amount Ai based on the outgoing amount Ao is computed by
40✔
1814
        // Ai = max(Ai(Ao), Ao), which caps the incoming amount such that the
40✔
1815
        // total node fee (Ai - Ao) is non-negative. This is commonly enforced
40✔
1816
        // by routing nodes.
40✔
1817

40✔
1818
        // The function Ai(Ao) is given by:
40✔
1819
        // Ai(Ao) = (Ao + Bo + Ro/PPM) + (Bi + (Ao + Ro/PPM + Bo)*Ri/PPM), where
40✔
1820
        // the first term is the net amount (the outgoing amount plus the
40✔
1821
        // outbound fee), and the second is the inbound fee computed based on
40✔
1822
        // the net amount.
40✔
1823

40✔
1824
        // Ai(Ao) can potentially become more negative in absolute value than
40✔
1825
        // Ao, which is why the above mentioned capping is needed. We can
40✔
1826
        // abbreviate Ai(Ao) with Ai(Ao) = m*Ao + n, where m and n are:
40✔
1827
        // m := (1 + Ro/PPM) * (1 + Ri/PPM)
40✔
1828
        // n := Bi + Bo*(1 + Ri/PPM)
40✔
1829

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

40✔
1836
        // If we want to compute the incoming amount based on the outgoing
40✔
1837
        // amount, which is the reverse problem, we need to solve Ai =
40✔
1838
        // max(Ai(Ao), Ao) for Ao(Ai). Given an incoming amount A,
40✔
1839
        // we look for an Ao such that A = max(Ai(Ao), Ao).
40✔
1840

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

40✔
1845
        // first case: Ai(Ao) <= Ao:
40✔
1846
        // Therefore, A = max(Ai(Ao), Ao) = Ao, we find Ao = A.
40✔
1847
        // This also leads to Ai(A) <= A by substitution into the condition.
40✔
1848

40✔
1849
        // second case: Ai(Ao) > Ao:
40✔
1850
        // Therefore, A = max(Ai(Ao), Ao) = Ai(Ao) = m*Ao + n. Solving for Ao
40✔
1851
        // gives Ao = (A - n)/m.
40✔
1852
        //
40✔
1853
        // We know
40✔
1854
        // Ai(Ao) > Ao  <=>  A = Ai(Ao) > Ao = (A - n)/m,
40✔
1855
        // so A > (A - n)/m.
40✔
1856
        //
40✔
1857
        // **Assuming m > 0**, by multiplying with m, we can transform this to
40✔
1858
        // A * m + n > A.
40✔
1859
        //
40✔
1860
        // We know Ai(A) = A*m + n, therefore Ai(A) > A.
40✔
1861
        //
40✔
1862
        // This means that if we apply the incoming amount calculation to the
40✔
1863
        // **incoming** amount, and this condition holds, then we know that we
40✔
1864
        // deal with the second case, being able to compute the outgoing amount
40✔
1865
        // based off the formula Ao = (A - n)/m, otherwise we will just return
40✔
1866
        // the incoming amount.
40✔
1867

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

40✔
1872
        // We compute m in terms of big.Int to be safe from overflows and to be
40✔
1873
        // consistent with later calculations.
40✔
1874
        // m := (PPM*PPM + Ri*PPM + Ro*PPM + Ro*Ri)/(PPM*PPM)
40✔
1875

40✔
1876
        // Compute terms in (PPM*PPM + Ri*PPM + Ro*PPM + Ro*Ri).
40✔
1877
        m1 := new(big.Int).Mul(PPM, PPM)
40✔
1878
        m2 := new(big.Int).Mul(Ri, PPM)
40✔
1879
        m3 := new(big.Int).Mul(Ro, PPM)
40✔
1880
        m4 := new(big.Int).Mul(Ro, Ri)
40✔
1881

40✔
1882
        // Add up terms m1..m4.
40✔
1883
        m := big.NewInt(0)
40✔
1884
        m.Add(m, m1)
40✔
1885
        m.Add(m, m2)
40✔
1886
        m.Add(m, m3)
40✔
1887
        m.Add(m, m4)
40✔
1888

40✔
1889
        // Since we compare to 0, we can multiply by PPM*PPM to avoid the
40✔
1890
        // division.
40✔
1891
        if m.Int64() <= 0 {
42✔
1892
                return incomingAmt
2✔
1893
        }
2✔
1894

1895
        // In order to decide if the total fee is negative, we apply the fee
1896
        // to the *incoming* amount as mentioned before.
1897

1898
        // We compute the test amount in terms of big.Int to be safe from
1899
        // overflows and to be consistent later calculations.
1900
        // testAmtF := A*m + n =
1901
        // = A + Bo + Bi + (PPM*(A*Ri + A*Ro + Ro*Ri) + A*Ri*Ro)/(PPM*PPM)
1902

1903
        // Compute terms in (A*Ri + A*Ro + Ro*Ri).
1904
        t1 := new(big.Int).Mul(A, Ri)
38✔
1905
        t2 := new(big.Int).Mul(A, Ro)
38✔
1906
        t3 := new(big.Int).Mul(Ro, Ri)
38✔
1907

38✔
1908
        // Sum up terms t1-t3.
38✔
1909
        t4 := big.NewInt(0)
38✔
1910
        t4.Add(t4, t1)
38✔
1911
        t4.Add(t4, t2)
38✔
1912
        t4.Add(t4, t3)
38✔
1913

38✔
1914
        // Compute PPM*(A*Ri + A*Ro + Ro*Ri).
38✔
1915
        t6 := new(big.Int).Mul(PPM, t4)
38✔
1916

38✔
1917
        // Compute A*Ri*Ro.
38✔
1918
        t7 := new(big.Int).Mul(A, Ri)
38✔
1919
        t7.Mul(t7, Ro)
38✔
1920

38✔
1921
        // Compute (PPM*(A*Ri + A*Ro + Ro*Ri) + A*Ri*Ro)/(PPM*PPM).
38✔
1922
        num := new(big.Int).Add(t6, t7)
38✔
1923
        denom := new(big.Int).Mul(PPM, PPM)
38✔
1924
        fraction := new(big.Int).Div(num, denom)
38✔
1925

38✔
1926
        // Sum up all terms.
38✔
1927
        testAmt := big.NewInt(0)
38✔
1928
        testAmt.Add(testAmt, A)
38✔
1929
        testAmt.Add(testAmt, Bo)
38✔
1930
        testAmt.Add(testAmt, Bi)
38✔
1931
        testAmt.Add(testAmt, fraction)
38✔
1932

38✔
1933
        // Protect against negative values for the integer cast to Msat.
38✔
1934
        if testAmt.Int64() < 0 {
42✔
1935
                return incomingAmt
4✔
1936
        }
4✔
1937

1938
        // If the second case holds, we have to compute the outgoing amount.
1939
        if lnwire.MilliSatoshi(testAmt.Int64()) > incomingAmt {
62✔
1940
                // Compute the outgoing amount by integer ceiling division. This
28✔
1941
                // precision is needed because PPM*PPM*A and other terms can
28✔
1942
                // easily overflow with int64, which happens with about
28✔
1943
                // A = 10_000 sat.
28✔
1944

28✔
1945
                // out := (A - n) / m = numerator / denominator
28✔
1946
                // numerator := PPM*(PPM*(A - Bo - Bi) - Bo*Ri)
28✔
1947
                // denominator := PPM*(PPM + Ri + Ro) + Ri*Ro
28✔
1948

28✔
1949
                var numerator big.Int
28✔
1950

28✔
1951
                // Compute (A - Bo - Bi).
28✔
1952
                temp1 := new(big.Int).Sub(A, Bo)
28✔
1953
                temp2 := new(big.Int).Sub(temp1, Bi)
28✔
1954

28✔
1955
                // Compute terms in (PPM*(A - Bo - Bi) - Bo*Ri).
28✔
1956
                temp3 := new(big.Int).Mul(PPM, temp2)
28✔
1957
                temp4 := new(big.Int).Mul(Bo, Ri)
28✔
1958

28✔
1959
                // Compute PPM*(PPM*(A - Bo - Bi) - Bo*Ri)
28✔
1960
                temp5 := new(big.Int).Sub(temp3, temp4)
28✔
1961
                numerator.Mul(PPM, temp5)
28✔
1962

28✔
1963
                var denominator big.Int
28✔
1964

28✔
1965
                // Compute (PPM + Ri + Ro).
28✔
1966
                temp1 = new(big.Int).Add(PPM, Ri)
28✔
1967
                temp2 = new(big.Int).Add(temp1, Ro)
28✔
1968

28✔
1969
                // Compute PPM*(PPM + Ri + Ro) + Ri*Ro.
28✔
1970
                temp3 = new(big.Int).Mul(PPM, temp2)
28✔
1971
                temp4 = new(big.Int).Mul(Ri, Ro)
28✔
1972
                denominator.Add(temp3, temp4)
28✔
1973

28✔
1974
                // We overestimate the outgoing amount by taking the ceiling of
28✔
1975
                // the division. This means that we may round slightly up by a
28✔
1976
                // MilliSatoshi, but this helps to ensure that we don't hit min
28✔
1977
                // HTLC constrains in the context of finding the minimum amount
28✔
1978
                // of a route.
28✔
1979
                // ceil = floor((numerator + denominator - 1) / denominator)
28✔
1980
                ceil := new(big.Int).Add(&numerator, &denominator)
28✔
1981
                ceil.Sub(ceil, big.NewInt(1))
28✔
1982
                ceil.Div(ceil, &denominator)
28✔
1983

28✔
1984
                return lnwire.MilliSatoshi(ceil.Int64())
28✔
1985
        }
28✔
1986

1987
        // Otherwise the inbound fee made up for the outbound fee, which is why
1988
        // we just return the incoming amount.
1989
        return incomingAmt
6✔
1990
}
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