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

lightningnetwork / lnd / 14977937992

12 May 2025 04:50PM UTC coverage: 58.596% (+0.04%) from 58.559%
14977937992

Pull #9677

github

web-flow
Merge 882e0ce18 into 1db6c31e2
Pull Request #9677: Expose confirmation count for pending 'channel open' transactions

142 of 178 new or added lines in 5 files covered. (79.78%)

35 existing lines in 6 files now uncovered.

97502 of 166397 relevant lines covered (58.6%)

1.82 hits per line

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

72.07
/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
        // confirmationHeight records the block height at which the funding
266
        // transaction was first confirmed.
267
        confirmationHeight tlv.RecordT[tlv.TlvType8, uint32]
268
}
269

270
// encode serializes the openChannelTlvData to the given io.Writer.
271
func (c *openChannelTlvData) encode(w io.Writer) error {
3✔
272
        tlvRecords := []tlv.Record{
3✔
273
                c.revokeKeyLoc.Record(),
3✔
274
                c.initialLocalBalance.Record(),
3✔
275
                c.initialRemoteBalance.Record(),
3✔
276
                c.realScid.Record(),
3✔
277
                c.confirmationHeight.Record(),
3✔
278
        }
3✔
279
        c.memo.WhenSome(func(memo tlv.RecordT[tlv.TlvType5, []byte]) {
6✔
280
                tlvRecords = append(tlvRecords, memo.Record())
3✔
281
        })
3✔
282
        c.tapscriptRoot.WhenSome(
3✔
283
                func(root tlv.RecordT[tlv.TlvType6, [32]byte]) {
3✔
284
                        tlvRecords = append(tlvRecords, root.Record())
×
285
                },
×
286
        )
287
        c.customBlob.WhenSome(func(blob tlv.RecordT[tlv.TlvType7, tlv.Blob]) {
3✔
288
                tlvRecords = append(tlvRecords, blob.Record())
×
289
        })
×
290

291
        tlv.SortRecords(tlvRecords)
3✔
292

3✔
293
        // Create the tlv stream.
3✔
294
        tlvStream, err := tlv.NewStream(tlvRecords...)
3✔
295
        if err != nil {
3✔
296
                return err
×
297
        }
×
298

299
        return tlvStream.Encode(w)
3✔
300
}
301

302
// decode deserializes the openChannelTlvData from the given io.Reader.
303
func (c *openChannelTlvData) decode(r io.Reader) error {
3✔
304
        memo := c.memo.Zero()
3✔
305
        tapscriptRoot := c.tapscriptRoot.Zero()
3✔
306
        blob := c.customBlob.Zero()
3✔
307

3✔
308
        // Create the tlv stream.
3✔
309
        tlvStream, err := tlv.NewStream(
3✔
310
                c.revokeKeyLoc.Record(),
3✔
311
                c.initialLocalBalance.Record(),
3✔
312
                c.initialRemoteBalance.Record(),
3✔
313
                c.realScid.Record(),
3✔
314
                memo.Record(),
3✔
315
                tapscriptRoot.Record(),
3✔
316
                blob.Record(),
3✔
317
                c.confirmationHeight.Record(),
3✔
318
        )
3✔
319
        if err != nil {
3✔
320
                return err
×
321
        }
×
322

323
        tlvs, err := tlvStream.DecodeWithParsedTypes(r)
3✔
324
        if err != nil {
3✔
325
                return err
×
326
        }
×
327

328
        if _, ok := tlvs[memo.TlvType()]; ok {
6✔
329
                c.memo = tlv.SomeRecordT(memo)
3✔
330
        }
3✔
331
        if _, ok := tlvs[tapscriptRoot.TlvType()]; ok {
3✔
332
                c.tapscriptRoot = tlv.SomeRecordT(tapscriptRoot)
×
333
        }
×
334
        if _, ok := tlvs[c.customBlob.TlvType()]; ok {
3✔
335
                c.customBlob = tlv.SomeRecordT(blob)
×
336
        }
×
337

338
        return nil
3✔
339
}
340

341
// indexStatus is an enum-like type that describes what state the
342
// outpoint is in. Currently only two possible values.
343
type indexStatus uint8
344

345
const (
346
        // outpointOpen represents an outpoint that is open in the outpoint index.
347
        outpointOpen indexStatus = 0
348

349
        // outpointClosed represents an outpoint that is closed in the outpoint
350
        // index.
351
        outpointClosed indexStatus = 1
352
)
353

354
// ChannelType is an enum-like type that describes one of several possible
355
// channel types. Each open channel is associated with a particular type as the
356
// channel type may determine how higher level operations are conducted such as
357
// fee negotiation, channel closing, the format of HTLCs, etc. Structure-wise,
358
// a ChannelType is a bit field, with each bit denoting a modification from the
359
// base channel type of single funder.
360
type ChannelType uint64
361

362
const (
363
        // NOTE: iota isn't used here for this enum needs to be stable
364
        // long-term as it will be persisted to the database.
365

366
        // SingleFunderBit represents a channel wherein one party solely funds
367
        // the entire capacity of the channel.
368
        SingleFunderBit ChannelType = 0
369

370
        // DualFunderBit represents a channel wherein both parties contribute
371
        // funds towards the total capacity of the channel. The channel may be
372
        // funded symmetrically or asymmetrically.
373
        DualFunderBit ChannelType = 1 << 0
374

375
        // SingleFunderTweaklessBit is similar to the basic SingleFunder channel
376
        // type, but it omits the tweak for one's key in the commitment
377
        // transaction of the remote party.
378
        SingleFunderTweaklessBit ChannelType = 1 << 1
379

380
        // NoFundingTxBit denotes if we have the funding transaction locally on
381
        // disk. This bit may be on if the funding transaction was crafted by a
382
        // wallet external to the primary daemon.
383
        NoFundingTxBit ChannelType = 1 << 2
384

385
        // AnchorOutputsBit indicates that the channel makes use of anchor
386
        // outputs to bump the commitment transaction's effective feerate. This
387
        // channel type also uses a delayed to_remote output script.
388
        AnchorOutputsBit ChannelType = 1 << 3
389

390
        // FrozenBit indicates that the channel is a frozen channel, meaning
391
        // that only the responder can decide to cooperatively close the
392
        // channel.
393
        FrozenBit ChannelType = 1 << 4
394

395
        // ZeroHtlcTxFeeBit indicates that the channel should use zero-fee
396
        // second-level HTLC transactions.
397
        ZeroHtlcTxFeeBit ChannelType = 1 << 5
398

399
        // LeaseExpirationBit indicates that the channel has been leased for a
400
        // period of time, constraining every output that pays to the channel
401
        // initiator with an additional CLTV of the lease maturity.
402
        LeaseExpirationBit ChannelType = 1 << 6
403

404
        // ZeroConfBit indicates that the channel is a zero-conf channel.
405
        ZeroConfBit ChannelType = 1 << 7
406

407
        // ScidAliasChanBit indicates that the channel has negotiated the
408
        // scid-alias channel type.
409
        ScidAliasChanBit ChannelType = 1 << 8
410

411
        // ScidAliasFeatureBit indicates that the scid-alias feature bit was
412
        // negotiated during the lifetime of this channel.
413
        ScidAliasFeatureBit ChannelType = 1 << 9
414

415
        // SimpleTaprootFeatureBit indicates that the simple-taproot-chans
416
        // feature bit was negotiated during the lifetime of the channel.
417
        SimpleTaprootFeatureBit ChannelType = 1 << 10
418

419
        // TapscriptRootBit indicates that this is a MuSig2 channel with a top
420
        // level tapscript commitment. This MUST be set along with the
421
        // SimpleTaprootFeatureBit.
422
        TapscriptRootBit ChannelType = 1 << 11
423
)
424

425
// IsSingleFunder returns true if the channel type if one of the known single
426
// funder variants.
427
func (c ChannelType) IsSingleFunder() bool {
3✔
428
        return c&DualFunderBit == 0
3✔
429
}
3✔
430

431
// IsDualFunder returns true if the ChannelType has the DualFunderBit set.
432
func (c ChannelType) IsDualFunder() bool {
×
433
        return c&DualFunderBit == DualFunderBit
×
434
}
×
435

436
// IsTweakless returns true if the target channel uses a commitment that
437
// doesn't tweak the key for the remote party.
438
func (c ChannelType) IsTweakless() bool {
3✔
439
        return c&SingleFunderTweaklessBit == SingleFunderTweaklessBit
3✔
440
}
3✔
441

442
// HasFundingTx returns true if this channel type is one that has a funding
443
// transaction stored locally.
444
func (c ChannelType) HasFundingTx() bool {
3✔
445
        return c&NoFundingTxBit == 0
3✔
446
}
3✔
447

448
// HasAnchors returns true if this channel type has anchor outputs on its
449
// commitment.
450
func (c ChannelType) HasAnchors() bool {
3✔
451
        return c&AnchorOutputsBit == AnchorOutputsBit
3✔
452
}
3✔
453

454
// ZeroHtlcTxFee returns true if this channel type uses second-level HTLC
455
// transactions signed with zero-fee.
456
func (c ChannelType) ZeroHtlcTxFee() bool {
3✔
457
        return c&ZeroHtlcTxFeeBit == ZeroHtlcTxFeeBit
3✔
458
}
3✔
459

460
// IsFrozen returns true if the channel is considered to be "frozen". A frozen
461
// channel means that only the responder can initiate a cooperative channel
462
// closure.
463
func (c ChannelType) IsFrozen() bool {
3✔
464
        return c&FrozenBit == FrozenBit
3✔
465
}
3✔
466

467
// HasLeaseExpiration returns true if the channel originated from a lease.
468
func (c ChannelType) HasLeaseExpiration() bool {
3✔
469
        return c&LeaseExpirationBit == LeaseExpirationBit
3✔
470
}
3✔
471

472
// HasZeroConf returns true if the channel is a zero-conf channel.
473
func (c ChannelType) HasZeroConf() bool {
3✔
474
        return c&ZeroConfBit == ZeroConfBit
3✔
475
}
3✔
476

477
// HasScidAliasChan returns true if the scid-alias channel type was negotiated.
478
func (c ChannelType) HasScidAliasChan() bool {
×
479
        return c&ScidAliasChanBit == ScidAliasChanBit
×
480
}
×
481

482
// HasScidAliasFeature returns true if the scid-alias feature bit was
483
// negotiated during the lifetime of this channel.
484
func (c ChannelType) HasScidAliasFeature() bool {
3✔
485
        return c&ScidAliasFeatureBit == ScidAliasFeatureBit
3✔
486
}
3✔
487

488
// IsTaproot returns true if the channel is using taproot features.
489
func (c ChannelType) IsTaproot() bool {
3✔
490
        return c&SimpleTaprootFeatureBit == SimpleTaprootFeatureBit
3✔
491
}
3✔
492

493
// HasTapscriptRoot returns true if the channel is using a top level tapscript
494
// root commitment.
495
func (c ChannelType) HasTapscriptRoot() bool {
3✔
496
        return c&TapscriptRootBit == TapscriptRootBit
3✔
497
}
3✔
498

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

511
        // MaxPendingAmount is the maximum pending HTLC value that the
512
        // owner of these constraints can offer the remote node at a
513
        // particular time.
514
        MaxPendingAmount lnwire.MilliSatoshi
515

516
        // MinHTLC is the minimum HTLC value that the owner of these
517
        // constraints can offer the remote node. If any HTLCs below this
518
        // amount are offered, then the HTLC will be rejected. This, in
519
        // tandem with the dust limit allows a node to regulate the
520
        // smallest HTLC that it deems economically relevant.
521
        MinHTLC lnwire.MilliSatoshi
522

523
        // MaxAcceptedHtlcs is the maximum number of HTLCs that the owner of
524
        // this set of constraints can offer the remote node. This allows each
525
        // node to limit their over all exposure to HTLCs that may need to be
526
        // acted upon in the case of a unilateral channel closure or a contract
527
        // breach.
528
        MaxAcceptedHtlcs uint16
529
}
530

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

543
        // CsvDelay is the relative time lock delay expressed in blocks. Any
544
        // settled outputs that pay to the owner of this channel configuration
545
        // MUST ensure that the delay branch uses this value as the relative
546
        // time lock. Similarly, any HTLC's offered by this node should use
547
        // this value as well.
548
        CsvDelay uint16
549
}
550

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

564
        // CommitmentParams is an embedding of the parameters
565
        // required to render an abstract channel state into a concrete
566
        // commitment transaction.
567
        CommitmentParams
568

569
        // MultiSigKey is the key to be used within the 2-of-2 output script
570
        // for the owner of this channel config.
571
        MultiSigKey keychain.KeyDescriptor
572

573
        // RevocationBasePoint is the base public key to be used when deriving
574
        // revocation keys for the remote node's commitment transaction. This
575
        // will be combined along with a per commitment secret to derive a
576
        // unique revocation key for each state.
577
        RevocationBasePoint keychain.KeyDescriptor
578

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

586
        // DelayBasePoint is the base public key to be used when deriving the
587
        // key used within the delayed pay-to-self output on the commitment
588
        // transaction for a node. This will be combined with a tweak derived
589
        // from the per-commitment point to ensure unique keys for each
590
        // commitment transaction.
591
        DelayBasePoint keychain.KeyDescriptor
592

593
        // HtlcBasePoint is the base public key to be used when deriving the
594
        // local HTLC key. The derived key (combined with the tweak derived
595
        // from the per-commitment point) is used within the "to self" clause
596
        // within any HTLC output scripts.
597
        HtlcBasePoint keychain.KeyDescriptor
598
}
599

600
// commitTlvData stores all the optional data that may be stored as a TLV stream
601
// at the _end_ of the normal serialized commit on disk.
602
type commitTlvData struct {
603
        // customBlob is a custom blob that may store extra data for custom
604
        // channels.
605
        customBlob tlv.OptionalRecordT[tlv.TlvType1, tlv.Blob]
606
}
607

608
// encode encodes the aux data into the passed io.Writer.
609
func (c *commitTlvData) encode(w io.Writer) error {
3✔
610
        var tlvRecords []tlv.Record
3✔
611
        c.customBlob.WhenSome(func(blob tlv.RecordT[tlv.TlvType1, tlv.Blob]) {
3✔
612
                tlvRecords = append(tlvRecords, blob.Record())
×
613
        })
×
614

615
        // Create the tlv stream.
616
        tlvStream, err := tlv.NewStream(tlvRecords...)
3✔
617
        if err != nil {
3✔
618
                return err
×
619
        }
×
620

621
        return tlvStream.Encode(w)
3✔
622
}
623

624
// decode attempts to decode the aux data from the passed io.Reader.
625
func (c *commitTlvData) decode(r io.Reader) error {
3✔
626
        blob := c.customBlob.Zero()
3✔
627

3✔
628
        tlvStream, err := tlv.NewStream(
3✔
629
                blob.Record(),
3✔
630
        )
3✔
631
        if err != nil {
3✔
632
                return err
×
633
        }
×
634

635
        tlvs, err := tlvStream.DecodeWithParsedTypes(r)
3✔
636
        if err != nil {
3✔
637
                return err
×
638
        }
×
639

640
        if _, ok := tlvs[c.customBlob.TlvType()]; ok {
3✔
641
                c.customBlob = tlv.SomeRecordT(blob)
×
642
        }
×
643

644
        return nil
3✔
645
}
646

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

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

665
        // LocalHtlcIndex is the current local running HTLC index. This value
666
        // will be incremented for each outgoing HTLC the local node offers.
667
        LocalHtlcIndex uint64
668

669
        // RemoteLogIndex is the cumulative log index index of the remote node
670
        // at this point in the commitment chain. This value will be
671
        // incremented for each _update_ added to the remote update log.
672
        RemoteLogIndex uint64
673

674
        // RemoteHtlcIndex is the current remote running HTLC index. This value
675
        // will be incremented for each outgoing HTLC the remote node offers.
676
        RemoteHtlcIndex uint64
677

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

685
        // RemoteBalance is the current available settled balance within the
686
        // channel directly spendable by the remote node.
687
        //
688
        // NOTE: This is the balance *after* subtracting any commitment fee,
689
        // AND anchor output values.
690
        RemoteBalance lnwire.MilliSatoshi
691

692
        // CommitFee is the amount calculated to be paid in fees for the
693
        // current set of commitment transactions. The fee amount is persisted
694
        // with the channel in order to allow the fee amount to be removed and
695
        // recalculated with each channel state update, including updates that
696
        // happen after a system restart.
697
        CommitFee btcutil.Amount
698

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

709
        // CommitTx is the latest version of the commitment state, broadcast
710
        // able by us.
711
        CommitTx *wire.MsgTx
712

713
        // CustomBlob is an optional blob that can be used to store information
714
        // specific to a custom channel type. This may track some custom
715
        // specific state for this given commitment.
716
        CustomBlob fn.Option[tlv.Blob]
717

718
        // CommitSig is one half of the signature required to fully complete
719
        // the script for the commitment transaction above. This is the
720
        // signature signed by the remote party for our version of the
721
        // commitment transactions.
722
        CommitSig []byte
723

724
        // Htlcs is the set of HTLC's that are pending at this particular
725
        // commitment height.
726
        Htlcs []HTLC
727
}
728

729
// amendTlvData updates the channel with the given auxiliary TLV data.
730
func (c *ChannelCommitment) amendTlvData(auxData commitTlvData) {
3✔
731
        auxData.customBlob.WhenSomeV(func(blob tlv.Blob) {
3✔
732
                c.CustomBlob = fn.Some(blob)
×
733
        })
×
734
}
735

736
// extractTlvData creates a new commitTlvData from the given commitment.
737
func (c *ChannelCommitment) extractTlvData() commitTlvData {
3✔
738
        var auxData commitTlvData
3✔
739

3✔
740
        c.CustomBlob.WhenSome(func(blob tlv.Blob) {
3✔
741
                auxData.customBlob = tlv.SomeRecordT(
×
742
                        tlv.NewPrimitiveRecord[tlv.TlvType1](blob),
×
743
                )
×
744
        })
×
745

746
        return auxData
3✔
747
}
748

749
// ChannelStatus is a bit vector used to indicate whether an OpenChannel is in
750
// the default usable state, or a state where it shouldn't be used.
751
type ChannelStatus uint64
752

753
var (
754
        // ChanStatusDefault is the normal state of an open channel.
755
        ChanStatusDefault ChannelStatus
756

757
        // ChanStatusBorked indicates that the channel has entered an
758
        // irreconcilable state, triggered by a state desynchronization or
759
        // channel breach.  Channels in this state should never be added to the
760
        // htlc switch.
761
        ChanStatusBorked ChannelStatus = 1
762

763
        // ChanStatusCommitBroadcasted indicates that a commitment for this
764
        // channel has been broadcasted.
765
        ChanStatusCommitBroadcasted ChannelStatus = 1 << 1
766

767
        // ChanStatusLocalDataLoss indicates that we have lost channel state
768
        // for this channel, and broadcasting our latest commitment might be
769
        // considered a breach.
770
        //
771
        // TODO(halseh): actually enforce that we are not force closing such a
772
        // channel.
773
        ChanStatusLocalDataLoss ChannelStatus = 1 << 2
774

775
        // ChanStatusRestored is a status flag that signals that the channel
776
        // has been restored, and doesn't have all the fields a typical channel
777
        // will have.
778
        ChanStatusRestored ChannelStatus = 1 << 3
779

780
        // ChanStatusCoopBroadcasted indicates that a cooperative close for
781
        // this channel has been broadcasted. Older cooperatively closed
782
        // channels will only have this status set. Newer ones will also have
783
        // close initiator information stored using the local/remote initiator
784
        // status. This status is set in conjunction with the initiator status
785
        // so that we do not need to check multiple channel statues for
786
        // cooperative closes.
787
        ChanStatusCoopBroadcasted ChannelStatus = 1 << 4
788

789
        // ChanStatusLocalCloseInitiator indicates that we initiated closing
790
        // the channel.
791
        ChanStatusLocalCloseInitiator ChannelStatus = 1 << 5
792

793
        // ChanStatusRemoteCloseInitiator indicates that the remote node
794
        // initiated closing the channel.
795
        ChanStatusRemoteCloseInitiator ChannelStatus = 1 << 6
796
)
797

798
// chanStatusStrings maps a ChannelStatus to a human friendly string that
799
// describes that status.
800
var chanStatusStrings = map[ChannelStatus]string{
801
        ChanStatusDefault:              "ChanStatusDefault",
802
        ChanStatusBorked:               "ChanStatusBorked",
803
        ChanStatusCommitBroadcasted:    "ChanStatusCommitBroadcasted",
804
        ChanStatusLocalDataLoss:        "ChanStatusLocalDataLoss",
805
        ChanStatusRestored:             "ChanStatusRestored",
806
        ChanStatusCoopBroadcasted:      "ChanStatusCoopBroadcasted",
807
        ChanStatusLocalCloseInitiator:  "ChanStatusLocalCloseInitiator",
808
        ChanStatusRemoteCloseInitiator: "ChanStatusRemoteCloseInitiator",
809
}
810

811
// orderedChanStatusFlags is an in-order list of all that channel status flags.
812
var orderedChanStatusFlags = []ChannelStatus{
813
        ChanStatusBorked,
814
        ChanStatusCommitBroadcasted,
815
        ChanStatusLocalDataLoss,
816
        ChanStatusRestored,
817
        ChanStatusCoopBroadcasted,
818
        ChanStatusLocalCloseInitiator,
819
        ChanStatusRemoteCloseInitiator,
820
}
821

822
// String returns a human-readable representation of the ChannelStatus.
823
func (c ChannelStatus) String() string {
3✔
824
        // If no flags are set, then this is the default case.
3✔
825
        if c == ChanStatusDefault {
6✔
826
                return chanStatusStrings[ChanStatusDefault]
3✔
827
        }
3✔
828

829
        // Add individual bit flags.
830
        statusStr := ""
3✔
831
        for _, flag := range orderedChanStatusFlags {
6✔
832
                if c&flag == flag {
6✔
833
                        statusStr += chanStatusStrings[flag] + "|"
3✔
834
                        c -= flag
3✔
835
                }
3✔
836
        }
837

838
        // Remove anything to the right of the final bar, including it as well.
839
        statusStr = strings.TrimRight(statusStr, "|")
3✔
840

3✔
841
        // Add any remaining flags which aren't accounted for as hex.
3✔
842
        if c != 0 {
3✔
843
                statusStr += "|0x" + strconv.FormatUint(uint64(c), 16)
×
844
        }
×
845

846
        // If this was purely an unknown flag, then remove the extra bar at the
847
        // start of the string.
848
        statusStr = strings.TrimLeft(statusStr, "|")
3✔
849

3✔
850
        return statusStr
3✔
851
}
852

853
// FinalHtlcByte defines a byte type that encodes information about the final
854
// htlc resolution.
855
type FinalHtlcByte byte
856

857
const (
858
        // FinalHtlcSettledBit is the bit that encodes whether the htlc was
859
        // settled or failed.
860
        FinalHtlcSettledBit FinalHtlcByte = 1 << 0
861

862
        // FinalHtlcOffchainBit is the bit that encodes whether the htlc was
863
        // resolved offchain or onchain.
864
        FinalHtlcOffchainBit FinalHtlcByte = 1 << 1
865
)
866

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

878
        // ChainHash is a hash which represents the blockchain that this
879
        // channel will be opened within. This value is typically the genesis
880
        // hash. In the case that the original chain went through a contentious
881
        // hard-fork, then this value will be tweaked using the unique fork
882
        // point on each branch.
883
        ChainHash chainhash.Hash
884

885
        // FundingOutpoint is the outpoint of the final funding transaction.
886
        // This value uniquely and globally identifies the channel within the
887
        // target blockchain as specified by the chain hash parameter.
888
        FundingOutpoint wire.OutPoint
889

890
        // ShortChannelID encodes the exact location in the chain in which the
891
        // channel was initially confirmed. This includes: the block height,
892
        // transaction index, and the output within the target transaction.
893
        //
894
        // If IsZeroConf(), then this will the "base" (very first) ALIAS scid
895
        // and the confirmed SCID will be stored in ConfirmedScid.
896
        ShortChannelID lnwire.ShortChannelID
897

898
        // IsPending indicates whether a channel's funding transaction has been
899
        // confirmed.
900
        IsPending bool
901

902
        // IsInitiator is a bool which indicates if we were the original
903
        // initiator for the channel. This value may affect how higher levels
904
        // negotiate fees, or close the channel.
