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

lightningnetwork / lnd / 12312390362

13 Dec 2024 08:44AM UTC coverage: 57.458% (+8.5%) from 48.92%
12312390362

Pull #9343

github

ellemouton
fn: rework the ContextGuard and add tests

In this commit, the ContextGuard struct is re-worked such that the
context that its new main WithCtx method provides is cancelled in sync
with a parent context being cancelled or with it's quit channel being
cancelled. Tests are added to assert the behaviour. In order for the
close of the quit channel to be consistent with the cancelling of the
derived context, the quit channel _must_ be contained internal to the
ContextGuard so that callers are only able to close the channel via the
exposed Quit method which will then take care to first cancel any
derived context that depend on the quit channel before returning.
Pull Request #9343: fn: expand the ContextGuard and add tests

101853 of 177264 relevant lines covered (57.46%)

24972.93 hits per line

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

73.41
/channeldb/channel.go
1
package channeldb
2

3
import (
4
        "bytes"
5
        "crypto/hmac"
6
        "crypto/sha256"
7
        "encoding/binary"
8
        "errors"
9
        "fmt"
10
        "io"
11
        "net"
12
        "strconv"
13
        "strings"
14
        "sync"
15

16
        "github.com/btcsuite/btcd/btcec/v2"
17
        "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
18
        "github.com/btcsuite/btcd/btcutil"
19
        "github.com/btcsuite/btcd/chaincfg/chainhash"
20
        "github.com/btcsuite/btcd/wire"
21
        "github.com/btcsuite/btcwallet/walletdb"
22
        "github.com/lightningnetwork/lnd/fn/v2"
23
        graphdb "github.com/lightningnetwork/lnd/graph/db"
24
        "github.com/lightningnetwork/lnd/graph/db/models"
25
        "github.com/lightningnetwork/lnd/htlcswitch/hop"
26
        "github.com/lightningnetwork/lnd/input"
27
        "github.com/lightningnetwork/lnd/keychain"
28
        "github.com/lightningnetwork/lnd/kvdb"
29
        "github.com/lightningnetwork/lnd/lntypes"
30
        "github.com/lightningnetwork/lnd/lnwire"
31
        "github.com/lightningnetwork/lnd/shachain"
32
        "github.com/lightningnetwork/lnd/tlv"
33
)
34

35
const (
36
        // AbsoluteThawHeightThreshold is the threshold at which a thaw height
37
        // begins to be interpreted as an absolute block height, rather than a
38
        // relative one.
39
        AbsoluteThawHeightThreshold uint32 = 500000
40

41
        // HTLCBlindingPointTLV is the tlv type used for storing blinding
42
        // points with HTLCs.
43
        HTLCBlindingPointTLV tlv.Type = 0
44
)
45

46
var (
47
        // closedChannelBucket stores summarization information concerning
48
        // previously open, but now closed channels.
49
        closedChannelBucket = []byte("closed-chan-bucket")
50

51
        // openChannelBucket stores all the currently open channels. This bucket
52
        // has a second, nested bucket which is keyed by a node's ID. Within
53
        // that node ID bucket, all attributes required to track, update, and
54
        // close a channel are stored.
55
        //
56
        // openChan -> nodeID -> chanPoint
57
        //
58
        // TODO(roasbeef): flesh out comment
59
        openChannelBucket = []byte("open-chan-bucket")
60

61
        // outpointBucket stores all of our channel outpoints and a tlv
62
        // stream containing channel data.
63
        //
64
        // outpoint -> tlv stream.
65
        //
66
        outpointBucket = []byte("outpoint-bucket")
67

68
        // chanIDBucket stores all of the 32-byte channel ID's we know about.
69
        // These could be derived from outpointBucket, but it is more
70
        // convenient to have these in their own bucket.
71
        //
72
        // chanID -> tlv stream.
73
        //
74
        chanIDBucket = []byte("chan-id-bucket")
75

76
        // historicalChannelBucket stores all channels that have seen their
77
        // commitment tx confirm. All information from their previous open state
78
        // is retained.
79
        historicalChannelBucket = []byte("historical-chan-bucket")
80

81
        // chanInfoKey can be accessed within the bucket for a channel
82
        // (identified by its chanPoint). This key stores all the static
83
        // information for a channel which is decided at the end of  the
84
        // funding flow.
85
        chanInfoKey = []byte("chan-info-key")
86

87
        // localUpfrontShutdownKey can be accessed within the bucket for a channel
88
        // (identified by its chanPoint). This key stores an optional upfront
89
        // shutdown script for the local peer.
90
        localUpfrontShutdownKey = []byte("local-upfront-shutdown-key")
91

92
        // remoteUpfrontShutdownKey can be accessed within the bucket for a channel
93
        // (identified by its chanPoint). This key stores an optional upfront
94
        // shutdown script for the remote peer.
95
        remoteUpfrontShutdownKey = []byte("remote-upfront-shutdown-key")
96

97
        // chanCommitmentKey can be accessed within the sub-bucket for a
98
        // particular channel. This key stores the up to date commitment state
99
        // for a particular channel party. Appending a 0 to the end of this key
100
        // indicates it's the commitment for the local party, and appending a 1
101
        // to the end of this key indicates it's the commitment for the remote
102
        // party.
103
        chanCommitmentKey = []byte("chan-commitment-key")
104

105
        // unsignedAckedUpdatesKey is an entry in the channel bucket that
106
        // contains the remote updates that we have acked, but not yet signed
107
        // for in one of our remote commits.
108
        unsignedAckedUpdatesKey = []byte("unsigned-acked-updates-key")
109

110
        // remoteUnsignedLocalUpdatesKey is an entry in the channel bucket that
111
        // contains the local updates that the remote party has acked, but
112
        // has not yet signed for in one of their local commits.
113
        remoteUnsignedLocalUpdatesKey = []byte("remote-unsigned-local-updates-key")
114

115
        // revocationStateKey stores their current revocation hash, our
116
        // preimage producer and their preimage store.
117
        revocationStateKey = []byte("revocation-state-key")
118

119
        // dataLossCommitPointKey stores the commitment point received from the
120
        // remote peer during a channel sync in case we have lost channel state.
121
        dataLossCommitPointKey = []byte("data-loss-commit-point-key")
122

123
        // forceCloseTxKey points to a the unilateral closing tx that we
124
        // broadcasted when moving the channel to state CommitBroadcasted.
125
        forceCloseTxKey = []byte("closing-tx-key")
126

127
        // coopCloseTxKey points to a the cooperative closing tx that we
128
        // broadcasted when moving the channel to state CoopBroadcasted.
129
        coopCloseTxKey = []byte("coop-closing-tx-key")
130

131
        // shutdownInfoKey points to the serialised shutdown info that has been
132
        // persisted for a channel. The existence of this info means that we
133
        // have sent the Shutdown message before and so should re-initiate the
134
        // shutdown on re-establish.
135
        shutdownInfoKey = []byte("shutdown-info-key")
136

137
        // commitDiffKey stores the current pending commitment state we've
138
        // extended to the remote party (if any). Each time we propose a new
139
        // state, we store the information necessary to reconstruct this state
140
        // from the prior commitment. This allows us to resync the remote party
141
        // to their expected state in the case of message loss.
142
        //
143
        // TODO(roasbeef): rename to commit chain?
144
        commitDiffKey = []byte("commit-diff-key")
145

146
        // frozenChanKey is the key where we store the information for any
147
        // active "frozen" channels. This key is present only in the leaf
148
        // bucket for a given channel.
149
        frozenChanKey = []byte("frozen-chans")
150

151
        // lastWasRevokeKey is a key that stores true when the last update we
152
        // sent was a revocation and false when it was a commitment signature.
153
        // This is nil in the case of new channels with no updates exchanged.
154
        lastWasRevokeKey = []byte("last-was-revoke")
155

156
        // finalHtlcsBucket contains the htlcs that have been resolved
157
        // definitively. Within this bucket, there is a sub-bucket for each
158
        // channel. In each channel bucket, the htlc indices are stored along
159
        // with final outcome.
160
        //
161
        // final-htlcs -> chanID -> htlcIndex -> outcome
162
        //
163
        // 'outcome' is a byte value that encodes:
164
        //
165
        //       | true      false
166
        // ------+------------------
167
        // bit 0 | settled   failed
168
        // bit 1 | offchain  onchain
169
        //
170
        // This bucket is positioned at the root level, because its contents
171
        // will be kept independent of the channel lifecycle. This is to avoid
172
        // the situation where a channel force-closes autonomously and the user
173
        // not being able to query for htlc outcomes anymore.
174
        finalHtlcsBucket = []byte("final-htlcs")
175
)
176

177
var (
178
        // ErrNoCommitmentsFound is returned when a channel has not set
179
        // commitment states.
180
        ErrNoCommitmentsFound = fmt.Errorf("no commitments found")
181

182
        // ErrNoChanInfoFound is returned when a particular channel does not
183
        // have any channels state.
184
        ErrNoChanInfoFound = fmt.Errorf("no chan info found")
185

186
        // ErrNoRevocationsFound is returned when revocation state for a
187
        // particular channel cannot be found.
188
        ErrNoRevocationsFound = fmt.Errorf("no revocations found")
189

190
        // ErrNoPendingCommit is returned when there is not a pending
191
        // commitment for a remote party. A new commitment is written to disk
192
        // each time we write a new state in order to be properly fault
193
        // tolerant.
194
        ErrNoPendingCommit = fmt.Errorf("no pending commits found")
195

196
        // ErrNoCommitPoint is returned when no data loss commit point is found
197
        // in the database.
198
        ErrNoCommitPoint = fmt.Errorf("no commit point found")
199

200
        // ErrNoCloseTx is returned when no closing tx is found for a channel
201
        // in the state CommitBroadcasted.
202
        ErrNoCloseTx = fmt.Errorf("no closing tx found")
203

204
        // ErrNoShutdownInfo is returned when no shutdown info has been
205
        // persisted for a channel.
206
        ErrNoShutdownInfo = errors.New("no shutdown info")
207

208
        // ErrNoRestoredChannelMutation is returned when a caller attempts to
209
        // mutate a channel that's been recovered.
210
        ErrNoRestoredChannelMutation = fmt.Errorf("cannot mutate restored " +
211
                "channel state")
212

213
        // ErrChanBorked is returned when a caller attempts to mutate a borked
214
        // channel.
215
        ErrChanBorked = fmt.Errorf("cannot mutate borked channel")
216

217
        // ErrMissingIndexEntry is returned when a caller attempts to close a
218
        // channel and the outpoint is missing from the index.
219
        ErrMissingIndexEntry = fmt.Errorf("missing outpoint from index")
220

221
        // ErrOnionBlobLength is returned is an onion blob with incorrect
222
        // length is read from disk.
223
        ErrOnionBlobLength = errors.New("onion blob < 1366 bytes")
224
)
225

226
const (
227
        // A tlv type definition used to serialize an outpoint's indexStatus
228
        // for use in the outpoint index.
229
        indexStatusType tlv.Type = 0
230
)
231

232
// openChannelTlvData houses the new data fields that are stored for each
233
// channel in a TLV stream within the root bucket. This is stored as a TLV
234
// stream appended to the existing hard-coded fields in the channel's root
235
// bucket. New fields being added to the channel state should be added here.
236
//
237
// NOTE: This struct is used for serialization purposes only and its fields
238
// should be accessed via the OpenChannel struct while in memory.
239
type openChannelTlvData struct {
240
        // revokeKeyLoc is the key locator for the revocation key.
241
        revokeKeyLoc tlv.RecordT[tlv.TlvType1, keyLocRecord]
242

243
        // initialLocalBalance is the initial local balance of the channel.
244
        initialLocalBalance tlv.RecordT[tlv.TlvType2, uint64]
245

246
        // initialRemoteBalance is the initial remote balance of the channel.
247
        initialRemoteBalance tlv.RecordT[tlv.TlvType3, uint64]
248

249
        // realScid is the real short channel ID of the channel corresponding to
250
        // the on-chain outpoint.
251
        realScid tlv.RecordT[tlv.TlvType4, lnwire.ShortChannelID]
252

253
        // memo is an optional text field that gives context to the user about
254
        // the channel.
255
        memo tlv.OptionalRecordT[tlv.TlvType5, []byte]
256

257
        // tapscriptRoot is the optional Tapscript root the channel funding
258
        // output commits to.
259
        tapscriptRoot tlv.OptionalRecordT[tlv.TlvType6, [32]byte]
260

261
        // customBlob is an optional TLV encoded blob of data representing
262
        // custom channel funding information.
263
        customBlob tlv.OptionalRecordT[tlv.TlvType7, tlv.Blob]
264
}
265

266
// encode serializes the openChannelTlvData to the given io.Writer.
267
func (c *openChannelTlvData) encode(w io.Writer) error {
3,221✔
268
        tlvRecords := []tlv.Record{
3,221✔
269
                c.revokeKeyLoc.Record(),
3,221✔
270
                c.initialLocalBalance.Record(),
3,221✔
271
                c.initialRemoteBalance.Record(),
3,221✔
272
                c.realScid.Record(),
3,221✔
273
        }
3,221✔
274
        c.memo.WhenSome(func(memo tlv.RecordT[tlv.TlvType5, []byte]) {
3,642✔
275
                tlvRecords = append(tlvRecords, memo.Record())
421✔
276
        })
421✔
277
        c.tapscriptRoot.WhenSome(
3,221✔
278
                func(root tlv.RecordT[tlv.TlvType6, [32]byte]) {
3,694✔
279
                        tlvRecords = append(tlvRecords, root.Record())
473✔
280
                },
473✔
281
        )
282
        c.customBlob.WhenSome(func(blob tlv.RecordT[tlv.TlvType7, tlv.Blob]) {
3,642✔
283
                tlvRecords = append(tlvRecords, blob.Record())
421✔
284
        })
421✔
285

286
        // Create the tlv stream.
287
        tlvStream, err := tlv.NewStream(tlvRecords...)
3,221✔
288
        if err != nil {
3,221✔
289
                return err
×
290
        }
×
291

292
        return tlvStream.Encode(w)
3,221✔
293
}
294

295
// decode deserializes the openChannelTlvData from the given io.Reader.
296
func (c *openChannelTlvData) decode(r io.Reader) error {
7,125✔
297
        memo := c.memo.Zero()
7,125✔
298
        tapscriptRoot := c.tapscriptRoot.Zero()
7,125✔
299
        blob := c.customBlob.Zero()
7,125✔
300

7,125✔
301
        // Create the tlv stream.
7,125✔
302
        tlvStream, err := tlv.NewStream(
7,125✔
303
                c.revokeKeyLoc.Record(),
7,125✔
304
                c.initialLocalBalance.Record(),
7,125✔
305
                c.initialRemoteBalance.Record(),
7,125✔
306
                c.realScid.Record(),
7,125✔
307
                memo.Record(),
7,125✔
308
                tapscriptRoot.Record(),
7,125✔
309
                blob.Record(),
7,125✔
310
        )
7,125✔
311
        if err != nil {
7,125✔
312
                return err
×
313
        }
×
314

315
        tlvs, err := tlvStream.DecodeWithParsedTypes(r)
7,125✔
316
        if err != nil {
7,125✔
317
                return err
×
318
        }
×
319

320
        if _, ok := tlvs[memo.TlvType()]; ok {
7,452✔
321
                c.memo = tlv.SomeRecordT(memo)
327✔
322
        }
327✔
323
        if _, ok := tlvs[tapscriptRoot.TlvType()]; ok {
7,560✔
324
                c.tapscriptRoot = tlv.SomeRecordT(tapscriptRoot)
435✔
325
        }
435✔
326
        if _, ok := tlvs[c.customBlob.TlvType()]; ok {
7,452✔
327
                c.customBlob = tlv.SomeRecordT(blob)
327✔
328
        }
327✔
329

330
        return nil
7,125✔
331
}
332

333
// indexStatus is an enum-like type that describes what state the
334
// outpoint is in. Currently only two possible values.
335
type indexStatus uint8
336

337
const (
338
        // outpointOpen represents an outpoint that is open in the outpoint index.
339
        outpointOpen indexStatus = 0
340

341
        // outpointClosed represents an outpoint that is closed in the outpoint
342
        // index.
343
        outpointClosed indexStatus = 1
344
)
345

346
// ChannelType is an enum-like type that describes one of several possible
347
// channel types. Each open channel is associated with a particular type as the
348
// channel type may determine how higher level operations are conducted such as
349
// fee negotiation, channel closing, the format of HTLCs, etc. Structure-wise,
350
// a ChannelType is a bit field, with each bit denoting a modification from the
351
// base channel type of single funder.
352
type ChannelType uint64
353

354
const (
355
        // NOTE: iota isn't used here for this enum needs to be stable
356
        // long-term as it will be persisted to the database.
357

358
        // SingleFunderBit represents a channel wherein one party solely funds
359
        // the entire capacity of the channel.
360
        SingleFunderBit ChannelType = 0
361

362
        // DualFunderBit represents a channel wherein both parties contribute
363
        // funds towards the total capacity of the channel. The channel may be
364
        // funded symmetrically or asymmetrically.
365
        DualFunderBit ChannelType = 1 << 0
366

367
        // SingleFunderTweaklessBit is similar to the basic SingleFunder channel
368
        // type, but it omits the tweak for one's key in the commitment
369
        // transaction of the remote party.
370
        SingleFunderTweaklessBit ChannelType = 1 << 1
371

372
        // NoFundingTxBit denotes if we have the funding transaction locally on
373
        // disk. This bit may be on if the funding transaction was crafted by a
374
        // wallet external to the primary daemon.
375
        NoFundingTxBit ChannelType = 1 << 2
376

377
        // AnchorOutputsBit indicates that the channel makes use of anchor
378
        // outputs to bump the commitment transaction's effective feerate. This
379
        // channel type also uses a delayed to_remote output script.
380
        AnchorOutputsBit ChannelType = 1 << 3
381

382
        // FrozenBit indicates that the channel is a frozen channel, meaning
383
        // that only the responder can decide to cooperatively close the
384
        // channel.
385
        FrozenBit ChannelType = 1 << 4
386

387
        // ZeroHtlcTxFeeBit indicates that the channel should use zero-fee
388
        // second-level HTLC transactions.
389
        ZeroHtlcTxFeeBit ChannelType = 1 << 5
390

391
        // LeaseExpirationBit indicates that the channel has been leased for a
392
        // period of time, constraining every output that pays to the channel
393
        // initiator with an additional CLTV of the lease maturity.
394
        LeaseExpirationBit ChannelType = 1 << 6
395

396
        // ZeroConfBit indicates that the channel is a zero-conf channel.
397
        ZeroConfBit ChannelType = 1 << 7
398

399
        // ScidAliasChanBit indicates that the channel has negotiated the
400
        // scid-alias channel type.
401
        ScidAliasChanBit ChannelType = 1 << 8
402

403
        // ScidAliasFeatureBit indicates that the scid-alias feature bit was
404
        // negotiated during the lifetime of this channel.
405
        ScidAliasFeatureBit ChannelType = 1 << 9
406

407
        // SimpleTaprootFeatureBit indicates that the simple-taproot-chans
408
        // feature bit was negotiated during the lifetime of the channel.
409
        SimpleTaprootFeatureBit ChannelType = 1 << 10
410

411
        // TapscriptRootBit indicates that this is a MuSig2 channel with a top
412
        // level tapscript commitment. This MUST be set along with the
413
        // SimpleTaprootFeatureBit.
414
        TapscriptRootBit ChannelType = 1 << 11
415
)
416

417
// IsSingleFunder returns true if the channel type if one of the known single
418
// funder variants.
419
func (c ChannelType) IsSingleFunder() bool {
10,432✔
420
        return c&DualFunderBit == 0
10,432✔
421
}
10,432✔
422

423
// IsDualFunder returns true if the ChannelType has the DualFunderBit set.
424
func (c ChannelType) IsDualFunder() bool {
×
425
        return c&DualFunderBit == DualFunderBit
×
426
}
×
427

428
// IsTweakless returns true if the target channel uses a commitment that
429
// doesn't tweak the key for the remote party.
430
func (c ChannelType) IsTweakless() bool {
10,643✔
431
        return c&SingleFunderTweaklessBit == SingleFunderTweaklessBit
10,643✔
432
}
10,643✔
433

434
// HasFundingTx returns true if this channel type is one that has a funding
435
// transaction stored locally.
436
func (c ChannelType) HasFundingTx() bool {
10,442✔
437
        return c&NoFundingTxBit == 0
10,442✔
438
}
10,442✔
439

440
// HasAnchors returns true if this channel type has anchor outputs on its
441
// commitment.
442
func (c ChannelType) HasAnchors() bool {
261,506✔
443
        return c&AnchorOutputsBit == AnchorOutputsBit
261,506✔
444
}
261,506✔
445

446
// ZeroHtlcTxFee returns true if this channel type uses second-level HTLC
447
// transactions signed with zero-fee.
448
func (c ChannelType) ZeroHtlcTxFee() bool {
211,105✔
449
        return c&ZeroHtlcTxFeeBit == ZeroHtlcTxFeeBit
211,105✔
450
}
211,105✔
451

452
// IsFrozen returns true if the channel is considered to be "frozen". A frozen
453
// channel means that only the responder can initiate a cooperative channel
454
// closure.
455
func (c ChannelType) IsFrozen() bool {
8,490✔
456
        return c&FrozenBit == FrozenBit
8,490✔
457
}
8,490✔
458

459
// HasLeaseExpiration returns true if the channel originated from a lease.
460
func (c ChannelType) HasLeaseExpiration() bool {
32,217✔
461
        return c&LeaseExpirationBit == LeaseExpirationBit
32,217✔
462
}
32,217✔
463

464
// HasZeroConf returns true if the channel is a zero-conf channel.
465
func (c ChannelType) HasZeroConf() bool {
645✔
466
        return c&ZeroConfBit == ZeroConfBit
645✔
467
}
645✔
468

469
// HasScidAliasChan returns true if the scid-alias channel type was negotiated.
470
func (c ChannelType) HasScidAliasChan() bool {
×
471
        return c&ScidAliasChanBit == ScidAliasChanBit
×
472
}
×
473

474
// HasScidAliasFeature returns true if the scid-alias feature bit was
475
// negotiated during the lifetime of this channel.
476
func (c ChannelType) HasScidAliasFeature() bool {
484✔
477
        return c&ScidAliasFeatureBit == ScidAliasFeatureBit
484✔
478
}
484✔
479

480
// IsTaproot returns true if the channel is using taproot features.
481
func (c ChannelType) IsTaproot() bool {
291,560✔
482
        return c&SimpleTaprootFeatureBit == SimpleTaprootFeatureBit
291,560✔
483
}
291,560✔
484

485
// HasTapscriptRoot returns true if the channel is using a top level tapscript
486
// root commitment.
487
func (c ChannelType) HasTapscriptRoot() bool {
286✔
488
        return c&TapscriptRootBit == TapscriptRootBit
286✔
489
}
286✔
490

491
// ChannelStateBounds are the parameters from OpenChannel and AcceptChannel
492
// that are responsible for providing bounds on the state space of the abstract
493
// channel state. These values must be remembered for normal channel operation
494
// but they do not impact how we compute the commitment transactions themselves.
495
type ChannelStateBounds struct {
496
        // ChanReserve is an absolute reservation on the channel for the
497
        // owner of this set of constraints. This means that the current
498
        // settled balance for this node CANNOT dip below the reservation
499
        // amount. This acts as a defense against costless attacks when
500
        // either side no longer has any skin in the game.
501
        ChanReserve btcutil.Amount
502

503
        // MaxPendingAmount is the maximum pending HTLC value that the
504
        // owner of these constraints can offer the remote node at a
505
        // particular time.
506
        MaxPendingAmount lnwire.MilliSatoshi
507

508
        // MinHTLC is the minimum HTLC value that the owner of these
509
        // constraints can offer the remote node. If any HTLCs below this
510
        // amount are offered, then the HTLC will be rejected. This, in
511
        // tandem with the dust limit allows a node to regulate the
512
        // smallest HTLC that it deems economically relevant.
513
        MinHTLC lnwire.MilliSatoshi
514

515
        // MaxAcceptedHtlcs is the maximum number of HTLCs that the owner of
516
        // this set of constraints can offer the remote node. This allows each
517
        // node to limit their over all exposure to HTLCs that may need to be
518
        // acted upon in the case of a unilateral channel closure or a contract
519
        // breach.
520
        MaxAcceptedHtlcs uint16
521
}
522

523
// CommitmentParams are the parameters from OpenChannel and
524
// AcceptChannel that are required to render an abstract channel state to a
525
// concrete commitment transaction. These values are necessary to (re)compute
526
// the commitment transaction. We treat these differently than the state space
527
// bounds because their history needs to be stored in order to properly handle
528
// chain resolution.
529
type CommitmentParams struct {
530
        // DustLimit is the threshold (in satoshis) below which any outputs
531
        // should be trimmed. When an output is trimmed, it isn't materialized
532
        // as an actual output, but is instead burned to miner's fees.
533
        DustLimit btcutil.Amount
534

535
        // CsvDelay is the relative time lock delay expressed in blocks. Any
536
        // settled outputs that pay to the owner of this channel configuration
537
        // MUST ensure that the delay branch uses this value as the relative
538
        // time lock. Similarly, any HTLC's offered by this node should use
539
        // this value as well.
540
        CsvDelay uint16
541
}
542

543
// ChannelConfig is a struct that houses the various configuration opens for
544
// channels. Each side maintains an instance of this configuration file as it
545
// governs: how the funding and commitment transaction to be created, the
546
// nature of HTLC's allotted, the keys to be used for delivery, and relative
547
// time lock parameters.
548
type ChannelConfig struct {
549
        // ChannelStateBounds is the set of constraints that must be
550
        // upheld for the duration of the channel for the owner of this channel
551
        // configuration. Constraints govern a number of flow control related
552
        // parameters, also including the smallest HTLC that will be accepted
553
        // by a participant.
554
        ChannelStateBounds
555

556
        // CommitmentParams is an embedding of the parameters
557
        // required to render an abstract channel state into a concrete
558
        // commitment transaction.
559
        CommitmentParams
560

561
        // MultiSigKey is the key to be used within the 2-of-2 output script
562
        // for the owner of this channel config.
563
        MultiSigKey keychain.KeyDescriptor
564

565
        // RevocationBasePoint is the base public key to be used when deriving
566
        // revocation keys for the remote node's commitment transaction. This
567
        // will be combined along with a per commitment secret to derive a
568
        // unique revocation key for each state.
569
        RevocationBasePoint keychain.KeyDescriptor
570

571
        // PaymentBasePoint is the base public key to be used when deriving
572
        // the key used within the non-delayed pay-to-self output on the
573
        // commitment transaction for a node. This will be combined with a
574
        // tweak derived from the per-commitment point to ensure unique keys
575
        // for each commitment transaction.
576
        PaymentBasePoint keychain.KeyDescriptor
577

578
        // DelayBasePoint is the base public key to be used when deriving the
579
        // key used within the delayed pay-to-self output on the commitment
580
        // transaction for a node. This will be combined with a tweak derived
581
        // from the per-commitment point to ensure unique keys for each
582
        // commitment transaction.
583
        DelayBasePoint keychain.KeyDescriptor
584

585
        // HtlcBasePoint is the base public key to be used when deriving the
586
        // local HTLC key. The derived key (combined with the tweak derived
587
        // from the per-commitment point) is used within the "to self" clause
588
        // within any HTLC output scripts.
589
        HtlcBasePoint keychain.KeyDescriptor
590
}
591

