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

lightningnetwork / lnd / 12026968820

26 Nov 2024 08:48AM UTC coverage: 49.896% (-9.1%) from 58.999%
12026968820

Pull #9303

github

yyforyongyu
lnwallet: add debug logs
Pull Request #9303: htlcswitch+routing: handle nil pointer dereference properly

20 of 23 new or added lines in 4 files covered. (86.96%)

25375 existing lines in 428 files now uncovered.

99993 of 200404 relevant lines covered (49.9%)

2.07 hits per line

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

69.2
/htlcswitch/link.go
1
package htlcswitch
2

3
import (
4
        "bytes"
5
        crand "crypto/rand"
6
        "crypto/sha256"
7
        "errors"
8
        "fmt"
9
        prand "math/rand"
10
        "sync"
11
        "sync/atomic"
12
        "time"
13

14
        "github.com/btcsuite/btcd/btcutil"
15
        "github.com/btcsuite/btcd/wire"
16
        "github.com/btcsuite/btclog/v2"
17
        "github.com/lightningnetwork/lnd/build"
18
        "github.com/lightningnetwork/lnd/channeldb"
19
        "github.com/lightningnetwork/lnd/channeldb/models"
20
        "github.com/lightningnetwork/lnd/contractcourt"
21
        "github.com/lightningnetwork/lnd/fn"
22
        "github.com/lightningnetwork/lnd/htlcswitch/hodl"
23
        "github.com/lightningnetwork/lnd/htlcswitch/hop"
24
        "github.com/lightningnetwork/lnd/input"
25
        "github.com/lightningnetwork/lnd/invoices"
26
        "github.com/lightningnetwork/lnd/lnpeer"
27
        "github.com/lightningnetwork/lnd/lntypes"
28
        "github.com/lightningnetwork/lnd/lnutils"
29
        "github.com/lightningnetwork/lnd/lnwallet"
30
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
31
        "github.com/lightningnetwork/lnd/lnwire"
32
        "github.com/lightningnetwork/lnd/queue"
33
        "github.com/lightningnetwork/lnd/ticker"
34
        "github.com/lightningnetwork/lnd/tlv"
35
)
36

37
func init() {
38
        prand.Seed(time.Now().UnixNano())
4✔
39
}
4✔
40

4✔
41
const (
42
        // DefaultMaxOutgoingCltvExpiry is the maximum outgoing time lock that
43
        // the node accepts for forwarded payments. The value is relative to the
44
        // current block height. The reason to have a maximum is to prevent
45
        // funds getting locked up unreasonably long. Otherwise, an attacker
46
        // willing to lock its own funds too, could force the funds of this node
47
        // to be locked up for an indefinite (max int32) number of blocks.
48
        //
49
        // The value 2016 corresponds to on average two weeks worth of blocks
50
        // and is based on the maximum number of hops (20), the default CLTV
51
        // delta (40), and some extra margin to account for the other lightning
52
        // implementations and past lnd versions which used to have a default
53
        // CLTV delta of 144.
54
        DefaultMaxOutgoingCltvExpiry = 2016
55

56
        // DefaultMinLinkFeeUpdateTimeout represents the minimum interval in
57
        // which a link should propose to update its commitment fee rate.
58
        DefaultMinLinkFeeUpdateTimeout = 10 * time.Minute
59

60
        // DefaultMaxLinkFeeUpdateTimeout represents the maximum interval in
61
        // which a link should propose to update its commitment fee rate.
62
        DefaultMaxLinkFeeUpdateTimeout = 60 * time.Minute
63

64
        // DefaultMaxLinkFeeAllocation is the highest allocation we'll allow
65
        // a channel's commitment fee to be of its balance. This only applies to
66
        // the initiator of the channel.
67
        DefaultMaxLinkFeeAllocation float64 = 0.5
68
)
69

70
// ExpectedFee computes the expected fee for a given htlc amount. The value
71
// returned from this function is to be used as a sanity check when forwarding
72
// HTLC's to ensure that an incoming HTLC properly adheres to our propagated
73
// forwarding policy.
74
//
75
// TODO(roasbeef): also add in current available channel bandwidth, inverse
76
// func
77
func ExpectedFee(f models.ForwardingPolicy,
78
        htlcAmt lnwire.MilliSatoshi) lnwire.MilliSatoshi {
79

4✔
80
        return f.BaseFee + (htlcAmt*f.FeeRate)/1000000
4✔
81
}
4✔
82

4✔
83
// ChannelLinkConfig defines the configuration for the channel link. ALL
84
// elements within the configuration MUST be non-nil for channel link to carry
85
// out its duties.
86
type ChannelLinkConfig struct {
87
        // FwrdingPolicy is the initial forwarding policy to be used when
88
        // deciding whether to forwarding incoming HTLC's or not. This value
89
        // can be updated with subsequent calls to UpdateForwardingPolicy
90
        // targeted at a given ChannelLink concrete interface implementation.
91
        FwrdingPolicy models.ForwardingPolicy
92

93
        // Circuits provides restricted access to the switch's circuit map,
94
        // allowing the link to open and close circuits.
95
        Circuits CircuitModifier
96

97
        // BestHeight returns the best known height.
98
        BestHeight func() uint32
99

100
        // ForwardPackets attempts to forward the batch of htlcs through the
101
        // switch. The function returns and error in case it fails to send one or
102
        // more packets. The link's quit signal should be provided to allow
103
        // cancellation of forwarding during link shutdown.
104
        ForwardPackets func(<-chan struct{}, bool, ...*htlcPacket) error
105

106
        // DecodeHopIterators facilitates batched decoding of HTLC Sphinx onion
107
        // blobs, which are then used to inform how to forward an HTLC.
108
        //
109
        // NOTE: This function assumes the same set of readers and preimages
110
        // are always presented for the same identifier.
111
        DecodeHopIterators func([]byte, []hop.DecodeHopIteratorRequest) (
112
                []hop.DecodeHopIteratorResponse, error)
113

114
        // ExtractErrorEncrypter function is responsible for decoding HTLC
115
        // Sphinx onion blob, and creating onion failure obfuscator.
116
        ExtractErrorEncrypter hop.ErrorEncrypterExtracter
117

118
        // FetchLastChannelUpdate retrieves the latest routing policy for a
119
        // target channel. This channel will typically be the outgoing channel
120
        // specified when we receive an incoming HTLC.  This will be used to
121
        // provide payment senders our latest policy when sending encrypted
122
        // error messages.
123
        FetchLastChannelUpdate func(lnwire.ShortChannelID) (
124
                *lnwire.ChannelUpdate1, error)
125

126
        // Peer is a lightning network node with which we have the channel link
127
        // opened.
128
        Peer lnpeer.Peer
129

130
        // Registry is a sub-system which responsible for managing the invoices
131
        // in thread-safe manner.
132
        Registry InvoiceDatabase
133

134
        // PreimageCache is a global witness beacon that houses any new
135
        // preimages discovered by other links. We'll use this to add new
136
        // witnesses that we discover which will notify any sub-systems
137
        // subscribed to new events.
138
        PreimageCache contractcourt.WitnessBeacon
139

140
        // OnChannelFailure is a function closure that we'll call if the
141
        // channel failed for some reason. Depending on the severity of the
142
        // error, the closure potentially must force close this channel and
143
        // disconnect the peer.
144
        //
145
        // NOTE: The method must return in order for the ChannelLink to be able
146
        // to shut down properly.
147
        OnChannelFailure func(lnwire.ChannelID, lnwire.ShortChannelID,
148
                LinkFailureError)
149

150
        // UpdateContractSignals is a function closure that we'll use to update
151
        // outside sub-systems with this channel's latest ShortChannelID.
152
        UpdateContractSignals func(*contractcourt.ContractSignals) error
153

154
        // NotifyContractUpdate is a function closure that we'll use to update
155
        // the contractcourt and more specifically the ChannelArbitrator of the
156
        // latest channel state.
157
        NotifyContractUpdate func(*contractcourt.ContractUpdate) error
158

159
        // ChainEvents is an active subscription to the chain watcher for this
160
        // channel to be notified of any on-chain activity related to this
161
        // channel.
162
        ChainEvents *contractcourt.ChainEventSubscription
163

164
        // FeeEstimator is an instance of a live fee estimator which will be
165
        // used to dynamically regulate the current fee of the commitment
166
        // transaction to ensure timely confirmation.
167
        FeeEstimator chainfee.Estimator
168

169
        // hodl.Mask is a bitvector composed of hodl.Flags, specifying breakpoints
170
        // for HTLC forwarding internal to the switch.
171
        //
172
        // NOTE: This should only be used for testing.
173
        HodlMask hodl.Mask
174

175
        // SyncStates is used to indicate that we need send the channel
176
        // reestablishment message to the remote peer. It should be done if our
177
        // clients have been restarted, or remote peer have been reconnected.
178
        SyncStates bool
179

180
        // BatchTicker is the ticker that determines the interval that we'll
181
        // use to check the batch to see if there're any updates we should
182
        // flush out. By batching updates into a single commit, we attempt to
183
        // increase throughput by maximizing the number of updates coalesced
184
        // into a single commit.
185
        BatchTicker ticker.Ticker
186

187
        // FwdPkgGCTicker is the ticker determining the frequency at which
188
        // garbage collection of forwarding packages occurs. We use a
189
        // time-based approach, as opposed to block epochs, as to not hinder
190
        // syncing.
191
        FwdPkgGCTicker ticker.Ticker
192

193
        // PendingCommitTicker is a ticker that allows the link to determine if
194
        // a locally initiated commitment dance gets stuck waiting for the
195
        // remote party to revoke.
196
        PendingCommitTicker ticker.Ticker
197

198
        // BatchSize is the max size of a batch of updates done to the link
199
        // before we do a state update.
200
        BatchSize uint32
201

202
        // UnsafeReplay will cause a link to replay the adds in its latest
203
        // commitment txn after the link is restarted. This should only be used
204
        // in testing, it is here to ensure the sphinx replay detection on the
205
        // receiving node is persistent.
206
        UnsafeReplay bool
207

208
        // MinUpdateTimeout represents the minimum interval in which a link
209
        // will propose to update its commitment fee rate. A random timeout will
210
        // be selected between this and MaxUpdateTimeout.
211
        MinUpdateTimeout time.Duration
212

213
        // MaxUpdateTimeout represents the maximum interval in which a link
214
        // will propose to update its commitment fee rate. A random timeout will
215
        // be selected between this and MinUpdateTimeout.
216
        MaxUpdateTimeout time.Duration
217

218
        // OutgoingCltvRejectDelta defines the number of blocks before expiry of
219
        // an htlc where we don't offer an htlc anymore. This should be at least
220
        // the outgoing broadcast delta, because in any case we don't want to
221
        // risk offering an htlc that triggers channel closure.
222
        OutgoingCltvRejectDelta uint32
223

224
        // TowerClient is an optional engine that manages the signing,
225
        // encrypting, and uploading of justice transactions to the daemon's
226
        // configured set of watchtowers for legacy channels.
227
        TowerClient TowerClient
228

229
        // MaxOutgoingCltvExpiry is the maximum outgoing timelock that the link
230
        // should accept for a forwarded HTLC. The value is relative to the
231
        // current block height.
232
        MaxOutgoingCltvExpiry uint32
233

234
        // MaxFeeAllocation is the highest allocation we'll allow a channel's
235
        // commitment fee to be of its balance. This only applies to the
236
        // initiator of the channel.
237
        MaxFeeAllocation float64
238

239
        // MaxAnchorsCommitFeeRate is the max commitment fee rate we'll use as
240
        // the initiator for channels of the anchor type.
241
        MaxAnchorsCommitFeeRate chainfee.SatPerKWeight
242

243
        // NotifyActiveLink allows the link to tell the ChannelNotifier when a
244
        // link is first started.
245
        NotifyActiveLink func(wire.OutPoint)
246

247
        // NotifyActiveChannel allows the link to tell the ChannelNotifier when
248
        // channels becomes active.
249
        NotifyActiveChannel func(wire.OutPoint)
250

251
        // NotifyInactiveChannel allows the switch to tell the ChannelNotifier
252
        // when channels become inactive.
253
        NotifyInactiveChannel func(wire.OutPoint)
254

255
        // NotifyInactiveLinkEvent allows the switch to tell the
256
        // ChannelNotifier when a channel link become inactive.
257
        NotifyInactiveLinkEvent func(wire.OutPoint)
258

259
        // HtlcNotifier is an instance of a htlcNotifier which we will pipe htlc
260
        // events through.
261
        HtlcNotifier htlcNotifier
262

263
        // FailAliasUpdate is a function used to fail an HTLC for an
264
        // option_scid_alias channel.
265
        FailAliasUpdate func(sid lnwire.ShortChannelID,
266
                incoming bool) *lnwire.ChannelUpdate1
267

268
        // GetAliases is used by the link and switch to fetch the set of
269
        // aliases for a given link.
270
        GetAliases func(base lnwire.ShortChannelID) []lnwire.ShortChannelID
271

272
        // PreviouslySentShutdown is an optional value that is set if, at the
273
        // time of the link being started, persisted shutdown info was found for
274
        // the channel. This value being set means that we previously sent a
275
        // Shutdown message to our peer, and so we should do so again on
276
        // re-establish and should not allow anymore HTLC adds on the outgoing
277
        // direction of the link.
278
        PreviouslySentShutdown fn.Option[lnwire.Shutdown]
279

280
        // Adds the option to disable forwarding payments in blinded routes
281
        // by failing back any blinding-related payloads as if they were
282
        // invalid.
283
        DisallowRouteBlinding bool
284

285
        // MaxFeeExposure is the threshold in milli-satoshis after which we'll
286
        // restrict the flow of HTLCs and fee updates.
287
        MaxFeeExposure lnwire.MilliSatoshi
288
}
289

290
// channelLink is the service which drives a channel's commitment update
291
// state-machine. In the event that an HTLC needs to be propagated to another
292
// link, the forward handler from config is used which sends HTLC to the
293
// switch. Additionally, the link encapsulate logic of commitment protocol
294
// message ordering and updates.
295
type channelLink struct {
296
        // The following fields are only meant to be used *atomically*
297
        started       int32
298
        reestablished int32
299
        shutdown      int32
300

301
        // failed should be set to true in case a link error happens, making
302
        // sure we don't process any more updates.
303
        failed bool
304

305
        // keystoneBatch represents a volatile list of keystones that must be
306
        // written before attempting to sign the next commitment txn. These
307
        // represent all the HTLC's forwarded to the link from the switch. Once
308
        // we lock them into our outgoing commitment, then the circuit has a
309
        // keystone, and is fully opened.
310
        keystoneBatch []Keystone
311

312
        // openedCircuits is the set of all payment circuits that will be open
313
        // once we make our next commitment. After making the commitment we'll
314
        // ACK all these from our mailbox to ensure that they don't get
315
        // re-delivered if we reconnect.
316
        openedCircuits []CircuitKey
317

318
        // closedCircuits is the set of all payment circuits that will be
319
        // closed once we make our next commitment. After taking the commitment
320
        // we'll ACK all these to ensure that they don't get re-delivered if we
321
        // reconnect.
322
        closedCircuits []CircuitKey
323

324
        // channel is a lightning network channel to which we apply htlc
325
        // updates.
326
        channel *lnwallet.LightningChannel
327

328
        // cfg is a structure which carries all dependable fields/handlers
329
        // which may affect behaviour of the service.
330
        cfg ChannelLinkConfig
331

332
        // mailBox is the main interface between the outside world and the
333
        // link. All incoming messages will be sent over this mailBox. Messages
334
        // include new updates from our connected peer, and new packets to be
335
        // forwarded sent by the switch.
336
        mailBox MailBox
337

338
        // upstream is a channel that new messages sent from the remote peer to
339
        // the local peer will be sent across.
340
        upstream chan lnwire.Message
341

342
        // downstream is a channel in which new multi-hop HTLC's to be
343
        // forwarded will be sent across. Messages from this channel are sent
344
        // by the HTLC switch.
345
        downstream chan *htlcPacket
346

347
        // updateFeeTimer is the timer responsible for updating the link's
348
        // commitment fee every time it fires.
349
        updateFeeTimer *time.Timer
350

351
        // uncommittedPreimages stores a list of all preimages that have been
352
        // learned since receiving the last CommitSig from the remote peer. The
353
        // batch will be flushed just before accepting the subsequent CommitSig
354
        // or on shutdown to avoid doing a write for each preimage received.
355
        uncommittedPreimages []lntypes.Preimage
356

357
        sync.RWMutex
358

359
        // hodlQueue is used to receive exit hop htlc resolutions from invoice
360
        // registry.
361
        hodlQueue *queue.ConcurrentQueue
362

363
        // hodlMap stores related htlc data for a circuit key. It allows
364
        // resolving those htlcs when we receive a message on hodlQueue.
365
        hodlMap map[models.CircuitKey]hodlHtlc
366

367
        // log is a link-specific logging instance.
368
        log btclog.Logger
369

370
        // isOutgoingAddBlocked tracks whether the channelLink can send an
371
        // UpdateAddHTLC.
372
        isOutgoingAddBlocked atomic.Bool
373

374
        // isIncomingAddBlocked tracks whether the channelLink can receive an
375
        // UpdateAddHTLC.
376
        isIncomingAddBlocked atomic.Bool
377

378
        // flushHooks is a hookMap that is triggered when we reach a channel
379
        // state with no live HTLCs.
380
        flushHooks hookMap
381

382
        // outgoingCommitHooks is a hookMap that is triggered after we send our
383
        // next CommitSig.
384
        outgoingCommitHooks hookMap
385

386
        // incomingCommitHooks is a hookMap that is triggered after we receive
387
        // our next CommitSig.
388
        incomingCommitHooks hookMap
389

390
        // ContextGuard is a helper that encapsulates a wait group and quit
391
        // channel and allows contexts that either block or cancel on those
392
        // depending on the use case.
393
        *fn.ContextGuard
394
}
395

396
// hookMap is a data structure that is used to track the hooks that need to be
397
// called in various parts of the channelLink's lifecycle.
398
//
399
// WARNING: NOT thread-safe.
400
type hookMap struct {
401
        // allocIdx keeps track of the next id we haven't yet allocated.
402
        allocIdx atomic.Uint64
403

404
        // transient is a map of hooks that are only called the next time invoke
405
        // is called. These hooks are deleted during invoke.
406
        transient map[uint64]func()
407

408
        // newTransients is a channel that we use to accept new hooks into the
409
        // hookMap.
410
        newTransients chan func()
411
}
412

413
// newHookMap initializes a new empty hookMap.
414
func newHookMap() hookMap {
415
        return hookMap{
416
                allocIdx:      atomic.Uint64{},
417
                transient:     make(map[uint64]func()),
418
                newTransients: make(chan func()),
419
        }
4✔
420
}
4✔
421

4✔
422
// alloc allocates space in the hook map for the supplied hook, the second
4✔
423
// argument determines whether it goes into the transient or persistent part
4✔
424
// of the hookMap.
4✔
425
func (m *hookMap) alloc(hook func()) uint64 {
4✔
426
        // We assume we never overflow a uint64. Seems OK.
427
        hookID := m.allocIdx.Add(1)
428
        if hookID == 0 {
429
                panic("hookMap allocIdx overflow")
430
        }
4✔
431
        m.transient[hookID] = hook
4✔
432

4✔
433
        return hookID
4✔
434
}
×
435

436
// invoke is used on a hook map to call all the registered hooks and then clear
4✔
437
// out the transient hooks so they are not called again.
4✔
438
func (m *hookMap) invoke() {
4✔
439
        for _, hook := range m.transient {
440
                hook()
441
        }
442

443
        m.transient = make(map[uint64]func())
4✔
444
}
8✔
445

4✔
446
// hodlHtlc contains htlc data that is required for resolution.
4✔
447
type hodlHtlc struct {
448
        add        lnwire.UpdateAddHTLC
4✔
449
        sourceRef  channeldb.AddRef
450
        obfuscator hop.ErrorEncrypter
451
}
452

453
// NewChannelLink creates a new instance of a ChannelLink given a configuration
454
// and active channel that will be used to verify/apply updates to.
455
func NewChannelLink(cfg ChannelLinkConfig,
456
        channel *lnwallet.LightningChannel) ChannelLink {
457

458
        logPrefix := fmt.Sprintf("ChannelLink(%v):", channel.ChannelPoint())
459

460
        // If the max fee exposure isn't set, use the default.
461
        if cfg.MaxFeeExposure == 0 {
4✔
462
                cfg.MaxFeeExposure = DefaultMaxFeeExposure
4✔
463
        }
4✔
464

4✔
465
        return &channelLink{
4✔
466
                cfg:                 cfg,
4✔
UNCOV
467
                channel:             channel,
×
UNCOV
468
                hodlMap:             make(map[models.CircuitKey]hodlHtlc),
×
469
                hodlQueue:           queue.NewConcurrentQueue(10),
470
                log:                 build.NewPrefixLog(logPrefix, log),
4✔
471
                flushHooks:          newHookMap(),
4✔
472
                outgoingCommitHooks: newHookMap(),
4✔
473
                incomingCommitHooks: newHookMap(),
4✔
474
                ContextGuard:        fn.NewContextGuard(),
4✔
475
        }
4✔
476
}
4✔
477

4✔
478
// A compile time check to ensure channelLink implements the ChannelLink
4✔
479
// interface.
4✔
480
var _ ChannelLink = (*channelLink)(nil)
4✔
481

482
// Start starts all helper goroutines required for the operation of the channel
483
// link.
484
//
485
// NOTE: Part of the ChannelLink interface.
486
func (l *channelLink) Start() error {
487
        if !atomic.CompareAndSwapInt32(&l.started, 0, 1) {
488
                err := fmt.Errorf("channel link(%v): already started", l)
489
                l.log.Warn("already started")
490
                return err
491
        }
4✔
492

4✔
493
        l.log.Info("starting")
×
494

×
495
        // If the config supplied watchtower client, ensure the channel is
×
496
        // registered before trying to use it during operation.
×
497
        if l.cfg.TowerClient != nil {
498
                err := l.cfg.TowerClient.RegisterChannel(
4✔
499
                        l.ChanID(), l.channel.State().ChanType,
4✔
500
                )
4✔
501
                if err != nil {
4✔
502
                        return err
8✔
503
                }
4✔
504
        }
4✔
505

4✔
506
        l.mailBox.ResetMessages()
4✔
507
        l.hodlQueue.Start()
×
508

×
509
        // Before launching the htlcManager messages, revert any circuits that
510
        // were marked open in the switch's circuit map, but did not make it
511
        // into a commitment txn. We use the next local htlc index as the cut
4✔
512
        // off point, since all indexes below that are committed. This action
4✔
513
        // is only performed if the link's final short channel ID has been
4✔
514
        // assigned, otherwise we would try to trim the htlcs belonging to the
4✔
515
        // all-zero, hop.Source ID.
4✔
516
        if l.ShortChanID() != hop.Source {
4✔
517
                localHtlcIndex, err := l.channel.NextLocalHtlcIndex()
4✔
518
                if err != nil {
4✔
519
                        return fmt.Errorf("unable to retrieve next local "+
4✔
520
                                "htlc index: %v", err)
4✔
521
                }
8✔
522

4✔
523
                // NOTE: This is automatically done by the switch when it
4✔
524
                // starts up, but is necessary to prevent inconsistencies in
×
525
                // the case that the link flaps. This is a result of a link's
×
526
                // life-cycle being shorter than that of the switch.
×
527
                chanID := l.ShortChanID()
528
                err = l.cfg.Circuits.TrimOpenCircuits(chanID, localHtlcIndex)
529
                if err != nil {
530
                        return fmt.Errorf("unable to trim circuits above "+
531
                                "local htlc index %d: %v", localHtlcIndex, err)
532
                }
4✔
533

4✔
534
                // Since the link is live, before we start the link we'll update
4✔
535
                // the ChainArbitrator with the set of new channel signals for
×
536
                // this channel.
×
537
                //
×
538
                // TODO(roasbeef): split goroutines within channel arb to avoid
539
                go func() {
540
                        signals := &contractcourt.ContractSignals{
541
                                ShortChanID: l.channel.ShortChanID(),
542
                        }
543

544
                        err := l.cfg.UpdateContractSignals(signals)
8✔
545
                        if err != nil {
4✔
546
                                l.log.Errorf("unable to update signals")
4✔
547
                        }
4✔
548
                }()
4✔
549
        }
4✔
550

4✔
551
        l.updateFeeTimer = time.NewTimer(l.randomFeeUpdateTimeout())
×
552

×
553
        l.Wg.Add(1)
554
        go l.htlcManager()
555

556
        return nil
4✔
557
}
4✔
558