905
        IsInitiator bool
906

907
        // chanStatus is the current status of this channel. If it is not in
908
        // the state Default, it should not be used for forwarding payments.
909
        chanStatus ChannelStatus
910

911
        // FundingBroadcastHeight is the height in which the funding
912
        // transaction was broadcast. This value can be used by higher level
913
        // sub-systems to determine if a channel is stale and/or should have
914
        // been confirmed before a certain height.
915
        FundingBroadcastHeight uint32
916

917
        // ConfirmationHeight records the block height at which the funding
918
        // transaction was first confirmed.
919
        ConfirmationHeight uint32
920

921
        // NumConfsRequired is the number of confirmations a channel's funding
922
        // transaction must have received in order to be considered available
923
        // for normal transactional use.
924
        NumConfsRequired uint16
925

926
        // ChannelFlags holds the flags that were sent as part of the
927
        // open_channel message.
928
        ChannelFlags lnwire.FundingFlag
929

930
        // IdentityPub is the identity public key of the remote node this
931
        // channel has been established with.
932
        IdentityPub *btcec.PublicKey
933

934
        // Capacity is the total capacity of this channel.
935
        Capacity btcutil.Amount
936

937
        // TotalMSatSent is the total number of milli-satoshis we've sent
938
        // within this channel.
939
        TotalMSatSent lnwire.MilliSatoshi
940

941
        // TotalMSatReceived is the total number of milli-satoshis we've
942
        // received within this channel.
943
        TotalMSatReceived lnwire.MilliSatoshi
944

945
        // InitialLocalBalance is the balance we have during the channel
946
        // opening. When we are not the initiator, this value represents the
947
        // push amount.
948
        InitialLocalBalance lnwire.MilliSatoshi
949

950
        // InitialRemoteBalance is the balance they have during the channel
951
        // opening.
952
        InitialRemoteBalance lnwire.MilliSatoshi
953

954
        // LocalChanCfg is the channel configuration for the local node.
955
        LocalChanCfg ChannelConfig
956

957
        // RemoteChanCfg is the channel configuration for the remote node.
958
        RemoteChanCfg ChannelConfig
959

960
        // LocalCommitment is the current local commitment state for the local
961
        // party. This is stored distinct from the state of the remote party
962
        // as there are certain asymmetric parameters which affect the
963
        // structure of each commitment.
964
        LocalCommitment ChannelCommitment
965

966
        // RemoteCommitment is the current remote commitment state for the
967
        // remote party. This is stored distinct from the state of the local
968
        // party as there are certain asymmetric parameters which affect the
969
        // structure of each commitment.
970
        RemoteCommitment ChannelCommitment
971

972
        // RemoteCurrentRevocation is the current revocation for their
973
        // commitment transaction. However, since this the derived public key,
974
        // we don't yet have the private key so we aren't yet able to verify
975
        // that it's actually in the hash chain.
976
        RemoteCurrentRevocation *btcec.PublicKey
977

978
        // RemoteNextRevocation is the revocation key to be used for the *next*
979
        // commitment transaction we create for the local node. Within the
980
        // specification, this value is referred to as the
981
        // per-commitment-point.
982
        RemoteNextRevocation *btcec.PublicKey
983

984
        // RevocationProducer is used to generate the revocation in such a way
985
        // that remote side might store it efficiently and have the ability to
986
        // restore the revocation by index if needed. Current implementation of
987
        // secret producer is shachain producer.
988
        RevocationProducer shachain.Producer
989

990
        // RevocationStore is used to efficiently store the revocations for
991
        // previous channels states sent to us by remote side. Current
992
        // implementation of secret store is shachain store.
993
        RevocationStore shachain.Store
994

995
        // Packager is used to create and update forwarding packages for this
996
        // channel, which encodes all necessary information to recover from
997
        // failures and reforward HTLCs that were not fully processed.
998
        Packager FwdPackager
999

1000
        // FundingTxn is the transaction containing this channel's funding
1001
        // outpoint. Upon restarts, this txn will be rebroadcast if the channel
1002
        // is found to be pending.
1003
        //
1004
        // NOTE: This value will only be populated for single-funder channels
1005
        // for which we are the initiator, and that we also have the funding
1006
        // transaction for. One can check this by using the HasFundingTx()
1007
        // method on the ChanType field.
1008
        FundingTxn *wire.MsgTx
1009

1010
        // LocalShutdownScript is set to a pre-set script if the channel was opened
1011
        // by the local node with option_upfront_shutdown_script set. If the option
1012
        // was not set, the field is empty.
1013
        LocalShutdownScript lnwire.DeliveryAddress
1014

1015
        // RemoteShutdownScript is set to a pre-set script if the channel was opened
1016
        // by the remote node with option_upfront_shutdown_script set. If the option
1017
        // was not set, the field is empty.
1018
        RemoteShutdownScript lnwire.DeliveryAddress
1019

1020
        // ThawHeight is the height when a frozen channel once again becomes a
1021
        // normal channel. If this is zero, then there're no restrictions on
1022
        // this channel. If the value is lower than 500,000, then it's
1023
        // interpreted as a relative height, or an absolute height otherwise.
1024
        ThawHeight uint32
1025

1026
        // LastWasRevoke is a boolean that determines if the last update we sent
1027
        // was a revocation (true) or a commitment signature (false).
1028
        LastWasRevoke bool
1029

1030
        // RevocationKeyLocator stores the KeyLocator information that we will
1031
        // need to derive the shachain root for this channel. This allows us to
1032
        // have private key isolation from lnd.
1033
        RevocationKeyLocator keychain.KeyLocator
1034

1035
        // confirmedScid is the confirmed ShortChannelID for a zero-conf
1036
        // channel. If the channel is unconfirmed, then this will be the
1037
        // default ShortChannelID. This is only set for zero-conf channels.
1038
        confirmedScid lnwire.ShortChannelID
1039

1040
        // Memo is any arbitrary information we wish to store locally about the
1041
        // channel that will be useful to our future selves.
1042
        Memo []byte
1043

1044
        // TapscriptRoot is an optional tapscript root used to derive the MuSig2
1045
        // funding output.
1046
        TapscriptRoot fn.Option[chainhash.Hash]
1047

1048
        // CustomBlob is an optional blob that can be used to store information
1049
        // specific to a custom channel type. This information is only created
1050
        // at channel funding time, and after wards is to be considered
1051
        // immutable.
1052
        CustomBlob fn.Option[tlv.Blob]
1053

1054
        // TODO(roasbeef): eww
1055
        Db *ChannelStateDB
1056

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

1059
        sync.RWMutex
1060
}
1061

1062
// String returns a string representation of the channel.
1063
func (c *OpenChannel) String() string {
3✔
1064
        indexStr := "height=%v, local_htlc_index=%v, local_log_index=%v, " +
3✔
1065
                "remote_htlc_index=%v, remote_log_index=%v"
3✔
1066

3✔
1067
        commit := c.LocalCommitment
3✔
1068
        local := fmt.Sprintf(indexStr, commit.CommitHeight,
3✔
1069
                commit.LocalHtlcIndex, commit.LocalLogIndex,
3✔
1070
                commit.RemoteHtlcIndex, commit.RemoteLogIndex,
3✔
1071
        )
3✔
1072

3✔
1073
        commit = c.RemoteCommitment
3✔
1074
        remote := fmt.Sprintf(indexStr, commit.CommitHeight,
3✔
1075
                commit.LocalHtlcIndex, commit.LocalLogIndex,
3✔
1076
                commit.RemoteHtlcIndex, commit.RemoteLogIndex,
3✔
1077
        )
3✔
1078

3✔
1079
        return fmt.Sprintf("SCID=%v, status=%v, initiator=%v, pending=%v, "+
3✔
1080
                "local commitment has %s, remote commitment has %s",
3✔
1081
                c.ShortChannelID, c.chanStatus, c.IsInitiator, c.IsPending,
3✔
1082
                local, remote,
3✔
1083
        )
3✔
1084
}
3✔
1085

1086
// Initiator returns the ChannelParty that originally opened this channel.
1087
func (c *OpenChannel) Initiator() lntypes.ChannelParty {
3✔
1088
        c.RLock()
3✔
1089
        defer c.RUnlock()
3✔
1090

3✔
1091
        if c.IsInitiator {
6✔
1092
                return lntypes.Local
3✔
1093
        }
3✔
1094

1095
        return lntypes.Remote
3✔
1096
}
1097

1098
// ShortChanID returns the current ShortChannelID of this channel.
1099
func (c *OpenChannel) ShortChanID() lnwire.ShortChannelID {
3✔
1100
        c.RLock()
3✔
1101
        defer c.RUnlock()
3✔
1102

3✔
1103
        return c.ShortChannelID
3✔
1104
}
3✔
1105

1106
// ZeroConfRealScid returns the zero-conf channel's confirmed scid. This should
1107
// only be called if IsZeroConf returns true.
1108
func (c *OpenChannel) ZeroConfRealScid() lnwire.ShortChannelID {
3✔
1109
        c.RLock()
3✔
1110
        defer c.RUnlock()
3✔
1111

3✔
1112
        return c.confirmedScid
3✔
1113
}
3✔
1114

1115
// ZeroConfConfirmed returns whether the zero-conf channel has confirmed. This
1116
// should only be called if IsZeroConf returns true.
1117
func (c *OpenChannel) ZeroConfConfirmed() bool {
3✔
1118
        c.RLock()
3✔
1119
        defer c.RUnlock()
3✔
1120

3✔
1121
        return c.confirmedScid != hop.Source
3✔
1122
}
3✔
1123

1124
// IsZeroConf returns whether the option_zeroconf channel type was negotiated.
1125
func (c *OpenChannel) IsZeroConf() bool {
3✔
1126
        c.RLock()
3✔
1127
        defer c.RUnlock()
3✔
1128

3✔
1129
        return c.ChanType.HasZeroConf()
3✔
1130
}
3✔
1131

1132
// IsOptionScidAlias returns whether the option_scid_alias channel type was
1133
// negotiated.
1134
func (c *OpenChannel) IsOptionScidAlias() bool {
×
1135
        c.RLock()
×
1136
        defer c.RUnlock()
×
1137

×
1138
        return c.ChanType.HasScidAliasChan()
×
1139
}
×
1140

1141
// NegotiatedAliasFeature returns whether the option-scid-alias feature bit was
1142
// negotiated.
1143
func (c *OpenChannel) NegotiatedAliasFeature() bool {
3✔
1144
        c.RLock()
3✔
1145
        defer c.RUnlock()
3✔
1146

3✔
1147
        return c.ChanType.HasScidAliasFeature()
3✔
1148
}
3✔
1149

1150
// ChanStatus returns the current ChannelStatus of this channel.
1151
func (c *OpenChannel) ChanStatus() ChannelStatus {
3✔
1152
        c.RLock()
3✔
1153
        defer c.RUnlock()
3✔
1154

3✔
1155
        return c.chanStatus
3✔
1156
}
3✔
1157

1158
// ApplyChanStatus allows the caller to modify the internal channel state in a
1159
// thead-safe manner.
1160
func (c *OpenChannel) ApplyChanStatus(status ChannelStatus) error {
×
1161
        c.Lock()
×
1162
        defer c.Unlock()
×
1163

×
1164
        return c.putChanStatus(status)
×
1165
}
×
1166

1167
// ClearChanStatus allows the caller to clear a particular channel status from
1168
// the primary channel status bit field. After this method returns, a call to
1169
// HasChanStatus(status) should return false.
1170
func (c *OpenChannel) ClearChanStatus(status ChannelStatus) error {
×
1171
        c.Lock()
×
1172
        defer c.Unlock()
×
1173

×
1174
        return c.clearChanStatus(status)
×
1175
}
×
1176

1177
// HasChanStatus returns true if the internal bitfield channel status of the
1178
// target channel has the specified status bit set.
1179
func (c *OpenChannel) HasChanStatus(status ChannelStatus) bool {
3✔
1180
        c.RLock()
3✔
1181
        defer c.RUnlock()
3✔
1182

3✔
1183
        return c.hasChanStatus(status)
3✔
1184
}
3✔
1185

1186
func (c *OpenChannel) hasChanStatus(status ChannelStatus) bool {
3✔
1187
        // Special case ChanStatusDefualt since it isn't actually flag, but a
3✔
1188
        // particular combination (or lack-there-of) of flags.
3✔
1189
        if status == ChanStatusDefault {
6✔
1190
                return c.chanStatus == ChanStatusDefault
3✔
1191
        }
3✔
1192

1193
        return c.chanStatus&status == status
3✔
1194
}
1195

1196
// BroadcastHeight returns the height at which the funding tx was broadcast.
1197
func (c *OpenChannel) BroadcastHeight() uint32 {
3✔
1198
        c.RLock()
3✔
1199
        defer c.RUnlock()
3✔
1200

3✔
1201
        return c.FundingBroadcastHeight
3✔
1202
}
3✔
1203

1204
// SetBroadcastHeight sets the FundingBroadcastHeight.
1205
func (c *OpenChannel) SetBroadcastHeight(height uint32) {
3✔
1206
        c.Lock()
3✔
1207
        defer c.Unlock()
3✔
1208

3✔
1209
        c.FundingBroadcastHeight = height
3✔
1210
}
3✔
1211

1212
// amendTlvData updates the channel with the given auxiliary TLV data.
1213
func (c *OpenChannel) amendTlvData(auxData openChannelTlvData) {
3✔
1214
        c.RevocationKeyLocator = auxData.revokeKeyLoc.Val.KeyLocator
3✔
1215
        c.InitialLocalBalance = lnwire.MilliSatoshi(
3✔
1216
                auxData.initialLocalBalance.Val,
3✔
1217
        )
3✔
1218
        c.InitialRemoteBalance = lnwire.MilliSatoshi(
3✔
1219
                auxData.initialRemoteBalance.Val,
3✔
1220
        )
3✔
1221
        c.confirmedScid = auxData.realScid.Val
3✔
1222
        c.ConfirmationHeight = auxData.confirmationHeight.Val
3✔
1223

3✔
1224
        auxData.memo.WhenSomeV(func(memo []byte) {
6✔
1225
                c.Memo = memo
3✔
1226
        })
3✔
1227
        auxData.tapscriptRoot.WhenSomeV(func(h [32]byte) {
3✔
1228
                c.TapscriptRoot = fn.Some[chainhash.Hash](h)
×
1229
        })
×
1230
        auxData.customBlob.WhenSomeV(func(blob tlv.Blob) {
3✔
1231
                c.CustomBlob = fn.Some(blob)
×
1232
        })
×
1233
}
1234

1235
// extractTlvData creates a new openChannelTlvData from the given channel.
1236
func (c *OpenChannel) extractTlvData() openChannelTlvData {
3✔
1237
        auxData := openChannelTlvData{
3✔
1238
                revokeKeyLoc: tlv.NewRecordT[tlv.TlvType1](
3✔
1239
                        keyLocRecord{c.RevocationKeyLocator},
3✔
1240
                ),
3✔
1241
                initialLocalBalance: tlv.NewPrimitiveRecord[tlv.TlvType2](
3✔
1242
                        uint64(c.InitialLocalBalance),
3✔
1243
                ),
3✔
1244
                initialRemoteBalance: tlv.NewPrimitiveRecord[tlv.TlvType3](
3✔
1245
                        uint64(c.InitialRemoteBalance),
3✔
1246
                ),
3✔
1247
                realScid: tlv.NewRecordT[tlv.TlvType4](
3✔
1248
                        c.confirmedScid,
3✔
1249
                ),
3✔
1250
                confirmationHeight: tlv.NewPrimitiveRecord[tlv.TlvType8](
3✔
1251
                        c.ConfirmationHeight,
3✔
1252
                ),
3✔
1253
        }
3✔
1254

3✔
1255
        if len(c.Memo) != 0 {
6✔
1256
                auxData.memo = tlv.SomeRecordT(
3✔
1257
                        tlv.NewPrimitiveRecord[tlv.TlvType5](c.Memo),
3✔
1258
                )
3✔
1259
        }
3✔
1260
        c.TapscriptRoot.WhenSome(func(h chainhash.Hash) {
3✔
1261
                auxData.tapscriptRoot = tlv.SomeRecordT(
×
1262
                        tlv.NewPrimitiveRecord[tlv.TlvType6, [32]byte](h),
×
1263
                )
×
1264
        })
×
1265
        c.CustomBlob.WhenSome(func(blob tlv.Blob) {
3✔
1266
                auxData.customBlob = tlv.SomeRecordT(
×
1267
                        tlv.NewPrimitiveRecord[tlv.TlvType7](blob),
×
1268
                )
×
1269
        })
×
1270

1271
        return auxData
3✔
1272
}
1273

1274
// Refresh updates the in-memory channel state using the latest state observed
1275
// on disk.
1276
func (c *OpenChannel) Refresh() error {
3✔
1277
        c.Lock()
3✔
1278
        defer c.Unlock()
3✔
1279

3✔
1280
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
1281
                chanBucket, err := fetchChanBucket(
3✔
1282
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1283
                )
3✔
1284
                if err != nil {
6✔
1285
                        return err
3✔
1286
                }
3✔
1287

1288
                // We'll re-populating the in-memory channel with the info
1289
                // fetched from disk.
1290
                if err := fetchChanInfo(chanBucket, c); err != nil {
3✔
1291
                        return fmt.Errorf("unable to fetch chan info: %w", err)
×
1292
                }
×
1293

1294
                // Also populate the channel's commitment states for both sides
1295
                // of the channel.
1296
                if err := fetchChanCommitments(chanBucket, c); err != nil {
3✔
1297
                        return fmt.Errorf("unable to fetch chan commitments: "+
×
1298
                                "%v", err)
×
1299
                }
×
1300

1301
                // Also retrieve the current revocation state.
1302
                if err := fetchChanRevocationState(chanBucket, c); err != nil {
3✔
1303
                        return fmt.Errorf("unable to fetch chan revocations: "+
×
1304
                                "%v", err)
×
1305
                }
×
1306

1307
                return nil
3✔
1308
        }, func() {})
3✔
1309
        if err != nil {
6✔
1310
                return err
3✔
1311
        }
3✔
1312

1313
        return nil
3✔
1314
}
1315

1316
// fetchChanBucket is a helper function that returns the bucket where a
1317
// channel's data resides in given: the public key for the node, the outpoint,
1318
// and the chainhash that the channel resides on.
1319
func fetchChanBucket(tx kvdb.RTx, nodeKey *btcec.PublicKey,
1320
        outPoint *wire.OutPoint, chainHash chainhash.Hash) (kvdb.RBucket, error) {
3✔
1321

3✔
1322
        // First fetch the top level bucket which stores all data related to
3✔
1323
        // current, active channels.
3✔
1324
        openChanBucket := tx.ReadBucket(openChannelBucket)
3✔
1325
        if openChanBucket == nil {
3✔
1326
                return nil, ErrNoChanDBExists
×
1327
        }
×
1328

1329
        // TODO(roasbeef): CreateTopLevelBucket on the interface isn't like
1330
        // CreateIfNotExists, will return error
1331

1332
        // Within this top level bucket, fetch the bucket dedicated to storing
1333
        // open channel data specific to the remote node.
1334
        nodePub := nodeKey.SerializeCompressed()
3✔
1335
        nodeChanBucket := openChanBucket.NestedReadBucket(nodePub)
3✔
1336
        if nodeChanBucket == nil {
3✔
1337
                return nil, ErrNoActiveChannels
×
1338
        }
×
1339

1340
        // We'll then recurse down an additional layer in order to fetch the
1341
        // bucket for this particular chain.
1342
        chainBucket := nodeChanBucket.NestedReadBucket(chainHash[:])
3✔
1343
        if chainBucket == nil {
3✔
1344
                return nil, ErrNoActiveChannels
×
1345
        }
×
1346

1347
        // With the bucket for the node and chain fetched, we can now go down
1348
        // another level, for this channel itself.
1349
        var chanPointBuf bytes.Buffer
3✔
1350
        if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
3✔
1351
                return nil, err
×
1352
        }
×
1353
        chanBucket := chainBucket.NestedReadBucket(chanPointBuf.Bytes())
3✔
1354
        if chanBucket == nil {
6✔
1355
                return nil, ErrChannelNotFound
3✔
1356
        }
3✔
1357

1358
        return chanBucket, nil
3✔
1359
}
1360

1361
// fetchChanBucketRw is a helper function that returns the bucket where a
1362
// channel's data resides in given: the public key for the node, the outpoint,
1363
// and the chainhash that the channel resides on. This differs from
1364
// fetchChanBucket in that it returns a writeable bucket.
1365
func fetchChanBucketRw(tx kvdb.RwTx, nodeKey *btcec.PublicKey,
1366
        outPoint *wire.OutPoint, chainHash chainhash.Hash) (kvdb.RwBucket,
1367
        error) {
3✔
1368

3✔
1369
        // First fetch the top level bucket which stores all data related to
3✔
1370
        // current, active channels.
3✔
1371
        openChanBucket := tx.ReadWriteBucket(openChannelBucket)
3✔
1372
        if openChanBucket == nil {
3✔
1373
                return nil, ErrNoChanDBExists
×
1374
        }
×
1375

1376
        // TODO(roasbeef): CreateTopLevelBucket on the interface isn't like
1377
        // CreateIfNotExists, will return error
1378

1379
        // Within this top level bucket, fetch the bucket dedicated to storing
1380
        // open channel data specific to the remote node.
1381
        nodePub := nodeKey.SerializeCompressed()
3✔
1382
        nodeChanBucket := openChanBucket.NestedReadWriteBucket(nodePub)
3✔
1383
        if nodeChanBucket == nil {
3✔
1384
                return nil, ErrNoActiveChannels
×
1385
        }
×
1386

1387
        // We'll then recurse down an additional layer in order to fetch the
1388
        // bucket for this particular chain.
1389
        chainBucket := nodeChanBucket.NestedReadWriteBucket(chainHash[:])
3✔
1390
        if chainBucket == nil {
3✔
1391
                return nil, ErrNoActiveChannels
×
1392
        }
×
1393

1394
        // With the bucket for the node and chain fetched, we can now go down
1395
        // another level, for this channel itself.
1396
        var chanPointBuf bytes.Buffer
3✔
1397
        if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
3✔
1398
                return nil, err
×
1399
        }
×
1400
        chanBucket := chainBucket.NestedReadWriteBucket(chanPointBuf.Bytes())
3✔
1401
        if chanBucket == nil {
4✔
1402
                return nil, ErrChannelNotFound
1✔
1403
        }
1✔
1404

1405
        return chanBucket, nil
3✔
1406
}
1407

1408
func fetchFinalHtlcsBucketRw(tx kvdb.RwTx,
1409
        chanID lnwire.ShortChannelID) (kvdb.RwBucket, error) {
3✔
1410

3✔
1411
        finalHtlcsBucket, err := tx.CreateTopLevelBucket(finalHtlcsBucket)
3✔
1412
        if err != nil {
3✔
1413
                return nil, err
×
1414
        }
×
1415

1416
        var chanIDBytes [8]byte
3✔
1417
        byteOrder.PutUint64(chanIDBytes[:], chanID.ToUint64())
3✔
1418
        chanBucket, err := finalHtlcsBucket.CreateBucketIfNotExists(
3✔
1419
                chanIDBytes[:],
3✔
1420
        )
3✔
1421
        if err != nil {
3✔
1422
                return nil, err
×
1423
        }
×
1424

1425
        return chanBucket, nil
3✔
1426
}
1427