592
// commitTlvData stores all the optional data that may be stored as a TLV stream
593
// at the _end_ of the normal serialized commit on disk.
594
type commitTlvData struct {
595
        // customBlob is a custom blob that may store extra data for custom
596
        // channels.
597
        customBlob tlv.OptionalRecordT[tlv.TlvType1, tlv.Blob]
598
}
599

600
// encode encodes the aux data into the passed io.Writer.
601
func (c *commitTlvData) encode(w io.Writer) error {
8,441✔
602
        var tlvRecords []tlv.Record
8,441✔
603
        c.customBlob.WhenSome(func(blob tlv.RecordT[tlv.TlvType1, tlv.Blob]) {
9,286✔
604
                tlvRecords = append(tlvRecords, blob.Record())
845✔
605
        })
845✔
606

607
        // Create the tlv stream.
608
        tlvStream, err := tlv.NewStream(tlvRecords...)
8,441✔
609
        if err != nil {
8,441✔
610
                return err
×
611
        }
×
612

613
        return tlvStream.Encode(w)
8,441✔
614
}
615

616
// decode attempts to decode the aux data from the passed io.Reader.
617
func (c *commitTlvData) decode(r io.Reader) error {
16,313✔
618
        blob := c.customBlob.Zero()
16,313✔
619

16,313✔
620
        tlvStream, err := tlv.NewStream(
16,313✔
621
                blob.Record(),
16,313✔
622
        )
16,313✔
623
        if err != nil {
16,313✔
624
                return err
×
625
        }
×
626

627
        tlvs, err := tlvStream.DecodeWithParsedTypes(r)
16,313✔
628
        if err != nil {
16,313✔
629
                return err
×
630
        }
×
631

632
        if _, ok := tlvs[c.customBlob.TlvType()]; ok {
16,971✔
633
                c.customBlob = tlv.SomeRecordT(blob)
658✔
634
        }
658✔
635

636
        return nil
16,313✔
637
}
638

639
// ChannelCommitment is a snapshot of the commitment state at a particular
640
// point in the commitment chain. With each state transition, a snapshot of the
641
// current state along with all non-settled HTLCs are recorded. These snapshots
642
// detail the state of the _remote_ party's commitment at a particular state
643
// number.  For ourselves (the local node) we ONLY store our most recent
644
// (unrevoked) state for safety purposes.
645
type ChannelCommitment struct {
646
        // CommitHeight is the update number that this ChannelDelta represents
647
        // the total number of commitment updates to this point. This can be
648
        // viewed as sort of a "commitment height" as this number is
649
        // monotonically increasing.
650
        CommitHeight uint64
651

652
        // LocalLogIndex is the cumulative log index index of the local node at
653
        // this point in the commitment chain. This value will be incremented
654
        // for each _update_ added to the local update log.
655
        LocalLogIndex uint64
656

657
        // LocalHtlcIndex is the current local running HTLC index. This value
658
        // will be incremented for each outgoing HTLC the local node offers.
659
        LocalHtlcIndex uint64
660

661
        // RemoteLogIndex is the cumulative log index index of the remote node
662
        // at this point in the commitment chain. This value will be
663
        // incremented for each _update_ added to the remote update log.
664
        RemoteLogIndex uint64
665

666
        // RemoteHtlcIndex is the current remote running HTLC index. This value
667
        // will be incremented for each outgoing HTLC the remote node offers.
668
        RemoteHtlcIndex uint64
669

670
        // LocalBalance is the current available settled balance within the
671
        // channel directly spendable by us.
672
        //
673
        // NOTE: This is the balance *after* subtracting any commitment fee,
674
        // AND anchor output values.
675
        LocalBalance lnwire.MilliSatoshi
676

677
        // RemoteBalance is the current available settled balance within the
678
        // channel directly spendable by the remote node.
679
        //
680
        // NOTE: This is the balance *after* subtracting any commitment fee,
681
        // AND anchor output values.
682
        RemoteBalance lnwire.MilliSatoshi
683

684
        // CommitFee is the amount calculated to be paid in fees for the
685
        // current set of commitment transactions. The fee amount is persisted
686
        // with the channel in order to allow the fee amount to be removed and
687
        // recalculated with each channel state update, including updates that
688
        // happen after a system restart.
689
        CommitFee btcutil.Amount
690

691
        // FeePerKw is the min satoshis/kilo-weight that should be paid within
692
        // the commitment transaction for the entire duration of the channel's
693
        // lifetime. This field may be updated during normal operation of the
694
        // channel as on-chain conditions change.
695
        //
696
        // TODO(halseth): make this SatPerKWeight. Cannot be done atm because
697
        // this will cause the import cycle lnwallet<->channeldb. Fee
698
        // estimation stuff should be in its own package.
699
        FeePerKw btcutil.Amount
700

701
        // CommitTx is the latest version of the commitment state, broadcast
702
        // able by us.
703
        CommitTx *wire.MsgTx
704

705
        // CustomBlob is an optional blob that can be used to store information
706
        // specific to a custom channel type. This may track some custom
707
        // specific state for this given commitment.
708
        CustomBlob fn.Option[tlv.Blob]
709

710
        // CommitSig is one half of the signature required to fully complete
711
        // the script for the commitment transaction above. This is the
712
        // signature signed by the remote party for our version of the
713
        // commitment transactions.
714
        CommitSig []byte
715

716
        // Htlcs is the set of HTLC's that are pending at this particular
717
        // commitment height.
718
        Htlcs []HTLC
719
}
720

721
// amendTlvData updates the channel with the given auxiliary TLV data.
722
func (c *ChannelCommitment) amendTlvData(auxData commitTlvData) {
16,313✔
723
        auxData.customBlob.WhenSomeV(func(blob tlv.Blob) {
16,971✔
724
                c.CustomBlob = fn.Some(blob)
658✔
725
        })
658✔
726
}
727

728
// extractTlvData creates a new commitTlvData from the given commitment.
729
func (c *ChannelCommitment) extractTlvData() commitTlvData {
8,441✔
730
        var auxData commitTlvData
8,441✔
731

8,441✔
732
        c.CustomBlob.WhenSome(func(blob tlv.Blob) {
9,286✔
733
                auxData.customBlob = tlv.SomeRecordT(
845✔
734
                        tlv.NewPrimitiveRecord[tlv.TlvType1](blob),
845✔
735
                )
845✔
736
        })
845✔
737

738
        return auxData
8,441✔
739
}
740

741
// ChannelStatus is a bit vector used to indicate whether an OpenChannel is in
742
// the default usable state, or a state where it shouldn't be used.
743
type ChannelStatus uint64
744

745
var (
746
        // ChanStatusDefault is the normal state of an open channel.
747
        ChanStatusDefault ChannelStatus
748

749
        // ChanStatusBorked indicates that the channel has entered an
750
        // irreconcilable state, triggered by a state desynchronization or
751
        // channel breach.  Channels in this state should never be added to the
752
        // htlc switch.
753
        ChanStatusBorked ChannelStatus = 1
754

755
        // ChanStatusCommitBroadcasted indicates that a commitment for this
756
        // channel has been broadcasted.
757
        ChanStatusCommitBroadcasted ChannelStatus = 1 << 1
758

759
        // ChanStatusLocalDataLoss indicates that we have lost channel state
760
        // for this channel, and broadcasting our latest commitment might be
761
        // considered a breach.
762
        //
763
        // TODO(halseh): actually enforce that we are not force closing such a
764
        // channel.
765
        ChanStatusLocalDataLoss ChannelStatus = 1 << 2
766

767
        // ChanStatusRestored is a status flag that signals that the channel
768
        // has been restored, and doesn't have all the fields a typical channel
769
        // will have.
770
        ChanStatusRestored ChannelStatus = 1 << 3
771

772
        // ChanStatusCoopBroadcasted indicates that a cooperative close for
773
        // this channel has been broadcasted. Older cooperatively closed
774
        // channels will only have this status set. Newer ones will also have
775
        // close initiator information stored using the local/remote initiator
776
        // status. This status is set in conjunction with the initiator status
777
        // so that we do not need to check multiple channel statues for
778
        // cooperative closes.
779
        ChanStatusCoopBroadcasted ChannelStatus = 1 << 4
780

781
        // ChanStatusLocalCloseInitiator indicates that we initiated closing
782
        // the channel.
783
        ChanStatusLocalCloseInitiator ChannelStatus = 1 << 5
784

785
        // ChanStatusRemoteCloseInitiator indicates that the remote node
786
        // initiated closing the channel.
787
        ChanStatusRemoteCloseInitiator ChannelStatus = 1 << 6
788
)
789

790
// chanStatusStrings maps a ChannelStatus to a human friendly string that
791
// describes that status.
792
var chanStatusStrings = map[ChannelStatus]string{
793
        ChanStatusDefault:              "ChanStatusDefault",
794
        ChanStatusBorked:               "ChanStatusBorked",
795
        ChanStatusCommitBroadcasted:    "ChanStatusCommitBroadcasted",
796
        ChanStatusLocalDataLoss:        "ChanStatusLocalDataLoss",
797
        ChanStatusRestored:             "ChanStatusRestored",
798
        ChanStatusCoopBroadcasted:      "ChanStatusCoopBroadcasted",
799
        ChanStatusLocalCloseInitiator:  "ChanStatusLocalCloseInitiator",
800
        ChanStatusRemoteCloseInitiator: "ChanStatusRemoteCloseInitiator",
801
}
802

803
// orderedChanStatusFlags is an in-order list of all that channel status flags.
804
var orderedChanStatusFlags = []ChannelStatus{
805
        ChanStatusBorked,
806
        ChanStatusCommitBroadcasted,
807
        ChanStatusLocalDataLoss,
808
        ChanStatusRestored,
809
        ChanStatusCoopBroadcasted,
810
        ChanStatusLocalCloseInitiator,
811
        ChanStatusRemoteCloseInitiator,
812
}
813

814
// String returns a human-readable representation of the ChannelStatus.
815
func (c ChannelStatus) String() string {
1✔
816
        // If no flags are set, then this is the default case.
1✔
817
        if c == ChanStatusDefault {
1✔
818
                return chanStatusStrings[ChanStatusDefault]
×
819
        }
×
820

821
        // Add individual bit flags.
822
        statusStr := ""
1✔
823
        for _, flag := range orderedChanStatusFlags {
8✔
824
                if c&flag == flag {
8✔
825
                        statusStr += chanStatusStrings[flag] + "|"
1✔
826
                        c -= flag
1✔
827
                }
1✔
828
        }
829

830
        // Remove anything to the right of the final bar, including it as well.
831
        statusStr = strings.TrimRight(statusStr, "|")
1✔
832

1✔
833
        // Add any remaining flags which aren't accounted for as hex.
1✔
834
        if c != 0 {
1✔
835
                statusStr += "|0x" + strconv.FormatUint(uint64(c), 16)
×
836
        }
×
837

838
        // If this was purely an unknown flag, then remove the extra bar at the
839
        // start of the string.
840
        statusStr = strings.TrimLeft(statusStr, "|")
1✔
841

1✔
842
        return statusStr
1✔
843
}
844

845
// FinalHtlcByte defines a byte type that encodes information about the final
846
// htlc resolution.
847
type FinalHtlcByte byte
848

849
const (
850
        // FinalHtlcSettledBit is the bit that encodes whether the htlc was
851
        // settled or failed.
852
        FinalHtlcSettledBit FinalHtlcByte = 1 << 0
853

854
        // FinalHtlcOffchainBit is the bit that encodes whether the htlc was
855
        // resolved offchain or onchain.
856
        FinalHtlcOffchainBit FinalHtlcByte = 1 << 1
857
)
858

859
// OpenChannel encapsulates the persistent and dynamic state of an open channel
860
// with a remote node. An open channel supports several options for on-disk
861
// serialization depending on the exact context. Full (upon channel creation)
862
// state commitments, and partial (due to a commitment update) writes are
863
// supported. Each partial write due to a state update appends the new update
864
// to an on-disk log, which can then subsequently be queried in order to
865
// "time-travel" to a prior state.
866
type OpenChannel struct {
867
        // ChanType denotes which type of channel this is.
868
        ChanType ChannelType
869

870
        // ChainHash is a hash which represents the blockchain that this
871
        // channel will be opened within. This value is typically the genesis
872
        // hash. In the case that the original chain went through a contentious
873
        // hard-fork, then this value will be tweaked using the unique fork
874
        // point on each branch.
875
        ChainHash chainhash.Hash
876

877
        // FundingOutpoint is the outpoint of the final funding transaction.
878
        // This value uniquely and globally identifies the channel within the
879
        // target blockchain as specified by the chain hash parameter.
880
        FundingOutpoint wire.OutPoint
881

882
        // ShortChannelID encodes the exact location in the chain in which the
883
        // channel was initially confirmed. This includes: the block height,
884
        // transaction index, and the output within the target transaction.
885
        //
886
        // If IsZeroConf(), then this will the "base" (very first) ALIAS scid
887
        // and the confirmed SCID will be stored in ConfirmedScid.
888
        ShortChannelID lnwire.ShortChannelID
889

890
        // IsPending indicates whether a channel's funding transaction has been
891
        // confirmed.
892
        IsPending bool
893

894
        // IsInitiator is a bool which indicates if we were the original
895
        // initiator for the channel. This value may affect how higher levels
896
        // negotiate fees, or close the channel.
897
        IsInitiator bool
898

899
        // chanStatus is the current status of this channel. If it is not in
900
        // the state Default, it should not be used for forwarding payments.
901
        chanStatus ChannelStatus
902

903
        // FundingBroadcastHeight is the height in which the funding
904
        // transaction was broadcast. This value can be used by higher level
905
        // sub-systems to determine if a channel is stale and/or should have
906
        // been confirmed before a certain height.
907
        FundingBroadcastHeight uint32
908

909
        // NumConfsRequired is the number of confirmations a channel's funding
910
        // transaction must have received in order to be considered available
911
        // for normal transactional use.
912
        NumConfsRequired uint16
913

914
        // ChannelFlags holds the flags that were sent as part of the
915
        // open_channel message.
916
        ChannelFlags lnwire.FundingFlag
917

918
        // IdentityPub is the identity public key of the remote node this
919
        // channel has been established with.
920
        IdentityPub *btcec.PublicKey
921

922
        // Capacity is the total capacity of this channel.
923
        Capacity btcutil.Amount
924

925
        // TotalMSatSent is the total number of milli-satoshis we've sent
926
        // within this channel.
927
        TotalMSatSent lnwire.MilliSatoshi
928

929
        // TotalMSatReceived is the total number of milli-satoshis we've
930
        // received within this channel.
931
        TotalMSatReceived lnwire.MilliSatoshi
932

933
        // InitialLocalBalance is the balance we have during the channel
934
        // opening. When we are not the initiator, this value represents the
935
        // push amount.
936
        InitialLocalBalance lnwire.MilliSatoshi
937

938
        // InitialRemoteBalance is the balance they have during the channel
939
        // opening.
940
        InitialRemoteBalance lnwire.MilliSatoshi
941

942
        // LocalChanCfg is the channel configuration for the local node.
943
        LocalChanCfg ChannelConfig
944

945
        // RemoteChanCfg is the channel configuration for the remote node.
946
        RemoteChanCfg ChannelConfig
947

948
        // LocalCommitment is the current local commitment state for the local
949
        // party. This is stored distinct from the state of the remote party
950
        // as there are certain asymmetric parameters which affect the
951
        // structure of each commitment.
952
        LocalCommitment ChannelCommitment
953

954
        // RemoteCommitment is the current remote commitment state for the
955
        // remote party. This is stored distinct from the state of the local
956
        // party as there are certain asymmetric parameters which affect the
957
        // structure of each commitment.
958
        RemoteCommitment ChannelCommitment
959

960
        // RemoteCurrentRevocation is the current revocation for their
961
        // commitment transaction. However, since this the derived public key,
962
        // we don't yet have the private key so we aren't yet able to verify
963
        // that it's actually in the hash chain.
964
        RemoteCurrentRevocation *btcec.PublicKey
965

966
        // RemoteNextRevocation is the revocation key to be used for the *next*
967
        // commitment transaction we create for the local node. Within the
968
        // specification, this value is referred to as the
969
        // per-commitment-point.
970
        RemoteNextRevocation *btcec.PublicKey
971

972
        // RevocationProducer is used to generate the revocation in such a way
973
        // that remote side might store it efficiently and have the ability to
974
        // restore the revocation by index if needed. Current implementation of
975
        // secret producer is shachain producer.
976
        RevocationProducer shachain.Producer
977

978
        // RevocationStore is used to efficiently store the revocations for
979
        // previous channels states sent to us by remote side. Current
980
        // implementation of secret store is shachain store.
981
        RevocationStore shachain.Store
982

983
        // Packager is used to create and update forwarding packages for this
984
        // channel, which encodes all necessary information to recover from
985
        // failures and reforward HTLCs that were not fully processed.
986
        Packager FwdPackager
987

988
        // FundingTxn is the transaction containing this channel's funding
989
        // outpoint. Upon restarts, this txn will be rebroadcast if the channel
990
        // is found to be pending.
991
        //
992
        // NOTE: This value will only be populated for single-funder channels
993
        // for which we are the initiator, and that we also have the funding
994
        // transaction for. One can check this by using the HasFundingTx()
995
        // method on the ChanType field.
996
        FundingTxn *wire.MsgTx
997

998
        // LocalShutdownScript is set to a pre-set script if the channel was opened
999
        // by the local node with option_upfront_shutdown_script set. If the option
1000
        // was not set, the field is empty.
1001
        LocalShutdownScript lnwire.DeliveryAddress
1002

1003
        // RemoteShutdownScript is set to a pre-set script if the channel was opened
1004
        // by the remote node with option_upfront_shutdown_script set. If the option
1005
        // was not set, the field is empty.
1006
        RemoteShutdownScript lnwire.DeliveryAddress
1007

1008
        // ThawHeight is the height when a frozen channel once again becomes a
1009
        // normal channel. If this is zero, then there're no restrictions on
1010
        // this channel. If the value is lower than 500,000, then it's
1011
        // interpreted as a relative height, or an absolute height otherwise.
1012
        ThawHeight uint32
1013

1014
        // LastWasRevoke is a boolean that determines if the last update we sent
1015
        // was a revocation (true) or a commitment signature (false).
1016
        LastWasRevoke bool
1017

1018
        // RevocationKeyLocator stores the KeyLocator information that we will
1019
        // need to derive the shachain root for this channel. This allows us to
1020
        // have private key isolation from lnd.
1021
        RevocationKeyLocator keychain.KeyLocator
1022

1023
        // confirmedScid is the confirmed ShortChannelID for a zero-conf
1024
        // channel. If the channel is unconfirmed, then this will be the
1025
        // default ShortChannelID. This is only set for zero-conf channels.
1026
        confirmedScid lnwire.ShortChannelID
1027

1028
        // Memo is any arbitrary information we wish to store locally about the
1029
        // channel that will be useful to our future selves.
1030
        Memo []byte
1031

1032
        // TapscriptRoot is an optional tapscript root used to derive the MuSig2
1033
        // funding output.
1034
        TapscriptRoot fn.Option[chainhash.Hash]
1035

1036
        // CustomBlob is an optional blob that can be used to store information
1037
        // specific to a custom channel type. This information is only created
1038
        // at channel funding time, and after wards is to be considered
1039
        // immutable.
1040
        CustomBlob fn.Option[tlv.Blob]
1041

1042
        // TODO(roasbeef): eww
1043
        Db *ChannelStateDB
1044

1045
        // TODO(roasbeef): just need to store local and remote HTLC's?
1046

1047
        sync.RWMutex
1048
}
1049

1050
// String returns a string representation of the channel.
1051
func (c *OpenChannel) String() string {
×
1052
        indexStr := "height=%v, local_htlc_index=%v, local_log_index=%v, " +
×
1053
                "remote_htlc_index=%v, remote_log_index=%v"
×
1054

×
1055
        commit := c.LocalCommitment
×
1056
        local := fmt.Sprintf(indexStr, commit.CommitHeight,
×
1057
                commit.LocalHtlcIndex, commit.LocalLogIndex,
×
1058
                commit.RemoteHtlcIndex, commit.RemoteLogIndex,
×
1059
        )
×
1060

×
1061
        commit = c.RemoteCommitment
×
1062
        remote := fmt.Sprintf(indexStr, commit.CommitHeight,
×
1063
                commit.LocalHtlcIndex, commit.LocalLogIndex,
×
1064
                commit.RemoteHtlcIndex, commit.RemoteLogIndex,
×
1065
        )
×
1066

×
1067
        return fmt.Sprintf("SCID=%v, status=%v, initiator=%v, pending=%v, "+
×
1068
                "local commitment has %s, remote commitment has %s",
×
1069
                c.ShortChannelID, c.chanStatus, c.IsInitiator, c.IsPending,
×
1070
                local, remote,
×
1071
        )
×
1072
}
×
1073

1074
// Initiator returns the ChannelParty that originally opened this channel.
1075
func (c *OpenChannel) Initiator() lntypes.ChannelParty {
15,468✔
1076
        c.RLock()
15,468✔
1077
        defer c.RUnlock()
15,468✔
1078

15,468✔
1079
        if c.IsInitiator {
25,040✔
1080
                return lntypes.Local
9,572✔
1081
        }
9,572✔
1082

1083
        return lntypes.Remote
5,896✔
1084
}
1085

1086
// ShortChanID returns the current ShortChannelID of this channel.
1087
func (c *OpenChannel) ShortChanID() lnwire.ShortChannelID {
8,230✔
1088
        c.RLock()
8,230✔
1089
        defer c.RUnlock()
8,230✔
1090

8,230✔
1091
        return c.ShortChannelID
8,230✔
1092
}
8,230✔
1093

1094
// ZeroConfRealScid returns the zero-conf channel's confirmed scid. This should
1095
// only be called if IsZeroConf returns true.
1096
func (c *OpenChannel) ZeroConfRealScid() lnwire.ShortChannelID {
9✔
1097
        c.RLock()
9✔
1098
        defer c.RUnlock()
9✔
1099

9✔
1100
        return c.confirmedScid
9✔
1101
}
9✔
1102

1103
// ZeroConfConfirmed returns whether the zero-conf channel has confirmed. This
1104
// should only be called if IsZeroConf returns true.
1105
func (c *OpenChannel) ZeroConfConfirmed() bool {
41✔
1106
        c.RLock()
41✔
1107
        defer c.RUnlock()
41✔
1108

41✔
1109
        return c.confirmedScid != hop.Source
41✔
1110
}
41✔
1111

1112
// IsZeroConf returns whether the option_zeroconf channel type was negotiated.
1113
func (c *OpenChannel) IsZeroConf() bool {
645✔
1114
        c.RLock()
645✔
1115
        defer c.RUnlock()
645✔
1116

645✔
1117
        return c.ChanType.HasZeroConf()
645✔
1118
}
645✔
1119

1120
// IsOptionScidAlias returns whether the option_scid_alias channel type was
1121
// negotiated.
1122
func (c *OpenChannel) IsOptionScidAlias() bool {
×
1123
        c.RLock()
×
1124
        defer c.RUnlock()
×
1125

×
1126
        return c.ChanType.HasScidAliasChan()
×
1127
}
×
1128

1129
// NegotiatedAliasFeature returns whether the option-scid-alias feature bit was
1130
// negotiated.
1131
func (c *OpenChannel) NegotiatedAliasFeature() bool {
482✔
1132
        c.RLock()
482✔
1133
        defer c.RUnlock()
482✔
1134

482✔
1135
        return c.ChanType.HasScidAliasFeature()
482✔
1136
}
482✔
1137

1138
// ChanStatus returns the current ChannelStatus of this channel.
1139
func (c *OpenChannel) ChanStatus() ChannelStatus {
211✔
1140
        c.RLock()
211✔
1141
        defer c.RUnlock()
211✔
1142

211✔
1143
        return c.chanStatus
211✔
1144
}
211✔
1145

1146
// ApplyChanStatus allows the caller to modify the internal channel state in a
1147
// thead-safe manner.
1148
func (c *OpenChannel) ApplyChanStatus(status ChannelStatus) error {
3✔
1149
        c.Lock()
3✔
1150
        defer c.Unlock()
3✔
1151

3✔
1152
        return c.putChanStatus(status)
3✔
1153
}
3✔
1154

1155
// ClearChanStatus allows the caller to clear a particular channel status from
1156
// the primary channel status bit field. After this method returns, a call to
1157
// HasChanStatus(status) should return false.
1158
func (c *OpenChannel) ClearChanStatus(status ChannelStatus) error {
4✔
1159
        c.Lock()
4✔
1160
        defer c.Unlock()
4✔
1161

4✔
1162
        return c.clearChanStatus(status)
4✔
1163
}
4✔
1164

1165
// HasChanStatus returns true if the internal bitfield channel status of the
1166
// target channel has the specified status bit set.
1167
func (c *OpenChannel) HasChanStatus(status ChannelStatus) bool {
373✔
1168
        c.RLock()
373✔
1169
        defer c.RUnlock()
373✔
1170

373✔
1171
        return c.hasChanStatus(status)
373✔
1172
}
373✔
1173

1174
func (c *OpenChannel) hasChanStatus(status ChannelStatus) bool {
20,656✔
1175
        // Special case ChanStatusDefualt since it isn't actually flag, but a
20,656✔
1176
        // particular combination (or lack-there-of) of flags.
20,656✔
1177
        if status == ChanStatusDefault {
20,661✔
1178
                return c.chanStatus == ChanStatusDefault
5✔
1179
        }
5✔
1180

1181
        return c.chanStatus&status == status
20,651✔
1182
}
1183