4✔
559
// Stop gracefully stops all active helper goroutines, then waits until they've
4✔
560
// exited.
4✔
561
//
4✔
562
// NOTE: Part of the ChannelLink interface.
563
func (l *channelLink) Stop() {
564
        if !atomic.CompareAndSwapInt32(&l.shutdown, 0, 1) {
565
                l.log.Warn("already stopped")
566
                return
567
        }
568

4✔
569
        l.log.Info("stopping")
4✔
UNCOV
570

×
UNCOV
571
        // As the link is stopping, we are no longer interested in htlc
×
UNCOV
572
        // resolutions coming from the invoice registry.
×
573
        l.cfg.Registry.HodlUnsubscribeAll(l.hodlQueue.ChanIn())
574

4✔
575
        if l.cfg.ChainEvents.Cancel != nil {
4✔
576
                l.cfg.ChainEvents.Cancel()
4✔
577
        }
4✔
578

4✔
579
        // Ensure the channel for the timer is drained.
4✔
580
        if l.updateFeeTimer != nil {
8✔
581
                if !l.updateFeeTimer.Stop() {
4✔
582
                        select {
4✔
583
                        case <-l.updateFeeTimer.C:
584
                        default:
585
                        }
8✔
586
                }
4✔
587
        }
×
588

×
589
        if l.hodlQueue != nil {
×
590
                l.hodlQueue.Stop()
591
        }
592

593
        close(l.Quit)
594
        l.Wg.Wait()
8✔
595

4✔
596
        // Now that the htlcManager has completely exited, reset the packet
4✔
597
        // courier. This allows the mailbox to revaluate any lingering Adds that
598
        // were delivered but didn't make it on a commitment to be failed back
4✔
599
        // if the link is offline for an extended period of time. The error is
4✔
600
        // ignored since it can only fail when the daemon is exiting.
4✔
601
        _ = l.mailBox.ResetPackets()
4✔
602

4✔
603
        // As a final precaution, we will attempt to flush any uncommitted
4✔
604
        // preimages to the preimage cache. The preimages should be re-delivered
4✔
605
        // after channel reestablishment, however this adds an extra layer of
4✔
606
        // protection in case the peer never returns. Without this, we will be
4✔
607
        // unable to settle any contracts depending on the preimages even though
4✔
608
        // we had learned them at some point.
4✔
609
        err := l.cfg.PreimageCache.AddPreimages(l.uncommittedPreimages...)
4✔
610
        if err != nil {
4✔
611
                l.log.Errorf("unable to add preimages=%v to cache: %v",
4✔
612
                        l.uncommittedPreimages, err)
4✔
613
        }
4✔
614
}
4✔
615

4✔
616
// WaitForShutdown blocks until the link finishes shutting down, which includes
×
617
// termination of all dependent goroutines.
×
618
func (l *channelLink) WaitForShutdown() {
×
619
        l.Wg.Wait()
620
}
621

622
// EligibleToForward returns a bool indicating if the channel is able to
623
// actively accept requests to forward HTLC's. We're able to forward HTLC's if
×
624
// we are eligible to update AND the channel isn't currently flushing the
×
625
// outgoing half of the channel.
×
626
func (l *channelLink) EligibleToForward() bool {
627
        return l.EligibleToUpdate() &&
628
                !l.IsFlushing(Outgoing)
629
}
630

631
// EligibleToUpdate returns a bool indicating if the channel is able to update
4✔
632
// channel state. We're able to update channel state if we know the remote
4✔
633
// party's next revocation point. Otherwise, we can't initiate new channel
4✔
634
// state. We also require that the short channel ID not be the all-zero source
4✔
635
// ID, meaning that the channel has had its ID finalized.
636
func (l *channelLink) EligibleToUpdate() bool {
637
        return l.channel.RemoteNextRevocation() != nil &&
638
                l.ShortChanID() != hop.Source &&
639
                l.isReestablished()
640
}
641

4✔
642
// EnableAdds sets the ChannelUpdateHandler state to allow UpdateAddHtlc's in
4✔
643
// the specified direction. It returns true if the state was changed and false
4✔
644
// if the desired state was already set before the method was called.
4✔
645
func (l *channelLink) EnableAdds(linkDirection LinkDirection) bool {
4✔
646
        if linkDirection == Outgoing {
647
                return l.isOutgoingAddBlocked.Swap(false)
648
        }
649

UNCOV
650
        return l.isIncomingAddBlocked.Swap(false)
×
UNCOV
651
}
×
UNCOV
652

×
UNCOV
653
// DisableAdds sets the ChannelUpdateHandler state to allow UpdateAddHtlc's in
×
654
// the specified direction. It returns true if the state was changed and false
UNCOV
655
// if the desired state was already set before the method was called.
×
656
func (l *channelLink) DisableAdds(linkDirection LinkDirection) bool {
657
        if linkDirection == Outgoing {
658
                return !l.isOutgoingAddBlocked.Swap(true)
659
        }
660

661
        return !l.isIncomingAddBlocked.Swap(true)
4✔
662
}
8✔
663

4✔
664
// IsFlushing returns true when UpdateAddHtlc's are disabled in the direction of
4✔
665
// the argument.
666
func (l *channelLink) IsFlushing(linkDirection LinkDirection) bool {
4✔
667
        if linkDirection == Outgoing {
668
                return l.isOutgoingAddBlocked.Load()
669
        }
670

671
        return l.isIncomingAddBlocked.Load()
4✔
672
}
8✔
673

4✔
674
// OnFlushedOnce adds a hook that will be called the next time the channel
4✔
675
// state reaches zero htlcs. This hook will only ever be called once. If the
676
// channel state already has zero htlcs, then this will be called immediately.
4✔
677
func (l *channelLink) OnFlushedOnce(hook func()) {
678
        select {
679
        case l.flushHooks.newTransients <- hook:
680
        case <-l.Quit:
681
        }
682
}
4✔
683

4✔
684
// OnCommitOnce adds a hook that will be called the next time a CommitSig
4✔
685
// message is sent in the argument's LinkDirection. This hook will only ever be
×
686
// called once. If no CommitSig is owed in the argument's LinkDirection, then
687
// we will call this hook be run immediately.
688
func (l *channelLink) OnCommitOnce(direction LinkDirection, hook func()) {
689
        var queue chan func()
690

691
        if direction == Outgoing {
692
                queue = l.outgoingCommitHooks.newTransients
693
        } else {
4✔
694
                queue = l.incomingCommitHooks.newTransients
4✔
695
        }
4✔
696

8✔
697
        select {
4✔
698
        case queue <- hook:
4✔
699
        case <-l.Quit:
×
700
        }
×
701
}
702

4✔
703
// isReestablished returns true if the link has successfully completed the
4✔
704
// channel reestablishment dance.
×
705
func (l *channelLink) isReestablished() bool {
706
        return atomic.LoadInt32(&l.reestablished) == 1
707
}
708

709
// markReestablished signals that the remote peer has successfully exchanged
710
// channel reestablish messages and that the channel is ready to process
4✔
711
// subsequent messages.
4✔
712
func (l *channelLink) markReestablished() {
4✔
713
        atomic.StoreInt32(&l.reestablished, 1)
714
}
715

716
// IsUnadvertised returns true if the underlying channel is unadvertised.
717
func (l *channelLink) IsUnadvertised() bool {
4✔
718
        state := l.channel.State()
4✔
719
        return state.ChannelFlags&lnwire.FFAnnounceChannel == 0
4✔
720
}
721

722
// sampleNetworkFee samples the current fee rate on the network to get into the
4✔
723
// chain in a timely manner. The returned value is expressed in fee-per-kw, as
4✔
724
// this is the native rate used when computing the fee for commitment
4✔
725
// transactions, and the second-level HTLC transactions.
4✔
726
func (l *channelLink) sampleNetworkFee() (chainfee.SatPerKWeight, error) {
727
        // We'll first query for the sat/kw recommended to be confirmed within 3
728
        // blocks.
729
        feePerKw, err := l.cfg.FeeEstimator.EstimateFeePerKW(3)
730
        if err != nil {
UNCOV
731
                return 0, err
×
UNCOV
732
        }
×
UNCOV
733

×
UNCOV
734
        l.log.Debugf("sampled fee rate for 3 block conf: %v sat/kw",
×
UNCOV
735
                int64(feePerKw))
×
736

×
737
        return feePerKw, nil
×
738
}
UNCOV
739

×
UNCOV
740
// shouldAdjustCommitFee returns true if we should update our commitment fee to
×
UNCOV
741
// match that of the network fee. We'll only update our commitment fee if the
×
UNCOV
742
// network fee is +/- 10% to our commitment fee or if our current commitment
×
743
// fee is below the minimum relay fee.
744
func shouldAdjustCommitFee(netFee, chanFee,
745
        minRelayFee chainfee.SatPerKWeight) bool {
746

747
        switch {
748
        // If the network fee is greater than our current commitment fee and
749
        // our current commitment fee is below the minimum relay fee then
UNCOV
750
        // we should switch to it no matter if it is less than a 10% increase.
×
UNCOV
751
        case netFee > chanFee && chanFee < minRelayFee:
×
UNCOV
752
                return true
×
753

754
        // If the network fee is greater than the commitment fee, then we'll
755
        // switch to it if it's at least 10% greater than the commit fee.
UNCOV
756
        case netFee > chanFee && netFee >= (chanFee+(chanFee*10)/100):
×
UNCOV
757
                return true
×
758

759
        // If the network fee is less than our commitment fee, then we'll
760
        // switch to it if it's at least 10% less than the commitment fee.
UNCOV
761
        case netFee < chanFee && netFee <= (chanFee-(chanFee*10)/100):
×
UNCOV
762
                return true
×
763

764
        // Otherwise, we won't modify our fee.
765
        default:
UNCOV
766
                return false
×
UNCOV
767
        }
×
768
}
769

UNCOV
770
// failCb is used to cut down on the argument verbosity.
×
UNCOV
771
type failCb func(update *lnwire.ChannelUpdate1) lnwire.FailureMessage
×
772

773
// createFailureWithUpdate creates a ChannelUpdate when failing an incoming or
774
// outgoing HTLC. It may return a FailureMessage that references a channel's
775
// alias. If the channel does not have an alias, then the regular channel
776
// update from disk will be returned.
777
func (l *channelLink) createFailureWithUpdate(incoming bool,
778
        outgoingScid lnwire.ShortChannelID, cb failCb) lnwire.FailureMessage {
779

780
        // Determine which SCID to use in case we need to use aliases in the
781
        // ChannelUpdate.
782
        scid := outgoingScid
783
        if incoming {
4✔
784
                scid = l.ShortChanID()
4✔
785
        }
4✔
786

4✔
787
        // Try using the FailAliasUpdate function. If it returns nil, fallback
4✔
788
        // to the non-alias behavior.
4✔
789
        update := l.cfg.FailAliasUpdate(scid, incoming)
×
790
        if update == nil {
×
791
                // Fallback to the non-alias behavior.
792
                var err error
793
                update, err = l.cfg.FetchLastChannelUpdate(l.ShortChanID())
794
                if err != nil {
4✔
795
                        return &lnwire.FailTemporaryNodeFailure{}
8✔
796
                }
4✔
797
        }
4✔
798

4✔
799
        return cb(update)
4✔
800
}
×
801

×
802
// syncChanState attempts to synchronize channel states with the remote party.
803
// This method is to be called upon reconnection after the initial funding
804
// flow. We'll compare out commitment chains with the remote party, and re-send
4✔
805
// either a danging commit signature, a revocation, or both.
806
func (l *channelLink) syncChanStates() error {
807
        chanState := l.channel.State()
808

809
        l.log.Infof("Attempting to re-synchronize channel: %v", chanState)
810

811
        // First, we'll generate our ChanSync message to send to the other
4✔
812
        // side. Based on this message, the remote party will decide if they
4✔
813
        // need to retransmit any data or not.
4✔
814
        localChanSyncMsg, err := chanState.ChanSyncMsg()
4✔
815
        if err != nil {
4✔
816
                return fmt.Errorf("unable to generate chan sync message for "+
4✔
817
                        "ChannelPoint(%v)", l.channel.ChannelPoint())
4✔
818
        }
4✔
819
        if err := l.cfg.Peer.SendMessage(true, localChanSyncMsg); err != nil {
4✔
820
                return fmt.Errorf("unable to send chan sync message for "+
4✔
821
                        "ChannelPoint(%v): %v", l.channel.ChannelPoint(), err)
×
822
        }
×
823

×
824
        var msgsToReSend []lnwire.Message
4✔
825

×
826
        // Next, we'll wait indefinitely to receive the ChanSync message. The
×
827
        // first message sent MUST be the ChanSync message.
×
828
        select {
829
        case msg := <-l.upstream:
4✔
830
                l.log.Tracef("Received msg=%v from peer(%x)", msg.MsgType(),
4✔
831
                        l.cfg.Peer.PubKey())
4✔
832

4✔
833
                remoteChanSyncMsg, ok := msg.(*lnwire.ChannelReestablish)
4✔
834
                if !ok {
4✔
835
                        return fmt.Errorf("first message sent to sync "+
4✔
836
                                "should be ChannelReestablish, instead "+
4✔
837
                                "received: %T", msg)
4✔
838
                }
4✔
839

4✔
840
                // If the remote party indicates that they think we haven't
×
841
                // done any state updates yet, then we'll retransmit the
×
842
                // channel_ready message first. We do this, as at this point
×
843
                // we can't be sure if they've really received the
×
844
                // ChannelReady message.
845
                if remoteChanSyncMsg.NextLocalCommitHeight == 1 &&
846
                        localChanSyncMsg.NextLocalCommitHeight == 1 &&
847
                        !l.channel.IsPending() {
848

849
                        l.log.Infof("resending ChannelReady message to peer")
850

4✔
851
                        nextRevocation, err := l.channel.NextRevocationKey()
4✔
852
                        if err != nil {
8✔
853
                                return fmt.Errorf("unable to create next "+
4✔
854
                                        "revocation: %v", err)
4✔
855
                        }
4✔
856

4✔
857
                        channelReadyMsg := lnwire.NewChannelReady(
4✔
858
                                l.ChanID(), nextRevocation,
×
859
                        )
×
860

×
861
                        // If this is a taproot channel, then we'll send the
862
                        // very same nonce that we sent above, as they should
4✔
863
                        // take the latest verification nonce we send.
4✔
864
                        if chanState.ChanType.IsTaproot() {
4✔
865
                                //nolint:lll
4✔
866
                                channelReadyMsg.NextLocalNonce = localChanSyncMsg.LocalNonce
4✔
867
                        }
4✔
868

4✔
869
                        // For channels that negotiated the option-scid-alias
8✔
870
                        // feature bit, ensure that we send over the alias in
4✔
871
                        // the channel_ready message. We'll send the first
4✔
872
                        // alias we find for the channel since it does not
4✔
873
                        // matter which alias we send. We'll error out if no
874
                        // aliases are found.
875
                        if l.negotiatedAliasFeature() {
876
                                aliases := l.getAliases()
877
                                if len(aliases) == 0 {
878
                                        // This shouldn't happen since we
879
                                        // always add at least one alias before
880
                                        // the channel reaches the link.
8✔
881
                                        return fmt.Errorf("no aliases found")
4✔
882
                                }
4✔
883

×
884
                                // getAliases returns a copy of the alias slice
×
885
                                // so it is ok to use a pointer to the first
×
886
                                // entry.
×
887
                                channelReadyMsg.AliasScid = &aliases[0]
×
888
                        }
889

890
                        err = l.cfg.Peer.SendMessage(false, channelReadyMsg)
891
                        if err != nil {
892
                                return fmt.Errorf("unable to re-send "+
4✔
893
                                        "ChannelReady: %v", err)
894
                        }
895
                }
4✔
896

4✔
897
                // In any case, we'll then process their ChanSync message.
×
898
                l.log.Info("received re-establishment message from remote side")
×
899

×
900
                var (
901
                        openedCircuits []CircuitKey
902
                        closedCircuits []CircuitKey
903
                )
4✔
904

4✔
905
                // We've just received a ChanSync message from the remote
4✔
906
                // party, so we'll process the message  in order to determine
4✔
907
                // if we need to re-transmit any messages to the remote party.
4✔
908
                ctx, cancel := l.WithCtxQuitNoTimeout()
4✔
909
                defer cancel()
4✔
910
                msgsToReSend, openedCircuits, closedCircuits, err =
4✔
911
                        l.channel.ProcessChanSyncMsg(ctx, remoteChanSyncMsg)
4✔
912
                if err != nil {
4✔
913
                        return err
4✔
914
                }
4✔
915

4✔
916
                // Repopulate any identifiers for circuits that may have been
4✔
917
                // opened or unclosed. This may happen if we needed to
8✔
918
                // retransmit a commitment signature message.
4✔
919
                l.openedCircuits = openedCircuits
4✔
920
                l.closedCircuits = closedCircuits
921

922
                // Ensure that all packets have been have been removed from the
923
                // link's mailbox.
924
                if err := l.ackDownStreamPackets(); err != nil {
4✔
925
                        return err
4✔
926
                }
4✔
927

4✔
928
                if len(msgsToReSend) > 0 {
4✔
929
                        l.log.Infof("sending %v updates to synchronize the "+
4✔
930
                                "state", len(msgsToReSend))
×
931
                }
×
932

933
                // If we have any messages to retransmit, we'll do so
4✔
UNCOV
934
                // immediately so we return to a synchronized state as soon as
×
UNCOV
935
                // possible.
×
UNCOV
936
                for _, msg := range msgsToReSend {
×
937
                        l.cfg.Peer.SendMessage(false, msg)
938
                }
939

940
        case <-l.Quit:
941
                return ErrLinkShuttingDown
4✔
UNCOV
942
        }
×
UNCOV
943

×
944
        return nil
945
}
4✔
946

4✔
947
// resolveFwdPkgs loads any forwarding packages for this link from disk, and
948
// reprocesses them in order. The primary goal is to make sure that any HTLCs
949
// we previously received are reinstated in memory, and forwarded to the switch
4✔
950
// if necessary. After a restart, this will also delete any previously
951
// completed packages.
952
func (l *channelLink) resolveFwdPkgs() error {
953
        fwdPkgs, err := l.channel.LoadFwdPkgs()
954
        if err != nil {
955
                return err
956
        }
957

4✔
958
        l.log.Debugf("loaded %d fwd pks", len(fwdPkgs))
4✔
959

4✔
960
        for _, fwdPkg := range fwdPkgs {
×
961
                if err := l.resolveFwdPkg(fwdPkg); err != nil {
×
962
                        return err
963
                }
4✔
964
        }
4✔
965

8✔
966
        // If any of our reprocessing steps require an update to the commitment
6✔
967
        // txn, we initiate a state transition to capture all relevant changes.
2✔
968
        if l.channel.NumPendingUpdates(lntypes.Local, lntypes.Remote) > 0 {
2✔
969
                return l.updateCommitTx()
970
        }
971

972
        return nil
973
}
8✔
974

4✔
975
// resolveFwdPkg interprets the FwdState of the provided package, either
4✔
976
// reprocesses any outstanding htlcs in the package, or performs garbage
977
// collection on the package.
4✔
978
func (l *channelLink) resolveFwdPkg(fwdPkg *channeldb.FwdPkg) error {
979
        // Remove any completed packages to clear up space.
980
        if fwdPkg.State == channeldb.FwdStateCompleted {
981
                l.log.Debugf("removing completed fwd pkg for height=%d",
982
                        fwdPkg.Height)
983

4✔
984
                err := l.channel.RemoveFwdPkgs(fwdPkg.Height)
4✔
985
                if err != nil {
8✔
986
                        l.log.Errorf("unable to remove fwd pkg for height=%d: "+
4✔
987
                                "%v", fwdPkg.Height, err)
4✔
988
                        return err
4✔
989
                }
4✔
990
        }
6✔
991

2✔
992
        // Otherwise this is either a new package or one has gone through
2✔
993
        // processing, but contains htlcs that need to be restored in memory.
2✔
994
        // We replay this forwarding package to make sure our local mem state
2✔
995
        // is resurrected, we mimic any original responses back to the remote
996
        // party, and re-forward the relevant HTLCs to the switch.
997

998
        // If the package is fully acked but not completed, it must still have
999
        // settles and fails to propagate.
1000
        if !fwdPkg.SettleFailFilter.IsFull() {
1001
                l.processRemoteSettleFails(fwdPkg)
1002
        }
1003

1004
        // Finally, replay *ALL ADDS* in this forwarding package. The
1005
        // downstream logic is able to filter out any duplicates, but we must
8✔
1006
        // shove the entire, original set of adds down the pipeline so that the
4✔
1007
        // batch of adds presented to the sphinx router does not ever change.
4✔
1008
        if !fwdPkg.AckFilter.IsFull() {
1009
                l.processRemoteAdds(fwdPkg)
1010

1011
                // If the link failed during processing the adds, we must
1012
                // return to ensure we won't attempted to update the state
1013
                // further.
8✔
1014
                if l.failed {
4✔
1015
                        return fmt.Errorf("link failed while " +
4✔
1016
                                "processing remote adds")
4✔
1017
                }
4✔
1018
        }
4✔
1019

4✔
1020
        return nil
×
1021
}
×
1022

×
1023
// fwdPkgGarbager periodically reads all forwarding packages from disk and
1024
// removes those that can be discarded. It is safe to do this entirely in the
1025
// background, since all state is coordinated on disk. This also ensures the
4✔
1026
// link can continue to process messages and interleave database accesses.
1027
//
1028
// NOTE: This MUST be run as a goroutine.
1029
func (l *channelLink) fwdPkgGarbager() {
1030
        defer l.Wg.Done()
1031

1032
        l.cfg.FwdPkgGCTicker.Resume()
1033
        defer l.cfg.FwdPkgGCTicker.Stop()
1034

4✔
1035
        if err := l.loadAndRemove(); err != nil {
4✔
1036
                l.log.Warnf("unable to run initial fwd pkgs gc: %v", err)
4✔
1037
        }
4✔
1038

4✔
1039
        for {
4✔
1040
                select {
4✔
1041
                case <-l.cfg.FwdPkgGCTicker.Ticks():
×
1042
                        if err := l.loadAndRemove(); err != nil {
×
1043
                                l.log.Warnf("unable to remove fwd pkgs: %v",
1044
                                        err)
8✔
1045
                                continue
4✔
UNCOV
1046
                        }
×
UNCOV
1047
                case <-l.Quit:
×
UNCOV
1048
                        return
×
UNCOV
1049
                }
×
UNCOV
1050
        }
×
1051
}
1052

4✔
1053
// loadAndRemove loads all the channels forwarding packages and determines if
4✔
1054
// they can be removed. It is called once before the FwdPkgGCTicker ticks so that
1055
// a longer tick interval can be used.
1056
func (l *channelLink) loadAndRemove() error {
1057
        fwdPkgs, err := l.channel.LoadFwdPkgs()
1058
        if err != nil {
1059
                return err
1060
        }
1061

4✔
1062
        var removeHeights []uint64
4✔
1063
        for _, fwdPkg := range fwdPkgs {
4✔
UNCOV
1064
                if fwdPkg.State != channeldb.FwdStateCompleted {
×
UNCOV
1065
                        continue
×
1066
                }
1067

4✔
1068
                removeHeights = append(removeHeights, fwdPkg.Height)
8✔
1069
        }
8✔
1070

4✔
1071
        // If removeHeights is empty, return early so we don't use a db
1072
        // transaction.
1073
        if len(removeHeights) == 0 {
4✔
1074
                return nil
1075
        }
1076

1077
        return l.channel.RemoveFwdPkgs(removeHeights...)
1078
}
8✔
1079

4✔
1080
// handleChanSyncErr performs the error handling logic in the case where we
4✔
1081
// could not successfully syncChanStates with our channel peer.
1082
func (l *channelLink) handleChanSyncErr(err error) {
4✔
1083
        l.log.Warnf("error when syncing channel states: %v", err)
1084

1085
        var errDataLoss *lnwallet.ErrCommitSyncLocalDataLoss
1086

1087
        switch {
4✔
1088
        case errors.Is(err, ErrLinkShuttingDown):
4✔
1089
                l.log.Debugf("unable to sync channel states, link is " +
4✔
1090
                        "shutting down")
4✔
1091
                return
4✔
1092

4✔
1093
        // We failed syncing the commit chains, probably because the remote has
4✔
1094
        // lost state. We should force close the channel.
4✔
1095
        case errors.Is(err, lnwallet.ErrCommitSyncRemoteDataLoss):
4✔
1096
                fallthrough
4✔
1097

1098
        // The remote sent us an invalid last commit secret, we should force
1099
        // close the channel.
1100
        // TODO(halseth): and permanently ban the peer?
4✔
1101
        case errors.Is(err, lnwallet.ErrInvalidLastCommitSecret):
4✔
1102
                fallthrough
1103

1104
        // The remote sent us a commit point different from what they sent us
1105
        // before.
1106
        // TODO(halseth): ban peer?
4✔
1107
        case errors.Is(err, lnwallet.ErrInvalidLocalUnrevokedCommitPoint):
4✔
1108
                // We'll fail the link and tell the peer to force close the
1109
                // channel. Note that the database state is not updated here,
1110
                // but will be updated when the close transaction is ready to
1111
                // avoid that we go down before storing the transaction in the
1112
                // db.
4✔
1113
                l.failf(
4✔
1114
                        LinkFailureError{
4✔
1115
                                code:          ErrSyncError,
4✔
1116
                                FailureAction: LinkFailureForceClose,
4✔
1117
                        },
4✔
1118
                        "unable to synchronize channel states: %v", err,
4✔
1119
                )
4✔
1120

4✔
1121
        // We have lost state and cannot safely force close the channel. Fail
4✔
1122
        // the channel and wait for the remote to hopefully force close it. The
4✔
1123
        // remote has sent us its latest unrevoked commitment point, and we'll
4✔
1124
        // store it in the database, such that we can attempt to recover the
4✔
1125
        // funds if the remote force closes the channel.
1126
        case errors.As(err, &errDataLoss):
1127
                err := l.channel.MarkDataLoss(
1128
                        errDataLoss.CommitPoint,
1129
                )
1130
                if err != nil {
1131
                        l.log.Errorf("unable to mark channel data loss: %v",
4✔
1132
                                err)
4✔
1133
                }
4✔
1134

4✔
1135
        // We determined the commit chains were not possible to sync. We
4✔
1136
        // cautiously fail the channel, but don't force close.
×
1137
        // TODO(halseth): can we safely force close in any cases where this
×
1138
        // error is returned?
×
1139
        case errors.Is(err, lnwallet.ErrCannotSyncCommitChains):
1140
                if err := l.channel.MarkBorked(); err != nil {
1141
                        l.log.Errorf("unable to mark channel borked: %v", err)
1142
                }
1143

1144
        // Other, unspecified error.
×
1145
        default:
×
1146
        }
×
1147

×
1148
        l.failf(
1149
                LinkFailureError{
1150
                        code:          ErrRecoveryError,
×
1151
                        FailureAction: LinkFailureForceNone,
1152
                },
1153
                "unable to synchronize channel states: %v", err,
4✔
1154
        )
4✔
1155
}
4✔
1156