1428
// fullSync syncs the contents of an OpenChannel while re-using an existing
1429
// database transaction.
1430
func (c *OpenChannel) fullSync(tx kvdb.RwTx) error {
3✔
1431
        // Fetch the outpoint bucket and check if the outpoint already exists.
3✔
1432
        opBucket := tx.ReadWriteBucket(outpointBucket)
3✔
1433
        if opBucket == nil {
3✔
1434
                return ErrNoChanDBExists
×
1435
        }
×
1436
        cidBucket := tx.ReadWriteBucket(chanIDBucket)
3✔
1437
        if cidBucket == nil {
3✔
1438
                return ErrNoChanDBExists
×
1439
        }
×
1440

1441
        var chanPointBuf bytes.Buffer
3✔
1442
        err := graphdb.WriteOutpoint(&chanPointBuf, &c.FundingOutpoint)
3✔
1443
        if err != nil {
3✔
1444
                return err
×
1445
        }
×
1446

1447
        // Now, check if the outpoint exists in our index.
1448
        if opBucket.Get(chanPointBuf.Bytes()) != nil {
6✔
1449
                return ErrChanAlreadyExists
3✔
1450
        }
3✔
1451

1452
        cid := lnwire.NewChanIDFromOutPoint(c.FundingOutpoint)
3✔
1453
        if cidBucket.Get(cid[:]) != nil {
3✔
1454
                return ErrChanAlreadyExists
×
1455
        }
×
1456

1457
        status := uint8(outpointOpen)
3✔
1458

3✔
1459
        // Write the status of this outpoint as the first entry in a tlv
3✔
1460
        // stream.
3✔
1461
        statusRecord := tlv.MakePrimitiveRecord(indexStatusType, &status)
3✔
1462
        opStream, err := tlv.NewStream(statusRecord)
3✔
1463
        if err != nil {
3✔
1464
                return err
×
1465
        }
×
1466

1467
        var b bytes.Buffer
3✔
1468
        if err := opStream.Encode(&b); err != nil {
3✔
1469
                return err
×
1470
        }
×
1471

1472
        // Add the outpoint to our outpoint index with the tlv stream.
1473
        if err := opBucket.Put(chanPointBuf.Bytes(), b.Bytes()); err != nil {
3✔
1474
                return err
×
1475
        }
×
1476

1477
        if err := cidBucket.Put(cid[:], []byte{}); err != nil {
3✔
1478
                return err
×
1479
        }
×
1480

1481
        // First fetch the top level bucket which stores all data related to
1482
        // current, active channels.
1483
        openChanBucket, err := tx.CreateTopLevelBucket(openChannelBucket)
3✔
1484
        if err != nil {
3✔
1485
                return err
×
1486
        }
×
1487

1488
        // Within this top level bucket, fetch the bucket dedicated to storing
1489
        // open channel data specific to the remote node.
1490
        nodePub := c.IdentityPub.SerializeCompressed()
3✔
1491
        nodeChanBucket, err := openChanBucket.CreateBucketIfNotExists(nodePub)
3✔
1492
        if err != nil {
3✔
1493
                return err
×
1494
        }
×
1495

1496
        // We'll then recurse down an additional layer in order to fetch the
1497
        // bucket for this particular chain.
1498
        chainBucket, err := nodeChanBucket.CreateBucketIfNotExists(c.ChainHash[:])
3✔
1499
        if err != nil {
3✔
1500
                return err
×
1501
        }
×
1502

1503
        // With the bucket for the node fetched, we can now go down another
1504
        // level, creating the bucket for this channel itself.
1505
        chanBucket, err := chainBucket.CreateBucket(
3✔
1506
                chanPointBuf.Bytes(),
3✔
1507
        )
3✔
1508
        switch {
3✔
1509
        case err == kvdb.ErrBucketExists:
×
1510
                // If this channel already exists, then in order to avoid
×
1511
                // overriding it, we'll return an error back up to the caller.
×
1512
                return ErrChanAlreadyExists
×
1513
        case err != nil:
×
1514
                return err
×
1515
        }
1516

1517
        return putOpenChannel(chanBucket, c)
3✔
1518
}
1519

1520
// MarkConfirmationHeight updates the channel's confirmation height once the
1521
// channel opening transaction receives one confirmation.
1522
func (c *OpenChannel) MarkConfirmationHeight(height uint32) error {
3✔
1523
        c.Lock()
3✔
1524
        defer c.Unlock()
3✔
1525

3✔
1526
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
1527
                chanBucket, err := fetchChanBucketRw(
3✔
1528
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1529
                )
3✔
1530
                if err != nil {
3✔
NEW
1531
                        return err
×
NEW
1532
                }
×
1533

1534
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
3✔
1535
                if err != nil {
3✔
NEW
1536
                        return err
×
NEW
1537
                }
×
1538

1539
                channel.ConfirmationHeight = height
3✔
1540

3✔
1541
                return putOpenChannel(chanBucket, channel)
3✔
1542
        }, func() {}); err != nil {
3✔
NEW
1543
                return err
×
NEW
1544
        }
×
1545

1546
        c.ConfirmationHeight = height
3✔
1547

3✔
1548
        return nil
3✔
1549
}
1550

1551
// MarkAsOpen marks a channel as fully open given a locator that uniquely
1552
// describes its location within the chain.
1553
func (c *OpenChannel) MarkAsOpen(openLoc lnwire.ShortChannelID) error {
3✔
1554
        c.Lock()
3✔
1555
        defer c.Unlock()
3✔
1556

3✔
1557
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
1558
                chanBucket, err := fetchChanBucketRw(
3✔
1559
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1560
                )
3✔
1561
                if err != nil {
3✔
1562
                        return err
×
1563
                }
×
1564

1565
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
3✔
1566
                if err != nil {
3✔
1567
                        return err
×
1568
                }
×
1569

1570
                channel.IsPending = false
3✔
1571
                channel.ShortChannelID = openLoc
3✔
1572

3✔
1573
                return putOpenChannel(chanBucket, channel)
3✔
1574
        }, func() {}); err != nil {
3✔
1575
                return err
×
1576
        }
×
1577

1578
        c.IsPending = false
3✔
1579
        c.ShortChannelID = openLoc
3✔
1580
        c.Packager = NewChannelPackager(openLoc)
3✔
1581

3✔
1582
        return nil
3✔
1583
}
1584

1585
// MarkRealScid marks the zero-conf channel's confirmed ShortChannelID. This
1586
// should only be done if IsZeroConf returns true.
1587
func (c *OpenChannel) MarkRealScid(realScid lnwire.ShortChannelID) error {
3✔
1588
        c.Lock()
3✔
1589
        defer c.Unlock()
3✔
1590

3✔
1591
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
1592
                chanBucket, err := fetchChanBucketRw(
3✔
1593
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1594
                )
3✔
1595
                if err != nil {
3✔
1596
                        return err
×
1597
                }
×
1598

1599
                channel, err := fetchOpenChannel(
3✔
1600
                        chanBucket, &c.FundingOutpoint,
3✔
1601
                )
3✔
1602
                if err != nil {
3✔
1603
                        return err
×
1604
                }
×
1605

1606
                channel.confirmedScid = realScid
3✔
1607

3✔
1608
                return putOpenChannel(chanBucket, channel)
3✔
1609
        }, func() {}); err != nil {
3✔
1610
                return err
×
1611
        }
×
1612

1613
        c.confirmedScid = realScid
3✔
1614

3✔
1615
        return nil
3✔
1616
}
1617

1618
// MarkScidAliasNegotiated adds ScidAliasFeatureBit to ChanType in-memory and
1619
// in the database.
1620
func (c *OpenChannel) MarkScidAliasNegotiated() error {
3✔
1621
        c.Lock()
3✔
1622
        defer c.Unlock()
3✔
1623

3✔
1624
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
1625
                chanBucket, err := fetchChanBucketRw(
3✔
1626
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1627
                )
3✔
1628
                if err != nil {
3✔
1629
                        return err
×
1630
                }
×
1631

1632
                channel, err := fetchOpenChannel(
3✔
1633
                        chanBucket, &c.FundingOutpoint,
3✔
1634
                )
3✔
1635
                if err != nil {
3✔
1636
                        return err
×
1637
                }
×
1638

1639
                channel.ChanType |= ScidAliasFeatureBit
3✔
1640
                return putOpenChannel(chanBucket, channel)
3✔
1641
        }, func() {}); err != nil {
3✔
1642
                return err
×
1643
        }
×
1644

1645
        c.ChanType |= ScidAliasFeatureBit
3✔
1646

3✔
1647
        return nil
3✔
1648
}
1649

1650
// MarkDataLoss marks sets the channel status to LocalDataLoss and stores the
1651
// passed commitPoint for use to retrieve funds in case the remote force closes
1652
// the channel.
1653
func (c *OpenChannel) MarkDataLoss(commitPoint *btcec.PublicKey) error {
3✔
1654
        c.Lock()
3✔
1655
        defer c.Unlock()
3✔
1656

3✔
1657
        var b bytes.Buffer
3✔
1658
        if err := WriteElement(&b, commitPoint); err != nil {
3✔
1659
                return err
×
1660
        }
×
1661

1662
        putCommitPoint := func(chanBucket kvdb.RwBucket) error {
6✔
1663
                return chanBucket.Put(dataLossCommitPointKey, b.Bytes())
3✔
1664
        }
3✔
1665

1666
        return c.putChanStatus(ChanStatusLocalDataLoss, putCommitPoint)
3✔
1667
}
1668

1669
// DataLossCommitPoint retrieves the stored commit point set during
1670
// MarkDataLoss. If not found ErrNoCommitPoint is returned.
1671
func (c *OpenChannel) DataLossCommitPoint() (*btcec.PublicKey, error) {
×
1672
        var commitPoint *btcec.PublicKey
×
1673

×
1674
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
×
1675
                chanBucket, err := fetchChanBucket(
×
1676
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
×
1677
                )
×
1678
                switch err {
×
1679
                case nil:
×
1680
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
×
1681
                        return ErrNoCommitPoint
×
1682
                default:
×
1683
                        return err
×
1684
                }
1685

1686
                bs := chanBucket.Get(dataLossCommitPointKey)
×
1687
                if bs == nil {
×
1688
                        return ErrNoCommitPoint
×
1689
                }
×
1690
                r := bytes.NewReader(bs)
×
1691
                if err := ReadElements(r, &commitPoint); err != nil {
×
1692
                        return err
×
1693
                }
×
1694

1695
                return nil
×
1696
        }, func() {
×
1697
                commitPoint = nil
×
1698
        })
×
1699
        if err != nil {
×
1700
                return nil, err
×
1701
        }
×
1702

1703
        return commitPoint, nil
×
1704
}
1705

1706
// MarkBorked marks the event when the channel as reached an irreconcilable
1707
// state, such as a channel breach or state desynchronization. Borked channels
1708
// should never be added to the switch.
1709
func (c *OpenChannel) MarkBorked() error {
3✔
1710
        c.Lock()
3✔
1711
        defer c.Unlock()
3✔
1712

3✔
1713
        return c.putChanStatus(ChanStatusBorked)
3✔
1714
}
3✔
1715

1716
// SecondCommitmentPoint returns the second per-commitment-point for use in the
1717
// channel_ready message.
1718
func (c *OpenChannel) SecondCommitmentPoint() (*btcec.PublicKey, error) {
3✔
1719
        c.RLock()
3✔
1720
        defer c.RUnlock()
3✔
1721

3✔
1722
        // Since we start at commitment height = 0, the second per commitment
3✔
1723
        // point is actually at the 1st index.
3✔
1724
        revocation, err := c.RevocationProducer.AtIndex(1)
3✔
1725
        if err != nil {
3✔
1726
                return nil, err
×
1727
        }
×
1728

1729
        return input.ComputeCommitmentPoint(revocation[:]), nil
3✔
1730
}
1731

1732
var (
1733
        // taprootRevRootKey is the key used to derive the revocation root for
1734
        // the taproot nonces. This is done via HMAC of the existing revocation
1735
        // root.
1736
        taprootRevRootKey = []byte("taproot-rev-root")
1737
)
1738

1739
// DeriveMusig2Shachain derives a shachain producer for the taproot channel
1740
// from normal shachain revocation root.
1741
func DeriveMusig2Shachain(revRoot shachain.Producer) (shachain.Producer, error) { //nolint:ll
3✔
1742
        // In order to obtain the revocation root hash to create the taproot
3✔
1743
        // revocation, we'll encode the producer into a buffer, then use that
3✔
1744
        // to derive the shachain root needed.
3✔
1745
        var rootHashBuf bytes.Buffer
3✔
1746
        if err := revRoot.Encode(&rootHashBuf); err != nil {
3✔
1747
                return nil, fmt.Errorf("unable to encode producer: %w", err)
×
1748
        }
×
1749

1750
        revRootHash := chainhash.HashH(rootHashBuf.Bytes())
3✔
1751

3✔
1752
        // For taproot channel types, we'll also generate a distinct shachain
3✔
1753
        // root using the same seed information. We'll use this to generate
3✔
1754
        // verification nonces for the channel. We'll bind with this a simple
3✔
1755
        // hmac.
3✔
1756
        taprootRevHmac := hmac.New(sha256.New, taprootRevRootKey)
3✔
1757
        if _, err := taprootRevHmac.Write(revRootHash[:]); err != nil {
3✔
1758
                return nil, err
×
1759
        }
×
1760

1761
        taprootRevRoot := taprootRevHmac.Sum(nil)
3✔
1762

3✔
1763
        // Once we have the root, we can then generate our shachain producer
3✔
1764
        // and from that generate the per-commitment point.
3✔
1765
        return shachain.NewRevocationProducerFromBytes(
3✔
1766
                taprootRevRoot,
3✔
1767
        )
3✔
1768
}
1769

1770
// NewMusigVerificationNonce generates the local or verification nonce for
1771
// another musig2 session. In order to permit our implementation to not have to
1772
// write any secret nonce state to disk, we'll use the _next_ shachain
1773
// pre-image as our primary randomness source. When used to generate the nonce
1774
// again to broadcast our commitment hte current height will be used.
1775
func NewMusigVerificationNonce(pubKey *btcec.PublicKey, targetHeight uint64,
1776
        shaGen shachain.Producer) (*musig2.Nonces, error) {
3✔
1777

3✔
1778
        // Now that we know what height we need, we'll grab the shachain
3✔
1779
        // pre-image at the target destination.
3✔
1780
        nextPreimage, err := shaGen.AtIndex(targetHeight)
3✔
1781
        if err != nil {
3✔
1782
                return nil, err
×
1783
        }
×
1784

1785
        shaChainRand := musig2.WithCustomRand(bytes.NewBuffer(nextPreimage[:]))
3✔
1786
        pubKeyOpt := musig2.WithPublicKey(pubKey)
3✔
1787

3✔
1788
        return musig2.GenNonces(pubKeyOpt, shaChainRand)
3✔
1789
}
1790

1791
// ChanSyncMsg returns the ChannelReestablish message that should be sent upon
1792
// reconnection with the remote peer that we're maintaining this channel with.
1793
// The information contained within this message is necessary to re-sync our
1794
// commitment chains in the case of a last or only partially processed message.
1795
// When the remote party receives this message one of three things may happen:
1796
//
1797
//  1. We're fully synced and no messages need to be sent.
1798
//  2. We didn't get the last CommitSig message they sent, so they'll re-send
1799
//     it.
1800
//  3. We didn't get the last RevokeAndAck message they sent, so they'll
1801
//     re-send it.
1802
//
1803
// If this is a restored channel, having status ChanStatusRestored, then we'll
1804
// modify our typical chan sync message to ensure they force close even if
1805
// we're on the very first state.
1806
func (c *OpenChannel) ChanSyncMsg() (*lnwire.ChannelReestablish, error) {
3✔
1807
        c.Lock()
3✔
1808
        defer c.Unlock()
3✔
1809

3✔
1810
        // The remote commitment height that we'll send in the
3✔
1811
        // ChannelReestablish message is our current commitment height plus
3✔
1812
        // one. If the receiver thinks that our commitment height is actually
3✔
1813
        // *equal* to this value, then they'll re-send the last commitment that
3✔
1814
        // they sent but we never fully processed.
3✔
1815
        localHeight := c.LocalCommitment.CommitHeight
3✔
1816
        nextLocalCommitHeight := localHeight + 1
3✔
1817

3✔
1818
        // The second value we'll send is the height of the remote commitment
3✔
1819
        // from our PoV. If the receiver thinks that their height is actually
3✔
1820
        // *one plus* this value, then they'll re-send their last revocation.
3✔
1821
        remoteChainTipHeight := c.RemoteCommitment.CommitHeight
3✔
1822

3✔
1823
        // If this channel has undergone a commitment update, then in order to
3✔
1824
        // prove to the remote party our knowledge of their prior commitment
3✔
1825
        // state, we'll also send over the last commitment secret that the
3✔
1826
        // remote party sent.
3✔
1827
        var lastCommitSecret [32]byte
3✔
1828
        if remoteChainTipHeight != 0 {
6✔
1829
                remoteSecret, err := c.RevocationStore.LookUp(
3✔
1830
                        remoteChainTipHeight - 1,
3✔
1831
                )
3✔
1832
                if err != nil {
3✔
1833
                        return nil, err
×
1834
                }
×
1835
                lastCommitSecret = [32]byte(*remoteSecret)
3✔
1836
        }
1837

1838
        // Additionally, we'll send over the current unrevoked commitment on
1839
        // our local commitment transaction.
1840
        currentCommitSecret, err := c.RevocationProducer.AtIndex(
3✔
1841
                localHeight,
3✔
1842
        )
3✔
1843
        if err != nil {
3✔
1844
                return nil, err
×
1845
        }
×
1846

1847
        // If we've restored this channel, then we'll purposefully give them an
1848
        // invalid LocalUnrevokedCommitPoint so they'll force close the channel
1849
        // allowing us to sweep our funds.
1850
        if c.hasChanStatus(ChanStatusRestored) {
6✔
1851
                currentCommitSecret[0] ^= 1
3✔
1852

3✔
1853
                // If this is a tweakless channel, then we'll purposefully send
3✔
1854
                // a next local height taht's invalid to trigger a force close
3✔
1855
                // on their end. We do this as tweakless channels don't require
3✔
1856
                // that the commitment point is valid, only that it's present.
3✔
1857
                if c.ChanType.IsTweakless() {
6✔
1858
                        nextLocalCommitHeight = 0
3✔
1859
                }
3✔
1860
        }
1861

1862
        // If this is a taproot channel, then we'll need to generate our next
1863
        // verification nonce to send to the remote party. They'll use this to
1864
        // sign the next update to our commitment transaction.
1865
        var nextTaprootNonce lnwire.OptMusig2NonceTLV
3✔
1866
        if c.ChanType.IsTaproot() {
6✔
1867
                taprootRevProducer, err := DeriveMusig2Shachain(
3✔
1868
                        c.RevocationProducer,
3✔
1869
                )
3✔
1870
                if err != nil {
3✔
1871
                        return nil, err
×
1872
                }
×
1873

1874
                nextNonce, err := NewMusigVerificationNonce(
3✔
1875
                        c.LocalChanCfg.MultiSigKey.PubKey,
3✔
1876
                        nextLocalCommitHeight, taprootRevProducer,
3✔
1877
                )
3✔
1878
                if err != nil {
3✔
1879
                        return nil, fmt.Errorf("unable to gen next "+
×
1880
                                "nonce: %w", err)
×
1881
                }
×
1882

1883
                nextTaprootNonce = lnwire.SomeMusig2Nonce(nextNonce.PubNonce)
3✔
1884
        }
1885

1886
        return &lnwire.ChannelReestablish{
3✔
1887
                ChanID: lnwire.NewChanIDFromOutPoint(
3✔
1888
                        c.FundingOutpoint,
3✔
1889
                ),
3✔
1890
                NextLocalCommitHeight:  nextLocalCommitHeight,
3✔
1891
                RemoteCommitTailHeight: remoteChainTipHeight,
3✔
1892
                LastRemoteCommitSecret: lastCommitSecret,
3✔
1893
                LocalUnrevokedCommitPoint: input.ComputeCommitmentPoint(
3✔
1894
                        currentCommitSecret[:],
3✔
1895
                ),
3✔
1896
                LocalNonce: nextTaprootNonce,
3✔
1897
        }, nil
3✔
1898
}
1899

1900
// MarkShutdownSent serialises and persist the given ShutdownInfo for this
1901
// channel. Persisting this info represents the fact that we have sent the
1902
// Shutdown message to the remote side and hence that we should re-transmit the
1903
// same Shutdown message on re-establish.
1904
func (c *OpenChannel) MarkShutdownSent(info *ShutdownInfo) error {
3✔
1905
        c.Lock()
3✔
1906
        defer c.Unlock()
3✔
1907

3✔
1908
        return c.storeShutdownInfo(info)
3✔
1909
}
3✔
1910

1911
// storeShutdownInfo serialises the ShutdownInfo and persists it under the
1912
// shutdownInfoKey.
1913
func (c *OpenChannel) storeShutdownInfo(info *ShutdownInfo) error {
3✔
1914
        var b bytes.Buffer
3✔
1915
        err := info.encode(&b)
3✔
1916
        if err != nil {
3✔
1917
                return err
×
1918
        }
×
1919

1920
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
1921
                chanBucket, err := fetchChanBucketRw(
3✔
1922
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1923
                )
3✔
1924
                if err != nil {
3✔
1925
                        return err
×
1926
                }
×
1927

1928
                return chanBucket.Put(shutdownInfoKey, b.Bytes())
3✔
1929
        }, func() {})
3✔
1930
}
1931

1932
// ShutdownInfo decodes the shutdown info stored for this channel and returns
1933
// the result. If no shutdown info has been persisted for this channel then the
1934
// ErrNoShutdownInfo error is returned.
1935
func (c *OpenChannel) ShutdownInfo() (fn.Option[ShutdownInfo], error) {
3✔
1936
        c.RLock()
3✔
1937
        defer c.RUnlock()
3✔
1938

3✔
1939
        var shutdownInfo *ShutdownInfo
3✔
1940
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
1941
                chanBucket, err := fetchChanBucket(
3✔
1942
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1943
                )
3✔
1944
                switch {
3✔
1945
                case err == nil:
3✔
1946
                case errors.Is(err, ErrNoChanDBExists),
1947
                        errors.Is(err, ErrNoActiveChannels),
1948
                        errors.Is(err, ErrChannelNotFound):
2✔
1949

2✔
1950
                        return ErrNoShutdownInfo
2✔
1951
                default:
×
1952
                        return err
×
1953
                }
1954

1955
                shutdownInfoBytes := chanBucket.Get(shutdownInfoKey)
3✔
1956
                if shutdownInfoBytes == nil {
6✔
1957
                        return ErrNoShutdownInfo
3✔
1958
                }
3✔
1959

1960
                shutdownInfo, err = decodeShutdownInfo(shutdownInfoBytes)
3✔
1961

3✔
1962
                return err
3✔
1963
        }, func() {
3✔
1964
                shutdownInfo = nil
3✔
1965
        })
3✔
1966
        if err != nil {
6✔
1967
                return fn.None[ShutdownInfo](), err
3✔
1968
        }
3✔
1969

1970
        return fn.Some[ShutdownInfo](*shutdownInfo), nil
3✔
1971
}
1972

1973
// isBorked returns true if the channel has been marked as borked in the
1974
// database. This requires an existing database transaction to already be
1975
// active.
1976
//
1977
// NOTE: The primary mutex should already be held before this method is called.
1978
func (c *OpenChannel) isBorked(chanBucket kvdb.RBucket) (bool, error) {
3✔
1979
        channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
3✔
1980
        if err != nil {
3✔
1981
                return false, err
×
1982
        }
×
1983

1984
        return channel.chanStatus != ChanStatusDefault, nil
3✔
1985
}
1986

1987
// MarkCommitmentBroadcasted marks the channel as a commitment transaction has
1988
// been broadcast, either our own or the remote, and we should watch the chain
1989
// for it to confirm before taking any further action. It takes as argument the
1990
// closing tx _we believe_ will appear in the chain. This is only used to
1991
// republish this tx at startup to ensure propagation, and we should still
1992
// handle the case where a different tx actually hits the chain.
1993
func (c *OpenChannel) MarkCommitmentBroadcasted(closeTx *wire.MsgTx,
1994
        closer lntypes.ChannelParty) error {
3✔
1995

3✔
1996
        return c.markBroadcasted(
3✔
1997
                ChanStatusCommitBroadcasted, forceCloseTxKey, closeTx,
3✔
1998
                closer,
3✔
1999
        )
3✔
2000
}
3✔
2001

2002
// MarkCoopBroadcasted marks the channel to indicate that a cooperative close
2003
// transaction has been broadcast, either our own or the remote, and that we
2004
// should watch the chain for it to confirm before taking further action. It
2005
// takes as argument a cooperative close tx that could appear on chain, and
2006
// should be rebroadcast upon startup. This is only used to republish and
2007
// ensure propagation, and we should still handle the case where a different tx
2008
// actually hits the chain.
2009
func (c *OpenChannel) MarkCoopBroadcasted(closeTx *wire.MsgTx,
2010
        closer lntypes.ChannelParty) error {
3✔
2011

3✔
2012
        return c.markBroadcasted(
3✔
2013
                ChanStatusCoopBroadcasted, coopCloseTxKey, closeTx,
3✔
2014
                closer,
3✔
2015
        )
3✔
2016
}
3✔
2017