1184
// BroadcastHeight returns the height at which the funding tx was broadcast.
1185
func (c *OpenChannel) BroadcastHeight() uint32 {
139✔
1186
        c.RLock()
139✔
1187
        defer c.RUnlock()
139✔
1188

139✔
1189
        return c.FundingBroadcastHeight
139✔
1190
}
139✔
1191

1192
// SetBroadcastHeight sets the FundingBroadcastHeight.
1193
func (c *OpenChannel) SetBroadcastHeight(height uint32) {
×
1194
        c.Lock()
×
1195
        defer c.Unlock()
×
1196

×
1197
        c.FundingBroadcastHeight = height
×
1198
}
×
1199

1200
// amendTlvData updates the channel with the given auxiliary TLV data.
1201
func (c *OpenChannel) amendTlvData(auxData openChannelTlvData) {
7,125✔
1202
        c.RevocationKeyLocator = auxData.revokeKeyLoc.Val.KeyLocator
7,125✔
1203
        c.InitialLocalBalance = lnwire.MilliSatoshi(
7,125✔
1204
                auxData.initialLocalBalance.Val,
7,125✔
1205
        )
7,125✔
1206
        c.InitialRemoteBalance = lnwire.MilliSatoshi(
7,125✔
1207
                auxData.initialRemoteBalance.Val,
7,125✔
1208
        )
7,125✔
1209
        c.confirmedScid = auxData.realScid.Val
7,125✔
1210

7,125✔
1211
        auxData.memo.WhenSomeV(func(memo []byte) {
7,452✔
1212
                c.Memo = memo
327✔
1213
        })
327✔
1214
        auxData.tapscriptRoot.WhenSomeV(func(h [32]byte) {
7,560✔
1215
                c.TapscriptRoot = fn.Some[chainhash.Hash](h)
435✔
1216
        })
435✔
1217
        auxData.customBlob.WhenSomeV(func(blob tlv.Blob) {
7,452✔
1218
                c.CustomBlob = fn.Some(blob)
327✔
1219
        })
327✔
1220
}
1221

1222
// extractTlvData creates a new openChannelTlvData from the given channel.
1223
func (c *OpenChannel) extractTlvData() openChannelTlvData {
3,221✔
1224
        auxData := openChannelTlvData{
3,221✔
1225
                revokeKeyLoc: tlv.NewRecordT[tlv.TlvType1](
3,221✔
1226
                        keyLocRecord{c.RevocationKeyLocator},
3,221✔
1227
                ),
3,221✔
1228
                initialLocalBalance: tlv.NewPrimitiveRecord[tlv.TlvType2](
3,221✔
1229
                        uint64(c.InitialLocalBalance),
3,221✔
1230
                ),
3,221✔
1231
                initialRemoteBalance: tlv.NewPrimitiveRecord[tlv.TlvType3](
3,221✔
1232
                        uint64(c.InitialRemoteBalance),
3,221✔
1233
                ),
3,221✔
1234
                realScid: tlv.NewRecordT[tlv.TlvType4](
3,221✔
1235
                        c.confirmedScid,
3,221✔
1236
                ),
3,221✔
1237
        }
3,221✔
1238

3,221✔
1239
        if len(c.Memo) != 0 {
3,642✔
1240
                auxData.memo = tlv.SomeRecordT(
421✔
1241
                        tlv.NewPrimitiveRecord[tlv.TlvType5](c.Memo),
421✔
1242
                )
421✔
1243
        }
421✔
1244
        c.TapscriptRoot.WhenSome(func(h chainhash.Hash) {
3,694✔
1245
                auxData.tapscriptRoot = tlv.SomeRecordT(
473✔
1246
                        tlv.NewPrimitiveRecord[tlv.TlvType6, [32]byte](h),
473✔
1247
                )
473✔
1248
        })
473✔
1249
        c.CustomBlob.WhenSome(func(blob tlv.Blob) {
3,642✔
1250
                auxData.customBlob = tlv.SomeRecordT(
421✔
1251
                        tlv.NewPrimitiveRecord[tlv.TlvType7](blob),
421✔
1252
                )
421✔
1253
        })
421✔
1254

1255
        return auxData
3,221✔
1256
}
1257

1258
// Refresh updates the in-memory channel state using the latest state observed
1259
// on disk.
1260
func (c *OpenChannel) Refresh() error {
5✔
1261
        c.Lock()
5✔
1262
        defer c.Unlock()
5✔
1263

5✔
1264
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
10✔
1265
                chanBucket, err := fetchChanBucket(
5✔
1266
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
5✔
1267
                )
5✔
1268
                if err != nil {
5✔
1269
                        return err
×
1270
                }
×
1271

1272
                // We'll re-populating the in-memory channel with the info
1273
                // fetched from disk.
1274
                if err := fetchChanInfo(chanBucket, c); err != nil {
5✔
1275
                        return fmt.Errorf("unable to fetch chan info: %w", err)
×
1276
                }
×
1277

1278
                // Also populate the channel's commitment states for both sides
1279
                // of the channel.
1280
                if err := fetchChanCommitments(chanBucket, c); err != nil {
5✔
1281
                        return fmt.Errorf("unable to fetch chan commitments: "+
×
1282
                                "%v", err)
×
1283
                }
×
1284

1285
                // Also retrieve the current revocation state.
1286
                if err := fetchChanRevocationState(chanBucket, c); err != nil {
5✔
1287
                        return fmt.Errorf("unable to fetch chan revocations: "+
×
1288
                                "%v", err)
×
1289
                }
×
1290

1291
                return nil
5✔
1292
        }, func() {})
5✔
1293
        if err != nil {
5✔
1294
                return err
×
1295
        }
×
1296

1297
        return nil
5✔
1298
}
1299

1300
// fetchChanBucket is a helper function that returns the bucket where a
1301
// channel's data resides in given: the public key for the node, the outpoint,
1302
// and the chainhash that the channel resides on.
1303
func fetchChanBucket(tx kvdb.RTx, nodeKey *btcec.PublicKey,
1304
        outPoint *wire.OutPoint, chainHash chainhash.Hash) (kvdb.RBucket, error) {
2,953✔
1305

2,953✔
1306
        // First fetch the top level bucket which stores all data related to
2,953✔
1307
        // current, active channels.
2,953✔
1308
        openChanBucket := tx.ReadBucket(openChannelBucket)
2,953✔
1309
        if openChanBucket == nil {
2,953✔
1310
                return nil, ErrNoChanDBExists
×
1311
        }
×
1312

1313
        // TODO(roasbeef): CreateTopLevelBucket on the interface isn't like
1314
        // CreateIfNotExists, will return error
1315

1316
        // Within this top level bucket, fetch the bucket dedicated to storing
1317
        // open channel data specific to the remote node.
1318
        nodePub := nodeKey.SerializeCompressed()
2,953✔
1319
        nodeChanBucket := openChanBucket.NestedReadBucket(nodePub)
2,953✔
1320
        if nodeChanBucket == nil {
4,075✔
1321
                return nil, ErrNoActiveChannels
1,122✔
1322
        }
1,122✔
1323

1324
        // We'll then recurse down an additional layer in order to fetch the
1325
        // bucket for this particular chain.
1326
        chainBucket := nodeChanBucket.NestedReadBucket(chainHash[:])
1,831✔
1327
        if chainBucket == nil {
1,831✔
1328
                return nil, ErrNoActiveChannels
×
1329
        }
×
1330

1331
        // With the bucket for the node and chain fetched, we can now go down
1332
        // another level, for this channel itself.
1333
        var chanPointBuf bytes.Buffer
1,831✔
1334
        if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
1,831✔
1335
                return nil, err
×
1336
        }
×
1337
        chanBucket := chainBucket.NestedReadBucket(chanPointBuf.Bytes())
1,831✔
1338
        if chanBucket == nil {
1,832✔
1339
                return nil, ErrChannelNotFound
1✔
1340
        }
1✔
1341

1342
        return chanBucket, nil
1,830✔
1343
}
1344

1345
// fetchChanBucketRw is a helper function that returns the bucket where a
1346
// channel's data resides in given: the public key for the node, the outpoint,
1347
// and the chainhash that the channel resides on. This differs from
1348
// fetchChanBucket in that it returns a writeable bucket.
1349
func fetchChanBucketRw(tx kvdb.RwTx, nodeKey *btcec.PublicKey,
1350
        outPoint *wire.OutPoint, chainHash chainhash.Hash) (kvdb.RwBucket,
1351
        error) {
6,864✔
1352

6,864✔
1353
        // First fetch the top level bucket which stores all data related to
6,864✔
1354
        // current, active channels.
6,864✔
1355
        openChanBucket := tx.ReadWriteBucket(openChannelBucket)
6,864✔
1356
        if openChanBucket == nil {
6,864✔
1357
                return nil, ErrNoChanDBExists
×
1358
        }
×
1359

1360
        // TODO(roasbeef): CreateTopLevelBucket on the interface isn't like
1361
        // CreateIfNotExists, will return error
1362

1363
        // Within this top level bucket, fetch the bucket dedicated to storing
1364
        // open channel data specific to the remote node.
1365
        nodePub := nodeKey.SerializeCompressed()
6,864✔
1366
        nodeChanBucket := openChanBucket.NestedReadWriteBucket(nodePub)
6,864✔
1367
        if nodeChanBucket == nil {
6,864✔
1368
                return nil, ErrNoActiveChannels
×
1369
        }
×
1370

1371
        // We'll then recurse down an additional layer in order to fetch the
1372
        // bucket for this particular chain.
1373
        chainBucket := nodeChanBucket.NestedReadWriteBucket(chainHash[:])
6,864✔
1374
        if chainBucket == nil {
6,864✔
1375
                return nil, ErrNoActiveChannels
×
1376
        }
×
1377

1378
        // With the bucket for the node and chain fetched, we can now go down
1379
        // another level, for this channel itself.
1380
        var chanPointBuf bytes.Buffer
6,864✔
1381
        if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
6,864✔
1382
                return nil, err
×
1383
        }
×
1384
        chanBucket := chainBucket.NestedReadWriteBucket(chanPointBuf.Bytes())
6,864✔
1385
        if chanBucket == nil {
6,864✔
1386
                return nil, ErrChannelNotFound
×
1387
        }
×
1388

1389
        return chanBucket, nil
6,864✔
1390
}
1391

1392
func fetchFinalHtlcsBucketRw(tx kvdb.RwTx,
1393
        chanID lnwire.ShortChannelID) (kvdb.RwBucket, error) {
3✔
1394

3✔
1395
        finalHtlcsBucket, err := tx.CreateTopLevelBucket(finalHtlcsBucket)
3✔
1396
        if err != nil {
3✔
1397
                return nil, err
×
1398
        }
×
1399

1400
        var chanIDBytes [8]byte
3✔
1401
        byteOrder.PutUint64(chanIDBytes[:], chanID.ToUint64())
3✔
1402
        chanBucket, err := finalHtlcsBucket.CreateBucketIfNotExists(
3✔
1403
                chanIDBytes[:],
3✔
1404
        )
3✔
1405
        if err != nil {
3✔
1406
                return nil, err
×
1407
        }
×
1408

1409
        return chanBucket, nil
3✔
1410
}
1411

1412
// fullSync syncs the contents of an OpenChannel while re-using an existing
1413
// database transaction.
1414
func (c *OpenChannel) fullSync(tx kvdb.RwTx) error {
881✔
1415
        // Fetch the outpoint bucket and check if the outpoint already exists.
881✔
1416
        opBucket := tx.ReadWriteBucket(outpointBucket)
881✔
1417
        if opBucket == nil {
881✔
1418
                return ErrNoChanDBExists
×
1419
        }
×
1420
        cidBucket := tx.ReadWriteBucket(chanIDBucket)
881✔
1421
        if cidBucket == nil {
881✔
1422
                return ErrNoChanDBExists
×
1423
        }
×
1424

1425
        var chanPointBuf bytes.Buffer
881✔
1426
        err := graphdb.WriteOutpoint(&chanPointBuf, &c.FundingOutpoint)
881✔
1427
        if err != nil {
881✔
1428
                return err
×
1429
        }
×
1430

1431
        // Now, check if the outpoint exists in our index.
1432
        if opBucket.Get(chanPointBuf.Bytes()) != nil {
881✔
1433
                return ErrChanAlreadyExists
×
1434
        }
×
1435

1436
        cid := lnwire.NewChanIDFromOutPoint(c.FundingOutpoint)
881✔
1437
        if cidBucket.Get(cid[:]) != nil {
881✔
1438
                return ErrChanAlreadyExists
×
1439
        }
×
1440

1441
        status := uint8(outpointOpen)
881✔
1442

881✔
1443
        // Write the status of this outpoint as the first entry in a tlv
881✔
1444
        // stream.
881✔
1445
        statusRecord := tlv.MakePrimitiveRecord(indexStatusType, &status)
881✔
1446
        opStream, err := tlv.NewStream(statusRecord)
881✔
1447
        if err != nil {
881✔
1448
                return err
×
1449
        }
×
1450

1451
        var b bytes.Buffer
881✔
1452
        if err := opStream.Encode(&b); err != nil {
881✔
1453
                return err
×
1454
        }
×
1455

1456
        // Add the outpoint to our outpoint index with the tlv stream.
1457
        if err := opBucket.Put(chanPointBuf.Bytes(), b.Bytes()); err != nil {
881✔
1458
                return err
×
1459
        }
×
1460

1461
        if err := cidBucket.Put(cid[:], []byte{}); err != nil {
881✔
1462
                return err
×
1463
        }
×
1464

1465
        // First fetch the top level bucket which stores all data related to
1466
        // current, active channels.
1467
        openChanBucket, err := tx.CreateTopLevelBucket(openChannelBucket)
881✔
1468
        if err != nil {
881✔
1469
                return err
×
1470
        }
×
1471

1472
        // Within this top level bucket, fetch the bucket dedicated to storing
1473
        // open channel data specific to the remote node.
1474
        nodePub := c.IdentityPub.SerializeCompressed()
881✔
1475
        nodeChanBucket, err := openChanBucket.CreateBucketIfNotExists(nodePub)
881✔
1476
        if err != nil {
881✔
1477
                return err
×
1478
        }
×
1479

1480
        // We'll then recurse down an additional layer in order to fetch the
1481
        // bucket for this particular chain.
1482
        chainBucket, err := nodeChanBucket.CreateBucketIfNotExists(c.ChainHash[:])
881✔
1483
        if err != nil {
881✔
1484
                return err
×
1485
        }
×
1486

1487
        // With the bucket for the node fetched, we can now go down another
1488
        // level, creating the bucket for this channel itself.
1489
        chanBucket, err := chainBucket.CreateBucket(
881✔
1490
                chanPointBuf.Bytes(),
881✔
1491
        )
881✔
1492
        switch {
881✔
1493
        case err == kvdb.ErrBucketExists:
×
1494
                // If this channel already exists, then in order to avoid
×
1495
                // overriding it, we'll return an error back up to the caller.
×
1496
                return ErrChanAlreadyExists
×
1497
        case err != nil:
×
1498
                return err
×
1499
        }
1500

1501
        return putOpenChannel(chanBucket, c)
881✔
1502
}
1503

1504
// MarkAsOpen marks a channel as fully open given a locator that uniquely
1505
// describes its location within the chain.
1506
func (c *OpenChannel) MarkAsOpen(openLoc lnwire.ShortChannelID) error {
163✔
1507
        c.Lock()
163✔
1508
        defer c.Unlock()
163✔
1509

163✔
1510
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
326✔
1511
                chanBucket, err := fetchChanBucketRw(
163✔
1512
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
163✔
1513
                )
163✔
1514
                if err != nil {
163✔
1515
                        return err
×
1516
                }
×
1517

1518
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
163✔
1519
                if err != nil {
163✔
1520
                        return err
×
1521
                }
×
1522

1523
                channel.IsPending = false
163✔
1524
                channel.ShortChannelID = openLoc
163✔
1525

163✔
1526
                return putOpenChannel(chanBucket, channel)
163✔
1527
        }, func() {}); err != nil {
163✔
1528
                return err
×
1529
        }
×
1530

1531
        c.IsPending = false
163✔
1532
        c.ShortChannelID = openLoc
163✔
1533
        c.Packager = NewChannelPackager(openLoc)
163✔
1534

163✔
1535
        return nil
163✔
1536
}
1537

1538
// MarkRealScid marks the zero-conf channel's confirmed ShortChannelID. This
1539
// should only be done if IsZeroConf returns true.
1540
func (c *OpenChannel) MarkRealScid(realScid lnwire.ShortChannelID) error {
7✔
1541
        c.Lock()
7✔
1542
        defer c.Unlock()
7✔
1543

7✔
1544
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
14✔
1545
                chanBucket, err := fetchChanBucketRw(
7✔
1546
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
7✔
1547
                )
7✔
1548
                if err != nil {
7✔
1549
                        return err
×
1550
                }
×
1551

1552
                channel, err := fetchOpenChannel(
7✔
1553
                        chanBucket, &c.FundingOutpoint,
7✔
1554
                )
7✔
1555
                if err != nil {
7✔
1556
                        return err
×
1557
                }
×
1558

1559
                channel.confirmedScid = realScid
7✔
1560

7✔
1561
                return putOpenChannel(chanBucket, channel)
7✔
1562
        }, func() {}); err != nil {
7✔
1563
                return err
×
1564
        }
×
1565

1566
        c.confirmedScid = realScid
7✔
1567

7✔
1568
        return nil
7✔
1569
}
1570

1571
// MarkScidAliasNegotiated adds ScidAliasFeatureBit to ChanType in-memory and
1572
// in the database.
1573
func (c *OpenChannel) MarkScidAliasNegotiated() error {
×
1574
        c.Lock()
×
1575
        defer c.Unlock()
×
1576

×
1577
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
1578
                chanBucket, err := fetchChanBucketRw(
×
1579
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
×
1580
                )
×
1581
                if err != nil {
×
1582
                        return err
×
1583
                }
×
1584

1585
                channel, err := fetchOpenChannel(
×
1586
                        chanBucket, &c.FundingOutpoint,
×
1587
                )
×
1588
                if err != nil {
×
1589
                        return err
×
1590
                }
×
1591

1592
                channel.ChanType |= ScidAliasFeatureBit
×
1593
                return putOpenChannel(chanBucket, channel)
×
1594
        }, func() {}); err != nil {
×
1595
                return err
×
1596
        }
×
1597

1598
        c.ChanType |= ScidAliasFeatureBit
×
1599

×
1600
        return nil
×
1601
}
1602

1603
// MarkDataLoss marks sets the channel status to LocalDataLoss and stores the
1604
// passed commitPoint for use to retrieve funds in case the remote force closes
1605
// the channel.
1606
func (c *OpenChannel) MarkDataLoss(commitPoint *btcec.PublicKey) error {
4✔
1607
        c.Lock()
4✔
1608
        defer c.Unlock()
4✔
1609

4✔
1610
        var b bytes.Buffer
4✔
1611
        if err := WriteElement(&b, commitPoint); err != nil {
4✔
1612
                return err
×
1613
        }
×
1614

1615
        putCommitPoint := func(chanBucket kvdb.RwBucket) error {
8✔
1616
                return chanBucket.Put(dataLossCommitPointKey, b.Bytes())
4✔
1617
        }
4✔
1618

1619
        return c.putChanStatus(ChanStatusLocalDataLoss, putCommitPoint)
4✔
1620
}
1621

1622
// DataLossCommitPoint retrieves the stored commit point set during
1623
// MarkDataLoss. If not found ErrNoCommitPoint is returned.
1624
func (c *OpenChannel) DataLossCommitPoint() (*btcec.PublicKey, error) {
4✔
1625
        var commitPoint *btcec.PublicKey
4✔
1626

4✔
1627
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
8✔
1628
                chanBucket, err := fetchChanBucket(
4✔
1629
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
4✔
1630
                )
4✔
1631
                switch err {
4✔
1632
                case nil:
4✔
1633
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
×
1634
                        return ErrNoCommitPoint
×
1635
                default:
×
1636
                        return err
×
1637
                }
1638

1639
                bs := chanBucket.Get(dataLossCommitPointKey)
4✔
1640
                if bs == nil {
4✔
1641
                        return ErrNoCommitPoint
×
1642
                }
×
1643
                r := bytes.NewReader(bs)
4✔
1644
                if err := ReadElements(r, &commitPoint); err != nil {
4✔
1645
                        return err
×
1646
                }
×
1647

1648
                return nil
4✔
1649
        }, func() {
4✔
1650
                commitPoint = nil
4✔
1651
        })
4✔
1652
        if err != nil {
4✔
1653
                return nil, err
×
1654
        }
×
1655

1656
        return commitPoint, nil
4✔
1657
}
1658

1659
// MarkBorked marks the event when the channel as reached an irreconcilable
1660
// state, such as a channel breach or state desynchronization. Borked channels
1661
// should never be added to the switch.
1662
func (c *OpenChannel) MarkBorked() error {
2✔
1663
        c.Lock()
2✔
1664
        defer c.Unlock()
2✔
1665

2✔
1666
        return c.putChanStatus(ChanStatusBorked)
2✔
1667
}
2✔
1668

1669
// SecondCommitmentPoint returns the second per-commitment-point for use in the
1670
// channel_ready message.
1671
func (c *OpenChannel) SecondCommitmentPoint() (*btcec.PublicKey, error) {
×
1672
        c.RLock()
×
1673
        defer c.RUnlock()
×
1674

×
1675
        // Since we start at commitment height = 0, the second per commitment
×
1676
        // point is actually at the 1st index.
×
1677
        revocation, err := c.RevocationProducer.AtIndex(1)
×
1678
        if err != nil {
×
1679
                return nil, err
×
1680
        }
×
1681

1682
        return input.ComputeCommitmentPoint(revocation[:]), nil
×
1683
}
1684

1685
var (
1686
        // taprootRevRootKey is the key used to derive the revocation root for
1687
        // the taproot nonces. This is done via HMAC of the existing revocation
1688
        // root.
1689
        taprootRevRootKey = []byte("taproot-rev-root")
1690
)
1691

1692
// DeriveMusig2Shachain derives a shachain producer for the taproot channel
1693
// from normal shachain revocation root.
1694
func DeriveMusig2Shachain(revRoot shachain.Producer) (shachain.Producer, error) { //nolint:ll
980✔
1695
        // In order to obtain the revocation root hash to create the taproot
980✔
1696
        // revocation, we'll encode the producer into a buffer, then use that
980✔
1697
        // to derive the shachain root needed.
980✔
1698
        var rootHashBuf bytes.Buffer
980✔
1699
        if err := revRoot.Encode(&rootHashBuf); err != nil {
980✔
1700
                return nil, fmt.Errorf("unable to encode producer: %w", err)
×
1701
        }
×
1702

1703
        revRootHash := chainhash.HashH(rootHashBuf.Bytes())
980✔
1704

980✔
1705
        // For taproot channel types, we'll also generate a distinct shachain
980✔
1706
        // root using the same seed information. We'll use this to generate
980✔
1707
        // verification nonces for the channel. We'll bind with this a simple
980✔
1708
        // hmac.
980✔
1709
        taprootRevHmac := hmac.New(sha256.New, taprootRevRootKey)
980✔
1710
        if _, err := taprootRevHmac.Write(revRootHash[:]); err != nil {
980✔
1711
                return nil, err
×
1712
        }
×
1713

1714
        taprootRevRoot := taprootRevHmac.Sum(nil)
980✔
1715

980✔
1716
        // Once we have the root, we can then generate our shachain producer
980✔
1717
        // and from that generate the per-commitment point.
980✔
1718
        return shachain.NewRevocationProducerFromBytes(
980✔
1719
                taprootRevRoot,
980✔
1720
        )
980✔
1721
}
1722

1723
// NewMusigVerificationNonce generates the local or verification nonce for
1724
// another musig2 session. In order to permit our implementation to not have to
1725
// write any secret nonce state to disk, we'll use the _next_ shachain
1726
// pre-image as our primary randomness source. When used to generate the nonce
1727
// again to broadcast our commitment hte current height will be used.
1728
func NewMusigVerificationNonce(pubKey *btcec.PublicKey, targetHeight uint64,
1729
        shaGen shachain.Producer) (*musig2.Nonces, error) {
215✔
1730

215✔
1731
        // Now that we know what height we need, we'll grab the shachain
215✔
1732
        // pre-image at the target destination.
215✔
1733
        nextPreimage, err := shaGen.AtIndex(targetHeight)
215✔
1734
        if err != nil {
215✔
1735
                return nil, err
×
1736
        }
×
1737

1738
        shaChainRand := musig2.WithCustomRand(bytes.NewBuffer(nextPreimage[:]))
215✔
1739
        pubKeyOpt := musig2.WithPublicKey(pubKey)
215✔
1740

215✔
1741
        return musig2.GenNonces(pubKeyOpt, shaChainRand)
215✔
1742
}
1743