4✔
1157
// htlcManager is the primary goroutine which drives a channel's commitment
4✔
1158
// update state-machine in response to messages received via several channels.
4✔
1159
// This goroutine reads messages from the upstream (remote) peer, and also from
4✔
1160
// downstream channel managed by the channel link. In the event that an htlc
1161
// needs to be forwarded, then send-only forward handler is used which sends
1162
// htlc packets to the switch. Additionally, this goroutine handles acting upon
1163
// all timeouts for any active HTLCs, manages the channel's revocation window,
1164
// and also the htlc trickle queue+timer for this active channels.
1165
//
1166
// NOTE: This MUST be run as a goroutine.
1167
func (l *channelLink) htlcManager() {
1168
        defer func() {
1169
                l.cfg.BatchTicker.Stop()
1170
                l.Wg.Done()
1171
                l.log.Infof("exited")
1172
        }()
4✔
1173

8✔
1174
        l.log.Infof("HTLC manager started, bandwidth=%v", l.Bandwidth())
4✔
1175

4✔
1176
        // Notify any clients that the link is now in the switch via an
4✔
1177
        // ActiveLinkEvent. We'll also defer an inactive link notification for
4✔
1178
        // when the link exits to ensure that every active notification is
1179
        // matched by an inactive one.
4✔
1180
        l.cfg.NotifyActiveLink(l.ChannelPoint())
4✔
1181
        defer l.cfg.NotifyInactiveLinkEvent(l.ChannelPoint())
4✔
1182

4✔
1183
        // TODO(roasbeef): need to call wipe chan whenever D/C?
4✔
1184

4✔
1185
        // If this isn't the first time that this channel link has been
4✔
1186
        // created, then we'll need to check to see if we need to
4✔
1187
        // re-synchronize state with the remote peer. settledHtlcs is a map of
4✔
1188
        // HTLC's that we re-settled as part of the channel state sync.
4✔
1189
        if l.cfg.SyncStates {
4✔
1190
                err := l.syncChanStates()
4✔
1191
                if err != nil {
4✔
1192
                        l.handleChanSyncErr(err)
4✔
1193
                        return
4✔
1194
                }
8✔
1195
        }
4✔
1196

8✔
1197
        // If a shutdown message has previously been sent on this link, then we
4✔
1198
        // need to make sure that we have disabled any HTLC adds on the outgoing
4✔
1199
        // direction of the link and that we re-resend the same shutdown message
4✔
1200
        // that we previously sent.
1201
        l.cfg.PreviouslySentShutdown.WhenSome(func(shutdown lnwire.Shutdown) {
1202
                // Immediately disallow any new outgoing HTLCs.
1203
                if !l.DisableAdds(Outgoing) {
1204
                        l.log.Warnf("Outgoing link adds already disabled")
1205
                }
1206

8✔
1207
                // Re-send the shutdown message the peer. Since syncChanStates
4✔
1208
                // would have sent any outstanding CommitSig, it is fine for us
4✔
1209
                // to immediately queue the shutdown message now.
×
1210
                err := l.cfg.Peer.SendMessage(false, &shutdown)
×
1211
                if err != nil {
1212
                        l.log.Warnf("Error sending shutdown message: %v", err)
1213
                }
1214
        })
1215

4✔
1216
        // We've successfully reestablished the channel, mark it as such to
4✔
1217
        // allow the switch to forward HTLCs in the outbound direction.
×
1218
        l.markReestablished()
×
1219

1220
        // Now that we've received both channel_ready and channel reestablish,
1221
        // we can go ahead and send the active channel notification. We'll also
1222
        // defer the inactive notification for when the link exits to ensure
1223
        // that every active notification is matched by an inactive one.
4✔
1224
        l.cfg.NotifyActiveChannel(l.ChannelPoint())
4✔
1225
        defer l.cfg.NotifyInactiveChannel(l.ChannelPoint())
4✔
1226

4✔
1227
        // With the channel states synced, we now reset the mailbox to ensure
4✔
1228
        // we start processing all unacked packets in order. This is done here
4✔
1229
        // to ensure that all acknowledgments that occur during channel
4✔
1230
        // resynchronization have taken affect, causing us only to pull unacked
4✔
1231
        // packets after starting to read from the downstream mailbox.
4✔
1232
        l.mailBox.ResetPackets()
4✔
1233

4✔
1234
        // After cleaning up any memory pertaining to incoming packets, we now
4✔
1235
        // replay our forwarding packages to handle any htlcs that can be
4✔
1236
        // processed locally, or need to be forwarded out to the switch. We will
4✔
1237
        // only attempt to resolve packages if our short chan id indicates that
4✔
1238
        // the channel is not pending, otherwise we should have no htlcs to
4✔
1239
        // reforward.
4✔
1240
        if l.ShortChanID() != hop.Source {
4✔
1241
                err := l.resolveFwdPkgs()
4✔
1242
                switch err {
4✔
1243
                // No error was encountered, success.
4✔
1244
                case nil:
4✔
1245

8✔
1246
                // If the duplicate keystone error was encountered, we'll fail
4✔
1247
                // without sending an Error message to the peer.
4✔
1248
                case ErrDuplicateKeystone:
1249
                        l.failf(LinkFailureError{code: ErrCircuitError},
4✔
1250
                                "temporary circuit error: %v", err)
1251
                        return
1252

1253
                // A non-nil error was encountered, send an Error message to
×
1254
                // the peer.
×
1255
                default:
×
1256
                        l.failf(LinkFailureError{code: ErrInternalError},
×
1257
                                "unable to resolve fwd pkgs: %v", err)
1258
                        return
1259
                }
1260

2✔
1261
                // With our link's in-memory state fully reconstructed, spawn a
2✔
1262
                // goroutine to manage the reclamation of disk space occupied by
2✔
1263
                // completed forwarding packages.
2✔
1264
                l.Wg.Add(1)
1265
                go l.fwdPkgGarbager()
1266
        }
1267

1268
        for {
1269
                // We must always check if we failed at some point processing
4✔
1270
                // the last update before processing the next.
4✔
1271
                if l.failed {
1272
                        l.log.Errorf("link failed, exiting htlcManager")
1273
                        return
8✔
1274
                }
4✔
1275

4✔
1276
                // If the previous event resulted in a non-empty batch, resume
8✔
1277
                // the batch ticker so that it can be cleared. Otherwise pause
4✔
1278
                // the ticker to prevent waking up the htlcManager while the
4✔
1279
                // batch is empty.
4✔
1280
                numUpdates := l.channel.NumPendingUpdates(
1281
                        lntypes.Local, lntypes.Remote,
1282
                )
1283
                if numUpdates > 0 {
1284
                        l.cfg.BatchTicker.Resume()
1285
                        l.log.Tracef("BatchTicker resumed, "+
4✔
1286
                                "NumPendingUpdates(Local, Remote)=%d",
4✔
1287
                                numUpdates,
4✔
1288
                        )
8✔
1289
                } else {
4✔
1290
                        l.cfg.BatchTicker.Pause()
4✔
1291
                        l.log.Trace("BatchTicker paused due to zero " +
4✔
1292
                                "NumPendingUpdates(Local, Remote)")
4✔
1293
                }
4✔
1294

8✔
1295
                select {
4✔
1296
                // We have a new hook that needs to be run when we reach a clean
4✔
1297
                // channel state.
4✔
1298
                case hook := <-l.flushHooks.newTransients:
4✔
1299
                        if l.channel.IsChannelClean() {
1300
                                hook()
4✔
1301
                        } else {
1302
                                l.flushHooks.alloc(hook)
1303
                        }
4✔
1304

8✔
1305
                // We have a new hook that needs to be run when we have
4✔
1306
                // committed all of our updates.
8✔
1307
                case hook := <-l.outgoingCommitHooks.newTransients:
4✔
1308
                        if !l.channel.OweCommitment() {
4✔
1309
                                hook()
1310
                        } else {
1311
                                l.outgoingCommitHooks.alloc(hook)
1312
                        }
4✔
1313

8✔
1314
                // We have a new hook that needs to be run when our peer has
4✔
1315
                // committed all of their updates.
4✔
UNCOV
1316
                case hook := <-l.incomingCommitHooks.newTransients:
×
UNCOV
1317
                        if !l.channel.NeedCommitment() {
×
1318
                                hook()
1319
                        } else {
1320
                                l.incomingCommitHooks.alloc(hook)
1321
                        }
×
1322

×
1323
                // Our update fee timer has fired, so we'll check the network
×
1324
                // fee to see if we should adjust our commitment fee.
×
1325
                case <-l.updateFeeTimer.C:
×
1326
                        l.updateFeeTimer.Reset(l.randomFeeUpdateTimeout())
×
1327

1328
                        // If we're not the initiator of the channel, don't we
1329
                        // don't control the fees, so we can ignore this.
UNCOV
1330
                        if !l.channel.IsInitiator() {
×
UNCOV
1331
                                continue
×
UNCOV
1332
                        }
×
UNCOV
1333

×
UNCOV
1334
                        // If we are the initiator, then we'll sample the
×
UNCOV
1335
                        // current fee rate to get into the chain within 3
×
1336
                        // blocks.
×
1337
                        netFee, err := l.sampleNetworkFee()
1338
                        if err != nil {
1339
                                l.log.Errorf("unable to sample network fee: %v",
1340
                                        err)
1341
                                continue
UNCOV
1342
                        }
×
UNCOV
1343

×
1344
                        minRelayFee := l.cfg.FeeEstimator.RelayFeePerKW()
×
1345

×
1346
                        newCommitFee := l.channel.IdealCommitFeeRate(
×
1347
                                netFee, minRelayFee,
1348
                                l.cfg.MaxAnchorsCommitFeeRate,
UNCOV
1349
                                l.cfg.MaxFeeAllocation,
×
UNCOV
1350
                        )
×
UNCOV
1351

×
UNCOV
1352
                        // We determine if we should adjust the commitment fee
×
UNCOV
1353
                        // based on the current commitment fee, the suggested
×
UNCOV
1354
                        // new commitment fee and the current minimum relay fee
×
UNCOV
1355
                        // rate.
×
UNCOV
1356
                        commitFee := l.channel.CommitFeeRate()
×
UNCOV
1357
                        if !shouldAdjustCommitFee(
×
UNCOV
1358
                                newCommitFee, commitFee, minRelayFee,
×
UNCOV
1359
                        ) {
×
UNCOV
1360

×
UNCOV
1361
                                continue
×
UNCOV
1362
                        }
×
UNCOV
1363

×
UNCOV
1364
                        // If we do, then we'll send a new UpdateFee message to
×
UNCOV
1365
                        // the remote party, to be locked in with a new update.
×
UNCOV
1366
                        if err := l.updateChannelFee(newCommitFee); err != nil {
×
1367
                                l.log.Errorf("unable to update fee rate: %v",
1368
                                        err)
1369
                                continue
1370
                        }
UNCOV
1371

×
1372
                // The underlying channel has notified us of a unilateral close
×
1373
                // carried out by the remote peer. In the case of such an
×
1374
                // event, we'll wipe the channel state from the peer, and mark
×
1375
                // the contract as fully settled. Afterwards we can exit.
1376
                //
1377
                // TODO(roasbeef): add force closure? also breach?
1378
                case <-l.cfg.ChainEvents.RemoteUnilateralClosure:
1379
                        l.log.Warnf("remote peer has closed on-chain")
1380

1381
                        // TODO(roasbeef): remove all together
1382
                        go func() {
1383
                                chanPoint := l.channel.ChannelPoint()
4✔
1384
                                l.cfg.Peer.WipeChannel(&chanPoint)
4✔
1385
                        }()
4✔
1386

4✔
1387
                        return
8✔
1388

4✔
1389
                case <-l.cfg.BatchTicker.Ticks():
4✔
1390
                        // Attempt to extend the remote commitment chain
4✔
1391
                        // including all the currently pending entries. If the
1392
                        // send was unsuccessful, then abandon the update,
4✔
1393
                        // waiting for the revocation window to open up.
1394
                        if !l.updateCommitTxOrFail() {
4✔
1395
                                return
4✔
1396
                        }
4✔
1397

4✔
1398
                case <-l.cfg.PendingCommitTicker.Ticks():
4✔
1399
                        l.failf(
4✔
1400
                                LinkFailureError{
×
1401
                                        code:          ErrRemoteUnresponsive,
×
1402
                                        FailureAction: LinkFailureDisconnect,
UNCOV
1403
                                },
×
UNCOV
1404
                                "unable to complete dance",
×
UNCOV
1405
                        )
×
UNCOV
1406
                        return
×
UNCOV
1407

×
UNCOV
1408
                // A message from the switch was just received. This indicates
×
UNCOV
1409
                // that the link is an intermediate hop in a multi-hop HTLC
×
UNCOV
1410
                // circuit.
×
UNCOV
1411
                case pkt := <-l.downstream:
×
1412
                        l.handleDownstreamPkt(pkt)
1413

1414
                // A message from the connected peer was just received. This
1415
                // indicates that we have a new incoming HTLC, either directly
1416
                // for us, or part of a multi-hop HTLC circuit.
4✔
1417
                case msg := <-l.upstream:
4✔
1418
                        l.handleUpstreamMsg(msg)
1419

1420
                // A htlc resolution is received. This means that we now have a
1421
                // resolution for a previously accepted htlc.
1422
                case hodlItem := <-l.hodlQueue.ChanOut():
4✔
1423
                        htlcResolution := hodlItem.(invoices.HtlcResolution)
4✔
1424
                        err := l.processHodlQueue(htlcResolution)
1425
                        switch err {
1426
                        // No error, success.
1427
                        case nil:
4✔
1428

4✔
1429
                        // If the duplicate keystone error was encountered,
4✔
1430
                        // fail back gracefully.
4✔
1431
                        case ErrDuplicateKeystone:
1432
                                l.failf(LinkFailureError{
4✔
1433
                                        code: ErrCircuitError,
1434
                                }, "process hodl queue: "+
1435
                                        "temporary circuit error: %v",
1436
                                        err,
×
1437
                                )
×
1438

×
1439
                        // Send an Error message to the peer.
×
1440
                        default:
×
1441
                                l.failf(LinkFailureError{
×
1442
                                        code: ErrInternalError,
×
1443
                                }, "process hodl queue: unable to update "+
1444
                                        "commitment: %v", err,
UNCOV
1445
                                )
×
UNCOV
1446
                        }
×
UNCOV
1447

×
UNCOV
1448
                case <-l.Quit:
×
UNCOV
1449
                        return
×
UNCOV
1450
                }
×
1451
        }
1452
}
1453

4✔
1454
// processHodlQueue processes a received htlc resolution and continues reading
4✔
1455
// from the hodl queue until no more resolutions remain. When this function
1456
// returns without an error, the commit tx should be updated.
1457
func (l *channelLink) processHodlQueue(
1458
        firstResolution invoices.HtlcResolution) error {
1459

1460
        // Try to read all waiting resolution messages, so that they can all be
1461
        // processed in a single commitment tx update.
1462
        htlcResolution := firstResolution
1463
loop:
4✔
1464
        for {
4✔
1465
                // Lookup all hodl htlcs that can be failed or settled with this event.
4✔
1466
                // The hodl htlc must be present in the map.
4✔
1467
                circuitKey := htlcResolution.CircuitKey()
4✔
1468
                hodlHtlc, ok := l.hodlMap[circuitKey]
4✔
1469
                if !ok {
8✔
1470
                        return fmt.Errorf("hodl htlc not found: %v", circuitKey)
4✔
1471
                }
4✔
1472

4✔
1473
                if err := l.processHtlcResolution(htlcResolution, hodlHtlc); err != nil {
4✔
1474
                        return err
4✔
1475
                }
×
1476

×
1477
                // Clean up hodl map.
1478
                delete(l.hodlMap, circuitKey)
4✔
1479

×
1480
                select {
×
1481
                case item := <-l.hodlQueue.ChanOut():
1482
                        htlcResolution = item.(invoices.HtlcResolution)
1483
                default:
4✔
1484
                        break loop
4✔
1485
                }
4✔
1486
        }
4✔
1487

4✔
1488
        // Update the commitment tx.
4✔
1489
        if err := l.updateCommitTx(); err != nil {
4✔
1490
                return err
1491
        }
1492

1493
        return nil
1494
}
4✔
UNCOV
1495

×
UNCOV
1496
// processHtlcResolution applies a received htlc resolution to the provided
×
1497
// htlc. When this function returns without an error, the commit tx should be
1498
// updated.
4✔
1499
func (l *channelLink) processHtlcResolution(resolution invoices.HtlcResolution,
1500
        htlc hodlHtlc) error {
1501

1502
        circuitKey := resolution.CircuitKey()
1503

1504
        // Determine required action for the resolution based on the type of
1505
        // resolution we have received.
4✔
1506
        switch res := resolution.(type) {
4✔
1507
        // Settle htlcs that returned a settle resolution using the preimage
4✔
1508
        // in the resolution.
4✔
1509
        case *invoices.HtlcSettleResolution:
4✔
1510
                l.log.Debugf("received settle resolution for %v "+
4✔
1511
                        "with outcome: %v", circuitKey, res.Outcome)
4✔
1512

1513
                return l.settleHTLC(
1514
                        res.Preimage, htlc.add.ID, htlc.sourceRef,
4✔
1515
                )
4✔
1516

4✔
1517
        // For htlc failures, we get the relevant failure message based
4✔
1518
        // on the failure resolution and then fail the htlc.
4✔
1519
        case *invoices.HtlcFailResolution:
4✔
1520
                l.log.Debugf("received cancel resolution for "+
4✔
1521
                        "%v with outcome: %v", circuitKey, res.Outcome)
1522

1523
                // Get the lnwire failure message based on the resolution
1524
                // result.
4✔
1525
                failure := getResolutionFailure(res, htlc.add.Amount)
4✔
1526

4✔
1527
                l.sendHTLCError(
4✔
1528
                        htlc.add, htlc.sourceRef, failure, htlc.obfuscator,
4✔
1529
                        true,
4✔
1530
                )
4✔
1531
                return nil
4✔
1532

4✔
1533
        // Fail if we do not get a settle of fail resolution, since we
4✔
1534
        // are only expecting to handle settles and fails.
4✔
1535
        default:
4✔
1536
                return fmt.Errorf("unknown htlc resolution type: %T",
4✔
1537
                        resolution)
1538
        }
1539
}
1540

×
1541
// getResolutionFailure returns the wire message that a htlc resolution should
×
1542
// be failed with.
×
1543
func getResolutionFailure(resolution *invoices.HtlcFailResolution,
1544
        amount lnwire.MilliSatoshi) *LinkError {
1545

1546
        // If the resolution has been resolved as part of a MPP timeout,
1547
        // we need to fail the htlc with lnwire.FailMppTimeout.
1548
        if resolution.Outcome == invoices.ResultMppTimeout {
1549
                return NewDetailedLinkError(
4✔
1550
                        &lnwire.FailMPPTimeout{}, resolution.Outcome,
4✔
1551
                )
4✔
1552
        }
4✔
1553

4✔
1554
        // If the htlc is not a MPP timeout, we fail it with
×
1555
        // FailIncorrectDetails. This error is sent for invoice payment
×
1556
        // failures such as underpayment/ expiry too soon and hodl invoices
×
1557
        // (which return FailIncorrectDetails to avoid leaking information).
×
1558
        incorrectDetails := lnwire.NewFailIncorrectDetails(
1559
                amount, uint32(resolution.AcceptHeight),
1560
        )
1561

1562
        return NewDetailedLinkError(incorrectDetails, resolution.Outcome)
1563
}
4✔
1564

4✔
1565
// randomFeeUpdateTimeout returns a random timeout between the bounds defined
4✔
1566
// within the link's configuration that will be used to determine when the link
4✔
1567
// should propose an update to its commitment fee rate.
4✔
1568
func (l *channelLink) randomFeeUpdateTimeout() time.Duration {
1569
        lower := int64(l.cfg.MinUpdateTimeout)
1570
        upper := int64(l.cfg.MaxUpdateTimeout)
1571
        return time.Duration(prand.Int63n(upper-lower) + lower)
1572
}
1573

4✔
1574
// handleDownstreamUpdateAdd processes an UpdateAddHTLC packet sent from the
4✔
1575
// downstream HTLC Switch.
4✔
1576
func (l *channelLink) handleDownstreamUpdateAdd(pkt *htlcPacket) error {
4✔
1577
        htlc, ok := pkt.htlc.(*lnwire.UpdateAddHTLC)
4✔
1578
        if !ok {
1579
                return errors.New("not an UpdateAddHTLC packet")
1580
        }
1581

4✔
1582
        // If we are flushing the link in the outgoing direction we can't add
4✔
1583
        // new htlcs to the link and we need to bounce it
4✔
1584
        if l.IsFlushing(Outgoing) {
×
1585
                l.mailBox.FailAdd(pkt)
×
1586

1587
                return NewDetailedLinkError(
1588
                        &lnwire.FailPermanentChannelFailure{},
1589
                        OutgoingFailureLinkNotEligible,
4✔
1590
                )
×
1591
        }
×
1592

×
1593
        // If hodl.AddOutgoing mode is active, we exit early to simulate
×
1594
        // arbitrary delays between the switch adding an ADD to the
×
1595
        // mailbox, and the HTLC being added to the commitment state.
×
1596
        if l.cfg.HodlMask.Active(hodl.AddOutgoing) {
×
1597
                l.log.Warnf(hodl.AddOutgoing.Warning())
1598
                l.mailBox.AckPacket(pkt.inKey())
1599
                return nil
1600
        }
1601

4✔
1602
        // Check if we can add the HTLC here without exceededing the max fee
×
1603
        // exposure threshold.
×
1604
        if l.isOverexposedWithHtlc(htlc, false) {
×
1605
                l.log.Debugf("Unable to handle downstream HTLC - max fee " +
×
1606
                        "exposure exceeded")
1607

1608
                l.mailBox.FailAdd(pkt)
1609

4✔
UNCOV
1610
                return NewDetailedLinkError(
×
UNCOV
1611
                        lnwire.NewTemporaryChannelFailure(nil),
×
UNCOV
1612
                        OutgoingFailureDownstreamHtlcAdd,
×
UNCOV
1613
                )
×
UNCOV
1614
        }
×
UNCOV
1615

×
UNCOV
1616
        // A new payment has been initiated via the downstream channel,
×
UNCOV
1617
        // so we add the new HTLC to our local log, then update the
×
UNCOV
1618
        // commitment chains.
×
UNCOV
1619
        htlc.ChanID = l.ChanID()
×
1620
        openCircuitRef := pkt.inKey()
1621

1622
        // We enforce the fee buffer for the commitment transaction because
1623
        // we are in control of adding this htlc. Nothing has locked-in yet so
1624
        // we can securely enforce the fee buffer which is only relevant if we
4✔
1625
        // are the initiator of the channel.
4✔
1626
        index, err := l.channel.AddHTLC(htlc, &openCircuitRef)
4✔
1627
        if err != nil {
4✔
1628
                // The HTLC was unable to be added to the state machine,
4✔
1629
                // as a result, we'll signal the switch to cancel the
4✔
1630
                // pending payment.
4✔
1631
                l.log.Warnf("Unable to handle downstream add HTLC: %v",
4✔
1632
                        err)
8✔
1633

4✔
1634
                // Remove this packet from the link's mailbox, this
4✔
1635
                // prevents it from being reprocessed if the link
4✔
1636
                // restarts and resets it mailbox. If this response
4✔
1637
                // doesn't make it back to the originating link, it will
4✔
1638
                // be rejected upon attempting to reforward the Add to
4✔
1639
                // the switch, since the circuit was never fully opened,
4✔
1640
                // and the forwarding package shows it as
4✔
1641
                // unacknowledged.
4✔
1642
                l.mailBox.FailAdd(pkt)
4✔
1643

4✔
1644
                return NewDetailedLinkError(
4✔
1645
                        lnwire.NewTemporaryChannelFailure(nil),
4✔
1646
                        OutgoingFailureDownstreamHtlcAdd,
4✔
1647
                )
4✔
1648
        }
4✔
1649

4✔
1650
        l.log.Tracef("received downstream htlc: payment_hash=%x, "+
4✔
1651
                "local_log_index=%v, pend_updates=%v",
4✔
1652
                htlc.PaymentHash[:], index,
4✔
1653
                l.channel.NumPendingUpdates(lntypes.Local, lntypes.Remote))
4✔
1654

1655
        pkt.outgoingChanID = l.ShortChanID()
4✔
1656
        pkt.outgoingHTLCID = index
4✔
1657
        htlc.ID = index
4✔
1658

4✔
1659
        l.log.Debugf("queueing keystone of ADD open circuit: %s->%s",
4✔
1660
                pkt.inKey(), pkt.outKey())
4✔
1661

4✔
1662
        l.openedCircuits = append(l.openedCircuits, pkt.inKey())
4✔
1663
        l.keystoneBatch = append(l.keystoneBatch, pkt.keystone())
4✔
1664

4✔
1665
        _ = l.cfg.Peer.SendMessage(false, htlc)
4✔
1666

4✔
1667
        // Send a forward event notification to htlcNotifier.
4✔
1668
        l.cfg.HtlcNotifier.NotifyForwardingEvent(
4✔
1669
                newHtlcKey(pkt),
4✔
1670
                HtlcInfo{
4✔
1671
                        IncomingTimeLock: pkt.incomingTimeout,
4✔
1672
                        IncomingAmt:      pkt.incomingAmount,
4✔
1673
                        OutgoingTimeLock: htlc.Expiry,
4✔
1674
                        OutgoingAmt:      htlc.Amount,
4✔
1675
                },
4✔
1676
                getEventType(pkt),
4✔
1677
        )
4✔
1678

4✔
1679
        l.tryBatchUpdateCommitTx()
4✔
1680

4✔
1681
        return nil
4✔
1682
}
4✔
1683