2018
// markBroadcasted is a helper function which modifies the channel status of the
2019
// receiving channel and inserts a close transaction under the requested key,
2020
// which should specify either a coop or force close. It adds a status which
2021
// indicates the party that initiated the channel close.
2022
func (c *OpenChannel) markBroadcasted(status ChannelStatus, key []byte,
2023
        closeTx *wire.MsgTx, closer lntypes.ChannelParty) error {
3✔
2024

3✔
2025
        c.Lock()
3✔
2026
        defer c.Unlock()
3✔
2027

3✔
2028
        // If a closing tx is provided, we'll generate a closure to write the
3✔
2029
        // transaction in the appropriate bucket under the given key.
3✔
2030
        var putClosingTx func(kvdb.RwBucket) error
3✔
2031
        if closeTx != nil {
6✔
2032
                var b bytes.Buffer
3✔
2033
                if err := WriteElement(&b, closeTx); err != nil {
3✔
2034
                        return err
×
2035
                }
×
2036

2037
                putClosingTx = func(chanBucket kvdb.RwBucket) error {
6✔
2038
                        return chanBucket.Put(key, b.Bytes())
3✔
2039
                }
3✔
2040
        }
2041

2042
        // Add the initiator status to the status provided. These statuses are
2043
        // set in addition to the broadcast status so that we do not need to
2044
        // migrate the original logic which does not store initiator.
2045
        if closer.IsLocal() {
6✔
2046
                status |= ChanStatusLocalCloseInitiator
3✔
2047
        } else {
6✔
2048
                status |= ChanStatusRemoteCloseInitiator
3✔
2049
        }
3✔
2050

2051
        return c.putChanStatus(status, putClosingTx)
3✔
2052
}
2053

2054
// BroadcastedCommitment retrieves the stored unilateral closing tx set during
2055
// MarkCommitmentBroadcasted. If not found ErrNoCloseTx is returned.
2056
func (c *OpenChannel) BroadcastedCommitment() (*wire.MsgTx, error) {
3✔
2057
        return c.getClosingTx(forceCloseTxKey)
3✔
2058
}
3✔
2059

2060
// BroadcastedCooperative retrieves the stored cooperative closing tx set during
2061
// MarkCoopBroadcasted. If not found ErrNoCloseTx is returned.
2062
func (c *OpenChannel) BroadcastedCooperative() (*wire.MsgTx, error) {
3✔
2063
        return c.getClosingTx(coopCloseTxKey)
3✔
2064
}
3✔
2065

2066
// getClosingTx is a helper method which returns the stored closing transaction
2067
// for key. The caller should use either the force or coop closing keys.
2068
func (c *OpenChannel) getClosingTx(key []byte) (*wire.MsgTx, error) {
3✔
2069
        var closeTx *wire.MsgTx
3✔
2070

3✔
2071
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
2072
                chanBucket, err := fetchChanBucket(
3✔
2073
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
2074
                )
3✔
2075
                switch err {
3✔
2076
                case nil:
3✔
2077
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
×
2078
                        return ErrNoCloseTx
×
2079
                default:
×
2080
                        return err
×
2081
                }
2082

2083
                bs := chanBucket.Get(key)
3✔
2084
                if bs == nil {
6✔
2085
                        return ErrNoCloseTx
3✔
2086
                }
3✔
2087
                r := bytes.NewReader(bs)
3✔
2088
                return ReadElement(r, &closeTx)
3✔
2089
        }, func() {
3✔
2090
                closeTx = nil
3✔
2091
        })
3✔
2092
        if err != nil {
6✔
2093
                return nil, err
3✔
2094
        }
3✔
2095

2096
        return closeTx, nil
3✔
2097
}
2098

2099
// putChanStatus appends the given status to the channel. fs is an optional
2100
// list of closures that are given the chanBucket in order to atomically add
2101
// extra information together with the new status.
2102
func (c *OpenChannel) putChanStatus(status ChannelStatus,
2103
        fs ...func(kvdb.RwBucket) error) error {
3✔
2104

3✔
2105
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
2106
                chanBucket, err := fetchChanBucketRw(
3✔
2107
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
2108
                )
3✔
2109
                if err != nil {
4✔
2110
                        return err
1✔
2111
                }
1✔
2112

2113
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
3✔
2114
                if err != nil {
3✔
2115
                        return err
×
2116
                }
×
2117

2118
                // Add this status to the existing bitvector found in the DB.
2119
                status = channel.chanStatus | status
3✔
2120
                channel.chanStatus = status
3✔
2121

3✔
2122
                if err := putOpenChannel(chanBucket, channel); err != nil {
3✔
2123
                        return err
×
2124
                }
×
2125

2126
                for _, f := range fs {
6✔
2127
                        // Skip execution of nil closures.
3✔
2128
                        if f == nil {
6✔
2129
                                continue
3✔
2130
                        }
2131

2132
                        if err := f(chanBucket); err != nil {
3✔
2133
                                return err
×
2134
                        }
×
2135
                }
2136

2137
                return nil
3✔
2138
        }, func() {}); err != nil {
4✔
2139
                return err
1✔
2140
        }
1✔
2141

2142
        // Update the in-memory representation to keep it in sync with the DB.
2143
        c.chanStatus = status
3✔
2144

3✔
2145
        return nil
3✔
2146
}
2147

2148
func (c *OpenChannel) clearChanStatus(status ChannelStatus) error {
×
2149
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
2150
                chanBucket, err := fetchChanBucketRw(
×
2151
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
×
2152
                )
×
2153
                if err != nil {
×
2154
                        return err
×
2155
                }
×
2156

2157
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
×
2158
                if err != nil {
×
2159
                        return err
×
2160
                }
×
2161

2162
                // Unset this bit in the bitvector on disk.
2163
                status = channel.chanStatus & ^status
×
2164
                channel.chanStatus = status
×
2165

×
2166
                return putOpenChannel(chanBucket, channel)
×
2167
        }, func() {}); err != nil {
×
2168
                return err
×
2169
        }
×
2170

2171
        // Update the in-memory representation to keep it in sync with the DB.
2172
        c.chanStatus = status
×
2173

×
2174
        return nil
×
2175
}
2176

2177
// putOpenChannel serializes, and stores the current state of the channel in its
2178
// entirety.
2179
func putOpenChannel(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
3✔
2180
        // First, we'll write out all the relatively static fields, that are
3✔
2181
        // decided upon initial channel creation.
3✔
2182
        if err := putChanInfo(chanBucket, channel); err != nil {
3✔
2183
                return fmt.Errorf("unable to store chan info: %w", err)
×
2184
        }
×
2185

2186
        // With the static channel info written out, we'll now write out the
2187
        // current commitment state for both parties.
2188
        if err := putChanCommitments(chanBucket, channel); err != nil {
3✔
2189
                return fmt.Errorf("unable to store chan commitments: %w", err)
×
2190
        }
×
2191

2192
        // Next, if this is a frozen channel, we'll add in the axillary
2193
        // information we need to store.
2194
        if channel.ChanType.IsFrozen() || channel.ChanType.HasLeaseExpiration() {
6✔
2195
                err := storeThawHeight(
3✔
2196
                        chanBucket, channel.ThawHeight,
3✔
2197
                )
3✔
2198
                if err != nil {
3✔
2199
                        return fmt.Errorf("unable to store thaw height: %w",
×
2200
                                err)
×
2201
                }
×
2202
        }
2203

2204
        // Finally, we'll write out the revocation state for both parties
2205
        // within a distinct key space.
2206
        if err := putChanRevocationState(chanBucket, channel); err != nil {
3✔
2207
                return fmt.Errorf("unable to store chan revocations: %w", err)
×
2208
        }
×
2209

2210
        return nil
3✔
2211
}
2212

2213
// fetchOpenChannel retrieves, and deserializes (including decrypting
2214
// sensitive) the complete channel currently active with the passed nodeID.
2215
func fetchOpenChannel(chanBucket kvdb.RBucket,
2216
        chanPoint *wire.OutPoint) (*OpenChannel, error) {
3✔
2217

3✔
2218
        channel := &OpenChannel{
3✔
2219
                FundingOutpoint: *chanPoint,
3✔
2220
        }
3✔
2221

3✔
2222
        // First, we'll read all the static information that changes less
3✔
2223
        // frequently from disk.
3✔
2224
        if err := fetchChanInfo(chanBucket, channel); err != nil {
3✔
2225
                return nil, fmt.Errorf("unable to fetch chan info: %w", err)
×
2226
        }
×
2227

2228
        // With the static information read, we'll now read the current
2229
        // commitment state for both sides of the channel.
2230
        if err := fetchChanCommitments(chanBucket, channel); err != nil {
3✔
2231
                return nil, fmt.Errorf("unable to fetch chan commitments: %w",
×
2232
                        err)
×
2233
        }
×
2234

2235
        // Next, if this is a frozen channel, we'll add in the axillary
2236
        // information we need to store.
2237
        if channel.ChanType.IsFrozen() || channel.ChanType.HasLeaseExpiration() {
6✔
2238
                thawHeight, err := fetchThawHeight(chanBucket)
3✔
2239
                if err != nil {
3✔
2240
                        return nil, fmt.Errorf("unable to store thaw "+
×
2241
                                "height: %v", err)
×
2242
                }
×
2243

2244
                channel.ThawHeight = thawHeight
3✔
2245
        }
2246

2247
        // Finally, we'll retrieve the current revocation state so we can
2248
        // properly
2249
        if err := fetchChanRevocationState(chanBucket, channel); err != nil {
3✔
2250
                return nil, fmt.Errorf("unable to fetch chan revocations: %w",
×
2251
                        err)
×
2252
        }
×
2253

2254
        channel.Packager = NewChannelPackager(channel.ShortChannelID)
3✔
2255

3✔
2256
        return channel, nil
3✔
2257
}
2258

2259
// SyncPending writes the contents of the channel to the database while it's in
2260
// the pending (waiting for funding confirmation) state. The IsPending flag
2261
// will be set to true. When the channel's funding transaction is confirmed,
2262
// the channel should be marked as "open" and the IsPending flag set to false.
2263
// Note that this function also creates a LinkNode relationship between this
2264
// newly created channel and a new LinkNode instance. This allows listing all
2265
// channels in the database globally, or according to the LinkNode they were
2266
// created with.
2267
//
2268
// TODO(roasbeef): addr param should eventually be an lnwire.NetAddress type
2269
// that includes service bits.
2270
func (c *OpenChannel) SyncPending(addr net.Addr, pendingHeight uint32) error {
3✔
2271
        c.Lock()
3✔
2272
        defer c.Unlock()
3✔
2273

3✔
2274
        c.FundingBroadcastHeight = pendingHeight
3✔
2275

3✔
2276
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
2277
                return syncNewChannel(tx, c, []net.Addr{addr})
3✔
2278
        }, func() {})
6✔
2279
}
2280

2281
// syncNewChannel will write the passed channel to disk, and also create a
2282
// LinkNode (if needed) for the channel peer.
2283
func syncNewChannel(tx kvdb.RwTx, c *OpenChannel, addrs []net.Addr) error {
3✔
2284
        // First, sync all the persistent channel state to disk.
3✔
2285
        if err := c.fullSync(tx); err != nil {
6✔
2286
                return err
3✔
2287
        }
3✔
2288

2289
        nodeInfoBucket, err := tx.CreateTopLevelBucket(nodeInfoBucket)
3✔
2290
        if err != nil {
3✔
2291
                return err
×
2292
        }
×
2293

2294
        // If a LinkNode for this identity public key already exists,
2295
        // then we can exit early.
2296
        nodePub := c.IdentityPub.SerializeCompressed()
3✔
2297
        if nodeInfoBucket.Get(nodePub) != nil {
6✔
2298
                return nil
3✔
2299
        }
3✔
2300

2301
        // Next, we need to establish a (possibly) new LinkNode relationship
2302
        // for this channel. The LinkNode metadata contains reachability,
2303
        // up-time, and service bits related information.
2304
        linkNode := NewLinkNode(
3✔
2305
                &LinkNodeDB{backend: c.Db.backend},
3✔
2306
                wire.MainNet, c.IdentityPub, addrs...,
3✔
2307
        )
3✔
2308

3✔
2309
        // TODO(roasbeef): do away with link node all together?
3✔
2310

3✔
2311
        return putLinkNode(nodeInfoBucket, linkNode)
3✔
2312
}
2313

2314
// UpdateCommitment updates the local commitment state. It locks in the pending
2315
// local updates that were received by us from the remote party. The commitment
2316
// state completely describes the balance state at this point in the commitment
2317
// chain. In addition to that, it persists all the remote log updates that we
2318
// have acked, but not signed a remote commitment for yet. These need to be
2319
// persisted to be able to produce a valid commit signature if a restart would
2320
// occur. This method its to be called when we revoke our prior commitment
2321
// state.
2322
//
2323
// A map is returned of all the htlc resolutions that were locked in this
2324
// commitment. Keys correspond to htlc indices and values indicate whether the
2325
// htlc was settled or failed.
2326
func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
2327
        unsignedAckedUpdates []LogUpdate) (map[uint64]bool, error) {
3✔
2328

3✔
2329
        c.Lock()
3✔
2330
        defer c.Unlock()
3✔
2331

3✔
2332
        // If this is a restored channel, then we want to avoid mutating the
3✔
2333
        // state as all, as it's impossible to do so in a protocol compliant
3✔
2334
        // manner.
3✔
2335
        if c.hasChanStatus(ChanStatusRestored) {
3✔
2336
                return nil, ErrNoRestoredChannelMutation
×
2337
        }
×
2338

2339
        var finalHtlcs = make(map[uint64]bool)
3✔
2340

3✔
2341
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
2342
                chanBucket, err := fetchChanBucketRw(
3✔
2343
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
2344
                )
3✔
2345
                if err != nil {
3✔
2346
                        return err
×
2347
                }
×
2348

2349
                // If the channel is marked as borked, then for safety reasons,
2350
                // we shouldn't attempt any further updates.
2351
                isBorked, err := c.isBorked(chanBucket)
3✔
2352
                if err != nil {
3✔
2353
                        return err
×
2354
                }
×
2355
                if isBorked {
3✔
2356
                        return ErrChanBorked
×
2357
                }
×
2358

2359
                if err = putChanInfo(chanBucket, c); err != nil {
3✔
2360
                        return fmt.Errorf("unable to store chan info: %w", err)
×
2361
                }
×
2362

2363
                // With the proper bucket fetched, we'll now write the latest
2364
                // commitment state to disk for the target party.
2365
                err = putChanCommitment(
3✔
2366
                        chanBucket, newCommitment, true,
3✔
2367
                )
3✔
2368
                if err != nil {
3✔
2369
                        return fmt.Errorf("unable to store chan "+
×
2370
                                "revocations: %v", err)
×
2371
                }
×
2372

2373
                // Persist unsigned but acked remote updates that need to be
2374
                // restored after a restart.
2375
                var b bytes.Buffer
3✔
2376
                err = serializeLogUpdates(&b, unsignedAckedUpdates)
3✔
2377
                if err != nil {
3✔
2378
                        return err
×
2379
                }
×
2380

2381
                err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes())
3✔
2382
                if err != nil {
3✔
2383
                        return fmt.Errorf("unable to store dangline remote "+
×
2384
                                "updates: %v", err)
×
2385
                }
×
2386

2387
                // Since we have just sent the counterparty a revocation, store true
2388
                // under lastWasRevokeKey.
2389
                var b2 bytes.Buffer
3✔
2390
                if err := WriteElements(&b2, true); err != nil {
3✔
2391
                        return err
×
2392
                }
×
2393

2394
                if err := chanBucket.Put(lastWasRevokeKey, b2.Bytes()); err != nil {
3✔
2395
                        return err
×
2396
                }
×
2397

2398
                // Persist the remote unsigned local updates that are not included
2399
                // in our new commitment.
2400
                updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
3✔
2401
                if updateBytes == nil {
6✔
2402
                        return nil
3✔
2403
                }
3✔
2404

2405
                r := bytes.NewReader(updateBytes)
3✔
2406
                updates, err := deserializeLogUpdates(r)
3✔
2407
                if err != nil {
3✔
2408
                        return err
×
2409
                }
×
2410

2411
                // Get the bucket where settled htlcs are recorded if the user
2412
                // opted in to storing this information.
2413
                var finalHtlcsBucket kvdb.RwBucket
3✔
2414
                if c.Db.parent.storeFinalHtlcResolutions {
6✔
2415
                        bucket, err := fetchFinalHtlcsBucketRw(
3✔
2416
                                tx, c.ShortChannelID,
3✔
2417
                        )
3✔
2418
                        if err != nil {
3✔
2419
                                return err
×
2420
                        }
×
2421

2422
                        finalHtlcsBucket = bucket
3✔
2423
                }
2424

2425
                var unsignedUpdates []LogUpdate
3✔
2426
                for _, upd := range updates {
6✔
2427
                        // Gather updates that are not on our local commitment.
3✔
2428
                        if upd.LogIndex >= newCommitment.LocalLogIndex {
3✔
2429
                                unsignedUpdates = append(unsignedUpdates, upd)
×
2430

×
2431
                                continue
×
2432
                        }
2433

2434
                        // The update was locked in. If the update was a
2435
                        // resolution, then store it in the database.
2436
                        err := processFinalHtlc(
3✔
2437
                                finalHtlcsBucket, upd, finalHtlcs,
3✔
2438
                        )
3✔
2439
                        if err != nil {
3✔
2440
                                return err
×
2441
                        }
×
2442
                }
2443

2444
                var b3 bytes.Buffer
3✔
2445
                err = serializeLogUpdates(&b3, unsignedUpdates)
3✔
2446
                if err != nil {
3✔
2447
                        return fmt.Errorf("unable to serialize log updates: %w",
×
2448
                                err)
×
2449
                }
×
2450

2451
                err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b3.Bytes())
3✔
2452
                if err != nil {
3✔
2453
                        return fmt.Errorf("unable to restore chanbucket: %w",
×
2454
                                err)
×
2455
                }
×
2456

2457
                return nil
3✔
2458
        }, func() {
3✔
2459
                finalHtlcs = make(map[uint64]bool)
3✔
2460
        })
3✔
2461
        if err != nil {
3✔
2462
                return nil, err
×
2463
        }
×
2464

2465
        c.LocalCommitment = *newCommitment
3✔
2466

3✔
2467
        return finalHtlcs, nil
3✔
2468
}
2469

2470
// processFinalHtlc stores a final htlc outcome in the database if signaled via
2471
// the supplied log update. An in-memory htlcs map is updated too.
2472
func processFinalHtlc(finalHtlcsBucket walletdb.ReadWriteBucket, upd LogUpdate,
2473
        finalHtlcs map[uint64]bool) error {
3✔
2474

3✔
2475
        var (
3✔
2476
                settled bool
3✔
2477
                id      uint64
3✔
2478
        )
3✔
2479

3✔
2480
        switch msg := upd.UpdateMsg.(type) {
3✔
2481
        case *lnwire.UpdateFulfillHTLC:
3✔
2482
                settled = true
3✔
2483
                id = msg.ID
3✔
2484

2485
        case *lnwire.UpdateFailHTLC:
3✔
2486
                settled = false
3✔
2487
                id = msg.ID
3✔
2488

2489
        case *lnwire.UpdateFailMalformedHTLC:
3✔
2490
                settled = false
3✔
2491
                id = msg.ID
3✔
2492

2493
        default:
×
2494
                return nil
×
2495
        }
2496

2497
        // Store the final resolution in the database if a bucket is provided.
2498
        if finalHtlcsBucket != nil {
6✔
2499
                err := putFinalHtlc(
3✔
2500
                        finalHtlcsBucket, id,
3✔
2501
                        FinalHtlcInfo{
3✔
2502
                                Settled:  settled,
3✔
2503
                                Offchain: true,
3✔
2504
                        },
3✔
2505
                )
3✔
2506
                if err != nil {
3✔
2507
                        return err
×
2508
                }
×
2509
        }
2510

2511
        finalHtlcs[id] = settled
3✔
2512

3✔
2513
        return nil
3✔
2514
}
2515

2516
// ActiveHtlcs returns a slice of HTLC's which are currently active on *both*
2517
// commitment transactions.
2518
func (c *OpenChannel) ActiveHtlcs() []HTLC {
3✔
2519
        c.RLock()
3✔
2520
        defer c.RUnlock()
3✔
2521

3✔
2522
        // We'll only return HTLC's that are locked into *both* commitment
3✔
2523
        // transactions. So we'll iterate through their set of HTLC's to note
3✔
2524
        // which ones are present on their commitment.
3✔
2525
        remoteHtlcs := make(map[[32]byte]struct{})
3✔
2526
        for _, htlc := range c.RemoteCommitment.Htlcs {
6✔
2527
                log.Tracef("RemoteCommitment has htlc: id=%v, update=%v "+
3✔
2528
                        "incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
3✔
2529
                        htlc.Incoming)
3✔
2530

3✔
2531
                onionHash := sha256.Sum256(htlc.OnionBlob[:])
3✔
2532
                remoteHtlcs[onionHash] = struct{}{}
3✔
2533
        }
3✔
2534

2535
        // Now that we know which HTLC's they have, we'll only mark the HTLC's
2536
        // as active if *we* know them as well.
2537
        activeHtlcs := make([]HTLC, 0, len(remoteHtlcs))
3✔
2538
        for _, htlc := range c.LocalCommitment.Htlcs {
6✔
2539
                log.Tracef("LocalCommitment has htlc: id=%v, update=%v "+
3✔
2540
                        "incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
3✔
2541
                        htlc.Incoming)
3✔
2542

3✔
2543
                onionHash := sha256.Sum256(htlc.OnionBlob[:])
3✔
2544
                if _, ok := remoteHtlcs[onionHash]; !ok {
6✔
2545
                        log.Tracef("Skipped htlc due to onion mismatched: "+
3✔
2546
                                "id=%v, update=%v incoming=%v",
3✔
2547
                                htlc.HtlcIndex, htlc.LogIndex, htlc.Incoming)
3✔
2548

3✔
2549
                        continue
3✔
2550
                }
2551

2552
                activeHtlcs = append(activeHtlcs, htlc)
3✔
2553
        }
2554

2555
        return activeHtlcs
3✔
2556
}
2557

2558
// HTLC is the on-disk representation of a hash time-locked contract. HTLCs are
2559
// contained within ChannelDeltas which encode the current state of the
2560
// commitment between state updates.
2561
//
2562
// TODO(roasbeef): save space by using smaller ints at tail end?
2563
type HTLC struct {
2564
        // TODO(yy): can embed an HTLCEntry here.
2565

2566
        // Signature is the signature for the second level covenant transaction
2567
        // for this HTLC. The second level transaction is a timeout tx in the
2568
        // case that this is an outgoing HTLC, and a success tx in the case
2569
        // that this is an incoming HTLC.
2570
        //
2571
        // TODO(roasbeef): make [64]byte instead?
2572
        Signature []byte
2573

2574
        // RHash is the payment hash of the HTLC.
2575
        RHash [32]byte
2576

2577
        // Amt is the amount of milli-satoshis this HTLC escrows.
2578
        Amt lnwire.MilliSatoshi
2579

2580
        // RefundTimeout is the absolute timeout on the HTLC that the sender
2581
        // must wait before reclaiming the funds in limbo.
2582
        RefundTimeout uint32
2583

2584
        // OutputIndex is the output index for this particular HTLC output
2585
        // within the commitment transaction.
2586
        OutputIndex int32
2587

2588
        // Incoming denotes whether we're the receiver or the sender of this
2589
        // HTLC.
2590
        Incoming bool
2591

2592
        // OnionBlob is an opaque blob which is used to complete multi-hop
2593
        // routing.
2594
        OnionBlob [lnwire.OnionPacketSize]byte
2595

2596
        // HtlcIndex is the HTLC counter index of this active, outstanding
2597
        // HTLC. This differs from the LogIndex, as the HtlcIndex is only
2598
        // incremented for each offered HTLC, while they LogIndex is
2599
        // incremented for each update (includes settle+fail).
2600
        HtlcIndex uint64
2601

2602
        // LogIndex is the cumulative log index of this HTLC. This differs
2603
        // from the HtlcIndex as this will be incremented for each new log
2604
        // update added.
2605
        LogIndex uint64
2606

2607
        // ExtraData contains any additional information that was transmitted
2608
        // with the HTLC via TLVs. This data *must* already be encoded as a
2609
        // TLV stream, and may be empty. The length of this data is naturally
2610
        // limited by the space available to TLVs in update_add_htlc:
2611
        // = 65535 bytes (bolt 8 maximum message size):
2612
        // - 2 bytes (bolt 1 message_type)
2613
        // - 32 bytes (channel_id)
2614
        // - 8 bytes (id)
2615
        // - 8 bytes (amount_msat)
2616
        // - 32 bytes (payment_hash)
2617
        // - 4 bytes (cltv_expiry)
2618
        // - 1366 bytes (onion_routing_packet)
2619
        // = 64083 bytes maximum possible TLV stream
2620
        //
2621
        // Note that this extra data is stored inline with the OnionBlob for
2622
        // legacy reasons, see serialization/deserialization functions for
2623
        // detail.
2624
        ExtraData lnwire.ExtraOpaqueData
2625

2626
        // BlindingPoint is an optional blinding point included with the HTLC.
2627
        //
2628
        // Note: this field is not a part of on-disk representation of the
2629
        // HTLC. It is stored in the ExtraData field, which is used to store
2630
        // a TLV stream of additional information associated with the HTLC.
2631
        BlindingPoint lnwire.BlindingPointRecord
2632

2633
        // CustomRecords is a set of custom TLV records that are associated with
2634
        // this HTLC. These records are used to store additional information
2635
        // about the HTLC that is not part of the standard HTLC fields. This
2636
        // field is encoded within the ExtraData field.
2637
        CustomRecords lnwire.CustomRecords
2638
}
2639