1744
// ChanSyncMsg returns the ChannelReestablish message that should be sent upon
1745
// reconnection with the remote peer that we're maintaining this channel with.
1746
// The information contained within this message is necessary to re-sync our
1747
// commitment chains in the case of a last or only partially processed message.
1748
// When the remote party receives this message one of three things may happen:
1749
//
1750
//  1. We're fully synced and no messages need to be sent.
1751
//  2. We didn't get the last CommitSig message they sent, so they'll re-send
1752
//     it.
1753
//  3. We didn't get the last RevokeAndAck message they sent, so they'll
1754
//     re-send it.
1755
//
1756
// If this is a restored channel, having status ChanStatusRestored, then we'll
1757
// modify our typical chan sync message to ensure they force close even if
1758
// we're on the very first state.
1759
func (c *OpenChannel) ChanSyncMsg() (*lnwire.ChannelReestablish, error) {
254✔
1760
        c.Lock()
254✔
1761
        defer c.Unlock()
254✔
1762

254✔
1763
        // The remote commitment height that we'll send in the
254✔
1764
        // ChannelReestablish message is our current commitment height plus
254✔
1765
        // one. If the receiver thinks that our commitment height is actually
254✔
1766
        // *equal* to this value, then they'll re-send the last commitment that
254✔
1767
        // they sent but we never fully processed.
254✔
1768
        localHeight := c.LocalCommitment.CommitHeight
254✔
1769
        nextLocalCommitHeight := localHeight + 1
254✔
1770

254✔
1771
        // The second value we'll send is the height of the remote commitment
254✔
1772
        // from our PoV. If the receiver thinks that their height is actually
254✔
1773
        // *one plus* this value, then they'll re-send their last revocation.
254✔
1774
        remoteChainTipHeight := c.RemoteCommitment.CommitHeight
254✔
1775

254✔
1776
        // If this channel has undergone a commitment update, then in order to
254✔
1777
        // prove to the remote party our knowledge of their prior commitment
254✔
1778
        // state, we'll also send over the last commitment secret that the
254✔
1779
        // remote party sent.
254✔
1780
        var lastCommitSecret [32]byte
254✔
1781
        if remoteChainTipHeight != 0 {
322✔
1782
                remoteSecret, err := c.RevocationStore.LookUp(
68✔
1783
                        remoteChainTipHeight - 1,
68✔
1784
                )
68✔
1785
                if err != nil {
68✔
1786
                        return nil, err
×
1787
                }
×
1788
                lastCommitSecret = [32]byte(*remoteSecret)
68✔
1789
        }
1790

1791
        // Additionally, we'll send over the current unrevoked commitment on
1792
        // our local commitment transaction.
1793
        currentCommitSecret, err := c.RevocationProducer.AtIndex(
254✔
1794
                localHeight,
254✔
1795
        )
254✔
1796
        if err != nil {
254✔
1797
                return nil, err
×
1798
        }
×
1799

1800
        // If we've restored this channel, then we'll purposefully give them an
1801
        // invalid LocalUnrevokedCommitPoint so they'll force close the channel
1802
        // allowing us to sweep our funds.
1803
        if c.hasChanStatus(ChanStatusRestored) {
254✔
1804
                currentCommitSecret[0] ^= 1
×
1805

×
1806
                // If this is a tweakless channel, then we'll purposefully send
×
1807
                // a next local height taht's invalid to trigger a force close
×
1808
                // on their end. We do this as tweakless channels don't require
×
1809
                // that the commitment point is valid, only that it's present.
×
1810
                if c.ChanType.IsTweakless() {
×
1811
                        nextLocalCommitHeight = 0
×
1812
                }
×
1813
        }
1814

1815
        // If this is a taproot channel, then we'll need to generate our next
1816
        // verification nonce to send to the remote party. They'll use this to
1817
        // sign the next update to our commitment transaction.
1818
        var nextTaprootNonce lnwire.OptMusig2NonceTLV
254✔
1819
        if c.ChanType.IsTaproot() {
275✔
1820
                taprootRevProducer, err := DeriveMusig2Shachain(
21✔
1821
                        c.RevocationProducer,
21✔
1822
                )
21✔
1823
                if err != nil {
21✔
1824
                        return nil, err
×
1825
                }
×
1826

1827
                nextNonce, err := NewMusigVerificationNonce(
21✔
1828
                        c.LocalChanCfg.MultiSigKey.PubKey,
21✔
1829
                        nextLocalCommitHeight, taprootRevProducer,
21✔
1830
                )
21✔
1831
                if err != nil {
21✔
1832
                        return nil, fmt.Errorf("unable to gen next "+
×
1833
                                "nonce: %w", err)
×
1834
                }
×
1835

1836
                nextTaprootNonce = lnwire.SomeMusig2Nonce(nextNonce.PubNonce)
21✔
1837
        }
1838

1839
        return &lnwire.ChannelReestablish{
254✔
1840
                ChanID: lnwire.NewChanIDFromOutPoint(
254✔
1841
                        c.FundingOutpoint,
254✔
1842
                ),
254✔
1843
                NextLocalCommitHeight:  nextLocalCommitHeight,
254✔
1844
                RemoteCommitTailHeight: remoteChainTipHeight,
254✔
1845
                LastRemoteCommitSecret: lastCommitSecret,
254✔
1846
                LocalUnrevokedCommitPoint: input.ComputeCommitmentPoint(
254✔
1847
                        currentCommitSecret[:],
254✔
1848
                ),
254✔
1849
                LocalNonce: nextTaprootNonce,
254✔
1850
        }, nil
254✔
1851
}
1852

1853
// MarkShutdownSent serialises and persist the given ShutdownInfo for this
1854
// channel. Persisting this info represents the fact that we have sent the
1855
// Shutdown message to the remote side and hence that we should re-transmit the
1856
// same Shutdown message on re-establish.
1857
func (c *OpenChannel) MarkShutdownSent(info *ShutdownInfo) error {
11✔
1858
        c.Lock()
11✔
1859
        defer c.Unlock()
11✔
1860

11✔
1861
        return c.storeShutdownInfo(info)
11✔
1862
}
11✔
1863

1864
// storeShutdownInfo serialises the ShutdownInfo and persists it under the
1865
// shutdownInfoKey.
1866
func (c *OpenChannel) storeShutdownInfo(info *ShutdownInfo) error {
11✔
1867
        var b bytes.Buffer
11✔
1868
        err := info.encode(&b)
11✔
1869
        if err != nil {
11✔
1870
                return err
×
1871
        }
×
1872

1873
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
22✔
1874
                chanBucket, err := fetchChanBucketRw(
11✔
1875
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
11✔
1876
                )
11✔
1877
                if err != nil {
11✔
1878
                        return err
×
1879
                }
×
1880

1881
                return chanBucket.Put(shutdownInfoKey, b.Bytes())
11✔
1882
        }, func() {})
11✔
1883
}
1884

1885
// ShutdownInfo decodes the shutdown info stored for this channel and returns
1886
// the result. If no shutdown info has been persisted for this channel then the
1887
// ErrNoShutdownInfo error is returned.
1888
func (c *OpenChannel) ShutdownInfo() (fn.Option[ShutdownInfo], error) {
4✔
1889
        c.RLock()
4✔
1890
        defer c.RUnlock()
4✔
1891

4✔
1892
        var shutdownInfo *ShutdownInfo
4✔
1893
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
8✔
1894
                chanBucket, err := fetchChanBucket(
4✔
1895
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
4✔
1896
                )
4✔
1897
                switch {
4✔
1898
                case err == nil:
4✔
1899
                case errors.Is(err, ErrNoChanDBExists),
1900
                        errors.Is(err, ErrNoActiveChannels),
1901
                        errors.Is(err, ErrChannelNotFound):
×
1902

×
1903
                        return ErrNoShutdownInfo
×
1904
                default:
×
1905
                        return err
×
1906
                }
1907

1908
                shutdownInfoBytes := chanBucket.Get(shutdownInfoKey)
4✔
1909
                if shutdownInfoBytes == nil {
6✔
1910
                        return ErrNoShutdownInfo
2✔
1911
                }
2✔
1912

1913
                shutdownInfo, err = decodeShutdownInfo(shutdownInfoBytes)
2✔
1914

2✔
1915
                return err
2✔
1916
        }, func() {
4✔
1917
                shutdownInfo = nil
4✔
1918
        })
4✔
1919
        if err != nil {
6✔
1920
                return fn.None[ShutdownInfo](), err
2✔
1921
        }
2✔
1922

1923
        return fn.Some[ShutdownInfo](*shutdownInfo), nil
2✔
1924
}
1925

1926
// isBorked returns true if the channel has been marked as borked in the
1927
// database. This requires an existing database transaction to already be
1928
// active.
1929
//
1930
// NOTE: The primary mutex should already be held before this method is called.
1931
func (c *OpenChannel) isBorked(chanBucket kvdb.RBucket) (bool, error) {
5,998✔
1932
        channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
5,998✔
1933
        if err != nil {
5,998✔
1934
                return false, err
×
1935
        }
×
1936

1937
        return channel.chanStatus != ChanStatusDefault, nil
5,998✔
1938
}
1939

1940
// MarkCommitmentBroadcasted marks the channel as a commitment transaction has
1941
// been broadcast, either our own or the remote, and we should watch the chain
1942
// for it to confirm before taking any further action. It takes as argument the
1943
// closing tx _we believe_ will appear in the chain. This is only used to
1944
// republish this tx at startup to ensure propagation, and we should still
1945
// handle the case where a different tx actually hits the chain.
1946
func (c *OpenChannel) MarkCommitmentBroadcasted(closeTx *wire.MsgTx,
1947
        closer lntypes.ChannelParty) error {
8✔
1948

8✔
1949
        return c.markBroadcasted(
8✔
1950
                ChanStatusCommitBroadcasted, forceCloseTxKey, closeTx,
8✔
1951
                closer,
8✔
1952
        )
8✔
1953
}
8✔
1954

1955
// MarkCoopBroadcasted marks the channel to indicate that a cooperative close
1956
// transaction has been broadcast, either our own or the remote, and that we
1957
// should watch the chain for it to confirm before taking further action. It
1958
// takes as argument a cooperative close tx that could appear on chain, and
1959
// should be rebroadcast upon startup. This is only used to republish and
1960
// ensure propagation, and we should still handle the case where a different tx
1961
// actually hits the chain.
1962
func (c *OpenChannel) MarkCoopBroadcasted(closeTx *wire.MsgTx,
1963
        closer lntypes.ChannelParty) error {
38✔
1964

38✔
1965
        return c.markBroadcasted(
38✔
1966
                ChanStatusCoopBroadcasted, coopCloseTxKey, closeTx,
38✔
1967
                closer,
38✔
1968
        )
38✔
1969
}
38✔
1970

1971
// markBroadcasted is a helper function which modifies the channel status of the
1972
// receiving channel and inserts a close transaction under the requested key,
1973
// which should specify either a coop or force close. It adds a status which
1974
// indicates the party that initiated the channel close.
1975
func (c *OpenChannel) markBroadcasted(status ChannelStatus, key []byte,
1976
        closeTx *wire.MsgTx, closer lntypes.ChannelParty) error {
46✔
1977

46✔
1978
        c.Lock()
46✔
1979
        defer c.Unlock()
46✔
1980

46✔
1981
        // If a closing tx is provided, we'll generate a closure to write the
46✔
1982
        // transaction in the appropriate bucket under the given key.
46✔
1983
        var putClosingTx func(kvdb.RwBucket) error
46✔
1984
        if closeTx != nil {
67✔
1985
                var b bytes.Buffer
21✔
1986
                if err := WriteElement(&b, closeTx); err != nil {
21✔
1987
                        return err
×
1988
                }
×
1989

1990
                putClosingTx = func(chanBucket kvdb.RwBucket) error {
42✔
1991
                        return chanBucket.Put(key, b.Bytes())
21✔
1992
                }
21✔
1993
        }
1994

1995
        // Add the initiator status to the status provided. These statuses are
1996
        // set in addition to the broadcast status so that we do not need to
1997
        // migrate the original logic which does not store initiator.
1998
        if closer.IsLocal() {
86✔
1999
                status |= ChanStatusLocalCloseInitiator
40✔
2000
        } else {
46✔
2001
                status |= ChanStatusRemoteCloseInitiator
6✔
2002
        }
6✔
2003

2004
        return c.putChanStatus(status, putClosingTx)
46✔
2005
}
2006

2007
// BroadcastedCommitment retrieves the stored unilateral closing tx set during
2008
// MarkCommitmentBroadcasted. If not found ErrNoCloseTx is returned.
2009
func (c *OpenChannel) BroadcastedCommitment() (*wire.MsgTx, error) {
7✔
2010
        return c.getClosingTx(forceCloseTxKey)
7✔
2011
}
7✔
2012

2013
// BroadcastedCooperative retrieves the stored cooperative closing tx set during
2014
// MarkCoopBroadcasted. If not found ErrNoCloseTx is returned.
2015
func (c *OpenChannel) BroadcastedCooperative() (*wire.MsgTx, error) {
9✔
2016
        return c.getClosingTx(coopCloseTxKey)
9✔
2017
}
9✔
2018

2019
// getClosingTx is a helper method which returns the stored closing transaction
2020
// for key. The caller should use either the force or coop closing keys.
2021
func (c *OpenChannel) getClosingTx(key []byte) (*wire.MsgTx, error) {
16✔
2022
        var closeTx *wire.MsgTx
16✔
2023

16✔
2024
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
32✔
2025
                chanBucket, err := fetchChanBucket(
16✔
2026
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
16✔
2027
                )
16✔
2028
                switch err {
16✔
2029
                case nil:
16✔
2030
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
×
2031
                        return ErrNoCloseTx
×
2032
                default:
×
2033
                        return err
×
2034
                }
2035

2036
                bs := chanBucket.Get(key)
16✔
2037
                if bs == nil {
18✔
2038
                        return ErrNoCloseTx
2✔
2039
                }
2✔
2040
                r := bytes.NewReader(bs)
14✔
2041
                return ReadElement(r, &closeTx)
14✔
2042
        }, func() {
16✔
2043
                closeTx = nil
16✔
2044
        })
16✔
2045
        if err != nil {
18✔
2046
                return nil, err
2✔
2047
        }
2✔
2048

2049
        return closeTx, nil
14✔
2050
}
2051

2052
// putChanStatus appends the given status to the channel. fs is an optional
2053
// list of closures that are given the chanBucket in order to atomically add
2054
// extra information together with the new status.
2055
func (c *OpenChannel) putChanStatus(status ChannelStatus,
2056
        fs ...func(kvdb.RwBucket) error) error {
55✔
2057

55✔
2058
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
110✔
2059
                chanBucket, err := fetchChanBucketRw(
55✔
2060
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
55✔
2061
                )
55✔
2062
                if err != nil {
55✔
2063
                        return err
×
2064
                }
×
2065

2066
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
55✔
2067
                if err != nil {
55✔
2068
                        return err
×
2069
                }
×
2070

2071
                // Add this status to the existing bitvector found in the DB.
2072
                status = channel.chanStatus | status
55✔
2073
                channel.chanStatus = status
55✔
2074

55✔
2075
                if err := putOpenChannel(chanBucket, channel); err != nil {
55✔
2076
                        return err
×
2077
                }
×
2078

2079
                for _, f := range fs {
105✔
2080
                        // Skip execution of nil closures.
50✔
2081
                        if f == nil {
75✔
2082
                                continue
25✔
2083
                        }
2084

2085
                        if err := f(chanBucket); err != nil {
25✔
2086
                                return err
×
2087
                        }
×
2088
                }
2089

2090
                return nil
55✔
2091
        }, func() {}); err != nil {
55✔
2092
                return err
×
2093
        }
×
2094

2095
        // Update the in-memory representation to keep it in sync with the DB.
2096
        c.chanStatus = status
55✔
2097

55✔
2098
        return nil
55✔
2099
}
2100

2101
func (c *OpenChannel) clearChanStatus(status ChannelStatus) error {
4✔
2102
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
8✔
2103
                chanBucket, err := fetchChanBucketRw(
4✔
2104
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
4✔
2105
                )
4✔
2106
                if err != nil {
4✔
2107
                        return err
×
2108
                }
×
2109

2110
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
4✔
2111
                if err != nil {
4✔
2112
                        return err
×
2113
                }
×
2114

2115
                // Unset this bit in the bitvector on disk.
2116
                status = channel.chanStatus & ^status
4✔
2117
                channel.chanStatus = status
4✔
2118

4✔
2119
                return putOpenChannel(chanBucket, channel)
4✔
2120
        }, func() {}); err != nil {
4✔
2121
                return err
×
2122
        }
×
2123

2124
        // Update the in-memory representation to keep it in sync with the DB.
2125
        c.chanStatus = status
4✔
2126

4✔
2127
        return nil
4✔
2128
}
2129

2130
// putOpenChannel serializes, and stores the current state of the channel in its
2131
// entirety.
2132
func putOpenChannel(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
1,224✔
2133
        // First, we'll write out all the relatively static fields, that are
1,224✔
2134
        // decided upon initial channel creation.
1,224✔
2135
        if err := putChanInfo(chanBucket, channel); err != nil {
1,224✔
2136
                return fmt.Errorf("unable to store chan info: %w", err)
×
2137
        }
×
2138

2139
        // With the static channel info written out, we'll now write out the
2140
        // current commitment state for both parties.
2141
        if err := putChanCommitments(chanBucket, channel); err != nil {
1,224✔
2142
                return fmt.Errorf("unable to store chan commitments: %w", err)
×
2143
        }
×
2144

2145
        // Next, if this is a frozen channel, we'll add in the axillary
2146
        // information we need to store.
2147
        if channel.ChanType.IsFrozen() || channel.ChanType.HasLeaseExpiration() {
1,652✔
2148
                err := storeThawHeight(
428✔
2149
                        chanBucket, channel.ThawHeight,
428✔
2150
                )
428✔
2151
                if err != nil {
428✔
2152
                        return fmt.Errorf("unable to store thaw height: %w",
×
2153
                                err)
×
2154
                }
×
2155
        }
2156

2157
        // Finally, we'll write out the revocation state for both parties
2158
        // within a distinct key space.
2159
        if err := putChanRevocationState(chanBucket, channel); err != nil {
1,224✔
2160
                return fmt.Errorf("unable to store chan revocations: %w", err)
×
2161
        }
×
2162

2163
        return nil
1,224✔
2164
}
2165

2166
// fetchOpenChannel retrieves, and deserializes (including decrypting
2167
// sensitive) the complete channel currently active with the passed nodeID.
2168
func fetchOpenChannel(chanBucket kvdb.RBucket,
2169
        chanPoint *wire.OutPoint) (*OpenChannel, error) {
7,120✔
2170

7,120✔
2171
        channel := &OpenChannel{
7,120✔
2172
                FundingOutpoint: *chanPoint,
7,120✔
2173
        }
7,120✔
2174

7,120✔
2175
        // First, we'll read all the static information that changes less
7,120✔
2176
        // frequently from disk.
7,120✔
2177
        if err := fetchChanInfo(chanBucket, channel); err != nil {
7,120✔
2178
                return nil, fmt.Errorf("unable to fetch chan info: %w", err)
×
2179
        }
×
2180

2181
        // With the static information read, we'll now read the current
2182
        // commitment state for both sides of the channel.
2183
        if err := fetchChanCommitments(chanBucket, channel); err != nil {
7,120✔
2184
                return nil, fmt.Errorf("unable to fetch chan commitments: %w",
×
2185
                        err)
×
2186
        }
×
2187

2188
        // Next, if this is a frozen channel, we'll add in the axillary
2189
        // information we need to store.
2190
        if channel.ChanType.IsFrozen() || channel.ChanType.HasLeaseExpiration() {
7,454✔
2191
                thawHeight, err := fetchThawHeight(chanBucket)
334✔
2192
                if err != nil {
334✔
2193
                        return nil, fmt.Errorf("unable to store thaw "+
×
2194
                                "height: %v", err)
×
2195
                }
×
2196

2197
                channel.ThawHeight = thawHeight
334✔
2198
        }
2199

2200
        // Finally, we'll retrieve the current revocation state so we can
2201
        // properly
2202
        if err := fetchChanRevocationState(chanBucket, channel); err != nil {
7,120✔
2203
                return nil, fmt.Errorf("unable to fetch chan revocations: %w",
×
2204
                        err)
×
2205
        }
×
2206

2207
        channel.Packager = NewChannelPackager(channel.ShortChannelID)
7,120✔
2208

7,120✔
2209
        return channel, nil
7,120✔
2210
}
2211

2212
// SyncPending writes the contents of the channel to the database while it's in
2213
// the pending (waiting for funding confirmation) state. The IsPending flag
2214
// will be set to true. When the channel's funding transaction is confirmed,
2215
// the channel should be marked as "open" and the IsPending flag set to false.
2216
// Note that this function also creates a LinkNode relationship between this
2217
// newly created channel and a new LinkNode instance. This allows listing all
2218
// channels in the database globally, or according to the LinkNode they were
2219
// created with.
2220
//
2221
// TODO(roasbeef): addr param should eventually be an lnwire.NetAddress type
2222
// that includes service bits.
2223
func (c *OpenChannel) SyncPending(addr net.Addr, pendingHeight uint32) error {
880✔
2224
        c.Lock()
880✔
2225
        defer c.Unlock()
880✔
2226

880✔
2227
        c.FundingBroadcastHeight = pendingHeight
880✔
2228

880✔
2229
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
1,760✔
2230
                return syncNewChannel(tx, c, []net.Addr{addr})
880✔
2231
        }, func() {})
1,760✔
2232
}
2233

2234
// syncNewChannel will write the passed channel to disk, and also create a
2235
// LinkNode (if needed) for the channel peer.
2236
func syncNewChannel(tx kvdb.RwTx, c *OpenChannel, addrs []net.Addr) error {
881✔
2237
        // First, sync all the persistent channel state to disk.
881✔
2238
        if err := c.fullSync(tx); err != nil {
881✔
2239
                return err
×
2240
        }
×
2241

2242
        nodeInfoBucket, err := tx.CreateTopLevelBucket(nodeInfoBucket)
881✔
2243
        if err != nil {
881✔
2244
                return err
×
2245
        }
×
2246

2247
        // If a LinkNode for this identity public key already exists,
2248
        // then we can exit early.
2249
        nodePub := c.IdentityPub.SerializeCompressed()
881✔
2250
        if nodeInfoBucket.Get(nodePub) != nil {
1,024✔
2251
                return nil
143✔
2252
        }
143✔
2253

2254
        // Next, we need to establish a (possibly) new LinkNode relationship
2255
        // for this channel. The LinkNode metadata contains reachability,
2256
        // up-time, and service bits related information.
2257
        linkNode := NewLinkNode(
738✔
2258
                &LinkNodeDB{backend: c.Db.backend},
738✔
2259
                wire.MainNet, c.IdentityPub, addrs...,
738✔
2260
        )
738✔
2261

738✔
2262
        // TODO(roasbeef): do away with link node all together?
738✔
2263

738✔
2264
        return putLinkNode(nodeInfoBucket, linkNode)
738✔
2265
}
2266

2267
// UpdateCommitment updates the local commitment state. It locks in the pending
2268
// local updates that were received by us from the remote party. The commitment
2269
// state completely describes the balance state at this point in the commitment
2270
// chain. In addition to that, it persists all the remote log updates that we
2271
// have acked, but not signed a remote commitment for yet. These need to be
2272
// persisted to be able to produce a valid commit signature if a restart would
2273
// occur. This method its to be called when we revoke our prior commitment
2274
// state.
2275
//
2276
// A map is returned of all the htlc resolutions that were locked in this
2277
// commitment. Keys correspond to htlc indices and values indicate whether the
2278
// htlc was settled or failed.
2279
func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
2280
        unsignedAckedUpdates []LogUpdate) (map[uint64]bool, error) {
1,999✔
2281

1,999✔
2282
        c.Lock()
1,999✔
2283
        defer c.Unlock()
1,999✔
2284

1,999✔
2285
        // If this is a restored channel, then we want to avoid mutating the
1,999✔
2286
        // state as all, as it's impossible to do so in a protocol compliant
1,999✔
2287
        // manner.
1,999✔
2288
        if c.hasChanStatus(ChanStatusRestored) {
2,000✔
2289
                return nil, ErrNoRestoredChannelMutation
1✔
2290
        }
1✔
2291

2292
        var finalHtlcs = make(map[uint64]bool)
1,998✔
2293

1,998✔
2294
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
3,996✔
2295
                chanBucket, err := fetchChanBucketRw(
1,998✔
2296
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1,998✔
2297
                )
1,998✔
2298
                if err != nil {
1,998✔
2299
                        return err
×
2300
                }
×
2301

2302
                // If the channel is marked as borked, then for safety reasons,
2303
                // we shouldn't attempt any further updates.
2304
                isBorked, err := c.isBorked(chanBucket)
1,998✔
2305
                if err != nil {
1,998✔
2306
                        return err
×
2307
                }
×
2308
                if isBorked {
1,999✔
2309
                        return ErrChanBorked
1✔
2310
                }
1✔
2311

2312
                if err = putChanInfo(chanBucket, c); err != nil {
1,997✔
2313
                        return fmt.Errorf("unable to store chan info: %w", err)
×
2314
                }
×
2315

2316
                // With the proper bucket fetched, we'll now write the latest
2317
                // commitment state to disk for the target party.
2318
                err = putChanCommitment(
1,997✔
2319
                        chanBucket, newCommitment, true,
1,997✔
2320
                )
1,997✔
2321
                if err != nil {
1,997✔
2322
                        return fmt.Errorf("unable to store chan "+
×
2323
                                "revocations: %v", err)
×
2324
                }
×
2325

2326
                // Persist unsigned but acked remote updates that need to be
2327
                // restored after a restart.
2328
                var b bytes.Buffer
1,997✔
2329
                err = serializeLogUpdates(&b, unsignedAckedUpdates)
1,997✔
2330
                if err != nil {
1,997✔
2331
                        return err
×
2332
                }
×
2333

2334
                err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes())
1,997✔
2335
                if err != nil {
1,997✔
2336
                        return fmt.Errorf("unable to store dangline remote "+
×
2337
                                "updates: %v", err)
×
2338
                }
×
2339

2340
                // Since we have just sent the counterparty a revocation, store true
2341
                // under lastWasRevokeKey.
2342
                var b2 bytes.Buffer
1,997✔
2343
                if err := WriteElements(&b2, true); err != nil {
1,997✔
2344
                        return err
×
2345
                }
×
2346

2347
                if err := chanBucket.Put(lastWasRevokeKey, b2.Bytes()); err != nil {
1,997✔
2348
                        return err
×
2349
                }
×
2350

2351
                // Persist the remote unsigned local updates that are not included
2352
                // in our new commitment.
2353
                updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
1,997✔
2354
                if updateBytes == nil {
2,509✔
2355
                        return nil
512✔
2356
                }
512✔
2357

2358
                r := bytes.NewReader(updateBytes)
1,485✔
2359
                updates, err := deserializeLogUpdates(r)
1,485✔
2360
                if err != nil {
1,485✔
2361
                        return err
×
2362
                }
×
2363

2364
                // Get the bucket where settled htlcs are recorded if the user
2365
                // opted in to storing this information.
2366
                var finalHtlcsBucket kvdb.RwBucket
1,485✔
2367
                if c.Db.parent.storeFinalHtlcResolutions {
1,486✔
2368
                        bucket, err := fetchFinalHtlcsBucketRw(
1✔
2369
                                tx, c.ShortChannelID,
1✔
2370
                        )
1✔
2371
                        if err != nil {
1✔
2372
                                return err
×
2373
                        }
×
2374

2375
                        finalHtlcsBucket = bucket
1✔
2376
                }
2377

2378
                var unsignedUpdates []LogUpdate
1,485✔
2379
                for _, upd := range updates {
1,912✔
2380
                        // Gather updates that are not on our local commitment.
427✔
2381
                        if upd.LogIndex >= newCommitment.LocalLogIndex {
427✔
2382
                                unsignedUpdates = append(unsignedUpdates, upd)
×
2383

×
2384
                                continue
×
2385
                        }
2386

2387
                        // The update was locked in. If the update was a
2388
                        // resolution, then store it in the database.
2389
                        err := processFinalHtlc(
427✔
2390
                                finalHtlcsBucket, upd, finalHtlcs,
427✔
2391
                        )
427✔
2392
                        if err != nil {
427✔
2393
                                return err
×
2394
                        }
×
2395
                }