4✔
1684
// handleDownstreamPkt processes an HTLC packet sent from the downstream HTLC
4✔
1685
// Switch. Possible messages sent by the switch include requests to forward new
4✔
1686
// HTLCs, timeout previously cleared HTLCs, and finally to settle currently
4✔
1687
// cleared HTLCs with the upstream peer.
1688
//
1689
// TODO(roasbeef): add sync ntfn to ensure switch always has consistent view?
1690
func (l *channelLink) handleDownstreamPkt(pkt *htlcPacket) {
1691
        switch htlc := pkt.htlc.(type) {
1692
        case *lnwire.UpdateAddHTLC:
1693
                // Handle add message. The returned error can be ignored,
1694
                // because it is also sent through the mailbox.
1695
                _ = l.handleDownstreamUpdateAdd(pkt)
4✔
1696

4✔
1697
        case *lnwire.UpdateFulfillHTLC:
4✔
1698
                // If hodl.SettleOutgoing mode is active, we exit early to
4✔
1699
                // simulate arbitrary delays between the switch adding the
4✔
1700
                // SETTLE to the mailbox, and the HTLC being added to the
4✔
1701
                // commitment state.
1702
                if l.cfg.HodlMask.Active(hodl.SettleOutgoing) {
4✔
1703
                        l.log.Warnf(hodl.SettleOutgoing.Warning())
4✔
1704
                        l.mailBox.AckPacket(pkt.inKey())
4✔
1705
                        return
4✔
1706
                }
4✔
1707

4✔
1708
                // An HTLC we forward to the switch has just settled somewhere
×
1709
                // upstream. Therefore we settle the HTLC within the our local
×
1710
                // state machine.
×
1711
                inKey := pkt.inKey()
×
1712
                err := l.channel.SettleHTLC(
1713
                        htlc.PaymentPreimage,
1714
                        pkt.incomingHTLCID,
1715
                        pkt.sourceRef,
1716
                        pkt.destRef,
4✔
1717
                        &inKey,
4✔
1718
                )
4✔
1719
                if err != nil {
4✔
1720
                        l.log.Errorf("unable to settle incoming HTLC for "+
4✔
1721
                                "circuit-key=%v: %v", inKey, err)
4✔
1722

4✔
1723
                        // If the HTLC index for Settle response was not known
4✔
1724
                        // to our commitment state, it has already been
4✔
1725
                        // cleaned up by a prior response. We'll thus try to
×
1726
                        // clean up any lingering state to ensure we don't
×
1727
                        // continue reforwarding.
×
1728
                        if _, ok := err.(lnwallet.ErrUnknownHtlcIndex); ok {
×
1729
                                l.cleanupSpuriousResponse(pkt)
×
1730
                        }
×
1731

×
1732
                        // Remove the packet from the link's mailbox to ensure
×
1733
                        // it doesn't get replayed after a reconnection.
×
1734
                        l.mailBox.AckPacket(inKey)
×
1735

×
1736
                        return
1737
                }
1738

1739
                l.log.Debugf("queueing removal of SETTLE closed circuit: "+
×
1740
                        "%s->%s", pkt.inKey(), pkt.outKey())
×
1741

×
1742
                l.closedCircuits = append(l.closedCircuits, pkt.inKey())
1743

1744
                // With the HTLC settled, we'll need to populate the wire
4✔
1745
                // message to target the specific channel and HTLC to be
4✔
1746
                // canceled.
4✔
1747
                htlc.ChanID = l.ChanID()
4✔
1748
                htlc.ID = pkt.incomingHTLCID
4✔
1749

4✔
1750
                // Then we send the HTLC settle message to the connected peer
4✔
1751
                // so we can continue the propagation of the settle message.
4✔
1752
                l.cfg.Peer.SendMessage(false, htlc)
4✔
1753

4✔
1754
                // Send a settle event notification to htlcNotifier.
4✔
1755
                l.cfg.HtlcNotifier.NotifySettleEvent(
4✔
1756
                        newHtlcKey(pkt),
4✔
1757
                        htlc.PaymentPreimage,
4✔
1758
                        getEventType(pkt),
4✔
1759
                )
4✔
1760

4✔
1761
                // Immediately update the commitment tx to minimize latency.
4✔
1762
                l.updateCommitTxOrFail()
4✔
1763

4✔
1764
        case *lnwire.UpdateFailHTLC:
4✔
1765
                // If hodl.FailOutgoing mode is active, we exit early to
4✔
1766
                // simulate arbitrary delays between the switch adding a FAIL to
4✔
1767
                // the mailbox, and the HTLC being added to the commitment
4✔
1768
                // state.
1769
                if l.cfg.HodlMask.Active(hodl.FailOutgoing) {
4✔
1770
                        l.log.Warnf(hodl.FailOutgoing.Warning())
4✔
1771
                        l.mailBox.AckPacket(pkt.inKey())
4✔
1772
                        return
4✔
1773
                }
4✔
1774

4✔
1775
                // An HTLC cancellation has been triggered somewhere upstream,
×
1776
                // we'll remove then HTLC from our local state machine.
×
1777
                inKey := pkt.inKey()
×
1778
                err := l.channel.FailHTLC(
×
1779
                        pkt.incomingHTLCID,
1780
                        htlc.Reason,
1781
                        pkt.sourceRef,
1782
                        pkt.destRef,
4✔
1783
                        &inKey,
4✔
1784
                )
4✔
1785
                if err != nil {
4✔
1786
                        l.log.Errorf("unable to cancel incoming HTLC for "+
4✔
1787
                                "circuit-key=%v: %v", inKey, err)
4✔
1788

4✔
1789
                        // If the HTLC index for Fail response was not known to
4✔
1790
                        // our commitment state, it has already been cleaned up
8✔
1791
                        // by a prior response. We'll thus try to clean up any
4✔
1792
                        // lingering state to ensure we don't continue
4✔
1793
                        // reforwarding.
4✔
1794
                        if _, ok := err.(lnwallet.ErrUnknownHtlcIndex); ok {
4✔
1795
                                l.cleanupSpuriousResponse(pkt)
4✔
1796
                        }
4✔
1797

4✔
1798
                        // Remove the packet from the link's mailbox to ensure
4✔
1799
                        // it doesn't get replayed after a reconnection.
4✔
UNCOV
1800
                        l.mailBox.AckPacket(inKey)
×
UNCOV
1801

×
1802
                        return
1803
                }
1804

1805
                l.log.Debugf("queueing removal of FAIL closed circuit: %s->%s",
4✔
1806
                        pkt.inKey(), pkt.outKey())
4✔
1807

4✔
1808
                l.closedCircuits = append(l.closedCircuits, pkt.inKey())
1809

1810
                // With the HTLC removed, we'll need to populate the wire
4✔
1811
                // message to target the specific channel and HTLC to be
4✔
1812
                // canceled. The "Reason" field will have already been set
4✔
1813
                // within the switch.
4✔
1814
                htlc.ChanID = l.ChanID()
4✔
1815
                htlc.ID = pkt.incomingHTLCID
4✔
1816

4✔
1817
                // We send the HTLC message to the peer which initially created
4✔
1818
                // the HTLC. If the incoming blinding point is non-nil, we
4✔
1819
                // know that we are a relaying node in a blinded path.
4✔
1820
                // Otherwise, we're either an introduction node or not part of
4✔
1821
                // a blinded path at all.
4✔
1822
                if err := l.sendIncomingHTLCFailureMsg(
4✔
1823
                        htlc.ID,
4✔
1824
                        pkt.obfuscator,
4✔
1825
                        htlc.Reason,
4✔
1826
                ); err != nil {
4✔
1827
                        l.log.Errorf("unable to send HTLC failure: %v",
4✔
1828
                                err)
4✔
1829

4✔
1830
                        return
4✔
1831
                }
4✔
1832

×
1833
                // If the packet does not have a link failure set, it failed
×
1834
                // further down the route so we notify a forwarding failure.
×
1835
                // Otherwise, we notify a link failure because it failed at our
×
1836
                // node.
×
1837
                if pkt.linkFailure != nil {
1838
                        l.cfg.HtlcNotifier.NotifyLinkFailEvent(
1839
                                newHtlcKey(pkt),
1840
                                newHtlcInfo(pkt),
1841
                                getEventType(pkt),
1842
                                pkt.linkFailure,
8✔
1843
                                false,
4✔
1844
                        )
4✔
1845
                } else {
4✔
1846
                        l.cfg.HtlcNotifier.NotifyForwardingFailEvent(
4✔
1847
                                newHtlcKey(pkt), getEventType(pkt),
4✔
1848
                        )
4✔
1849
                }
4✔
1850

8✔
1851
                // Immediately update the commitment tx to minimize latency.
4✔
1852
                l.updateCommitTxOrFail()
4✔
1853
        }
4✔
1854
}
4✔
1855

1856
// tryBatchUpdateCommitTx updates the commitment transaction if the batch is
1857
// full.
4✔
1858
func (l *channelLink) tryBatchUpdateCommitTx() {
1859
        pending := l.channel.NumPendingUpdates(lntypes.Local, lntypes.Remote)
1860
        if pending < uint64(l.cfg.BatchSize) {
1861
                return
1862
        }
1863

4✔
1864
        l.updateCommitTxOrFail()
4✔
1865
}
8✔
1866

4✔
1867
// cleanupSpuriousResponse attempts to ack any AddRef or SettleFailRef
4✔
1868
// associated with this packet. If successful in doing so, it will also purge
1869
// the open circuit from the circuit map and remove the packet from the link's
4✔
1870
// mailbox.
1871
func (l *channelLink) cleanupSpuriousResponse(pkt *htlcPacket) {
1872
        inKey := pkt.inKey()
1873

1874
        l.log.Debugf("cleaning up spurious response for incoming "+
1875
                "circuit-key=%v", inKey)
UNCOV
1876

×
UNCOV
1877
        // If the htlc packet doesn't have a source reference, it is unsafe to
×
UNCOV
1878
        // proceed, as skipping this ack may cause the htlc to be reforwarded.
×
UNCOV
1879
        if pkt.sourceRef == nil {
×
UNCOV
1880
                l.log.Errorf("unable to cleanup response for incoming "+
×
UNCOV
1881
                        "circuit-key=%v, does not contain source reference",
×
UNCOV
1882
                        inKey)
×
UNCOV
1883
                return
×
UNCOV
1884
        }
×
UNCOV
1885

×
UNCOV
1886
        // If the source reference is present,  we will try to prevent this link
×
UNCOV
1887
        // from resending the packet to the switch. To do so, we ack the AddRef
×
UNCOV
1888
        // of the incoming HTLC belonging to this link.
×
UNCOV
1889
        err := l.channel.AckAddHtlcs(*pkt.sourceRef)
×
1890
        if err != nil {
1891
                l.log.Errorf("unable to ack AddRef for incoming "+
1892
                        "circuit-key=%v: %v", inKey, err)
1893

UNCOV
1894
                // If this operation failed, it is unsafe to attempt removal of
×
UNCOV
1895
                // the destination reference or circuit, so we exit early. The
×
1896
                // cleanup may proceed with a different packet in the future
×
1897
                // that succeeds on this step.
×
1898
                return
×
1899
        }
×
1900

×
1901
        // Now that we know this link will stop retransmitting Adds to the
×
1902
        // switch, we can begin to teardown the response reference and circuit
×
1903
        // map.
×
1904
        //
×
1905
        // If the packet includes a destination reference, then a response for
1906
        // this HTLC was locked into the outgoing channel. Attempt to remove
1907
        // this reference, so we stop retransmitting the response internally.
1908
        // Even if this fails, we will proceed in trying to delete the circuit.
1909
        // When retransmitting responses, the destination references will be
1910
        // cleaned up if an open circuit is not found in the circuit map.
1911
        if pkt.destRef != nil {
1912
                err := l.channel.AckSettleFails(*pkt.destRef)
1913
                if err != nil {
1914
                        l.log.Errorf("unable to ack SettleFailRef "+
1915
                                "for incoming circuit-key=%v: %v",
UNCOV
1916
                                inKey, err)
×
1917
                }
×
1918
        }
×
1919

×
1920
        l.log.Debugf("deleting circuit for incoming circuit-key=%x", inKey)
×
1921

×
1922
        // With all known references acked, we can now safely delete the circuit
×
1923
        // from the switch's circuit map, as the state is no longer needed.
1924
        err = l.cfg.Circuits.DeleteCircuits(inKey)
UNCOV
1925
        if err != nil {
×
UNCOV
1926
                l.log.Errorf("unable to delete circuit for "+
×
UNCOV
1927
                        "circuit-key=%v: %v", inKey, err)
×
UNCOV
1928
        }
×
UNCOV
1929
}
×
UNCOV
1930