2640
// serializeExtraData encodes a TLV stream of extra data to be stored with a
2641
// HTLC. It uses the update_add_htlc TLV types, because this is where extra
2642
// data is passed with a HTLC. At present blinding points are the only extra
2643
// data that we will store, and the function is a no-op if a nil blinding
2644
// point is provided.
2645
//
2646
// This function MUST be called to persist all HTLC values when they are
2647
// serialized.
2648
func (h *HTLC) serializeExtraData() error {
3✔
2649
        var records []tlv.RecordProducer
3✔
2650
        h.BlindingPoint.WhenSome(func(b tlv.RecordT[lnwire.BlindingPointTlvType,
3✔
2651
                *btcec.PublicKey]) {
6✔
2652

3✔
2653
                records = append(records, &b)
3✔
2654
        })
3✔
2655

2656
        records, err := h.CustomRecords.ExtendRecordProducers(records)
3✔
2657
        if err != nil {
3✔
2658
                return err
×
2659
        }
×
2660

2661
        return h.ExtraData.PackRecords(records...)
3✔
2662
}
2663

2664
// deserializeExtraData extracts TLVs from the extra data persisted for the
2665
// htlc and populates values in the struct accordingly.
2666
//
2667
// This function MUST be called to populate the struct properly when HTLCs
2668
// are deserialized.
2669
func (h *HTLC) deserializeExtraData() error {
3✔
2670
        if len(h.ExtraData) == 0 {
6✔
2671
                return nil
3✔
2672
        }
3✔
2673

2674
        blindingPoint := h.BlindingPoint.Zero()
3✔
2675
        tlvMap, err := h.ExtraData.ExtractRecords(&blindingPoint)
3✔
2676
        if err != nil {
3✔
2677
                return err
×
2678
        }
×
2679

2680
        if val, ok := tlvMap[h.BlindingPoint.TlvType()]; ok && val == nil {
6✔
2681
                h.BlindingPoint = tlv.SomeRecordT(blindingPoint)
3✔
2682

3✔
2683
                // Remove the entry from the TLV map. Anything left in the map
3✔
2684
                // will be included in the custom records field.
3✔
2685
                delete(tlvMap, h.BlindingPoint.TlvType())
3✔
2686
        }
3✔
2687

2688
        // Set the custom records field to the remaining TLV records.
2689
        customRecords, err := lnwire.NewCustomRecords(tlvMap)
3✔
2690
        if err != nil {
3✔
2691
                return err
×
2692
        }
×
2693
        h.CustomRecords = customRecords
3✔
2694

3✔
2695
        return nil
3✔
2696
}
2697

2698
// SerializeHtlcs writes out the passed set of HTLC's into the passed writer
2699
// using the current default on-disk serialization format.
2700
//
2701
// This inline serialization has been extended to allow storage of extra data
2702
// associated with a HTLC in the following way:
2703
//   - The known-length onion blob (1366 bytes) is serialized as var bytes in
2704
//     WriteElements (ie, the length 1366 was written, followed by the 1366
2705
//     onion bytes).
2706
//   - To include extra data, we append any extra data present to this one
2707
//     variable length of data. Since we know that the onion is strictly 1366
2708
//     bytes, any length after that should be considered to be extra data.
2709
//
2710
// NOTE: This API is NOT stable, the on-disk format will likely change in the
2711
// future.
2712
func SerializeHtlcs(b io.Writer, htlcs ...HTLC) error {
3✔
2713
        numHtlcs := uint16(len(htlcs))
3✔
2714
        if err := WriteElement(b, numHtlcs); err != nil {
3✔
2715
                return err
×
2716
        }
×
2717

2718
        for _, htlc := range htlcs {
6✔
2719
                // Populate TLV stream for any additional fields contained
3✔
2720
                // in the TLV.
3✔
2721
                if err := htlc.serializeExtraData(); err != nil {
3✔
2722
                        return err
×
2723
                }
×
2724

2725
                // The onion blob and hltc data are stored as a single var
2726
                // bytes blob.
2727
                onionAndExtraData := make(
3✔
2728
                        []byte, lnwire.OnionPacketSize+len(htlc.ExtraData),
3✔
2729
                )
3✔
2730
                copy(onionAndExtraData, htlc.OnionBlob[:])
3✔
2731
                copy(onionAndExtraData[lnwire.OnionPacketSize:], htlc.ExtraData)
3✔
2732

3✔
2733
                if err := WriteElements(b,
3✔
2734
                        htlc.Signature, htlc.RHash, htlc.Amt, htlc.RefundTimeout,
3✔
2735
                        htlc.OutputIndex, htlc.Incoming, onionAndExtraData,
3✔
2736
                        htlc.HtlcIndex, htlc.LogIndex,
3✔
2737
                ); err != nil {
3✔
2738
                        return err
×
2739
                }
×
2740
        }
2741

2742
        return nil
3✔
2743
}
2744

2745
// DeserializeHtlcs attempts to read out a slice of HTLC's from the passed
2746
// io.Reader. The bytes within the passed reader MUST have been previously
2747
// written to using the SerializeHtlcs function.
2748
//
2749
// This inline deserialization has been extended to allow storage of extra data
2750
// associated with a HTLC in the following way:
2751
//   - The known-length onion blob (1366 bytes) and any additional data present
2752
//     are read out as a single blob of variable byte data.
2753
//   - They are stored like this to take advantage of the variable space
2754
//     available for extension without migration (see SerializeHtlcs).
2755
//   - The first 1366 bytes are interpreted as the onion blob, and any remaining
2756
//     bytes as extra HTLC data.
2757
//   - This extra HTLC data is expected to be serialized as a TLV stream, and
2758
//     its parsing is left to higher layers.
2759
//
2760
// NOTE: This API is NOT stable, the on-disk format will likely change in the
2761
// future.
2762
func DeserializeHtlcs(r io.Reader) ([]HTLC, error) {
3✔
2763
        var numHtlcs uint16
3✔
2764
        if err := ReadElement(r, &numHtlcs); err != nil {
3✔
2765
                return nil, err
×
2766
        }
×
2767

2768
        var htlcs []HTLC
3✔
2769
        if numHtlcs == 0 {
6✔
2770
                return htlcs, nil
3✔
2771
        }
3✔
2772

2773
        htlcs = make([]HTLC, numHtlcs)
3✔
2774
        for i := uint16(0); i < numHtlcs; i++ {
6✔
2775
                var onionAndExtraData []byte
3✔
2776
                if err := ReadElements(r,
3✔
2777
                        &htlcs[i].Signature, &htlcs[i].RHash, &htlcs[i].Amt,
3✔
2778
                        &htlcs[i].RefundTimeout, &htlcs[i].OutputIndex,
3✔
2779
                        &htlcs[i].Incoming, &onionAndExtraData,
3✔
2780
                        &htlcs[i].HtlcIndex, &htlcs[i].LogIndex,
3✔
2781
                ); err != nil {
3✔
2782
                        return htlcs, err
×
2783
                }
×
2784

2785
                // Sanity check that we have at least the onion blob size we
2786
                // expect.
2787
                if len(onionAndExtraData) < lnwire.OnionPacketSize {
3✔
2788
                        return nil, ErrOnionBlobLength
×
2789
                }
×
2790

2791
                // First OnionPacketSize bytes are our fixed length onion
2792
                // packet.
2793
                copy(
3✔
2794
                        htlcs[i].OnionBlob[:],
3✔
2795
                        onionAndExtraData[0:lnwire.OnionPacketSize],
3✔
2796
                )
3✔
2797

3✔
2798
                // Any additional bytes belong to extra data. ExtraDataLen
3✔
2799
                // will be >= 0, because we know that we always have a fixed
3✔
2800
                // length onion packet.
3✔
2801
                extraDataLen := len(onionAndExtraData) - lnwire.OnionPacketSize
3✔
2802
                if extraDataLen > 0 {
6✔
2803
                        htlcs[i].ExtraData = make([]byte, extraDataLen)
3✔
2804

3✔
2805
                        copy(
3✔
2806
                                htlcs[i].ExtraData,
3✔
2807
                                onionAndExtraData[lnwire.OnionPacketSize:],
3✔
2808
                        )
3✔
2809
                }
3✔
2810

2811
                // Finally, deserialize any TLVs contained in that extra data
2812
                // if they are present.
2813
                if err := htlcs[i].deserializeExtraData(); err != nil {
3✔
2814
                        return nil, err
×
2815
                }
×
2816
        }
2817

2818
        return htlcs, nil
3✔
2819
}
2820

2821
// Copy returns a full copy of the target HTLC.
2822
func (h *HTLC) Copy() HTLC {
3✔
2823
        clone := HTLC{
3✔
2824
                Incoming:      h.Incoming,
3✔
2825
                Amt:           h.Amt,
3✔
2826
                RefundTimeout: h.RefundTimeout,
3✔
2827
                OutputIndex:   h.OutputIndex,
3✔
2828
        }
3✔
2829
        copy(clone.Signature[:], h.Signature)
3✔
2830
        copy(clone.RHash[:], h.RHash[:])
3✔
2831
        copy(clone.ExtraData, h.ExtraData)
3✔
2832
        clone.BlindingPoint = h.BlindingPoint
3✔
2833
        clone.CustomRecords = h.CustomRecords.Copy()
3✔
2834

3✔
2835
        return clone
3✔
2836
}
3✔
2837

2838
// LogUpdate represents a pending update to the remote commitment chain. The
2839
// log update may be an add, fail, or settle entry. We maintain this data in
2840
// order to be able to properly retransmit our proposed state if necessary.
2841
type LogUpdate struct {
2842
        // LogIndex is the log index of this proposed commitment update entry.
2843
        LogIndex uint64
2844

2845
        // UpdateMsg is the update message that was included within our
2846
        // local update log. The LogIndex value denotes the log index of this
2847
        // update which will be used when restoring our local update log if
2848
        // we're left with a dangling update on restart.
2849
        UpdateMsg lnwire.Message
2850
}
2851

2852
// serializeLogUpdate writes a log update to the provided io.Writer.
2853
func serializeLogUpdate(w io.Writer, l *LogUpdate) error {
3✔
2854
        return WriteElements(w, l.LogIndex, l.UpdateMsg)
3✔
2855
}
3✔
2856

2857
// deserializeLogUpdate reads a log update from the provided io.Reader.
2858
func deserializeLogUpdate(r io.Reader) (*LogUpdate, error) {
3✔
2859
        l := &LogUpdate{}
3✔
2860
        if err := ReadElements(r, &l.LogIndex, &l.UpdateMsg); err != nil {
3✔
2861
                return nil, err
×
2862
        }
×
2863

2864
        return l, nil
3✔
2865
}
2866

2867
// CommitDiff represents the delta needed to apply the state transition between
2868
// two subsequent commitment states. Given state N and state N+1, one is able
2869
// to apply the set of messages contained within the CommitDiff to N to arrive
2870
// at state N+1. Each time a new commitment is extended, we'll write a new
2871
// commitment (along with the full commitment state) to disk so we can
2872
// re-transmit the state in the case of a connection loss or message drop.
2873
type CommitDiff struct {
2874
        // ChannelCommitment is the full commitment state that one would arrive
2875
        // at by applying the set of messages contained in the UpdateDiff to
2876
        // the prior accepted commitment.
2877
        Commitment ChannelCommitment
2878

2879
        // LogUpdates is the set of messages sent prior to the commitment state
2880
        // transition in question. Upon reconnection, if we detect that they
2881
        // don't have the commitment, then we re-send this along with the
2882
        // proper signature.
2883
        LogUpdates []LogUpdate
2884

2885
        // CommitSig is the exact CommitSig message that should be sent after
2886
        // the set of LogUpdates above has been retransmitted. The signatures
2887
        // within this message should properly cover the new commitment state
2888
        // and also the HTLC's within the new commitment state.
2889
        CommitSig *lnwire.CommitSig
2890

2891
        // OpenedCircuitKeys is a set of unique identifiers for any downstream
2892
        // Add packets included in this commitment txn. After a restart, this
2893
        // set of htlcs is acked from the link's incoming mailbox to ensure
2894
        // there isn't an attempt to re-add them to this commitment txn.
2895
        OpenedCircuitKeys []models.CircuitKey
2896

2897
        // ClosedCircuitKeys records the unique identifiers for any settle/fail
2898
        // packets that were resolved by this commitment txn. After a restart,
2899
        // this is used to ensure those circuits are removed from the circuit
2900
        // map, and the downstream packets in the link's mailbox are removed.
2901
        ClosedCircuitKeys []models.CircuitKey
2902

2903
        // AddAcks specifies the locations (commit height, pkg index) of any
2904
        // Adds that were failed/settled in this commit diff. This will ack
2905
        // entries in *this* channel's forwarding packages.
2906
        //
2907
        // NOTE: This value is not serialized, it is used to atomically mark the
2908
        // resolution of adds, such that they will not be reprocessed after a
2909
        // restart.
2910
        AddAcks []AddRef
2911

2912
        // SettleFailAcks specifies the locations (chan id, commit height, pkg
2913
        // index) of any Settles or Fails that were locked into this commit
2914
        // diff, and originate from *another* channel, i.e. the outgoing link.
2915
        //
2916
        // NOTE: This value is not serialized, it is used to atomically acks
2917
        // settles and fails from the forwarding packages of other channels,
2918
        // such that they will not be reforwarded internally after a restart.
2919
        SettleFailAcks []SettleFailRef
2920
}
2921

2922
// serializeLogUpdates serializes provided list of updates to a stream.
2923
func serializeLogUpdates(w io.Writer, logUpdates []LogUpdate) error {
3✔
2924
        numUpdates := uint16(len(logUpdates))
3✔
2925
        if err := binary.Write(w, byteOrder, numUpdates); err != nil {
3✔
2926
                return err
×
2927
        }
×
2928

2929
        for _, diff := range logUpdates {
6✔
2930
                err := WriteElements(w, diff.LogIndex, diff.UpdateMsg)
3✔
2931
                if err != nil {
3✔
2932
                        return err
×
2933
                }
×
2934
        }
2935

2936
        return nil
3✔
2937
}
2938

2939
// deserializeLogUpdates deserializes a list of updates from a stream.
2940
func deserializeLogUpdates(r io.Reader) ([]LogUpdate, error) {
3✔
2941
        var numUpdates uint16
3✔
2942
        if err := binary.Read(r, byteOrder, &numUpdates); err != nil {
3✔
2943
                return nil, err
×
2944
        }
×
2945

2946
        logUpdates := make([]LogUpdate, numUpdates)
3✔
2947
        for i := 0; i < int(numUpdates); i++ {
6✔
2948
                err := ReadElements(r,
3✔
2949
                        &logUpdates[i].LogIndex, &logUpdates[i].UpdateMsg,
3✔
2950
                )
3✔
2951
                if err != nil {
3✔
2952
                        return nil, err
×
2953
                }
×
2954
        }
2955
        return logUpdates, nil
3✔
2956
}
2957

2958
func serializeCommitDiff(w io.Writer, diff *CommitDiff) error { // nolint: dupl
3✔
2959
        if err := serializeChanCommit(w, &diff.Commitment); err != nil {
3✔
2960
                return err
×
2961
        }
×
2962

2963
        if err := WriteElements(w, diff.CommitSig); err != nil {
3✔
2964
                return err
×
2965
        }
×
2966

2967
        if err := serializeLogUpdates(w, diff.LogUpdates); err != nil {
3✔
2968
                return err
×
2969
        }
×
2970

2971
        numOpenRefs := uint16(len(diff.OpenedCircuitKeys))
3✔
2972
        if err := binary.Write(w, byteOrder, numOpenRefs); err != nil {
3✔
2973
                return err
×
2974
        }
×
2975

2976
        for _, openRef := range diff.OpenedCircuitKeys {
6✔
2977
                err := WriteElements(w, openRef.ChanID, openRef.HtlcID)
3✔
2978
                if err != nil {
3✔
2979
                        return err
×
2980
                }
×
2981
        }
2982

2983
        numClosedRefs := uint16(len(diff.ClosedCircuitKeys))
3✔
2984
        if err := binary.Write(w, byteOrder, numClosedRefs); err != nil {
3✔
2985
                return err
×
2986
        }
×
2987

2988
        for _, closedRef := range diff.ClosedCircuitKeys {
6✔
2989
                err := WriteElements(w, closedRef.ChanID, closedRef.HtlcID)
3✔
2990
                if err != nil {
3✔
2991
                        return err
×
2992
                }
×
2993
        }
2994

2995
        // We'll also encode the commit aux data stream here. We do this here
2996
        // rather than above (at the call to serializeChanCommit), to ensure
2997
        // backwards compat for reads to existing non-custom channels.
2998
        auxData := diff.Commitment.extractTlvData()
3✔
2999
        if err := auxData.encode(w); err != nil {
3✔
3000
                return fmt.Errorf("unable to write aux data: %w", err)
×
3001
        }
×
3002

3003
        return nil
3✔
3004
}
3005

3006
func deserializeCommitDiff(r io.Reader) (*CommitDiff, error) {
3✔
3007
        var (
3✔
3008
                d   CommitDiff
3✔
3009
                err error
3✔
3010
        )
3✔
3011

3✔
3012
        d.Commitment, err = deserializeChanCommit(r)
3✔
3013
        if err != nil {
3✔
3014
                return nil, err
×
3015
        }
×
3016

3017
        var msg lnwire.Message
3✔
3018
        if err := ReadElements(r, &msg); err != nil {
3✔
3019
                return nil, err
×
3020
        }
×
3021
        commitSig, ok := msg.(*lnwire.CommitSig)
3✔
3022
        if !ok {
3✔
3023
                return nil, fmt.Errorf("expected lnwire.CommitSig, instead "+
×
3024
                        "read: %T", msg)
×
3025
        }
×
3026
        d.CommitSig = commitSig
3✔
3027

3✔
3028
        d.LogUpdates, err = deserializeLogUpdates(r)
3✔
3029
        if err != nil {
3✔
3030
                return nil, err
×
3031
        }
×
3032

3033
        var numOpenRefs uint16
3✔
3034
        if err := binary.Read(r, byteOrder, &numOpenRefs); err != nil {
3✔
3035
                return nil, err
×
3036
        }
×
3037

3038
        d.OpenedCircuitKeys = make([]models.CircuitKey, numOpenRefs)
3✔
3039
        for i := 0; i < int(numOpenRefs); i++ {
6✔
3040
                err := ReadElements(r,
3✔
3041
                        &d.OpenedCircuitKeys[i].ChanID,
3✔
3042
                        &d.OpenedCircuitKeys[i].HtlcID)
3✔
3043
                if err != nil {
3✔
3044
                        return nil, err
×
3045
                }
×
3046
        }
3047

3048
        var numClosedRefs uint16
3✔
3049
        if err := binary.Read(r, byteOrder, &numClosedRefs); err != nil {
3✔
3050
                return nil, err
×
3051
        }
×
3052

3053
        d.ClosedCircuitKeys = make([]models.CircuitKey, numClosedRefs)
3✔
3054
        for i := 0; i < int(numClosedRefs); i++ {
6✔
3055
                err := ReadElements(r,
3✔
3056
                        &d.ClosedCircuitKeys[i].ChanID,
3✔
3057
                        &d.ClosedCircuitKeys[i].HtlcID)
3✔
3058
                if err != nil {
3✔
3059
                        return nil, err
×
3060
                }
×
3061
        }
3062

3063
        // As a final step, we'll read out any aux commit data that we have at
3064
        // the end of this byte stream. We do this here to ensure backward
3065
        // compatibility, as otherwise we risk erroneously reading into the
3066
        // wrong field.
3067
        var auxData commitTlvData
3✔
3068
        if err := auxData.decode(r); err != nil {
3✔
3069
                return nil, fmt.Errorf("unable to decode aux data: %w", err)
×
3070
        }
×
3071

3072
        d.Commitment.amendTlvData(auxData)
3✔
3073

3✔
3074
        return &d, nil
3✔
3075
}
3076

3077
// AppendRemoteCommitChain appends a new CommitDiff to the end of the
3078
// commitment chain for the remote party. This method is to be used once we
3079
// have prepared a new commitment state for the remote party, but before we
3080
// transmit it to the remote party. The contents of the argument should be
3081
// sufficient to retransmit the updates and signature needed to reconstruct the
3082
// state in full, in the case that we need to retransmit.
3083
func (c *OpenChannel) AppendRemoteCommitChain(diff *CommitDiff) error {
3✔
3084
        c.Lock()
3✔
3085
        defer c.Unlock()
3✔
3086

3✔
3087
        // If this is a restored channel, then we want to avoid mutating the
3✔
3088
        // state at all, as it's impossible to do so in a protocol compliant
3✔
3089
        // manner.
3✔
3090
        if c.hasChanStatus(ChanStatusRestored) {
3✔
3091
                return ErrNoRestoredChannelMutation
×
3092
        }
×
3093

3094
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
3095
                // First, we'll grab the writable bucket where this channel's
3✔
3096
                // data resides.
3✔
3097
                chanBucket, err := fetchChanBucketRw(
3✔
3098
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
3099
                )
3✔
3100
                if err != nil {
3✔
3101
                        return err
×
3102
                }
×
3103

3104
                // If the channel is marked as borked, then for safety reasons,
3105
                // we shouldn't attempt any further updates.
3106
                isBorked, err := c.isBorked(chanBucket)
3✔
3107
                if err != nil {
3✔
3108
                        return err
×
3109
                }
×
3110
                if isBorked {
3✔
3111
                        return ErrChanBorked
×
3112
                }
×
3113

3114
                // Any outgoing settles and fails necessarily have a
3115
                // corresponding adds in this channel's forwarding packages.
3116
                // Mark all of these as being fully processed in our forwarding
3117
                // package, which prevents us from reprocessing them after
3118
                // startup.
3119
                err = c.Packager.AckAddHtlcs(tx, diff.AddAcks...)
3✔
3120
                if err != nil {
3✔
3121
                        return err
×
3122
                }
×
3123

3124
                // Additionally, we ack from any fails or settles that are
3125
                // persisted in another channel's forwarding package. This
3126
                // prevents the same fails and settles from being retransmitted
3127
                // after restarts. The actual fail or settle we need to
3128
                // propagate to the remote party is now in the commit diff.
3129
                err = c.Packager.AckSettleFails(tx, diff.SettleFailAcks...)
3✔
3130
                if err != nil {
3✔
3131
                        return err
×
3132
                }
×
3133

3134
                // We are sending a commitment signature so lastWasRevokeKey should
3135
                // store false.
3136
                var b bytes.Buffer
3✔
3137
                if err := WriteElements(&b, false); err != nil {
3✔
3138
                        return err
×
3139
                }
×
3140
                if err := chanBucket.Put(lastWasRevokeKey, b.Bytes()); err != nil {
3✔
3141
                        return err
×
3142
                }
×
3143

3144
                // TODO(roasbeef): use seqno to derive key for later LCP
3145

3146
                // With the bucket retrieved, we'll now serialize the commit
3147
                // diff itself, and write it to disk.
3148
                var b2 bytes.Buffer
3✔
3149
                if err := serializeCommitDiff(&b2, diff); err != nil {
3✔
3150
                        return err
×
3151
                }
×
3152
                return chanBucket.Put(commitDiffKey, b2.Bytes())
3✔
3153
        }, func() {})