2396

2397
                var b3 bytes.Buffer
1,485✔
2398
                err = serializeLogUpdates(&b3, unsignedUpdates)
1,485✔
2399
                if err != nil {
1,485✔
2400
                        return fmt.Errorf("unable to serialize log updates: %w",
×
2401
                                err)
×
2402
                }
×
2403

2404
                err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b3.Bytes())
1,485✔
2405
                if err != nil {
1,485✔
2406
                        return fmt.Errorf("unable to restore chanbucket: %w",
×
2407
                                err)
×
2408
                }
×
2409

2410
                return nil
1,485✔
2411
        }, func() {
1,998✔
2412
                finalHtlcs = make(map[uint64]bool)
1,998✔
2413
        })
1,998✔
2414
        if err != nil {
1,999✔
2415
                return nil, err
1✔
2416
        }
1✔
2417

2418
        c.LocalCommitment = *newCommitment
1,997✔
2419

1,997✔
2420
        return finalHtlcs, nil
1,997✔
2421
}
2422

2423
// processFinalHtlc stores a final htlc outcome in the database if signaled via
2424
// the supplied log update. An in-memory htlcs map is updated too.
2425
func processFinalHtlc(finalHtlcsBucket walletdb.ReadWriteBucket, upd LogUpdate,
2426
        finalHtlcs map[uint64]bool) error {
427✔
2427

427✔
2428
        var (
427✔
2429
                settled bool
427✔
2430
                id      uint64
427✔
2431
        )
427✔
2432

427✔
2433
        switch msg := upd.UpdateMsg.(type) {
427✔
2434
        case *lnwire.UpdateFulfillHTLC:
285✔
2435
                settled = true
285✔
2436
                id = msg.ID
285✔
2437

2438
        case *lnwire.UpdateFailHTLC:
131✔
2439
                settled = false
131✔
2440
                id = msg.ID
131✔
2441

2442
        case *lnwire.UpdateFailMalformedHTLC:
3✔
2443
                settled = false
3✔
2444
                id = msg.ID
3✔
2445

2446
        default:
8✔
2447
                return nil
8✔
2448
        }
2449

2450
        // Store the final resolution in the database if a bucket is provided.
2451
        if finalHtlcsBucket != nil {
420✔
2452
                err := putFinalHtlc(
1✔
2453
                        finalHtlcsBucket, id,
1✔
2454
                        FinalHtlcInfo{
1✔
2455
                                Settled:  settled,
1✔
2456
                                Offchain: true,
1✔
2457
                        },
1✔
2458
                )
1✔
2459
                if err != nil {
1✔
2460
                        return err
×
2461
                }
×
2462
        }
2463

2464
        finalHtlcs[id] = settled
419✔
2465

419✔
2466
        return nil
419✔
2467
}
2468

2469
// ActiveHtlcs returns a slice of HTLC's which are currently active on *both*
2470
// commitment transactions.
2471
func (c *OpenChannel) ActiveHtlcs() []HTLC {
1,627✔
2472
        c.RLock()
1,627✔
2473
        defer c.RUnlock()
1,627✔
2474

1,627✔
2475
        // We'll only return HTLC's that are locked into *both* commitment
1,627✔
2476
        // transactions. So we'll iterate through their set of HTLC's to note
1,627✔
2477
        // which ones are present on their commitment.
1,627✔
2478
        remoteHtlcs := make(map[[32]byte]struct{})
1,627✔
2479
        for _, htlc := range c.RemoteCommitment.Htlcs {
8,355✔
2480
                log.Tracef("RemoteCommitment has htlc: id=%v, update=%v "+
6,728✔
2481
                        "incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
6,728✔
2482
                        htlc.Incoming)
6,728✔
2483

6,728✔
2484
                onionHash := sha256.Sum256(htlc.OnionBlob[:])
6,728✔
2485
                remoteHtlcs[onionHash] = struct{}{}
6,728✔
2486
        }
6,728✔
2487

2488
        // Now that we know which HTLC's they have, we'll only mark the HTLC's
2489
        // as active if *we* know them as well.
2490
        activeHtlcs := make([]HTLC, 0, len(remoteHtlcs))
1,627✔
2491
        for _, htlc := range c.LocalCommitment.Htlcs {
8,351✔
2492
                log.Tracef("LocalCommitment has htlc: id=%v, update=%v "+
6,724✔
2493
                        "incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
6,724✔
2494
                        htlc.Incoming)
6,724✔
2495

6,724✔
2496
                onionHash := sha256.Sum256(htlc.OnionBlob[:])
6,724✔
2497
                if _, ok := remoteHtlcs[onionHash]; !ok {
7,005✔
2498
                        log.Tracef("Skipped htlc due to onion mismatched: "+
281✔
2499
                                "id=%v, update=%v incoming=%v",
281✔
2500
                                htlc.HtlcIndex, htlc.LogIndex, htlc.Incoming)
281✔
2501

281✔
2502
                        continue
281✔
2503
                }
2504

2505
                activeHtlcs = append(activeHtlcs, htlc)
6,443✔
2506
        }
2507

2508
        return activeHtlcs
1,627✔
2509
}
2510

2511
// HTLC is the on-disk representation of a hash time-locked contract. HTLCs are
2512
// contained within ChannelDeltas which encode the current state of the
2513
// commitment between state updates.
2514
//
2515
// TODO(roasbeef): save space by using smaller ints at tail end?
2516
type HTLC struct {
2517
        // TODO(yy): can embed an HTLCEntry here.
2518

2519
        // Signature is the signature for the second level covenant transaction
2520
        // for this HTLC. The second level transaction is a timeout tx in the
2521
        // case that this is an outgoing HTLC, and a success tx in the case
2522
        // that this is an incoming HTLC.
2523
        //
2524
        // TODO(roasbeef): make [64]byte instead?
2525
        Signature []byte
2526

2527
        // RHash is the payment hash of the HTLC.
2528
        RHash [32]byte
2529

2530
        // Amt is the amount of milli-satoshis this HTLC escrows.
2531
        Amt lnwire.MilliSatoshi
2532

2533
        // RefundTimeout is the absolute timeout on the HTLC that the sender
2534
        // must wait before reclaiming the funds in limbo.
2535
        RefundTimeout uint32
2536

2537
        // OutputIndex is the output index for this particular HTLC output
2538
        // within the commitment transaction.
2539
        OutputIndex int32
2540

2541
        // Incoming denotes whether we're the receiver or the sender of this
2542
        // HTLC.
2543
        Incoming bool
2544

2545
        // OnionBlob is an opaque blob which is used to complete multi-hop
2546
        // routing.
2547
        OnionBlob [lnwire.OnionPacketSize]byte
2548

2549
        // HtlcIndex is the HTLC counter index of this active, outstanding
2550
        // HTLC. This differs from the LogIndex, as the HtlcIndex is only
2551
        // incremented for each offered HTLC, while they LogIndex is
2552
        // incremented for each update (includes settle+fail).
2553
        HtlcIndex uint64
2554

2555
        // LogIndex is the cumulative log index of this HTLC. This differs
2556
        // from the HtlcIndex as this will be incremented for each new log
2557
        // update added.
2558
        LogIndex uint64
2559

2560
        // ExtraData contains any additional information that was transmitted
2561
        // with the HTLC via TLVs. This data *must* already be encoded as a
2562
        // TLV stream, and may be empty. The length of this data is naturally
2563
        // limited by the space available to TLVs in update_add_htlc:
2564
        // = 65535 bytes (bolt 8 maximum message size):
2565
        // - 2 bytes (bolt 1 message_type)
2566
        // - 32 bytes (channel_id)
2567
        // - 8 bytes (id)
2568
        // - 8 bytes (amount_msat)
2569
        // - 32 bytes (payment_hash)
2570
        // - 4 bytes (cltv_expiry)
2571
        // - 1366 bytes (onion_routing_packet)
2572
        // = 64083 bytes maximum possible TLV stream
2573
        //
2574
        // Note that this extra data is stored inline with the OnionBlob for
2575
        // legacy reasons, see serialization/deserialization functions for
2576
        // detail.
2577
        ExtraData lnwire.ExtraOpaqueData
2578

2579
        // BlindingPoint is an optional blinding point included with the HTLC.
2580
        //
2581
        // Note: this field is not a part of on-disk representation of the
2582
        // HTLC. It is stored in the ExtraData field, which is used to store
2583
        // a TLV stream of additional information associated with the HTLC.
2584
        BlindingPoint lnwire.BlindingPointRecord
2585

2586
        // CustomRecords is a set of custom TLV records that are associated with
2587
        // this HTLC. These records are used to store additional information
2588
        // about the HTLC that is not part of the standard HTLC fields. This
2589
        // field is encoded within the ExtraData field.
2590
        CustomRecords lnwire.CustomRecords
2591
}
2592

2593
// serializeExtraData encodes a TLV stream of extra data to be stored with a
2594
// HTLC. It uses the update_add_htlc TLV types, because this is where extra
2595
// data is passed with a HTLC. At present blinding points are the only extra
2596
// data that we will store, and the function is a no-op if a nil blinding
2597
// point is provided.
2598
//
2599
// This function MUST be called to persist all HTLC values when they are
2600
// serialized.
2601
func (h *HTLC) serializeExtraData() error {
30,143✔
2602
        var records []tlv.RecordProducer
30,143✔
2603
        h.BlindingPoint.WhenSome(func(b tlv.RecordT[lnwire.BlindingPointTlvType,
30,143✔
2604
                *btcec.PublicKey]) {
30,147✔
2605

4✔
2606
                records = append(records, &b)
4✔
2607
        })
4✔
2608

2609
        records, err := h.CustomRecords.ExtendRecordProducers(records)
30,143✔
2610
        if err != nil {
30,143✔
2611
                return err
×
2612
        }
×
2613

2614
        return h.ExtraData.PackRecords(records...)
30,143✔
2615
}
2616

2617
// deserializeExtraData extracts TLVs from the extra data persisted for the
2618
// htlc and populates values in the struct accordingly.
2619
//
2620
// This function MUST be called to populate the struct properly when HTLCs
2621
// are deserialized.
2622
func (h *HTLC) deserializeExtraData() error {
68,485✔
2623
        if len(h.ExtraData) == 0 {
135,288✔
2624
                return nil
66,803✔
2625
        }
66,803✔
2626

2627
        blindingPoint := h.BlindingPoint.Zero()
1,682✔
2628
        tlvMap, err := h.ExtraData.ExtractRecords(&blindingPoint)
1,682✔
2629
        if err != nil {
1,682✔
2630
                return err
×
2631
        }
×
2632

2633
        if val, ok := tlvMap[h.BlindingPoint.TlvType()]; ok && val == nil {
1,686✔
2634
                h.BlindingPoint = tlv.SomeRecordT(blindingPoint)
4✔
2635

4✔
2636
                // Remove the entry from the TLV map. Anything left in the map
4✔
2637
                // will be included in the custom records field.
4✔
2638
                delete(tlvMap, h.BlindingPoint.TlvType())
4✔
2639
        }
4✔
2640

2641
        // Set the custom records field to the remaining TLV records.
2642
        customRecords, err := lnwire.NewCustomRecords(tlvMap)
1,682✔
2643
        if err != nil {
1,682✔
2644
                return err
×
2645
        }
×
2646
        h.CustomRecords = customRecords
1,682✔
2647

1,682✔
2648
        return nil
1,682✔
2649
}
2650

2651
// SerializeHtlcs writes out the passed set of HTLC's into the passed writer
2652
// using the current default on-disk serialization format.
2653
//
2654
// This inline serialization has been extended to allow storage of extra data
2655
// associated with a HTLC in the following way:
2656
//   - The known-length onion blob (1366 bytes) is serialized as var bytes in
2657
//     WriteElements (ie, the length 1366 was written, followed by the 1366
2658
//     onion bytes).
2659
//   - To include extra data, we append any extra data present to this one
2660
//     variable length of data. Since we know that the onion is strictly 1366
2661
//     bytes, any length after that should be considered to be extra data.
2662
//
2663
// NOTE: This API is NOT stable, the on-disk format will likely change in the
2664
// future.
2665
func SerializeHtlcs(b io.Writer, htlcs ...HTLC) error {
8,462✔
2666
        numHtlcs := uint16(len(htlcs))
8,462✔
2667
        if err := WriteElement(b, numHtlcs); err != nil {
8,462✔
2668
                return err
×
2669
        }
×
2670

2671
        for _, htlc := range htlcs {
38,605✔
2672
                // Populate TLV stream for any additional fields contained
30,143✔
2673
                // in the TLV.
30,143✔
2674
                if err := htlc.serializeExtraData(); err != nil {
30,143✔
2675
                        return err
×
2676
                }
×
2677

2678
                // The onion blob and hltc data are stored as a single var
2679
                // bytes blob.
2680
                onionAndExtraData := make(
30,143✔
2681
                        []byte, lnwire.OnionPacketSize+len(htlc.ExtraData),
30,143✔
2682
                )
30,143✔
2683
                copy(onionAndExtraData, htlc.OnionBlob[:])
30,143✔
2684
                copy(onionAndExtraData[lnwire.OnionPacketSize:], htlc.ExtraData)
30,143✔
2685

30,143✔
2686
                if err := WriteElements(b,
30,143✔
2687
                        htlc.Signature, htlc.RHash, htlc.Amt, htlc.RefundTimeout,
30,143✔
2688
                        htlc.OutputIndex, htlc.Incoming, onionAndExtraData,
30,143✔
2689
                        htlc.HtlcIndex, htlc.LogIndex,
30,143✔
2690
                ); err != nil {
30,143✔
2691
                        return err
×
2692
                }
×
2693
        }
2694

2695
        return nil
8,462✔
2696
}
2697

2698
// DeserializeHtlcs attempts to read out a slice of HTLC's from the passed
2699
// io.Reader. The bytes within the passed reader MUST have been previously
2700
// written to using the SerializeHtlcs function.
2701
//
2702
// This inline deserialization has been extended to allow storage of extra data
2703
// associated with a HTLC in the following way:
2704
//   - The known-length onion blob (1366 bytes) and any additional data present
2705
//     are read out as a single blob of variable byte data.
2706
//   - They are stored like this to take advantage of the variable space
2707
//     available for extension without migration (see SerializeHtlcs).
2708
//   - The first 1366 bytes are interpreted as the onion blob, and any remaining
2709
//     bytes as extra HTLC data.
2710
//   - This extra HTLC data is expected to be serialized as a TLV stream, and
2711
//     its parsing is left to higher layers.
2712
//
2713
// NOTE: This API is NOT stable, the on-disk format will likely change in the
2714
// future.
2715
func DeserializeHtlcs(r io.Reader) ([]HTLC, error) {
16,333✔
2716
        var numHtlcs uint16
16,333✔
2717
        if err := ReadElement(r, &numHtlcs); err != nil {
16,333✔
2718
                return nil, err
×
2719
        }
×
2720

2721
        var htlcs []HTLC
16,333✔
2722
        if numHtlcs == 0 {
23,222✔
2723
                return htlcs, nil
6,889✔
2724
        }
6,889✔
2725

2726
        htlcs = make([]HTLC, numHtlcs)
9,444✔
2727
        for i := uint16(0); i < numHtlcs; i++ {
77,930✔
2728
                var onionAndExtraData []byte
68,486✔
2729
                if err := ReadElements(r,
68,486✔
2730
                        &htlcs[i].Signature, &htlcs[i].RHash, &htlcs[i].Amt,
68,486✔
2731
                        &htlcs[i].RefundTimeout, &htlcs[i].OutputIndex,
68,486✔
2732
                        &htlcs[i].Incoming, &onionAndExtraData,
68,486✔
2733
                        &htlcs[i].HtlcIndex, &htlcs[i].LogIndex,
68,486✔
2734
                ); err != nil {
68,486✔
2735
                        return htlcs, err
×
2736
                }
×
2737

2738
                // Sanity check that we have at least the onion blob size we
2739
                // expect.
2740
                if len(onionAndExtraData) < lnwire.OnionPacketSize {
68,487✔
2741
                        return nil, ErrOnionBlobLength
1✔
2742
                }
1✔
2743

2744
                // First OnionPacketSize bytes are our fixed length onion
2745
                // packet.
2746
                copy(
68,485✔
2747
                        htlcs[i].OnionBlob[:],
68,485✔
2748
                        onionAndExtraData[0:lnwire.OnionPacketSize],
68,485✔
2749
                )
68,485✔
2750

68,485✔
2751
                // Any additional bytes belong to extra data. ExtraDataLen
68,485✔
2752
                // will be >= 0, because we know that we always have a fixed
68,485✔
2753
                // length onion packet.
68,485✔
2754
                extraDataLen := len(onionAndExtraData) - lnwire.OnionPacketSize
68,485✔
2755
                if extraDataLen > 0 {
70,167✔
2756
                        htlcs[i].ExtraData = make([]byte, extraDataLen)
1,682✔
2757

1,682✔
2758
                        copy(
1,682✔
2759
                                htlcs[i].ExtraData,
1,682✔
2760
                                onionAndExtraData[lnwire.OnionPacketSize:],
1,682✔
2761
                        )
1,682✔
2762
                }
1,682✔
2763

2764
                // Finally, deserialize any TLVs contained in that extra data
2765
                // if they are present.
2766
                if err := htlcs[i].deserializeExtraData(); err != nil {
68,485✔
2767
                        return nil, err
×
2768
                }
×
2769
        }
2770

2771
        return htlcs, nil
9,443✔
2772
}
2773

2774
// Copy returns a full copy of the target HTLC.
2775
func (h *HTLC) Copy() HTLC {
267✔
2776
        clone := HTLC{
267✔
2777
                Incoming:      h.Incoming,
267✔
2778
                Amt:           h.Amt,
267✔
2779
                RefundTimeout: h.RefundTimeout,
267✔
2780
                OutputIndex:   h.OutputIndex,
267✔
2781
        }
267✔
2782
        copy(clone.Signature[:], h.Signature)
267✔
2783
        copy(clone.RHash[:], h.RHash[:])
267✔
2784
        copy(clone.ExtraData, h.ExtraData)
267✔
2785
        clone.BlindingPoint = h.BlindingPoint
267✔
2786
        clone.CustomRecords = h.CustomRecords.Copy()
267✔
2787

267✔
2788
        return clone
267✔
2789
}
267✔
2790

2791
// LogUpdate represents a pending update to the remote commitment chain. The
2792
// log update may be an add, fail, or settle entry. We maintain this data in
2793
// order to be able to properly retransmit our proposed state if necessary.
2794
type LogUpdate struct {
2795
        // LogIndex is the log index of this proposed commitment update entry.
2796
        LogIndex uint64
2797

2798
        // UpdateMsg is the update message that was included within our
2799
        // local update log. The LogIndex value denotes the log index of this
2800
        // update which will be used when restoring our local update log if
2801
        // we're left with a dangling update on restart.
2802
        UpdateMsg lnwire.Message
2803
}
2804

2805
// serializeLogUpdate writes a log update to the provided io.Writer.
2806
func serializeLogUpdate(w io.Writer, l *LogUpdate) error {
1,245✔
2807
        return WriteElements(w, l.LogIndex, l.UpdateMsg)
1,245✔
2808
}
1,245✔
2809

2810
// deserializeLogUpdate reads a log update from the provided io.Reader.
2811
func deserializeLogUpdate(r io.Reader) (*LogUpdate, error) {
83✔
2812
        l := &LogUpdate{}
83✔
2813
        if err := ReadElements(r, &l.LogIndex, &l.UpdateMsg); err != nil {
83✔
2814
                return nil, err
×
2815
        }
×
2816

2817
        return l, nil
83✔
2818
}
2819

2820
// CommitDiff represents the delta needed to apply the state transition between
2821
// two subsequent commitment states. Given state N and state N+1, one is able
2822
// to apply the set of messages contained within the CommitDiff to N to arrive
2823
// at state N+1. Each time a new commitment is extended, we'll write a new
2824
// commitment (along with the full commitment state) to disk so we can
2825
// re-transmit the state in the case of a connection loss or message drop.
2826
type CommitDiff struct {
2827
        // ChannelCommitment is the full commitment state that one would arrive
2828
        // at by applying the set of messages contained in the UpdateDiff to
2829
        // the prior accepted commitment.
2830
        Commitment ChannelCommitment
2831

2832
        // LogUpdates is the set of messages sent prior to the commitment state
2833
        // transition in question. Upon reconnection, if we detect that they
2834
        // don't have the commitment, then we re-send this along with the
2835
        // proper signature.
2836
        LogUpdates []LogUpdate
2837

2838
        // CommitSig is the exact CommitSig message that should be sent after
2839
        // the set of LogUpdates above has been retransmitted. The signatures
2840
        // within this message should properly cover the new commitment state
2841
        // and also the HTLC's within the new commitment state.
2842
        CommitSig *lnwire.CommitSig
2843

2844
        // OpenedCircuitKeys is a set of unique identifiers for any downstream
2845
        // Add packets included in this commitment txn. After a restart, this
2846
        // set of htlcs is acked from the link's incoming mailbox to ensure
2847
        // there isn't an attempt to re-add them to this commitment txn.
2848
        OpenedCircuitKeys []models.CircuitKey
2849

2850
        // ClosedCircuitKeys records the unique identifiers for any settle/fail
2851
        // packets that were resolved by this commitment txn. After a restart,
2852
        // this is used to ensure those circuits are removed from the circuit
2853
        // map, and the downstream packets in the link's mailbox are removed.
2854
        ClosedCircuitKeys []models.CircuitKey
2855

2856
        // AddAcks specifies the locations (commit height, pkg index) of any
2857
        // Adds that were failed/settled in this commit diff. This will ack
2858
        // entries in *this* channel's forwarding packages.
2859
        //
2860
        // NOTE: This value is not serialized, it is used to atomically mark the
2861
        // resolution of adds, such that they will not be reprocessed after a
2862
        // restart.
2863
        AddAcks []AddRef
2864

2865
        // SettleFailAcks specifies the locations (chan id, commit height, pkg
2866
        // index) of any Settles or Fails that were locked into this commit
2867
        // diff, and originate from *another* channel, i.e. the outgoing link.
2868
        //
2869
        // NOTE: This value is not serialized, it is used to atomically acks
2870
        // settles and fails from the forwarding packages of other channels,
2871
        // such that they will not be reforwarded internally after a restart.
2872
        SettleFailAcks []SettleFailRef
2873
}
2874

2875
// serializeLogUpdates serializes provided list of updates to a stream.
2876
func serializeLogUpdates(w io.Writer, logUpdates []LogUpdate) error {
9,017✔
2877
        numUpdates := uint16(len(logUpdates))
9,017✔
2878
        if err := binary.Write(w, byteOrder, numUpdates); err != nil {
9,017✔
2879
                return err
×
2880
        }
×
2881

2882
        for _, diff := range logUpdates {
12,736✔
2883
                err := WriteElements(w, diff.LogIndex, diff.UpdateMsg)
3,719✔
2884
                if err != nil {
3,719✔
2885
                        return err
×
2886
                }
×
2887
        }
2888

2889
        return nil
9,017✔
2890
}
2891

2892
// deserializeLogUpdates deserializes a list of updates from a stream.
2893
func deserializeLogUpdates(r io.Reader) ([]LogUpdate, error) {
5,381✔
2894
        var numUpdates uint16
5,381✔
2895
        if err := binary.Read(r, byteOrder, &numUpdates); err != nil {
5,381✔
2896
                return nil, err
×
2897
        }
×
2898

2899
        logUpdates := make([]LogUpdate, numUpdates)
5,381✔
2900
        for i := 0; i < int(numUpdates); i++ {
8,741✔
2901
                err := ReadElements(r,
3,360✔
2902
                        &logUpdates[i].LogIndex, &logUpdates[i].UpdateMsg,
3,360✔
2903
                )
3,360✔
2904
                if err != nil {
3,360✔
2905
                        return nil, err
×
2906
                }
×
2907
        }
2908
        return logUpdates, nil
5,381✔
2909
}
2910

2911
func serializeCommitDiff(w io.Writer, diff *CommitDiff) error { // nolint: dupl
2,043✔
2912
        if err := serializeChanCommit(w, &diff.Commitment); err != nil {
2,043✔
2913
                return err
×
2914
        }
×
2915

2916
        if err := WriteElements(w, diff.CommitSig); err != nil {
2,043✔
2917
                return err
×
2918
        }
×
2919

2920
        if err := serializeLogUpdates(w, diff.LogUpdates); err != nil {
2,043✔
2921
                return err
×
2922
        }
×
2923

2924
        numOpenRefs := uint16(len(diff.OpenedCircuitKeys))
2,043✔
2925
        if err := binary.Write(w, byteOrder, numOpenRefs); err != nil {
2,043✔
2926
                return err
×
2927
        }
×
2928

2929
        for _, openRef := range diff.OpenedCircuitKeys {
2,504✔
2930
                err := WriteElements(w, openRef.ChanID, openRef.HtlcID)
461✔
2931
                if err != nil {
461✔
2932
                        return err
×
2933
                }
×
2934
        }
2935

2936
        numClosedRefs := uint16(len(diff.ClosedCircuitKeys))
2,043✔
2937
        if err := binary.Write(w, byteOrder, numClosedRefs); err != nil {
2,043✔
2938
                return err
×
2939
        }
×
2940

2941
        for _, closedRef := range diff.ClosedCircuitKeys {
2,082✔
2942
                err := WriteElements(w, closedRef.ChanID, closedRef.HtlcID)
39✔
2943
                if err != nil {
39✔
2944
                        return err
×
2945
                }
×
2946
        }
2947

2948
        // We'll also encode the commit aux data stream here. We do this here
2949
        // rather than above (at the call to serializeChanCommit), to ensure
2950
        // backwards compat for reads to existing non-custom channels.
2951
        auxData := diff.Commitment.extractTlvData()
2,043✔
2952
        if err := auxData.encode(w); err != nil {
2,043✔
2953
                return fmt.Errorf("unable to write aux data: %w", err)
×
2954
        }
×
2955

2956
        return nil
2,043✔
2957
}
2958