×
1931
// handleUpstreamMsg processes wire messages related to commitment state
×
1932
// updates from the upstream peer. The upstream peer is the peer whom we have a
×
1933
// direct channel with, updating our respective commitment chains.
×
1934
func (l *channelLink) handleUpstreamMsg(msg lnwire.Message) {
1935
        switch msg := msg.(type) {
1936
        case *lnwire.UpdateAddHTLC:
1937
                if l.IsFlushing(Incoming) {
1938
                        // This is forbidden by the protocol specification.
1939
                        // The best chance we have to deal with this is to drop
4✔
1940
                        // the connection. This should roll back the channel
4✔
1941
                        // state to the last CommitSig. If the remote has
4✔
1942
                        // already sent a CommitSig we haven't received yet,
4✔
1943
                        // channel state will be re-synchronized with a
×
1944
                        // ChannelReestablish message upon reconnection and the
×
1945
                        // protocol state that caused us to flush the link will
×
1946
                        // be rolled back. In the event that there was some
×
1947
                        // non-deterministic behavior in the remote that caused
×
1948
                        // them to violate the protocol, we have a decent shot
×
1949
                        // at correcting it this way, since reconnecting will
×
1950
                        // put us in the cleanest possible state to try again.
×
1951
                        //
×
1952
                        // In addition to the above, it is possible for us to
×
1953
                        // hit this case in situations where we improperly
×
1954
                        // handle message ordering due to concurrency choices.
×
1955
                        // An issue has been filed to address this here:
×
1956
                        // https://github.com/lightningnetwork/lnd/issues/8393
×
1957
                        l.failf(
×
1958
                                LinkFailureError{
×
1959
                                        code:             ErrInvalidUpdate,
×
1960
                                        FailureAction:    LinkFailureDisconnect,
×
1961
                                        PermanentFailure: false,
×
1962
                                        Warning:          true,
×
1963
                                },
×
1964
                                "received add while link is flushing",
×
1965
                        )
×
1966

×
1967
                        return
×
1968
                }
×
1969

×
1970
                // Disallow htlcs with blinding points set if we haven't
×
1971
                // enabled the feature. This saves us from having to process
×
1972
                // the onion at all, but will only catch blinded payments
×
1973
                // where we are a relaying node (as the blinding point will
×
1974
                // be in the payload when we're the introduction node).
1975
                if msg.BlindingPoint.IsSome() && l.cfg.DisallowRouteBlinding {
1976
                        l.failf(LinkFailureError{code: ErrInvalidUpdate},
1977
                                "blinding point included when route blinding "+
1978
                                        "is disabled")
1979

1980
                        return
4✔
1981
                }
×
1982

×
1983
                // We have to check the limit here rather than later in the
×
1984
                // switch because the counterparty can keep sending HTLC's
×
1985
                // without sending a revoke. This would mean that the switch
×
1986
                // check would only occur later.
×
1987
                if l.isOverexposedWithHtlc(msg, true) {
1988
                        l.failf(LinkFailureError{code: ErrInternalError},
1989
                                "peer sent us an HTLC that exceeded our max "+
1990
                                        "fee exposure")
1991

1992
                        return
4✔
1993
                }
×
1994

×
1995
                // We just received an add request from an upstream peer, so we
×
1996
                // add it to our state machine, then add the HTLC to our
×
1997
                // "settle" list in the event that we know the preimage.
×
1998
                index, err := l.channel.ReceiveHTLC(msg)
×
1999
                if err != nil {
2000
                        l.failf(LinkFailureError{code: ErrInvalidUpdate},
2001
                                "unable to handle upstream add HTLC: %v", err)
2002
                        return
2003
                }
4✔
2004

4✔
2005
                l.log.Tracef("receive upstream htlc with payment hash(%x), "+
×
2006
                        "assigning index: %v", msg.PaymentHash[:], index)
×
2007

×
2008
        case *lnwire.UpdateFulfillHTLC:
×
2009
                pre := msg.PaymentPreimage
2010
                idx := msg.ID
4✔
2011

4✔
2012
                // Before we pipeline the settle, we'll check the set of active
2013
                // htlc's to see if the related UpdateAddHTLC has been fully
4✔
2014
                // locked-in.
4✔
2015
                var lockedin bool
4✔
2016
                htlcs := l.channel.ActiveHtlcs()
4✔
2017
                for _, add := range htlcs {
4✔
2018
                        // The HTLC will be outgoing and match idx.
4✔
2019
                        if !add.Incoming && add.HtlcIndex == idx {
4✔
2020
                                lockedin = true
4✔
2021
                                break
4✔
2022
                        }
8✔
2023
                }
4✔
2024

8✔
2025
                if !lockedin {
4✔
2026
                        l.failf(
4✔
2027
                                LinkFailureError{code: ErrInvalidUpdate},
2028
                                "unable to handle upstream settle",
2029
                        )
2030
                        return
4✔
UNCOV
2031
                }
×
UNCOV
2032

×
UNCOV
2033
                if err := l.channel.ReceiveHTLCSettle(pre, idx); err != nil {
×
UNCOV
2034
                        l.failf(
×
UNCOV
2035
                                LinkFailureError{
×
UNCOV
2036
                                        code:          ErrInvalidUpdate,
×
2037
                                        FailureAction: LinkFailureForceClose,
2038
                                },
8✔
2039
                                "unable to handle upstream settle HTLC: %v", err,
4✔
2040
                        )
4✔
2041
                        return
4✔
2042
                }
4✔
2043

4✔
2044
                settlePacket := &htlcPacket{
4✔
2045
                        outgoingChanID: l.ShortChanID(),
4✔
2046
                        outgoingHTLCID: idx,
4✔
2047
                        htlc: &lnwire.UpdateFulfillHTLC{
4✔
2048
                                PaymentPreimage: pre,
2049
                        },
4✔
2050
                }
4✔
2051

4✔
2052
                // Add the newly discovered preimage to our growing list of
4✔
2053
                // uncommitted preimage. These will be written to the witness
4✔
2054
                // cache just before accepting the next commitment signature
4✔
2055
                // from the remote peer.
4✔
2056
                l.uncommittedPreimages = append(l.uncommittedPreimages, pre)
4✔
2057

4✔
2058
                // Pipeline this settle, send it to the switch.
4✔
2059
                go l.forwardBatch(false, settlePacket)
4✔
2060

4✔
2061
        case *lnwire.UpdateFailMalformedHTLC:
4✔
2062
                // Convert the failure type encoded within the HTLC fail
4✔
2063
                // message to the proper generic lnwire error code.
4✔
2064
                var failure lnwire.FailureMessage
4✔
2065
                switch msg.FailureCode {
2066
                case lnwire.CodeInvalidOnionVersion:
4✔
2067
                        failure = &lnwire.FailInvalidOnionVersion{
4✔
2068
                                OnionSHA256: msg.ShaOnionBlob,
4✔
2069
                        }
4✔
2070
                case lnwire.CodeInvalidOnionHmac:
4✔
2071
                        failure = &lnwire.FailInvalidOnionHmac{
4✔
2072
                                OnionSHA256: msg.ShaOnionBlob,
4✔
2073
                        }
4✔
2074

4✔
2075
                case lnwire.CodeInvalidOnionKey:
×
2076
                        failure = &lnwire.FailInvalidOnionKey{
×
2077
                                OnionSHA256: msg.ShaOnionBlob,
×
2078
                        }
×
2079

2080
                // Handle malformed errors that are part of a blinded route.
×
2081
                // This case is slightly different, because we expect every
×
2082
                // relaying node in the blinded portion of the route to send
×
2083
                // malformed errors. If we're also a relaying node, we're
×
2084
                // likely going to switch this error out anyway for our own
2085
                // malformed error, but we handle the case here for
2086
                // completeness.
2087
                case lnwire.CodeInvalidBlinding:
2088
                        failure = &lnwire.FailInvalidBlinding{
2089
                                OnionSHA256: msg.ShaOnionBlob,
2090
                        }
2091

2092
                default:
4✔
2093
                        l.log.Warnf("unexpected failure code received in "+
4✔
2094
                                "UpdateFailMailformedHTLC: %v", msg.FailureCode)
4✔
2095

4✔
2096
                        // We don't just pass back the error we received from
UNCOV
2097
                        // our successor. Otherwise we might report a failure
×
UNCOV
2098
                        // that penalizes us more than needed. If the onion that
×
UNCOV
2099
                        // we forwarded was correct, the node should have been
×
UNCOV
2100
                        // able to send back its own failure. The node did not
×
UNCOV
2101
                        // send back its own failure, so we assume there was a
×
UNCOV
2102
                        // problem with the onion and report that back. We reuse
×
UNCOV
2103
                        // the invalid onion key failure because there is no
×
UNCOV
2104
                        // specific error for this case.
×
UNCOV
2105
                        failure = &lnwire.FailInvalidOnionKey{
×
UNCOV
2106
                                OnionSHA256: msg.ShaOnionBlob,
×
UNCOV
2107
                        }
×
UNCOV
2108
                }
×
UNCOV
2109

×
UNCOV
2110
                // With the error parsed, we'll convert the into it's opaque
×
UNCOV
2111
                // form.
×
UNCOV
2112
                var b bytes.Buffer
×
2113
                if err := lnwire.EncodeFailure(&b, failure, 0); err != nil {
2114
                        l.log.Errorf("unable to encode malformed error: %v", err)
2115
                        return
2116
                }
2117

4✔
2118
                // If remote side have been unable to parse the onion blob we
4✔
2119
                // have sent to it, than we should transform the malformed HTLC
×
2120
                // message to the usual HTLC fail message.
×
2121
                err := l.channel.ReceiveFailHTLC(msg.ID, b.Bytes())
×
2122
                if err != nil {
2123
                        l.failf(LinkFailureError{code: ErrInvalidUpdate},
2124
                                "unable to handle upstream fail HTLC: %v", err)
2125
                        return
2126
                }
4✔
2127

4✔
2128
        case *lnwire.UpdateFailHTLC:
×
2129
                // Verify that the failure reason is at least 256 bytes plus
×
2130
                // overhead.
×
2131
                const minimumFailReasonLength = lnwire.FailureMessageLength +
×
2132
                        2 + 2 + 32
2133

4✔
2134
                if len(msg.Reason) < minimumFailReasonLength {
4✔
2135
                        // We've received a reason with a non-compliant length.
4✔
2136
                        // Older nodes happily relay back these failures that
4✔
2137
                        // may originate from a node further downstream.
4✔
2138
                        // Therefore we can't just fail the channel.
4✔
2139
                        //
4✔
UNCOV
2140
                        // We want to be compliant ourselves, so we also can't
×
UNCOV
2141
                        // pass back the reason unmodified. And we must make
×
UNCOV
2142
                        // sure that we don't hit the magic length check of 260
×
UNCOV
2143
                        // bytes in processRemoteSettleFails either.
×
UNCOV
2144
                        //
×
UNCOV
2145
                        // Because the reason is unreadable for the payer
×
UNCOV
2146
                        // anyway, we just replace it by a compliant-length
×
UNCOV
2147
                        // series of random bytes.
×
UNCOV
2148
                        msg.Reason = make([]byte, minimumFailReasonLength)
×
UNCOV
2149
                        _, err := crand.Read(msg.Reason[:])
×
UNCOV
2150
                        if err != nil {
×
UNCOV
2151
                                l.log.Errorf("Random generation error: %v", err)
×
UNCOV
2152

×
UNCOV
2153
                                return
×
UNCOV
2154
                        }
×
UNCOV
2155
                }
×
2156

×
2157
                // Add fail to the update log.
×
2158
                idx := msg.ID
×
2159
                err := l.channel.ReceiveFailHTLC(idx, msg.Reason[:])
×
2160
                if err != nil {
2161
                        l.failf(LinkFailureError{code: ErrInvalidUpdate},
2162
                                "unable to handle upstream fail HTLC: %v", err)
2163
                        return
4✔
2164
                }
4✔
2165

4✔
2166
        case *lnwire.CommitSig:
×
2167
                // Since we may have learned new preimages for the first time,
×
2168
                // we'll add them to our preimage cache. By doing this, we
×
2169
                // ensure any contested contracts watched by any on-chain
×
2170
                // arbitrators can now sweep this HTLC on-chain. We delay
2171
                // committing the preimages until just before accepting the new
4✔
2172
                // remote commitment, as afterwards the peer won't resend the
4✔
2173
                // Settle messages on the next channel reestablishment. Doing so
4✔
2174
                // allows us to more effectively batch this operation, instead
4✔
2175
                // of doing a single write per preimage.
4✔
2176
                err := l.cfg.PreimageCache.AddPreimages(
4✔
2177
                        l.uncommittedPreimages...,
4✔
2178
                )
4✔
2179
                if err != nil {
4✔
2180
                        l.failf(
4✔
2181
                                LinkFailureError{code: ErrInternalError},
4✔
2182
                                "unable to add preimages=%v to cache: %v",
4✔
2183
                                l.uncommittedPreimages, err,
4✔
2184
                        )
4✔
2185
                        return
×
2186
                }
×
2187

×
2188
                // Instead of truncating the slice to conserve memory
×
2189
                // allocations, we simply set the uncommitted preimage slice to
×
2190
                // nil so that a new one will be initialized if any more
×
2191
                // witnesses are discovered. We do this because the maximum size
×
2192
                // that the slice can occupy is 15KB, and we want to ensure we
2193
                // release that memory back to the runtime.
2194
                l.uncommittedPreimages = nil
2195

2196
                // We just received a new updates to our local commitment
2197
                // chain, validate this new commitment, closing the link if
2198
                // invalid.
2199
                auxSigBlob, err := msg.CustomRecords.Serialize()
4✔
2200
                if err != nil {
4✔
2201
                        l.failf(
4✔
2202
                                LinkFailureError{code: ErrInvalidCommitment},
4✔
2203
                                "unable to serialize custom records: %v", err,
4✔
2204
                        )
4✔
2205

4✔
2206
                        return
×
2207
                }
×
2208
                err = l.channel.ReceiveNewCommitment(&lnwallet.CommitSigs{
×
2209
                        CommitSig:  msg.CommitSig,
×
2210
                        HtlcSigs:   msg.HtlcSigs,
×
2211
                        PartialSig: msg.PartialSig,
×
2212
                        AuxSigBlob: auxSigBlob,
×
2213
                })
4✔
2214
                if err != nil {
4✔
2215
                        // If we were unable to reconstruct their proposed
4✔
2216
                        // commitment, then we'll examine the type of error. If
4✔
2217
                        // it's an InvalidCommitSigError, then we'll send a
4✔
2218
                        // direct error.
4✔
2219
                        var sendData []byte
4✔
2220
                        switch err.(type) {
×
2221
                        case *lnwallet.InvalidCommitSigError:
×
2222
                                sendData = []byte(err.Error())
×
2223
                        case *lnwallet.InvalidHtlcSigError:
×
2224
                                sendData = []byte(err.Error())
×
2225
                        }
×
2226
                        l.failf(
×
2227
                                LinkFailureError{
×
2228
                                        code:          ErrInvalidCommitment,
×
2229
                                        FailureAction: LinkFailureForceClose,
×
2230
                                        SendData:      sendData,
2231
                                },
×
2232
                                "ChannelPoint(%v): unable to accept new "+
×
2233
                                        "commitment: %v",
×
2234
                                l.channel.ChannelPoint(), err,
×
2235
                        )
×
2236
                        return
×
2237
                }
×
2238

×
2239
                // As we've just accepted a new state, we'll now
×
2240
                // immediately send the remote peer a revocation for our prior
×
2241
                // state.
×
2242
                nextRevocation, currentHtlcs, finalHTLCs, err :=
2243
                        l.channel.RevokeCurrentCommitment()
2244
                if err != nil {
2245
                        l.log.Errorf("unable to revoke commitment: %v", err)
2246

2247
                        // We need to fail the channel in case revoking our
4✔
2248
                        // local commitment does not succeed. We might have
4✔
2249
                        // already advanced our channel state which would lead
4✔
2250
                        // us to proceed with an unclean state.
×
2251
                        //
×
2252
                        // NOTE: We do not trigger a force close because this
×
2253
                        // could resolve itself in case our db was just busy
×
2254
                        // not accepting new transactions.
×
2255
                        l.failf(
×
2256
                                LinkFailureError{
×
2257
                                        code:          ErrInternalError,
×
2258
                                        Warning:       true,
×
2259
                                        FailureAction: LinkFailureDisconnect,
×
2260
                                },
×
2261
                                "ChannelPoint(%v): unable to accept new "+
×
2262
                                        "commitment: %v",
×
2263
                                l.channel.ChannelPoint(), err,
×
2264
                        )
×
2265
                        return
×
2266
                }
×
2267

×
2268
                // As soon as we are ready to send our next revocation, we can
×
2269
                // invoke the incoming commit hooks.
×
2270
                l.RWMutex.Lock()
×
2271
                l.incomingCommitHooks.invoke()
×
2272
                l.RWMutex.Unlock()
2273

2274
                l.cfg.Peer.SendMessage(false, nextRevocation)
2275

4✔
2276
                // Notify the incoming htlcs of which the resolutions were
4✔
2277
                // locked in.
4✔
2278
                for id, settled := range finalHTLCs {
4✔
2279
                        l.cfg.HtlcNotifier.NotifyFinalHtlcEvent(
4✔
2280
                                models.CircuitKey{
4✔
2281
                                        ChanID: l.ShortChanID(),
4✔
2282
                                        HtlcID: id,
4✔
2283
                                },
8✔
2284
                                channeldb.FinalHtlcInfo{
4✔
2285
                                        Settled:  settled,
4✔
2286
                                        Offchain: true,
4✔
2287
                                },
4✔
2288
                        )
4✔
2289
                }
4✔
2290

4✔
2291
                // Since we just revoked our commitment, we may have a new set
4✔
2292
                // of HTLC's on our commitment, so we'll send them using our
4✔
2293
                // function closure NotifyContractUpdate.
4✔
2294
                newUpdate := &contractcourt.ContractUpdate{
4✔
2295
                        HtlcKey: contractcourt.LocalHtlcSet,
2296
                        Htlcs:   currentHtlcs,
2297
                }
2298
                err = l.cfg.NotifyContractUpdate(newUpdate)
2299
                if err != nil {
4✔
2300
                        l.log.Errorf("unable to notify contract update: %v",
4✔
2301
                                err)
4✔
2302
                        return
4✔
2303
                }
4✔
2304

4✔
2305
                select {
×
2306
                case <-l.Quit:
×
2307
                        return
×
2308
                default:
×
2309
                }
2310

4✔
2311
                // If the remote party initiated the state transition,
×
2312
                // we'll reply with a signature to provide them with their
×
2313
                // version of the latest commitment. Otherwise, both commitment
4✔
2314
                // chains are fully synced from our PoV, then we don't need to
2315
                // reply with a signature as both sides already have a
2316
                // commitment with the latest accepted.
2317
                if l.channel.OweCommitment() {
2318
                        if !l.updateCommitTxOrFail() {
2319
                                return
2320
                        }
2321
                }
2322

8✔
2323
                // Now that we have finished processing the incoming CommitSig
4✔
2324
                // and sent out our RevokeAndAck, we invoke the flushHooks if
×
2325
                // the channel state is clean.
×
2326
                l.RWMutex.Lock()
2327
                if l.channel.IsChannelClean() {
2328
                        l.flushHooks.invoke()
2329
                }
2330
                l.RWMutex.Unlock()
2331

4✔
2332
        case *lnwire.RevokeAndAck:
8✔
2333
                // We've received a revocation from the remote chain, if valid,
4✔
2334
                // this moves the remote chain forward, and expands our
4✔
2335
                // revocation window.
4✔
2336

2337
                // We now process the message and advance our remote commit
4✔
2338
                // chain.
4✔
2339
                fwdPkg, remoteHTLCs, err := l.channel.ReceiveRevocation(msg)
4✔
2340
                if err != nil {
4✔
2341
                        // TODO(halseth): force close?
4✔
2342
                        l.failf(
4✔
2343
                                LinkFailureError{
4✔
2344
                                        code:          ErrInvalidRevocation,
4✔
2345
                                        FailureAction: LinkFailureDisconnect,
4✔
2346
                                },
×
2347
                                "unable to accept revocation: %v", err,
×
2348
                        )
×
2349
                        return
×
2350
                }
×
2351

×
2352
                // The remote party now has a new primary commitment, so we'll
×
2353
                // update the contract court to be aware of this new set (the
×
2354
                // prior old remote pending).
×
2355
                newUpdate := &contractcourt.ContractUpdate{
×
2356
                        HtlcKey: contractcourt.RemoteHtlcSet,
2357
                        Htlcs:   remoteHTLCs,
2358
                }
2359
                err = l.cfg.NotifyContractUpdate(newUpdate)
2360
                if err != nil {
4✔
2361
                        l.log.Errorf("unable to notify contract update: %v",
4✔
2362
                                err)
4✔
2363
                        return
4✔
2364
                }
4✔
2365

4✔
2366
                select {
×
2367
                case <-l.Quit:
×
2368
                        return
×
2369
                default:
×
2370
                }
2371

4✔
UNCOV
2372
                // If we have a tower client for this channel type, we'll
×
UNCOV
2373
                // create a backup for the current state.
×
2374
                if l.cfg.TowerClient != nil {
4✔
2375
                        state := l.channel.State()
2376
                        chanID := l.ChanID()
2377

2378
                        err = l.cfg.TowerClient.BackupState(
2379
                                &chanID, state.RemoteCommitment.CommitHeight-1,
8✔
2380
                        )
4✔
2381
                        if err != nil {
4✔
2382
                                l.failf(LinkFailureError{
4✔
2383
                                        code: ErrInternalError,
4✔
2384
                                }, "unable to queue breach backup: %v", err)
4✔
2385
                                return
4✔
2386
                        }
4✔
2387
                }
×
2388

×
2389
                l.processRemoteSettleFails(fwdPkg)
×
2390
                l.processRemoteAdds(fwdPkg)
×
2391

×
2392
                // If the link failed during processing the adds, we must
2393
                // return to ensure we won't attempted to update the state
2394
                // further.
4✔
2395
                if l.failed {
4✔
2396
                        return
4✔
2397
                }
4✔
2398

4✔
2399
                // The revocation window opened up. If there are pending local
4✔
2400
                // updates, try to update the commit tx. Pending updates could
8✔
2401
                // already have been present because of a previously failed
4✔
2402
                // update to the commit tx or freshly added in by
4✔
2403
                // processRemoteAdds. Also in case there are no local updates,
2404
                // but there are still remote updates that are not in the remote
2405
                // commit tx yet, send out an update.
2406
                if l.channel.OweCommitment() {
2407
                        if !l.updateCommitTxOrFail() {
2408
                                return
2409
                        }
2410
                }
2411

8✔
2412
                // Now that we have finished processing the RevokeAndAck, we
4✔
UNCOV
2413
                // can invoke the flushHooks if the channel state is clean.
×
UNCOV
2414
                l.RWMutex.Lock()
×
2415
                if l.channel.IsChannelClean() {
2416
                        l.flushHooks.invoke()
2417
                }
2418
                l.RWMutex.Unlock()
2419

4✔
2420
        case *lnwire.UpdateFee:
8✔
2421
                // Check and see if their proposed fee-rate would make us
4✔
2422
                // exceed the fee threshold.
4✔
2423
                fee := chainfee.SatPerKWeight(msg.FeePerKw)
4✔
2424

UNCOV
2425
                isDust, err := l.exceedsFeeExposureLimit(fee)
×
UNCOV
2426
                if err != nil {
×
UNCOV
2427
                        // This shouldn't typically happen. If it does, it
×
UNCOV
2428
                        // indicates something is wrong with our channel state.
×
UNCOV
2429
                        l.log.Errorf("Unable to determine if fee threshold " +
×
UNCOV
2430
                                "exceeded")
×
UNCOV
2431
                        l.failf(LinkFailureError{code: ErrInternalError},
×
2432
                                "error calculating fee exposure: %v", err)
×
2433

×
2434
                        return
×
2435
                }
×
2436

×
2437
                if isDust {
×
2438
                        // The proposed fee-rate makes us exceed the fee
×
2439
                        // threshold.
×
2440
                        l.failf(LinkFailureError{code: ErrInternalError},
×
2441
                                "fee threshold exceeded: %v", err)
UNCOV
2442
                        return
×
2443
                }
×
2444

×
2445
                // We received fee update from peer. If we are the initiator we
×
2446
                // will fail the channel, if not we will apply the update.
×
2447
                if err := l.channel.ReceiveUpdateFee(fee); err != nil {
×
2448
                        l.failf(LinkFailureError{code: ErrInvalidUpdate},
×
2449
                                "error receiving fee update: %v", err)
2450
                        return
2451
                }
UNCOV
2452

×
2453
                // Update the mailbox's feerate as well.
×
2454
                l.mailBox.SetFeeRate(fee)
×
2455

×
2456
        // In the case where we receive a warning message from our peer, just
×
2457
        // log it and move on. We choose not to disconnect from our peer,
2458
        // although we "MAY" do so according to the specification.
UNCOV
2459
        case *lnwire.Warning:
×
2460
                l.log.Warnf("received warning message from peer: %v",
2461
                        msg.Warning())
2462

2463
        case *lnwire.Error:
UNCOV
2464
                // Error received from remote, MUST fail channel, but should
×
UNCOV
2465
                // only print the contents of the error message if all
×
UNCOV
2466
                // characters are printable ASCII.
×
2467
                l.failf(
2468
                        LinkFailureError{
4✔
2469
                                code: ErrRemoteError,
4✔
2470

4✔
2471
                                // TODO(halseth): we currently don't fail the
4✔
2472
                                // channel permanently, as there are some sync
4✔
2473
                                // issues with other implementations that will
4✔
2474
                                // lead to them sending an error message, but
4✔
2475
                                // we can recover from on next connection. See
4✔
2476
                                // https://github.com/ElementsProject/lightning/issues/4212
4✔
2477
                                PermanentFailure: false,
4✔
2478
                        },
4✔
2479
                        "ChannelPoint(%v): received error from peer: %v",
4✔
2480
                        l.channel.ChannelPoint(), msg.Error(),
4✔
2481
                )
4✔
2482
        default:
4✔
2483
                l.log.Warnf("received unknown message of type %T", msg)
4✔
2484
        }
4✔
2485

4✔
2486
}
4✔
2487

×
2488
// ackDownStreamPackets is responsible for removing htlcs from a link's mailbox
×
2489
// for packets delivered from server, and cleaning up any circuits closed by
2490
// signing a previous commitment txn. This method ensures that the circuits are
2491
// removed from the circuit map before removing them from the link's mailbox,
2492
// otherwise it could be possible for some circuit to be missed if this link
2493
// flaps.
2494
func (l *channelLink) ackDownStreamPackets() error {
2495
        // First, remove the downstream Add packets that were included in the
2496
        // previous commitment signature. This will prevent the Adds from being
2497
        // replayed if this link disconnects.
2498
        for _, inKey := range l.openedCircuits {
2499
                // In order to test the sphinx replay logic of the remote
4✔
2500
                // party, unsafe replay does not acknowledge the packets from
4✔
2501
                // the mailbox. We can then force a replay of any Add packets
4✔
2502
                // held in memory by disconnecting and reconnecting the link.
4✔
2503
                if l.cfg.UnsafeReplay {
8✔
2504
                        continue
4✔
2505
                }
4✔
2506

4✔
2507
                l.log.Debugf("removing Add packet %s from mailbox", inKey)
4✔
2508
                l.mailBox.AckPacket(inKey)
8✔
2509
        }
4✔
2510

2511
        // Now, we will delete all circuits closed by the previous commitment
2512
        // signature, which is the result of downstream Settle/Fail packets. We
4✔
2513
        // batch them here to ensure circuits are closed atomically and for
4✔
2514
        // performance.
2515
        err := l.cfg.Circuits.DeleteCircuits(l.closedCircuits...)
2516
        switch err {
2517
        case nil:
2518
                // Successful deletion.
2519

2520
        default:
4✔
2521
                l.log.Errorf("unable to delete %d circuits: %v",
4✔
2522
                        len(l.closedCircuits), err)
4✔
2523
                return err
2524
        }
2525

×
2526
        // With the circuits removed from memory and disk, we now ack any
×
2527
        // Settle/Fails in the mailbox to ensure they do not get redelivered
×
2528
        // after startup. If forgive is enabled and we've reached this point,
×
2529
        // the circuits must have been removed at some point, so it is now safe
2530
        // to un-queue the corresponding Settle/Fails.
2531
        for _, inKey := range l.closedCircuits {
2532
                l.log.Debugf("removing Fail/Settle packet %s from mailbox",
2533
                        inKey)
2534
                l.mailBox.AckPacket(inKey)
2535
        }
2536

8✔
2537
        // Lastly, reset our buffers to be empty while keeping any acquired
4✔
2538
        // growth in the backing array.
4✔
2539
        l.openedCircuits = l.openedCircuits[:0]
4✔
2540
        l.closedCircuits = l.closedCircuits[:0]
4✔
2541

2542
        return nil
2543
}
2544

4✔
2545
// updateCommitTxOrFail updates the commitment tx and if that fails, it fails
4✔
2546
// the link.
4✔
2547
func (l *channelLink) updateCommitTxOrFail() bool {
4✔
2548
        err := l.updateCommitTx()
2549
        switch err {
2550
        // No error encountered, success.
2551
        case nil:
2552

4✔
2553
        // A duplicate keystone error should be resolved and is not fatal, so
4✔
2554
        // we won't send an Error message to the peer.
4✔
2555
        case ErrDuplicateKeystone:
2556
                l.failf(LinkFailureError{code: ErrCircuitError},
4✔
2557
                        "temporary circuit error: %v", err)
2558
                return false
2559

2560
        // Any other error is treated results in an Error message being sent to
×
2561
        // the peer.
×
2562
        default:
×
2563
                l.failf(LinkFailureError{code: ErrInternalError},
×
2564
                        "unable to update commitment: %v", err)
2565
                return false
2566
        }
UNCOV
2567

×
UNCOV
2568
        return true
×
UNCOV
2569
}
×
UNCOV
2570

×
2571
// updateCommitTx signs, then sends an update to the remote peer adding a new
2572
// commitment to their commitment chain which includes all the latest updates
2573
// we've received+processed up to this point.
4✔
2574
func (l *channelLink) updateCommitTx() error {
2575
        // Preemptively write all pending keystones to disk, just in case the
2576
        // HTLCs we have in memory are included in the subsequent attempt to
2577
        // sign a commitment state.
2578
        err := l.cfg.Circuits.OpenCircuits(l.keystoneBatch...)
2579
        if err != nil {
4✔
2580
                // If ErrDuplicateKeystone is returned, the caller will catch
4✔
2581
                // it.
4✔
2582
                return err
4✔
2583
        }
4✔
2584

4✔
2585
        // Reset the batch, but keep the backing buffer to avoid reallocating.
×
2586
        l.keystoneBatch = l.keystoneBatch[:0]
×
2587

×
2588
        // If hodl.Commit mode is active, we will refrain from attempting to
×
2589
        // commit any in-memory modifications to the channel state. Exiting here
2590
        // permits testing of either the switch or link's ability to trim
2591
        // circuits that have been opened, but unsuccessfully committed.
4✔
2592
        if l.cfg.HodlMask.Active(hodl.Commit) {
4✔
2593
                l.log.Warnf(hodl.Commit.Warning())
4✔
2594
                return nil
4✔
2595
        }
4✔
2596

4✔
2597
        ctx, done := l.WithCtxQuitNoTimeout()
8✔
2598
        defer done()
4✔
2599

4✔
2600
        newCommit, err := l.channel.SignNextCommitment(ctx)
4✔
2601
        if err == lnwallet.ErrNoWindow {
2602
                l.cfg.PendingCommitTicker.Resume()
4✔
2603
                l.log.Trace("PendingCommitTicker resumed")
4✔
2604

4✔
2605
                n := l.channel.NumPendingUpdates(lntypes.Local, lntypes.Remote)
4✔
2606
                l.log.Tracef("revocation window exhausted, unable to send: "+
8✔
2607
                        "%v, pend_updates=%v, dangling_closes%v", n,
4✔
2608
                        lnutils.SpewLogClosure(l.openedCircuits),
4✔
2609
                        lnutils.SpewLogClosure(l.closedCircuits))
4✔
2610

4✔
2611
                return nil
4✔
2612
        } else if err != nil {
4✔
2613
                return err
4✔
2614
        }
4✔
2615

4✔
2616
        if err := l.ackDownStreamPackets(); err != nil {
4✔
2617
                return err
8✔
2618
        }
×
2619

×
2620
        l.cfg.PendingCommitTicker.Pause()
2621
        l.log.Trace("PendingCommitTicker paused after ackDownStreamPackets")
4✔
2622

×
2623
        // The remote party now has a new pending commitment, so we'll update
×
2624
        // the contract court to be aware of this new set (the prior old remote
2625
        // pending).
4✔
2626
        newUpdate := &contractcourt.ContractUpdate{
4✔
2627
                HtlcKey: contractcourt.RemotePendingHtlcSet,
4✔
2628
                Htlcs:   newCommit.PendingHTLCs,
4✔
2629
        }
4✔
2630
        err = l.cfg.NotifyContractUpdate(newUpdate)
4✔
2631
        if err != nil {
4✔
2632
                l.log.Errorf("unable to notify contract update: %v", err)
4✔
2633
                return err
4✔
2634
        }
4✔
2635

4✔
2636
        select {
4✔
2637
        case <-l.Quit:
×
2638
                return ErrLinkShuttingDown
×
2639
        default:
×
2640
        }
2641

4✔
UNCOV
2642
        auxBlobRecords, err := lnwire.ParseCustomRecords(newCommit.AuxSigBlob)
×
UNCOV
2643
        if err != nil {
×
2644
                return fmt.Errorf("error parsing aux sigs: %w", err)
4✔
2645
        }
2646

2647
        commitSig := &lnwire.CommitSig{
4✔
2648
                ChanID:        l.ChanID(),
4✔
2649
                CommitSig:     newCommit.CommitSig,
×
2650
                HtlcSigs:      newCommit.HtlcSigs,
×
2651
                PartialSig:    newCommit.PartialSig,
2652
                CustomRecords: auxBlobRecords,
4✔
2653
        }
4✔
2654
        l.cfg.Peer.SendMessage(false, commitSig)
4✔
2655

4✔
2656
        // Now that we have sent out a new CommitSig, we invoke the outgoing set
4✔
2657
        // of commit hooks.
4✔
2658
        l.RWMutex.Lock()
4✔
2659
        l.outgoingCommitHooks.invoke()
4✔
2660
        l.RWMutex.Unlock()
4✔
2661

4✔
2662
        return nil
4✔
2663
}
4✔
2664

4✔
2665
// Peer returns the representation of remote peer with which we have the
4✔
2666
// channel link opened.
4✔
2667
//
4✔
2668
// NOTE: Part of the ChannelLink interface.
2669
func (l *channelLink) PeerPubKey() [33]byte {
2670
        return l.cfg.Peer.PubKey()
2671
}
2672

2673
// ChannelPoint returns the channel outpoint for the channel link.
2674
// NOTE: Part of the ChannelLink interface.
4✔
2675
func (l *channelLink) ChannelPoint() wire.OutPoint {
4✔
2676
        return l.channel.ChannelPoint()
4✔
2677
}
2678

2679
// ShortChanID returns the short channel ID for the channel link. The short
2680
// channel ID encodes the exact location in the main chain that the original
4✔
2681
// funding output can be found.
4✔
2682
//
4✔
2683
// NOTE: Part of the ChannelLink interface.
2684
func (l *channelLink) ShortChanID() lnwire.ShortChannelID {
2685
        l.RLock()
2686
        defer l.RUnlock()
2687

2688
        return l.channel.ShortChanID()
2689
}
4✔
2690