3✔
3154
}
3155

3156
// RemoteCommitChainTip returns the "tip" of the current remote commitment
3157
// chain. This value will be non-nil iff, we've created a new commitment for
3158
// the remote party that they haven't yet ACK'd. In this case, their commitment
3159
// chain will have a length of two: their current unrevoked commitment, and
3160
// this new pending commitment. Once they revoked their prior state, we'll swap
3161
// these pointers, causing the tip and the tail to point to the same entry.
3162
func (c *OpenChannel) RemoteCommitChainTip() (*CommitDiff, error) {
3✔
3163
        var cd *CommitDiff
3✔
3164
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
3165
                chanBucket, err := fetchChanBucket(
3✔
3166
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
3167
                )
3✔
3168
                switch err {
3✔
3169
                case nil:
3✔
3170
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
2✔
3171
                        return ErrNoPendingCommit
2✔
3172
                default:
×
3173
                        return err
×
3174
                }
3175

3176
                tipBytes := chanBucket.Get(commitDiffKey)
3✔
3177
                if tipBytes == nil {
6✔
3178
                        return ErrNoPendingCommit
3✔
3179
                }
3✔
3180

3181
                tipReader := bytes.NewReader(tipBytes)
3✔
3182
                dcd, err := deserializeCommitDiff(tipReader)
3✔
3183
                if err != nil {
3✔
3184
                        return err
×
3185
                }
×
3186

3187
                cd = dcd
3✔
3188
                return nil
3✔
3189
        }, func() {
3✔
3190
                cd = nil
3✔
3191
        })
3✔
3192
        if err != nil {
6✔
3193
                return nil, err
3✔
3194
        }
3✔
3195

3196
        return cd, nil
3✔
3197
}
3198

3199
// UnsignedAckedUpdates retrieves the persisted unsigned acked remote log
3200
// updates that still need to be signed for.
3201
func (c *OpenChannel) UnsignedAckedUpdates() ([]LogUpdate, error) {
3✔
3202
        var updates []LogUpdate
3✔
3203
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
3204
                chanBucket, err := fetchChanBucket(
3✔
3205
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
3206
                )
3✔
3207
                switch err {
3✔
3208
                case nil:
3✔
3209
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
2✔
3210
                        return nil
2✔
3211
                default:
×
3212
                        return err
×
3213
                }
3214

3215
                updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
3✔
3216
                if updateBytes == nil {
6✔
3217
                        return nil
3✔
3218
                }
3✔
3219

3220
                r := bytes.NewReader(updateBytes)
3✔
3221
                updates, err = deserializeLogUpdates(r)
3✔
3222
                return err
3✔
3223
        }, func() {
3✔
3224
                updates = nil
3✔
3225
        })
3✔
3226
        if err != nil {
3✔
3227
                return nil, err
×
3228
        }
×
3229

3230
        return updates, nil
3✔
3231
}
3232

3233
// RemoteUnsignedLocalUpdates retrieves the persisted, unsigned local log
3234
// updates that the remote still needs to sign for.
3235
func (c *OpenChannel) RemoteUnsignedLocalUpdates() ([]LogUpdate, error) {
3✔
3236
        var updates []LogUpdate
3✔
3237
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
3238
                chanBucket, err := fetchChanBucket(
3✔
3239
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
3240
                )
3✔
3241
                switch err {
3✔
3242
                case nil:
3✔
3243
                        break
3✔
3244
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
2✔
3245
                        return nil
2✔
3246
                default:
×
3247
                        return err
×
3248
                }
3249

3250
                updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
3✔
3251
                if updateBytes == nil {
6✔
3252
                        return nil
3✔
3253
                }
3✔
3254

3255
                r := bytes.NewReader(updateBytes)
3✔
3256
                updates, err = deserializeLogUpdates(r)
3✔
3257
                return err
3✔
3258
        }, func() {
3✔
3259
                updates = nil
3✔
3260
        })
3✔
3261
        if err != nil {
3✔
3262
                return nil, err
×
3263
        }
×
3264

3265
        return updates, nil
3✔
3266
}
3267

3268
// InsertNextRevocation inserts the _next_ commitment point (revocation) into
3269
// the database, and also modifies the internal RemoteNextRevocation attribute
3270
// to point to the passed key. This method is to be using during final channel
3271
// set up, _after_ the channel has been fully confirmed.
3272
//
3273
// NOTE: If this method isn't called, then the target channel won't be able to
3274
// propose new states for the commitment state of the remote party.
3275
func (c *OpenChannel) InsertNextRevocation(revKey *btcec.PublicKey) error {
3✔
3276
        c.Lock()
3✔
3277
        defer c.Unlock()
3✔
3278

3✔
3279
        c.RemoteNextRevocation = revKey
3✔
3280

3✔
3281
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
3282
                chanBucket, err := fetchChanBucketRw(
3✔
3283
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
3284
                )
3✔
3285
                if err != nil {
3✔
3286
                        return err
×
3287
                }
×
3288

3289
                return putChanRevocationState(chanBucket, c)
3✔
3290
        }, func() {})
3✔
3291
        if err != nil {
3✔
3292
                return err
×
3293
        }
×
3294

3295
        return nil
3✔
3296
}
3297

3298
// AdvanceCommitChainTail records the new state transition within an on-disk
3299
// append-only log which records all state transitions by the remote peer. In
3300
// the case of an uncooperative broadcast of a prior state by the remote peer,
3301
// this log can be consulted in order to reconstruct the state needed to
3302
// rectify the situation. This method will add the current commitment for the
3303
// remote party to the revocation log, and promote the current pending
3304
// commitment to the current remote commitment. The updates parameter is the
3305
// set of local updates that the peer still needs to send us a signature for.
3306
// We store this set of updates in case we go down.
3307
func (c *OpenChannel) AdvanceCommitChainTail(fwdPkg *FwdPkg,
3308
        updates []LogUpdate, ourOutputIndex, theirOutputIndex uint32) error {
3✔
3309

3✔
3310
        c.Lock()
3✔
3311
        defer c.Unlock()
3✔
3312

3✔
3313
        // If this is a restored channel, then we want to avoid mutating the
3✔
3314
        // state at all, as it's impossible to do so in a protocol compliant
3✔
3315
        // manner.
3✔
3316
        if c.hasChanStatus(ChanStatusRestored) {
3✔
3317
                return ErrNoRestoredChannelMutation
×
3318
        }
×
3319

3320
        var newRemoteCommit *ChannelCommitment
3✔
3321

3✔
3322
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
3323
                chanBucket, err := fetchChanBucketRw(
3✔
3324
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
3325
                )
3✔
3326
                if err != nil {
3✔
3327
                        return err
×
3328
                }
×
3329

3330
                // If the channel is marked as borked, then for safety reasons,
3331
                // we shouldn't attempt any further updates.
3332
                isBorked, err := c.isBorked(chanBucket)
3✔
3333
                if err != nil {
3✔
3334
                        return err
×
3335
                }
×
3336
                if isBorked {
3✔
3337
                        return ErrChanBorked
×
3338
                }
×
3339

3340
                // Persist the latest preimage state to disk as the remote peer
3341
                // has just added to our local preimage store, and given us a
3342
                // new pending revocation key.
3343
                if err := putChanRevocationState(chanBucket, c); err != nil {
3✔
3344
                        return err
×
3345
                }
×
3346

3347
                // With the current preimage producer/store state updated,
3348
                // append a new log entry recording this the delta of this
3349
                // state transition.
3350
                //
3351
                // TODO(roasbeef): could make the deltas relative, would save
3352
                // space, but then tradeoff for more disk-seeks to recover the
3353
                // full state.
3354
                logKey := revocationLogBucket
3✔
3355
                logBucket, err := chanBucket.CreateBucketIfNotExists(logKey)
3✔
3356
                if err != nil {
3✔
3357
                        return err
×
3358
                }
×
3359

3360
                // Before we append this revoked state to the revocation log,
3361
                // we'll swap out what's currently the tail of the commit tip,
3362
                // with the current locked-in commitment for the remote party.
3363
                tipBytes := chanBucket.Get(commitDiffKey)
3✔
3364
                tipReader := bytes.NewReader(tipBytes)
3✔
3365
                newCommit, err := deserializeCommitDiff(tipReader)
3✔
3366
                if err != nil {
3✔
3367
                        return err
×
3368
                }
×
3369
                err = putChanCommitment(
3✔
3370
                        chanBucket, &newCommit.Commitment, false,
3✔
3371
                )
3✔
3372
                if err != nil {
3✔
3373
                        return err
×
3374
                }
×
3375
                if err := chanBucket.Delete(commitDiffKey); err != nil {
3✔
3376
                        return err
×
3377
                }
×
3378

3379
                // With the commitment pointer swapped, we can now add the
3380
                // revoked (prior) state to the revocation log.
3381
                err = putRevocationLog(
3✔
3382
                        logBucket, &c.RemoteCommitment, ourOutputIndex,
3✔
3383
                        theirOutputIndex, c.Db.parent.noRevLogAmtData,
3✔
3384
                )
3✔
3385
                if err != nil {
3✔
3386
                        return err
×
3387
                }
×
3388

3389
                // Lastly, we write the forwarding package to disk so that we
3390
                // can properly recover from failures and reforward HTLCs that
3391
                // have not received a corresponding settle/fail.
3392
                if err := c.Packager.AddFwdPkg(tx, fwdPkg); err != nil {
3✔
3393
                        return err
×
3394
                }
×
3395

3396
                // Persist the unsigned acked updates that are not included
3397
                // in their new commitment.
3398
                updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
3✔
3399
                if updateBytes == nil {
6✔
3400
                        // This shouldn't normally happen as we always store
3✔
3401
                        // the number of updates, but could still be
3✔
3402
                        // encountered by nodes that are upgrading.
3✔
3403
                        newRemoteCommit = &newCommit.Commitment
3✔
3404
                        return nil
3✔
3405
                }
3✔
3406

3407
                r := bytes.NewReader(updateBytes)
3✔
3408
                unsignedUpdates, err := deserializeLogUpdates(r)
3✔
3409
                if err != nil {
3✔
3410
                        return err
×
3411
                }
×
3412

3413
                var validUpdates []LogUpdate
3✔
3414
                for _, upd := range unsignedUpdates {
6✔
3415
                        lIdx := upd.LogIndex
3✔
3416

3✔
3417
                        // Filter for updates that are not on the remote
3✔
3418
                        // commitment.
3✔
3419
                        if lIdx >= newCommit.Commitment.RemoteLogIndex {
6✔
3420
                                validUpdates = append(validUpdates, upd)
3✔
3421
                        }
3✔
3422
                }
3423

3424
                var b bytes.Buffer
3✔
3425
                err = serializeLogUpdates(&b, validUpdates)
3✔
3426
                if err != nil {
3✔
3427
                        return fmt.Errorf("unable to serialize log updates: %w",
×
3428
                                err)
×
3429
                }
×
3430

3431
                err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes())
3✔
3432
                if err != nil {
3✔
3433
                        return fmt.Errorf("unable to store under "+
×
3434
                                "unsignedAckedUpdatesKey: %w", err)
×
3435
                }
×
3436

3437
                // Persist the local updates the peer hasn't yet signed so they
3438
                // can be restored after restart.
3439
                var b2 bytes.Buffer
3✔
3440
                err = serializeLogUpdates(&b2, updates)
3✔
3441
                if err != nil {
3✔
3442
                        return err
×
3443
                }
×
3444

3445
                err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b2.Bytes())
3✔
3446
                if err != nil {
3✔
3447
                        return fmt.Errorf("unable to restore remote unsigned "+
×
3448
                                "local updates: %v", err)
×
3449
                }
×
3450

3451
                newRemoteCommit = &newCommit.Commitment
3✔
3452

3✔
3453
                return nil
3✔
3454
        }, func() {
3✔
3455
                newRemoteCommit = nil
3✔
3456
        })
3✔
3457
        if err != nil {
3✔
3458
                return err
×
3459
        }
×
3460

3461
        // With the db transaction complete, we'll swap over the in-memory
3462
        // pointer of the new remote commitment, which was previously the tip
3463
        // of the commit chain.
3464
        c.RemoteCommitment = *newRemoteCommit
3✔
3465

3✔
3466
        return nil
3✔
3467
}
3468

3469
// FinalHtlcInfo contains information about the final outcome of an htlc.
3470
type FinalHtlcInfo struct {
3471
        // Settled is true is the htlc was settled. If false, the htlc was
3472
        // failed.
3473
        Settled bool
3474

3475
        // Offchain indicates whether the htlc was resolved off-chain or
3476
        // on-chain.
3477
        Offchain bool
3478
}
3479

3480
// putFinalHtlc writes the final htlc outcome to the database. Additionally it
3481
// records whether the htlc was resolved off-chain or on-chain.
3482
func putFinalHtlc(finalHtlcsBucket kvdb.RwBucket, id uint64,
3483
        info FinalHtlcInfo) error {
3✔
3484

3✔
3485
        var key [8]byte
3✔
3486
        byteOrder.PutUint64(key[:], id)
3✔
3487

3✔
3488
        var finalHtlcByte FinalHtlcByte
3✔
3489
        if info.Settled {
6✔
3490
                finalHtlcByte |= FinalHtlcSettledBit
3✔
3491
        }
3✔
3492
        if info.Offchain {
6✔
3493
                finalHtlcByte |= FinalHtlcOffchainBit
3✔
3494
        }
3✔
3495

3496
        return finalHtlcsBucket.Put(key[:], []byte{byte(finalHtlcByte)})
3✔
3497
}
3498

3499
// NextLocalHtlcIndex returns the next unallocated local htlc index. To ensure
3500
// this always returns the next index that has been not been allocated, this
3501
// will first try to examine any pending commitments, before falling back to the
3502
// last locked-in remote commitment.
3503
func (c *OpenChannel) NextLocalHtlcIndex() (uint64, error) {
3✔
3504
        // First, load the most recent commit diff that we initiated for the
3✔
3505
        // remote party. If no pending commit is found, this is not treated as
3✔
3506
        // a critical error, since we can always fall back.
3✔
3507
        pendingRemoteCommit, err := c.RemoteCommitChainTip()
3✔
3508
        if err != nil && err != ErrNoPendingCommit {
3✔
3509
                return 0, err
×
3510
        }
×
3511

3512
        // If a pending commit was found, its local htlc index will be at least
3513
        // as large as the one on our local commitment.
3514
        if pendingRemoteCommit != nil {
3✔
3515
                return pendingRemoteCommit.Commitment.LocalHtlcIndex, nil
×
3516
        }
×
3517

3518
        // Otherwise, fallback to using the local htlc index of their commitment.
3519
        return c.RemoteCommitment.LocalHtlcIndex, nil
3✔
3520
}
3521

3522
// LoadFwdPkgs scans the forwarding log for any packages that haven't been
3523
// processed, and returns their deserialized log updates in map indexed by the
3524
// remote commitment height at which the updates were locked in.
3525
func (c *OpenChannel) LoadFwdPkgs() ([]*FwdPkg, error) {
3✔
3526
        c.RLock()
3✔
3527
        defer c.RUnlock()
3✔
3528

3✔
3529
        var fwdPkgs []*FwdPkg
3✔
3530
        if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
3531
                var err error
3✔
3532
                fwdPkgs, err = c.Packager.LoadFwdPkgs(tx)
3✔
3533
                return err
3✔
3534
        }, func() {
6✔
3535
                fwdPkgs = nil
3✔
3536
        }); err != nil {
3✔
3537
                return nil, err
×
3538
        }
×
3539

3540
        return fwdPkgs, nil
3✔
3541
}
3542

3543
// AckAddHtlcs updates the AckAddFilter containing any of the provided AddRefs
3544
// indicating that a response to this Add has been committed to the remote party.
3545
// Doing so will prevent these Add HTLCs from being reforwarded internally.
3546
func (c *OpenChannel) AckAddHtlcs(addRefs ...AddRef) error {
×
3547
        c.Lock()
×
3548
        defer c.Unlock()
×
3549

×
3550
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
3551
                return c.Packager.AckAddHtlcs(tx, addRefs...)
×
3552
        }, func() {})
×
3553
}
3554

3555
// AckSettleFails updates the SettleFailFilter containing any of the provided
3556
// SettleFailRefs, indicating that the response has been delivered to the
3557
// incoming link, corresponding to a particular AddRef. Doing so will prevent
3558
// the responses from being retransmitted internally.
3559
func (c *OpenChannel) AckSettleFails(settleFailRefs ...SettleFailRef) error {
×
3560
        c.Lock()
×
3561
        defer c.Unlock()
×
3562

×
3563
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
3564
                return c.Packager.AckSettleFails(tx, settleFailRefs...)
×
3565
        }, func() {})
×
3566
}
3567

3568
// SetFwdFilter atomically sets the forwarding filter for the forwarding package
3569
// identified by `height`.
3570
func (c *OpenChannel) SetFwdFilter(height uint64, fwdFilter *PkgFilter) error {
3✔
3571
        c.Lock()
3✔
3572
        defer c.Unlock()
3✔
3573

3✔
3574
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
3575
                return c.Packager.SetFwdFilter(tx, height, fwdFilter)
3✔
3576
        }, func() {})
6✔
3577
}
3578

3579
// RemoveFwdPkgs atomically removes forwarding packages specified by the remote
3580
// commitment heights. If one of the intermediate RemovePkg calls fails, then the
3581
// later packages won't be removed.
3582
//
3583
// NOTE: This method should only be called on packages marked FwdStateCompleted.
3584
func (c *OpenChannel) RemoveFwdPkgs(heights ...uint64) error {
3✔
3585
        c.Lock()
3✔
3586
        defer c.Unlock()
3✔
3587

3✔
3588
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
3589
                for _, height := range heights {
6✔
3590
                        err := c.Packager.RemovePkg(tx, height)
3✔
3591
                        if err != nil {
4✔
3592
                                return err
1✔
3593
                        }
1✔
3594
                }
3595

3596
                return nil
3✔
3597
        }, func() {})
3✔
3598
}
3599

3600
// revocationLogTailCommitHeight returns the commit height at the end of the
3601
// revocation log. This entry represents the last previous state for the remote
3602
// node's commitment chain. The ChannelDelta returned by this method will
3603
// always lag one state behind the most current (unrevoked) state of the remote
3604
// node's commitment chain.
3605
// NOTE: used in unit test only.
3606
func (c *OpenChannel) revocationLogTailCommitHeight() (uint64, error) {
×
3607
        c.RLock()
×
3608
        defer c.RUnlock()
×
3609

×
3610
        var height uint64
×
3611

×
3612
        // If we haven't created any state updates yet, then we'll exit early as
×
3613
        // there's nothing to be found on disk in the revocation bucket.
×
3614
        if c.RemoteCommitment.CommitHeight == 0 {
×
3615
                return height, nil
×
3616
        }
×
3617

3618
        if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
×
3619
                chanBucket, err := fetchChanBucket(
×
3620
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
×
3621
                )
×
3622
                if err != nil {
×
3623
                        return err
×
3624
                }
×
3625

3626
                logBucket, err := fetchLogBucket(chanBucket)
×
3627
                if err != nil {
×
3628
                        return err
×
3629
                }
×
3630

3631
                // Once we have the bucket that stores the revocation log from
3632
                // this channel, we'll jump to the _last_ key in bucket. Since
3633
                // the key is the commit height, we'll decode the bytes and
3634
                // return it.
3635
                cursor := logBucket.ReadCursor()
×
3636
                rawHeight, _ := cursor.Last()
×
3637
                height = byteOrder.Uint64(rawHeight)
×
3638

×
3639
                return nil
×
3640
        }, func() {}); err != nil {
×
3641
                return height, err
×
3642
        }
×
3643

3644
        return height, nil
×
3645
}
3646

3647
// CommitmentHeight returns the current commitment height. The commitment
3648
// height represents the number of updates to the commitment state to date.
3649
// This value is always monotonically increasing. This method is provided in
3650
// order to allow multiple instances of a particular open channel to obtain a
3651
// consistent view of the number of channel updates to date.
3652
func (c *OpenChannel) CommitmentHeight() (uint64, error) {
×
3653
        c.RLock()
×
3654
        defer c.RUnlock()
×
3655

×
3656
        var height uint64
×
3657
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
×
3658
                // Get the bucket dedicated to storing the metadata for open
×
3659
                // channels.
×
3660
                chanBucket, err := fetchChanBucket(
×
3661
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
×
3662
                )
×
3663
                if err != nil {
×
3664
                        return err
×
3665
                }
×
3666

3667
                commit, err := fetchChanCommitment(chanBucket, true)
×
3668
                if err != nil {
×
3669
                        return err
×
3670
                }
×
3671

3672
                height = commit.CommitHeight
×
3673
                return nil
×
3674
        }, func() {
×
3675
                height = 0
×
3676
        })
×
3677
        if err != nil {
×
3678
                return 0, err
×
3679
        }
×
3680

3681
        return height, nil
×
3682
}
3683

3684
// FindPreviousState scans through the append-only log in an attempt to recover
3685
// the previous channel state indicated by the update number. This method is
3686
// intended to be used for obtaining the relevant data needed to claim all
3687
// funds rightfully spendable in the case of an on-chain broadcast of the
3688
// commitment transaction.
3689
func (c *OpenChannel) FindPreviousState(
3690
        updateNum uint64) (*RevocationLog, *ChannelCommitment, error) {
3✔
3691

3✔
3692
        c.RLock()
3✔
3693
        defer c.RUnlock()
3✔
3694

3✔
3695
        commit := &ChannelCommitment{}
3✔
3696
        rl := &RevocationLog{}
3✔
3697

3✔
3698
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
3699
                chanBucket, err := fetchChanBucket(
3✔
3700
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
3701
                )
3✔
3702
                if err != nil {
3✔
3703
                        return err
×
3704
                }
×
3705

3706
                // Find the revocation log from both the new and the old
3707
                // bucket.
3708
                r, c, err := fetchRevocationLogCompatible(chanBucket, updateNum)
3✔
3709
                if err != nil {
6✔
3710
                        return err
3✔
3711
                }
3✔
3712

3713
                rl = r
3✔
3714
                commit = c
3✔
3715
                return nil
3✔
3716
        }, func() {})
3✔
3717
        if err != nil {
6✔
3718
                return nil, nil, err
3✔
3719
        }
3✔
3720

3721
        // Either the `rl` or the `commit` is nil here. We return them as-is
3722
        // and leave it to the caller to decide its following action.
3723
        return rl, commit, nil
3✔
3724
}
3725

3726
// ClosureType is an enum like structure that details exactly _how_ a channel
3727
// was closed. Three closure types are currently possible: none, cooperative,
3728
// local force close, remote force close, and (remote) breach.
3729
type ClosureType uint8
3730

3731
const (
3732
        // CooperativeClose indicates that a channel has been closed
3733
        // cooperatively.  This means that both channel peers were online and
3734
        // signed a new transaction paying out the settled balance of the
3735
        // contract.
3736
        CooperativeClose ClosureType = 0
3737

3738
        // LocalForceClose indicates that we have unilaterally broadcast our
3739
        // current commitment state on-chain.
3740
        LocalForceClose ClosureType = 1
3741

3742
        // RemoteForceClose indicates that the remote peer has unilaterally
3743
        // broadcast their current commitment state on-chain.
3744
        RemoteForceClose ClosureType = 4
3745

3746
        // BreachClose indicates that the remote peer attempted to broadcast a
3747
        // prior _revoked_ channel state.
3748
        BreachClose ClosureType = 2
3749

3750
        // FundingCanceled indicates that the channel never was fully opened
3751
        // before it was marked as closed in the database. This can happen if
3752
        // we or the remote fail at some point during the opening workflow, or
3753
        // we timeout waiting for the funding transaction to be confirmed.
3754
        FundingCanceled ClosureType = 3
3755

3756
        // Abandoned indicates that the channel state was removed without
3757
        // any further actions. This is intended to clean up unusable
3758
        // channels during development.
3759
        Abandoned ClosureType = 5
3760
)
3761