2959
func deserializeCommitDiff(r io.Reader) (*CommitDiff, error) {
2,036✔
2960
        var (
2,036✔
2961
                d   CommitDiff
2,036✔
2962
                err error
2,036✔
2963
        )
2,036✔
2964

2,036✔
2965
        d.Commitment, err = deserializeChanCommit(r)
2,036✔
2966
        if err != nil {
2,036✔
2967
                return nil, err
×
2968
        }
×
2969

2970
        var msg lnwire.Message
2,036✔
2971
        if err := ReadElements(r, &msg); err != nil {
2,036✔
2972
                return nil, err
×
2973
        }
×
2974
        commitSig, ok := msg.(*lnwire.CommitSig)
2,036✔
2975
        if !ok {
2,036✔
2976
                return nil, fmt.Errorf("expected lnwire.CommitSig, instead "+
×
2977
                        "read: %T", msg)
×
2978
        }
×
2979
        d.CommitSig = commitSig
2,036✔
2980

2,036✔
2981
        d.LogUpdates, err = deserializeLogUpdates(r)
2,036✔
2982
        if err != nil {
2,036✔
2983
                return nil, err
×
2984
        }
×
2985

2986
        var numOpenRefs uint16
2,036✔
2987
        if err := binary.Read(r, byteOrder, &numOpenRefs); err != nil {
2,036✔
2988
                return nil, err
×
2989
        }
×
2990

2991
        d.OpenedCircuitKeys = make([]models.CircuitKey, numOpenRefs)
2,036✔
2992
        for i := 0; i < int(numOpenRefs); i++ {
2,524✔
2993
                err := ReadElements(r,
488✔
2994
                        &d.OpenedCircuitKeys[i].ChanID,
488✔
2995
                        &d.OpenedCircuitKeys[i].HtlcID)
488✔
2996
                if err != nil {
488✔
2997
                        return nil, err
×
2998
                }
×
2999
        }
3000

3001
        var numClosedRefs uint16
2,036✔
3002
        if err := binary.Read(r, byteOrder, &numClosedRefs); err != nil {
2,036✔
3003
                return nil, err
×
3004
        }
×
3005

3006
        d.ClosedCircuitKeys = make([]models.CircuitKey, numClosedRefs)
2,036✔
3007
        for i := 0; i < int(numClosedRefs); i++ {
2,072✔
3008
                err := ReadElements(r,
36✔
3009
                        &d.ClosedCircuitKeys[i].ChanID,
36✔
3010
                        &d.ClosedCircuitKeys[i].HtlcID)
36✔
3011
                if err != nil {
36✔
3012
                        return nil, err
×
3013
                }
×
3014
        }
3015

3016
        // As a final step, we'll read out any aux commit data that we have at
3017
        // the end of this byte stream. We do this here to ensure backward
3018
        // compatibility, as otherwise we risk erroneously reading into the
3019
        // wrong field.
3020
        var auxData commitTlvData
2,036✔
3021
        if err := auxData.decode(r); err != nil {
2,036✔
3022
                return nil, fmt.Errorf("unable to decode aux data: %w", err)
×
3023
        }
×
3024

3025
        d.Commitment.amendTlvData(auxData)
2,036✔
3026

2,036✔
3027
        return &d, nil
2,036✔
3028
}
3029

3030
// AppendRemoteCommitChain appends a new CommitDiff to the end of the
3031
// commitment chain for the remote party. This method is to be used once we
3032
// have prepared a new commitment state for the remote party, but before we
3033
// transmit it to the remote party. The contents of the argument should be
3034
// sufficient to retransmit the updates and signature needed to reconstruct the
3035
// state in full, in the case that we need to retransmit.
3036
func (c *OpenChannel) AppendRemoteCommitChain(diff *CommitDiff) error {
2,045✔
3037
        c.Lock()
2,045✔
3038
        defer c.Unlock()
2,045✔
3039

2,045✔
3040
        // If this is a restored channel, then we want to avoid mutating the
2,045✔
3041
        // state at all, as it's impossible to do so in a protocol compliant
2,045✔
3042
        // manner.
2,045✔
3043
        if c.hasChanStatus(ChanStatusRestored) {
2,046✔
3044
                return ErrNoRestoredChannelMutation
1✔
3045
        }
1✔
3046

3047
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
4,088✔
3048
                // First, we'll grab the writable bucket where this channel's
2,044✔
3049
                // data resides.
2,044✔
3050
                chanBucket, err := fetchChanBucketRw(
2,044✔
3051
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
2,044✔
3052
                )
2,044✔
3053
                if err != nil {
2,044✔
3054
                        return err
×
3055
                }
×
3056

3057
                // If the channel is marked as borked, then for safety reasons,
3058
                // we shouldn't attempt any further updates.
3059
                isBorked, err := c.isBorked(chanBucket)
2,044✔
3060
                if err != nil {
2,044✔
3061
                        return err
×
3062
                }
×
3063
                if isBorked {
2,045✔
3064
                        return ErrChanBorked
1✔
3065
                }
1✔
3066

3067
                // Any outgoing settles and fails necessarily have a
3068
                // corresponding adds in this channel's forwarding packages.
3069
                // Mark all of these as being fully processed in our forwarding
3070
                // package, which prevents us from reprocessing them after
3071
                // startup.
3072
                err = c.Packager.AckAddHtlcs(tx, diff.AddAcks...)
2,043✔
3073
                if err != nil {
2,043✔
3074
                        return err
×
3075
                }
×
3076

3077
                // Additionally, we ack from any fails or settles that are
3078
                // persisted in another channel's forwarding package. This
3079
                // prevents the same fails and settles from being retransmitted
3080
                // after restarts. The actual fail or settle we need to
3081
                // propagate to the remote party is now in the commit diff.
3082
                err = c.Packager.AckSettleFails(tx, diff.SettleFailAcks...)
2,043✔
3083
                if err != nil {
2,043✔
3084
                        return err
×
3085
                }
×
3086

3087
                // We are sending a commitment signature so lastWasRevokeKey should
3088
                // store false.
3089
                var b bytes.Buffer
2,043✔
3090
                if err := WriteElements(&b, false); err != nil {
2,043✔
3091
                        return err
×
3092
                }
×
3093
                if err := chanBucket.Put(lastWasRevokeKey, b.Bytes()); err != nil {
2,043✔
3094
                        return err
×
3095
                }
×
3096

3097
                // TODO(roasbeef): use seqno to derive key for later LCP
3098

3099
                // With the bucket retrieved, we'll now serialize the commit
3100
                // diff itself, and write it to disk.
3101
                var b2 bytes.Buffer
2,043✔
3102
                if err := serializeCommitDiff(&b2, diff); err != nil {
2,043✔
3103
                        return err
×
3104
                }
×
3105
                return chanBucket.Put(commitDiffKey, b2.Bytes())
2,043✔
3106
        }, func() {})
2,044✔
3107
}
3108

3109
// RemoteCommitChainTip returns the "tip" of the current remote commitment
3110
// chain. This value will be non-nil iff, we've created a new commitment for
3111
// the remote party that they haven't yet ACK'd. In this case, their commitment
3112
// chain will have a length of two: their current unrevoked commitment, and
3113
// this new pending commitment. Once they revoked their prior state, we'll swap
3114
// these pointers, causing the tip and the tail to point to the same entry.
3115
func (c *OpenChannel) RemoteCommitChainTip() (*CommitDiff, error) {
1,243✔
3116
        var cd *CommitDiff
1,243✔
3117
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2,486✔
3118
                chanBucket, err := fetchChanBucket(
1,243✔
3119
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1,243✔
3120
                )
1,243✔
3121
                switch err {
1,243✔
3122
                case nil:
869✔
3123
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
374✔
3124
                        return ErrNoPendingCommit
374✔
3125
                default:
×
3126
                        return err
×
3127
                }
3128

3129
                tipBytes := chanBucket.Get(commitDiffKey)
869✔
3130
                if tipBytes == nil {
1,657✔
3131
                        return ErrNoPendingCommit
788✔
3132
                }
788✔
3133

3134
                tipReader := bytes.NewReader(tipBytes)
81✔
3135
                dcd, err := deserializeCommitDiff(tipReader)
81✔
3136
                if err != nil {
81✔
3137
                        return err
×
3138
                }
×
3139

3140
                cd = dcd
81✔
3141
                return nil
81✔
3142
        }, func() {
1,243✔
3143
                cd = nil
1,243✔
3144
        })
1,243✔
3145
        if err != nil {
2,405✔
3146
                return nil, err
1,162✔
3147
        }
1,162✔
3148

3149
        return cd, err
81✔
3150
}
3151

3152
// UnsignedAckedUpdates retrieves the persisted unsigned acked remote log
3153
// updates that still need to be signed for.
3154
func (c *OpenChannel) UnsignedAckedUpdates() ([]LogUpdate, error) {
809✔
3155
        var updates []LogUpdate
809✔
3156
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
1,618✔
3157
                chanBucket, err := fetchChanBucket(
809✔
3158
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
809✔
3159
                )
809✔
3160
                switch err {
809✔
3161
                case nil:
435✔
3162
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
374✔
3163
                        return nil
374✔
3164
                default:
×
3165
                        return err
×
3166
                }
3167

3168
                updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
435✔
3169
                if updateBytes == nil {
797✔
3170
                        return nil
362✔
3171
                }
362✔
3172

3173
                r := bytes.NewReader(updateBytes)
73✔
3174
                updates, err = deserializeLogUpdates(r)
73✔
3175
                return err
73✔
3176
        }, func() {
809✔
3177
                updates = nil
809✔
3178
        })
809✔
3179
        if err != nil {
809✔
3180
                return nil, err
×
3181
        }
×
3182

3183
        return updates, nil
809✔
3184
}
3185

3186
// RemoteUnsignedLocalUpdates retrieves the persisted, unsigned local log
3187
// updates that the remote still needs to sign for.
3188
func (c *OpenChannel) RemoteUnsignedLocalUpdates() ([]LogUpdate, error) {
808✔
3189
        var updates []LogUpdate
808✔
3190
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
1,616✔
3191
                chanBucket, err := fetchChanBucket(
808✔
3192
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
808✔
3193
                )
808✔
3194
                switch err {
808✔
3195
                case nil:
434✔
3196
                        break
434✔
3197
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
374✔
3198
                        return nil
374✔
3199
                default:
×
3200
                        return err
×
3201
                }
3202

3203
                updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
434✔
3204
                if updateBytes == nil {
827✔
3205
                        return nil
393✔
3206
                }
393✔
3207

3208
                r := bytes.NewReader(updateBytes)
41✔
3209
                updates, err = deserializeLogUpdates(r)
41✔
3210
                return err
41✔
3211
        }, func() {
808✔
3212
                updates = nil
808✔
3213
        })
808✔
3214
        if err != nil {
808✔
3215
                return nil, err
×
3216
        }
×
3217

3218
        return updates, nil
808✔
3219
}
3220

3221
// InsertNextRevocation inserts the _next_ commitment point (revocation) into
3222
// the database, and also modifies the internal RemoteNextRevocation attribute
3223
// to point to the passed key. This method is to be using during final channel
3224
// set up, _after_ the channel has been fully confirmed.
3225
//
3226
// NOTE: If this method isn't called, then the target channel won't be able to
3227
// propose new states for the commitment state of the remote party.
3228
func (c *OpenChannel) InsertNextRevocation(revKey *btcec.PublicKey) error {
626✔
3229
        c.Lock()
626✔
3230
        defer c.Unlock()
626✔
3231

626✔
3232
        c.RemoteNextRevocation = revKey
626✔
3233

626✔
3234
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
1,252✔
3235
                chanBucket, err := fetchChanBucketRw(
626✔
3236
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
626✔
3237
                )
626✔
3238
                if err != nil {
626✔
3239
                        return err
×
3240
                }
×
3241

3242
                return putChanRevocationState(chanBucket, c)
626✔
3243
        }, func() {})
626✔
3244
        if err != nil {
626✔
3245
                return err
×
3246
        }
×
3247

3248
        return nil
626✔
3249
}
3250

3251
// AdvanceCommitChainTail records the new state transition within an on-disk
3252
// append-only log which records all state transitions by the remote peer. In
3253
// the case of an uncooperative broadcast of a prior state by the remote peer,
3254
// this log can be consulted in order to reconstruct the state needed to
3255
// rectify the situation. This method will add the current commitment for the
3256
// remote party to the revocation log, and promote the current pending
3257
// commitment to the current remote commitment. The updates parameter is the
3258
// set of local updates that the peer still needs to send us a signature for.
3259
// We store this set of updates in case we go down.
3260
func (c *OpenChannel) AdvanceCommitChainTail(fwdPkg *FwdPkg,
3261
        updates []LogUpdate, ourOutputIndex, theirOutputIndex uint32) error {
1,957✔
3262

1,957✔
3263
        c.Lock()
1,957✔
3264
        defer c.Unlock()
1,957✔
3265

1,957✔
3266
        // If this is a restored channel, then we want to avoid mutating the
1,957✔
3267
        // state at all, as it's impossible to do so in a protocol compliant
1,957✔
3268
        // manner.
1,957✔
3269
        if c.hasChanStatus(ChanStatusRestored) {
1,958✔
3270
                return ErrNoRestoredChannelMutation
1✔
3271
        }
1✔
3272

3273
        var newRemoteCommit *ChannelCommitment
1,956✔
3274

1,956✔
3275
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
3,912✔
3276
                chanBucket, err := fetchChanBucketRw(
1,956✔
3277
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1,956✔
3278
                )
1,956✔
3279
                if err != nil {
1,956✔
3280
                        return err
×
3281
                }
×
3282

3283
                // If the channel is marked as borked, then for safety reasons,
3284
                // we shouldn't attempt any further updates.
3285
                isBorked, err := c.isBorked(chanBucket)
1,956✔
3286
                if err != nil {
1,956✔
3287
                        return err
×
3288
                }
×
3289
                if isBorked {
1,957✔
3290
                        return ErrChanBorked
1✔
3291
                }
1✔
3292

3293
                // Persist the latest preimage state to disk as the remote peer
3294
                // has just added to our local preimage store, and given us a
3295
                // new pending revocation key.
3296
                if err := putChanRevocationState(chanBucket, c); err != nil {
1,955✔
3297
                        return err
×
3298
                }
×
3299

3300
                // With the current preimage producer/store state updated,
3301
                // append a new log entry recording this the delta of this
3302
                // state transition.
3303
                //
3304
                // TODO(roasbeef): could make the deltas relative, would save
3305
                // space, but then tradeoff for more disk-seeks to recover the
3306
                // full state.
3307
                logKey := revocationLogBucket
1,955✔
3308
                logBucket, err := chanBucket.CreateBucketIfNotExists(logKey)
1,955✔
3309
                if err != nil {
1,955✔
3310
                        return err
×
3311
                }
×
3312

3313
                // Before we append this revoked state to the revocation log,
3314
                // we'll swap out what's currently the tail of the commit tip,
3315
                // with the current locked-in commitment for the remote party.
3316
                tipBytes := chanBucket.Get(commitDiffKey)
1,955✔
3317
                tipReader := bytes.NewReader(tipBytes)
1,955✔
3318
                newCommit, err := deserializeCommitDiff(tipReader)
1,955✔
3319
                if err != nil {
1,955✔
3320
                        return err
×
3321
                }
×
3322
                err = putChanCommitment(
1,955✔
3323
                        chanBucket, &newCommit.Commitment, false,
1,955✔
3324
                )
1,955✔
3325
                if err != nil {
1,955✔
3326
                        return err
×
3327
                }
×
3328
                if err := chanBucket.Delete(commitDiffKey); err != nil {
1,955✔
3329
                        return err
×
3330
                }
×
3331

3332
                // With the commitment pointer swapped, we can now add the
3333
                // revoked (prior) state to the revocation log.
3334
                err = putRevocationLog(
1,955✔
3335
                        logBucket, &c.RemoteCommitment, ourOutputIndex,
1,955✔
3336
                        theirOutputIndex, c.Db.parent.noRevLogAmtData,
1,955✔
3337
                )
1,955✔
3338
                if err != nil {
1,955✔
3339
                        return err
×
3340
                }
×
3341

3342
                // Lastly, we write the forwarding package to disk so that we
3343
                // can properly recover from failures and reforward HTLCs that
3344
                // have not received a corresponding settle/fail.
3345
                if err := c.Packager.AddFwdPkg(tx, fwdPkg); err != nil {
1,955✔
3346
                        return err
×
3347
                }
×
3348

3349
                // Persist the unsigned acked updates that are not included
3350
                // in their new commitment.
3351
                updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
1,955✔
3352
                if updateBytes == nil {
2,164✔
3353
                        // This shouldn't normally happen as we always store
209✔
3354
                        // the number of updates, but could still be
209✔
3355
                        // encountered by nodes that are upgrading.
209✔
3356
                        newRemoteCommit = &newCommit.Commitment
209✔
3357
                        return nil
209✔
3358
                }
209✔
3359

3360
                r := bytes.NewReader(updateBytes)
1,746✔
3361
                unsignedUpdates, err := deserializeLogUpdates(r)
1,746✔
3362
                if err != nil {
1,746✔
3363
                        return err
×
3364
                }
×
3365

3366
                var validUpdates []LogUpdate
1,746✔
3367
                for _, upd := range unsignedUpdates {
3,129✔
3368
                        lIdx := upd.LogIndex
1,383✔
3369

1,383✔
3370
                        // Filter for updates that are not on the remote
1,383✔
3371
                        // commitment.
1,383✔
3372
                        if lIdx >= newCommit.Commitment.RemoteLogIndex {
1,511✔
3373
                                validUpdates = append(validUpdates, upd)
128✔
3374
                        }
128✔
3375
                }
3376

3377
                var b bytes.Buffer
1,746✔
3378
                err = serializeLogUpdates(&b, validUpdates)
1,746✔
3379
                if err != nil {
1,746✔
3380
                        return fmt.Errorf("unable to serialize log updates: %w",
×
3381
                                err)
×
3382
                }
×
3383

3384
                err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes())
1,746✔
3385
                if err != nil {
1,746✔
3386
                        return fmt.Errorf("unable to store under "+
×
3387
                                "unsignedAckedUpdatesKey: %w", err)
×
3388
                }
×
3389

3390
                // Persist the local updates the peer hasn't yet signed so they
3391
                // can be restored after restart.
3392
                var b2 bytes.Buffer
1,746✔
3393
                err = serializeLogUpdates(&b2, updates)
1,746✔
3394
                if err != nil {
1,746✔
3395
                        return err
×
3396
                }
×
3397

3398
                err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b2.Bytes())
1,746✔
3399
                if err != nil {
1,746✔
3400
                        return fmt.Errorf("unable to restore remote unsigned "+
×
3401
                                "local updates: %v", err)
×
3402
                }
×
3403

3404
                newRemoteCommit = &newCommit.Commitment
1,746✔
3405

1,746✔
3406
                return nil
1,746✔
3407
        }, func() {
1,956✔
3408
                newRemoteCommit = nil
1,956✔
3409
        })
1,956✔
3410
        if err != nil {
1,957✔
3411
                return err
1✔
3412
        }
1✔
3413

3414
        // With the db transaction complete, we'll swap over the in-memory
3415
        // pointer of the new remote commitment, which was previously the tip
3416
        // of the commit chain.
3417
        c.RemoteCommitment = *newRemoteCommit
1,955✔
3418

1,955✔
3419
        return nil
1,955✔
3420
}
3421

3422
// FinalHtlcInfo contains information about the final outcome of an htlc.
3423
type FinalHtlcInfo struct {
3424
        // Settled is true is the htlc was settled. If false, the htlc was
3425
        // failed.
3426
        Settled bool
3427

3428
        // Offchain indicates whether the htlc was resolved off-chain or
3429
        // on-chain.
3430
        Offchain bool
3431
}
3432

3433
// putFinalHtlc writes the final htlc outcome to the database. Additionally it
3434
// records whether the htlc was resolved off-chain or on-chain.
3435
func putFinalHtlc(finalHtlcsBucket kvdb.RwBucket, id uint64,
3436
        info FinalHtlcInfo) error {
3✔
3437

3✔
3438
        var key [8]byte
3✔
3439
        byteOrder.PutUint64(key[:], id)
3✔
3440

3✔
3441
        var finalHtlcByte FinalHtlcByte
3✔
3442
        if info.Settled {
6✔
3443
                finalHtlcByte |= FinalHtlcSettledBit
3✔
3444
        }
3✔
3445
        if info.Offchain {
5✔
3446
                finalHtlcByte |= FinalHtlcOffchainBit
2✔
3447
        }
2✔
3448

3449
        return finalHtlcsBucket.Put(key[:], []byte{byte(finalHtlcByte)})
3✔
3450
}
3451

3452
// NextLocalHtlcIndex returns the next unallocated local htlc index. To ensure
3453
// this always returns the next index that has been not been allocated, this
3454
// will first try to examine any pending commitments, before falling back to the
3455
// last locked-in remote commitment.
3456
func (c *OpenChannel) NextLocalHtlcIndex() (uint64, error) {
379✔
3457
        // First, load the most recent commit diff that we initiated for the
379✔
3458
        // remote party. If no pending commit is found, this is not treated as
379✔
3459
        // a critical error, since we can always fall back.
379✔
3460
        pendingRemoteCommit, err := c.RemoteCommitChainTip()
379✔
3461
        if err != nil && err != ErrNoPendingCommit {
379✔
3462
                return 0, err
×
3463
        }
×
3464

3465
        // If a pending commit was found, its local htlc index will be at least
3466
        // as large as the one on our local commitment.
3467
        if pendingRemoteCommit != nil {
395✔
3468
                return pendingRemoteCommit.Commitment.LocalHtlcIndex, nil
16✔
3469
        }
16✔
3470

3471
        // Otherwise, fallback to using the local htlc index of their commitment.
3472
        return c.RemoteCommitment.LocalHtlcIndex, nil
363✔
3473
}
3474

3475
// LoadFwdPkgs scans the forwarding log for any packages that haven't been
3476
// processed, and returns their deserialized log updates in map indexed by the
3477
// remote commitment height at which the updates were locked in.
3478
func (c *OpenChannel) LoadFwdPkgs() ([]*FwdPkg, error) {
445✔
3479
        c.RLock()
445✔
3480
        defer c.RUnlock()
445✔
3481

445✔
3482
        var fwdPkgs []*FwdPkg
445✔
3483
        if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
875✔
3484
                var err error
430✔
3485
                fwdPkgs, err = c.Packager.LoadFwdPkgs(tx)
430✔
3486
                return err
430✔
3487
        }, func() {
875✔
3488
                fwdPkgs = nil
445✔
3489
        }); err != nil {
460✔
3490
                return nil, err
15✔
3491
        }
15✔
3492

3493
        return fwdPkgs, nil
430✔
3494
}
3495

3496
// AckAddHtlcs updates the AckAddFilter containing any of the provided AddRefs
3497
// indicating that a response to this Add has been committed to the remote party.
3498
// Doing so will prevent these Add HTLCs from being reforwarded internally.
3499
func (c *OpenChannel) AckAddHtlcs(addRefs ...AddRef) error {
1✔
3500
        c.Lock()
1✔
3501
        defer c.Unlock()
1✔
3502

1✔
3503
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
3504
                return c.Packager.AckAddHtlcs(tx, addRefs...)
1✔
3505
        }, func() {})
2✔
3506
}
3507

3508
// AckSettleFails updates the SettleFailFilter containing any of the provided
3509
// SettleFailRefs, indicating that the response has been delivered to the
3510
// incoming link, corresponding to a particular AddRef. Doing so will prevent
3511
// the responses from being retransmitted internally.
3512
func (c *OpenChannel) AckSettleFails(settleFailRefs ...SettleFailRef) error {
×
3513
        c.Lock()
×
3514
        defer c.Unlock()
×
3515

×
3516
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
3517
                return c.Packager.AckSettleFails(tx, settleFailRefs...)
×
3518
        }, func() {})
×
3519
}
3520

3521
// SetFwdFilter atomically sets the forwarding filter for the forwarding package
3522
// identified by `height`.
3523
func (c *OpenChannel) SetFwdFilter(height uint64, fwdFilter *PkgFilter) error {
1,173✔
3524
        c.Lock()
1,173✔
3525
        defer c.Unlock()
1,173✔
3526

1,173✔
3527
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2,346✔
3528
                return c.Packager.SetFwdFilter(tx, height, fwdFilter)
1,173✔
3529
        }, func() {})
2,346✔
3530
}
3531

3532
// RemoveFwdPkgs atomically removes forwarding packages specified by the remote
3533
// commitment heights. If one of the intermediate RemovePkg calls fails, then the
3534
// later packages won't be removed.
3535
//
3536
// NOTE: This method should only be called on packages marked FwdStateCompleted.
3537
func (c *OpenChannel) RemoveFwdPkgs(heights ...uint64) error {
1✔
3538
        c.Lock()
1✔
3539
        defer c.Unlock()
1✔
3540

1✔
3541
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
3542
                for _, height := range heights {
2✔
3543
                        err := c.Packager.RemovePkg(tx, height)
1✔
3544
                        if err != nil {
1✔
3545
                                return err
×
3546
                        }
×
3547
                }
3548

3549
                return nil
1✔
3550
        }, func() {})
1✔
3551
}
3552

3553
// revocationLogTailCommitHeight returns the commit height at the end of the
3554
// revocation log. This entry represents the last previous state for the remote
3555
// node's commitment chain. The ChannelDelta returned by this method will
3556
// always lag one state behind the most current (unrevoked) state of the remote
3557
// node's commitment chain.
3558
// NOTE: used in unit test only.
3559
func (c *OpenChannel) revocationLogTailCommitHeight() (uint64, error) {
2✔
3560
        c.RLock()
2✔
3561
        defer c.RUnlock()
2✔
3562

2✔
3563
        var height uint64
2✔
3564

2✔
3565
        // If we haven't created any state updates yet, then we'll exit early as
2✔
3566
        // there's nothing to be found on disk in the revocation bucket.
2✔
3567
        if c.RemoteCommitment.CommitHeight == 0 {
2✔
3568
                return height, nil
×
3569
        }
×
3570

3571
        if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
4✔
3572
                chanBucket, err := fetchChanBucket(
2✔
3573
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
2✔
3574
                )
2✔
3575
                if err != nil {
2✔
3576
                        return err
×
3577
                }
×
3578

3579
                logBucket, err := fetchLogBucket(chanBucket)
2✔
3580
                if err != nil {
2✔
3581
                        return err
×
3582
                }
×
3583

3584
                // Once we have the bucket that stores the revocation log from
3585
                // this channel, we'll jump to the _last_ key in bucket. Since
3586
                // the key is the commit height, we'll decode the bytes and
3587
                // return it.
3588
                cursor := logBucket.ReadCursor()
2✔
3589
                rawHeight, _ := cursor.Last()
2✔
3590
                height = byteOrder.Uint64(rawHeight)
2✔
3591

2✔
3592
                return nil
2✔
3593
        }, func() {}); err != nil {
2✔
3594
                return height, err
×
3595
        }