4✔
2691
// UpdateShortChanID updates the short channel ID for a link. This may be
4✔
2692
// required in the event that a link is created before the short chan ID for it
4✔
2693
// is known, or a re-org occurs, and the funding transaction changes location
4✔
2694
// within the chain.
4✔
2695
//
2696
// NOTE: Part of the ChannelLink interface.
2697
func (l *channelLink) UpdateShortChanID() (lnwire.ShortChannelID, error) {
2698
        chanID := l.ChanID()
2699

2700
        // Refresh the channel state's short channel ID by loading it from disk.
2701
        // This ensures that the channel state accurately reflects the updated
2702
        // short channel ID.
4✔
2703
        err := l.channel.State().Refresh()
4✔
2704
        if err != nil {
4✔
2705
                l.log.Errorf("unable to refresh short_chan_id for chan_id=%v: "+
4✔
2706
                        "%v", chanID, err)
4✔
2707
                return hop.Source, err
4✔
2708
        }
4✔
2709

4✔
2710
        return hop.Source, nil
×
2711
}
×
2712

×
2713
// ChanID returns the channel ID for the channel link. The channel ID is a more
×
2714
// compact representation of a channel's full outpoint.
2715
//
4✔
2716
// NOTE: Part of the ChannelLink interface.
2717
func (l *channelLink) ChanID() lnwire.ChannelID {
2718
        return lnwire.NewChanIDFromOutPoint(l.channel.ChannelPoint())
2719
}
2720

2721
// Bandwidth returns the total amount that can flow through the channel link at
2722
// this given instance. The value returned is expressed in millisatoshi and can
4✔
2723
// be used by callers when making forwarding decisions to determine if a link
4✔
2724
// can accept an HTLC.
4✔
2725
//
2726
// NOTE: Part of the ChannelLink interface.
2727
func (l *channelLink) Bandwidth() lnwire.MilliSatoshi {
2728
        // Get the balance available on the channel for new HTLCs. This takes
2729
        // the channel reserve into account so HTLCs up to this value won't
2730
        // violate it.
2731
        return l.channel.AvailableBalance()
2732
}
4✔
2733

4✔
2734
// MayAddOutgoingHtlc indicates whether we can add an outgoing htlc with the
4✔
2735
// amount provided to the link. This check does not reserve a space, since
4✔
2736
// forwards or other payments may use the available slot, so it should be
4✔
2737
// considered best-effort.
4✔
2738
func (l *channelLink) MayAddOutgoingHtlc(amt lnwire.MilliSatoshi) error {
2739
        return l.channel.MayAddOutgoingHtlc(amt)
2740
}
2741

2742
// getDustSum is a wrapper method that calls the underlying channel's dust sum
2743
// method.
4✔
2744
//
4✔
2745
// NOTE: Part of the dustHandler interface.
4✔
2746
func (l *channelLink) getDustSum(whoseCommit lntypes.ChannelParty,
2747
        dryRunFee fn.Option[chainfee.SatPerKWeight]) lnwire.MilliSatoshi {
2748

2749
        return l.channel.GetDustSum(whoseCommit, dryRunFee)
2750
}
2751

2752
// getFeeRate is a wrapper method that retrieves the underlying channel's
4✔
2753
// feerate.
4✔
2754
//
4✔
2755
// NOTE: Part of the dustHandler interface.
4✔
2756
func (l *channelLink) getFeeRate() chainfee.SatPerKWeight {
2757
        return l.channel.CommitFeeRate()
2758
}
2759

2760
// getDustClosure returns a closure that can be used by the switch or mailbox
2761
// to evaluate whether a given HTLC is dust.
4✔
2762
//
4✔
2763
// NOTE: Part of the dustHandler interface.
4✔
2764
func (l *channelLink) getDustClosure() dustClosure {
2765
        localDustLimit := l.channel.State().LocalChanCfg.DustLimit
2766
        remoteDustLimit := l.channel.State().RemoteChanCfg.DustLimit
2767
        chanType := l.channel.State().ChanType
2768

2769
        return dustHelper(chanType, localDustLimit, remoteDustLimit)
4✔
2770
}
4✔
2771

4✔
2772
// getCommitFee returns either the local or remote CommitFee in satoshis. This
4✔
2773
// is used so that the Switch can have access to the commitment fee without
4✔
2774
// needing to have a *LightningChannel. This doesn't include dust.
4✔
2775
//
4✔
2776
// NOTE: Part of the dustHandler interface.
2777
func (l *channelLink) getCommitFee(remote bool) btcutil.Amount {
2778
        if remote {
2779
                return l.channel.State().RemoteCommitment.CommitFee
2780
        }
2781

2782
        return l.channel.State().LocalCommitment.CommitFee
4✔
2783
}
8✔
2784

4✔
2785
// exceedsFeeExposureLimit returns whether or not the new proposed fee-rate
4✔
2786
// increases the total dust and fees within the channel past the configured
2787
// fee threshold. It first calculates the dust sum over every update in the
4✔
2788
// update log with the proposed fee-rate and taking into account both the local
2789
// and remote dust limits. It uses every update in the update log instead of
2790
// what is actually on the local and remote commitments because it is assumed
2791
// that in a worst-case scenario, every update in the update log could
2792
// theoretically be on either commitment transaction and this needs to be
2793
// accounted for with this fee-rate. It then calculates the local and remote
2794
// commitment fees given the proposed fee-rate. Finally, it tallies the results
2795
// and determines if the fee threshold has been exceeded.
2796
func (l *channelLink) exceedsFeeExposureLimit(
2797
        feePerKw chainfee.SatPerKWeight) (bool, error) {
2798

2799
        dryRunFee := fn.Some[chainfee.SatPerKWeight](feePerKw)
2800

2801
        // Get the sum of dust for both the local and remote commitments using
UNCOV
2802
        // this "dry-run" fee.
×
UNCOV
2803
        localDustSum := l.getDustSum(lntypes.Local, dryRunFee)
×
UNCOV
2804
        remoteDustSum := l.getDustSum(lntypes.Remote, dryRunFee)
×
UNCOV
2805

×
UNCOV
2806
        // Calculate the local and remote commitment fees using this dry-run
×
UNCOV
2807
        // fee.
×
UNCOV
2808
        localFee, remoteFee, err := l.channel.CommitFeeTotalAt(feePerKw)
×
UNCOV
2809
        if err != nil {
×
UNCOV
2810
                return false, err
×
UNCOV
2811
        }
×
UNCOV
2812

×
UNCOV
2813
        // Finally, check whether the max fee exposure was exceeded on either
×
UNCOV
2814
        // future commitment transaction with the fee-rate.
×
2815
        totalLocalDust := localDustSum + lnwire.NewMSatFromSatoshis(localFee)
×
2816
        if totalLocalDust > l.cfg.MaxFeeExposure {
×
2817
                l.log.Debugf("ChannelLink(%v): exceeds fee exposure limit: "+
2818
                        "local dust: %v, local fee: %v", l.ShortChanID(),
2819
                        totalLocalDust, localFee)
UNCOV
2820

×
UNCOV
2821
                return true, nil
×
2822
        }
×
2823

×
2824
        totalRemoteDust := remoteDustSum + lnwire.NewMSatFromSatoshis(
×
2825
                remoteFee,
×
2826
        )
×
2827

×
2828
        if totalRemoteDust > l.cfg.MaxFeeExposure {
UNCOV
2829
                l.log.Debugf("ChannelLink(%v): exceeds fee exposure limit: "+
×
UNCOV
2830
                        "remote dust: %v, remote fee: %v", l.ShortChanID(),
×
UNCOV
2831
                        totalRemoteDust, remoteFee)
×
UNCOV
2832

×
UNCOV
2833
                return true, nil
×
2834
        }
×
2835

×
2836
        return false, nil
×
2837
}
×
2838

×
2839
// isOverexposedWithHtlc calculates whether the proposed HTLC will make the
×
2840
// channel exceed the fee threshold. It first fetches the largest fee-rate that
UNCOV
2841
// may be on any unrevoked commitment transaction. Then, using this fee-rate,
×
2842
// determines if the to-be-added HTLC is dust. If the HTLC is dust, it adds to
2843
// the overall dust sum. If it is not dust, it contributes to weight, which
2844
// also adds to the overall dust sum by an increase in fees. If the dust sum on
2845
// either commitment exceeds the configured fee threshold, this function
2846
// returns true.
2847
func (l *channelLink) isOverexposedWithHtlc(htlc *lnwire.UpdateAddHTLC,
2848
        incoming bool) bool {
2849

2850
        dustClosure := l.getDustClosure()
2851

2852
        feeRate := l.channel.WorstCaseFeeRate()
2853

4✔
2854
        amount := htlc.Amount.ToSatoshis()
4✔
2855

4✔
2856
        // See if this HTLC is dust on both the local and remote commitments.
4✔
2857
        isLocalDust := dustClosure(feeRate, incoming, lntypes.Local, amount)
4✔
2858
        isRemoteDust := dustClosure(feeRate, incoming, lntypes.Remote, amount)
4✔
2859

4✔
2860
        // Calculate the dust sum for the local and remote commitments.
4✔
2861
        localDustSum := l.getDustSum(
4✔
2862
                lntypes.Local, fn.None[chainfee.SatPerKWeight](),
4✔
2863
        )
4✔
2864
        remoteDustSum := l.getDustSum(
4✔
2865
                lntypes.Remote, fn.None[chainfee.SatPerKWeight](),
4✔
2866
        )
4✔
2867

4✔
2868
        // Grab the larger of the local and remote commitment fees w/o dust.
4✔
2869
        commitFee := l.getCommitFee(false)
4✔
2870

4✔
2871
        if l.getCommitFee(true) > commitFee {
4✔
2872
                commitFee = l.getCommitFee(true)
4✔
2873
        }
4✔
2874

4✔
2875
        commitFeeMSat := lnwire.NewMSatFromSatoshis(commitFee)
4✔
2876

8✔
2877
        localDustSum += commitFeeMSat
4✔
2878
        remoteDustSum += commitFeeMSat
4✔
2879

2880
        // Calculate the additional fee increase if this is a non-dust HTLC.
4✔
2881
        weight := lntypes.WeightUnit(input.HTLCWeight)
4✔
2882
        additional := lnwire.NewMSatFromSatoshis(
4✔
2883
                feeRate.FeeForWeight(weight),
4✔
2884
        )
4✔
2885

4✔
2886
        if isLocalDust {
4✔
2887
                // If this is dust, it doesn't contribute to weight but does
4✔
2888
                // contribute to the overall dust sum.
4✔
2889
                localDustSum += lnwire.NewMSatFromSatoshis(amount)
4✔
2890
        } else {
4✔
2891
                // Account for the fee increase that comes with an increase in
8✔
2892
                // weight.
4✔
2893
                localDustSum += additional
4✔
2894
        }
4✔
2895

8✔
2896
        if localDustSum > l.cfg.MaxFeeExposure {
4✔
2897
                // The max fee exposure was exceeded.
4✔
2898
                l.log.Debugf("ChannelLink(%v): HTLC %v makes the channel "+
4✔
2899
                        "overexposed, total local dust: %v (current commit "+
4✔
2900
                        "fee: %v)", l.ShortChanID(), htlc, localDustSum)
2901

4✔
UNCOV
2902
                return true
×
UNCOV
2903
        }
×
UNCOV
2904

×
UNCOV
2905
        if isRemoteDust {
×
UNCOV
2906
                // If this is dust, it doesn't contribute to weight but does
×
UNCOV
2907
                // contribute to the overall dust sum.
×
UNCOV
2908
                remoteDustSum += lnwire.NewMSatFromSatoshis(amount)
×
2909
        } else {
2910
                // Account for the fee increase that comes with an increase in
8✔
2911
                // weight.
4✔
2912
                remoteDustSum += additional
4✔
2913
        }
4✔
2914

8✔
2915
        if remoteDustSum > l.cfg.MaxFeeExposure {
4✔
2916
                // The max fee exposure was exceeded.
4✔
2917
                l.log.Debugf("ChannelLink(%v): HTLC %v makes the channel "+
4✔
2918
                        "overexposed, total remote dust: %v (current commit "+
4✔
2919
                        "fee: %v)", l.ShortChanID(), htlc, remoteDustSum)
2920

4✔
2921
                return true
×
2922
        }
×
2923

×
2924
        return false
×
2925
}
×
2926

×
2927
// dustClosure is a function that evaluates whether an HTLC is dust. It returns
×
2928
// true if the HTLC is dust. It takes in a feerate, a boolean denoting whether
2929
// the HTLC is incoming (i.e. one that the remote sent), a boolean denoting
4✔
2930
// whether to evaluate on the local or remote commit, and finally an HTLC
2931
// amount to test.
2932
type dustClosure func(feerate chainfee.SatPerKWeight, incoming bool,
2933
        whoseCommit lntypes.ChannelParty, amt btcutil.Amount) bool
2934

2935
// dustHelper is used to construct the dustClosure.
2936
func dustHelper(chantype channeldb.ChannelType, localDustLimit,
2937
        remoteDustLimit btcutil.Amount) dustClosure {
2938

2939
        isDust := func(feerate chainfee.SatPerKWeight, incoming bool,
2940
                whoseCommit lntypes.ChannelParty, amt btcutil.Amount) bool {
2941

2942
                var dustLimit btcutil.Amount
4✔
2943
                if whoseCommit.IsLocal() {
4✔
2944
                        dustLimit = localDustLimit
4✔
2945
                } else {
8✔
2946
                        dustLimit = remoteDustLimit
4✔
2947
                }
4✔
2948

8✔
2949
                return lnwallet.HtlcIsDust(
4✔
2950
                        chantype, incoming, whoseCommit, feerate, amt,
8✔
2951
                        dustLimit,
4✔
2952
                )
4✔
2953
        }
2954

4✔
2955
        return isDust
4✔
2956
}
4✔
2957

4✔
2958
// zeroConfConfirmed returns whether or not the zero-conf channel has
2959
// confirmed on-chain.
2960
//
4✔
2961
// Part of the scidAliasHandler interface.
2962
func (l *channelLink) zeroConfConfirmed() bool {
2963
        return l.channel.State().ZeroConfConfirmed()
2964
}
2965

2966
// confirmedScid returns the confirmed SCID for a zero-conf channel. This
2967
// should not be called for non-zero-conf channels.
4✔
2968
//
4✔
2969
// Part of the scidAliasHandler interface.
4✔
2970
func (l *channelLink) confirmedScid() lnwire.ShortChannelID {
2971
        return l.channel.State().ZeroConfRealScid()
2972
}
2973

2974
// isZeroConf returns whether or not the underlying channel is a zero-conf
2975
// channel.
4✔
2976
//
4✔
2977
// Part of the scidAliasHandler interface.
4✔
2978
func (l *channelLink) isZeroConf() bool {
2979
        return l.channel.State().IsZeroConf()
2980
}
2981

2982
// negotiatedAliasFeature returns whether or not the underlying channel has
2983
// negotiated the option-scid-alias feature bit. This will be true for both
4✔
2984
// option-scid-alias and zero-conf channel-types. It will also be true for
4✔
2985
// channels with the feature bit but without the above channel-types.
4✔
2986
//
2987
// Part of the scidAliasFeature interface.
2988
func (l *channelLink) negotiatedAliasFeature() bool {
2989
        return l.channel.State().NegotiatedAliasFeature()
2990
}
2991

2992
// getAliases returns the set of aliases for the underlying channel.
2993
//
4✔
2994
// Part of the scidAliasHandler interface.
4✔
2995
func (l *channelLink) getAliases() []lnwire.ShortChannelID {
4✔
2996
        return l.cfg.GetAliases(l.ShortChanID())
2997
}
2998

2999
// attachFailAliasUpdate sets the link's FailAliasUpdate function.
3000
//
4✔
3001
// Part of the scidAliasHandler interface.
4✔
3002
func (l *channelLink) attachFailAliasUpdate(closure func(
4✔
3003
        sid lnwire.ShortChannelID, incoming bool) *lnwire.ChannelUpdate1) {
3004

3005
        l.Lock()
3006
        l.cfg.FailAliasUpdate = closure
3007
        l.Unlock()
3008
}
4✔
3009

4✔
3010
// AttachMailBox updates the current mailbox used by this link, and hooks up
4✔
3011
// the mailbox's message and packet outboxes to the link's upstream and
4✔
3012
// downstream chans, respectively.
4✔
3013
func (l *channelLink) AttachMailBox(mailbox MailBox) {
4✔
3014
        l.Lock()
3015
        l.mailBox = mailbox
3016
        l.upstream = mailbox.MessageOutBox()
3017
        l.downstream = mailbox.PacketOutBox()
3018
        l.Unlock()
4✔
3019

4✔
3020
        // Set the mailbox's fee rate. This may be refreshing a feerate that was
4✔
3021
        // never committed.
4✔
3022
        l.mailBox.SetFeeRate(l.getFeeRate())
4✔
3023

4✔
3024
        // Also set the mailbox's dust closure so that it can query whether HTLC's
4✔
3025
        // are dust given the current feerate.
4✔
3026
        l.mailBox.SetDustClosure(l.getDustClosure())
4✔
3027
}
4✔
3028

4✔
3029
// UpdateForwardingPolicy updates the forwarding policy for the target
4✔
3030
// ChannelLink. Once updated, the link will use the new forwarding policy to
4✔
3031
// govern if it an incoming HTLC should be forwarded or not. We assume that
4✔
3032
// fields that are zero are intentionally set to zero, so we'll use newPolicy to
4✔
3033
// update all of the link's FwrdingPolicy's values.
3034
//
3035
// NOTE: Part of the ChannelLink interface.
3036
func (l *channelLink) UpdateForwardingPolicy(
3037
        newPolicy models.ForwardingPolicy) {
3038

3039
        l.Lock()
3040
        defer l.Unlock()
3041

3042
        l.cfg.FwrdingPolicy = newPolicy
4✔
3043
}
4✔
3044

4✔
3045
// CheckHtlcForward should return a nil error if the passed HTLC details
4✔
3046
// satisfy the current forwarding policy fo the target link. Otherwise,
4✔
3047
// a LinkError with a valid protocol failure message should be returned
4✔
3048
// in order to signal to the source of the HTLC, the policy consistency
4✔
3049
// issue.
3050
//
3051
// NOTE: Part of the ChannelLink interface.
3052
func (l *channelLink) CheckHtlcForward(payHash [32]byte,
3053
        incomingHtlcAmt, amtToForward lnwire.MilliSatoshi,
3054
        incomingTimeout, outgoingTimeout uint32,
3055
        inboundFee models.InboundFee,
3056
        heightNow uint32, originalScid lnwire.ShortChannelID) *LinkError {
3057

3058
        l.RLock()
3059
        policy := l.cfg.FwrdingPolicy
3060
        l.RUnlock()
3061

4✔
3062
        // Using the outgoing HTLC amount, we'll calculate the outgoing
4✔
3063
        // fee this incoming HTLC must carry in order to satisfy the constraints
4✔
3064
        // of the outgoing link.
4✔
3065
        outFee := ExpectedFee(policy, amtToForward)
4✔
3066

4✔
3067
        // Then calculate the inbound fee that we charge based on the sum of
4✔
3068
        // outgoing HTLC amount and outgoing fee.
4✔
3069
        inFee := inboundFee.CalcFee(amtToForward + outFee)
4✔
3070

4✔
3071
        // Add up both fee components. It is important to calculate both fees
4✔
3072
        // separately. An alternative way of calculating is to first determine
4✔
3073
        // an aggregate fee and apply that to the outgoing HTLC amount. However,
4✔
3074
        // rounding may cause the result to be slightly higher than in the case
4✔
3075
        // of separately rounded fee components. This potentially causes failed
4✔
3076
        // forwards for senders and is something to be avoided.
4✔
3077
        expectedFee := inFee + int64(outFee)
4✔
3078

4✔
3079
        // If the actual fee is less than our expected fee, then we'll reject
4✔
3080
        // this HTLC as it didn't provide a sufficient amount of fees, or the
4✔
3081
        // values have been tampered with, or the send used incorrect/dated
4✔
3082
        // information to construct the forwarding information for this hop. In
4✔
3083
        // any case, we'll cancel this HTLC.
4✔
3084
        actualFee := int64(incomingHtlcAmt) - int64(amtToForward)
4✔
3085
        if incomingHtlcAmt < amtToForward || actualFee < expectedFee {
4✔
3086
                l.log.Warnf("outgoing htlc(%x) has insufficient fee: "+
4✔
3087
                        "expected %v, got %v: incoming=%v, outgoing=%v, "+
4✔
3088
                        "inboundFee=%v",
4✔
3089
                        payHash[:], expectedFee, actualFee,
4✔
3090
                        incomingHtlcAmt, amtToForward, inboundFee,
8✔
3091
                )
4✔
3092

4✔
3093
                // As part of the returned error, we'll send our latest routing
4✔
3094
                // policy so the sending node obtains the most up to date data.
4✔
3095
                cb := func(upd *lnwire.ChannelUpdate1) lnwire.FailureMessage {
4✔
3096
                        return lnwire.NewFeeInsufficient(amtToForward, *upd)
4✔
3097
                }
4✔
3098
                failure := l.createFailureWithUpdate(false, originalScid, cb)
4✔
3099
                return NewLinkError(failure)
4✔
3100
        }
8✔
3101

4✔
3102
        // Check whether the outgoing htlc satisfies the channel policy.
4✔
3103
        err := l.canSendHtlc(
4✔
3104
                policy, payHash, amtToForward, outgoingTimeout, heightNow,
4✔
3105
                originalScid,
3106
        )
3107
        if err != nil {
3108
                return err
4✔
3109
        }
4✔
3110

4✔
3111
        // Finally, we'll ensure that the time-lock on the outgoing HTLC meets
4✔
3112
        // the following constraint: the incoming time-lock minus our time-lock
8✔
3113
        // delta should equal the outgoing time lock. Otherwise, whether the
4✔
3114
        // sender messed up, or an intermediate node tampered with the HTLC.
4✔
3115
        timeDelta := policy.TimeLockDelta
3116
        if incomingTimeout < outgoingTimeout+timeDelta {
3117
                l.log.Warnf("incoming htlc(%x) has incorrect time-lock value: "+
3118
                        "expected at least %v block delta, got %v block delta",
3119
                        payHash[:], timeDelta, incomingTimeout-outgoingTimeout)
3120

4✔
3121
                // Grab the latest routing policy so the sending node is up to
4✔
UNCOV
3122
                // date with our current policy.
×
UNCOV
3123
                cb := func(upd *lnwire.ChannelUpdate1) lnwire.FailureMessage {
×
UNCOV
3124
                        return lnwire.NewIncorrectCltvExpiry(
×
UNCOV
3125
                                incomingTimeout, *upd,
×
UNCOV
3126
                        )
×
UNCOV
3127
                }
×
UNCOV
3128
                failure := l.createFailureWithUpdate(false, originalScid, cb)
×
UNCOV
3129
                return NewLinkError(failure)
×
UNCOV
3130
        }
×
UNCOV
3131

×
UNCOV
3132
        return nil
×
UNCOV
3133
}
×
UNCOV
3134

×
3135
// CheckHtlcTransit should return a nil error if the passed HTLC details
3136
// satisfy the current channel policy.  Otherwise, a LinkError with a
3137
// valid protocol failure message should be returned in order to signal
4✔
3138
// the violation. This call is intended to be used for locally initiated
3139
// payments for which there is no corresponding incoming htlc.
3140
func (l *channelLink) CheckHtlcTransit(payHash [32]byte,
3141
        amt lnwire.MilliSatoshi, timeout uint32,
3142
        heightNow uint32) *LinkError {
3143

3144
        l.RLock()
3145
        policy := l.cfg.FwrdingPolicy
3146
        l.RUnlock()
3147

4✔
3148
        // We pass in hop.Source here as this is only used in the Switch when
4✔
3149
        // trying to send over a local link. This causes the fallback mechanism
4✔
3150
        // to occur.
4✔
3151
        return l.canSendHtlc(
4✔
3152
                policy, payHash, amt, timeout, heightNow, hop.Source,
4✔
3153
        )
4✔
3154
}
4✔
3155