3762
// ChannelCloseSummary contains the final state of a channel at the point it
3763
// was closed. Once a channel is closed, all the information pertaining to that
3764
// channel within the openChannelBucket is deleted, and a compact summary is
3765
// put in place instead.
3766
type ChannelCloseSummary struct {
3767
        // ChanPoint is the outpoint for this channel's funding transaction,
3768
        // and is used as a unique identifier for the channel.
3769
        ChanPoint wire.OutPoint
3770

3771
        // ShortChanID encodes the exact location in the chain in which the
3772
        // channel was initially confirmed. This includes: the block height,
3773
        // transaction index, and the output within the target transaction.
3774
        ShortChanID lnwire.ShortChannelID
3775

3776
        // ChainHash is the hash of the genesis block that this channel resides
3777
        // within.
3778
        ChainHash chainhash.Hash
3779

3780
        // ClosingTXID is the txid of the transaction which ultimately closed
3781
        // this channel.
3782
        ClosingTXID chainhash.Hash
3783

3784
        // RemotePub is the public key of the remote peer that we formerly had
3785
        // a channel with.
3786
        RemotePub *btcec.PublicKey
3787

3788
        // Capacity was the total capacity of the channel.
3789
        Capacity btcutil.Amount
3790

3791
        // CloseHeight is the height at which the funding transaction was
3792
        // spent.
3793
        CloseHeight uint32
3794

3795
        // SettledBalance is our total balance settled balance at the time of
3796
        // channel closure. This _does not_ include the sum of any outputs that
3797
        // have been time-locked as a result of the unilateral channel closure.
3798
        SettledBalance btcutil.Amount
3799

3800
        // TimeLockedBalance is the sum of all the time-locked outputs at the
3801
        // time of channel closure. If we triggered the force closure of this
3802
        // channel, then this value will be non-zero if our settled output is
3803
        // above the dust limit. If we were on the receiving side of a channel
3804
        // force closure, then this value will be non-zero if we had any
3805
        // outstanding outgoing HTLC's at the time of channel closure.
3806
        TimeLockedBalance btcutil.Amount
3807

3808
        // CloseType details exactly _how_ the channel was closed. Five closure
3809
        // types are possible: cooperative, local force, remote force, breach
3810
        // and funding canceled.
3811
        CloseType ClosureType
3812

3813
        // IsPending indicates whether this channel is in the 'pending close'
3814
        // state, which means the channel closing transaction has been
3815
        // confirmed, but not yet been fully resolved. In the case of a channel
3816
        // that has been cooperatively closed, it will go straight into the
3817
        // fully resolved state as soon as the closing transaction has been
3818
        // confirmed. However, for channels that have been force closed, they'll
3819
        // stay marked as "pending" until _all_ the pending funds have been
3820
        // swept.
3821
        IsPending bool
3822

3823
        // RemoteCurrentRevocation is the current revocation for their
3824
        // commitment transaction. However, since this is the derived public key,
3825
        // we don't yet have the private key so we aren't yet able to verify
3826
        // that it's actually in the hash chain.
3827
        RemoteCurrentRevocation *btcec.PublicKey
3828

3829
        // RemoteNextRevocation is the revocation key to be used for the *next*
3830
        // commitment transaction we create for the local node. Within the
3831
        // specification, this value is referred to as the
3832
        // per-commitment-point.
3833
        RemoteNextRevocation *btcec.PublicKey
3834

3835
        // LocalChanConfig is the channel configuration for the local node.
3836
        LocalChanConfig ChannelConfig
3837

3838
        // LastChanSyncMsg is the ChannelReestablish message for this channel
3839
        // for the state at the point where it was closed.
3840
        LastChanSyncMsg *lnwire.ChannelReestablish
3841
}
3842

3843
// CloseChannel closes a previously active Lightning channel. Closing a channel
3844
// entails deleting all saved state within the database concerning this
3845
// channel. This method also takes a struct that summarizes the state of the
3846
// channel at closing, this compact representation will be the only component
3847
// of a channel left over after a full closing. It takes an optional set of
3848
// channel statuses which will be written to the historical channel bucket.
3849
// These statuses are used to record close initiators.
3850
func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary,
3851
        statuses ...ChannelStatus) error {
3✔
3852

3✔
3853
        c.Lock()
3✔
3854
        defer c.Unlock()
3✔
3855

3✔
3856
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
3857
                openChanBucket := tx.ReadWriteBucket(openChannelBucket)
3✔
3858
                if openChanBucket == nil {
3✔
3859
                        return ErrNoChanDBExists
×
3860
                }
×
3861

3862
                nodePub := c.IdentityPub.SerializeCompressed()
3✔
3863
                nodeChanBucket := openChanBucket.NestedReadWriteBucket(nodePub)
3✔
3864
                if nodeChanBucket == nil {
3✔
3865
                        return ErrNoActiveChannels
×
3866
                }
×
3867

3868
                chainBucket := nodeChanBucket.NestedReadWriteBucket(c.ChainHash[:])
3✔
3869
                if chainBucket == nil {
3✔
3870
                        return ErrNoActiveChannels
×
3871
                }
×
3872

3873
                var chanPointBuf bytes.Buffer
3✔
3874
                err := graphdb.WriteOutpoint(&chanPointBuf, &c.FundingOutpoint)
3✔
3875
                if err != nil {
3✔
3876
                        return err
×
3877
                }
×
3878
                chanKey := chanPointBuf.Bytes()
3✔
3879
                chanBucket := chainBucket.NestedReadWriteBucket(
3✔
3880
                        chanKey,
3✔
3881
                )
3✔
3882
                if chanBucket == nil {
3✔
3883
                        return ErrNoActiveChannels
×
3884
                }
×
3885

3886
                // Before we delete the channel state, we'll read out the full
3887
                // details, as we'll also store portions of this information
3888
                // for record keeping.
3889
                chanState, err := fetchOpenChannel(
3✔
3890
                        chanBucket, &c.FundingOutpoint,
3✔
3891
                )
3✔
3892
                if err != nil {
3✔
3893
                        return err
×
3894
                }
×
3895

3896
                // Delete all the forwarding packages stored for this particular
3897
                // channel.
3898
                if err = chanState.Packager.Wipe(tx); err != nil {
3✔
3899
                        return err
×
3900
                }
×
3901

3902
                // Now that the index to this channel has been deleted, purge
3903
                // the remaining channel metadata from the database.
3904
                err = deleteOpenChannel(chanBucket)
3✔
3905
                if err != nil {
3✔
3906
                        return err
×
3907
                }
×
3908

3909
                // We'll also remove the channel from the frozen channel bucket
3910
                // if we need to.
3911
                if c.ChanType.IsFrozen() || c.ChanType.HasLeaseExpiration() {
6✔
3912
                        err := deleteThawHeight(chanBucket)
3✔
3913
                        if err != nil {
3✔
3914
                                return err
×
3915
                        }
×
3916
                }
3917

3918
                // With the base channel data deleted, attempt to delete the
3919
                // information stored within the revocation log.
3920
                if err := deleteLogBucket(chanBucket); err != nil {
3✔
3921
                        return err
×
3922
                }
×
3923

3924
                err = chainBucket.DeleteNestedBucket(chanPointBuf.Bytes())
3✔
3925
                if err != nil {
3✔
3926
                        return err
×
3927
                }
×
3928

3929
                // Fetch the outpoint bucket to see if the outpoint exists or
3930
                // not.
3931
                opBucket := tx.ReadWriteBucket(outpointBucket)
3✔
3932
                if opBucket == nil {
3✔
3933
                        return ErrNoChanDBExists
×
3934
                }
×
3935

3936
                // Add the closed outpoint to our outpoint index. This should
3937
                // replace an open outpoint in the index.
3938
                if opBucket.Get(chanPointBuf.Bytes()) == nil {
3✔
3939
                        return ErrMissingIndexEntry
×
3940
                }
×
3941

3942
                status := uint8(outpointClosed)
3✔
3943

3✔
3944
                // Write the IndexStatus of this outpoint as the first entry in a tlv
3✔
3945
                // stream.
3✔
3946
                statusRecord := tlv.MakePrimitiveRecord(indexStatusType, &status)
3✔
3947
                opStream, err := tlv.NewStream(statusRecord)
3✔
3948
                if err != nil {
3✔
3949
                        return err
×
3950
                }
×
3951

3952
                var b bytes.Buffer
3✔
3953
                if err := opStream.Encode(&b); err != nil {
3✔
3954
                        return err
×
3955
                }
×
3956

3957
                // Finally add the closed outpoint and tlv stream to the index.
3958
                if err := opBucket.Put(chanPointBuf.Bytes(), b.Bytes()); err != nil {
3✔
3959
                        return err
×
3960
                }
×
3961

3962
                // Add channel state to the historical channel bucket.
3963
                historicalBucket, err := tx.CreateTopLevelBucket(
3✔
3964
                        historicalChannelBucket,
3✔
3965
                )
3✔
3966
                if err != nil {
3✔
3967
                        return err
×
3968
                }
×
3969

3970
                historicalChanBucket, err :=
3✔
3971
                        historicalBucket.CreateBucketIfNotExists(chanKey)
3✔
3972
                if err != nil {
3✔
3973
                        return err
×
3974
                }
×
3975

3976
                // Apply any additional statuses to the channel state.
3977
                for _, status := range statuses {
6✔
3978
                        chanState.chanStatus |= status
3✔
3979
                }
3✔
3980

3981
                err = putOpenChannel(historicalChanBucket, chanState)
3✔
3982
                if err != nil {
3✔
3983
                        return err
×
3984
                }
×
3985

3986
                // Finally, create a summary of this channel in the closed
3987
                // channel bucket for this node.
3988
                return putChannelCloseSummary(
3✔
3989
                        tx, chanPointBuf.Bytes(), summary, chanState,
3✔
3990
                )
3✔
3991
        }, func() {})
3✔
3992
}
3993

3994
// ChannelSnapshot is a frozen snapshot of the current channel state. A
3995
// snapshot is detached from the original channel that generated it, providing
3996
// read-only access to the current or prior state of an active channel.
3997
//
3998
// TODO(roasbeef): remove all together? pretty much just commitment
3999
type ChannelSnapshot struct {
4000
        // RemoteIdentity is the identity public key of the remote node that we
4001
        // are maintaining the open channel with.
4002
        RemoteIdentity btcec.PublicKey
4003

4004
        // ChanPoint is the outpoint that created the channel. This output is
4005
        // found within the funding transaction and uniquely identified the
4006
        // channel on the resident chain.
4007
        ChannelPoint wire.OutPoint
4008

4009
        // ChainHash is the genesis hash of the chain that the channel resides
4010
        // within.
4011
        ChainHash chainhash.Hash
4012

4013
        // Capacity is the total capacity of the channel.
4014
        Capacity btcutil.Amount
4015

4016
        // TotalMSatSent is the total number of milli-satoshis we've sent
4017
        // within this channel.
4018
        TotalMSatSent lnwire.MilliSatoshi
4019

4020
        // TotalMSatReceived is the total number of milli-satoshis we've
4021
        // received within this channel.
4022
        TotalMSatReceived lnwire.MilliSatoshi
4023

4024
        // ChannelCommitment is the current up-to-date commitment for the
4025
        // target channel.
4026
        ChannelCommitment
4027
}
4028

4029
// Snapshot returns a read-only snapshot of the current channel state. This
4030
// snapshot includes information concerning the current settled balance within
4031
// the channel, metadata detailing total flows, and any outstanding HTLCs.
4032
func (c *OpenChannel) Snapshot() *ChannelSnapshot {
3✔
4033
        c.RLock()
3✔
4034
        defer c.RUnlock()
3✔
4035

3✔
4036
        localCommit := c.LocalCommitment
3✔
4037
        snapshot := &ChannelSnapshot{
3✔
4038
                RemoteIdentity:    *c.IdentityPub,
3✔
4039
                ChannelPoint:      c.FundingOutpoint,
3✔
4040
                Capacity:          c.Capacity,
3✔
4041
                TotalMSatSent:     c.TotalMSatSent,
3✔
4042
                TotalMSatReceived: c.TotalMSatReceived,
3✔
4043
                ChainHash:         c.ChainHash,
3✔
4044
                ChannelCommitment: ChannelCommitment{
3✔
4045
                        LocalBalance:  localCommit.LocalBalance,
3✔
4046
                        RemoteBalance: localCommit.RemoteBalance,
3✔
4047
                        CommitHeight:  localCommit.CommitHeight,
3✔
4048
                        CommitFee:     localCommit.CommitFee,
3✔
4049
                },
3✔
4050
        }
3✔
4051

3✔
4052
        localCommit.CustomBlob.WhenSome(func(blob tlv.Blob) {
3✔
4053
                blobCopy := make([]byte, len(blob))
×
4054
                copy(blobCopy, blob)
×
4055

×
4056
                snapshot.ChannelCommitment.CustomBlob = fn.Some(blobCopy)
×
4057
        })
×
4058

4059
        // Copy over the current set of HTLCs to ensure the caller can't mutate
4060
        // our internal state.
4061
        snapshot.Htlcs = make([]HTLC, len(localCommit.Htlcs))
3✔
4062
        for i, h := range localCommit.Htlcs {
6✔
4063
                snapshot.Htlcs[i] = h.Copy()
3✔
4064
        }
3✔
4065

4066
        return snapshot
3✔
4067
}
4068

4069
// LatestCommitments returns the two latest commitments for both the local and
4070
// remote party. These commitments are read from disk to ensure that only the
4071
// latest fully committed state is returned. The first commitment returned is
4072
// the local commitment, and the second returned is the remote commitment.
4073
func (c *OpenChannel) LatestCommitments() (*ChannelCommitment, *ChannelCommitment, error) {
3✔
4074
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
4075
                chanBucket, err := fetchChanBucket(
3✔
4076
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
4077
                )
3✔
4078
                if err != nil {
3✔
4079
                        return err
×
4080
                }
×
4081

4082
                return fetchChanCommitments(chanBucket, c)
3✔
4083
        }, func() {})
3✔
4084
        if err != nil {
3✔
4085
                return nil, nil, err
×
4086
        }
×
4087

4088
        return &c.LocalCommitment, &c.RemoteCommitment, nil
3✔
4089
}
4090

4091
// RemoteRevocationStore returns the most up to date commitment version of the
4092
// revocation storage tree for the remote party. This method can be used when
4093
// acting on a possible contract breach to ensure, that the caller has the most
4094
// up to date information required to deliver justice.
4095
func (c *OpenChannel) RemoteRevocationStore() (shachain.Store, error) {
3✔
4096
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
4097
                chanBucket, err := fetchChanBucket(
3✔
4098
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
4099
                )
3✔
4100
                if err != nil {
3✔
4101
                        return err
×
4102
                }
×
4103

4104
                return fetchChanRevocationState(chanBucket, c)
3✔
4105
        }, func() {})
3✔
4106
        if err != nil {
3✔
4107
                return nil, err
×
4108
        }
×
4109

4110
        return c.RevocationStore, nil
3✔
4111
}
4112

4113
// AbsoluteThawHeight determines a frozen channel's absolute thaw height. If the
4114
// channel is not frozen, then 0 is returned.
4115
func (c *OpenChannel) AbsoluteThawHeight() (uint32, error) {
3✔
4116
        // Only frozen channels have a thaw height.
3✔
4117
        if !c.ChanType.IsFrozen() && !c.ChanType.HasLeaseExpiration() {
6✔
4118
                return 0, nil
3✔
4119
        }
3✔
4120

4121
        // If the channel has the frozen bit set and it's thaw height is below
4122
        // the absolute threshold, then it's interpreted as a relative height to
4123
        // the chain's current height.
4124
        if c.ChanType.IsFrozen() && c.ThawHeight < AbsoluteThawHeightThreshold {
6✔
4125
                // We'll only known of the channel's short ID once it's
3✔
4126
                // confirmed.
3✔
4127
                if c.IsPending {
3✔
4128
                        return 0, errors.New("cannot use relative thaw " +
×
4129
                                "height for unconfirmed channel")
×
4130
                }
×
4131

4132
                // For non-zero-conf channels, this is the base height to use.
4133
                blockHeightBase := c.ShortChannelID.BlockHeight
3✔
4134

3✔
4135
                // If this is a zero-conf channel, the ShortChannelID will be
3✔
4136
                // an alias.
3✔
4137
                if c.IsZeroConf() {
3✔
4138
                        if !c.ZeroConfConfirmed() {
×
4139
                                return 0, errors.New("cannot use relative " +
×
4140
                                        "height for unconfirmed zero-conf " +
×
4141
                                        "channel")
×
4142
                        }
×
4143

4144
                        // Use the confirmed SCID's BlockHeight.
4145
                        blockHeightBase = c.confirmedScid.BlockHeight
×
4146
                }
4147

4148
                return blockHeightBase + c.ThawHeight, nil
3✔
4149
        }
4150

4151
        return c.ThawHeight, nil
×
4152
}
4153

4154
// DeriveHeightHint derives the block height for the channel opening.
4155
func (c *OpenChannel) DeriveHeightHint() uint32 {
3✔
4156
        // As a height hint, we'll try to use the opening height, but if the
3✔
4157
        // channel isn't yet open, then we'll use the height it was broadcast
3✔
4158
        // at. This may be an unconfirmed zero-conf channel.
3✔
4159
        heightHint := c.ShortChanID().BlockHeight
3✔
4160
        if heightHint == 0 {
6✔
4161
                heightHint = c.BroadcastHeight()
3✔
4162
        }
3✔
4163

4164
        // Since no zero-conf state is stored in a channel backup, the below
4165
        // logic will not be triggered for restored, zero-conf channels. Set
4166
        // the height hint for zero-conf channels.
4167
        if c.IsZeroConf() {
6✔
4168
                if c.ZeroConfConfirmed() {
6✔
4169
                        // If the zero-conf channel is confirmed, we'll use the
3✔
4170
                        // confirmed SCID's block height.
3✔
4171
                        heightHint = c.ZeroConfRealScid().BlockHeight
3✔
4172
                } else {
6✔
4173
                        // The zero-conf channel is unconfirmed. We'll need to
3✔
4174
                        // use the FundingBroadcastHeight.
3✔
4175
                        heightHint = c.BroadcastHeight()
3✔
4176
                }
3✔
4177
        }
4178

4179
        return heightHint
3✔
4180
}
4181

4182
func putChannelCloseSummary(tx kvdb.RwTx, chanID []byte,
4183
        summary *ChannelCloseSummary, lastChanState *OpenChannel) error {
3✔
4184

3✔
4185
        closedChanBucket, err := tx.CreateTopLevelBucket(closedChannelBucket)
3✔
4186
        if err != nil {
3✔
4187
                return err
×
4188
        }
×
4189

4190
        summary.RemoteCurrentRevocation = lastChanState.RemoteCurrentRevocation
3✔
4191
        summary.RemoteNextRevocation = lastChanState.RemoteNextRevocation
3✔
4192
        summary.LocalChanConfig = lastChanState.LocalChanCfg
3✔
4193

3✔
4194
        var b bytes.Buffer
3✔
4195
        if err := serializeChannelCloseSummary(&b, summary); err != nil {
3✔
4196
                return err
×
4197
        }
×
4198

4199
        return closedChanBucket.Put(chanID, b.Bytes())
3✔
4200
}
4201

4202
func serializeChannelCloseSummary(w io.Writer, cs *ChannelCloseSummary) error {
3✔
4203
        err := WriteElements(w,
3✔
4204
                cs.ChanPoint, cs.ShortChanID, cs.ChainHash, cs.ClosingTXID,
3✔
4205
                cs.CloseHeight, cs.RemotePub, cs.Capacity, cs.SettledBalance,
3✔
4206
                cs.TimeLockedBalance, cs.CloseType, cs.IsPending,
3✔
4207
        )
3✔
4208
        if err != nil {
3✔
4209
                return err
×
4210
        }
×
4211

4212
        // If this is a close channel summary created before the addition of
4213
        // the new fields, then we can exit here.
4214
        if cs.RemoteCurrentRevocation == nil {
3✔
4215
                return WriteElements(w, false)
×
4216
        }
×
4217

4218
        // If fields are present, write boolean to indicate this, and continue.
4219
        if err := WriteElements(w, true); err != nil {
3✔
4220
                return err
×
4221
        }
×
4222

4223
        if err := WriteElements(w, cs.RemoteCurrentRevocation); err != nil {
3✔
4224
                return err
×
4225
        }
×
4226

4227
        if err := writeChanConfig(w, &cs.LocalChanConfig); err != nil {
3✔
4228
                return err
×
4229
        }
×
4230

4231
        // The RemoteNextRevocation field is optional, as it's possible for a
4232
        // channel to be closed before we learn of the next unrevoked
4233
        // revocation point for the remote party. Write a boolean indicating
4234
        // whether this field is present or not.
4235
        if err := WriteElements(w, cs.RemoteNextRevocation != nil); err != nil {
3✔
4236
                return err
×
4237
        }
×
4238

4239
        // Write the field, if present.
4240
        if cs.RemoteNextRevocation != nil {
6✔
4241
                if err = WriteElements(w, cs.RemoteNextRevocation); err != nil {
3✔
4242
                        return err
×
4243
                }
×
4244
        }
4245

4246
        // Write whether the channel sync message is present.
4247
        if err := WriteElements(w, cs.LastChanSyncMsg != nil); err != nil {
3✔
4248
                return err
×
4249
        }
×
4250

4251
        // Write the channel sync message, if present.
4252
        if cs.LastChanSyncMsg != nil {
6✔
4253
                if err := WriteElements(w, cs.LastChanSyncMsg); err != nil {
3✔
4254
                        return err
×
4255
                }
×
4256
        }
4257

4258
        return nil
3✔
4259
}
4260

4261
func deserializeCloseChannelSummary(r io.Reader) (*ChannelCloseSummary, error) {
3✔
4262
        c := &ChannelCloseSummary{}
3✔
4263

3✔
4264
        err := ReadElements(r,
3✔
4265
                &c.ChanPoint, &c.ShortChanID, &c.ChainHash, &c.ClosingTXID,
3✔
4266
                &c.CloseHeight, &c.RemotePub, &c.Capacity, &c.SettledBalance,
3✔
4267
                &c.TimeLockedBalance, &c.CloseType, &c.IsPending,
3✔
4268
        )
3✔
4269
        if err != nil {
3✔
4270
                return nil, err
×
4271
        }
×
4272

4273
        // We'll now check to see if the channel close summary was encoded with
4274
        // any of the additional optional fields.
4275
        var hasNewFields bool
3✔
4276
        err = ReadElements(r, &hasNewFields)
3✔
4277
        if err != nil {
3✔
4278
                return nil, err
×
4279
        }
×
4280

4281
        // If fields are not present, we can return.
4282
        if !hasNewFields {
3✔
4283
                return c, nil
×
4284
        }
×
4285

4286
        // Otherwise read the new fields.
4287
        if err := ReadElements(r, &c.RemoteCurrentRevocation); err != nil {
3✔
4288
                return nil, err
×
4289
        }
×
4290

4291
        if err := readChanConfig(r, &c.LocalChanConfig); err != nil {
3✔
4292
                return nil, err
×
4293
        }
×
4294

4295
        // Finally, we'll attempt to read the next unrevoked commitment point
4296
        // for the remote party. If we closed the channel before receiving a
4297
        // channel_ready message then this might not be present. A boolean
4298
        // indicating whether the field is present will come first.
4299
        var hasRemoteNextRevocation bool
3✔
4300
        err = ReadElements(r, &hasRemoteNextRevocation)
3✔
4301
        if err != nil {
3✔
4302
                return nil, err
×
4303
        }
×
4304

4305
        // If this field was written, read it.
4306
        if hasRemoteNextRevocation {
6✔
4307
                err = ReadElements(r, &c.RemoteNextRevocation)
3✔
4308
                if err != nil {
3✔
4309
                        return nil, err
×
4310
                }
×
4311
        }
4312

4313
        // Check if we have a channel sync message to read.
4314
        var hasChanSyncMsg bool
3✔
4315
        err = ReadElements(r, &hasChanSyncMsg)
3✔
4316
        if err == io.EOF {
3✔
4317
                return c, nil
×
4318
        } else if err != nil {
3✔
4319
                return nil, err
×
4320
        }
×
4321

4322
        // If a chan sync message is present, read it.
4323
        if hasChanSyncMsg {
6✔
4324
                // We must pass in reference to a lnwire.Message for the codec
3✔
4325
                // to support it.
3✔
4326
                var msg lnwire.Message
3✔
4327
                if err := ReadElements(r, &msg); err != nil {
3✔
4328
                        return nil, err
×
4329
                }
×
4330

4331
                chanSync, ok := msg.(*lnwire.ChannelReestablish)
3✔
4332
                if !ok {
3✔
4333
                        return nil, errors.New("unable cast db Message to " +
×
4334
                                "ChannelReestablish")
×
4335
                }
×
4336
                c.LastChanSyncMsg = chanSync
3✔
4337
        }
4338

4339
        return c, nil
3✔
4340
}
4341