×
3596

3597
        return height, nil
2✔
3598
}
3599

3600
// CommitmentHeight returns the current commitment height. The commitment
3601
// height represents the number of updates to the commitment state to date.
3602
// This value is always monotonically increasing. This method is provided in
3603
// order to allow multiple instances of a particular open channel to obtain a
3604
// consistent view of the number of channel updates to date.
3605
func (c *OpenChannel) CommitmentHeight() (uint64, error) {
1✔
3606
        c.RLock()
1✔
3607
        defer c.RUnlock()
1✔
3608

1✔
3609
        var height uint64
1✔
3610
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2✔
3611
                // Get the bucket dedicated to storing the metadata for open
1✔
3612
                // channels.
1✔
3613
                chanBucket, err := fetchChanBucket(
1✔
3614
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
3615
                )
1✔
3616
                if err != nil {
1✔
3617
                        return err
×
3618
                }
×
3619

3620
                commit, err := fetchChanCommitment(chanBucket, true)
1✔
3621
                if err != nil {
1✔
3622
                        return err
×
3623
                }
×
3624

3625
                height = commit.CommitHeight
1✔
3626
                return nil
1✔
3627
        }, func() {
1✔
3628
                height = 0
1✔
3629
        })
1✔
3630
        if err != nil {
1✔
3631
                return 0, err
×
3632
        }
×
3633

3634
        return height, nil
1✔
3635
}
3636

3637
// FindPreviousState scans through the append-only log in an attempt to recover
3638
// the previous channel state indicated by the update number. This method is
3639
// intended to be used for obtaining the relevant data needed to claim all
3640
// funds rightfully spendable in the case of an on-chain broadcast of the
3641
// commitment transaction.
3642
func (c *OpenChannel) FindPreviousState(
3643
        updateNum uint64) (*RevocationLog, *ChannelCommitment, error) {
31✔
3644

31✔
3645
        c.RLock()
31✔
3646
        defer c.RUnlock()
31✔
3647

31✔
3648
        commit := &ChannelCommitment{}
31✔
3649
        rl := &RevocationLog{}
31✔
3650

31✔
3651
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
62✔
3652
                chanBucket, err := fetchChanBucket(
31✔
3653
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
31✔
3654
                )
31✔
3655
                if err != nil {
32✔
3656
                        return err
1✔
3657
                }
1✔
3658

3659
                // Find the revocation log from both the new and the old
3660
                // bucket.
3661
                r, c, err := fetchRevocationLogCompatible(chanBucket, updateNum)
30✔
3662
                if err != nil {
49✔
3663
                        return err
19✔
3664
                }
19✔
3665

3666
                rl = r
11✔
3667
                commit = c
11✔
3668
                return nil
11✔
3669
        }, func() {})
31✔
3670
        if err != nil {
51✔
3671
                return nil, nil, err
20✔
3672
        }
20✔
3673

3674
        // Either the `rl` or the `commit` is nil here. We return them as-is
3675
        // and leave it to the caller to decide its following action.
3676
        return rl, commit, nil
11✔
3677
}
3678

3679
// ClosureType is an enum like structure that details exactly _how_ a channel
3680
// was closed. Three closure types are currently possible: none, cooperative,
3681
// local force close, remote force close, and (remote) breach.
3682
type ClosureType uint8
3683

3684
const (
3685
        // CooperativeClose indicates that a channel has been closed
3686
        // cooperatively.  This means that both channel peers were online and
3687
        // signed a new transaction paying out the settled balance of the
3688
        // contract.
3689
        CooperativeClose ClosureType = 0
3690

3691
        // LocalForceClose indicates that we have unilaterally broadcast our
3692
        // current commitment state on-chain.
3693
        LocalForceClose ClosureType = 1
3694

3695
        // RemoteForceClose indicates that the remote peer has unilaterally
3696
        // broadcast their current commitment state on-chain.
3697
        RemoteForceClose ClosureType = 4
3698

3699
        // BreachClose indicates that the remote peer attempted to broadcast a
3700
        // prior _revoked_ channel state.
3701
        BreachClose ClosureType = 2
3702

3703
        // FundingCanceled indicates that the channel never was fully opened
3704
        // before it was marked as closed in the database. This can happen if
3705
        // we or the remote fail at some point during the opening workflow, or
3706
        // we timeout waiting for the funding transaction to be confirmed.
3707
        FundingCanceled ClosureType = 3
3708

3709
        // Abandoned indicates that the channel state was removed without
3710
        // any further actions. This is intended to clean up unusable
3711
        // channels during development.
3712
        Abandoned ClosureType = 5
3713
)
3714

3715
// ChannelCloseSummary contains the final state of a channel at the point it
3716
// was closed. Once a channel is closed, all the information pertaining to that
3717
// channel within the openChannelBucket is deleted, and a compact summary is
3718
// put in place instead.
3719
type ChannelCloseSummary struct {
3720
        // ChanPoint is the outpoint for this channel's funding transaction,
3721
        // and is used as a unique identifier for the channel.
3722
        ChanPoint wire.OutPoint
3723

3724
        // ShortChanID encodes the exact location in the chain in which the
3725
        // channel was initially confirmed. This includes: the block height,
3726
        // transaction index, and the output within the target transaction.
3727
        ShortChanID lnwire.ShortChannelID
3728

3729
        // ChainHash is the hash of the genesis block that this channel resides
3730
        // within.
3731
        ChainHash chainhash.Hash
3732

3733
        // ClosingTXID is the txid of the transaction which ultimately closed
3734
        // this channel.
3735
        ClosingTXID chainhash.Hash
3736

3737
        // RemotePub is the public key of the remote peer that we formerly had
3738
        // a channel with.
3739
        RemotePub *btcec.PublicKey
3740

3741
        // Capacity was the total capacity of the channel.
3742
        Capacity btcutil.Amount
3743

3744
        // CloseHeight is the height at which the funding transaction was
3745
        // spent.
3746
        CloseHeight uint32
3747

3748
        // SettledBalance is our total balance settled balance at the time of
3749
        // channel closure. This _does not_ include the sum of any outputs that
3750
        // have been time-locked as a result of the unilateral channel closure.
3751
        SettledBalance btcutil.Amount
3752

3753
        // TimeLockedBalance is the sum of all the time-locked outputs at the
3754
        // time of channel closure. If we triggered the force closure of this
3755
        // channel, then this value will be non-zero if our settled output is
3756
        // above the dust limit. If we were on the receiving side of a channel
3757
        // force closure, then this value will be non-zero if we had any
3758
        // outstanding outgoing HTLC's at the time of channel closure.
3759
        TimeLockedBalance btcutil.Amount
3760

3761
        // CloseType details exactly _how_ the channel was closed. Five closure
3762
        // types are possible: cooperative, local force, remote force, breach
3763
        // and funding canceled.
3764
        CloseType ClosureType
3765

3766
        // IsPending indicates whether this channel is in the 'pending close'
3767
        // state, which means the channel closing transaction has been
3768
        // confirmed, but not yet been fully resolved. In the case of a channel
3769
        // that has been cooperatively closed, it will go straight into the
3770
        // fully resolved state as soon as the closing transaction has been
3771
        // confirmed. However, for channels that have been force closed, they'll
3772
        // stay marked as "pending" until _all_ the pending funds have been
3773
        // swept.
3774
        IsPending bool
3775

3776
        // RemoteCurrentRevocation is the current revocation for their
3777
        // commitment transaction. However, since this is the derived public key,
3778
        // we don't yet have the private key so we aren't yet able to verify
3779
        // that it's actually in the hash chain.
3780
        RemoteCurrentRevocation *btcec.PublicKey
3781

3782
        // RemoteNextRevocation is the revocation key to be used for the *next*
3783
        // commitment transaction we create for the local node. Within the
3784
        // specification, this value is referred to as the
3785
        // per-commitment-point.
3786
        RemoteNextRevocation *btcec.PublicKey
3787

3788
        // LocalChanConfig is the channel configuration for the local node.
3789
        LocalChanConfig ChannelConfig
3790

3791
        // LastChanSyncMsg is the ChannelReestablish message for this channel
3792
        // for the state at the point where it was closed.
3793
        LastChanSyncMsg *lnwire.ChannelReestablish
3794
}
3795

3796
// CloseChannel closes a previously active Lightning channel. Closing a channel
3797
// entails deleting all saved state within the database concerning this
3798
// channel. This method also takes a struct that summarizes the state of the
3799
// channel at closing, this compact representation will be the only component
3800
// of a channel left over after a full closing. It takes an optional set of
3801
// channel statuses which will be written to the historical channel bucket.
3802
// These statuses are used to record close initiators.
3803
func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary,
3804
        statuses ...ChannelStatus) error {
114✔
3805

114✔
3806
        c.Lock()
114✔
3807
        defer c.Unlock()
114✔
3808

114✔
3809
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
228✔
3810
                openChanBucket := tx.ReadWriteBucket(openChannelBucket)
114✔
3811
                if openChanBucket == nil {
114✔
3812
                        return ErrNoChanDBExists
×
3813
                }
×
3814

3815
                nodePub := c.IdentityPub.SerializeCompressed()
114✔
3816
                nodeChanBucket := openChanBucket.NestedReadWriteBucket(nodePub)
114✔
3817
                if nodeChanBucket == nil {
114✔
3818
                        return ErrNoActiveChannels
×
3819
                }
×
3820

3821
                chainBucket := nodeChanBucket.NestedReadWriteBucket(c.ChainHash[:])
114✔
3822
                if chainBucket == nil {
114✔
3823
                        return ErrNoActiveChannels
×
3824
                }
×
3825

3826
                var chanPointBuf bytes.Buffer
114✔
3827
                err := graphdb.WriteOutpoint(&chanPointBuf, &c.FundingOutpoint)
114✔
3828
                if err != nil {
114✔
3829
                        return err
×
3830
                }
×
3831
                chanKey := chanPointBuf.Bytes()
114✔
3832
                chanBucket := chainBucket.NestedReadWriteBucket(
114✔
3833
                        chanKey,
114✔
3834
                )
114✔
3835
                if chanBucket == nil {
114✔
3836
                        return ErrNoActiveChannels
×
3837
                }
×
3838

3839
                // Before we delete the channel state, we'll read out the full
3840
                // details, as we'll also store portions of this information
3841
                // for record keeping.
3842
                chanState, err := fetchOpenChannel(
114✔
3843
                        chanBucket, &c.FundingOutpoint,
114✔
3844
                )
114✔
3845
                if err != nil {
114✔
3846
                        return err
×
3847
                }
×
3848

3849
                // Delete all the forwarding packages stored for this particular
3850
                // channel.
3851
                if err = chanState.Packager.Wipe(tx); err != nil {
114✔
3852
                        return err
×
3853
                }
×
3854

3855
                // Now that the index to this channel has been deleted, purge
3856
                // the remaining channel metadata from the database.
3857
                err = deleteOpenChannel(chanBucket)
114✔
3858
                if err != nil {
114✔
3859
                        return err
×
3860
                }
×
3861

3862
                // We'll also remove the channel from the frozen channel bucket
3863
                // if we need to.
3864
                if c.ChanType.IsFrozen() || c.ChanType.HasLeaseExpiration() {
221✔
3865
                        err := deleteThawHeight(chanBucket)
107✔
3866
                        if err != nil {
107✔
3867
                                return err
×
3868
                        }
×
3869
                }
3870

3871
                // With the base channel data deleted, attempt to delete the
3872
                // information stored within the revocation log.
3873
                if err := deleteLogBucket(chanBucket); err != nil {
114✔
3874
                        return err
×
3875
                }
×
3876

3877
                err = chainBucket.DeleteNestedBucket(chanPointBuf.Bytes())
114✔
3878
                if err != nil {
114✔
3879
                        return err
×
3880
                }
×
3881

3882
                // Fetch the outpoint bucket to see if the outpoint exists or
3883
                // not.
3884
                opBucket := tx.ReadWriteBucket(outpointBucket)
114✔
3885
                if opBucket == nil {
114✔
3886
                        return ErrNoChanDBExists
×
3887
                }
×
3888

3889
                // Add the closed outpoint to our outpoint index. This should
3890
                // replace an open outpoint in the index.
3891
                if opBucket.Get(chanPointBuf.Bytes()) == nil {
114✔
3892
                        return ErrMissingIndexEntry
×
3893
                }
×
3894

3895
                status := uint8(outpointClosed)
114✔
3896

114✔
3897
                // Write the IndexStatus of this outpoint as the first entry in a tlv
114✔
3898
                // stream.
114✔
3899
                statusRecord := tlv.MakePrimitiveRecord(indexStatusType, &status)
114✔
3900
                opStream, err := tlv.NewStream(statusRecord)
114✔
3901
                if err != nil {
114✔
3902
                        return err
×
3903
                }
×
3904

3905
                var b bytes.Buffer
114✔
3906
                if err := opStream.Encode(&b); err != nil {
114✔
3907
                        return err
×
3908
                }
×
3909

3910
                // Finally add the closed outpoint and tlv stream to the index.
3911
                if err := opBucket.Put(chanPointBuf.Bytes(), b.Bytes()); err != nil {
114✔
3912
                        return err
×
3913
                }
×
3914

3915
                // Add channel state to the historical channel bucket.
3916
                historicalBucket, err := tx.CreateTopLevelBucket(
114✔
3917
                        historicalChannelBucket,
114✔
3918
                )
114✔
3919
                if err != nil {
114✔
3920
                        return err
×
3921
                }
×
3922

3923
                historicalChanBucket, err :=
114✔
3924
                        historicalBucket.CreateBucketIfNotExists(chanKey)
114✔
3925
                if err != nil {
114✔
3926
                        return err
×
3927
                }
×
3928

3929
                // Apply any additional statuses to the channel state.
3930
                for _, status := range statuses {
119✔
3931
                        chanState.chanStatus |= status
5✔
3932
                }
5✔
3933

3934
                err = putOpenChannel(historicalChanBucket, chanState)
114✔
3935
                if err != nil {
114✔
3936
                        return err
×
3937
                }
×
3938

3939
                // Finally, create a summary of this channel in the closed
3940
                // channel bucket for this node.
3941
                return putChannelCloseSummary(
114✔
3942
                        tx, chanPointBuf.Bytes(), summary, chanState,
114✔
3943
                )
114✔
3944
        }, func() {})
114✔
3945
}
3946

3947
// ChannelSnapshot is a frozen snapshot of the current channel state. A
3948
// snapshot is detached from the original channel that generated it, providing
3949
// read-only access to the current or prior state of an active channel.
3950
//
3951
// TODO(roasbeef): remove all together? pretty much just commitment
3952
type ChannelSnapshot struct {
3953
        // RemoteIdentity is the identity public key of the remote node that we
3954
        // are maintaining the open channel with.
3955
        RemoteIdentity btcec.PublicKey
3956

3957
        // ChanPoint is the outpoint that created the channel. This output is
3958
        // found within the funding transaction and uniquely identified the
3959
        // channel on the resident chain.
3960
        ChannelPoint wire.OutPoint
3961

3962
        // ChainHash is the genesis hash of the chain that the channel resides
3963
        // within.
3964
        ChainHash chainhash.Hash
3965

3966
        // Capacity is the total capacity of the channel.
3967
        Capacity btcutil.Amount
3968

3969
        // TotalMSatSent is the total number of milli-satoshis we've sent
3970
        // within this channel.
3971
        TotalMSatSent lnwire.MilliSatoshi
3972

3973
        // TotalMSatReceived is the total number of milli-satoshis we've
3974
        // received within this channel.
3975
        TotalMSatReceived lnwire.MilliSatoshi
3976

3977
        // ChannelCommitment is the current up-to-date commitment for the
3978
        // target channel.
3979
        ChannelCommitment
3980
}
3981

3982
// Snapshot returns a read-only snapshot of the current channel state. This
3983
// snapshot includes information concerning the current settled balance within
3984
// the channel, metadata detailing total flows, and any outstanding HTLCs.
3985
func (c *OpenChannel) Snapshot() *ChannelSnapshot {
72✔
3986
        c.RLock()
72✔
3987
        defer c.RUnlock()
72✔
3988

72✔
3989
        localCommit := c.LocalCommitment
72✔
3990
        snapshot := &ChannelSnapshot{
72✔
3991
                RemoteIdentity:    *c.IdentityPub,
72✔
3992
                ChannelPoint:      c.FundingOutpoint,
72✔
3993
                Capacity:          c.Capacity,
72✔
3994
                TotalMSatSent:     c.TotalMSatSent,
72✔
3995
                TotalMSatReceived: c.TotalMSatReceived,
72✔
3996
                ChainHash:         c.ChainHash,
72✔
3997
                ChannelCommitment: ChannelCommitment{
72✔
3998
                        LocalBalance:  localCommit.LocalBalance,
72✔
3999
                        RemoteBalance: localCommit.RemoteBalance,
72✔
4000
                        CommitHeight:  localCommit.CommitHeight,
72✔
4001
                        CommitFee:     localCommit.CommitFee,
72✔
4002
                },
72✔
4003
        }
72✔
4004

72✔
4005
        localCommit.CustomBlob.WhenSome(func(blob tlv.Blob) {
72✔
4006
                blobCopy := make([]byte, len(blob))
×
4007
                copy(blobCopy, blob)
×
4008

×
4009
                snapshot.ChannelCommitment.CustomBlob = fn.Some(blobCopy)
×
4010
        })
×
4011

4012
        // Copy over the current set of HTLCs to ensure the caller can't mutate
4013
        // our internal state.
4014
        snapshot.Htlcs = make([]HTLC, len(localCommit.Htlcs))
72✔
4015
        for i, h := range localCommit.Htlcs {
339✔
4016
                snapshot.Htlcs[i] = h.Copy()
267✔
4017
        }
267✔
4018

4019
        return snapshot
72✔
4020
}
4021

4022
// LatestCommitments returns the two latest commitments for both the local and
4023
// remote party. These commitments are read from disk to ensure that only the
4024
// latest fully committed state is returned. The first commitment returned is
4025
// the local commitment, and the second returned is the remote commitment.
4026
func (c *OpenChannel) LatestCommitments() (*ChannelCommitment, *ChannelCommitment, error) {
15✔
4027
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
30✔
4028
                chanBucket, err := fetchChanBucket(
15✔
4029
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
15✔
4030
                )
15✔
4031
                if err != nil {
15✔
4032
                        return err
×
4033
                }
×
4034

4035
                return fetchChanCommitments(chanBucket, c)
15✔
4036
        }, func() {})
15✔
4037
        if err != nil {
15✔
4038
                return nil, nil, err
×
4039
        }
×
4040

4041
        return &c.LocalCommitment, &c.RemoteCommitment, nil
15✔
4042
}
4043

4044
// RemoteRevocationStore returns the most up to date commitment version of the
4045
// revocation storage tree for the remote party. This method can be used when
4046
// acting on a possible contract breach to ensure, that the caller has the most
4047
// up to date information required to deliver justice.
4048
func (c *OpenChannel) RemoteRevocationStore() (shachain.Store, error) {
15✔
4049
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
30✔
4050
                chanBucket, err := fetchChanBucket(
15✔
4051
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
15✔
4052
                )
15✔
4053
                if err != nil {
15✔
4054
                        return err
×
4055
                }
×
4056

4057
                return fetchChanRevocationState(chanBucket, c)
15✔
4058
        }, func() {})
15✔
4059
        if err != nil {
15✔
4060
                return nil, err
×
4061
        }
×
4062

4063
        return c.RevocationStore, nil
15✔
4064
}
4065

4066
// AbsoluteThawHeight determines a frozen channel's absolute thaw height. If the
4067
// channel is not frozen, then 0 is returned.
4068
func (c *OpenChannel) AbsoluteThawHeight() (uint32, error) {
×
4069
        // Only frozen channels have a thaw height.
×
4070
        if !c.ChanType.IsFrozen() && !c.ChanType.HasLeaseExpiration() {
×
4071
                return 0, nil
×
4072
        }
×
4073

4074
        // If the channel has the frozen bit set and it's thaw height is below
4075
        // the absolute threshold, then it's interpreted as a relative height to
4076
        // the chain's current height.
4077
        if c.ChanType.IsFrozen() && c.ThawHeight < AbsoluteThawHeightThreshold {
×
4078
                // We'll only known of the channel's short ID once it's
×
4079
                // confirmed.
×
4080
                if c.IsPending {
×
4081
                        return 0, errors.New("cannot use relative thaw " +
×
4082
                                "height for unconfirmed channel")
×
4083
                }
×
4084

4085
                // For non-zero-conf channels, this is the base height to use.
4086
                blockHeightBase := c.ShortChannelID.BlockHeight
×
4087

×
4088
                // If this is a zero-conf channel, the ShortChannelID will be
×
4089
                // an alias.
×
4090
                if c.IsZeroConf() {
×
4091
                        if !c.ZeroConfConfirmed() {
×
4092
                                return 0, errors.New("cannot use relative " +
×
4093
                                        "height for unconfirmed zero-conf " +
×
4094
                                        "channel")
×
4095
                        }
×
4096

4097
                        // Use the confirmed SCID's BlockHeight.
4098
                        blockHeightBase = c.confirmedScid.BlockHeight
×
4099
                }
4100

4101
                return blockHeightBase + c.ThawHeight, nil
×
4102
        }
4103

4104
        return c.ThawHeight, nil
×
4105
}
4106

4107
func putChannelCloseSummary(tx kvdb.RwTx, chanID []byte,
4108
        summary *ChannelCloseSummary, lastChanState *OpenChannel) error {
114✔
4109

114✔
4110
        closedChanBucket, err := tx.CreateTopLevelBucket(closedChannelBucket)
114✔
4111
        if err != nil {
114✔
4112
                return err
×
4113
        }
×
4114

4115
        summary.RemoteCurrentRevocation = lastChanState.RemoteCurrentRevocation
114✔
4116
        summary.RemoteNextRevocation = lastChanState.RemoteNextRevocation
114✔
4117
        summary.LocalChanConfig = lastChanState.LocalChanCfg
114✔
4118

114✔
4119
        var b bytes.Buffer
114✔
4120
        if err := serializeChannelCloseSummary(&b, summary); err != nil {
114✔
4121
                return err
×
4122
        }
×
4123

4124
        return closedChanBucket.Put(chanID, b.Bytes())
114✔
4125
}
4126

4127
func serializeChannelCloseSummary(w io.Writer, cs *ChannelCloseSummary) error {
121✔
4128
        err := WriteElements(w,
121✔
4129
                cs.ChanPoint, cs.ShortChanID, cs.ChainHash, cs.ClosingTXID,
121✔
4130
                cs.CloseHeight, cs.RemotePub, cs.Capacity, cs.SettledBalance,
121✔
4131
                cs.TimeLockedBalance, cs.CloseType, cs.IsPending,
121✔
4132
        )
121✔
4133
        if err != nil {
121✔
4134
                return err
×
4135
        }
×
4136

4137
        // If this is a close channel summary created before the addition of
4138
        // the new fields, then we can exit here.
4139
        if cs.RemoteCurrentRevocation == nil {
121✔
4140
                return WriteElements(w, false)
×
4141
        }
×
4142

4143
        // If fields are present, write boolean to indicate this, and continue.
4144
        if err := WriteElements(w, true); err != nil {
121✔
4145
                return err
×
4146
        }
×
4147

4148
        if err := WriteElements(w, cs.RemoteCurrentRevocation); err != nil {
121✔
4149
                return err
×
4150
        }
×
4151

4152
        if err := writeChanConfig(w, &cs.LocalChanConfig); err != nil {
121✔
4153
                return err
×
4154
        }
×
4155

4156
        // The RemoteNextRevocation field is optional, as it's possible for a
4157
        // channel to be closed before we learn of the next unrevoked
4158
        // revocation point for the remote party. Write a boolean indicating
4159
        // whether this field is present or not.
4160
        if err := WriteElements(w, cs.RemoteNextRevocation != nil); err != nil {
121✔
4161
                return err
×
4162
        }
×
4163

4164
        // Write the field, if present.
4165
        if cs.RemoteNextRevocation != nil {
240✔
4166
                if err = WriteElements(w, cs.RemoteNextRevocation); err != nil {
119✔
4167
                        return err
×
4168
                }
×
4169
        }
4170

4171
        // Write whether the channel sync message is present.
4172
        if err := WriteElements(w, cs.LastChanSyncMsg != nil); err != nil {
121✔
4173
                return err
×
4174
        }
×
4175

4176
        // Write the channel sync message, if present.
4177
        if cs.LastChanSyncMsg != nil {
121✔
4178
                if err := WriteElements(w, cs.LastChanSyncMsg); err != nil {
×
4179
                        return err
×
4180
                }
×
4181
        }
4182

4183
        return nil
121✔
4184
}
4185

4186
func deserializeCloseChannelSummary(r io.Reader) (*ChannelCloseSummary, error) {
130✔
4187
        c := &ChannelCloseSummary{}
130✔
4188

130✔
4189
        err := ReadElements(r,
130✔
4190
                &c.ChanPoint, &c.ShortChanID, &c.ChainHash, &c.ClosingTXID,
130✔
4191
                &c.CloseHeight, &c.RemotePub, &c.Capacity, &c.SettledBalance,
130✔
4192
                &c.TimeLockedBalance, &c.CloseType, &c.IsPending,
130✔
4193
        )
130✔
4194
        if err != nil {
130✔
4195
                return nil, err
×
4196
        }
×
4197

4198
        // We'll now check to see if the channel close summary was encoded with
4199
        // any of the additional optional fields.
4200
        var hasNewFields bool
130✔
4201
        err = ReadElements(r, &hasNewFields)
130✔
4202
        if err != nil {
130✔
4203
                return nil, err
×
4204
        }
×
4205

4206
        // If fields are not present, we can return.
4207
        if !hasNewFields {
138✔
4208
                return c, nil
8✔
4209
        }
8✔
4210

4211
        // Otherwise read the new fields.
4212
        if err := ReadElements(r, &c.RemoteCurrentRevocation); err != nil {
122✔
4213
                return nil, err
×
4214
        }
×
4215

4216
        if err := readChanConfig(r, &c.LocalChanConfig); err != nil {
122✔
4217
                return nil, err
×
4218
        }
×
4219

4220
        // Finally, we'll attempt to read the next unrevoked commitment point
4221
        // for the remote party. If we closed the channel before receiving a
4222
        // channel_ready message then this might not be present. A boolean
4223
        // indicating whether the field is present will come first.
4224
        var hasRemoteNextRevocation bool
122✔
4225
        err = ReadElements(r, &hasRemoteNextRevocation)
122✔
4226
        if err != nil {
122✔
4227
                return nil, err
×
4228
        }
×
4229

4230
        // If this field was written, read it.
4231
        if hasRemoteNextRevocation {
244✔
4232
                err = ReadElements(r, &c.RemoteNextRevocation)
122✔
4233
                if err != nil {
122✔
4234
                        return nil, err
×
4235
                }
×
4236
        }
4237

4238
        // Check if we have a channel sync message to read.
4239
        var hasChanSyncMsg bool
122✔
4240
        err = ReadElements(r, &hasChanSyncMsg)
122✔
4241
        if err == io.EOF {
122✔
4242
                return c, nil
×
4243
        } else if err != nil {
122✔
4244
                return nil, err
×
4245
        }
×
4246

4247
        // If a chan sync message is present, read it.
4248
        if hasChanSyncMsg {
122✔
4249
                // We must pass in reference to a lnwire.Message for the codec
×
4250
                // to support it.
×
4251
                var msg lnwire.Message
×
4252
                if err := ReadElements(r, &msg); err != nil {
×
4253
                        return nil, err
×
4254
                }
×
4255

4256
                chanSync, ok := msg.(*lnwire.ChannelReestablish)
×
4257
                if !ok {
×
4258
                        return nil, errors.New("unable cast db Message to " +
×
4259
                                "ChannelReestablish")
×
4260
                }
×
4261
                c.LastChanSyncMsg = chanSync
×
4262
        }
4263

4264
        return c, nil
122✔
4265
}
4266