4✔
3156
// canSendHtlc checks whether the given htlc parameters satisfy
4✔
3157
// the channel's amount and time lock constraints.
4✔
3158
func (l *channelLink) canSendHtlc(policy models.ForwardingPolicy,
4✔
3159
        payHash [32]byte, amt lnwire.MilliSatoshi, timeout uint32,
4✔
3160
        heightNow uint32, originalScid lnwire.ShortChannelID) *LinkError {
3161

3162
        // As our first sanity check, we'll ensure that the passed HTLC isn't
3163
        // too small for the next hop. If so, then we'll cancel the HTLC
3164
        // directly.
3165
        if amt < policy.MinHTLCOut {
4✔
3166
                l.log.Warnf("outgoing htlc(%x) is too small: min_htlc=%v, "+
4✔
3167
                        "htlc_value=%v", payHash[:], policy.MinHTLCOut,
4✔
3168
                        amt)
4✔
3169

4✔
3170
                // As part of the returned error, we'll send our latest routing
8✔
3171
                // policy so the sending node obtains the most up to date data.
4✔
3172
                cb := func(upd *lnwire.ChannelUpdate1) lnwire.FailureMessage {
4✔
3173
                        return lnwire.NewAmountBelowMinimum(amt, *upd)
4✔
3174
                }
4✔
3175
                failure := l.createFailureWithUpdate(false, originalScid, cb)
4✔
3176
                return NewLinkError(failure)
4✔
3177
        }
8✔
3178

4✔
3179
        // Next, ensure that the passed HTLC isn't too large. If so, we'll
4✔
3180
        // cancel the HTLC directly.
4✔
3181
        if policy.MaxHTLC != 0 && amt > policy.MaxHTLC {
4✔
3182
                l.log.Warnf("outgoing htlc(%x) is too large: max_htlc=%v, "+
3183
                        "htlc_value=%v", payHash[:], policy.MaxHTLC, amt)
3184

3185
                // As part of the returned error, we'll send our latest routing
3186
                // policy so the sending node obtains the most up-to-date data.
8✔
3187
                cb := func(upd *lnwire.ChannelUpdate1) lnwire.FailureMessage {
4✔
3188
                        return lnwire.NewTemporaryChannelFailure(upd)
4✔
3189
                }
4✔
3190
                failure := l.createFailureWithUpdate(false, originalScid, cb)
4✔
3191
                return NewDetailedLinkError(failure, OutgoingFailureHTLCExceedsMax)
4✔
3192
        }
8✔
3193

4✔
3194
        // We want to avoid offering an HTLC which will expire in the near
4✔
3195
        // future, so we'll reject an HTLC if the outgoing expiration time is
4✔
3196
        // too close to the current height.
4✔
3197
        if timeout <= heightNow+l.cfg.OutgoingCltvRejectDelta {
3198
                l.log.Warnf("htlc(%x) has an expiry that's too soon: "+
3199
                        "outgoing_expiry=%v, best_height=%v", payHash[:],
3200
                        timeout, heightNow)
3201

3202
                cb := func(upd *lnwire.ChannelUpdate1) lnwire.FailureMessage {
4✔
UNCOV
3203
                        return lnwire.NewExpiryTooSoon(*upd)
×
UNCOV
3204
                }
×
UNCOV
3205
                failure := l.createFailureWithUpdate(false, originalScid, cb)
×
UNCOV
3206
                return NewLinkError(failure)
×
UNCOV
3207
        }
×
UNCOV
3208

×
UNCOV
3209
        // Check absolute max delta.
×
UNCOV
3210
        if timeout > l.cfg.MaxOutgoingCltvExpiry+heightNow {
×
UNCOV
3211
                l.log.Warnf("outgoing htlc(%x) has a time lock too far in "+
×
3212
                        "the future: got %v, but maximum is %v", payHash[:],
3213
                        timeout-heightNow, l.cfg.MaxOutgoingCltvExpiry)
3214

3215
                return NewLinkError(&lnwire.FailExpiryTooFar{})
4✔
UNCOV
3216
        }
×
UNCOV
3217

×
UNCOV
3218
        // Check to see if there is enough balance in this channel.
×
UNCOV
3219
        if amt > l.Bandwidth() {
×
UNCOV
3220
                l.log.Warnf("insufficient bandwidth to route htlc: %v is "+
×
UNCOV
3221
                        "larger than %v", amt, l.Bandwidth())
×
3222
                cb := func(upd *lnwire.ChannelUpdate1) lnwire.FailureMessage {
3223
                        return lnwire.NewTemporaryChannelFailure(upd)
3224
                }
8✔
3225
                failure := l.createFailureWithUpdate(false, originalScid, cb)
4✔
3226
                return NewDetailedLinkError(
4✔
3227
                        failure, OutgoingFailureInsufficientBalance,
8✔
3228
                )
4✔
3229
        }
4✔
3230

4✔
3231
        return nil
4✔
3232
}
4✔
3233

4✔
3234
// Stats returns the statistics of channel link.
3235
//
3236
// NOTE: Part of the ChannelLink interface.
4✔
3237
func (l *channelLink) Stats() (uint64, lnwire.MilliSatoshi, lnwire.MilliSatoshi) {
3238
        snapshot := l.channel.StateSnapshot()
3239

3240
        return snapshot.ChannelCommitment.CommitHeight,
3241
                snapshot.TotalMSatSent,
3242
                snapshot.TotalMSatReceived
4✔
3243
}
4✔
3244

4✔
3245
// String returns the string representation of channel link.
4✔
3246
//
4✔
3247
// NOTE: Part of the ChannelLink interface.
4✔
3248
func (l *channelLink) String() string {
4✔
3249
        return l.channel.ChannelPoint().String()
3250
}
3251

3252
// handleSwitchPacket handles the switch packets. This packets which might be
3253
// forwarded to us from another channel link in case the htlc update came from
×
3254
// another peer or if the update was created by user
×
3255
//
×
3256
// NOTE: Part of the packetHandler interface.
3257
func (l *channelLink) handleSwitchPacket(pkt *htlcPacket) error {
3258
        l.log.Tracef("received switch packet inkey=%v, outkey=%v",
3259
                pkt.inKey(), pkt.outKey())
3260

3261
        return l.mailBox.AddPacket(pkt)
3262
}
4✔
3263

4✔
3264
// HandleChannelUpdate handles the htlc requests as settle/add/fail which sent
4✔
3265
// to us from remote peer we have a channel with.
4✔
3266
//
4✔
3267
// NOTE: Part of the ChannelLink interface.
4✔
3268
func (l *channelLink) HandleChannelUpdate(message lnwire.Message) {
3269
        select {
3270
        case <-l.Quit:
3271
                // Return early if the link is already in the process of
3272
                // quitting. It doesn't make sense to hand the message to the
3273
                // mailbox here.
4✔
3274
                return
4✔
3275
        default:
×
3276
        }
×
3277

×
3278
        err := l.mailBox.AddMessage(message)
×
3279
        if err != nil {
×
3280
                l.log.Errorf("failed to add Message to mailbox: %v", err)
4✔
3281
        }
3282
}
3283

4✔
3284
// updateChannelFee updates the commitment fee-per-kw on this channel by
4✔
3285
// committing to an update_fee message.
×
3286
func (l *channelLink) updateChannelFee(feePerKw chainfee.SatPerKWeight) error {
×
3287
        l.log.Infof("updating commit fee to %v", feePerKw)
3288

3289
        // We skip sending the UpdateFee message if the channel is not
3290
        // currently eligible to forward messages.
UNCOV
3291
        if !l.EligibleToUpdate() {
×
UNCOV
3292
                l.log.Debugf("skipping fee update for inactive channel")
×
UNCOV
3293
                return nil
×
UNCOV
3294
        }
×
UNCOV
3295

×
UNCOV
3296
        // Check and see if our proposed fee-rate would make us exceed the fee
×
3297
        // threshold.
×
3298
        thresholdExceeded, err := l.exceedsFeeExposureLimit(feePerKw)
×
3299
        if err != nil {
×
3300
                // This shouldn't typically happen. If it does, it indicates
3301
                // something is wrong with our channel state.
3302
                return err
UNCOV
3303
        }
×
UNCOV
3304

×
3305
        if thresholdExceeded {
×
3306
                return fmt.Errorf("link fee threshold exceeded")
×
3307
        }
×
3308

×
3309
        // First, we'll update the local fee on our commitment.
UNCOV
3310
        if err := l.channel.UpdateFee(feePerKw); err != nil {
×
3311
                return err
×
3312
        }
×
3313

3314
        // The fee passed the channel's validation checks, so we update the
UNCOV
3315
        // mailbox feerate.
×
3316
        l.mailBox.SetFeeRate(feePerKw)
×
3317

×
3318
        // We'll then attempt to send a new UpdateFee message, and also lock it
3319
        // in immediately by triggering a commitment update.
3320
        msg := lnwire.NewUpdateFee(l.ChanID(), uint32(feePerKw))
UNCOV
3321
        if err := l.cfg.Peer.SendMessage(false, msg); err != nil {
×
UNCOV
3322
                return err
×
UNCOV
3323
        }
×
UNCOV
3324
        return l.updateCommitTx()
×
UNCOV
3325
}
×
UNCOV
3326

×
3327
// processRemoteSettleFails accepts a batch of settle/fail payment descriptors
×
3328
// after receiving a revocation from the remote party, and reprocesses them in
×
UNCOV
3329
// the context of the provided forwarding package. Any settles or fails that
×
3330
// have already been acknowledged in the forwarding package will not be sent to
3331
// the switch.
3332
func (l *channelLink) processRemoteSettleFails(fwdPkg *channeldb.FwdPkg) {
3333
        if len(fwdPkg.SettleFails) == 0 {
3334
                return
3335
        }
3336

3337
        l.log.Debugf("settle-fail-filter: %v", fwdPkg.SettleFailFilter)
4✔
3338

8✔
3339
        var switchPackets []*htlcPacket
4✔
3340
        for i, update := range fwdPkg.SettleFails {
4✔
3341
                destRef := fwdPkg.DestRef(uint16(i))
3342

4✔
3343
                // Skip any settles or fails that have already been
4✔
3344
                // acknowledged by the incoming link that originated the
4✔
3345
                // forwarded Add.
8✔
3346
                if fwdPkg.SettleFailFilter.Contains(uint16(i)) {
4✔
3347
                        continue
4✔
3348
                }
4✔
3349

4✔
3350
                // TODO(roasbeef): rework log entries to a shared
4✔
3351
                // interface.
4✔
3352

×
3353
                switch msg := update.UpdateMsg.(type) {
3354
                // A settle for an HTLC we previously forwarded HTLC has been
3355
                // received. So we'll forward the HTLC to the switch which will
3356
                // handle propagating the settle to the prior hop.
3357
                case *lnwire.UpdateFulfillHTLC:
3358
                        // If hodl.SettleIncoming is requested, we will not
4✔
3359
                        // forward the SETTLE to the switch and will not signal
3360
                        // a free slot on the commitment transaction.
3361
                        if l.cfg.HodlMask.Active(hodl.SettleIncoming) {
3362
                                l.log.Warnf(hodl.SettleIncoming.Warning())
4✔
3363
                                continue
4✔
3364
                        }
4✔
3365

4✔
3366
                        settlePacket := &htlcPacket{
4✔
3367
                                outgoingChanID: l.ShortChanID(),
×
3368
                                outgoingHTLCID: msg.ID,
×
3369
                                destRef:        &destRef,
3370
                                htlc:           msg,
3371
                        }
4✔
3372

4✔
3373
                        // Add the packet to the batch to be forwarded, and
4✔
3374
                        // notify the overflow queue that a spare spot has been
4✔
3375
                        // freed up within the commitment state.
4✔
3376
                        switchPackets = append(switchPackets, settlePacket)
4✔
3377

4✔
3378
                // A failureCode message for a previously forwarded HTLC has
4✔
3379
                // been received. As a result a new slot will be freed up in
4✔
3380
                // our commitment state, so we'll forward this to the switch so
4✔
3381
                // the backwards undo can continue.
4✔
3382
                case *lnwire.UpdateFailHTLC:
3383
                        // If hodl.SettleIncoming is requested, we will not
3384
                        // forward the FAIL to the switch and will not signal a
3385
                        // free slot on the commitment transaction.
3386
                        if l.cfg.HodlMask.Active(hodl.FailIncoming) {
3387
                                l.log.Warnf(hodl.FailIncoming.Warning())
4✔
3388
                                continue
4✔
3389
                        }
4✔
3390

4✔
3391
                        // Fetch the reason the HTLC was canceled so we can
4✔
3392
                        // continue to propagate it. This failure originated
×
3393
                        // from another node, so the linkFailure field is not
×
3394
                        // set on the packet.
3395
                        failPacket := &htlcPacket{
3396
                                outgoingChanID: l.ShortChanID(),
3397
                                outgoingHTLCID: msg.ID,
3398
                                destRef:        &destRef,
3399
                                htlc:           msg,
3400
                        }
4✔
3401

4✔
3402
                        l.log.Debugf("Failed to send HTLC with ID=%d", msg.ID)
4✔
3403

4✔
3404
                        // If the failure message lacks an HMAC (but includes
4✔
3405
                        // the 4 bytes for encoding the message and padding
4✔
3406
                        // lengths, then this means that we received it as an
4✔
3407
                        // UpdateFailMalformedHTLC. As a result, we'll signal
4✔
3408
                        // that we need to convert this error within the switch
4✔
3409
                        // to an actual error, by encrypting it as if we were
4✔
3410
                        // the originating hop.
4✔
3411
                        convertedErrorSize := lnwire.FailureMessageLength + 4
4✔
3412
                        if len(msg.Reason) == convertedErrorSize {
4✔
3413
                                failPacket.convertedError = true
4✔
3414
                        }
4✔
3415

4✔
3416
                        // Add the packet to the batch to be forwarded, and
4✔
3417
                        // notify the overflow queue that a spare spot has been
8✔
3418
                        // freed up within the commitment state.
4✔
3419
                        switchPackets = append(switchPackets, failPacket)
4✔
3420
                }
3421
        }
3422

3423
        // Only spawn the task forward packets we have a non-zero number.
3424
        if len(switchPackets) > 0 {
4✔
3425
                go l.forwardBatch(false, switchPackets...)
3426
        }
3427
}
3428

3429
// processRemoteAdds serially processes each of the Add payment descriptors
8✔
3430
// which have been "locked-in" by receiving a revocation from the remote party.
4✔
3431
// The forwarding package provided instructs how to process this batch,
4✔
3432
// indicating whether this is the first time these Adds are being processed, or
3433
// whether we are reprocessing as a result of a failure or restart. Adds that
3434
// have already been acknowledged in the forwarding package will be ignored.
3435
//
3436
//nolint:funlen
3437
func (l *channelLink) processRemoteAdds(fwdPkg *channeldb.FwdPkg) {
3438
        l.log.Tracef("processing %d remote adds for height %d",
3439
                len(fwdPkg.Adds), fwdPkg.Height)
3440

3441
        decodeReqs := make(
3442
                []hop.DecodeHopIteratorRequest, 0, len(fwdPkg.Adds),
4✔
3443
        )
4✔
3444
        for _, update := range fwdPkg.Adds {
4✔
3445
                if msg, ok := update.UpdateMsg.(*lnwire.UpdateAddHTLC); ok {
4✔
3446
                        // Before adding the new htlc to the state machine,
4✔
3447
                        // parse the onion object in order to obtain the
4✔
3448
                        // routing information with DecodeHopIterator function
4✔
3449
                        // which process the Sphinx packet.
8✔
3450
                        onionReader := bytes.NewReader(msg.OnionBlob[:])
8✔
3451

4✔
3452
                        req := hop.DecodeHopIteratorRequest{
4✔
3453
                                OnionReader:    onionReader,
4✔
3454
                                RHash:          msg.PaymentHash[:],
4✔
3455
                                IncomingCltv:   msg.Expiry,
4✔
3456
                                IncomingAmount: msg.Amount,
4✔
3457
                                BlindingPoint:  msg.BlindingPoint,
4✔
3458
                        }
4✔
3459

4✔
3460
                        decodeReqs = append(decodeReqs, req)
4✔
3461
                }
4✔
3462
        }
4✔
3463

4✔
3464
        // Atomically decode the incoming htlcs, simultaneously checking for
4✔
3465
        // replay attempts. A particular index in the returned, spare list of
4✔
3466
        // channel iterators should only be used if the failure code at the
4✔
3467
        // same index is lnwire.FailCodeNone.
3468
        decodeResps, sphinxErr := l.cfg.DecodeHopIterators(
3469
                fwdPkg.ID(), decodeReqs,
3470
        )
3471
        if sphinxErr != nil {
3472
                l.failf(LinkFailureError{code: ErrInternalError},
3473
                        "unable to decode hop iterators: %v", sphinxErr)
4✔
3474
                return
4✔
3475
        }
4✔
3476

4✔
3477
        var switchPackets []*htlcPacket
×
3478

×
3479
        for i, update := range fwdPkg.Adds {
×
3480
                idx := uint16(i)
×
3481

3482
                //nolint:forcetypeassert
4✔
3483
                add := *update.UpdateMsg.(*lnwire.UpdateAddHTLC)
4✔
3484
                sourceRef := fwdPkg.SourceRef(idx)
8✔
3485

4✔
3486
                if fwdPkg.State == channeldb.FwdStateProcessed &&
4✔
3487
                        fwdPkg.AckFilter.Contains(idx) {
4✔
3488

4✔
3489
                        // If this index is already found in the ack filter,
4✔
3490
                        // the response to this forwarding decision has already
4✔
3491
                        // been committed by one of our commitment txns. ADDs
4✔
3492
                        // in this state are waiting for the rest of the fwding
4✔
3493
                        // package to get acked before being garbage collected.
×
3494
                        continue
×
3495
                }
×
3496

×
3497
                // An incoming HTLC add has been full-locked in. As a result we
×
3498
                // can now examine the forwarding details of the HTLC, and the
×
3499
                // HTLC itself to decide if: we should forward it, cancel it,
×
3500
                // or are able to settle it (and it adheres to our fee related
3501
                // constraints).
3502

3503
                // Before adding the new htlc to the state machine, parse the
3504
                // onion object in order to obtain the routing information with
3505
                // DecodeHopIterator function which process the Sphinx packet.
3506
                chanIterator, failureCode := decodeResps[i].Result()
3507
                if failureCode != lnwire.CodeNone {
3508
                        // If we're unable to process the onion blob then we
3509
                        // should send the malformed htlc error to payment
3510
                        // sender.
3511
                        l.sendMalformedHTLCError(
4✔
3512
                                add.ID, failureCode, add.OnionBlob, &sourceRef,
8✔
3513
                        )
4✔
3514

4✔
3515
                        l.log.Errorf("unable to decode onion hop "+
4✔
3516
                                "iterator: %v", failureCode)
4✔
3517
                        continue
4✔
3518
                }
4✔
3519

4✔
3520
                heightNow := l.cfg.BestHeight()
4✔
3521

4✔
3522
                pld, routeRole, pldErr := chanIterator.HopPayload()
4✔
3523
                if pldErr != nil {
3524
                        // If we're unable to process the onion payload, or we
3525
                        // received invalid onion payload failure, then we
4✔
3526
                        // should send an error back to the caller so the HTLC
4✔
3527
                        // can be canceled.
4✔
3528
                        var failedType uint64
8✔
3529

4✔
3530
                        // We need to get the underlying error value, so we
4✔
3531
                        // can't use errors.As as suggested by the linter.
4✔
3532
                        //nolint:errorlint
4✔
3533
                        if e, ok := pldErr.(hop.ErrInvalidPayload); ok {
4✔
3534
                                failedType = uint64(e.Type)
4✔
3535
                        }
4✔
3536

4✔
3537
                        // If we couldn't parse the payload, make our best
4✔
3538
                        // effort at creating an error encrypter that knows
4✔
3539
                        // what blinding type we were, but if we couldn't
×
3540
                        // parse the payload we have no way of knowing whether
×
3541
                        // we were the introduction node or not.
3542
                        //
3543
                        //nolint:lll
3544
                        obfuscator, failCode := chanIterator.ExtractErrorEncrypter(
3545
                                l.cfg.ExtractErrorEncrypter,
3546
                                // We need our route role here because we
3547
                                // couldn't parse or validate the payload.
3548
                                routeRole == hop.RouteRoleIntroduction,
3549
                        )
4✔
3550
                        if failCode != lnwire.CodeNone {
4✔
3551
                                l.log.Errorf("could not extract error "+
4✔
3552
                                        "encrypter: %v", pldErr)
4✔
3553

4✔
3554
                                // We can't process this htlc, send back
4✔
3555
                                // malformed.
4✔
3556
                                l.sendMalformedHTLCError(
×
3557
                                        add.ID, failureCode, add.OnionBlob,
×
3558
                                        &sourceRef,
×
3559
                                )
×
3560

×
3561
                                continue
×
3562
                        }
×
3563

×
3564
                        // TODO: currently none of the test unit infrastructure
×
3565
                        // is setup to handle TLV payloads, so testing this
×
3566
                        // would require implementing a separate mock iterator
×
3567
                        // for TLV payloads that also supports injecting invalid
3568
                        // payloads. Deferring this non-trival effort till a
3569
                        // later date
3570
                        failure := lnwire.NewInvalidOnionPayload(failedType, 0)
3571

3572
                        l.sendHTLCError(
3573
                                add, sourceRef, NewLinkError(failure),
3574
                                obfuscator, false,
3575
                        )
4✔
3576

4✔
3577
                        l.log.Errorf("unable to decode forwarding "+
4✔
3578
                                "instructions: %v", pldErr)
4✔
3579

4✔
3580
                        continue
4✔
3581
                }
4✔
3582

4✔
3583
                // Retrieve onion obfuscator from onion blob in order to
4✔
3584
                // produce initial obfuscation of the onion failureCode.
4✔
3585
                obfuscator, failureCode := chanIterator.ExtractErrorEncrypter(
4✔
3586
                        l.cfg.ExtractErrorEncrypter,
3587
                        routeRole == hop.RouteRoleIntroduction,
3588
                )
3589
                if failureCode != lnwire.CodeNone {
3590
                        // If we're unable to process the onion blob than we
4✔
3591
                        // should send the malformed htlc error to payment
4✔
3592
                        // sender.
4✔
3593
                        l.sendMalformedHTLCError(
4✔
3594
                                add.ID, failureCode, add.OnionBlob,
4✔
UNCOV
3595
                                &sourceRef,
×
UNCOV
3596
                        )
×
UNCOV
3597

×
UNCOV
3598
                        l.log.Errorf("unable to decode onion "+
×
UNCOV
3599
                                "obfuscator: %v", failureCode)
×
UNCOV
3600

×
UNCOV
3601
                        continue
×
UNCOV
3602
                }
×
UNCOV
3603

×
UNCOV
3604
                fwdInfo := pld.ForwardingInfo()
×
UNCOV
3605

×
UNCOV
3606
                // Check whether the payload we've just processed uses our
×
3607
                // node as the introduction point (gave us a blinding key in
3608
                // the payload itself) and fail it back if we don't support
3609
                // route blinding.
4✔
3610
                if fwdInfo.NextBlinding.IsSome() &&
4✔
3611
                        l.cfg.DisallowRouteBlinding {
4✔
3612

4✔
3613
                        failure := lnwire.NewInvalidBlinding(
4✔
3614
                                fn.Some(add.OnionBlob),
4✔
3615
                        )
4✔
3616

8✔
3617
                        l.sendHTLCError(
4✔
3618
                                add, sourceRef, NewLinkError(failure),
4✔
3619
                                obfuscator, false,
4✔
3620
                        )
4✔
3621

4✔
3622
                        l.log.Error("rejected htlc that uses use as an " +
4✔
3623
                                "introduction point when we do not support " +
4✔
3624
                                "route blinding")
4✔
3625

4✔
3626
                        continue
4✔
3627
                }
4✔
3628

4✔
3629
                switch fwdInfo.NextHop {
4✔
3630
                case hop.Exit:
4✔
3631
                        err := l.processExitHop(
4✔
3632
                                add, sourceRef, obfuscator, fwdInfo,
3633
                                heightNow, pld,
3634
                        )
4✔
3635
                        if err != nil {
4✔
3636
                                l.failf(LinkFailureError{
4✔
3637
                                        code: ErrInternalError,
4✔
3638
                                }, err.Error()) //nolint
4✔
3639

4✔
3640
                                return
8✔
3641
                        }
4✔
3642

4✔
3643
                // There are additional channels left within this route. So
4✔
3644
                // we'll simply do some forwarding package book-keeping.
4✔
3645
                default:
4✔
3646
                        // If hodl.AddIncoming is requested, we will not
4✔
3647
                        // validate the forwarded ADD, nor will we send the
3648
                        // packet to the htlc switch.
3649
                        if l.cfg.HodlMask.Active(hodl.AddIncoming) {
3650
                                l.log.Warnf(hodl.AddIncoming.Warning())
4✔
3651
                                continue
4✔
3652
                        }
4✔
3653

4✔
3654
                        switch fwdPkg.State {
4✔
3655
                        case channeldb.FwdStateProcessed:
×
3656
                                // This add was not forwarded on the previous
×
3657
                                // processing phase, run it through our
3658
                                // validation pipeline to reproduce an error.
3659
                                // This may trigger a different error due to
4✔
3660
                                // expiring timelocks, but we expect that an
4✔
3661
                                // error will be reproduced.
4✔
3662
                                if !fwdPkg.FwdFilter.Contains(idx) {
4✔
3663
                                        break
4✔
3664
                                }
4✔
3665

4✔
3666
                                // Otherwise, it was already processed, we can
4✔
3667
                                // can collect it and continue.
4✔
3668
                                outgoingAdd := &lnwire.UpdateAddHTLC{
4✔
3669
                                        Expiry:        fwdInfo.OutgoingCTLV,
4✔
3670
                                        Amount:        fwdInfo.AmountToForward,
4✔
3671
                                        PaymentHash:   add.PaymentHash,
4✔
3672
                                        BlindingPoint: fwdInfo.NextBlinding,
4✔
3673
                                }
4✔
3674

4✔
3675
                                // Finally, we'll encode the onion packet for
×
3676
                                // the _next_ hop using the hop iterator
3677
                                // decoded for the current hop.
3678
                                buf := bytes.NewBuffer(
3679
                                        outgoingAdd.OnionBlob[0:0],
3680
                                )
4✔
3681

4✔
3682
                                // We know this cannot fail, as this ADD
4✔
3683
                                // was marked forwarded in a previous
4✔
3684
                                // round of processing.
4✔
3685
                                chanIterator.EncodeNextHop(buf)
4✔
3686

4✔
3687
                                inboundFee := l.cfg.FwrdingPolicy.InboundFee
8✔
3688

4✔
3689
                                //nolint:lll
4✔
3690
                                updatePacket := &htlcPacket{
4✔
3691
                                        incomingChanID:       l.ShortChanID(),
4✔
3692
                                        incomingHTLCID:       add.ID,
4✔
3693
                                        outgoingChanID:       fwdInfo.NextHop,
4✔
3694
                                        sourceRef:            &sourceRef,
3695
                                        incomingAmount:       add.Amount,
3696
                                        amount:               outgoingAdd.Amount,
3697
                                        htlc:                 outgoingAdd,
3698
                                        obfuscator:           obfuscator,
4✔
3699
                                        incomingTimeout:      add.Expiry,
4✔
3700
                                        outgoingTimeout:      fwdInfo.OutgoingCTLV,
4✔
3701
                                        inOnionCustomRecords: pld.CustomRecords(),
4✔
3702
                                        inboundFee:           inboundFee,
4✔
3703
                                        inWireCustomRecords:  add.CustomRecords.Copy(),
4✔
3704
                                }
4✔
3705
                                switchPackets = append(
4✔
3706
                                        switchPackets, updatePacket,
4✔
3707
                                )
4✔
3708

4✔
3709
                                continue
4✔
3710
                        }
4✔
3711

4✔
3712
                        // TODO(roasbeef): ensure don't accept outrageous
4✔
3713
                        // timeout for htlc
4✔
3714

4✔
3715
                        // With all our forwarding constraints met, we'll
4✔
3716
                        // create the outgoing HTLC using the parameters as
4✔
3717
                        // specified in the forwarding info.
4✔
3718
                        addMsg := &lnwire.UpdateAddHTLC{
4✔
3719
                                Expiry:        fwdInfo.OutgoingCTLV,
4✔
3720
                                Amount:        fwdInfo.AmountToForward,
4✔
3721
                                PaymentHash:   add.PaymentHash,
4✔
3722
                                BlindingPoint: fwdInfo.NextBlinding,
4✔
3723
                        }
4✔
3724

4✔
3725
                        // Finally, we'll encode the onion packet for the
4✔
3726
                        // _next_ hop using the hop iterator decoded for the
4✔
3727
                        // current hop.
4✔
3728
                        buf := bytes.NewBuffer(addMsg.OnionBlob[0:0])
4✔
3729
                        err := chanIterator.EncodeNextHop(buf)
4✔
3730
                        if err != nil {
3731
                                l.log.Errorf("unable to encode the "+
3732
                                        "remaining route %v", err)
3733

3734
                                cb := func(upd *lnwire.ChannelUpdate1) lnwire.FailureMessage { //nolint:lll
3735
                                        return lnwire.NewTemporaryChannelFailure(upd)
3736
                                }
3737

3738
                                failure := l.createFailureWithUpdate(
4✔
3739
                                        true, hop.Source, cb,
4✔
3740
                                )
4✔
3741

4✔
3742
                                l.sendHTLCError(
4✔
3743
                                        add, sourceRef, NewLinkError(failure),
4✔
3744
                                        obfuscator, false,
4✔
3745
                                )
8✔
3746
                                continue
4✔
3747
                        }
4✔
3748

4✔
3749
                        // Now that this add has been reprocessed, only append
4✔
3750
                        // it to our list of packets to forward to the switch
3751
                        // this is the first time processing the add. If the
3752
                        // fwd pkg has already been processed, then we entered
3753
                        // the above section to recreate a previous error.  If
3754
                        // the packet had previously been forwarded, it would
4✔
3755
                        // have been added to switchPackets at the top of this
4✔
3756
                        // section.
4✔
3757
                        if fwdPkg.State == channeldb.FwdStateLockedIn {
×
3758
                                inboundFee := l.cfg.FwrdingPolicy.InboundFee
×
3759

×
3760
                                //nolint:lll
×
3761
                                updatePacket := &htlcPacket{
×
3762
                                        incomingChanID:       l.ShortChanID(),
×
3763
                                        incomingHTLCID:       add.ID,
3764
                                        outgoingChanID:       fwdInfo.NextHop,
×
3765
                                        sourceRef:            &sourceRef,
×
3766
                                        incomingAmount:       add.Amount,
×
3767
                                        amount:               addMsg.Amount,
×
3768
                                        htlc:                 addMsg,
×
3769
                                        obfuscator:           obfuscator,
×
3770
                                        incomingTimeout:      add.Expiry,
×
3771
                                        outgoingTimeout:      fwdInfo.OutgoingCTLV,
×
3772
                                        inOnionCustomRecords: pld.CustomRecords(),
×
3773
                                        inboundFee:           inboundFee,
3774
                                        inWireCustomRecords:  add.CustomRecords.Copy(),
3775
                                }
3776

3777
                                fwdPkg.FwdFilter.Set(idx)
3778
                                switchPackets = append(switchPackets,
3779
                                        updatePacket)
3780
                        }
3781
                }
3782
        }
3783

8✔
3784
        // Commit the htlcs we are intending to forward if this package has not
4✔
3785
        // been fully processed.
4✔
3786
        if fwdPkg.State == channeldb.FwdStateLockedIn {
4✔
3787
                err := l.channel.SetFwdFilter(fwdPkg.Height, fwdPkg.FwdFilter)
4✔
3788
                if err != nil {
4✔
3789
                        l.failf(LinkFailureError{code: ErrInternalError},
4✔
3790
                                "unable to set fwd filter: %v", err)
4✔
3791
                        return
4✔
3792
                }
4✔
3793
        }
4✔
3794

4✔
3795
        if len(switchPackets) == 0 {
4✔
3796
                return
4✔
3797
        }
4✔
3798

4✔
3799
        replay := fwdPkg.State != channeldb.FwdStateLockedIn
4✔
3800

4✔
3801
        l.log.Debugf("forwarding %d packets to switch: replay=%v",
4✔
3802
                len(switchPackets), replay)
4✔
3803

4✔
3804
        // NOTE: This call is made synchronous so that we ensure all circuits
4✔
3805
        // are committed in the exact order that they are processed in the link.
4✔
3806
        // Failing to do this could cause reorderings/gaps in the range of
4✔
3807
        // opened circuits, which violates assumptions made by the circuit
3808
        // trimming.
3809
        l.forwardBatch(replay, switchPackets...)
3810
}
3811