4342
func writeChanConfig(b io.Writer, c *ChannelConfig) error {
3✔
4343
        return WriteElements(b,
3✔
4344
                c.DustLimit, c.MaxPendingAmount, c.ChanReserve, c.MinHTLC,
3✔
4345
                c.MaxAcceptedHtlcs, c.CsvDelay, c.MultiSigKey,
3✔
4346
                c.RevocationBasePoint, c.PaymentBasePoint, c.DelayBasePoint,
3✔
4347
                c.HtlcBasePoint,
3✔
4348
        )
3✔
4349
}
3✔
4350

4351
// fundingTxPresent returns true if expect the funding transcation to be found
4352
// on disk or already populated within the passed open channel struct.
4353
func fundingTxPresent(channel *OpenChannel) bool {
3✔
4354
        chanType := channel.ChanType
3✔
4355

3✔
4356
        return chanType.IsSingleFunder() && chanType.HasFundingTx() &&
3✔
4357
                channel.IsInitiator &&
3✔
4358
                !channel.hasChanStatus(ChanStatusRestored)
3✔
4359
}
3✔
4360

4361
func putChanInfo(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
3✔
4362
        var w bytes.Buffer
3✔
4363
        if err := WriteElements(&w,
3✔
4364
                channel.ChanType, channel.ChainHash, channel.FundingOutpoint,
3✔
4365
                channel.ShortChannelID, channel.IsPending, channel.IsInitiator,
3✔
4366
                channel.chanStatus, channel.FundingBroadcastHeight,
3✔
4367
                channel.NumConfsRequired, channel.ChannelFlags,
3✔
4368
                channel.IdentityPub, channel.Capacity, channel.TotalMSatSent,
3✔
4369
                channel.TotalMSatReceived,
3✔
4370
        ); err != nil {
3✔
4371
                return err
×
4372
        }
×
4373

4374
        // For single funder channels that we initiated, and we have the
4375
        // funding transaction, then write the funding txn.
4376
        if fundingTxPresent(channel) {
6✔
4377
                if err := WriteElement(&w, channel.FundingTxn); err != nil {
3✔
4378
                        return err
×
4379
                }
×
4380
        }
4381

4382
        if err := writeChanConfig(&w, &channel.LocalChanCfg); err != nil {
3✔
4383
                return err
×
4384
        }
×
4385
        if err := writeChanConfig(&w, &channel.RemoteChanCfg); err != nil {
3✔
4386
                return err
×
4387
        }
×
4388

4389
        auxData := channel.extractTlvData()
3✔
4390
        if err := auxData.encode(&w); err != nil {
3✔
4391
                return fmt.Errorf("unable to encode aux data: %w", err)
×
4392
        }
×
4393

4394
        if err := chanBucket.Put(chanInfoKey, w.Bytes()); err != nil {
3✔
4395
                return err
×
4396
        }
×
4397

4398
        // Finally, add optional shutdown scripts for the local and remote peer if
4399
        // they are present.
4400
        if err := putOptionalUpfrontShutdownScript(
3✔
4401
                chanBucket, localUpfrontShutdownKey, channel.LocalShutdownScript,
3✔
4402
        ); err != nil {
3✔
4403
                return err
×
4404
        }
×
4405

4406
        return putOptionalUpfrontShutdownScript(
3✔
4407
                chanBucket, remoteUpfrontShutdownKey, channel.RemoteShutdownScript,
3✔
4408
        )
3✔
4409
}
4410

4411
// putOptionalUpfrontShutdownScript adds a shutdown script under the key
4412
// provided if it has a non-zero length.
4413
func putOptionalUpfrontShutdownScript(chanBucket kvdb.RwBucket, key []byte,
4414
        script []byte) error {
3✔
4415
        // If the script is empty, we do not need to add anything.
3✔
4416
        if len(script) == 0 {
6✔
4417
                return nil
3✔
4418
        }
3✔
4419

4420
        var w bytes.Buffer
3✔
4421
        if err := WriteElement(&w, script); err != nil {
3✔
4422
                return err
×
4423
        }
×
4424

4425
        return chanBucket.Put(key, w.Bytes())
3✔
4426
}
4427

4428
// getOptionalUpfrontShutdownScript reads the shutdown script stored under the
4429
// key provided if it is present. Upfront shutdown scripts are optional, so the
4430
// function returns with no error if the key is not present.
4431
func getOptionalUpfrontShutdownScript(chanBucket kvdb.RBucket, key []byte,
4432
        script *lnwire.DeliveryAddress) error {
3✔
4433

3✔
4434
        // Return early if the bucket does not exit, a shutdown script was not set.
3✔
4435
        bs := chanBucket.Get(key)
3✔
4436
        if bs == nil {
6✔
4437
                return nil
3✔
4438
        }
3✔
4439

4440
        var tempScript []byte
3✔
4441
        r := bytes.NewReader(bs)
3✔
4442
        if err := ReadElement(r, &tempScript); err != nil {
3✔
4443
                return err
×
4444
        }
×
4445
        *script = tempScript
3✔
4446

3✔
4447
        return nil
3✔
4448
}
4449

4450
func serializeChanCommit(w io.Writer, c *ChannelCommitment) error {
3✔
4451
        if err := WriteElements(w,
3✔
4452
                c.CommitHeight, c.LocalLogIndex, c.LocalHtlcIndex,
3✔
4453
                c.RemoteLogIndex, c.RemoteHtlcIndex, c.LocalBalance,
3✔
4454
                c.RemoteBalance, c.CommitFee, c.FeePerKw, c.CommitTx,
3✔
4455
                c.CommitSig,
3✔
4456
        ); err != nil {
3✔
4457
                return err
×
4458
        }
×
4459

4460
        return SerializeHtlcs(w, c.Htlcs...)
3✔
4461
}
4462

4463
func putChanCommitment(chanBucket kvdb.RwBucket, c *ChannelCommitment,
4464
        local bool) error {
3✔
4465

3✔
4466
        var commitKey []byte
3✔
4467
        if local {
6✔
4468
                commitKey = append(chanCommitmentKey, byte(0x00))
3✔
4469
        } else {
6✔
4470
                commitKey = append(chanCommitmentKey, byte(0x01))
3✔
4471
        }
3✔
4472

4473
        var b bytes.Buffer
3✔
4474
        if err := serializeChanCommit(&b, c); err != nil {
3✔
4475
                return err
×
4476
        }
×
4477

4478
        // Before we write to disk, we'll also write our aux data as well.
4479
        auxData := c.extractTlvData()
3✔
4480
        if err := auxData.encode(&b); err != nil {
3✔
4481
                return fmt.Errorf("unable to write aux data: %w", err)
×
4482
        }
×
4483

4484
        return chanBucket.Put(commitKey, b.Bytes())
3✔
4485
}
4486

4487
func putChanCommitments(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
3✔
4488
        // If this is a restored channel, then we don't have any commitments to
3✔
4489
        // write.
3✔
4490
        if channel.hasChanStatus(ChanStatusRestored) {
6✔
4491
                return nil
3✔
4492
        }
3✔
4493

4494
        err := putChanCommitment(
3✔
4495
                chanBucket, &channel.LocalCommitment, true,
3✔
4496
        )
3✔
4497
        if err != nil {
3✔
4498
                return err
×
4499
        }
×
4500

4501
        return putChanCommitment(
3✔
4502
                chanBucket, &channel.RemoteCommitment, false,
3✔
4503
        )
3✔
4504
}
4505

4506
func putChanRevocationState(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
3✔
4507
        var b bytes.Buffer
3✔
4508
        err := WriteElements(
3✔
4509
                &b, channel.RemoteCurrentRevocation, channel.RevocationProducer,
3✔
4510
                channel.RevocationStore,
3✔
4511
        )
3✔
4512
        if err != nil {
3✔
4513
                return err
×
4514
        }
×
4515

4516
        // If the next revocation is present, which is only the case after the
4517
        // ChannelReady message has been sent, then we'll write it to disk.
4518
        if channel.RemoteNextRevocation != nil {
6✔
4519
                err = WriteElements(&b, channel.RemoteNextRevocation)
3✔
4520
                if err != nil {
3✔
4521
                        return err
×
4522
                }
×
4523
        }
4524

4525
        return chanBucket.Put(revocationStateKey, b.Bytes())
3✔
4526
}
4527

4528
func readChanConfig(b io.Reader, c *ChannelConfig) error {
3✔
4529
        return ReadElements(b,
3✔
4530
                &c.DustLimit, &c.MaxPendingAmount, &c.ChanReserve,
3✔
4531
                &c.MinHTLC, &c.MaxAcceptedHtlcs, &c.CsvDelay,
3✔
4532
                &c.MultiSigKey, &c.RevocationBasePoint,
3✔
4533
                &c.PaymentBasePoint, &c.DelayBasePoint,
3✔
4534
                &c.HtlcBasePoint,
3✔
4535
        )
3✔
4536
}
3✔
4537

4538
func fetchChanInfo(chanBucket kvdb.RBucket, channel *OpenChannel) error {
3✔
4539
        infoBytes := chanBucket.Get(chanInfoKey)
3✔
4540
        if infoBytes == nil {
3✔
4541
                return ErrNoChanInfoFound
×
4542
        }
×
4543
        r := bytes.NewReader(infoBytes)
3✔
4544

3✔
4545
        if err := ReadElements(r,
3✔
4546
                &channel.ChanType, &channel.ChainHash, &channel.FundingOutpoint,
3✔
4547
                &channel.ShortChannelID, &channel.IsPending, &channel.IsInitiator,
3✔
4548
                &channel.chanStatus, &channel.FundingBroadcastHeight,
3✔
4549
                &channel.NumConfsRequired, &channel.ChannelFlags,
3✔
4550
                &channel.IdentityPub, &channel.Capacity, &channel.TotalMSatSent,
3✔
4551
                &channel.TotalMSatReceived,
3✔
4552
        ); err != nil {
3✔
4553
                return err
×
4554
        }
×
4555

4556
        // For single funder channels that we initiated and have the funding
4557
        // transaction to, read the funding txn.
4558
        if fundingTxPresent(channel) {
6✔
4559
                if err := ReadElement(r, &channel.FundingTxn); err != nil {
3✔
4560
                        return err
×
4561
                }
×
4562
        }
4563

4564
        if err := readChanConfig(r, &channel.LocalChanCfg); err != nil {
3✔
4565
                return err
×
4566
        }
×
4567
        if err := readChanConfig(r, &channel.RemoteChanCfg); err != nil {
3✔
4568
                return err
×
4569
        }
×
4570

4571
        // Retrieve the boolean stored under lastWasRevokeKey.
4572
        lastWasRevokeBytes := chanBucket.Get(lastWasRevokeKey)
3✔
4573
        if lastWasRevokeBytes == nil {
6✔
4574
                // If nothing has been stored under this key, we store false in the
3✔
4575
                // OpenChannel struct.
3✔
4576
                channel.LastWasRevoke = false
3✔
4577
        } else {
6✔
4578
                // Otherwise, read the value into the LastWasRevoke field.
3✔
4579
                revokeReader := bytes.NewReader(lastWasRevokeBytes)
3✔
4580
                err := ReadElements(revokeReader, &channel.LastWasRevoke)
3✔
4581
                if err != nil {
3✔
4582
                        return err
×
4583
                }
×
4584
        }
4585

4586
        var auxData openChannelTlvData
3✔
4587
        if err := auxData.decode(r); err != nil {
3✔
4588
                return fmt.Errorf("unable to decode aux data: %w", err)
×
4589
        }
×
4590

4591
        // Assign all the relevant fields from the aux data into the actual
4592
        // open channel.
4593
        channel.amendTlvData(auxData)
3✔
4594

3✔
4595
        channel.Packager = NewChannelPackager(channel.ShortChannelID)
3✔
4596

3✔
4597
        // Finally, read the optional shutdown scripts.
3✔
4598
        if err := getOptionalUpfrontShutdownScript(
3✔
4599
                chanBucket, localUpfrontShutdownKey, &channel.LocalShutdownScript,
3✔
4600
        ); err != nil {
3✔
4601
                return err
×
4602
        }
×
4603

4604
        return getOptionalUpfrontShutdownScript(
3✔
4605
                chanBucket, remoteUpfrontShutdownKey, &channel.RemoteShutdownScript,
3✔
4606
        )
3✔
4607
}
4608

4609
func deserializeChanCommit(r io.Reader) (ChannelCommitment, error) {
3✔
4610
        var c ChannelCommitment
3✔
4611

3✔
4612
        err := ReadElements(r,
3✔
4613
                &c.CommitHeight, &c.LocalLogIndex, &c.LocalHtlcIndex, &c.RemoteLogIndex,
3✔
4614
                &c.RemoteHtlcIndex, &c.LocalBalance, &c.RemoteBalance,
3✔
4615
                &c.CommitFee, &c.FeePerKw, &c.CommitTx, &c.CommitSig,
3✔
4616
        )
3✔
4617
        if err != nil {
3✔
4618
                return c, err
×
4619
        }
×
4620

4621
        c.Htlcs, err = DeserializeHtlcs(r)
3✔
4622
        if err != nil {
3✔
4623
                return c, err
×
4624
        }
×
4625

4626
        return c, nil
3✔
4627
}
4628

4629
func fetchChanCommitment(chanBucket kvdb.RBucket,
4630
        local bool) (ChannelCommitment, error) {
3✔
4631

3✔
4632
        var commitKey []byte
3✔
4633
        if local {
6✔
4634
                commitKey = append(chanCommitmentKey, byte(0x00))
3✔
4635
        } else {
6✔
4636
                commitKey = append(chanCommitmentKey, byte(0x01))
3✔
4637
        }
3✔
4638

4639
        commitBytes := chanBucket.Get(commitKey)
3✔
4640
        if commitBytes == nil {
3✔
4641
                return ChannelCommitment{}, ErrNoCommitmentsFound
×
4642
        }
×
4643

4644
        r := bytes.NewReader(commitBytes)
3✔
4645
        chanCommit, err := deserializeChanCommit(r)
3✔
4646
        if err != nil {
3✔
4647
                return ChannelCommitment{}, fmt.Errorf("unable to decode "+
×
4648
                        "chan commit: %w", err)
×
4649
        }
×
4650

4651
        // We'll also check to see if we have any aux data stored as the end of
4652
        // the stream.
4653
        var auxData commitTlvData
3✔
4654
        if err := auxData.decode(r); err != nil {
3✔
4655
                return ChannelCommitment{}, fmt.Errorf("unable to decode "+
×
4656
                        "chan aux data: %w", err)
×
4657
        }
×
4658

4659
        chanCommit.amendTlvData(auxData)
3✔
4660

3✔
4661
        return chanCommit, nil
3✔
4662
}
4663

4664
func fetchChanCommitments(chanBucket kvdb.RBucket, channel *OpenChannel) error {
3✔
4665
        var err error
3✔
4666

3✔
4667
        // If this is a restored channel, then we don't have any commitments to
3✔
4668
        // read.
3✔
4669
        if channel.hasChanStatus(ChanStatusRestored) {
6✔
4670
                return nil
3✔
4671
        }
3✔
4672

4673
        channel.LocalCommitment, err = fetchChanCommitment(chanBucket, true)
3✔
4674
        if err != nil {
3✔
4675
                return err
×
4676
        }
×
4677
        channel.RemoteCommitment, err = fetchChanCommitment(chanBucket, false)
3✔
4678
        if err != nil {
3✔
4679
                return err
×
4680
        }
×
4681

4682
        return nil
3✔
4683
}
4684

4685
func fetchChanRevocationState(chanBucket kvdb.RBucket, channel *OpenChannel) error {
3✔
4686
        revBytes := chanBucket.Get(revocationStateKey)
3✔
4687
        if revBytes == nil {
3✔
4688
                return ErrNoRevocationsFound
×
4689
        }
×
4690
        r := bytes.NewReader(revBytes)
3✔
4691

3✔
4692
        err := ReadElements(
3✔
4693
                r, &channel.RemoteCurrentRevocation, &channel.RevocationProducer,
3✔
4694
                &channel.RevocationStore,
3✔
4695
        )
3✔
4696
        if err != nil {
3✔
4697
                return err
×
4698
        }
×
4699

4700
        // If there aren't any bytes left in the buffer, then we don't yet have
4701
        // the next remote revocation, so we can exit early here.
4702
        if r.Len() == 0 {
6✔
4703
                return nil
3✔
4704
        }
3✔
4705

4706
        // Otherwise we'll read the next revocation for the remote party which
4707
        // is always the last item within the buffer.
4708
        return ReadElements(r, &channel.RemoteNextRevocation)
3✔
4709
}
4710

4711
func deleteOpenChannel(chanBucket kvdb.RwBucket) error {
3✔
4712
        if err := chanBucket.Delete(chanInfoKey); err != nil {
3✔
4713
                return err
×
4714
        }
×
4715

4716
        err := chanBucket.Delete(append(chanCommitmentKey, byte(0x00)))
3✔
4717
        if err != nil {
3✔
4718
                return err
×
4719
        }
×
4720
        err = chanBucket.Delete(append(chanCommitmentKey, byte(0x01)))
3✔
4721
        if err != nil {
3✔
4722
                return err
×
4723
        }
×
4724

4725
        if err := chanBucket.Delete(revocationStateKey); err != nil {
3✔
4726
                return err
×
4727
        }
×
4728

4729
        if diff := chanBucket.Get(commitDiffKey); diff != nil {
6✔
4730
                return chanBucket.Delete(commitDiffKey)
3✔
4731
        }
3✔
4732

4733
        return nil
3✔
4734
}
4735

4736
// makeLogKey converts a uint64 into an 8 byte array.
4737
func makeLogKey(updateNum uint64) [8]byte {
3✔
4738
        var key [8]byte
3✔
4739
        byteOrder.PutUint64(key[:], updateNum)
3✔
4740
        return key
3✔
4741
}
3✔
4742

4743
func fetchThawHeight(chanBucket kvdb.RBucket) (uint32, error) {
3✔
4744
        var height uint32
3✔
4745

3✔
4746
        heightBytes := chanBucket.Get(frozenChanKey)
3✔
4747
        heightReader := bytes.NewReader(heightBytes)
3✔
4748

3✔
4749
        if err := ReadElements(heightReader, &height); err != nil {
3✔
4750
                return 0, err
×
4751
        }
×
4752

4753
        return height, nil
3✔
4754
}
4755

4756
func storeThawHeight(chanBucket kvdb.RwBucket, height uint32) error {
3✔
4757
        var heightBuf bytes.Buffer
3✔
4758
        if err := WriteElements(&heightBuf, height); err != nil {
3✔
4759
                return err
×
4760
        }
×
4761

4762
        return chanBucket.Put(frozenChanKey, heightBuf.Bytes())
3✔
4763
}
4764

4765
func deleteThawHeight(chanBucket kvdb.RwBucket) error {
3✔
4766
        return chanBucket.Delete(frozenChanKey)
3✔
4767
}
3✔
4768

4769
// keyLocRecord is a wrapper struct around keychain.KeyLocator to implement the
4770
// tlv.RecordProducer interface.
4771
type keyLocRecord struct {
4772
        keychain.KeyLocator
4773
}
4774

4775
// Record creates a Record out of a KeyLocator using the passed Type and the
4776
// EKeyLocator and DKeyLocator functions. The size will always be 8 as
4777
// KeyFamily is uint32 and the Index is uint32.
4778
//
4779
// NOTE: This is part of the tlv.RecordProducer interface.
4780
func (k *keyLocRecord) Record() tlv.Record {
3✔
4781
        // Note that we set the type here as zero, as when used with a
3✔
4782
        // tlv.RecordT, the type param will be used as the type.
3✔
4783
        return tlv.MakeStaticRecord(
3✔
4784
                0, &k.KeyLocator, 8, EKeyLocator, DKeyLocator,
3✔
4785
        )
3✔
4786
}
3✔
4787

4788
// EKeyLocator is an encoder for keychain.KeyLocator.
4789
func EKeyLocator(w io.Writer, val interface{}, buf *[8]byte) error {
3✔
4790
        if v, ok := val.(*keychain.KeyLocator); ok {
6✔
4791
                err := tlv.EUint32T(w, uint32(v.Family), buf)
3✔
4792
                if err != nil {
3✔
4793
                        return err
×
4794
                }
×
4795

4796
                return tlv.EUint32T(w, v.Index, buf)
3✔
4797
        }
4798
        return tlv.NewTypeForEncodingErr(val, "keychain.KeyLocator")
×
4799
}
4800

4801
// DKeyLocator is a decoder for keychain.KeyLocator.
4802
func DKeyLocator(r io.Reader, val interface{}, buf *[8]byte, l uint64) error {
3✔
4803
        if v, ok := val.(*keychain.KeyLocator); ok {
6✔
4804
                var family uint32
3✔
4805
                err := tlv.DUint32(r, &family, buf, 4)
3✔
4806
                if err != nil {
3✔
4807
                        return err
×
4808
                }
×
4809
                v.Family = keychain.KeyFamily(family)
3✔
4810

3✔
4811
                return tlv.DUint32(r, &v.Index, buf, 4)
3✔
4812
        }
4813
        return tlv.NewTypeForDecodingErr(val, "keychain.KeyLocator", l, 8)
×
4814
}
4815

4816
// ShutdownInfo contains various info about the shutdown initiation of a
4817
// channel.
4818
type ShutdownInfo struct {
4819
        // DeliveryScript is the address that we have included in any previous
4820
        // Shutdown message for a particular channel and so should include in
4821
        // any future re-sends of the Shutdown message.
4822
        DeliveryScript tlv.RecordT[tlv.TlvType0, lnwire.DeliveryAddress]
4823

4824
        // LocalInitiator is true if we sent a Shutdown message before ever
4825
        // receiving a Shutdown message from the remote peer.
4826
        LocalInitiator tlv.RecordT[tlv.TlvType1, bool]
4827
}
4828

4829
// NewShutdownInfo constructs a new ShutdownInfo object.
4830
func NewShutdownInfo(deliveryScript lnwire.DeliveryAddress,
4831
        locallyInitiated bool) *ShutdownInfo {
3✔
4832

3✔
4833
        return &ShutdownInfo{
3✔
4834
                DeliveryScript: tlv.NewRecordT[tlv.TlvType0](deliveryScript),
3✔
4835
                LocalInitiator: tlv.NewPrimitiveRecord[tlv.TlvType1](
3✔
4836
                        locallyInitiated,
3✔
4837
                ),
3✔
4838
        }
3✔
4839
}
3✔
4840

4841
// Closer identifies the ChannelParty that initiated the coop-closure process.
4842
func (s ShutdownInfo) Closer() lntypes.ChannelParty {
3✔
4843
        if s.LocalInitiator.Val {
6✔
4844
                return lntypes.Local
3✔
4845
        }
3✔
4846

4847
        return lntypes.Remote
3✔
4848
}
4849

4850
// encode serialises the ShutdownInfo to the given io.Writer.
4851
func (s *ShutdownInfo) encode(w io.Writer) error {
3✔
4852
        records := []tlv.Record{
3✔
4853
                s.DeliveryScript.Record(),
3✔
4854
                s.LocalInitiator.Record(),
3✔
4855
        }
3✔
4856

3✔
4857
        stream, err := tlv.NewStream(records...)
3✔
4858
        if err != nil {
3✔
4859
                return err
×
4860
        }
×
4861

4862
        return stream.Encode(w)
3✔
4863
}
4864

4865
// decodeShutdownInfo constructs a ShutdownInfo struct by decoding the given
4866
// byte slice.
4867
func decodeShutdownInfo(b []byte) (*ShutdownInfo, error) {
3✔
4868
        tlvStream := lnwire.ExtraOpaqueData(b)
3✔
4869

3✔
4870
        var info ShutdownInfo
3✔
4871
        records := []tlv.RecordProducer{
3✔
4872
                &info.DeliveryScript,
3✔
4873
                &info.LocalInitiator,
3✔
4874
        }
3✔
4875

3✔
4876
        _, err := tlvStream.ExtractRecords(records...)
3✔
4877

3✔
4878
        return &info, err
3✔
4879
}
3✔
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