4267
func writeChanConfig(b io.Writer, c *ChannelConfig) error {
6,563✔
4268
        return WriteElements(b,
6,563✔
4269
                c.DustLimit, c.MaxPendingAmount, c.ChanReserve, c.MinHTLC,
6,563✔
4270
                c.MaxAcceptedHtlcs, c.CsvDelay, c.MultiSigKey,
6,563✔
4271
                c.RevocationBasePoint, c.PaymentBasePoint, c.DelayBasePoint,
6,563✔
4272
                c.HtlcBasePoint,
6,563✔
4273
        )
6,563✔
4274
}
6,563✔
4275

4276
// fundingTxPresent returns true if expect the funding transcation to be found
4277
// on disk or already populated within the passed open channel struct.
4278
func fundingTxPresent(channel *OpenChannel) bool {
10,346✔
4279
        chanType := channel.ChanType
10,346✔
4280

10,346✔
4281
        return chanType.IsSingleFunder() && chanType.HasFundingTx() &&
10,346✔
4282
                channel.IsInitiator &&
10,346✔
4283
                !channel.hasChanStatus(ChanStatusRestored)
10,346✔
4284
}
10,346✔
4285

4286
func putChanInfo(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
3,221✔
4287
        var w bytes.Buffer
3,221✔
4288
        if err := WriteElements(&w,
3,221✔
4289
                channel.ChanType, channel.ChainHash, channel.FundingOutpoint,
3,221✔
4290
                channel.ShortChannelID, channel.IsPending, channel.IsInitiator,
3,221✔
4291
                channel.chanStatus, channel.FundingBroadcastHeight,
3,221✔
4292
                channel.NumConfsRequired, channel.ChannelFlags,
3,221✔
4293
                channel.IdentityPub, channel.Capacity, channel.TotalMSatSent,
3,221✔
4294
                channel.TotalMSatReceived,
3,221✔
4295
        ); err != nil {
3,221✔
4296
                return err
×
4297
        }
×
4298

4299
        // For single funder channels that we initiated, and we have the
4300
        // funding transaction, then write the funding txn.
4301
        if fundingTxPresent(channel) {
5,108✔
4302
                if err := WriteElement(&w, channel.FundingTxn); err != nil {
1,887✔
4303
                        return err
×
4304
                }
×
4305
        }
4306

4307
        if err := writeChanConfig(&w, &channel.LocalChanCfg); err != nil {
3,221✔
4308
                return err
×
4309
        }
×
4310
        if err := writeChanConfig(&w, &channel.RemoteChanCfg); err != nil {
3,221✔
4311
                return err
×
4312
        }
×
4313

4314
        auxData := channel.extractTlvData()
3,221✔
4315
        if err := auxData.encode(&w); err != nil {
3,221✔
4316
                return fmt.Errorf("unable to encode aux data: %w", err)
×
4317
        }
×
4318

4319
        if err := chanBucket.Put(chanInfoKey, w.Bytes()); err != nil {
3,221✔
4320
                return err
×
4321
        }
×
4322

4323
        // Finally, add optional shutdown scripts for the local and remote peer if
4324
        // they are present.
4325
        if err := putOptionalUpfrontShutdownScript(
3,221✔
4326
                chanBucket, localUpfrontShutdownKey, channel.LocalShutdownScript,
3,221✔
4327
        ); err != nil {
3,221✔
4328
                return err
×
4329
        }
×
4330

4331
        return putOptionalUpfrontShutdownScript(
3,221✔
4332
                chanBucket, remoteUpfrontShutdownKey, channel.RemoteShutdownScript,
3,221✔
4333
        )
3,221✔
4334
}
4335

4336
// putOptionalUpfrontShutdownScript adds a shutdown script under the key
4337
// provided if it has a non-zero length.
4338
func putOptionalUpfrontShutdownScript(chanBucket kvdb.RwBucket, key []byte,
4339
        script []byte) error {
6,442✔
4340
        // If the script is empty, we do not need to add anything.
6,442✔
4341
        if len(script) == 0 {
12,874✔
4342
                return nil
6,432✔
4343
        }
6,432✔
4344

4345
        var w bytes.Buffer
10✔
4346
        if err := WriteElement(&w, script); err != nil {
10✔
4347
                return err
×
4348
        }
×
4349

4350
        return chanBucket.Put(key, w.Bytes())
10✔
4351
}
4352

4353
// getOptionalUpfrontShutdownScript reads the shutdown script stored under the
4354
// key provided if it is present. Upfront shutdown scripts are optional, so the
4355
// function returns with no error if the key is not present.
4356
func getOptionalUpfrontShutdownScript(chanBucket kvdb.RBucket, key []byte,
4357
        script *lnwire.DeliveryAddress) error {
14,250✔
4358

14,250✔
4359
        // Return early if the bucket does not exit, a shutdown script was not set.
14,250✔
4360
        bs := chanBucket.Get(key)
14,250✔
4361
        if bs == nil {
28,496✔
4362
                return nil
14,246✔
4363
        }
14,246✔
4364

4365
        var tempScript []byte
4✔
4366
        r := bytes.NewReader(bs)
4✔
4367
        if err := ReadElement(r, &tempScript); err != nil {
4✔
4368
                return err
×
4369
        }
×
4370
        *script = tempScript
4✔
4371

4✔
4372
        return nil
4✔
4373
}
4374

4375
func serializeChanCommit(w io.Writer, c *ChannelCommitment) error {
8,444✔
4376
        if err := WriteElements(w,
8,444✔
4377
                c.CommitHeight, c.LocalLogIndex, c.LocalHtlcIndex,
8,444✔
4378
                c.RemoteLogIndex, c.RemoteHtlcIndex, c.LocalBalance,
8,444✔
4379
                c.RemoteBalance, c.CommitFee, c.FeePerKw, c.CommitTx,
8,444✔
4380
                c.CommitSig,
8,444✔
4381
        ); err != nil {
8,444✔
4382
                return err
×
4383
        }
×
4384

4385
        return SerializeHtlcs(w, c.Htlcs...)
8,444✔
4386
}
4387

4388
func putChanCommitment(chanBucket kvdb.RwBucket, c *ChannelCommitment,
4389
        local bool) error {
6,398✔
4390

6,398✔
4391
        var commitKey []byte
6,398✔
4392
        if local {
9,618✔
4393
                commitKey = append(chanCommitmentKey, byte(0x00))
3,220✔
4394
        } else {
6,398✔
4395
                commitKey = append(chanCommitmentKey, byte(0x01))
3,178✔
4396
        }
3,178✔
4397

4398
        var b bytes.Buffer
6,398✔
4399
        if err := serializeChanCommit(&b, c); err != nil {
6,398✔
4400
                return err
×
4401
        }
×
4402

4403
        // Before we write to disk, we'll also write our aux data as well.
4404
        auxData := c.extractTlvData()
6,398✔
4405
        if err := auxData.encode(&b); err != nil {
6,398✔
4406
                return fmt.Errorf("unable to write aux data: %w", err)
×
4407
        }
×
4408

4409
        return chanBucket.Put(commitKey, b.Bytes())
6,398✔
4410
}
4411

4412
func putChanCommitments(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
1,224✔
4413
        // If this is a restored channel, then we don't have any commitments to
1,224✔
4414
        // write.
1,224✔
4415
        if channel.hasChanStatus(ChanStatusRestored) {
1,225✔
4416
                return nil
1✔
4417
        }
1✔
4418

4419
        err := putChanCommitment(
1,223✔
4420
                chanBucket, &channel.LocalCommitment, true,
1,223✔
4421
        )
1,223✔
4422
        if err != nil {
1,223✔
4423
                return err
×
4424
        }
×
4425

4426
        return putChanCommitment(
1,223✔
4427
                chanBucket, &channel.RemoteCommitment, false,
1,223✔
4428
        )
1,223✔
4429
}
4430

4431
func putChanRevocationState(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
3,805✔
4432
        var b bytes.Buffer
3,805✔
4433
        err := WriteElements(
3,805✔
4434
                &b, channel.RemoteCurrentRevocation, channel.RevocationProducer,
3,805✔
4435
                channel.RevocationStore,
3,805✔
4436
        )
3,805✔
4437
        if err != nil {
3,805✔
4438
                return err
×
4439
        }
×
4440

4441
        // If the next revocation is present, which is only the case after the
4442
        // ChannelReady message has been sent, then we'll write it to disk.
4443
        if channel.RemoteNextRevocation != nil {
6,849✔
4444
                err = WriteElements(&b, channel.RemoteNextRevocation)
3,044✔
4445
                if err != nil {
3,044✔
4446
                        return err
×
4447
                }
×
4448
        }
4449

4450
        return chanBucket.Put(revocationStateKey, b.Bytes())
3,805✔
4451
}
4452

4453
func readChanConfig(b io.Reader, c *ChannelConfig) error {
14,372✔
4454
        return ReadElements(b,
14,372✔
4455
                &c.DustLimit, &c.MaxPendingAmount, &c.ChanReserve,
14,372✔
4456
                &c.MinHTLC, &c.MaxAcceptedHtlcs, &c.CsvDelay,
14,372✔
4457
                &c.MultiSigKey, &c.RevocationBasePoint,
14,372✔
4458
                &c.PaymentBasePoint, &c.DelayBasePoint,
14,372✔
4459
                &c.HtlcBasePoint,
14,372✔
4460
        )
14,372✔
4461
}
14,372✔
4462

4463
func fetchChanInfo(chanBucket kvdb.RBucket, channel *OpenChannel) error {
7,125✔
4464
        infoBytes := chanBucket.Get(chanInfoKey)
7,125✔
4465
        if infoBytes == nil {
7,125✔
4466
                return ErrNoChanInfoFound
×
4467
        }
×
4468
        r := bytes.NewReader(infoBytes)
7,125✔
4469

7,125✔
4470
        if err := ReadElements(r,
7,125✔
4471
                &channel.ChanType, &channel.ChainHash, &channel.FundingOutpoint,
7,125✔
4472
                &channel.ShortChannelID, &channel.IsPending, &channel.IsInitiator,
7,125✔
4473
                &channel.chanStatus, &channel.FundingBroadcastHeight,
7,125✔
4474
                &channel.NumConfsRequired, &channel.ChannelFlags,
7,125✔
4475
                &channel.IdentityPub, &channel.Capacity, &channel.TotalMSatSent,
7,125✔
4476
                &channel.TotalMSatReceived,
7,125✔
4477
        ); err != nil {
7,125✔
4478
                return err
×
4479
        }
×
4480

4481
        // For single funder channels that we initiated and have the funding
4482
        // transaction to, read the funding txn.
4483
        if fundingTxPresent(channel) {
10,902✔
4484
                if err := ReadElement(r, &channel.FundingTxn); err != nil {
3,777✔
4485
                        return err
×
4486
                }
×
4487
        }
4488

4489
        if err := readChanConfig(r, &channel.LocalChanCfg); err != nil {
7,125✔
4490
                return err
×
4491
        }
×
4492
        if err := readChanConfig(r, &channel.RemoteChanCfg); err != nil {
7,125✔
4493
                return err
×
4494
        }
×
4495

4496
        // Retrieve the boolean stored under lastWasRevokeKey.
4497
        lastWasRevokeBytes := chanBucket.Get(lastWasRevokeKey)
7,125✔
4498
        if lastWasRevokeBytes == nil {
8,448✔
4499
                // If nothing has been stored under this key, we store false in the
1,323✔
4500
                // OpenChannel struct.
1,323✔
4501
                channel.LastWasRevoke = false
1,323✔
4502
        } else {
7,125✔
4503
                // Otherwise, read the value into the LastWasRevoke field.
5,802✔
4504
                revokeReader := bytes.NewReader(lastWasRevokeBytes)
5,802✔
4505
                err := ReadElements(revokeReader, &channel.LastWasRevoke)
5,802✔
4506
                if err != nil {
5,802✔
4507
                        return err
×
4508
                }
×
4509
        }
4510

4511
        var auxData openChannelTlvData
7,125✔
4512
        if err := auxData.decode(r); err != nil {
7,125✔
4513
                return fmt.Errorf("unable to decode aux data: %w", err)
×
4514
        }
×
4515

4516
        // Assign all the relevant fields from the aux data into the actual
4517
        // open channel.
4518
        channel.amendTlvData(auxData)
7,125✔
4519

7,125✔
4520
        channel.Packager = NewChannelPackager(channel.ShortChannelID)
7,125✔
4521

7,125✔
4522
        // Finally, read the optional shutdown scripts.
7,125✔
4523
        if err := getOptionalUpfrontShutdownScript(
7,125✔
4524
                chanBucket, localUpfrontShutdownKey, &channel.LocalShutdownScript,
7,125✔
4525
        ); err != nil {
7,125✔
4526
                return err
×
4527
        }
×
4528

4529
        return getOptionalUpfrontShutdownScript(
7,125✔
4530
                chanBucket, remoteUpfrontShutdownKey, &channel.RemoteShutdownScript,
7,125✔
4531
        )
7,125✔
4532
}
4533

4534
func deserializeChanCommit(r io.Reader) (ChannelCommitment, error) {
16,314✔
4535
        var c ChannelCommitment
16,314✔
4536

16,314✔
4537
        err := ReadElements(r,
16,314✔
4538
                &c.CommitHeight, &c.LocalLogIndex, &c.LocalHtlcIndex, &c.RemoteLogIndex,
16,314✔
4539
                &c.RemoteHtlcIndex, &c.LocalBalance, &c.RemoteBalance,
16,314✔
4540
                &c.CommitFee, &c.FeePerKw, &c.CommitTx, &c.CommitSig,
16,314✔
4541
        )
16,314✔
4542
        if err != nil {
16,314✔
4543
                return c, err
×
4544
        }
×
4545

4546
        c.Htlcs, err = DeserializeHtlcs(r)
16,314✔
4547
        if err != nil {
16,314✔
4548
                return c, err
×
4549
        }
×
4550

4551
        return c, nil
16,314✔
4552
}
4553

4554
func fetchChanCommitment(chanBucket kvdb.RBucket,
4555
        local bool) (ChannelCommitment, error) {
14,277✔
4556

14,277✔
4557
        var commitKey []byte
14,277✔
4558
        if local {
21,416✔
4559
                commitKey = append(chanCommitmentKey, byte(0x00))
7,139✔
4560
        } else {
14,277✔
4561
                commitKey = append(chanCommitmentKey, byte(0x01))
7,138✔
4562
        }
7,138✔
4563

4564
        commitBytes := chanBucket.Get(commitKey)
14,277✔
4565
        if commitBytes == nil {
14,277✔
4566
                return ChannelCommitment{}, ErrNoCommitmentsFound
×
4567
        }
×
4568

4569
        r := bytes.NewReader(commitBytes)
14,277✔
4570
        chanCommit, err := deserializeChanCommit(r)
14,277✔
4571
        if err != nil {
14,277✔
4572
                return ChannelCommitment{}, fmt.Errorf("unable to decode "+
×
4573
                        "chan commit: %w", err)
×
4574
        }
×
4575

4576
        // We'll also check to see if we have any aux data stored as the end of
4577
        // the stream.
4578
        var auxData commitTlvData
14,277✔
4579
        if err := auxData.decode(r); err != nil {
14,277✔
4580
                return ChannelCommitment{}, fmt.Errorf("unable to decode "+
×
4581
                        "chan aux data: %w", err)
×
4582
        }
×
4583

4584
        chanCommit.amendTlvData(auxData)
14,277✔
4585

14,277✔
4586
        return chanCommit, nil
14,277✔
4587
}
4588

4589
func fetchChanCommitments(chanBucket kvdb.RBucket, channel *OpenChannel) error {
7,140✔
4590
        var err error
7,140✔
4591

7,140✔
4592
        // If this is a restored channel, then we don't have any commitments to
7,140✔
4593
        // read.
7,140✔
4594
        if channel.hasChanStatus(ChanStatusRestored) {
7,142✔
4595
                return nil
2✔
4596
        }
2✔
4597

4598
        channel.LocalCommitment, err = fetchChanCommitment(chanBucket, true)
7,138✔
4599
        if err != nil {
7,138✔
4600
                return err
×
4601
        }
×
4602
        channel.RemoteCommitment, err = fetchChanCommitment(chanBucket, false)
7,138✔
4603
        if err != nil {
7,138✔
4604
                return err
×
4605
        }
×
4606

4607
        return nil
7,138✔
4608
}
4609

4610
func fetchChanRevocationState(chanBucket kvdb.RBucket, channel *OpenChannel) error {
7,140✔
4611
        revBytes := chanBucket.Get(revocationStateKey)
7,140✔
4612
        if revBytes == nil {
7,140✔
4613
                return ErrNoRevocationsFound
×
4614
        }
×
4615
        r := bytes.NewReader(revBytes)
7,140✔
4616

7,140✔
4617
        err := ReadElements(
7,140✔
4618
                r, &channel.RemoteCurrentRevocation, &channel.RevocationProducer,
7,140✔
4619
                &channel.RevocationStore,
7,140✔
4620
        )
7,140✔
4621
        if err != nil {
7,140✔
4622
                return err
×
4623
        }
×
4624

4625
        // If there aren't any bytes left in the buffer, then we don't yet have
4626
        // the next remote revocation, so we can exit early here.
4627
        if r.Len() == 0 {
7,345✔
4628
                return nil
205✔
4629
        }
205✔
4630

4631
        // Otherwise we'll read the next revocation for the remote party which
4632
        // is always the last item within the buffer.
4633
        return ReadElements(r, &channel.RemoteNextRevocation)
6,935✔
4634
}
4635

4636
func deleteOpenChannel(chanBucket kvdb.RwBucket) error {
114✔
4637
        if err := chanBucket.Delete(chanInfoKey); err != nil {
114✔
4638
                return err
×
4639
        }
×
4640

4641
        err := chanBucket.Delete(append(chanCommitmentKey, byte(0x00)))
114✔
4642
        if err != nil {
114✔
4643
                return err
×
4644
        }
×
4645
        err = chanBucket.Delete(append(chanCommitmentKey, byte(0x01)))
114✔
4646
        if err != nil {
114✔
4647
                return err
×
4648
        }
×
4649

4650
        if err := chanBucket.Delete(revocationStateKey); err != nil {
114✔
4651
                return err
×
4652
        }
×
4653

4654
        if diff := chanBucket.Get(commitDiffKey); diff != nil {
114✔
4655
                return chanBucket.Delete(commitDiffKey)
×
4656
        }
×
4657

4658
        return nil
114✔
4659
}
4660

4661
// makeLogKey converts a uint64 into an 8 byte array.
4662
func makeLogKey(updateNum uint64) [8]byte {
10,023✔
4663
        var key [8]byte
10,023✔
4664
        byteOrder.PutUint64(key[:], updateNum)
10,023✔
4665
        return key
10,023✔
4666
}
10,023✔
4667

4668
func fetchThawHeight(chanBucket kvdb.RBucket) (uint32, error) {
334✔
4669
        var height uint32
334✔
4670

334✔
4671
        heightBytes := chanBucket.Get(frozenChanKey)
334✔
4672
        heightReader := bytes.NewReader(heightBytes)
334✔
4673

334✔
4674
        if err := ReadElements(heightReader, &height); err != nil {
334✔
4675
                return 0, err
×
4676
        }
×
4677

4678
        return height, nil
334✔
4679
}
4680

4681
func storeThawHeight(chanBucket kvdb.RwBucket, height uint32) error {
428✔
4682
        var heightBuf bytes.Buffer
428✔
4683
        if err := WriteElements(&heightBuf, height); err != nil {
428✔
4684
                return err
×
4685
        }
×
4686

4687
        return chanBucket.Put(frozenChanKey, heightBuf.Bytes())
428✔
4688
}
4689

4690
func deleteThawHeight(chanBucket kvdb.RwBucket) error {
107✔
4691
        return chanBucket.Delete(frozenChanKey)
107✔
4692
}
107✔
4693

4694
// keyLocRecord is a wrapper struct around keychain.KeyLocator to implement the
4695
// tlv.RecordProducer interface.
4696
type keyLocRecord struct {
4697
        keychain.KeyLocator
4698
}
4699

4700
// Record creates a Record out of a KeyLocator using the passed Type and the
4701
// EKeyLocator and DKeyLocator functions. The size will always be 8 as
4702
// KeyFamily is uint32 and the Index is uint32.
4703
//
4704
// NOTE: This is part of the tlv.RecordProducer interface.
4705
func (k *keyLocRecord) Record() tlv.Record {
10,346✔
4706
        // Note that we set the type here as zero, as when used with a
10,346✔
4707
        // tlv.RecordT, the type param will be used as the type.
10,346✔
4708
        return tlv.MakeStaticRecord(
10,346✔
4709
                0, &k.KeyLocator, 8, EKeyLocator, DKeyLocator,
10,346✔
4710
        )
10,346✔
4711
}
10,346✔
4712

4713
// EKeyLocator is an encoder for keychain.KeyLocator.
4714
func EKeyLocator(w io.Writer, val interface{}, buf *[8]byte) error {
3,222✔
4715
        if v, ok := val.(*keychain.KeyLocator); ok {
6,444✔
4716
                err := tlv.EUint32T(w, uint32(v.Family), buf)
3,222✔
4717
                if err != nil {
3,222✔
4718
                        return err
×
4719
                }
×
4720

4721
                return tlv.EUint32T(w, v.Index, buf)
3,222✔
4722
        }
4723
        return tlv.NewTypeForEncodingErr(val, "keychain.KeyLocator")
×
4724
}
4725

4726
// DKeyLocator is a decoder for keychain.KeyLocator.
4727
func DKeyLocator(r io.Reader, val interface{}, buf *[8]byte, l uint64) error {
7,126✔
4728
        if v, ok := val.(*keychain.KeyLocator); ok {
14,252✔
4729
                var family uint32
7,126✔
4730
                err := tlv.DUint32(r, &family, buf, 4)
7,126✔
4731
                if err != nil {
7,126✔
4732
                        return err
×
4733
                }
×
4734
                v.Family = keychain.KeyFamily(family)
7,126✔
4735

7,126✔
4736
                return tlv.DUint32(r, &v.Index, buf, 4)
7,126✔
4737
        }
4738
        return tlv.NewTypeForDecodingErr(val, "keychain.KeyLocator", l, 8)
×
4739
}
4740

4741
// ShutdownInfo contains various info about the shutdown initiation of a
4742
// channel.
4743
type ShutdownInfo struct {
4744
        // DeliveryScript is the address that we have included in any previous
4745
        // Shutdown message for a particular channel and so should include in
4746
        // any future re-sends of the Shutdown message.
4747
        DeliveryScript tlv.RecordT[tlv.TlvType0, lnwire.DeliveryAddress]
4748

4749
        // LocalInitiator is true if we sent a Shutdown message before ever
4750
        // receiving a Shutdown message from the remote peer.
4751
        LocalInitiator tlv.RecordT[tlv.TlvType1, bool]
4752
}
4753

4754
// NewShutdownInfo constructs a new ShutdownInfo object.
4755
func NewShutdownInfo(deliveryScript lnwire.DeliveryAddress,
4756
        locallyInitiated bool) *ShutdownInfo {
13✔
4757

13✔
4758
        return &ShutdownInfo{
13✔
4759
                DeliveryScript: tlv.NewRecordT[tlv.TlvType0](deliveryScript),
13✔
4760
                LocalInitiator: tlv.NewPrimitiveRecord[tlv.TlvType1](
13✔
4761
                        locallyInitiated,
13✔
4762
                ),
13✔
4763
        }
13✔
4764
}
13✔
4765

4766
// Closer identifies the ChannelParty that initiated the coop-closure process.
4767
func (s ShutdownInfo) Closer() lntypes.ChannelParty {
×
4768
        if s.LocalInitiator.Val {
×
4769
                return lntypes.Local
×
4770
        }
×
4771

4772
        return lntypes.Remote
×
4773
}
4774

4775
// encode serialises the ShutdownInfo to the given io.Writer.
4776
func (s *ShutdownInfo) encode(w io.Writer) error {
11✔
4777
        records := []tlv.Record{
11✔
4778
                s.DeliveryScript.Record(),
11✔
4779
                s.LocalInitiator.Record(),
11✔
4780
        }
11✔
4781

11✔
4782
        stream, err := tlv.NewStream(records...)
11✔
4783
        if err != nil {
11✔
4784
                return err
×
4785
        }
×
4786

4787
        return stream.Encode(w)
11✔
4788
}
4789

4790
// decodeShutdownInfo constructs a ShutdownInfo struct by decoding the given
4791
// byte slice.
4792
func decodeShutdownInfo(b []byte) (*ShutdownInfo, error) {
2✔
4793
        tlvStream := lnwire.ExtraOpaqueData(b)
2✔
4794

2✔
4795
        var info ShutdownInfo
2✔
4796
        records := []tlv.RecordProducer{
2✔
4797
                &info.DeliveryScript,
2✔
4798
                &info.LocalInitiator,
2✔
4799
        }
2✔
4800

2✔
4801
        _, err := tlvStream.ExtractRecords(records...)
2✔
4802

2✔
4803
        return &info, err
2✔
4804
}
2✔
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