3812
// processExitHop handles an htlc for which this link is the exit hop. It
8✔
3813
// returns a boolean indicating whether the commitment tx needs an update.
4✔
3814
func (l *channelLink) processExitHop(add lnwire.UpdateAddHTLC,
4✔
3815
        sourceRef channeldb.AddRef, obfuscator hop.ErrorEncrypter,
×
3816
        fwdInfo hop.ForwardingInfo, heightNow uint32,
×
3817
        payload invoices.Payload) error {
×
3818

×
3819
        // If hodl.ExitSettle is requested, we will not validate the final hop's
3820
        // ADD, nor will we settle the corresponding invoice or respond with the
3821
        // preimage.
8✔
3822
        if l.cfg.HodlMask.Active(hodl.ExitSettle) {
4✔
3823
                l.log.Warnf("%s for htlc(rhash=%x,htlcIndex=%v)",
4✔
3824
                        hodl.ExitSettle.Warning(), add.PaymentHash, add.ID)
3825

4✔
3826
                return nil
4✔
3827
        }
4✔
3828

4✔
3829
        // As we're the exit hop, we'll double check the hop-payload included in
4✔
3830
        // the HTLC to ensure that it was crafted correctly by the sender and
4✔
3831
        // is compatible with the HTLC we were extended.
4✔
3832
        //
4✔
3833
        // For a special case, if the fwdInfo doesn't have any blinded path
4✔
3834
        // information, and the incoming HTLC had special extra data, then
4✔
3835
        // we'll skip this amount check. The invoice acceptor will make sure we
4✔
3836
        // reject the HTLC if it's not containing the correct amount after
3837
        // examining the custom data.
3838
        hasBlindedPath := fwdInfo.NextBlinding.IsSome()
3839
        customHTLC := len(add.CustomRecords) > 0 && !hasBlindedPath
3840
        log.Tracef("Exit hop has_blinded_path=%v custom_htlc_bypass=%v",
3841
                hasBlindedPath, customHTLC)
3842

4✔
3843
        if !customHTLC && add.Amount < fwdInfo.AmountToForward {
4✔
3844
                l.log.Errorf("onion payload of incoming htlc(%x) has "+
4✔
3845
                        "incompatible value: expected <=%v, got %v",
4✔
3846
                        add.PaymentHash, add.Amount, fwdInfo.AmountToForward)
8✔
3847

4✔
3848
                failure := NewLinkError(
4✔
3849
                        lnwire.NewFinalIncorrectHtlcAmount(add.Amount),
3850
                )
3851
                l.sendHTLCError(add, sourceRef, failure, obfuscator, true)
3852

8✔
3853
                return nil
4✔
3854
        }
4✔
3855

3856
        // We'll also ensure that our time-lock value has been computed
4✔
3857
        // correctly.
4✔
3858
        if add.Expiry < fwdInfo.OutgoingCTLV {
4✔
3859
                l.log.Errorf("onion payload of incoming htlc(%x) has "+
×
3860
                        "incompatible time-lock: expected <=%v, got %v",
×
3861
                        add.PaymentHash, add.Expiry, fwdInfo.OutgoingCTLV)
3862

3863
                failure := NewLinkError(
3864
                        lnwire.NewFinalIncorrectCltvExpiry(add.Expiry),
4✔
3865
                )
×
3866

×
3867
                l.sendHTLCError(add, sourceRef, failure, obfuscator, true)
3868

3869
                return nil
8✔
3870
        }
4✔
3871

4✔
3872
        // Notify the invoiceRegistry of the exit hop htlc. If we crash right
3873
        // after this, this code will be re-executed after restart. We will
3874
        // receive back a resolution event.
3875
        invoiceHash := lntypes.Hash(add.PaymentHash)
4✔
3876

3877
        circuitKey := models.CircuitKey{
3878
                ChanID: l.ShortChanID(),
3879
                HtlcID: add.ID,
3880
        }
3881

3882
        event, err := l.cfg.Registry.NotifyExitHopHtlc(
3883
                invoiceHash, add.Amount, add.Expiry, int32(heightNow),
4✔
3884
                circuitKey, l.hodlQueue.ChanIn(), add.CustomRecords, payload,
4✔
3885
        )
4✔
3886
        if err != nil {
4✔
3887
                return err
4✔
3888
        }
8✔
3889

4✔
3890
        // Create a hodlHtlc struct and decide either resolved now or later.
4✔
3891
        htlc := hodlHtlc{
4✔
3892
                add:        add,
4✔
3893
                sourceRef:  sourceRef,
4✔
3894
                obfuscator: obfuscator,
3895
        }
3896

3897
        // If the event is nil, the invoice is being held, so we save payment
3898
        // descriptor for future reference.
3899
        if event == nil {
3900
                l.hodlMap[circuitKey] = htlc
3901
                return nil
3902
        }
3903

3904
        // Process the received resolution.
4✔
3905
        return l.processHtlcResolution(event, htlc)
4✔
3906
}
4✔
3907

4✔
3908
// settleHTLC settles the HTLC on the channel.
4✔
3909
func (l *channelLink) settleHTLC(preimage lntypes.Preimage,
4✔
UNCOV
3910
        htlcIndex uint64, sourceRef channeldb.AddRef) error {
×
UNCOV
3911

×
UNCOV
3912
        hash := preimage.Hash()
×
UNCOV
3913

×
UNCOV
3914
        l.log.Infof("settling htlc %v as exit hop", hash)
×
UNCOV
3915

×
UNCOV
3916
        err := l.channel.SettleHTLC(
×
UNCOV
3917
                preimage, htlcIndex, &sourceRef, nil, nil,
×
UNCOV
3918
        )
×
UNCOV
3919
        if err != nil {
×
UNCOV
3920
                return fmt.Errorf("unable to settle htlc: %w", err)
×
3921
        }
3922

3923
        // If the link is in hodl.BogusSettle mode, replace the preimage with a
3924
        // fake one before sending it to the peer.
4✔
UNCOV
3925
        if l.cfg.HodlMask.Active(hodl.BogusSettle) {
×
UNCOV
3926
                l.log.Warnf(hodl.BogusSettle.Warning())
×
UNCOV
3927
                preimage = [32]byte{}
×
UNCOV
3928
                copy(preimage[:], bytes.Repeat([]byte{2}, 32))
×
UNCOV
3929
        }
×
UNCOV
3930

×
UNCOV
3931
        // HTLC was successfully settled locally send notification about it
×
UNCOV
3932
        // remote peer.
×
UNCOV
3933
        l.cfg.Peer.SendMessage(false, &lnwire.UpdateFulfillHTLC{
×
UNCOV
3934
                ChanID:          l.ChanID(),
×
UNCOV
3935
                ID:              htlcIndex,
×
UNCOV
3936
                PaymentPreimage: preimage,
×
3937
        })
3938

3939
        // Once we have successfully settled the htlc, notify a settle event.
3940
        l.cfg.HtlcNotifier.NotifySettleEvent(
3941
                HtlcKey{
4✔
3942
                        IncomingCircuit: models.CircuitKey{
4✔
3943
                                ChanID: l.ShortChanID(),
4✔
3944
                                HtlcID: htlcIndex,
4✔
3945
                        },
4✔
3946
                },
4✔
3947
                preimage,
4✔
3948
                HtlcEventTypeReceive,
4✔
3949
        )
4✔
3950

4✔
3951
        return nil
4✔
3952
}
8✔
3953

4✔
3954
// forwardBatch forwards the given htlcPackets to the switch, and waits on the
4✔
3955
// err chan for the individual responses. This method is intended to be spawned
3956
// as a goroutine so the responses can be handled in the background.
3957
func (l *channelLink) forwardBatch(replay bool, packets ...*htlcPacket) {
4✔
3958
        // Don't forward packets for which we already have a response in our
4✔
3959
        // mailbox. This could happen if a packet fails and is buffered in the
4✔
3960
        // mailbox, and the incoming link flaps.
4✔
3961
        var filteredPkts = make([]*htlcPacket, 0, len(packets))
4✔
3962
        for _, pkt := range packets {
4✔
3963
                if l.mailBox.HasPacket(pkt.inKey()) {
4✔
3964
                        continue
4✔
3965
                }
8✔
3966

4✔
3967
                filteredPkts = append(filteredPkts, pkt)
4✔
3968
        }
4✔
3969

3970
        err := l.cfg.ForwardPackets(l.Quit, replay, filteredPkts...)
3971
        if err != nil {
4✔
3972
                log.Errorf("Unhandled error while reforwarding htlc "+
3973
                        "settle/fail over htlcswitch: %v", err)
3974
        }
3975
}
3976

4✔
3977
// sendHTLCError functions cancels HTLC and send cancel message back to the
4✔
3978
// peer from which HTLC was received.
4✔
3979
func (l *channelLink) sendHTLCError(add lnwire.UpdateAddHTLC,
4✔
3980
        sourceRef channeldb.AddRef, failure *LinkError,
4✔
3981
        e hop.ErrorEncrypter, isReceive bool) {
4✔
3982

4✔
3983
        reason, err := e.EncryptFirstHop(failure.WireMessage())
4✔
3984
        if err != nil {
4✔
3985
                l.log.Errorf("unable to obfuscate error: %v", err)
4✔
3986
                return
×
3987
        }
×
3988

3989
        err = l.channel.FailHTLC(add.ID, reason, &sourceRef, nil, nil)
3990
        if err != nil {
3991
                l.log.Errorf("unable cancel htlc: %v", err)
8✔
3992
                return
4✔
3993
        }
4✔
3994

4✔
3995
        // Send the appropriate failure message depending on whether we're
4✔
3996
        // in a blinded route or not.
3997
        if err := l.sendIncomingHTLCFailureMsg(
3998
                add.ID, e, reason,
3999
        ); err != nil {
4✔
4000
                l.log.Errorf("unable to send HTLC failure: %v", err)
4✔
4001
                return
4✔
4002
        }
4✔
4003

4✔
4004
        // Notify a link failure on our incoming link. Outgoing htlc information
4✔
4005
        // is not available at this point, because we have not decrypted the
4✔
4006
        // onion, so it is excluded.
4✔
4007
        var eventType HtlcEventType
4✔
4008
        if isReceive {
4✔
4009
                eventType = HtlcEventTypeReceive
4✔
4010
        } else {
4✔
4011
                eventType = HtlcEventTypeForward
4✔
4012
        }
4✔
4013

4✔
4014
        l.cfg.HtlcNotifier.NotifyLinkFailEvent(
4✔
4015
                HtlcKey{
4✔
4016
                        IncomingCircuit: models.CircuitKey{
4✔
4017
                                ChanID: l.ShortChanID(),
4✔
4018
                                HtlcID: add.ID,
4019
                        },
4020
                },
4021
                HtlcInfo{
4022
                        IncomingTimeLock: add.Expiry,
4023
                        IncomingAmt:      add.Amount,
4✔
4024
                },
4✔
4025
                eventType,
4✔
4026
                failure,
4✔
4027
                true,
4✔
4028
        )
8✔
4029
}
8✔
4030

4✔
4031
// sendPeerHTLCFailure handles sending a HTLC failure message back to the
4032
// peer from which the HTLC was received. This function is primarily used to
4033
// handle the special requirements of route blinding, specifically:
4✔
4034
// - Forwarding nodes must switch out any errors with MalformedFailHTLC
4035
// - Introduction nodes should return regular HTLC failure messages.
4036
//
4✔
4037
// It accepts the original opaque failure, which will be used in the case
4✔
UNCOV
4038
// that we're not part of a blinded route and an error encrypter that'll be
×
UNCOV
4039
// used if we are the introduction node and need to present an error as if
×
UNCOV
4040
// we're the failing party.
×
4041
func (l *channelLink) sendIncomingHTLCFailureMsg(htlcIndex uint64,
4042
        e hop.ErrorEncrypter,
4043
        originalFailure lnwire.OpaqueReason) error {
4044

4045
        var msg lnwire.Message
4046
        switch {
4047
        // Our circuit's error encrypter will be nil if this was a locally
4✔
4048
        // initiated payment. We can only hit a blinded error for a locally
4✔
4049
        // initiated payment if we allow ourselves to be picked as the
4✔
4050
        // introduction node for our own payments and in that case we
4✔
4051
        // shouldn't reach this code. To prevent the HTLC getting stuck,
×
4052
        // we fail it back and log an error.
×
4053
        // code.
×
4054
        case e == nil:
4055
                msg = &lnwire.UpdateFailHTLC{
4✔
4056
                        ChanID: l.ChanID(),
4✔
4057
                        ID:     htlcIndex,
×
4058
                        Reason: originalFailure,
×
4059
                }
×
4060

4061
                l.log.Errorf("Unexpected blinded failure when "+
4062
                        "we are the sending node, incoming htlc: %v(%v)",
4063
                        l.ShortChanID(), htlcIndex)
4✔
4064

4✔
4065
        // For cleartext hops (ie, non-blinded/normal) we don't need any
4✔
4066
        // transformation on the error message and can just send the original.
×
4067
        case !e.Type().IsBlinded():
×
4068
                msg = &lnwire.UpdateFailHTLC{
×
4069
                        ChanID: l.ChanID(),
4070
                        ID:     htlcIndex,
4071
                        Reason: originalFailure,
4072
                }
4073

4✔
4074
        // When we're the introduction node, we need to convert the error to
8✔
4075
        // a UpdateFailHTLC.
4✔
4076
        case e.Type() == hop.EncrypterTypeIntroduction:
8✔
4077
                l.log.Debugf("Introduction blinded node switching out failure "+
4✔
4078
                        "error: %v", htlcIndex)
4✔
4079

4080
                // The specification does not require that we set the onion
4✔
4081
                // blob.
4✔
4082
                failureMsg := lnwire.NewInvalidBlinding(
4✔
4083
                        fn.None[[lnwire.OnionPacketSize]byte](),
4✔
4084
                )
4✔
4085
                reason, err := e.EncryptFirstHop(failureMsg)
4✔
4086
                if err != nil {
4✔
4087
                        return err
4✔
4088
                }
4✔
4089

4✔
4090
                msg = &lnwire.UpdateFailHTLC{
4✔
4091
                        ChanID: l.ChanID(),
4✔
4092
                        ID:     htlcIndex,
4✔
4093
                        Reason: reason,
4✔
4094
                }
4✔
4095

4096
        // If we are a relaying node, we need to switch out any error that
4097
        // we've received to a malformed HTLC error.
4098
        case e.Type() == hop.EncrypterTypeRelaying:
4099
                l.log.Debugf("Relaying blinded node switching out malformed "+
4100
                        "error: %v", htlcIndex)
4101

4102
                msg = &lnwire.UpdateFailMalformedHTLC{
4103
                        ChanID:      l.ChanID(),
4104
                        ID:          htlcIndex,
4105
                        FailureCode: lnwire.CodeInvalidBlinding,
4106
                }
4107

4108
        default:
4109
                return fmt.Errorf("unexpected encrypter: %d", e)
4✔
4110
        }
4✔
4111

4✔
4112
        if err := l.cfg.Peer.SendMessage(false, msg); err != nil {
4✔
4113
                l.log.Warnf("Send update fail failed: %v", err)
4114
        }
4115

4116
        return nil
4117
}
4118

4119
// sendMalformedHTLCError helper function which sends the malformed HTLC update
4120
// to the payment sender.
×
4121
func (l *channelLink) sendMalformedHTLCError(htlcIndex uint64,
×
4122
        code lnwire.FailCode, onionBlob [lnwire.OnionPacketSize]byte,
×
4123
        sourceRef *channeldb.AddRef) {
×
4124

×
4125
        shaOnionBlob := sha256.Sum256(onionBlob[:])
×
4126
        err := l.channel.MalformedFailHTLC(htlcIndex, code, shaOnionBlob, sourceRef)
×
4127
        if err != nil {
×
4128
                l.log.Errorf("unable cancel htlc: %v", err)
×
4129
                return
×
4130
        }
4131

4132
        l.cfg.Peer.SendMessage(false, &lnwire.UpdateFailMalformedHTLC{
4133
                ChanID:       l.ChanID(),
4✔
4134
                ID:           htlcIndex,
4✔
4135
                ShaOnionBlob: shaOnionBlob,
4✔
4136
                FailureCode:  code,
4✔
4137
        })
4✔
4138
}
4✔
4139

4140
// failf is a function which is used to encapsulate the action necessary for
4141
// properly failing the link. It takes a LinkFailureError, which will be passed
4142
// to the OnChannelFailure closure, in order for it to determine if we should
4✔
4143
// force close the channel, and if we should send an error message to the
4✔
4144
// remote peer.
4✔
4145
func (l *channelLink) failf(linkErr LinkFailureError, format string,
4✔
4146
        a ...interface{}) {
4✔
4147

4✔
4148
        reason := fmt.Errorf(format, a...)
4✔
4149

4✔
4150
        // Return if we have already notified about a failure.
4✔
4151
        if l.failed {
4✔
4152
                l.log.Warnf("ignoring link failure (%v), as link already "+
4✔
4153
                        "failed", reason)
×
4154
                return
×
4155
        }
4156

4✔
4157
        l.log.Errorf("failing link: %s with error: %v", reason, linkErr)
4✔
4158

4✔
4159
        // Set failed, such that we won't process any more updates, and notify
4✔
4160
        // the peer about the failure.
4✔
4161
        l.failed = true
4162
        l.cfg.OnChannelFailure(l.ChanID(), l.ShortChanID(), linkErr)
4163
}
4164

4✔
4165
// FundingCustomBlob returns the custom funding blob of the channel that this
4✔
4166
// link is associated with. The funding blob represents static information about
4✔
4167
// the channel that was created at channel funding time.
4✔
4168
func (l *channelLink) FundingCustomBlob() fn.Option[tlv.Blob] {
4✔
4169
        if l.channel == nil {
4✔
4170
                return fn.None[tlv.Blob]()
4✔
4171
        }
4✔
4172

4✔
4173
        if l.channel.State() == nil {
4174
                return fn.None[tlv.Blob]()
×
4175
        }
×
4176

4177
        return l.channel.State().CustomBlob
4178
}
4✔
4179

×
4180
// CommitmentCustomBlob returns the custom blob of the current local commitment
×
4181
// of the channel that this link is associated with.
4182
func (l *channelLink) CommitmentCustomBlob() fn.Option[tlv.Blob] {
4✔
4183
        if l.channel == nil {
4184
                return fn.None[tlv.Blob]()
4185
        }
4186

4187
        return l.channel.LocalCommitmentBlob()
4188
}
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