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

lightningnetwork / lnd / 19616403112

23 Nov 2025 07:49PM UTC coverage: 65.173% (-0.06%) from 65.229%
19616403112

Pull #10390

github

web-flow
Merge bf85a3dc9 into 8c8662c86
Pull Request #10390: Defer Channel Cleanup after a channel is closed to avoid kv-sql stress

53 of 206 new or added lines in 4 files covered. (25.73%)

127 existing lines in 27 files now uncovered.

137610 of 211145 relevant lines covered (65.17%)

20759.97 hits per line

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

77.19
/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
        // pendingCleanupBucket stores information about channels that have been
82
        // closed but whose data (revocation logs, forwarding packages) has not
83
        // yet been deleted. This is used by SQL backends to defer heavy cleanup
84
        // operations to startup.
85
        pendingCleanupBucket = []byte("pending-cleanup-bucket")
86

87
        // chanInfoKey can be accessed within the bucket for a channel
88
        // (identified by its chanPoint). This key stores all the static
89
        // information for a channel which is decided at the end of  the
90
        // funding flow.
91
        chanInfoKey = []byte("chan-info-key")
92

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

98
        // remoteUpfrontShutdownKey can be accessed within the bucket for a channel
99
        // (identified by its chanPoint). This key stores an optional upfront
100
        // shutdown script for the remote peer.
101
        remoteUpfrontShutdownKey = []byte("remote-upfront-shutdown-key")
102

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

111
        // unsignedAckedUpdatesKey is an entry in the channel bucket that
112
        // contains the remote updates that we have acked, but not yet signed
113
        // for in one of our remote commits.
114
        unsignedAckedUpdatesKey = []byte("unsigned-acked-updates-key")
115

116
        // remoteUnsignedLocalUpdatesKey is an entry in the channel bucket that
117
        // contains the local updates that the remote party has acked, but
118
        // has not yet signed for in one of their local commits.
119
        remoteUnsignedLocalUpdatesKey = []byte("remote-unsigned-local-updates-key")
120

121
        // revocationStateKey stores their current revocation hash, our
122
        // preimage producer and their preimage store.
123
        revocationStateKey = []byte("revocation-state-key")
124

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

129
        // forceCloseTxKey points to a the unilateral closing tx that we
130
        // broadcasted when moving the channel to state CommitBroadcasted.
131
        forceCloseTxKey = []byte("closing-tx-key")
132

133
        // coopCloseTxKey points to a the cooperative closing tx that we
134
        // broadcasted when moving the channel to state CoopBroadcasted.
135
        coopCloseTxKey = []byte("coop-closing-tx-key")
136

137
        // shutdownInfoKey points to the serialised shutdown info that has been
138
        // persisted for a channel. The existence of this info means that we
139
        // have sent the Shutdown message before and so should re-initiate the
140
        // shutdown on re-establish.
141
        shutdownInfoKey = []byte("shutdown-info-key")
142

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

152
        // frozenChanKey is the key where we store the information for any
153
        // active "frozen" channels. This key is present only in the leaf
154
        // bucket for a given channel.
155
        frozenChanKey = []byte("frozen-chans")
156

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

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

183
var (
184
        // ErrNoCommitmentsFound is returned when a channel has not set
185
        // commitment states.
186
        ErrNoCommitmentsFound = fmt.Errorf("no commitments found")
187

188
        // ErrNoChanInfoFound is returned when a particular channel does not
189
        // have any channels state.
190
        ErrNoChanInfoFound = fmt.Errorf("no chan info found")
191

192
        // ErrNoRevocationsFound is returned when revocation state for a
193
        // particular channel cannot be found.
194
        ErrNoRevocationsFound = fmt.Errorf("no revocations found")
195

196
        // ErrNoPendingCommit is returned when there is not a pending
197
        // commitment for a remote party. A new commitment is written to disk
198
        // each time we write a new state in order to be properly fault
199
        // tolerant.
200
        ErrNoPendingCommit = fmt.Errorf("no pending commits found")
201

202
        // ErrNoCommitPoint is returned when no data loss commit point is found
203
        // in the database.
204
        ErrNoCommitPoint = fmt.Errorf("no commit point found")
205

206
        // ErrNoCloseTx is returned when no closing tx is found for a channel
207
        // in the state CommitBroadcasted.
208
        ErrNoCloseTx = fmt.Errorf("no closing tx found")
209

210
        // ErrNoShutdownInfo is returned when no shutdown info has been
211
        // persisted for a channel.
212
        ErrNoShutdownInfo = errors.New("no shutdown info")
213

214
        // ErrNoRestoredChannelMutation is returned when a caller attempts to
215
        // mutate a channel that's been recovered.
216
        ErrNoRestoredChannelMutation = fmt.Errorf("cannot mutate restored " +
217
                "channel state")
218

219
        // ErrChanBorked is returned when a caller attempts to mutate a borked
220
        // channel.
221
        ErrChanBorked = fmt.Errorf("cannot mutate borked channel")
222

223
        // ErrMissingIndexEntry is returned when a caller attempts to close a
224
        // channel and the outpoint is missing from the index.
225
        ErrMissingIndexEntry = fmt.Errorf("missing outpoint from index")
226

227
        // ErrOnionBlobLength is returned is an onion blob with incorrect
228
        // length is read from disk.
229
        ErrOnionBlobLength = errors.New("onion blob < 1366 bytes")
230
)
231

232
const (
233
        // A tlv type definition used to serialize an outpoint's indexStatus
234
        // for use in the outpoint index.
235
        indexStatusType tlv.Type = 0
236
)
237

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

249
        // initialLocalBalance is the initial local balance of the channel.
250
        initialLocalBalance tlv.RecordT[tlv.TlvType2, uint64]
251

252
        // initialRemoteBalance is the initial remote balance of the channel.
253
        initialRemoteBalance tlv.RecordT[tlv.TlvType3, uint64]
254

255
        // realScid is the real short channel ID of the channel corresponding to
256
        // the on-chain outpoint.
257
        realScid tlv.RecordT[tlv.TlvType4, lnwire.ShortChannelID]
258

259
        // memo is an optional text field that gives context to the user about
260
        // the channel.
261
        memo tlv.OptionalRecordT[tlv.TlvType5, []byte]
262

263
        // tapscriptRoot is the optional Tapscript root the channel funding
264
        // output commits to.
265
        tapscriptRoot tlv.OptionalRecordT[tlv.TlvType6, [32]byte]
266

267
        // customBlob is an optional TLV encoded blob of data representing
268
        // custom channel funding information.
269
        customBlob tlv.OptionalRecordT[tlv.TlvType7, tlv.Blob]
270

271
        // confirmationHeight records the block height at which the funding
272
        // transaction was first confirmed.
273
        confirmationHeight tlv.RecordT[tlv.TlvType8, uint32]
274
}
275

276
// encode serializes the openChannelTlvData to the given io.Writer.
277
func (c *openChannelTlvData) encode(w io.Writer) error {
3,386✔
278
        tlvRecords := []tlv.Record{
3,386✔
279
                c.revokeKeyLoc.Record(),
3,386✔
280
                c.initialLocalBalance.Record(),
3,386✔
281
                c.initialRemoteBalance.Record(),
3,386✔
282
                c.realScid.Record(),
3,386✔
283
                c.confirmationHeight.Record(),
3,386✔
284
        }
3,386✔
285
        c.memo.WhenSome(func(memo tlv.RecordT[tlv.TlvType5, []byte]) {
3,821✔
286
                tlvRecords = append(tlvRecords, memo.Record())
435✔
287
        })
435✔
288
        c.tapscriptRoot.WhenSome(
3,386✔
289
                func(root tlv.RecordT[tlv.TlvType6, [32]byte]) {
3,970✔
290
                        tlvRecords = append(tlvRecords, root.Record())
584✔
291
                },
584✔
292
        )
293
        c.customBlob.WhenSome(func(blob tlv.RecordT[tlv.TlvType7, tlv.Blob]) {
3,818✔
294
                tlvRecords = append(tlvRecords, blob.Record())
432✔
295
        })
432✔
296

297
        tlv.SortRecords(tlvRecords)
3,386✔
298

3,386✔
299
        // Create the tlv stream.
3,386✔
300
        tlvStream, err := tlv.NewStream(tlvRecords...)
3,386✔
301
        if err != nil {
3,386✔
302
                return err
×
303
        }
×
304

305
        return tlvStream.Encode(w)
3,386✔
306
}
307

308
// decode deserializes the openChannelTlvData from the given io.Reader.
309
func (c *openChannelTlvData) decode(r io.Reader) error {
7,516✔
310
        memo := c.memo.Zero()
7,516✔
311
        tapscriptRoot := c.tapscriptRoot.Zero()
7,516✔
312
        blob := c.customBlob.Zero()
7,516✔
313

7,516✔
314
        // Create the tlv stream.
7,516✔
315
        tlvStream, err := tlv.NewStream(
7,516✔
316
                c.revokeKeyLoc.Record(),
7,516✔
317
                c.initialLocalBalance.Record(),
7,516✔
318
                c.initialRemoteBalance.Record(),
7,516✔
319
                c.realScid.Record(),
7,516✔
320
                memo.Record(),
7,516✔
321
                tapscriptRoot.Record(),
7,516✔
322
                blob.Record(),
7,516✔
323
                c.confirmationHeight.Record(),
7,516✔
324
        )
7,516✔
325
        if err != nil {
7,516✔
326
                return err
×
327
        }
×
328

329
        tlvs, err := tlvStream.DecodeWithParsedTypes(r)
7,516✔
330
        if err != nil {
7,516✔
331
                return err
×
332
        }
×
333

334
        if _, ok := tlvs[memo.TlvType()]; ok {
7,860✔
335
                c.memo = tlv.SomeRecordT(memo)
344✔
336
        }
344✔
337
        if _, ok := tlvs[tapscriptRoot.TlvType()]; ok {
8,242✔
338
                c.tapscriptRoot = tlv.SomeRecordT(tapscriptRoot)
726✔
339
        }
726✔
340
        if _, ok := tlvs[c.customBlob.TlvType()]; ok {
7,857✔
341
                c.customBlob = tlv.SomeRecordT(blob)
341✔
342
        }
341✔
343

344
        return nil
7,516✔
345
}
346

347
// indexStatus is an enum-like type that describes what state the
348
// outpoint is in. Currently only two possible values.
349
type indexStatus uint8
350

351
const (
352
        // outpointOpen represents an outpoint that is open in the outpoint index.
353
        outpointOpen indexStatus = 0
354

355
        // outpointClosed represents an outpoint that is closed in the outpoint
356
        // index.
357
        outpointClosed indexStatus = 1
358
)
359

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

368
const (
369
        // NOTE: iota isn't used here for this enum needs to be stable
370
        // long-term as it will be persisted to the database.
371

372
        // SingleFunderBit represents a channel wherein one party solely funds
373
        // the entire capacity of the channel.
374
        SingleFunderBit ChannelType = 0
375

376
        // DualFunderBit represents a channel wherein both parties contribute
377
        // funds towards the total capacity of the channel. The channel may be
378
        // funded symmetrically or asymmetrically.
379
        DualFunderBit ChannelType = 1 << 0
380

381
        // SingleFunderTweaklessBit is similar to the basic SingleFunder channel
382
        // type, but it omits the tweak for one's key in the commitment
383
        // transaction of the remote party.
384
        SingleFunderTweaklessBit ChannelType = 1 << 1
385

386
        // NoFundingTxBit denotes if we have the funding transaction locally on
387
        // disk. This bit may be on if the funding transaction was crafted by a
388
        // wallet external to the primary daemon.
389
        NoFundingTxBit ChannelType = 1 << 2
390

391
        // AnchorOutputsBit indicates that the channel makes use of anchor
392
        // outputs to bump the commitment transaction's effective feerate. This
393
        // channel type also uses a delayed to_remote output script.
394
        AnchorOutputsBit ChannelType = 1 << 3
395

396
        // FrozenBit indicates that the channel is a frozen channel, meaning
397
        // that only the responder can decide to cooperatively close the
398
        // channel.
399
        FrozenBit ChannelType = 1 << 4
400

401
        // ZeroHtlcTxFeeBit indicates that the channel should use zero-fee
402
        // second-level HTLC transactions.
403
        ZeroHtlcTxFeeBit ChannelType = 1 << 5
404

405
        // LeaseExpirationBit indicates that the channel has been leased for a
406
        // period of time, constraining every output that pays to the channel
407
        // initiator with an additional CLTV of the lease maturity.
408
        LeaseExpirationBit ChannelType = 1 << 6
409

410
        // ZeroConfBit indicates that the channel is a zero-conf channel.
411
        ZeroConfBit ChannelType = 1 << 7
412

413
        // ScidAliasChanBit indicates that the channel has negotiated the
414
        // scid-alias channel type.
415
        ScidAliasChanBit ChannelType = 1 << 8
416

417
        // ScidAliasFeatureBit indicates that the scid-alias feature bit was
418
        // negotiated during the lifetime of this channel.
419
        ScidAliasFeatureBit ChannelType = 1 << 9
420

421
        // SimpleTaprootFeatureBit indicates that the simple-taproot-chans
422
        // feature bit was negotiated during the lifetime of the channel.
423
        SimpleTaprootFeatureBit ChannelType = 1 << 10
424

425
        // TapscriptRootBit indicates that this is a MuSig2 channel with a top
426
        // level tapscript commitment. This MUST be set along with the
427
        // SimpleTaprootFeatureBit.
428
        TapscriptRootBit ChannelType = 1 << 11
429
)
430

431
// IsSingleFunder returns true if the channel type if one of the known single
432
// funder variants.
433
func (c ChannelType) IsSingleFunder() bool {
10,986✔
434
        return c&DualFunderBit == 0
10,986✔
435
}
10,986✔
436

437
// IsDualFunder returns true if the ChannelType has the DualFunderBit set.
438
func (c ChannelType) IsDualFunder() bool {
×
439
        return c&DualFunderBit == DualFunderBit
×
440
}
×
441

442
// IsTweakless returns true if the target channel uses a commitment that
443
// doesn't tweak the key for the remote party.
444
func (c ChannelType) IsTweakless() bool {
11,016✔
445
        return c&SingleFunderTweaklessBit == SingleFunderTweaklessBit
11,016✔
446
}
11,016✔
447

448
// HasFundingTx returns true if this channel type is one that has a funding
449
// transaction stored locally.
450
func (c ChannelType) HasFundingTx() bool {
10,997✔
451
        return c&NoFundingTxBit == 0
10,997✔
452
}
10,997✔
453

454
// HasAnchors returns true if this channel type has anchor outputs on its
455
// commitment.
456
func (c ChannelType) HasAnchors() bool {
254,574✔
457
        return c&AnchorOutputsBit == AnchorOutputsBit
254,574✔
458
}
254,574✔
459

460
// ZeroHtlcTxFee returns true if this channel type uses second-level HTLC
461
// transactions signed with zero-fee.
462
func (c ChannelType) ZeroHtlcTxFee() bool {
204,324✔
463
        return c&ZeroHtlcTxFeeBit == ZeroHtlcTxFeeBit
204,324✔
464
}
204,324✔
465

466
// IsFrozen returns true if the channel is considered to be "frozen". A frozen
467
// channel means that only the responder can initiate a cooperative channel
468
// closure.
469
func (c ChannelType) IsFrozen() bool {
8,945✔
470
        return c&FrozenBit == FrozenBit
8,945✔
471
}
8,945✔
472

473
// HasLeaseExpiration returns true if the channel originated from a lease.
474
func (c ChannelType) HasLeaseExpiration() bool {
33,494✔
475
        return c&LeaseExpirationBit == LeaseExpirationBit
33,494✔
476
}
33,494✔
477

478
// HasZeroConf returns true if the channel is a zero-conf channel.
479
func (c ChannelType) HasZeroConf() bool {
656✔
480
        return c&ZeroConfBit == ZeroConfBit
656✔
481
}
656✔
482

483
// HasScidAliasChan returns true if the scid-alias channel type was negotiated.
484
func (c ChannelType) HasScidAliasChan() bool {
×
485
        return c&ScidAliasChanBit == ScidAliasChanBit
×
486
}
×
487

488
// HasScidAliasFeature returns true if the scid-alias feature bit was
489
// negotiated during the lifetime of this channel.
490
func (c ChannelType) HasScidAliasFeature() bool {
504✔
491
        return c&ScidAliasFeatureBit == ScidAliasFeatureBit
504✔
492
}
504✔
493

494
// IsTaproot returns true if the channel is using taproot features.
495
func (c ChannelType) IsTaproot() bool {
286,833✔
496
        return c&SimpleTaprootFeatureBit == SimpleTaprootFeatureBit
286,833✔
497
}
286,833✔
498

499
// HasTapscriptRoot returns true if the channel is using a top level tapscript
500
// root commitment.
501
func (c ChannelType) HasTapscriptRoot() bool {
358✔
502
        return c&TapscriptRootBit == TapscriptRootBit
358✔
503
}
358✔
504

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

517
        // MaxPendingAmount is the maximum pending HTLC value that the
518
        // owner of these constraints can offer the remote node at a
519
        // particular time.
520
        MaxPendingAmount lnwire.MilliSatoshi
521

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

529
        // MaxAcceptedHtlcs is the maximum number of HTLCs that the owner of
530
        // this set of constraints can offer the remote node. This allows each
531
        // node to limit their over all exposure to HTLCs that may need to be
532
        // acted upon in the case of a unilateral channel closure or a contract
533
        // breach.
534
        MaxAcceptedHtlcs uint16
535
}
536

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

549
        // CsvDelay is the relative time lock delay expressed in blocks. Any
550
        // settled outputs that pay to the owner of this channel configuration
551
        // MUST ensure that the delay branch uses this value as the relative
552
        // time lock. Similarly, any HTLC's offered by this node should use
553
        // this value as well.
554
        CsvDelay uint16
555
}
556

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

570
        // CommitmentParams is an embedding of the parameters
571
        // required to render an abstract channel state into a concrete
572
        // commitment transaction.
573
        CommitmentParams
574

575
        // MultiSigKey is the key to be used within the 2-of-2 output script
576
        // for the owner of this channel config.
577
        MultiSigKey keychain.KeyDescriptor
578

579
        // RevocationBasePoint is the base public key to be used when deriving
580
        // revocation keys for the remote node's commitment transaction. This
581
        // will be combined along with a per commitment secret to derive a
582
        // unique revocation key for each state.
583
        RevocationBasePoint keychain.KeyDescriptor
584

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

592
        // DelayBasePoint is the base public key to be used when deriving the
593
        // key used within the delayed pay-to-self output on the commitment
594
        // transaction for a node. This will be combined with a tweak derived
595
        // from the per-commitment point to ensure unique keys for each
596
        // commitment transaction.
597
        DelayBasePoint keychain.KeyDescriptor
598

599
        // HtlcBasePoint is the base public key to be used when deriving the
600
        // local HTLC key. The derived key (combined with the tweak derived
601
        // from the per-commitment point) is used within the "to self" clause
602
        // within any HTLC output scripts.
603
        HtlcBasePoint keychain.KeyDescriptor
604
}
605

606
// commitTlvData stores all the optional data that may be stored as a TLV stream
607
// at the _end_ of the normal serialized commit on disk.
608
type commitTlvData struct {
609
        // customBlob is a custom blob that may store extra data for custom
610
        // channels.
611
        customBlob tlv.OptionalRecordT[tlv.TlvType1, tlv.Blob]
612
}
613

614
// encode encodes the aux data into the passed io.Writer.
615
func (c *commitTlvData) encode(w io.Writer) error {
8,867✔
616
        var tlvRecords []tlv.Record
8,867✔
617
        c.customBlob.WhenSome(func(blob tlv.RecordT[tlv.TlvType1, tlv.Blob]) {
9,734✔
618
                tlvRecords = append(tlvRecords, blob.Record())
867✔
619
        })
867✔
620

621
        // Create the tlv stream.
622
        tlvStream, err := tlv.NewStream(tlvRecords...)
8,867✔
623
        if err != nil {
8,867✔
624
                return err
×
625
        }
×
626

627
        return tlvStream.Encode(w)
8,867✔
628
}
629

630
// decode attempts to decode the aux data from the passed io.Reader.
631
func (c *commitTlvData) decode(r io.Reader) error {
17,194✔
632
        blob := c.customBlob.Zero()
17,194✔
633

17,194✔
634
        tlvStream, err := tlv.NewStream(
17,194✔
635
                blob.Record(),
17,194✔
636
        )
17,194✔
637
        if err != nil {
17,194✔
638
                return err
×
639
        }
×
640

641
        tlvs, err := tlvStream.DecodeWithParsedTypes(r)
17,194✔
642
        if err != nil {
17,194✔
643
                return err
×
644
        }
×
645

646
        if _, ok := tlvs[c.customBlob.TlvType()]; ok {
17,880✔
647
                c.customBlob = tlv.SomeRecordT(blob)
686✔
648
        }
686✔
649

650
        return nil
17,194✔
651
}
652

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

666
        // LocalLogIndex is the cumulative log index index of the local node at
667
        // this point in the commitment chain. This value will be incremented
668
        // for each _update_ added to the local update log.
669
        LocalLogIndex uint64
670

671
        // LocalHtlcIndex is the current local running HTLC index. This value
672
        // will be incremented for each outgoing HTLC the local node offers.
673
        LocalHtlcIndex uint64
674

675
        // RemoteLogIndex is the cumulative log index index of the remote node
676
        // at this point in the commitment chain. This value will be
677
        // incremented for each _update_ added to the remote update log.
678
        RemoteLogIndex uint64
679

680
        // RemoteHtlcIndex is the current remote running HTLC index. This value
681
        // will be incremented for each outgoing HTLC the remote node offers.
682
        RemoteHtlcIndex uint64
683

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

691
        // RemoteBalance is the current available settled balance within the
692
        // channel directly spendable by the remote node.
693
        //
694
        // NOTE: This is the balance *after* subtracting any commitment fee,
695
        // AND anchor output values.
696
        RemoteBalance lnwire.MilliSatoshi
697

698
        // CommitFee is the amount calculated to be paid in fees for the
699
        // current set of commitment transactions. The fee amount is persisted
700
        // with the channel in order to allow the fee amount to be removed and
701
        // recalculated with each channel state update, including updates that
702
        // happen after a system restart.
703
        CommitFee btcutil.Amount
704

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

715
        // CommitTx is the latest version of the commitment state, broadcast
716
        // able by us.
717
        CommitTx *wire.MsgTx
718

719
        // CustomBlob is an optional blob that can be used to store information
720
        // specific to a custom channel type. This may track some custom
721
        // specific state for this given commitment.
722
        CustomBlob fn.Option[tlv.Blob]
723

724
        // CommitSig is one half of the signature required to fully complete
725
        // the script for the commitment transaction above. This is the
726
        // signature signed by the remote party for our version of the
727
        // commitment transactions.
728
        CommitSig []byte
729

730
        // Htlcs is the set of HTLC's that are pending at this particular
731
        // commitment height.
732
        Htlcs []HTLC
733
}
734

735
// amendTlvData updates the channel with the given auxiliary TLV data.
736
func (c *ChannelCommitment) amendTlvData(auxData commitTlvData) {
17,194✔
737
        auxData.customBlob.WhenSomeV(func(blob tlv.Blob) {
17,880✔
738
                c.CustomBlob = fn.Some(blob)
686✔
739
        })
686✔
740
}
741

742
// extractTlvData creates a new commitTlvData from the given commitment.
743
func (c *ChannelCommitment) extractTlvData() commitTlvData {
8,867✔
744
        var auxData commitTlvData
8,867✔
745

8,867✔
746
        c.CustomBlob.WhenSome(func(blob tlv.Blob) {
9,734✔
747
                auxData.customBlob = tlv.SomeRecordT(
867✔
748
                        tlv.NewPrimitiveRecord[tlv.TlvType1](blob),
867✔
749
                )
867✔
750
        })
867✔
751

752
        return auxData
8,867✔
753
}
754

755
// ChannelStatus is a bit vector used to indicate whether an OpenChannel is in
756
// the default usable state, or a state where it shouldn't be used.
757
type ChannelStatus uint64
758

759
var (
760
        // ChanStatusDefault is the normal state of an open channel.
761
        ChanStatusDefault ChannelStatus
762

763
        // ChanStatusBorked indicates that the channel has entered an
764
        // irreconcilable state, triggered by a state desynchronization or
765
        // channel breach.  Channels in this state should never be added to the
766
        // htlc switch.
767
        ChanStatusBorked ChannelStatus = 1
768

769
        // ChanStatusCommitBroadcasted indicates that a commitment for this
770
        // channel has been broadcasted.
771
        ChanStatusCommitBroadcasted ChannelStatus = 1 << 1
772

773
        // ChanStatusLocalDataLoss indicates that we have lost channel state
774
        // for this channel, and broadcasting our latest commitment might be
775
        // considered a breach.
776
        //
777
        // TODO(halseh): actually enforce that we are not force closing such a
778
        // channel.
779
        ChanStatusLocalDataLoss ChannelStatus = 1 << 2
780

781
        // ChanStatusRestored is a status flag that signals that the channel
782
        // has been restored, and doesn't have all the fields a typical channel
783
        // will have.
784
        ChanStatusRestored ChannelStatus = 1 << 3
785

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

795
        // ChanStatusLocalCloseInitiator indicates that we initiated closing
796
        // the channel.
797
        ChanStatusLocalCloseInitiator ChannelStatus = 1 << 5
798

799
        // ChanStatusRemoteCloseInitiator indicates that the remote node
800
        // initiated closing the channel.
801
        ChanStatusRemoteCloseInitiator ChannelStatus = 1 << 6
802
)
803

804
// chanStatusStrings maps a ChannelStatus to a human friendly string that
805
// describes that status.
806
var chanStatusStrings = map[ChannelStatus]string{
807
        ChanStatusDefault:              "ChanStatusDefault",
808
        ChanStatusBorked:               "ChanStatusBorked",
809
        ChanStatusCommitBroadcasted:    "ChanStatusCommitBroadcasted",
810
        ChanStatusLocalDataLoss:        "ChanStatusLocalDataLoss",
811
        ChanStatusRestored:             "ChanStatusRestored",
812
        ChanStatusCoopBroadcasted:      "ChanStatusCoopBroadcasted",
813
        ChanStatusLocalCloseInitiator:  "ChanStatusLocalCloseInitiator",
814
        ChanStatusRemoteCloseInitiator: "ChanStatusRemoteCloseInitiator",
815
}
816

817
// orderedChanStatusFlags is an in-order list of all that channel status flags.
818
var orderedChanStatusFlags = []ChannelStatus{
819
        ChanStatusBorked,
820
        ChanStatusCommitBroadcasted,
821
        ChanStatusLocalDataLoss,
822
        ChanStatusRestored,
823
        ChanStatusCoopBroadcasted,
824
        ChanStatusLocalCloseInitiator,
825
        ChanStatusRemoteCloseInitiator,
826
}
827

828
// String returns a human-readable representation of the ChannelStatus.
829
func (c ChannelStatus) String() string {
4✔
830
        // If no flags are set, then this is the default case.
4✔
831
        if c == ChanStatusDefault {
7✔
832
                return chanStatusStrings[ChanStatusDefault]
3✔
833
        }
3✔
834

835
        // Add individual bit flags.
836
        statusStr := ""
4✔
837
        for _, flag := range orderedChanStatusFlags {
14✔
838
                if c&flag == flag {
14✔
839
                        statusStr += chanStatusStrings[flag] + "|"
4✔
840
                        c -= flag
4✔
841
                }
4✔
842
        }
843

844
        // Remove anything to the right of the final bar, including it as well.
845
        statusStr = strings.TrimRight(statusStr, "|")
4✔
846

4✔
847
        // Add any remaining flags which aren't accounted for as hex.
4✔
848
        if c != 0 {
4✔
849
                statusStr += "|0x" + strconv.FormatUint(uint64(c), 16)
×
850
        }
×
851

852
        // If this was purely an unknown flag, then remove the extra bar at the
853
        // start of the string.
854
        statusStr = strings.TrimLeft(statusStr, "|")
4✔
855

4✔
856
        return statusStr
4✔
857
}
858

859
// FinalHtlcByte defines a byte type that encodes information about the final
860
// htlc resolution.
861
type FinalHtlcByte byte
862

863
const (
864
        // FinalHtlcSettledBit is the bit that encodes whether the htlc was
865
        // settled or failed.
866
        FinalHtlcSettledBit FinalHtlcByte = 1 << 0
867

868
        // FinalHtlcOffchainBit is the bit that encodes whether the htlc was
869
        // resolved offchain or onchain.
870
        FinalHtlcOffchainBit FinalHtlcByte = 1 << 1
871
)
872

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

884
        // ChainHash is a hash which represents the blockchain that this
885
        // channel will be opened within. This value is typically the genesis
886
        // hash. In the case that the original chain went through a contentious
887
        // hard-fork, then this value will be tweaked using the unique fork
888
        // point on each branch.
889
        ChainHash chainhash.Hash
890

891
        // FundingOutpoint is the outpoint of the final funding transaction.
892
        // This value uniquely and globally identifies the channel within the
893
        // target blockchain as specified by the chain hash parameter.
894
        FundingOutpoint wire.OutPoint
895

896
        // ShortChannelID encodes the exact location in the chain in which the
897
        // channel was initially confirmed. This includes: the block height,
898
        // transaction index, and the output within the target transaction.
899
        //
900
        // If IsZeroConf(), then this will the "base" (very first) ALIAS scid
901
        // and the confirmed SCID will be stored in ConfirmedScid.
902
        ShortChannelID lnwire.ShortChannelID
903

904
        // IsPending indicates whether a channel's funding transaction has been
905
        // confirmed.
906
        IsPending bool
907

908
        // IsInitiator is a bool which indicates if we were the original
909
        // initiator for the channel. This value may affect how higher levels
910
        // negotiate fees, or close the channel.
911
        IsInitiator bool
912

913
        // chanStatus is the current status of this channel. If it is not in
914
        // the state Default, it should not be used for forwarding payments.
915
        chanStatus ChannelStatus
916

917
        // FundingBroadcastHeight is the height in which the funding
918
        // transaction was broadcast. This value can be used by higher level
919
        // sub-systems to determine if a channel is stale and/or should have
920
        // been confirmed before a certain height.
921
        FundingBroadcastHeight uint32
922

923
        // ConfirmationHeight records the block height at which the funding
924
        // transaction was first confirmed.
925
        ConfirmationHeight uint32
926

927
        // NumConfsRequired is the number of confirmations a channel's funding
928
        // transaction must have received in order to be considered available
929
        // for normal transactional use.
930
        NumConfsRequired uint16
931

932
        // ChannelFlags holds the flags that were sent as part of the
933
        // open_channel message.
934
        ChannelFlags lnwire.FundingFlag
935

936
        // IdentityPub is the identity public key of the remote node this
937
        // channel has been established with.
938
        IdentityPub *btcec.PublicKey
939

940
        // Capacity is the total capacity of this channel.
941
        Capacity btcutil.Amount
942

943
        // TotalMSatSent is the total number of milli-satoshis we've sent
944
        // within this channel.
945
        TotalMSatSent lnwire.MilliSatoshi
946

947
        // TotalMSatReceived is the total number of milli-satoshis we've
948
        // received within this channel.
949
        TotalMSatReceived lnwire.MilliSatoshi
950

951
        // InitialLocalBalance is the balance we have during the channel
952
        // opening. When we are not the initiator, this value represents the
953
        // push amount.
954
        InitialLocalBalance lnwire.MilliSatoshi
955

956
        // InitialRemoteBalance is the balance they have during the channel
957
        // opening.
958
        InitialRemoteBalance lnwire.MilliSatoshi
959

960
        // LocalChanCfg is the channel configuration for the local node.
961
        LocalChanCfg ChannelConfig
962

963
        // RemoteChanCfg is the channel configuration for the remote node.
964
        RemoteChanCfg ChannelConfig
965

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

972
        // RemoteCommitment is the current remote commitment state for the
973
        // remote party. This is stored distinct from the state of the local
974
        // party as there are certain asymmetric parameters which affect the
975
        // structure of each commitment.
976
        RemoteCommitment ChannelCommitment
977

978
        // RemoteCurrentRevocation is the current revocation for their
979
        // commitment transaction. However, since this the derived public key,
980
        // we don't yet have the private key so we aren't yet able to verify
981
        // that it's actually in the hash chain.
982
        RemoteCurrentRevocation *btcec.PublicKey
983

984
        // RemoteNextRevocation is the revocation key to be used for the *next*
985
        // commitment transaction we create for the local node. Within the
986
        // specification, this value is referred to as the
987
        // per-commitment-point.
988
        RemoteNextRevocation *btcec.PublicKey
989

990
        // RevocationProducer is used to generate the revocation in such a way
991
        // that remote side might store it efficiently and have the ability to
992
        // restore the revocation by index if needed. Current implementation of
993
        // secret producer is shachain producer.
994
        RevocationProducer shachain.Producer
995

996
        // RevocationStore is used to efficiently store the revocations for
997
        // previous channels states sent to us by remote side. Current
998
        // implementation of secret store is shachain store.
999
        RevocationStore shachain.Store
1000

1001
        // Packager is used to create and update forwarding packages for this
1002
        // channel, which encodes all necessary information to recover from
1003
        // failures and reforward HTLCs that were not fully processed.
1004
        Packager FwdPackager
1005

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

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

1021
        // RemoteShutdownScript is set to a pre-set script if the channel was opened
1022
        // by the remote node with option_upfront_shutdown_script set. If the option
1023
        // was not set, the field is empty.
1024
        RemoteShutdownScript lnwire.DeliveryAddress
1025

1026
        // ThawHeight is the height when a frozen channel once again becomes a
1027
        // normal channel. If this is zero, then there're no restrictions on
1028
        // this channel. If the value is lower than 500,000, then it's
1029
        // interpreted as a relative height, or an absolute height otherwise.
1030
        ThawHeight uint32
1031

1032
        // LastWasRevoke is a boolean that determines if the last update we sent
1033
        // was a revocation (true) or a commitment signature (false).
1034
        LastWasRevoke bool
1035

1036
        // RevocationKeyLocator stores the KeyLocator information that we will
1037
        // need to derive the shachain root for this channel. This allows us to
1038
        // have private key isolation from lnd.
1039
        RevocationKeyLocator keychain.KeyLocator
1040

1041
        // confirmedScid is the confirmed ShortChannelID for a zero-conf
1042
        // channel. If the channel is unconfirmed, then this will be the
1043
        // default ShortChannelID. This is only set for zero-conf channels.
1044
        confirmedScid lnwire.ShortChannelID
1045

1046
        // Memo is any arbitrary information we wish to store locally about the
1047
        // channel that will be useful to our future selves.
1048
        Memo []byte
1049

1050
        // TapscriptRoot is an optional tapscript root used to derive the MuSig2
1051
        // funding output.
1052
        TapscriptRoot fn.Option[chainhash.Hash]
1053

1054
        // CustomBlob is an optional blob that can be used to store information
1055
        // specific to a custom channel type. This information is only created
1056
        // at channel funding time, and after wards is to be considered
1057
        // immutable.
1058
        CustomBlob fn.Option[tlv.Blob]
1059

1060
        // TODO(roasbeef): eww
1061
        Db *ChannelStateDB
1062

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

1065
        sync.RWMutex
1066
}
1067

1068
// String returns a string representation of the channel.
1069
func (c *OpenChannel) String() string {
3✔
1070
        indexStr := "height=%v, local_htlc_index=%v, local_log_index=%v, " +
3✔
1071
                "remote_htlc_index=%v, remote_log_index=%v"
3✔
1072

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

3✔
1079
        commit = c.RemoteCommitment
3✔
1080
        remote := fmt.Sprintf(indexStr, commit.CommitHeight,
3✔
1081
                commit.LocalHtlcIndex, commit.LocalLogIndex,
3✔
1082
                commit.RemoteHtlcIndex, commit.RemoteLogIndex,
3✔
1083
        )
3✔
1084

3✔
1085
        return fmt.Sprintf("SCID=%v, status=%v, initiator=%v, pending=%v, "+
3✔
1086
                "local commitment has %s, remote commitment has %s",
3✔
1087
                c.ShortChannelID, c.chanStatus, c.IsInitiator, c.IsPending,
3✔
1088
                local, remote,
3✔
1089
        )
3✔
1090
}
3✔
1091

1092
// Initiator returns the ChannelParty that originally opened this channel.
1093
func (c *OpenChannel) Initiator() lntypes.ChannelParty {
15,940✔
1094
        c.RLock()
15,940✔
1095
        defer c.RUnlock()
15,940✔
1096

15,940✔
1097
        if c.IsInitiator {
25,758✔
1098
                return lntypes.Local
9,818✔
1099
        }
9,818✔
1100

1101
        return lntypes.Remote
6,125✔
1102
}
1103

1104
// ShortChanID returns the current ShortChannelID of this channel.
1105
func (c *OpenChannel) ShortChanID() lnwire.ShortChannelID {
8,329✔
1106
        c.RLock()
8,329✔
1107
        defer c.RUnlock()
8,329✔
1108

8,329✔
1109
        return c.ShortChannelID
8,329✔
1110
}
8,329✔
1111

1112
// ZeroConfRealScid returns the zero-conf channel's confirmed scid. This should
1113
// only be called if IsZeroConf returns true.
1114
func (c *OpenChannel) ZeroConfRealScid() lnwire.ShortChannelID {
29✔
1115
        c.RLock()
29✔
1116
        defer c.RUnlock()
29✔
1117

29✔
1118
        return c.confirmedScid
29✔
1119
}
29✔
1120

1121
// ZeroConfConfirmed returns whether the zero-conf channel has confirmed. This
1122
// should only be called if IsZeroConf returns true.
1123
func (c *OpenChannel) ZeroConfConfirmed() bool {
40✔
1124
        c.RLock()
40✔
1125
        defer c.RUnlock()
40✔
1126

40✔
1127
        return c.confirmedScid != hop.Source
40✔
1128
}
40✔
1129

1130
// IsZeroConf returns whether the option_zeroconf channel type was negotiated.
1131
func (c *OpenChannel) IsZeroConf() bool {
656✔
1132
        c.RLock()
656✔
1133
        defer c.RUnlock()
656✔
1134

656✔
1135
        return c.ChanType.HasZeroConf()
656✔
1136
}
656✔
1137

1138
// IsOptionScidAlias returns whether the option_scid_alias channel type was
1139
// negotiated.
1140
func (c *OpenChannel) IsOptionScidAlias() bool {
×
1141
        c.RLock()
×
1142
        defer c.RUnlock()
×
1143

×
1144
        return c.ChanType.HasScidAliasChan()
×
1145
}
×
1146

1147
// NegotiatedAliasFeature returns whether the option-scid-alias feature bit was
1148
// negotiated.
1149
func (c *OpenChannel) NegotiatedAliasFeature() bool {
485✔
1150
        c.RLock()
485✔
1151
        defer c.RUnlock()
485✔
1152

485✔
1153
        return c.ChanType.HasScidAliasFeature()
485✔
1154
}
485✔
1155

1156
// ChanStatus returns the current ChannelStatus of this channel.
1157
func (c *OpenChannel) ChanStatus() ChannelStatus {
216✔
1158
        c.RLock()
216✔
1159
        defer c.RUnlock()
216✔
1160

216✔
1161
        return c.chanStatus
216✔
1162
}
216✔
1163

1164
// ApplyChanStatus allows the caller to modify the internal channel state in a
1165
// thead-safe manner.
1166
func (c *OpenChannel) ApplyChanStatus(status ChannelStatus) error {
3✔
1167
        c.Lock()
3✔
1168
        defer c.Unlock()
3✔
1169

3✔
1170
        return c.putChanStatus(status)
3✔
1171
}
3✔
1172

1173
// ClearChanStatus allows the caller to clear a particular channel status from
1174
// the primary channel status bit field. After this method returns, a call to
1175
// HasChanStatus(status) should return false.
1176
func (c *OpenChannel) ClearChanStatus(status ChannelStatus) error {
4✔
1177
        c.Lock()
4✔
1178
        defer c.Unlock()
4✔
1179

4✔
1180
        return c.clearChanStatus(status)
4✔
1181
}
4✔
1182

1183
// HasChanStatus returns true if the internal bitfield channel status of the
1184
// target channel has the specified status bit set.
1185
func (c *OpenChannel) HasChanStatus(status ChannelStatus) bool {
379✔
1186
        c.RLock()
379✔
1187
        defer c.RUnlock()
379✔
1188

379✔
1189
        return c.hasChanStatus(status)
379✔
1190
}
379✔
1191

1192
func (c *OpenChannel) hasChanStatus(status ChannelStatus) bool {
21,695✔
1193
        // Special case ChanStatusDefualt since it isn't actually flag, but a
21,695✔
1194
        // particular combination (or lack-there-of) of flags.
21,695✔
1195
        if status == ChanStatusDefault {
21,703✔
1196
                return c.chanStatus == ChanStatusDefault
8✔
1197
        }
8✔
1198

1199
        return c.chanStatus&status == status
21,690✔
1200
}
1201

1202
// BroadcastHeight returns the height at which the funding tx was broadcast.
1203
func (c *OpenChannel) BroadcastHeight() uint32 {
141✔
1204
        c.RLock()
141✔
1205
        defer c.RUnlock()
141✔
1206

141✔
1207
        return c.FundingBroadcastHeight
141✔
1208
}
141✔
1209

1210
// SetBroadcastHeight sets the FundingBroadcastHeight.
1211
func (c *OpenChannel) SetBroadcastHeight(height uint32) {
3✔
1212
        c.Lock()
3✔
1213
        defer c.Unlock()
3✔
1214

3✔
1215
        c.FundingBroadcastHeight = height
3✔
1216
}
3✔
1217

1218
// amendTlvData updates the channel with the given auxiliary TLV data.
1219
func (c *OpenChannel) amendTlvData(auxData openChannelTlvData) {
7,516✔
1220
        c.RevocationKeyLocator = auxData.revokeKeyLoc.Val.KeyLocator
7,516✔
1221
        c.InitialLocalBalance = lnwire.MilliSatoshi(
7,516✔
1222
                auxData.initialLocalBalance.Val,
7,516✔
1223
        )
7,516✔
1224
        c.InitialRemoteBalance = lnwire.MilliSatoshi(
7,516✔
1225
                auxData.initialRemoteBalance.Val,
7,516✔
1226
        )
7,516✔
1227
        c.confirmedScid = auxData.realScid.Val
7,516✔
1228
        c.ConfirmationHeight = auxData.confirmationHeight.Val
7,516✔
1229

7,516✔
1230
        auxData.memo.WhenSomeV(func(memo []byte) {
7,860✔
1231
                c.Memo = memo
344✔
1232
        })
344✔
1233
        auxData.tapscriptRoot.WhenSomeV(func(h [32]byte) {
8,242✔
1234
                c.TapscriptRoot = fn.Some[chainhash.Hash](h)
726✔
1235
        })
726✔
1236
        auxData.customBlob.WhenSomeV(func(blob tlv.Blob) {
7,857✔
1237
                c.CustomBlob = fn.Some(blob)
341✔
1238
        })
341✔
1239
}
1240

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

3,386✔
1261
        if len(c.Memo) != 0 {
3,821✔
1262
                auxData.memo = tlv.SomeRecordT(
435✔
1263
                        tlv.NewPrimitiveRecord[tlv.TlvType5](c.Memo),
435✔
1264
                )
435✔
1265
        }
435✔
1266
        c.TapscriptRoot.WhenSome(func(h chainhash.Hash) {
3,970✔
1267
                auxData.tapscriptRoot = tlv.SomeRecordT(
584✔
1268
                        tlv.NewPrimitiveRecord[tlv.TlvType6, [32]byte](h),
584✔
1269
                )
584✔
1270
        })
584✔
1271
        c.CustomBlob.WhenSome(func(blob tlv.Blob) {
3,818✔
1272
                auxData.customBlob = tlv.SomeRecordT(
432✔
1273
                        tlv.NewPrimitiveRecord[tlv.TlvType7](blob),
432✔
1274
                )
432✔
1275
        })
432✔
1276

1277
        return auxData
3,386✔
1278
}
1279

1280
// Refresh updates the in-memory channel state using the latest state observed
1281
// on disk.
1282
func (c *OpenChannel) Refresh() error {
9✔
1283
        c.Lock()
9✔
1284
        defer c.Unlock()
9✔
1285

9✔
1286
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
18✔
1287
                chanBucket, err := fetchChanBucket(
9✔
1288
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
9✔
1289
                )
9✔
1290
                if err != nil {
12✔
1291
                        return err
3✔
1292
                }
3✔
1293

1294
                // We'll re-populating the in-memory channel with the info
1295
                // fetched from disk.
1296
                if err := fetchChanInfo(chanBucket, c); err != nil {
9✔
1297
                        return fmt.Errorf("unable to fetch chan info: %w", err)
×
1298
                }
×
1299

1300
                // Also populate the channel's commitment states for both sides
1301
                // of the channel.
1302
                if err := fetchChanCommitments(chanBucket, c); err != nil {
9✔
1303
                        return fmt.Errorf("unable to fetch chan commitments: "+
×
1304
                                "%v", err)
×
1305
                }
×
1306

1307
                // Also retrieve the current revocation state.
1308
                if err := fetchChanRevocationState(chanBucket, c); err != nil {
9✔
1309
                        return fmt.Errorf("unable to fetch chan revocations: "+
×
1310
                                "%v", err)
×
1311
                }
×
1312

1313
                return nil
9✔
1314
        }, func() {})
9✔
1315
        if err != nil {
12✔
1316
                return err
3✔
1317
        }
3✔
1318

1319
        return nil
9✔
1320
}
1321

1322
// fetchChanBucket is a helper function that returns the bucket where a
1323
// channel's data resides in given: the public key for the node, the outpoint,
1324
// and the chainhash that the channel resides on.
1325
func fetchChanBucket(tx kvdb.RTx, nodeKey *btcec.PublicKey,
1326
        outPoint *wire.OutPoint, chainHash chainhash.Hash) (kvdb.RBucket, error) {
2,992✔
1327

2,992✔
1328
        // First fetch the top level bucket which stores all data related to
2,992✔
1329
        // current, active channels.
2,992✔
1330
        openChanBucket := tx.ReadBucket(openChannelBucket)
2,992✔
1331
        if openChanBucket == nil {
2,992✔
1332
                return nil, ErrNoChanDBExists
×
1333
        }
×
1334

1335
        // TODO(roasbeef): CreateTopLevelBucket on the interface isn't like
1336
        // CreateIfNotExists, will return error
1337

1338
        // Within this top level bucket, fetch the bucket dedicated to storing
1339
        // open channel data specific to the remote node.
1340
        nodePub := nodeKey.SerializeCompressed()
2,992✔
1341
        nodeChanBucket := openChanBucket.NestedReadBucket(nodePub)
2,992✔
1342
        if nodeChanBucket == nil {
4,144✔
1343
                return nil, ErrNoActiveChannels
1,152✔
1344
        }
1,152✔
1345

1346
        // We'll then recurse down an additional layer in order to fetch the
1347
        // bucket for this particular chain.
1348
        chainBucket := nodeChanBucket.NestedReadBucket(chainHash[:])
1,840✔
1349
        if chainBucket == nil {
1,840✔
1350
                return nil, ErrNoActiveChannels
×
1351
        }
×
1352

1353
        // With the bucket for the node and chain fetched, we can now go down
1354
        // another level, for this channel itself.
1355
        var chanPointBuf bytes.Buffer
1,840✔
1356
        if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
1,840✔
1357
                return nil, err
×
1358
        }
×
1359
        chanBucket := chainBucket.NestedReadBucket(chanPointBuf.Bytes())
1,840✔
1360
        if chanBucket == nil {
1,844✔
1361
                return nil, ErrChannelNotFound
4✔
1362
        }
4✔
1363

1364
        return chanBucket, nil
1,839✔
1365
}
1366

1367
// fetchChanBucketRw is a helper function that returns the bucket where a
1368
// channel's data resides in given: the public key for the node, the outpoint,
1369
// and the chainhash that the channel resides on. This differs from
1370
// fetchChanBucket in that it returns a writeable bucket.
1371
func fetchChanBucketRw(tx kvdb.RwTx, nodeKey *btcec.PublicKey,
1372
        outPoint *wire.OutPoint, chainHash chainhash.Hash) (kvdb.RwBucket,
1373
        error) {
7,218✔
1374

7,218✔
1375
        // First fetch the top level bucket which stores all data related to
7,218✔
1376
        // current, active channels.
7,218✔
1377
        openChanBucket := tx.ReadWriteBucket(openChannelBucket)
7,218✔
1378
        if openChanBucket == nil {
7,218✔
1379
                return nil, ErrNoChanDBExists
×
1380
        }
×
1381

1382
        // TODO(roasbeef): CreateTopLevelBucket on the interface isn't like
1383
        // CreateIfNotExists, will return error
1384

1385
        // Within this top level bucket, fetch the bucket dedicated to storing
1386
        // open channel data specific to the remote node.
1387
        nodePub := nodeKey.SerializeCompressed()
7,218✔
1388
        nodeChanBucket := openChanBucket.NestedReadWriteBucket(nodePub)
7,218✔
1389
        if nodeChanBucket == nil {
7,218✔
1390
                return nil, ErrNoActiveChannels
×
1391
        }
×
1392

1393
        // We'll then recurse down an additional layer in order to fetch the
1394
        // bucket for this particular chain.
1395
        chainBucket := nodeChanBucket.NestedReadWriteBucket(chainHash[:])
7,218✔
1396
        if chainBucket == nil {
7,218✔
1397
                return nil, ErrNoActiveChannels
×
1398
        }
×
1399

1400
        // With the bucket for the node and chain fetched, we can now go down
1401
        // another level, for this channel itself.
1402
        var chanPointBuf bytes.Buffer
7,218✔
1403
        if err := graphdb.WriteOutpoint(&chanPointBuf, outPoint); err != nil {
7,218✔
1404
                return nil, err
×
1405
        }
×
1406
        chanBucket := chainBucket.NestedReadWriteBucket(chanPointBuf.Bytes())
7,218✔
1407
        if chanBucket == nil {
7,219✔
1408
                return nil, ErrChannelNotFound
1✔
1409
        }
1✔
1410

1411
        return chanBucket, nil
7,218✔
1412
}
1413

1414
func fetchFinalHtlcsBucketRw(tx kvdb.RwTx,
1415
        chanID lnwire.ShortChannelID) (kvdb.RwBucket, error) {
6✔
1416

6✔
1417
        finalHtlcsBucket, err := tx.CreateTopLevelBucket(finalHtlcsBucket)
6✔
1418
        if err != nil {
6✔
1419
                return nil, err
×
1420
        }
×
1421

1422
        var chanIDBytes [8]byte
6✔
1423
        byteOrder.PutUint64(chanIDBytes[:], chanID.ToUint64())
6✔
1424
        chanBucket, err := finalHtlcsBucket.CreateBucketIfNotExists(
6✔
1425
                chanIDBytes[:],
6✔
1426
        )
6✔
1427
        if err != nil {
6✔
1428
                return nil, err
×
1429
        }
×
1430

1431
        return chanBucket, nil
6✔
1432
}
1433

1434
// fullSync syncs the contents of an OpenChannel while re-using an existing
1435
// database transaction.
1436
func (c *OpenChannel) fullSync(tx kvdb.RwTx) error {
901✔
1437
        // Fetch the outpoint bucket and check if the outpoint already exists.
901✔
1438
        opBucket := tx.ReadWriteBucket(outpointBucket)
901✔
1439
        if opBucket == nil {
901✔
1440
                return ErrNoChanDBExists
×
1441
        }
×
1442
        cidBucket := tx.ReadWriteBucket(chanIDBucket)
901✔
1443
        if cidBucket == nil {
901✔
1444
                return ErrNoChanDBExists
×
1445
        }
×
1446

1447
        var chanPointBuf bytes.Buffer
901✔
1448
        err := graphdb.WriteOutpoint(&chanPointBuf, &c.FundingOutpoint)
901✔
1449
        if err != nil {
901✔
1450
                return err
×
1451
        }
×
1452

1453
        // Now, check if the outpoint exists in our index.
1454
        if opBucket.Get(chanPointBuf.Bytes()) != nil {
904✔
1455
                return ErrChanAlreadyExists
3✔
1456
        }
3✔
1457

1458
        cid := lnwire.NewChanIDFromOutPoint(c.FundingOutpoint)
901✔
1459
        if cidBucket.Get(cid[:]) != nil {
901✔
1460
                return ErrChanAlreadyExists
×
1461
        }
×
1462

1463
        status := uint8(outpointOpen)
901✔
1464

901✔
1465
        // Write the status of this outpoint as the first entry in a tlv
901✔
1466
        // stream.
901✔
1467
        statusRecord := tlv.MakePrimitiveRecord(indexStatusType, &status)
901✔
1468
        opStream, err := tlv.NewStream(statusRecord)
901✔
1469
        if err != nil {
901✔
1470
                return err
×
1471
        }
×
1472

1473
        var b bytes.Buffer
901✔
1474
        if err := opStream.Encode(&b); err != nil {
901✔
1475
                return err
×
1476
        }
×
1477

1478
        // Add the outpoint to our outpoint index with the tlv stream.
1479
        if err := opBucket.Put(chanPointBuf.Bytes(), b.Bytes()); err != nil {
901✔
1480
                return err
×
1481
        }
×
1482

1483
        if err := cidBucket.Put(cid[:], []byte{}); err != nil {
901✔
1484
                return err
×
1485
        }
×
1486

1487
        // First fetch the top level bucket which stores all data related to
1488
        // current, active channels.
1489
        openChanBucket, err := tx.CreateTopLevelBucket(openChannelBucket)
901✔
1490
        if err != nil {
901✔
1491
                return err
×
1492
        }
×
1493

1494
        // Within this top level bucket, fetch the bucket dedicated to storing
1495
        // open channel data specific to the remote node.
1496
        nodePub := c.IdentityPub.SerializeCompressed()
901✔
1497
        nodeChanBucket, err := openChanBucket.CreateBucketIfNotExists(nodePub)
901✔
1498
        if err != nil {
901✔
1499
                return err
×
1500
        }
×
1501

1502
        // We'll then recurse down an additional layer in order to fetch the
1503
        // bucket for this particular chain.
1504
        chainBucket, err := nodeChanBucket.CreateBucketIfNotExists(c.ChainHash[:])
901✔
1505
        if err != nil {
901✔
1506
                return err
×
1507
        }
×
1508

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

1523
        return putOpenChannel(chanBucket, c)
901✔
1524
}
1525

1526
// MarkConfirmationHeight updates the channel's confirmation height once the
1527
// channel opening transaction receives one confirmation.
1528
func (c *OpenChannel) MarkConfirmationHeight(height uint32) error {
44✔
1529
        c.Lock()
44✔
1530
        defer c.Unlock()
44✔
1531

44✔
1532
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
88✔
1533
                chanBucket, err := fetchChanBucketRw(
44✔
1534
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
44✔
1535
                )
44✔
1536
                if err != nil {
44✔
1537
                        return err
×
1538
                }
×
1539

1540
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
44✔
1541
                if err != nil {
44✔
1542
                        return err
×
1543
                }
×
1544

1545
                channel.ConfirmationHeight = height
44✔
1546

44✔
1547
                return putOpenChannel(chanBucket, channel)
44✔
1548
        }, func() {}); err != nil {
44✔
1549
                return err
×
1550
        }
×
1551

1552
        c.ConfirmationHeight = height
44✔
1553

44✔
1554
        return nil
44✔
1555
}
1556

1557
// MarkAsOpen marks a channel as fully open given a locator that uniquely
1558
// describes its location within the chain.
1559
func (c *OpenChannel) MarkAsOpen(openLoc lnwire.ShortChannelID) error {
169✔
1560
        c.Lock()
169✔
1561
        defer c.Unlock()
169✔
1562

169✔
1563
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
338✔
1564
                chanBucket, err := fetchChanBucketRw(
169✔
1565
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
169✔
1566
                )
169✔
1567
                if err != nil {
169✔
1568
                        return err
×
1569
                }
×
1570

1571
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
169✔
1572
                if err != nil {
169✔
1573
                        return err
×
1574
                }
×
1575

1576
                channel.IsPending = false
169✔
1577
                channel.ShortChannelID = openLoc
169✔
1578

169✔
1579
                return putOpenChannel(chanBucket, channel)
169✔
1580
        }, func() {}); err != nil {
169✔
1581
                return err
×
1582
        }
×
1583

1584
        c.IsPending = false
169✔
1585
        c.ShortChannelID = openLoc
169✔
1586
        c.Packager = NewChannelPackager(openLoc)
169✔
1587

169✔
1588
        return nil
169✔
1589
}
1590

1591
// MarkRealScid marks the zero-conf channel's confirmed ShortChannelID. This
1592
// should only be done if IsZeroConf returns true.
1593
func (c *OpenChannel) MarkRealScid(realScid lnwire.ShortChannelID) error {
10✔
1594
        c.Lock()
10✔
1595
        defer c.Unlock()
10✔
1596

10✔
1597
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
20✔
1598
                chanBucket, err := fetchChanBucketRw(
10✔
1599
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
10✔
1600
                )
10✔
1601
                if err != nil {
10✔
1602
                        return err
×
1603
                }
×
1604

1605
                channel, err := fetchOpenChannel(
10✔
1606
                        chanBucket, &c.FundingOutpoint,
10✔
1607
                )
10✔
1608
                if err != nil {
10✔
1609
                        return err
×
1610
                }
×
1611

1612
                channel.confirmedScid = realScid
10✔
1613

10✔
1614
                return putOpenChannel(chanBucket, channel)
10✔
1615
        }, func() {}); err != nil {
10✔
1616
                return err
×
1617
        }
×
1618

1619
        c.confirmedScid = realScid
10✔
1620

10✔
1621
        return nil
10✔
1622
}
1623

1624
// MarkScidAliasNegotiated adds ScidAliasFeatureBit to ChanType in-memory and
1625
// in the database.
1626
func (c *OpenChannel) MarkScidAliasNegotiated() error {
3✔
1627
        c.Lock()
3✔
1628
        defer c.Unlock()
3✔
1629

3✔
1630
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
1631
                chanBucket, err := fetchChanBucketRw(
3✔
1632
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1633
                )
3✔
1634
                if err != nil {
3✔
1635
                        return err
×
1636
                }
×
1637

1638
                channel, err := fetchOpenChannel(
3✔
1639
                        chanBucket, &c.FundingOutpoint,
3✔
1640
                )
3✔
1641
                if err != nil {
3✔
1642
                        return err
×
1643
                }
×
1644

1645
                channel.ChanType |= ScidAliasFeatureBit
3✔
1646
                return putOpenChannel(chanBucket, channel)
3✔
1647
        }, func() {}); err != nil {
3✔
1648
                return err
×
1649
        }
×
1650

1651
        c.ChanType |= ScidAliasFeatureBit
3✔
1652

3✔
1653
        return nil
3✔
1654
}
1655

1656
// MarkDataLoss marks sets the channel status to LocalDataLoss and stores the
1657
// passed commitPoint for use to retrieve funds in case the remote force closes
1658
// the channel.
1659
func (c *OpenChannel) MarkDataLoss(commitPoint *btcec.PublicKey) error {
7✔
1660
        c.Lock()
7✔
1661
        defer c.Unlock()
7✔
1662

7✔
1663
        var b bytes.Buffer
7✔
1664
        if err := WriteElement(&b, commitPoint); err != nil {
7✔
1665
                return err
×
1666
        }
×
1667

1668
        putCommitPoint := func(chanBucket kvdb.RwBucket) error {
14✔
1669
                return chanBucket.Put(dataLossCommitPointKey, b.Bytes())
7✔
1670
        }
7✔
1671

1672
        return c.putChanStatus(ChanStatusLocalDataLoss, putCommitPoint)
7✔
1673
}
1674

1675
// DataLossCommitPoint retrieves the stored commit point set during
1676
// MarkDataLoss. If not found ErrNoCommitPoint is returned.
1677
func (c *OpenChannel) DataLossCommitPoint() (*btcec.PublicKey, error) {
4✔
1678
        var commitPoint *btcec.PublicKey
4✔
1679

4✔
1680
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
8✔
1681
                chanBucket, err := fetchChanBucket(
4✔
1682
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
4✔
1683
                )
4✔
1684
                switch err {
4✔
1685
                case nil:
4✔
1686
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
×
1687
                        return ErrNoCommitPoint
×
1688
                default:
×
1689
                        return err
×
1690
                }
1691

1692
                bs := chanBucket.Get(dataLossCommitPointKey)
4✔
1693
                if bs == nil {
4✔
1694
                        return ErrNoCommitPoint
×
1695
                }
×
1696
                r := bytes.NewReader(bs)
4✔
1697
                if err := ReadElements(r, &commitPoint); err != nil {
4✔
1698
                        return err
×
1699
                }
×
1700

1701
                return nil
4✔
1702
        }, func() {
4✔
1703
                commitPoint = nil
4✔
1704
        })
4✔
1705
        if err != nil {
4✔
1706
                return nil, err
×
1707
        }
×
1708

1709
        return commitPoint, nil
4✔
1710
}
1711

1712
// MarkBorked marks the event when the channel as reached an irreconcilable
1713
// state, such as a channel breach or state desynchronization. Borked channels
1714
// should never be added to the switch.
1715
func (c *OpenChannel) MarkBorked() error {
5✔
1716
        c.Lock()
5✔
1717
        defer c.Unlock()
5✔
1718

5✔
1719
        return c.putChanStatus(ChanStatusBorked)
5✔
1720
}
5✔
1721

1722
// SecondCommitmentPoint returns the second per-commitment-point for use in the
1723
// channel_ready message.
1724
func (c *OpenChannel) SecondCommitmentPoint() (*btcec.PublicKey, error) {
3✔
1725
        c.RLock()
3✔
1726
        defer c.RUnlock()
3✔
1727

3✔
1728
        // Since we start at commitment height = 0, the second per commitment
3✔
1729
        // point is actually at the 1st index.
3✔
1730
        revocation, err := c.RevocationProducer.AtIndex(1)
3✔
1731
        if err != nil {
3✔
1732
                return nil, err
×
1733
        }
×
1734

1735
        return input.ComputeCommitmentPoint(revocation[:]), nil
3✔
1736
}
1737

1738
var (
1739
        // taprootRevRootKey is the key used to derive the revocation root for
1740
        // the taproot nonces. This is done via HMAC of the existing revocation
1741
        // root.
1742
        taprootRevRootKey = []byte("taproot-rev-root")
1743
)
1744

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

1756
        revRootHash := chainhash.HashH(rootHashBuf.Bytes())
998✔
1757

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

1767
        taprootRevRoot := taprootRevHmac.Sum(nil)
998✔
1768

998✔
1769
        // Once we have the root, we can then generate our shachain producer
998✔
1770
        // and from that generate the per-commitment point.
998✔
1771
        return shachain.NewRevocationProducerFromBytes(
998✔
1772
                taprootRevRoot,
998✔
1773
        )
998✔
1774
}
1775

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

331✔
1784
        // Now that we know what height we need, we'll grab the shachain
331✔
1785
        // pre-image at the target destination.
331✔
1786
        nextPreimage, err := shaGen.AtIndex(targetHeight)
331✔
1787
        if err != nil {
331✔
1788
                return nil, err
×
1789
        }
×
1790

1791
        shaChainRand := musig2.WithCustomRand(bytes.NewBuffer(nextPreimage[:]))
331✔
1792
        pubKeyOpt := musig2.WithPublicKey(pubKey)
331✔
1793

331✔
1794
        return musig2.GenNonces(pubKeyOpt, shaChainRand)
331✔
1795
}
1796

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

259✔
1816
        // The remote commitment height that we'll send in the
259✔
1817
        // ChannelReestablish message is our current commitment height plus
259✔
1818
        // one. If the receiver thinks that our commitment height is actually
259✔
1819
        // *equal* to this value, then they'll re-send the last commitment that
259✔
1820
        // they sent but we never fully processed.
259✔
1821
        localHeight := c.LocalCommitment.CommitHeight
259✔
1822
        nextLocalCommitHeight := localHeight + 1
259✔
1823

259✔
1824
        // The second value we'll send is the height of the remote commitment
259✔
1825
        // from our PoV. If the receiver thinks that their height is actually
259✔
1826
        // *one plus* this value, then they'll re-send their last revocation.
259✔
1827
        remoteChainTipHeight := c.RemoteCommitment.CommitHeight
259✔
1828

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

1844
        // Additionally, we'll send over the current unrevoked commitment on
1845
        // our local commitment transaction.
1846
        currentCommitSecret, err := c.RevocationProducer.AtIndex(
259✔
1847
                localHeight,
259✔
1848
        )
259✔
1849
        if err != nil {
259✔
1850
                return nil, err
×
1851
        }
×
1852

1853
        // If we've restored this channel, then we'll purposefully give them an
1854
        // invalid LocalUnrevokedCommitPoint so they'll force close the channel
1855
        // allowing us to sweep our funds.
1856
        if c.hasChanStatus(ChanStatusRestored) {
262✔
1857
                currentCommitSecret[0] ^= 1
3✔
1858

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

1868
        // If this is a taproot channel, then we'll need to generate our next
1869
        // verification nonce to send to the remote party. They'll use this to
1870
        // sign the next update to our commitment transaction.
1871
        var nextTaprootNonce lnwire.OptMusig2NonceTLV
259✔
1872
        if c.ChanType.IsTaproot() {
285✔
1873
                taprootRevProducer, err := DeriveMusig2Shachain(
26✔
1874
                        c.RevocationProducer,
26✔
1875
                )
26✔
1876
                if err != nil {
26✔
1877
                        return nil, err
×
1878
                }
×
1879

1880
                nextNonce, err := NewMusigVerificationNonce(
26✔
1881
                        c.LocalChanCfg.MultiSigKey.PubKey,
26✔
1882
                        nextLocalCommitHeight, taprootRevProducer,
26✔
1883
                )
26✔
1884
                if err != nil {
26✔
1885
                        return nil, fmt.Errorf("unable to gen next "+
×
1886
                                "nonce: %w", err)
×
1887
                }
×
1888

1889
                nextTaprootNonce = lnwire.SomeMusig2Nonce(nextNonce.PubNonce)
26✔
1890
        }
1891

1892
        return &lnwire.ChannelReestablish{
259✔
1893
                ChanID: lnwire.NewChanIDFromOutPoint(
259✔
1894
                        c.FundingOutpoint,
259✔
1895
                ),
259✔
1896
                NextLocalCommitHeight:  nextLocalCommitHeight,
259✔
1897
                RemoteCommitTailHeight: remoteChainTipHeight,
259✔
1898
                LastRemoteCommitSecret: lastCommitSecret,
259✔
1899
                LocalUnrevokedCommitPoint: input.ComputeCommitmentPoint(
259✔
1900
                        currentCommitSecret[:],
259✔
1901
                ),
259✔
1902
                LocalNonce: nextTaprootNonce,
259✔
1903
        }, nil
259✔
1904
}
1905

1906
// MarkShutdownSent serialises and persist the given ShutdownInfo for this
1907
// channel. Persisting this info represents the fact that we have sent the
1908
// Shutdown message to the remote side and hence that we should re-transmit the
1909
// same Shutdown message on re-establish.
1910
func (c *OpenChannel) MarkShutdownSent(info *ShutdownInfo) error {
14✔
1911
        c.Lock()
14✔
1912
        defer c.Unlock()
14✔
1913

14✔
1914
        return c.storeShutdownInfo(info)
14✔
1915
}
14✔
1916

1917
// storeShutdownInfo serialises the ShutdownInfo and persists it under the
1918
// shutdownInfoKey.
1919
func (c *OpenChannel) storeShutdownInfo(info *ShutdownInfo) error {
14✔
1920
        var b bytes.Buffer
14✔
1921
        err := info.encode(&b)
14✔
1922
        if err != nil {
14✔
1923
                return err
×
1924
        }
×
1925

1926
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
28✔
1927
                chanBucket, err := fetchChanBucketRw(
14✔
1928
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
14✔
1929
                )
14✔
1930
                if err != nil {
14✔
1931
                        return err
×
1932
                }
×
1933

1934
                return chanBucket.Put(shutdownInfoKey, b.Bytes())
14✔
1935
        }, func() {})
14✔
1936
}
1937

1938
// ShutdownInfo decodes the shutdown info stored for this channel and returns
1939
// the result. If no shutdown info has been persisted for this channel then the
1940
// ErrNoShutdownInfo error is returned.
1941
func (c *OpenChannel) ShutdownInfo() (fn.Option[ShutdownInfo], error) {
7✔
1942
        c.RLock()
7✔
1943
        defer c.RUnlock()
7✔
1944

7✔
1945
        var shutdownInfo *ShutdownInfo
7✔
1946
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
14✔
1947
                chanBucket, err := fetchChanBucket(
7✔
1948
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
7✔
1949
                )
7✔
1950
                switch {
7✔
1951
                case err == nil:
7✔
1952
                case errors.Is(err, ErrNoChanDBExists),
1953
                        errors.Is(err, ErrNoActiveChannels),
1954
                        errors.Is(err, ErrChannelNotFound):
2✔
1955

2✔
1956
                        return ErrNoShutdownInfo
2✔
1957
                default:
×
1958
                        return err
×
1959
                }
1960

1961
                shutdownInfoBytes := chanBucket.Get(shutdownInfoKey)
7✔
1962
                if shutdownInfoBytes == nil {
12✔
1963
                        return ErrNoShutdownInfo
5✔
1964
                }
5✔
1965

1966
                shutdownInfo, err = decodeShutdownInfo(shutdownInfoBytes)
5✔
1967

5✔
1968
                return err
5✔
1969
        }, func() {
7✔
1970
                shutdownInfo = nil
7✔
1971
        })
7✔
1972
        if err != nil {
12✔
1973
                return fn.None[ShutdownInfo](), err
5✔
1974
        }
5✔
1975

1976
        return fn.Some[ShutdownInfo](*shutdownInfo), nil
5✔
1977
}
1978

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

1990
        return channel.chanStatus != ChanStatusDefault, nil
6,298✔
1991
}
1992

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

11✔
2002
        return c.markBroadcasted(
11✔
2003
                ChanStatusCommitBroadcasted, forceCloseTxKey, closeTx,
11✔
2004
                closer,
11✔
2005
        )
11✔
2006
}
11✔
2007

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

41✔
2018
        return c.markBroadcasted(
41✔
2019
                ChanStatusCoopBroadcasted, coopCloseTxKey, closeTx,
41✔
2020
                closer,
41✔
2021
        )
41✔
2022
}
41✔
2023

2024
// markBroadcasted is a helper function which modifies the channel status of the
2025
// receiving channel and inserts a close transaction under the requested key,
2026
// which should specify either a coop or force close. It adds a status which
2027
// indicates the party that initiated the channel close.
2028
func (c *OpenChannel) markBroadcasted(status ChannelStatus, key []byte,
2029
        closeTx *wire.MsgTx, closer lntypes.ChannelParty) error {
49✔
2030

49✔
2031
        c.Lock()
49✔
2032
        defer c.Unlock()
49✔
2033

49✔
2034
        // If a closing tx is provided, we'll generate a closure to write the
49✔
2035
        // transaction in the appropriate bucket under the given key.
49✔
2036
        var putClosingTx func(kvdb.RwBucket) error
49✔
2037
        if closeTx != nil {
73✔
2038
                var b bytes.Buffer
24✔
2039
                if err := WriteElement(&b, closeTx); err != nil {
24✔
2040
                        return err
×
2041
                }
×
2042

2043
                putClosingTx = func(chanBucket kvdb.RwBucket) error {
48✔
2044
                        return chanBucket.Put(key, b.Bytes())
24✔
2045
                }
24✔
2046
        }
2047

2048
        // Add the initiator status to the status provided. These statuses are
2049
        // set in addition to the broadcast status so that we do not need to
2050
        // migrate the original logic which does not store initiator.
2051
        if closer.IsLocal() {
92✔
2052
                status |= ChanStatusLocalCloseInitiator
43✔
2053
        } else {
52✔
2054
                status |= ChanStatusRemoteCloseInitiator
9✔
2055
        }
9✔
2056

2057
        return c.putChanStatus(status, putClosingTx)
49✔
2058
}
2059

2060
// BroadcastedCommitment retrieves the stored unilateral closing tx set during
2061
// MarkCommitmentBroadcasted. If not found ErrNoCloseTx is returned.
2062
func (c *OpenChannel) BroadcastedCommitment() (*wire.MsgTx, error) {
10✔
2063
        return c.getClosingTx(forceCloseTxKey)
10✔
2064
}
10✔
2065

2066
// BroadcastedCooperative retrieves the stored cooperative closing tx set during
2067
// MarkCoopBroadcasted. If not found ErrNoCloseTx is returned.
2068
func (c *OpenChannel) BroadcastedCooperative() (*wire.MsgTx, error) {
12✔
2069
        return c.getClosingTx(coopCloseTxKey)
12✔
2070
}
12✔
2071

2072
// getClosingTx is a helper method which returns the stored closing transaction
2073
// for key. The caller should use either the force or coop closing keys.
2074
func (c *OpenChannel) getClosingTx(key []byte) (*wire.MsgTx, error) {
19✔
2075
        var closeTx *wire.MsgTx
19✔
2076

19✔
2077
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
38✔
2078
                chanBucket, err := fetchChanBucket(
19✔
2079
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
19✔
2080
                )
19✔
2081
                switch err {
19✔
2082
                case nil:
19✔
2083
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
×
2084
                        return ErrNoCloseTx
×
2085
                default:
×
2086
                        return err
×
2087
                }
2088

2089
                bs := chanBucket.Get(key)
19✔
2090
                if bs == nil {
24✔
2091
                        return ErrNoCloseTx
5✔
2092
                }
5✔
2093
                r := bytes.NewReader(bs)
17✔
2094
                return ReadElement(r, &closeTx)
17✔
2095
        }, func() {
19✔
2096
                closeTx = nil
19✔
2097
        })
19✔
2098
        if err != nil {
24✔
2099
                return nil, err
5✔
2100
        }
5✔
2101

2102
        return closeTx, nil
17✔
2103
}
2104

2105
// putChanStatus appends the given status to the channel. fs is an optional
2106
// list of closures that are given the chanBucket in order to atomically add
2107
// extra information together with the new status.
2108
func (c *OpenChannel) putChanStatus(status ChannelStatus,
2109
        fs ...func(kvdb.RwBucket) error) error {
58✔
2110

58✔
2111
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
116✔
2112
                chanBucket, err := fetchChanBucketRw(
58✔
2113
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
58✔
2114
                )
58✔
2115
                if err != nil {
59✔
2116
                        return err
1✔
2117
                }
1✔
2118

2119
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
58✔
2120
                if err != nil {
58✔
2121
                        return err
×
2122
                }
×
2123

2124
                // Add this status to the existing bitvector found in the DB.
2125
                status = channel.chanStatus | status
58✔
2126
                channel.chanStatus = status
58✔
2127

58✔
2128
                if err := putOpenChannel(chanBucket, channel); err != nil {
58✔
2129
                        return err
×
2130
                }
×
2131

2132
                for _, f := range fs {
111✔
2133
                        // Skip execution of nil closures.
53✔
2134
                        if f == nil {
81✔
2135
                                continue
28✔
2136
                        }
2137

2138
                        if err := f(chanBucket); err != nil {
28✔
2139
                                return err
×
2140
                        }
×
2141
                }
2142

2143
                return nil
58✔
2144
        }, func() {}); err != nil {
59✔
2145
                return err
1✔
2146
        }
1✔
2147

2148
        // Update the in-memory representation to keep it in sync with the DB.
2149
        c.chanStatus = status
58✔
2150

58✔
2151
        return nil
58✔
2152
}
2153

2154
func (c *OpenChannel) clearChanStatus(status ChannelStatus) error {
4✔
2155
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
8✔
2156
                chanBucket, err := fetchChanBucketRw(
4✔
2157
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
4✔
2158
                )
4✔
2159
                if err != nil {
4✔
2160
                        return err
×
2161
                }
×
2162

2163
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
4✔
2164
                if err != nil {
4✔
2165
                        return err
×
2166
                }
×
2167

2168
                // Unset this bit in the bitvector on disk.
2169
                status = channel.chanStatus & ^status
4✔
2170
                channel.chanStatus = status
4✔
2171

4✔
2172
                return putOpenChannel(chanBucket, channel)
4✔
2173
        }, func() {}); err != nil {
4✔
2174
                return err
×
2175
        }
×
2176

2177
        // Update the in-memory representation to keep it in sync with the DB.
2178
        c.chanStatus = status
4✔
2179

4✔
2180
        return nil
4✔
2181
}
2182

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

2192
        // With the static channel info written out, we'll now write out the
2193
        // current commitment state for both parties.
2194
        if err := putChanCommitments(chanBucket, channel); err != nil {
1,290✔
2195
                return fmt.Errorf("unable to store chan commitments: %w", err)
×
2196
        }
×
2197

2198
        // Next, if this is a frozen channel, we'll add in the axillary
2199
        // information we need to store.
2200
        if channel.ChanType.IsFrozen() || channel.ChanType.HasLeaseExpiration() {
1,732✔
2201
                err := storeThawHeight(
442✔
2202
                        chanBucket, channel.ThawHeight,
442✔
2203
                )
442✔
2204
                if err != nil {
442✔
2205
                        return fmt.Errorf("unable to store thaw height: %w",
×
2206
                                err)
×
2207
                }
×
2208
        }
2209

2210
        // Finally, we'll write out the revocation state for both parties
2211
        // within a distinct key space.
2212
        if err := putChanRevocationState(chanBucket, channel); err != nil {
1,290✔
2213
                return fmt.Errorf("unable to store chan revocations: %w", err)
×
2214
        }
×
2215

2216
        return nil
1,290✔
2217
}
2218

2219
// fetchOpenChannel retrieves, and deserializes (including decrypting
2220
// sensitive) the complete channel currently active with the passed nodeID.
2221
func fetchOpenChannel(chanBucket kvdb.RBucket,
2222
        chanPoint *wire.OutPoint) (*OpenChannel, error) {
7,510✔
2223

7,510✔
2224
        channel := &OpenChannel{
7,510✔
2225
                FundingOutpoint: *chanPoint,
7,510✔
2226
        }
7,510✔
2227

7,510✔
2228
        // First, we'll read all the static information that changes less
7,510✔
2229
        // frequently from disk.
7,510✔
2230
        if err := fetchChanInfo(chanBucket, channel); err != nil {
7,510✔
2231
                return nil, fmt.Errorf("unable to fetch chan info: %w", err)
×
2232
        }
×
2233

2234
        // With the static information read, we'll now read the current
2235
        // commitment state for both sides of the channel.
2236
        if err := fetchChanCommitments(chanBucket, channel); err != nil {
7,510✔
2237
                return nil, fmt.Errorf("unable to fetch chan commitments: %w",
×
2238
                        err)
×
2239
        }
×
2240

2241
        // Next, if this is a frozen channel, we'll add in the axillary
2242
        // information we need to store.
2243
        if channel.ChanType.IsFrozen() || channel.ChanType.HasLeaseExpiration() {
7,860✔
2244
                thawHeight, err := fetchThawHeight(chanBucket)
350✔
2245
                if err != nil {
350✔
2246
                        return nil, fmt.Errorf("unable to store thaw "+
×
2247
                                "height: %v", err)
×
2248
                }
×
2249

2250
                channel.ThawHeight = thawHeight
350✔
2251
        }
2252

2253
        // Finally, we'll retrieve the current revocation state so we can
2254
        // properly
2255
        if err := fetchChanRevocationState(chanBucket, channel); err != nil {
7,510✔
2256
                return nil, fmt.Errorf("unable to fetch chan revocations: %w",
×
2257
                        err)
×
2258
        }
×
2259

2260
        channel.Packager = NewChannelPackager(channel.ShortChannelID)
7,510✔
2261

7,510✔
2262
        return channel, nil
7,510✔
2263
}
2264

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

900✔
2280
        c.FundingBroadcastHeight = pendingHeight
900✔
2281

900✔
2282
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
1,800✔
2283
                return syncNewChannel(tx, c, []net.Addr{addr})
900✔
2284
        }, func() {})
1,800✔
2285
}
2286

2287
// syncNewChannel will write the passed channel to disk, and also create a
2288
// LinkNode (if needed) for the channel peer.
2289
func syncNewChannel(tx kvdb.RwTx, c *OpenChannel, addrs []net.Addr) error {
901✔
2290
        // First, sync all the persistent channel state to disk.
901✔
2291
        if err := c.fullSync(tx); err != nil {
904✔
2292
                return err
3✔
2293
        }
3✔
2294

2295
        nodeInfoBucket, err := tx.CreateTopLevelBucket(nodeInfoBucket)
901✔
2296
        if err != nil {
901✔
2297
                return err
×
2298
        }
×
2299

2300
        // If a LinkNode for this identity public key already exists,
2301
        // then we can exit early.
2302
        nodePub := c.IdentityPub.SerializeCompressed()
901✔
2303
        if nodeInfoBucket.Get(nodePub) != nil {
1,047✔
2304
                return nil
146✔
2305
        }
146✔
2306

2307
        // Next, we need to establish a (possibly) new LinkNode relationship
2308
        // for this channel. The LinkNode metadata contains reachability,
2309
        // up-time, and service bits related information.
2310
        linkNode := NewLinkNode(
758✔
2311
                &LinkNodeDB{backend: c.Db.backend},
758✔
2312
                wire.MainNet, c.IdentityPub, addrs...,
758✔
2313
        )
758✔
2314

758✔
2315
        // TODO(roasbeef): do away with link node all together?
758✔
2316

758✔
2317
        return putLinkNode(nodeInfoBucket, linkNode)
758✔
2318
}
2319

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

2,101✔
2335
        c.Lock()
2,101✔
2336
        defer c.Unlock()
2,101✔
2337

2,101✔
2338
        // If this is a restored channel, then we want to avoid mutating the
2,101✔
2339
        // state as all, as it's impossible to do so in a protocol compliant
2,101✔
2340
        // manner.
2,101✔
2341
        if c.hasChanStatus(ChanStatusRestored) {
2,102✔
2342
                return nil, ErrNoRestoredChannelMutation
1✔
2343
        }
1✔
2344

2345
        var finalHtlcs = make(map[uint64]bool)
2,100✔
2346

2,100✔
2347
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
4,200✔
2348
                chanBucket, err := fetchChanBucketRw(
2,100✔
2349
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
2,100✔
2350
                )
2,100✔
2351
                if err != nil {
2,100✔
2352
                        return err
×
2353
                }
×
2354

2355
                // If the channel is marked as borked, then for safety reasons,
2356
                // we shouldn't attempt any further updates.
2357
                isBorked, err := c.isBorked(chanBucket)
2,100✔
2358
                if err != nil {
2,100✔
2359
                        return err
×
2360
                }
×
2361
                if isBorked {
2,101✔
2362
                        return ErrChanBorked
1✔
2363
                }
1✔
2364

2365
                if err = putChanInfo(chanBucket, c); err != nil {
2,099✔
2366
                        return fmt.Errorf("unable to store chan info: %w", err)
×
2367
                }
×
2368

2369
                // With the proper bucket fetched, we'll now write the latest
2370
                // commitment state to disk for the target party.
2371
                err = putChanCommitment(
2,099✔
2372
                        chanBucket, newCommitment, true,
2,099✔
2373
                )
2,099✔
2374
                if err != nil {
2,099✔
2375
                        return fmt.Errorf("unable to store chan "+
×
2376
                                "revocations: %v", err)
×
2377
                }
×
2378

2379
                // Persist unsigned but acked remote updates that need to be
2380
                // restored after a restart.
2381
                var b bytes.Buffer
2,099✔
2382
                err = serializeLogUpdates(&b, unsignedAckedUpdates)
2,099✔
2383
                if err != nil {
2,099✔
2384
                        return err
×
2385
                }
×
2386

2387
                err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes())
2,099✔
2388
                if err != nil {
2,099✔
2389
                        return fmt.Errorf("unable to store dangline remote "+
×
2390
                                "updates: %v", err)
×
2391
                }
×
2392

2393
                // Since we have just sent the counterparty a revocation, store true
2394
                // under lastWasRevokeKey.
2395
                var b2 bytes.Buffer
2,099✔
2396
                if err := WriteElements(&b2, true); err != nil {
2,099✔
2397
                        return err
×
2398
                }
×
2399

2400
                if err := chanBucket.Put(lastWasRevokeKey, b2.Bytes()); err != nil {
2,099✔
2401
                        return err
×
2402
                }
×
2403

2404
                // Persist the remote unsigned local updates that are not included
2405
                // in our new commitment.
2406
                updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
2,099✔
2407
                if updateBytes == nil {
2,621✔
2408
                        return nil
522✔
2409
                }
522✔
2410

2411
                r := bytes.NewReader(updateBytes)
1,580✔
2412
                updates, err := deserializeLogUpdates(r)
1,580✔
2413
                if err != nil {
1,580✔
2414
                        return err
×
2415
                }
×
2416

2417
                // Get the bucket where settled htlcs are recorded if the user
2418
                // opted in to storing this information.
2419
                var finalHtlcsBucket kvdb.RwBucket
1,580✔
2420
                if c.Db.parent.storeFinalHtlcResolutions {
1,584✔
2421
                        bucket, err := fetchFinalHtlcsBucketRw(
4✔
2422
                                tx, c.ShortChannelID,
4✔
2423
                        )
4✔
2424
                        if err != nil {
4✔
2425
                                return err
×
2426
                        }
×
2427

2428
                        finalHtlcsBucket = bucket
4✔
2429
                }
2430

2431
                var unsignedUpdates []LogUpdate
1,580✔
2432
                for _, upd := range updates {
2,034✔
2433
                        // Gather updates that are not on our local commitment.
454✔
2434
                        if upd.LogIndex >= newCommitment.LocalLogIndex {
454✔
2435
                                unsignedUpdates = append(unsignedUpdates, upd)
×
2436

×
2437
                                continue
×
2438
                        }
2439

2440
                        // The update was locked in. If the update was a
2441
                        // resolution, then store it in the database.
2442
                        err := processFinalHtlc(
454✔
2443
                                finalHtlcsBucket, upd, finalHtlcs,
454✔
2444
                        )
454✔
2445
                        if err != nil {
454✔
2446
                                return err
×
2447
                        }
×
2448
                }
2449

2450
                var b3 bytes.Buffer
1,580✔
2451
                err = serializeLogUpdates(&b3, unsignedUpdates)
1,580✔
2452
                if err != nil {
1,580✔
2453
                        return fmt.Errorf("unable to serialize log updates: %w",
×
2454
                                err)
×
2455
                }
×
2456

2457
                err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b3.Bytes())
1,580✔
2458
                if err != nil {
1,580✔
2459
                        return fmt.Errorf("unable to restore chanbucket: %w",
×
2460
                                err)
×
2461
                }
×
2462

2463
                return nil
1,580✔
2464
        }, func() {
2,100✔
2465
                finalHtlcs = make(map[uint64]bool)
2,100✔
2466
        })
2,100✔
2467
        if err != nil {
2,101✔
2468
                return nil, err
1✔
2469
        }
1✔
2470

2471
        c.LocalCommitment = *newCommitment
2,099✔
2472

2,099✔
2473
        return finalHtlcs, nil
2,099✔
2474
}
2475

2476
// processFinalHtlc stores a final htlc outcome in the database if signaled via
2477
// the supplied log update. An in-memory htlcs map is updated too.
2478
func processFinalHtlc(finalHtlcsBucket walletdb.ReadWriteBucket, upd LogUpdate,
2479
        finalHtlcs map[uint64]bool) error {
454✔
2480

454✔
2481
        var (
454✔
2482
                settled bool
454✔
2483
                id      uint64
454✔
2484
        )
454✔
2485

454✔
2486
        switch msg := upd.UpdateMsg.(type) {
454✔
2487
        case *lnwire.UpdateFulfillHTLC:
312✔
2488
                settled = true
312✔
2489
                id = msg.ID
312✔
2490

2491
        case *lnwire.UpdateFailHTLC:
134✔
2492
                settled = false
134✔
2493
                id = msg.ID
134✔
2494

2495
        case *lnwire.UpdateFailMalformedHTLC:
6✔
2496
                settled = false
6✔
2497
                id = msg.ID
6✔
2498

2499
        default:
8✔
2500
                return nil
8✔
2501
        }
2502

2503
        // Store the final resolution in the database if a bucket is provided.
2504
        if finalHtlcsBucket != nil {
450✔
2505
                err := putFinalHtlc(
4✔
2506
                        finalHtlcsBucket, id,
4✔
2507
                        FinalHtlcInfo{
4✔
2508
                                Settled:  settled,
4✔
2509
                                Offchain: true,
4✔
2510
                        },
4✔
2511
                )
4✔
2512
                if err != nil {
4✔
2513
                        return err
×
2514
                }
×
2515
        }
2516

2517
        finalHtlcs[id] = settled
446✔
2518

446✔
2519
        return nil
446✔
2520
}
2521

2522
// ActiveHtlcs returns a slice of HTLC's which are currently active on *both*
2523
// commitment transactions.
2524
func (c *OpenChannel) ActiveHtlcs() []HTLC {
1,641✔
2525
        c.RLock()
1,641✔
2526
        defer c.RUnlock()
1,641✔
2527

1,641✔
2528
        // We'll only return HTLC's that are locked into *both* commitment
1,641✔
2529
        // transactions. So we'll iterate through their set of HTLC's to note
1,641✔
2530
        // which ones are present on their commitment.
1,641✔
2531
        remoteHtlcs := make(map[[32]byte]struct{})
1,641✔
2532
        for _, htlc := range c.RemoteCommitment.Htlcs {
8,108✔
2533
                log.Tracef("RemoteCommitment has htlc: id=%v, update=%v "+
6,467✔
2534
                        "incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
6,467✔
2535
                        htlc.Incoming)
6,467✔
2536

6,467✔
2537
                onionHash := sha256.Sum256(htlc.OnionBlob[:])
6,467✔
2538
                remoteHtlcs[onionHash] = struct{}{}
6,467✔
2539
        }
6,467✔
2540

2541
        // Now that we know which HTLC's they have, we'll only mark the HTLC's
2542
        // as active if *we* know them as well.
2543
        activeHtlcs := make([]HTLC, 0, len(remoteHtlcs))
1,641✔
2544
        for _, htlc := range c.LocalCommitment.Htlcs {
8,112✔
2545
                log.Tracef("LocalCommitment has htlc: id=%v, update=%v "+
6,471✔
2546
                        "incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
6,471✔
2547
                        htlc.Incoming)
6,471✔
2548

6,471✔
2549
                onionHash := sha256.Sum256(htlc.OnionBlob[:])
6,471✔
2550
                if _, ok := remoteHtlcs[onionHash]; !ok {
6,753✔
2551
                        log.Tracef("Skipped htlc due to onion mismatched: "+
282✔
2552
                                "id=%v, update=%v incoming=%v",
282✔
2553
                                htlc.HtlcIndex, htlc.LogIndex, htlc.Incoming)
282✔
2554

282✔
2555
                        continue
282✔
2556
                }
2557

2558
                activeHtlcs = append(activeHtlcs, htlc)
6,192✔
2559
        }
2560

2561
        return activeHtlcs
1,641✔
2562
}
2563

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

2572
        // Signature is the signature for the second level covenant transaction
2573
        // for this HTLC. The second level transaction is a timeout tx in the
2574
        // case that this is an outgoing HTLC, and a success tx in the case
2575
        // that this is an incoming HTLC.
2576
        //
2577
        // TODO(roasbeef): make [64]byte instead?
2578
        Signature []byte
2579

2580
        // RHash is the payment hash of the HTLC.
2581
        RHash [32]byte
2582

2583
        // Amt is the amount of milli-satoshis this HTLC escrows.
2584
        Amt lnwire.MilliSatoshi
2585

2586
        // RefundTimeout is the absolute timeout on the HTLC that the sender
2587
        // must wait before reclaiming the funds in limbo.
2588
        RefundTimeout uint32
2589

2590
        // OutputIndex is the output index for this particular HTLC output
2591
        // within the commitment transaction.
2592
        OutputIndex int32
2593

2594
        // Incoming denotes whether we're the receiver or the sender of this
2595
        // HTLC.
2596
        Incoming bool
2597

2598
        // OnionBlob is an opaque blob which is used to complete multi-hop
2599
        // routing.
2600
        OnionBlob [lnwire.OnionPacketSize]byte
2601

2602
        // HtlcIndex is the HTLC counter index of this active, outstanding
2603
        // HTLC. This differs from the LogIndex, as the HtlcIndex is only
2604
        // incremented for each offered HTLC, while they LogIndex is
2605
        // incremented for each update (includes settle+fail).
2606
        HtlcIndex uint64
2607

2608
        // LogIndex is the cumulative log index of this HTLC. This differs
2609
        // from the HtlcIndex as this will be incremented for each new log
2610
        // update added.
2611
        LogIndex uint64
2612

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

2632
        // BlindingPoint is an optional blinding point included with the HTLC.
2633
        //
2634
        // Note: this field is not a part of on-disk representation of the
2635
        // HTLC. It is stored in the ExtraData field, which is used to store
2636
        // a TLV stream of additional information associated with the HTLC.
2637
        BlindingPoint lnwire.BlindingPointRecord
2638

2639
        // CustomRecords is a set of custom TLV records that are associated with
2640
        // this HTLC. These records are used to store additional information
2641
        // about the HTLC that is not part of the standard HTLC fields. This
2642
        // field is encoded within the ExtraData field.
2643
        CustomRecords lnwire.CustomRecords
2644
}
2645

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

7✔
2659
                records = append(records, &b)
7✔
2660
        })
7✔
2661

2662
        records, err := h.CustomRecords.ExtendRecordProducers(records)
28,235✔
2663
        if err != nil {
28,235✔
2664
                return err
×
2665
        }
×
2666

2667
        return h.ExtraData.PackRecords(records...)
28,235✔
2668
}
2669

2670
// deserializeExtraData extracts TLVs from the extra data persisted for the
2671
// htlc and populates values in the struct accordingly.
2672
//
2673
// This function MUST be called to populate the struct properly when HTLCs
2674
// are deserialized.
2675
func (h *HTLC) deserializeExtraData() error {
64,040✔
2676
        if len(h.ExtraData) == 0 {
125,889✔
2677
                return nil
61,849✔
2678
        }
61,849✔
2679

2680
        blindingPoint := h.BlindingPoint.Zero()
2,194✔
2681
        tlvMap, err := h.ExtraData.ExtractRecords(&blindingPoint)
2,194✔
2682
        if err != nil {
2,194✔
2683
                return err
×
2684
        }
×
2685

2686
        if val, ok := tlvMap[h.BlindingPoint.TlvType()]; ok && val == nil {
2,201✔
2687
                h.BlindingPoint = tlv.SomeRecordT(blindingPoint)
7✔
2688

7✔
2689
                // Remove the entry from the TLV map. Anything left in the map
7✔
2690
                // will be included in the custom records field.
7✔
2691
                delete(tlvMap, h.BlindingPoint.TlvType())
7✔
2692
        }
7✔
2693

2694
        // Set the custom records field to the remaining TLV records.
2695
        customRecords, err := lnwire.NewCustomRecords(tlvMap)
2,194✔
2696
        if err != nil {
2,194✔
2697
                return err
×
2698
        }
×
2699
        h.CustomRecords = customRecords
2,194✔
2700

2,194✔
2701
        return nil
2,194✔
2702
}
2703

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

2724
        for _, htlc := range htlcs {
37,123✔
2725
                // Populate TLV stream for any additional fields contained
28,235✔
2726
                // in the TLV.
28,235✔
2727
                if err := htlc.serializeExtraData(); err != nil {
28,235✔
2728
                        return err
×
2729
                }
×
2730

2731
                // The onion blob and hltc data are stored as a single var
2732
                // bytes blob.
2733
                onionAndExtraData := make(
28,235✔
2734
                        []byte, lnwire.OnionPacketSize+len(htlc.ExtraData),
28,235✔
2735
                )
28,235✔
2736
                copy(onionAndExtraData, htlc.OnionBlob[:])
28,235✔
2737
                copy(onionAndExtraData[lnwire.OnionPacketSize:], htlc.ExtraData)
28,235✔
2738

28,235✔
2739
                if err := WriteElements(b,
28,235✔
2740
                        htlc.Signature, htlc.RHash, htlc.Amt, htlc.RefundTimeout,
28,235✔
2741
                        htlc.OutputIndex, htlc.Incoming, onionAndExtraData,
28,235✔
2742
                        htlc.HtlcIndex, htlc.LogIndex,
28,235✔
2743
                ); err != nil {
28,235✔
2744
                        return err
×
2745
                }
×
2746
        }
2747

2748
        return nil
8,888✔
2749
}
2750

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

2774
        var htlcs []HTLC
17,214✔
2775
        if numHtlcs == 0 {
24,576✔
2776
                return htlcs, nil
7,362✔
2777
        }
7,362✔
2778

2779
        htlcs = make([]HTLC, numHtlcs)
9,855✔
2780
        for i := uint16(0); i < numHtlcs; i++ {
73,896✔
2781
                var onionAndExtraData []byte
64,041✔
2782
                if err := ReadElements(r,
64,041✔
2783
                        &htlcs[i].Signature, &htlcs[i].RHash, &htlcs[i].Amt,
64,041✔
2784
                        &htlcs[i].RefundTimeout, &htlcs[i].OutputIndex,
64,041✔
2785
                        &htlcs[i].Incoming, &onionAndExtraData,
64,041✔
2786
                        &htlcs[i].HtlcIndex, &htlcs[i].LogIndex,
64,041✔
2787
                ); err != nil {
64,041✔
2788
                        return htlcs, err
×
2789
                }
×
2790

2791
                // Sanity check that we have at least the onion blob size we
2792
                // expect.
2793
                if len(onionAndExtraData) < lnwire.OnionPacketSize {
64,042✔
2794
                        return nil, ErrOnionBlobLength
1✔
2795
                }
1✔
2796

2797
                // First OnionPacketSize bytes are our fixed length onion
2798
                // packet.
2799
                copy(
64,040✔
2800
                        htlcs[i].OnionBlob[:],
64,040✔
2801
                        onionAndExtraData[0:lnwire.OnionPacketSize],
64,040✔
2802
                )
64,040✔
2803

64,040✔
2804
                // Any additional bytes belong to extra data. ExtraDataLen
64,040✔
2805
                // will be >= 0, because we know that we always have a fixed
64,040✔
2806
                // length onion packet.
64,040✔
2807
                extraDataLen := len(onionAndExtraData) - lnwire.OnionPacketSize
64,040✔
2808
                if extraDataLen > 0 {
66,234✔
2809
                        htlcs[i].ExtraData = make([]byte, extraDataLen)
2,194✔
2810

2,194✔
2811
                        copy(
2,194✔
2812
                                htlcs[i].ExtraData,
2,194✔
2813
                                onionAndExtraData[lnwire.OnionPacketSize:],
2,194✔
2814
                        )
2,194✔
2815
                }
2,194✔
2816

2817
                // Finally, deserialize any TLVs contained in that extra data
2818
                // if they are present.
2819
                if err := htlcs[i].deserializeExtraData(); err != nil {
64,040✔
2820
                        return nil, err
×
2821
                }
×
2822
        }
2823

2824
        return htlcs, nil
9,854✔
2825
}
2826

2827
// Copy returns a full copy of the target HTLC.
2828
func (h *HTLC) Copy() HTLC {
272✔
2829
        clone := HTLC{
272✔
2830
                Incoming:      h.Incoming,
272✔
2831
                Amt:           h.Amt,
272✔
2832
                RefundTimeout: h.RefundTimeout,
272✔
2833
                OutputIndex:   h.OutputIndex,
272✔
2834
        }
272✔
2835
        copy(clone.Signature[:], h.Signature)
272✔
2836
        copy(clone.RHash[:], h.RHash[:])
272✔
2837
        copy(clone.ExtraData, h.ExtraData)
272✔
2838
        clone.BlindingPoint = h.BlindingPoint
272✔
2839
        clone.CustomRecords = h.CustomRecords.Copy()
272✔
2840

272✔
2841
        return clone
272✔
2842
}
272✔
2843

2844
// LogUpdate represents a pending update to the remote commitment chain. The
2845
// log update may be an add, fail, or settle entry. We maintain this data in
2846
// order to be able to properly retransmit our proposed state if necessary.
2847
type LogUpdate struct {
2848
        // LogIndex is the log index of this proposed commitment update entry.
2849
        LogIndex uint64
2850

2851
        // UpdateMsg is the update message that was included within our
2852
        // local update log. The LogIndex value denotes the log index of this
2853
        // update which will be used when restoring our local update log if
2854
        // we're left with a dangling update on restart.
2855
        UpdateMsg lnwire.Message
2856
}
2857

2858
// serializeLogUpdate writes a log update to the provided io.Writer.
2859
func serializeLogUpdate(w io.Writer, l *LogUpdate) error {
1,297✔
2860
        return WriteElements(w, l.LogIndex, l.UpdateMsg)
1,297✔
2861
}
1,297✔
2862

2863
// deserializeLogUpdate reads a log update from the provided io.Reader.
2864
func deserializeLogUpdate(r io.Reader) (*LogUpdate, error) {
87✔
2865
        l := &LogUpdate{}
87✔
2866
        if err := ReadElements(r, &l.LogIndex, &l.UpdateMsg); err != nil {
87✔
2867
                return nil, err
×
2868
        }
×
2869

2870
        return l, nil
87✔
2871
}
2872

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

2885
        // LogUpdates is the set of messages sent prior to the commitment state
2886
        // transition in question. Upon reconnection, if we detect that they
2887
        // don't have the commitment, then we re-send this along with the
2888
        // proper signature.
2889
        LogUpdates []LogUpdate
2890

2891
        // CommitSig is the exact CommitSig message that should be sent after
2892
        // the set of LogUpdates above has been retransmitted. The signatures
2893
        // within this message should properly cover the new commitment state
2894
        // and also the HTLC's within the new commitment state.
2895
        CommitSig *lnwire.CommitSig
2896

2897
        // OpenedCircuitKeys is a set of unique identifiers for any downstream
2898
        // Add packets included in this commitment txn. After a restart, this
2899
        // set of htlcs is acked from the link's incoming mailbox to ensure
2900
        // there isn't an attempt to re-add them to this commitment txn.
2901
        OpenedCircuitKeys []models.CircuitKey
2902

2903
        // ClosedCircuitKeys records the unique identifiers for any settle/fail
2904
        // packets that were resolved by this commitment txn. After a restart,
2905
        // this is used to ensure those circuits are removed from the circuit
2906
        // map, and the downstream packets in the link's mailbox are removed.
2907
        ClosedCircuitKeys []models.CircuitKey
2908

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

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

2928
// serializeLogUpdates serializes provided list of updates to a stream.
2929
func serializeLogUpdates(w io.Writer, logUpdates []LogUpdate) error {
9,502✔
2930
        numUpdates := uint16(len(logUpdates))
9,502✔
2931
        if err := binary.Write(w, byteOrder, numUpdates); err != nil {
9,502✔
2932
                return err
×
2933
        }
×
2934

2935
        for _, diff := range logUpdates {
13,386✔
2936
                err := WriteElements(w, diff.LogIndex, diff.UpdateMsg)
3,884✔
2937
                if err != nil {
3,884✔
2938
                        return err
×
2939
                }
×
2940
        }
2941

2942
        return nil
9,502✔
2943
}
2944

2945
// deserializeLogUpdates deserializes a list of updates from a stream.
2946
func deserializeLogUpdates(r io.Reader) ([]LogUpdate, error) {
5,676✔
2947
        var numUpdates uint16
5,676✔
2948
        if err := binary.Read(r, byteOrder, &numUpdates); err != nil {
5,676✔
2949
                return nil, err
×
2950
        }
×
2951

2952
        logUpdates := make([]LogUpdate, numUpdates)
5,676✔
2953
        for i := 0; i < int(numUpdates); i++ {
9,199✔
2954
                err := ReadElements(r,
3,523✔
2955
                        &logUpdates[i].LogIndex, &logUpdates[i].UpdateMsg,
3,523✔
2956
                )
3,523✔
2957
                if err != nil {
3,523✔
2958
                        return nil, err
×
2959
                }
×
2960
        }
2961
        return logUpdates, nil
5,676✔
2962
}
2963

2964
func serializeCommitDiff(w io.Writer, diff *CommitDiff) error { // nolint: dupl
2,145✔
2965
        if err := serializeChanCommit(w, &diff.Commitment); err != nil {
2,145✔
2966
                return err
×
2967
        }
×
2968

2969
        if err := WriteElements(w, diff.CommitSig); err != nil {
2,145✔
2970
                return err
×
2971
        }
×
2972

2973
        if err := serializeLogUpdates(w, diff.LogUpdates); err != nil {
2,145✔
2974
                return err
×
2975
        }
×
2976

2977
        numOpenRefs := uint16(len(diff.OpenedCircuitKeys))
2,145✔
2978
        if err := binary.Write(w, byteOrder, numOpenRefs); err != nil {
2,145✔
2979
                return err
×
2980
        }
×
2981

2982
        for _, openRef := range diff.OpenedCircuitKeys {
2,609✔
2983
                err := WriteElements(w, openRef.ChanID, openRef.HtlcID)
464✔
2984
                if err != nil {
464✔
2985
                        return err
×
2986
                }
×
2987
        }
2988

2989
        numClosedRefs := uint16(len(diff.ClosedCircuitKeys))
2,145✔
2990
        if err := binary.Write(w, byteOrder, numClosedRefs); err != nil {
2,145✔
2991
                return err
×
2992
        }
×
2993

2994
        for _, closedRef := range diff.ClosedCircuitKeys {
2,187✔
2995
                err := WriteElements(w, closedRef.ChanID, closedRef.HtlcID)
42✔
2996
                if err != nil {
42✔
2997
                        return err
×
2998
                }
×
2999
        }
3000

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

3009
        return nil
2,145✔
3010
}
3011

3012
func deserializeCommitDiff(r io.Reader) (*CommitDiff, error) {
2,141✔
3013
        var (
2,141✔
3014
                d   CommitDiff
2,141✔
3015
                err error
2,141✔
3016
        )
2,141✔
3017

2,141✔
3018
        d.Commitment, err = deserializeChanCommit(r)
2,141✔
3019
        if err != nil {
2,141✔
3020
                return nil, err
×
3021
        }
×
3022

3023
        var msg lnwire.Message
2,141✔
3024
        if err := ReadElements(r, &msg); err != nil {
2,141✔
3025
                return nil, err
×
3026
        }
×
3027
        commitSig, ok := msg.(*lnwire.CommitSig)
2,141✔
3028
        if !ok {
2,141✔
3029
                return nil, fmt.Errorf("expected lnwire.CommitSig, instead "+
×
3030
                        "read: %T", msg)
×
3031
        }
×
3032
        d.CommitSig = commitSig
2,141✔
3033

2,141✔
3034
        d.LogUpdates, err = deserializeLogUpdates(r)
2,141✔
3035
        if err != nil {
2,141✔
3036
                return nil, err
×
3037
        }
×
3038

3039
        var numOpenRefs uint16
2,141✔
3040
        if err := binary.Read(r, byteOrder, &numOpenRefs); err != nil {
2,141✔
3041
                return nil, err
×
3042
        }
×
3043

3044
        d.OpenedCircuitKeys = make([]models.CircuitKey, numOpenRefs)
2,141✔
3045
        for i := 0; i < int(numOpenRefs); i++ {
2,632✔
3046
                err := ReadElements(r,
491✔
3047
                        &d.OpenedCircuitKeys[i].ChanID,
491✔
3048
                        &d.OpenedCircuitKeys[i].HtlcID)
491✔
3049
                if err != nil {
491✔
3050
                        return nil, err
×
3051
                }
×
3052
        }
3053

3054
        var numClosedRefs uint16
2,141✔
3055
        if err := binary.Read(r, byteOrder, &numClosedRefs); err != nil {
2,141✔
3056
                return nil, err
×
3057
        }
×
3058

3059
        d.ClosedCircuitKeys = make([]models.CircuitKey, numClosedRefs)
2,141✔
3060
        for i := 0; i < int(numClosedRefs); i++ {
2,180✔
3061
                err := ReadElements(r,
39✔
3062
                        &d.ClosedCircuitKeys[i].ChanID,
39✔
3063
                        &d.ClosedCircuitKeys[i].HtlcID)
39✔
3064
                if err != nil {
39✔
3065
                        return nil, err
×
3066
                }
×
3067
        }
3068

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

3078
        d.Commitment.amendTlvData(auxData)
2,141✔
3079

2,141✔
3080
        return &d, nil
2,141✔
3081
}
3082

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

2,147✔
3093
        // If this is a restored channel, then we want to avoid mutating the
2,147✔
3094
        // state at all, as it's impossible to do so in a protocol compliant
2,147✔
3095
        // manner.
2,147✔
3096
        if c.hasChanStatus(ChanStatusRestored) {
2,148✔
3097
                return ErrNoRestoredChannelMutation
1✔
3098
        }
1✔
3099

3100
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
4,292✔
3101
                // First, we'll grab the writable bucket where this channel's
2,146✔
3102
                // data resides.
2,146✔
3103
                chanBucket, err := fetchChanBucketRw(
2,146✔
3104
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
2,146✔
3105
                )
2,146✔
3106
                if err != nil {
2,146✔
3107
                        return err
×
3108
                }
×
3109

3110
                // If the channel is marked as borked, then for safety reasons,
3111
                // we shouldn't attempt any further updates.
3112
                isBorked, err := c.isBorked(chanBucket)
2,146✔
3113
                if err != nil {
2,146✔
3114
                        return err
×
3115
                }
×
3116
                if isBorked {
2,147✔
3117
                        return ErrChanBorked
1✔
3118
                }
1✔
3119

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

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

3140
                // We are sending a commitment signature so lastWasRevokeKey should
3141
                // store false.
3142
                var b bytes.Buffer
2,145✔
3143
                if err := WriteElements(&b, false); err != nil {
2,145✔
3144
                        return err
×
3145
                }
×
3146
                if err := chanBucket.Put(lastWasRevokeKey, b.Bytes()); err != nil {
2,145✔
3147
                        return err
×
3148
                }
×
3149

3150
                // TODO(roasbeef): use seqno to derive key for later LCP
3151

3152
                // With the bucket retrieved, we'll now serialize the commit
3153
                // diff itself, and write it to disk.
3154
                var b2 bytes.Buffer
2,145✔
3155
                if err := serializeCommitDiff(&b2, diff); err != nil {
2,145✔
3156
                        return err
×
3157
                }
×
3158
                return chanBucket.Put(commitDiffKey, b2.Bytes())
2,145✔
3159
        }, func() {})
2,146✔
3160
}
3161

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

3182
                tipBytes := chanBucket.Get(commitDiffKey)
875✔
3183
                if tipBytes == nil {
1,666✔
3184
                        return ErrNoPendingCommit
791✔
3185
                }
791✔
3186

3187
                tipReader := bytes.NewReader(tipBytes)
87✔
3188
                dcd, err := deserializeCommitDiff(tipReader)
87✔
3189
                if err != nil {
87✔
3190
                        return err
×
3191
                }
×
3192

3193
                cd = dcd
87✔
3194
                return nil
87✔
3195
        }, func() {
1,259✔
3196
                cd = nil
1,259✔
3197
        })
1,259✔
3198
        if err != nil {
2,434✔
3199
                return nil, err
1,175✔
3200
        }
1,175✔
3201

3202
        return cd, nil
87✔
3203
}
3204

3205
// UnsignedAckedUpdates retrieves the persisted unsigned acked remote log
3206
// updates that still need to be signed for.
3207
func (c *OpenChannel) UnsignedAckedUpdates() ([]LogUpdate, error) {
823✔
3208
        var updates []LogUpdate
823✔
3209
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
1,646✔
3210
                chanBucket, err := fetchChanBucket(
823✔
3211
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
823✔
3212
                )
823✔
3213
                switch err {
823✔
3214
                case nil:
439✔
3215
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
387✔
3216
                        return nil
387✔
3217
                default:
×
3218
                        return err
×
3219
                }
3220

3221
                updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
439✔
3222
                if updateBytes == nil {
804✔
3223
                        return nil
365✔
3224
                }
365✔
3225

3226
                r := bytes.NewReader(updateBytes)
77✔
3227
                updates, err = deserializeLogUpdates(r)
77✔
3228
                return err
77✔
3229
        }, func() {
823✔
3230
                updates = nil
823✔
3231
        })
823✔
3232
        if err != nil {
823✔
3233
                return nil, err
×
3234
        }
×
3235

3236
        return updates, nil
823✔
3237
}
3238

3239
// RemoteUnsignedLocalUpdates retrieves the persisted, unsigned local log
3240
// updates that the remote still needs to sign for.
3241
func (c *OpenChannel) RemoteUnsignedLocalUpdates() ([]LogUpdate, error) {
822✔
3242
        var updates []LogUpdate
822✔
3243
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
1,644✔
3244
                chanBucket, err := fetchChanBucket(
822✔
3245
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
822✔
3246
                )
822✔
3247
                switch err {
822✔
3248
                case nil:
438✔
3249
                        break
438✔
3250
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
387✔
3251
                        return nil
387✔
3252
                default:
×
3253
                        return err
×
3254
                }
3255

3256
                updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
438✔
3257
                if updateBytes == nil {
834✔
3258
                        return nil
396✔
3259
                }
396✔
3260

3261
                r := bytes.NewReader(updateBytes)
45✔
3262
                updates, err = deserializeLogUpdates(r)
45✔
3263
                return err
45✔
3264
        }, func() {
822✔
3265
                updates = nil
822✔
3266
        })
822✔
3267
        if err != nil {
822✔
3268
                return nil, err
×
3269
        }
×
3270

3271
        return updates, nil
822✔
3272
}
3273

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

639✔
3285
        c.RemoteNextRevocation = revKey
639✔
3286

639✔
3287
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
1,278✔
3288
                chanBucket, err := fetchChanBucketRw(
639✔
3289
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
639✔
3290
                )
639✔
3291
                if err != nil {
639✔
3292
                        return err
×
3293
                }
×
3294

3295
                return putChanRevocationState(chanBucket, c)
639✔
3296
        }, func() {})
639✔
3297
        if err != nil {
639✔
3298
                return err
×
3299
        }
×
3300

3301
        return nil
639✔
3302
}
3303

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

2,059✔
3316
        c.Lock()
2,059✔
3317
        defer c.Unlock()
2,059✔
3318

2,059✔
3319
        // If this is a restored channel, then we want to avoid mutating the
2,059✔
3320
        // state at all, as it's impossible to do so in a protocol compliant
2,059✔
3321
        // manner.
2,059✔
3322
        if c.hasChanStatus(ChanStatusRestored) {
2,060✔
3323
                return ErrNoRestoredChannelMutation
1✔
3324
        }
1✔
3325

3326
        var newRemoteCommit *ChannelCommitment
2,058✔
3327

2,058✔
3328
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
4,116✔
3329
                chanBucket, err := fetchChanBucketRw(
2,058✔
3330
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
2,058✔
3331
                )
2,058✔
3332
                if err != nil {
2,058✔
3333
                        return err
×
3334
                }
×
3335

3336
                // If the channel is marked as borked, then for safety reasons,
3337
                // we shouldn't attempt any further updates.
3338
                isBorked, err := c.isBorked(chanBucket)
2,058✔
3339
                if err != nil {
2,058✔
3340
                        return err
×
3341
                }
×
3342
                if isBorked {
2,059✔
3343
                        return ErrChanBorked
1✔
3344
                }
1✔
3345

3346
                // Persist the latest preimage state to disk as the remote peer
3347
                // has just added to our local preimage store, and given us a
3348
                // new pending revocation key.
3349
                if err := putChanRevocationState(chanBucket, c); err != nil {
2,057✔
3350
                        return err
×
3351
                }
×
3352

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

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

3385
                // With the commitment pointer swapped, we can now add the
3386
                // revoked (prior) state to the revocation log.
3387
                err = putRevocationLog(
2,057✔
3388
                        logBucket, &c.RemoteCommitment, ourOutputIndex,
2,057✔
3389
                        theirOutputIndex, c.Db.parent.noRevLogAmtData,
2,057✔
3390
                )
2,057✔
3391
                if err != nil {
2,057✔
3392
                        return err
×
3393
                }
×
3394

3395
                // Lastly, we write the forwarding package to disk so that we
3396
                // can properly recover from failures and reforward HTLCs that
3397
                // have not received a corresponding settle/fail.
3398
                if err := c.Packager.AddFwdPkg(tx, fwdPkg); err != nil {
2,057✔
3399
                        return err
×
3400
                }
×
3401

3402
                // Persist the unsigned acked updates that are not included
3403
                // in their new commitment.
3404
                updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
2,057✔
3405
                if updateBytes == nil {
2,272✔
3406
                        // This shouldn't normally happen as we always store
215✔
3407
                        // the number of updates, but could still be
215✔
3408
                        // encountered by nodes that are upgrading.
215✔
3409
                        newRemoteCommit = &newCommit.Commitment
215✔
3410
                        return nil
215✔
3411
                }
215✔
3412

3413
                r := bytes.NewReader(updateBytes)
1,845✔
3414
                unsignedUpdates, err := deserializeLogUpdates(r)
1,845✔
3415
                if err != nil {
1,845✔
3416
                        return err
×
3417
                }
×
3418

3419
                var validUpdates []LogUpdate
1,845✔
3420
                for _, upd := range unsignedUpdates {
3,305✔
3421
                        lIdx := upd.LogIndex
1,460✔
3422

1,460✔
3423
                        // Filter for updates that are not on the remote
1,460✔
3424
                        // commitment.
1,460✔
3425
                        if lIdx >= newCommit.Commitment.RemoteLogIndex {
1,616✔
3426
                                validUpdates = append(validUpdates, upd)
156✔
3427
                        }
156✔
3428
                }
3429

3430
                var b bytes.Buffer
1,845✔
3431
                err = serializeLogUpdates(&b, validUpdates)
1,845✔
3432
                if err != nil {
1,845✔
3433
                        return fmt.Errorf("unable to serialize log updates: %w",
×
3434
                                err)
×
3435
                }
×
3436

3437
                err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes())
1,845✔
3438
                if err != nil {
1,845✔
3439
                        return fmt.Errorf("unable to store under "+
×
3440
                                "unsignedAckedUpdatesKey: %w", err)
×
3441
                }
×
3442

3443
                // Persist the local updates the peer hasn't yet signed so they
3444
                // can be restored after restart.
3445
                var b2 bytes.Buffer
1,845✔
3446
                err = serializeLogUpdates(&b2, updates)
1,845✔
3447
                if err != nil {
1,845✔
3448
                        return err
×
3449
                }
×
3450

3451
                err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b2.Bytes())
1,845✔
3452
                if err != nil {
1,845✔
3453
                        return fmt.Errorf("unable to restore remote unsigned "+
×
3454
                                "local updates: %v", err)
×
3455
                }
×
3456

3457
                newRemoteCommit = &newCommit.Commitment
1,845✔
3458

1,845✔
3459
                return nil
1,845✔
3460
        }, func() {
2,058✔
3461
                newRemoteCommit = nil
2,058✔
3462
        })
2,058✔
3463
        if err != nil {
2,059✔
3464
                return err
1✔
3465
        }
1✔
3466

3467
        // With the db transaction complete, we'll swap over the in-memory
3468
        // pointer of the new remote commitment, which was previously the tip
3469
        // of the commit chain.
3470
        c.RemoteCommitment = *newRemoteCommit
2,057✔
3471

2,057✔
3472
        return nil
2,057✔
3473
}
3474

3475
// FinalHtlcInfo contains information about the final outcome of an htlc.
3476
type FinalHtlcInfo struct {
3477
        // Settled is true is the htlc was settled. If false, the htlc was
3478
        // failed.
3479
        Settled bool
3480

3481
        // Offchain indicates whether the htlc was resolved off-chain or
3482
        // on-chain.
3483
        Offchain bool
3484
}
3485

3486
// putFinalHtlc writes the final htlc outcome to the database. Additionally it
3487
// records whether the htlc was resolved off-chain or on-chain.
3488
func putFinalHtlc(finalHtlcsBucket kvdb.RwBucket, id uint64,
3489
        info FinalHtlcInfo) error {
6✔
3490

6✔
3491
        var key [8]byte
6✔
3492
        byteOrder.PutUint64(key[:], id)
6✔
3493

6✔
3494
        var finalHtlcByte FinalHtlcByte
6✔
3495
        if info.Settled {
12✔
3496
                finalHtlcByte |= FinalHtlcSettledBit
6✔
3497
        }
6✔
3498
        if info.Offchain {
11✔
3499
                finalHtlcByte |= FinalHtlcOffchainBit
5✔
3500
        }
5✔
3501

3502
        return finalHtlcsBucket.Put(key[:], []byte{byte(finalHtlcByte)})
6✔
3503
}
3504

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

3518
        // If a pending commit was found, its local htlc index will be at least
3519
        // as large as the one on our local commitment.
3520
        if pendingRemoteCommit != nil {
398✔
3521
                return pendingRemoteCommit.Commitment.LocalHtlcIndex, nil
16✔
3522
        }
16✔
3523

3524
        // Otherwise, fallback to using the local htlc index of their commitment.
3525
        return c.RemoteCommitment.LocalHtlcIndex, nil
366✔
3526
}
3527

3528
// LoadFwdPkgs scans the forwarding log for any packages that haven't been
3529
// processed, and returns their deserialized log updates in map indexed by the
3530
// remote commitment height at which the updates were locked in.
3531
func (c *OpenChannel) LoadFwdPkgs() ([]*FwdPkg, error) {
449✔
3532
        c.RLock()
449✔
3533
        defer c.RUnlock()
449✔
3534

449✔
3535
        var fwdPkgs []*FwdPkg
449✔
3536
        if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
882✔
3537
                var err error
433✔
3538
                fwdPkgs, err = c.Packager.LoadFwdPkgs(tx)
433✔
3539
                return err
433✔
3540
        }, func() {
882✔
3541
                fwdPkgs = nil
449✔
3542
        }); err != nil {
465✔
3543
                return nil, err
16✔
3544
        }
16✔
3545

3546
        return fwdPkgs, nil
433✔
3547
}
3548

3549
// AckAddHtlcs updates the AckAddFilter containing any of the provided AddRefs
3550
// indicating that a response to this Add has been committed to the remote party.
3551
// Doing so will prevent these Add HTLCs from being reforwarded internally.
3552
func (c *OpenChannel) AckAddHtlcs(addRefs ...AddRef) error {
1✔
3553
        c.Lock()
1✔
3554
        defer c.Unlock()
1✔
3555

1✔
3556
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
3557
                return c.Packager.AckAddHtlcs(tx, addRefs...)
1✔
3558
        }, func() {})
2✔
3559
}
3560

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

×
3569
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
3570
                return c.Packager.AckSettleFails(tx, settleFailRefs...)
×
3571
        }, func() {})
×
3572
}
3573

3574
// SetFwdFilter atomically sets the forwarding filter for the forwarding package
3575
// identified by `height`.
3576
func (c *OpenChannel) SetFwdFilter(height uint64, fwdFilter *PkgFilter) error {
1,184✔
3577
        c.Lock()
1,184✔
3578
        defer c.Unlock()
1,184✔
3579

1,184✔
3580
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2,368✔
3581
                return c.Packager.SetFwdFilter(tx, height, fwdFilter)
1,184✔
3582
        }, func() {})
2,368✔
3583
}
3584

3585
// RemoveFwdPkgs atomically removes forwarding packages specified by the remote
3586
// commitment heights. If one of the intermediate RemovePkg calls fails, then the
3587
// later packages won't be removed.
3588
//
3589
// NOTE: This method should only be called on packages marked FwdStateCompleted.
3590
func (c *OpenChannel) RemoveFwdPkgs(heights ...uint64) error {
4✔
3591
        c.Lock()
4✔
3592
        defer c.Unlock()
4✔
3593

4✔
3594
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
8✔
3595
                for _, height := range heights {
8✔
3596
                        err := c.Packager.RemovePkg(tx, height)
4✔
3597
                        if err != nil {
4✔
UNCOV
3598
                                return err
×
UNCOV
3599
                        }
×
3600
                }
3601

3602
                return nil
4✔
3603
        }, func() {})
4✔
3604
}
3605

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

2✔
3616
        var height uint64
2✔
3617

2✔
3618
        // If we haven't created any state updates yet, then we'll exit early as
2✔
3619
        // there's nothing to be found on disk in the revocation bucket.
2✔
3620
        if c.RemoteCommitment.CommitHeight == 0 {
2✔
3621
                return height, nil
×
3622
        }
×
3623

3624
        if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
4✔
3625
                chanBucket, err := fetchChanBucket(
2✔
3626
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
2✔
3627
                )
2✔
3628
                if err != nil {
2✔
3629
                        return err
×
3630
                }
×
3631

3632
                logBucket, err := fetchLogBucket(chanBucket)
2✔
3633
                if err != nil {
2✔
3634
                        return err
×
3635
                }
×
3636

3637
                // Once we have the bucket that stores the revocation log from
3638
                // this channel, we'll jump to the _last_ key in bucket. Since
3639
                // the key is the commit height, we'll decode the bytes and
3640
                // return it.
3641
                cursor := logBucket.ReadCursor()
2✔
3642
                rawHeight, _ := cursor.Last()
2✔
3643
                height = byteOrder.Uint64(rawHeight)
2✔
3644

2✔
3645
                return nil
2✔
3646
        }, func() {}); err != nil {
2✔
3647
                return height, err
×
3648
        }
×
3649

3650
        return height, nil
2✔
3651
}
3652

3653
// CommitmentHeight returns the current commitment height. The commitment
3654
// height represents the number of updates to the commitment state to date.
3655
// This value is always monotonically increasing. This method is provided in
3656
// order to allow multiple instances of a particular open channel to obtain a
3657
// consistent view of the number of channel updates to date.
3658
func (c *OpenChannel) CommitmentHeight() (uint64, error) {
1✔
3659
        c.RLock()
1✔
3660
        defer c.RUnlock()
1✔
3661

1✔
3662
        var height uint64
1✔
3663
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2✔
3664
                // Get the bucket dedicated to storing the metadata for open
1✔
3665
                // channels.
1✔
3666
                chanBucket, err := fetchChanBucket(
1✔
3667
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
3668
                )
1✔
3669
                if err != nil {
1✔
3670
                        return err
×
3671
                }
×
3672

3673
                commit, err := fetchChanCommitment(chanBucket, true)
1✔
3674
                if err != nil {
1✔
3675
                        return err
×
3676
                }
×
3677

3678
                height = commit.CommitHeight
1✔
3679
                return nil
1✔
3680
        }, func() {
1✔
3681
                height = 0
1✔
3682
        })
1✔
3683
        if err != nil {
1✔
3684
                return 0, err
×
3685
        }
×
3686

3687
        return height, nil
1✔
3688
}
3689

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

34✔
3698
        c.RLock()
34✔
3699
        defer c.RUnlock()
34✔
3700

34✔
3701
        commit := &ChannelCommitment{}
34✔
3702
        rl := &RevocationLog{}
34✔
3703

34✔
3704
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
68✔
3705
                chanBucket, err := fetchChanBucket(
34✔
3706
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
34✔
3707
                )
34✔
3708
                if err != nil {
35✔
3709
                        return err
1✔
3710
                }
1✔
3711

3712
                // Find the revocation log from both the new and the old
3713
                // bucket.
3714
                r, c, err := fetchRevocationLogCompatible(chanBucket, updateNum)
33✔
3715
                if err != nil {
55✔
3716
                        return err
22✔
3717
                }
22✔
3718

3719
                rl = r
14✔
3720
                commit = c
14✔
3721
                return nil
14✔
3722
        }, func() {})
34✔
3723
        if err != nil {
57✔
3724
                return nil, nil, err
23✔
3725
        }
23✔
3726

3727
        // Either the `rl` or the `commit` is nil here. We return them as-is
3728
        // and leave it to the caller to decide its following action.
3729
        return rl, commit, nil
14✔
3730
}
3731

3732
// ClosureType is an enum like structure that details exactly _how_ a channel
3733
// was closed. Three closure types are currently possible: none, cooperative,
3734
// local force close, remote force close, and (remote) breach.
3735
type ClosureType uint8
3736

3737
const (
3738
        // CooperativeClose indicates that a channel has been closed
3739
        // cooperatively.  This means that both channel peers were online and
3740
        // signed a new transaction paying out the settled balance of the
3741
        // contract.
3742
        CooperativeClose ClosureType = 0
3743

3744
        // LocalForceClose indicates that we have unilaterally broadcast our
3745
        // current commitment state on-chain.
3746
        LocalForceClose ClosureType = 1
3747

3748
        // RemoteForceClose indicates that the remote peer has unilaterally
3749
        // broadcast their current commitment state on-chain.
3750
        RemoteForceClose ClosureType = 4
3751

3752
        // BreachClose indicates that the remote peer attempted to broadcast a
3753
        // prior _revoked_ channel state.
3754
        BreachClose ClosureType = 2
3755

3756
        // FundingCanceled indicates that the channel never was fully opened
3757
        // before it was marked as closed in the database. This can happen if
3758
        // we or the remote fail at some point during the opening workflow, or
3759
        // we timeout waiting for the funding transaction to be confirmed.
3760
        FundingCanceled ClosureType = 3
3761

3762
        // Abandoned indicates that the channel state was removed without
3763
        // any further actions. This is intended to clean up unusable
3764
        // channels during development.
3765
        Abandoned ClosureType = 5
3766
)
3767

3768
// PendingCleanupInfo contains the information needed to clean up a channel's
3769
// data after it has been closed. This is used by SQL backends to defer heavy
3770
// deletion operations to startup.
3771
type PendingCleanupInfo struct {
3772
        // ChanPoint is the funding outpoint of the channel.
3773
        ChanPoint wire.OutPoint
3774

3775
        // ShortChanID is the short channel ID of the channel.
3776
        ShortChanID lnwire.ShortChannelID
3777

3778
        // NodePub is the compressed public key of the remote node.
3779
        NodePub [33]byte
3780

3781
        // ChainHash is the hash of the chain this channel belongs to.
3782
        ChainHash chainhash.Hash
3783
}
3784

3785
// Encode serializes the PendingCleanupInfo to the given writer.
3786
func (p *PendingCleanupInfo) Encode(w io.Writer) error {
1✔
3787
        if err := WriteElements(w, p.ChanPoint, p.ShortChanID); err != nil {
1✔
NEW
3788
                return err
×
NEW
3789
        }
×
3790

3791
        if _, err := w.Write(p.NodePub[:]); err != nil {
1✔
NEW
3792
                return err
×
NEW
3793
        }
×
3794

3795
        if _, err := w.Write(p.ChainHash[:]); err != nil {
1✔
NEW
3796
                return err
×
NEW
3797
        }
×
3798

3799
        return nil
1✔
3800
}
3801

3802
// Decode deserializes the PendingCleanupInfo from the given reader.
3803
func (p *PendingCleanupInfo) Decode(r io.Reader) error {
1✔
3804
        if err := ReadElements(r, &p.ChanPoint, &p.ShortChanID); err != nil {
1✔
NEW
3805
                return err
×
NEW
3806
        }
×
3807

3808
        if _, err := io.ReadFull(r, p.NodePub[:]); err != nil {
1✔
NEW
3809
                return err
×
NEW
3810
        }
×
3811

3812
        if _, err := io.ReadFull(r, p.ChainHash[:]); err != nil {
1✔
NEW
3813
                return err
×
NEW
3814
        }
×
3815

3816
        return nil
1✔
3817
}
3818

3819
// ChannelCloseSummary contains the final state of a channel at the point it
3820
// was closed. Once a channel is closed, all the information pertaining to that
3821
// channel within the openChannelBucket is deleted, and a compact summary is
3822
// put in place instead.
3823
type ChannelCloseSummary struct {
3824
        // ChanPoint is the outpoint for this channel's funding transaction,
3825
        // and is used as a unique identifier for the channel.
3826
        ChanPoint wire.OutPoint
3827

3828
        // ShortChanID encodes the exact location in the chain in which the
3829
        // channel was initially confirmed. This includes: the block height,
3830
        // transaction index, and the output within the target transaction.
3831
        ShortChanID lnwire.ShortChannelID
3832

3833
        // ChainHash is the hash of the genesis block that this channel resides
3834
        // within.
3835
        ChainHash chainhash.Hash
3836

3837
        // ClosingTXID is the txid of the transaction which ultimately closed
3838
        // this channel.
3839
        ClosingTXID chainhash.Hash
3840

3841
        // RemotePub is the public key of the remote peer that we formerly had
3842
        // a channel with.
3843
        RemotePub *btcec.PublicKey
3844

3845
        // Capacity was the total capacity of the channel.
3846
        Capacity btcutil.Amount
3847

3848
        // CloseHeight is the height at which the funding transaction was
3849
        // spent.
3850
        CloseHeight uint32
3851

3852
        // SettledBalance is our total balance settled balance at the time of
3853
        // channel closure. This _does not_ include the sum of any outputs that
3854
        // have been time-locked as a result of the unilateral channel closure.
3855
        SettledBalance btcutil.Amount
3856

3857
        // TimeLockedBalance is the sum of all the time-locked outputs at the
3858
        // time of channel closure. If we triggered the force closure of this
3859
        // channel, then this value will be non-zero if our settled output is
3860
        // above the dust limit. If we were on the receiving side of a channel
3861
        // force closure, then this value will be non-zero if we had any
3862
        // outstanding outgoing HTLC's at the time of channel closure.
3863
        TimeLockedBalance btcutil.Amount
3864

3865
        // CloseType details exactly _how_ the channel was closed. Five closure
3866
        // types are possible: cooperative, local force, remote force, breach
3867
        // and funding canceled.
3868
        CloseType ClosureType
3869

3870
        // IsPending indicates whether this channel is in the 'pending close'
3871
        // state, which means the channel closing transaction has been
3872
        // confirmed, but not yet been fully resolved. In the case of a channel
3873
        // that has been cooperatively closed, it will go straight into the
3874
        // fully resolved state as soon as the closing transaction has been
3875
        // confirmed. However, for channels that have been force closed, they'll
3876
        // stay marked as "pending" until _all_ the pending funds have been
3877
        // swept.
3878
        IsPending bool
3879

3880
        // RemoteCurrentRevocation is the current revocation for their
3881
        // commitment transaction. However, since this is the derived public key,
3882
        // we don't yet have the private key so we aren't yet able to verify
3883
        // that it's actually in the hash chain.
3884
        RemoteCurrentRevocation *btcec.PublicKey
3885

3886
        // RemoteNextRevocation is the revocation key to be used for the *next*
3887
        // commitment transaction we create for the local node. Within the
3888
        // specification, this value is referred to as the
3889
        // per-commitment-point.
3890
        RemoteNextRevocation *btcec.PublicKey
3891

3892
        // LocalChanConfig is the channel configuration for the local node.
3893
        LocalChanConfig ChannelConfig
3894

3895
        // LastChanSyncMsg is the ChannelReestablish message for this channel
3896
        // for the state at the point where it was closed.
3897
        LastChanSyncMsg *lnwire.ChannelReestablish
3898
}
3899

3900
// CloseChannel closes a previously active Lightning channel. Closing a channel
3901
// entails deleting all saved state within the database concerning this
3902
// channel. This method also takes a struct that summarizes the state of the
3903
// channel at closing, this compact representation will be the only component
3904
// of a channel left over after a full closing. It takes an optional set of
3905
// channel statuses which will be written to the historical channel bucket.
3906
// These statuses are used to record close initiators.
3907
func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary,
3908
        statuses ...ChannelStatus) error {
119✔
3909

119✔
3910
        c.Lock()
119✔
3911
        defer c.Unlock()
119✔
3912

119✔
3913
        // Check if the backend prefers deferring heavy operations to startup.
119✔
3914
        // Postgres backends return true here to avoid lock contention.
119✔
3915
        deferCleanup := kvdb.ShouldDeferHeavyOperations(c.Db.backend)
119✔
3916

119✔
3917
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
238✔
3918
                openChanBucket := tx.ReadWriteBucket(openChannelBucket)
119✔
3919
                if openChanBucket == nil {
119✔
3920
                        return ErrNoChanDBExists
×
3921
                }
×
3922

3923
                nodePub := c.IdentityPub.SerializeCompressed()
119✔
3924
                nodeChanBucket := openChanBucket.NestedReadWriteBucket(nodePub)
119✔
3925
                if nodeChanBucket == nil {
119✔
3926
                        return ErrNoActiveChannels
×
3927
                }
×
3928

3929
                chainBucket := nodeChanBucket.NestedReadWriteBucket(c.ChainHash[:])
119✔
3930
                if chainBucket == nil {
119✔
3931
                        return ErrNoActiveChannels
×
3932
                }
×
3933

3934
                var chanPointBuf bytes.Buffer
119✔
3935
                err := graphdb.WriteOutpoint(&chanPointBuf, &c.FundingOutpoint)
119✔
3936
                if err != nil {
119✔
3937
                        return err
×
3938
                }
×
3939
                chanKey := chanPointBuf.Bytes()
119✔
3940
                chanBucket := chainBucket.NestedReadWriteBucket(
119✔
3941
                        chanKey,
119✔
3942
                )
119✔
3943
                if chanBucket == nil {
119✔
3944
                        return ErrNoActiveChannels
×
3945
                }
×
3946

3947
                // Before we delete the channel state, we'll read out the full
3948
                // details, as we'll also store portions of this information
3949
                // for record keeping.
3950
                chanState, err := fetchOpenChannel(
119✔
3951
                        chanBucket, &c.FundingOutpoint,
119✔
3952
                )
119✔
3953
                if err != nil {
119✔
3954
                        return err
×
3955
                }
×
3956

3957
                if deferCleanup {
119✔
NEW
3958
                        // For postgres backends, store cleanup info and defer
×
NEW
3959
                        // the heavy deletion operations to startup.
×
NEW
3960
                        err = storePendingCleanup(
×
NEW
3961
                                tx, c, nodePub, chanKey,
×
NEW
3962
                        )
×
NEW
3963
                        if err != nil {
×
NEW
3964
                                return err
×
NEW
3965
                        }
×
3966
                } else {
119✔
3967
                        // For non-postgres backends (bbolt, sqlite), perform
119✔
3968
                        // immediate cleanup.
119✔
3969
                        err = performImmediateCleanup(
119✔
3970
                                tx, chanState, chanBucket, chainBucket,
119✔
3971
                                chanPointBuf.Bytes(),
119✔
3972
                        )
119✔
3973
                        if err != nil {
119✔
3974
                                return err
×
3975
                        }
×
3976
                }
3977

3978
                // Fetch the outpoint bucket to see if the outpoint exists or
3979
                // not.
3980
                opBucket := tx.ReadWriteBucket(outpointBucket)
119✔
3981
                if opBucket == nil {
119✔
3982
                        return ErrNoChanDBExists
×
3983
                }
×
3984

3985
                // Add the closed outpoint to our outpoint index. This should
3986
                // replace an open outpoint in the index.
3987
                if opBucket.Get(chanPointBuf.Bytes()) == nil {
119✔
3988
                        return ErrMissingIndexEntry
×
3989
                }
×
3990

3991
                status := uint8(outpointClosed)
119✔
3992

119✔
3993
                // Write the IndexStatus of this outpoint as the first entry in a tlv
119✔
3994
                // stream.
119✔
3995
                statusRecord := tlv.MakePrimitiveRecord(indexStatusType, &status)
119✔
3996
                opStream, err := tlv.NewStream(statusRecord)
119✔
3997
                if err != nil {
119✔
3998
                        return err
×
3999
                }
×
4000

4001
                var b bytes.Buffer
119✔
4002
                if err := opStream.Encode(&b); err != nil {
119✔
4003
                        return err
×
4004
                }
×
4005

4006
                // Finally add the closed outpoint and tlv stream to the index.
4007
                if err := opBucket.Put(chanPointBuf.Bytes(), b.Bytes()); err != nil {
119✔
4008
                        return err
×
4009
                }
×
4010

4011
                // Add channel state to the historical channel bucket.
4012
                historicalBucket, err := tx.CreateTopLevelBucket(
119✔
4013
                        historicalChannelBucket,
119✔
4014
                )
119✔
4015
                if err != nil {
119✔
4016
                        return err
×
4017
                }
×
4018

4019
                historicalChanBucket, err :=
119✔
4020
                        historicalBucket.CreateBucketIfNotExists(chanKey)
119✔
4021
                if err != nil {
119✔
4022
                        return err
×
4023
                }
×
4024

4025
                // Apply any additional statuses to the channel state.
4026
                for _, status := range statuses {
127✔
4027
                        chanState.chanStatus |= status
8✔
4028
                }
8✔
4029

4030
                err = putOpenChannel(historicalChanBucket, chanState)
119✔
4031
                if err != nil {
119✔
4032
                        return err
×
4033
                }
×
4034

4035
                // Finally, create a summary of this channel in the closed
4036
                // channel bucket for this node.
4037
                return putChannelCloseSummary(
119✔
4038
                        tx, chanPointBuf.Bytes(), summary, chanState,
119✔
4039
                )
119✔
4040
        }, func() {})
119✔
4041
}
4042

4043
// ChannelSnapshot is a frozen snapshot of the current channel state. A
4044
// snapshot is detached from the original channel that generated it, providing
4045
// read-only access to the current or prior state of an active channel.
4046
//
4047
// TODO(roasbeef): remove all together? pretty much just commitment
4048
type ChannelSnapshot struct {
4049
        // RemoteIdentity is the identity public key of the remote node that we
4050
        // are maintaining the open channel with.
4051
        RemoteIdentity btcec.PublicKey
4052

4053
        // ChanPoint is the outpoint that created the channel. This output is
4054
        // found within the funding transaction and uniquely identified the
4055
        // channel on the resident chain.
4056
        ChannelPoint wire.OutPoint
4057

4058
        // ChainHash is the genesis hash of the chain that the channel resides
4059
        // within.
4060
        ChainHash chainhash.Hash
4061

4062
        // Capacity is the total capacity of the channel.
4063
        Capacity btcutil.Amount
4064

4065
        // TotalMSatSent is the total number of milli-satoshis we've sent
4066
        // within this channel.
4067
        TotalMSatSent lnwire.MilliSatoshi
4068

4069
        // TotalMSatReceived is the total number of milli-satoshis we've
4070
        // received within this channel.
4071
        TotalMSatReceived lnwire.MilliSatoshi
4072

4073
        // ChannelCommitment is the current up-to-date commitment for the
4074
        // target channel.
4075
        ChannelCommitment
4076
}
4077

4078
// Snapshot returns a read-only snapshot of the current channel state. This
4079
// snapshot includes information concerning the current settled balance within
4080
// the channel, metadata detailing total flows, and any outstanding HTLCs.
4081
func (c *OpenChannel) Snapshot() *ChannelSnapshot {
75✔
4082
        c.RLock()
75✔
4083
        defer c.RUnlock()
75✔
4084

75✔
4085
        localCommit := c.LocalCommitment
75✔
4086
        snapshot := &ChannelSnapshot{
75✔
4087
                RemoteIdentity:    *c.IdentityPub,
75✔
4088
                ChannelPoint:      c.FundingOutpoint,
75✔
4089
                Capacity:          c.Capacity,
75✔
4090
                TotalMSatSent:     c.TotalMSatSent,
75✔
4091
                TotalMSatReceived: c.TotalMSatReceived,
75✔
4092
                ChainHash:         c.ChainHash,
75✔
4093
                ChannelCommitment: ChannelCommitment{
75✔
4094
                        LocalBalance:  localCommit.LocalBalance,
75✔
4095
                        RemoteBalance: localCommit.RemoteBalance,
75✔
4096
                        CommitHeight:  localCommit.CommitHeight,
75✔
4097
                        CommitFee:     localCommit.CommitFee,
75✔
4098
                },
75✔
4099
        }
75✔
4100

75✔
4101
        localCommit.CustomBlob.WhenSome(func(blob tlv.Blob) {
75✔
4102
                blobCopy := make([]byte, len(blob))
×
4103
                copy(blobCopy, blob)
×
4104

×
4105
                snapshot.ChannelCommitment.CustomBlob = fn.Some(blobCopy)
×
4106
        })
×
4107

4108
        // Copy over the current set of HTLCs to ensure the caller can't mutate
4109
        // our internal state.
4110
        snapshot.Htlcs = make([]HTLC, len(localCommit.Htlcs))
75✔
4111
        for i, h := range localCommit.Htlcs {
347✔
4112
                snapshot.Htlcs[i] = h.Copy()
272✔
4113
        }
272✔
4114

4115
        return snapshot
75✔
4116
}
4117

4118
// LatestCommitments returns the two latest commitments for both the local and
4119
// remote party. These commitments are read from disk to ensure that only the
4120
// latest fully committed state is returned. The first commitment returned is
4121
// the local commitment, and the second returned is the remote commitment.
4122
func (c *OpenChannel) LatestCommitments() (*ChannelCommitment, *ChannelCommitment, error) {
18✔
4123
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
36✔
4124
                chanBucket, err := fetchChanBucket(
18✔
4125
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
18✔
4126
                )
18✔
4127
                if err != nil {
18✔
4128
                        return err
×
4129
                }
×
4130

4131
                return fetchChanCommitments(chanBucket, c)
18✔
4132
        }, func() {})
18✔
4133
        if err != nil {
18✔
4134
                return nil, nil, err
×
4135
        }
×
4136

4137
        return &c.LocalCommitment, &c.RemoteCommitment, nil
18✔
4138
}
4139

4140
// RemoteRevocationStore returns the most up to date commitment version of the
4141
// revocation storage tree for the remote party. This method can be used when
4142
// acting on a possible contract breach to ensure, that the caller has the most
4143
// up to date information required to deliver justice.
4144
func (c *OpenChannel) RemoteRevocationStore() (shachain.Store, error) {
18✔
4145
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
36✔
4146
                chanBucket, err := fetchChanBucket(
18✔
4147
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
18✔
4148
                )
18✔
4149
                if err != nil {
18✔
4150
                        return err
×
4151
                }
×
4152

4153
                return fetchChanRevocationState(chanBucket, c)
18✔
4154
        }, func() {})
18✔
4155
        if err != nil {
18✔
4156
                return nil, err
×
4157
        }
×
4158

4159
        return c.RevocationStore, nil
18✔
4160
}
4161

4162
// AbsoluteThawHeight determines a frozen channel's absolute thaw height. If the
4163
// channel is not frozen, then 0 is returned.
4164
func (c *OpenChannel) AbsoluteThawHeight() (uint32, error) {
3✔
4165
        // Only frozen channels have a thaw height.
3✔
4166
        if !c.ChanType.IsFrozen() && !c.ChanType.HasLeaseExpiration() {
6✔
4167
                return 0, nil
3✔
4168
        }
3✔
4169

4170
        // If the channel has the frozen bit set and it's thaw height is below
4171
        // the absolute threshold, then it's interpreted as a relative height to
4172
        // the chain's current height.
4173
        if c.ChanType.IsFrozen() && c.ThawHeight < AbsoluteThawHeightThreshold {
6✔
4174
                // We'll only known of the channel's short ID once it's
3✔
4175
                // confirmed.
3✔
4176
                if c.IsPending {
3✔
4177
                        return 0, errors.New("cannot use relative thaw " +
×
4178
                                "height for unconfirmed channel")
×
4179
                }
×
4180

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

3✔
4184
                // If this is a zero-conf channel, the ShortChannelID will be
3✔
4185
                // an alias.
3✔
4186
                if c.IsZeroConf() {
3✔
4187
                        if !c.ZeroConfConfirmed() {
×
4188
                                return 0, errors.New("cannot use relative " +
×
4189
                                        "height for unconfirmed zero-conf " +
×
4190
                                        "channel")
×
4191
                        }
×
4192

4193
                        // Use the confirmed SCID's BlockHeight.
4194
                        blockHeightBase = c.confirmedScid.BlockHeight
×
4195
                }
4196

4197
                return blockHeightBase + c.ThawHeight, nil
3✔
4198
        }
4199

4200
        return c.ThawHeight, nil
×
4201
}
4202

4203
// DeriveHeightHint derives the block height for the channel opening.
4204
func (c *OpenChannel) DeriveHeightHint() uint32 {
29✔
4205
        // As a height hint, we'll try to use the opening height, but if the
29✔
4206
        // channel isn't yet open, then we'll use the height it was broadcast
29✔
4207
        // at. This may be an unconfirmed zero-conf channel.
29✔
4208
        heightHint := c.ShortChanID().BlockHeight
29✔
4209
        if heightHint == 0 {
32✔
4210
                heightHint = c.BroadcastHeight()
3✔
4211
        }
3✔
4212

4213
        // Since no zero-conf state is stored in a channel backup, the below
4214
        // logic will not be triggered for restored, zero-conf channels. Set
4215
        // the height hint for zero-conf channels.
4216
        if c.IsZeroConf() {
32✔
4217
                if c.ZeroConfConfirmed() {
6✔
4218
                        // If the zero-conf channel is confirmed, we'll use the
3✔
4219
                        // confirmed SCID's block height.
3✔
4220
                        heightHint = c.ZeroConfRealScid().BlockHeight
3✔
4221
                } else {
6✔
4222
                        // The zero-conf channel is unconfirmed. We'll need to
3✔
4223
                        // use the FundingBroadcastHeight.
3✔
4224
                        heightHint = c.BroadcastHeight()
3✔
4225
                }
3✔
4226
        }
4227

4228
        return heightHint
29✔
4229
}
4230

4231
func putChannelCloseSummary(tx kvdb.RwTx, chanID []byte,
4232
        summary *ChannelCloseSummary, lastChanState *OpenChannel) error {
119✔
4233

119✔
4234
        closedChanBucket, err := tx.CreateTopLevelBucket(closedChannelBucket)
119✔
4235
        if err != nil {
119✔
4236
                return err
×
4237
        }
×
4238

4239
        summary.RemoteCurrentRevocation = lastChanState.RemoteCurrentRevocation
119✔
4240
        summary.RemoteNextRevocation = lastChanState.RemoteNextRevocation
119✔
4241
        summary.LocalChanConfig = lastChanState.LocalChanCfg
119✔
4242

119✔
4243
        var b bytes.Buffer
119✔
4244
        if err := serializeChannelCloseSummary(&b, summary); err != nil {
119✔
4245
                return err
×
4246
        }
×
4247

4248
        return closedChanBucket.Put(chanID, b.Bytes())
119✔
4249
}
4250

4251
func serializeChannelCloseSummary(w io.Writer, cs *ChannelCloseSummary) error {
126✔
4252
        err := WriteElements(w,
126✔
4253
                cs.ChanPoint, cs.ShortChanID, cs.ChainHash, cs.ClosingTXID,
126✔
4254
                cs.CloseHeight, cs.RemotePub, cs.Capacity, cs.SettledBalance,
126✔
4255
                cs.TimeLockedBalance, cs.CloseType, cs.IsPending,
126✔
4256
        )
126✔
4257
        if err != nil {
126✔
4258
                return err
×
4259
        }
×
4260

4261
        // If this is a close channel summary created before the addition of
4262
        // the new fields, then we can exit here.
4263
        if cs.RemoteCurrentRevocation == nil {
126✔
4264
                return WriteElements(w, false)
×
4265
        }
×
4266

4267
        // If fields are present, write boolean to indicate this, and continue.
4268
        if err := WriteElements(w, true); err != nil {
126✔
4269
                return err
×
4270
        }
×
4271

4272
        if err := WriteElements(w, cs.RemoteCurrentRevocation); err != nil {
126✔
4273
                return err
×
4274
        }
×
4275

4276
        if err := writeChanConfig(w, &cs.LocalChanConfig); err != nil {
126✔
4277
                return err
×
4278
        }
×
4279

4280
        // The RemoteNextRevocation field is optional, as it's possible for a
4281
        // channel to be closed before we learn of the next unrevoked
4282
        // revocation point for the remote party. Write a boolean indicating
4283
        // whether this field is present or not.
4284
        if err := WriteElements(w, cs.RemoteNextRevocation != nil); err != nil {
126✔
4285
                return err
×
4286
        }
×
4287

4288
        // Write the field, if present.
4289
        if cs.RemoteNextRevocation != nil {
250✔
4290
                if err = WriteElements(w, cs.RemoteNextRevocation); err != nil {
124✔
4291
                        return err
×
4292
                }
×
4293
        }
4294

4295
        // Write whether the channel sync message is present.
4296
        if err := WriteElements(w, cs.LastChanSyncMsg != nil); err != nil {
126✔
4297
                return err
×
4298
        }
×
4299

4300
        // Write the channel sync message, if present.
4301
        if cs.LastChanSyncMsg != nil {
129✔
4302
                if err := WriteElements(w, cs.LastChanSyncMsg); err != nil {
3✔
4303
                        return err
×
4304
                }
×
4305
        }
4306

4307
        return nil
126✔
4308
}
4309

4310
func deserializeCloseChannelSummary(r io.Reader) (*ChannelCloseSummary, error) {
133✔
4311
        c := &ChannelCloseSummary{}
133✔
4312

133✔
4313
        err := ReadElements(r,
133✔
4314
                &c.ChanPoint, &c.ShortChanID, &c.ChainHash, &c.ClosingTXID,
133✔
4315
                &c.CloseHeight, &c.RemotePub, &c.Capacity, &c.SettledBalance,
133✔
4316
                &c.TimeLockedBalance, &c.CloseType, &c.IsPending,
133✔
4317
        )
133✔
4318
        if err != nil {
133✔
4319
                return nil, err
×
4320
        }
×
4321

4322
        // We'll now check to see if the channel close summary was encoded with
4323
        // any of the additional optional fields.
4324
        var hasNewFields bool
133✔
4325
        err = ReadElements(r, &hasNewFields)
133✔
4326
        if err != nil {
133✔
4327
                return nil, err
×
4328
        }
×
4329

4330
        // If fields are not present, we can return.
4331
        if !hasNewFields {
141✔
4332
                return c, nil
8✔
4333
        }
8✔
4334

4335
        // Otherwise read the new fields.
4336
        if err := ReadElements(r, &c.RemoteCurrentRevocation); err != nil {
125✔
4337
                return nil, err
×
4338
        }
×
4339

4340
        if err := readChanConfig(r, &c.LocalChanConfig); err != nil {
125✔
4341
                return nil, err
×
4342
        }
×
4343

4344
        // Finally, we'll attempt to read the next unrevoked commitment point
4345
        // for the remote party. If we closed the channel before receiving a
4346
        // channel_ready message then this might not be present. A boolean
4347
        // indicating whether the field is present will come first.
4348
        var hasRemoteNextRevocation bool
125✔
4349
        err = ReadElements(r, &hasRemoteNextRevocation)
125✔
4350
        if err != nil {
125✔
4351
                return nil, err
×
4352
        }
×
4353

4354
        // If this field was written, read it.
4355
        if hasRemoteNextRevocation {
250✔
4356
                err = ReadElements(r, &c.RemoteNextRevocation)
125✔
4357
                if err != nil {
125✔
4358
                        return nil, err
×
4359
                }
×
4360
        }
4361

4362
        // Check if we have a channel sync message to read.
4363
        var hasChanSyncMsg bool
125✔
4364
        err = ReadElements(r, &hasChanSyncMsg)
125✔
4365
        if err == io.EOF {
125✔
4366
                return c, nil
×
4367
        } else if err != nil {
125✔
4368
                return nil, err
×
4369
        }
×
4370

4371
        // If a chan sync message is present, read it.
4372
        if hasChanSyncMsg {
128✔
4373
                // We must pass in reference to a lnwire.Message for the codec
3✔
4374
                // to support it.
3✔
4375
                var msg lnwire.Message
3✔
4376
                if err := ReadElements(r, &msg); err != nil {
3✔
4377
                        return nil, err
×
4378
                }
×
4379

4380
                chanSync, ok := msg.(*lnwire.ChannelReestablish)
3✔
4381
                if !ok {
3✔
4382
                        return nil, errors.New("unable cast db Message to " +
×
4383
                                "ChannelReestablish")
×
4384
                }
×
4385
                c.LastChanSyncMsg = chanSync
3✔
4386
        }
4387

4388
        return c, nil
125✔
4389
}
4390

4391
func writeChanConfig(b io.Writer, c *ChannelConfig) error {
6,892✔
4392
        return WriteElements(b,
6,892✔
4393
                c.DustLimit, c.MaxPendingAmount, c.ChanReserve, c.MinHTLC,
6,892✔
4394
                c.MaxAcceptedHtlcs, c.CsvDelay, c.MultiSigKey,
6,892✔
4395
                c.RevocationBasePoint, c.PaymentBasePoint, c.DelayBasePoint,
6,892✔
4396
                c.HtlcBasePoint,
6,892✔
4397
        )
6,892✔
4398
}
6,892✔
4399

4400
// fundingTxPresent returns true if expect the funding transcation to be found
4401
// on disk or already populated within the passed open channel struct.
4402
func fundingTxPresent(channel *OpenChannel) bool {
10,899✔
4403
        chanType := channel.ChanType
10,899✔
4404

10,899✔
4405
        return chanType.IsSingleFunder() && chanType.HasFundingTx() &&
10,899✔
4406
                channel.IsInitiator &&
10,899✔
4407
                !channel.hasChanStatus(ChanStatusRestored)
10,899✔
4408
}
10,899✔
4409

4410
func putChanInfo(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
3,386✔
4411
        var w bytes.Buffer
3,386✔
4412
        if err := WriteElements(&w,
3,386✔
4413
                channel.ChanType, channel.ChainHash, channel.FundingOutpoint,
3,386✔
4414
                channel.ShortChannelID, channel.IsPending, channel.IsInitiator,
3,386✔
4415
                channel.chanStatus, channel.FundingBroadcastHeight,
3,386✔
4416
                channel.NumConfsRequired, channel.ChannelFlags,
3,386✔
4417
                channel.IdentityPub, channel.Capacity, channel.TotalMSatSent,
3,386✔
4418
                channel.TotalMSatReceived,
3,386✔
4419
        ); err != nil {
3,386✔
4420
                return err
×
4421
        }
×
4422

4423
        // For single funder channels that we initiated, and we have the
4424
        // funding transaction, then write the funding txn.
4425
        if fundingTxPresent(channel) {
5,352✔
4426
                if err := WriteElement(&w, channel.FundingTxn); err != nil {
1,966✔
4427
                        return err
×
4428
                }
×
4429
        }
4430

4431
        if err := writeChanConfig(&w, &channel.LocalChanCfg); err != nil {
3,386✔
4432
                return err
×
4433
        }
×
4434
        if err := writeChanConfig(&w, &channel.RemoteChanCfg); err != nil {
3,386✔
4435
                return err
×
4436
        }
×
4437

4438
        auxData := channel.extractTlvData()
3,386✔
4439
        if err := auxData.encode(&w); err != nil {
3,386✔
4440
                return fmt.Errorf("unable to encode aux data: %w", err)
×
4441
        }
×
4442

4443
        if err := chanBucket.Put(chanInfoKey, w.Bytes()); err != nil {
3,386✔
4444
                return err
×
4445
        }
×
4446

4447
        // Finally, add optional shutdown scripts for the local and remote peer if
4448
        // they are present.
4449
        if err := putOptionalUpfrontShutdownScript(
3,386✔
4450
                chanBucket, localUpfrontShutdownKey, channel.LocalShutdownScript,
3,386✔
4451
        ); err != nil {
3,386✔
4452
                return err
×
4453
        }
×
4454

4455
        return putOptionalUpfrontShutdownScript(
3,386✔
4456
                chanBucket, remoteUpfrontShutdownKey, channel.RemoteShutdownScript,
3,386✔
4457
        )
3,386✔
4458
}
4459

4460
// putOptionalUpfrontShutdownScript adds a shutdown script under the key
4461
// provided if it has a non-zero length.
4462
func putOptionalUpfrontShutdownScript(chanBucket kvdb.RwBucket, key []byte,
4463
        script []byte) error {
6,769✔
4464
        // If the script is empty, we do not need to add anything.
6,769✔
4465
        if len(script) == 0 {
13,528✔
4466
                return nil
6,759✔
4467
        }
6,759✔
4468

4469
        var w bytes.Buffer
13✔
4470
        if err := WriteElement(&w, script); err != nil {
13✔
4471
                return err
×
4472
        }
×
4473

4474
        return chanBucket.Put(key, w.Bytes())
13✔
4475
}
4476

4477
// getOptionalUpfrontShutdownScript reads the shutdown script stored under the
4478
// key provided if it is present. Upfront shutdown scripts are optional, so the
4479
// function returns with no error if the key is not present.
4480
func getOptionalUpfrontShutdownScript(chanBucket kvdb.RBucket, key []byte,
4481
        script *lnwire.DeliveryAddress) error {
15,029✔
4482

15,029✔
4483
        // Return early if the bucket does not exit, a shutdown script was not set.
15,029✔
4484
        bs := chanBucket.Get(key)
15,029✔
4485
        if bs == nil {
30,054✔
4486
                return nil
15,025✔
4487
        }
15,025✔
4488

4489
        var tempScript []byte
7✔
4490
        r := bytes.NewReader(bs)
7✔
4491
        if err := ReadElement(r, &tempScript); err != nil {
7✔
4492
                return err
×
4493
        }
×
4494
        *script = tempScript
7✔
4495

7✔
4496
        return nil
7✔
4497
}
4498

4499
func serializeChanCommit(w io.Writer, c *ChannelCommitment) error {
8,870✔
4500
        if err := WriteElements(w,
8,870✔
4501
                c.CommitHeight, c.LocalLogIndex, c.LocalHtlcIndex,
8,870✔
4502
                c.RemoteLogIndex, c.RemoteHtlcIndex, c.LocalBalance,
8,870✔
4503
                c.RemoteBalance, c.CommitFee, c.FeePerKw, c.CommitTx,
8,870✔
4504
                c.CommitSig,
8,870✔
4505
        ); err != nil {
8,870✔
4506
                return err
×
4507
        }
×
4508

4509
        return SerializeHtlcs(w, c.Htlcs...)
8,870✔
4510
}
4511

4512
func putChanCommitment(chanBucket kvdb.RwBucket, c *ChannelCommitment,
4513
        local bool) error {
6,725✔
4514

6,725✔
4515
        var commitKey []byte
6,725✔
4516
        if local {
10,110✔
4517
                commitKey = append(chanCommitmentKey, byte(0x00))
3,385✔
4518
        } else {
6,728✔
4519
                commitKey = append(chanCommitmentKey, byte(0x01))
3,343✔
4520
        }
3,343✔
4521

4522
        var b bytes.Buffer
6,725✔
4523
        if err := serializeChanCommit(&b, c); err != nil {
6,725✔
4524
                return err
×
4525
        }
×
4526

4527
        // Before we write to disk, we'll also write our aux data as well.
4528
        auxData := c.extractTlvData()
6,725✔
4529
        if err := auxData.encode(&b); err != nil {
6,725✔
4530
                return fmt.Errorf("unable to write aux data: %w", err)
×
4531
        }
×
4532

4533
        return chanBucket.Put(commitKey, b.Bytes())
6,725✔
4534
}
4535

4536
func putChanCommitments(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
1,290✔
4537
        // If this is a restored channel, then we don't have any commitments to
1,290✔
4538
        // write.
1,290✔
4539
        if channel.hasChanStatus(ChanStatusRestored) {
1,294✔
4540
                return nil
4✔
4541
        }
4✔
4542

4543
        err := putChanCommitment(
1,289✔
4544
                chanBucket, &channel.LocalCommitment, true,
1,289✔
4545
        )
1,289✔
4546
        if err != nil {
1,289✔
4547
                return err
×
4548
        }
×
4549

4550
        return putChanCommitment(
1,289✔
4551
                chanBucket, &channel.RemoteCommitment, false,
1,289✔
4552
        )
1,289✔
4553
}
4554

4555
func putChanRevocationState(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
3,980✔
4556
        var b bytes.Buffer
3,980✔
4557
        err := WriteElements(
3,980✔
4558
                &b, channel.RemoteCurrentRevocation, channel.RevocationProducer,
3,980✔
4559
                channel.RevocationStore,
3,980✔
4560
        )
3,980✔
4561
        if err != nil {
3,980✔
4562
                return err
×
4563
        }
×
4564

4565
        // If the next revocation is present, which is only the case after the
4566
        // ChannelReady message has been sent, then we'll write it to disk.
4567
        if channel.RemoteNextRevocation != nil {
7,151✔
4568
                err = WriteElements(&b, channel.RemoteNextRevocation)
3,171✔
4569
                if err != nil {
3,171✔
4570
                        return err
×
4571
                }
×
4572
        }
4573

4574
        return chanBucket.Put(revocationStateKey, b.Bytes())
3,980✔
4575
}
4576

4577
func readChanConfig(b io.Reader, c *ChannelConfig) error {
15,151✔
4578
        return ReadElements(b,
15,151✔
4579
                &c.DustLimit, &c.MaxPendingAmount, &c.ChanReserve,
15,151✔
4580
                &c.MinHTLC, &c.MaxAcceptedHtlcs, &c.CsvDelay,
15,151✔
4581
                &c.MultiSigKey, &c.RevocationBasePoint,
15,151✔
4582
                &c.PaymentBasePoint, &c.DelayBasePoint,
15,151✔
4583
                &c.HtlcBasePoint,
15,151✔
4584
        )
15,151✔
4585
}
15,151✔
4586

4587
func fetchChanInfo(chanBucket kvdb.RBucket, channel *OpenChannel) error {
7,516✔
4588
        infoBytes := chanBucket.Get(chanInfoKey)
7,516✔
4589
        if infoBytes == nil {
7,516✔
4590
                return ErrNoChanInfoFound
×
4591
        }
×
4592
        r := bytes.NewReader(infoBytes)
7,516✔
4593

7,516✔
4594
        if err := ReadElements(r,
7,516✔
4595
                &channel.ChanType, &channel.ChainHash, &channel.FundingOutpoint,
7,516✔
4596
                &channel.ShortChannelID, &channel.IsPending, &channel.IsInitiator,
7,516✔
4597
                &channel.chanStatus, &channel.FundingBroadcastHeight,
7,516✔
4598
                &channel.NumConfsRequired, &channel.ChannelFlags,
7,516✔
4599
                &channel.IdentityPub, &channel.Capacity, &channel.TotalMSatSent,
7,516✔
4600
                &channel.TotalMSatReceived,
7,516✔
4601
        ); err != nil {
7,516✔
4602
                return err
×
4603
        }
×
4604

4605
        // For single funder channels that we initiated and have the funding
4606
        // transaction to, read the funding txn.
4607
        if fundingTxPresent(channel) {
11,503✔
4608
                if err := ReadElement(r, &channel.FundingTxn); err != nil {
3,987✔
4609
                        return err
×
4610
                }
×
4611
        }
4612

4613
        if err := readChanConfig(r, &channel.LocalChanCfg); err != nil {
7,516✔
4614
                return err
×
4615
        }
×
4616
        if err := readChanConfig(r, &channel.RemoteChanCfg); err != nil {
7,516✔
4617
                return err
×
4618
        }
×
4619

4620
        // Retrieve the boolean stored under lastWasRevokeKey.
4621
        lastWasRevokeBytes := chanBucket.Get(lastWasRevokeKey)
7,516✔
4622
        if lastWasRevokeBytes == nil {
8,938✔
4623
                // If nothing has been stored under this key, we store false in the
1,422✔
4624
                // OpenChannel struct.
1,422✔
4625
                channel.LastWasRevoke = false
1,422✔
4626
        } else {
7,519✔
4627
                // Otherwise, read the value into the LastWasRevoke field.
6,097✔
4628
                revokeReader := bytes.NewReader(lastWasRevokeBytes)
6,097✔
4629
                err := ReadElements(revokeReader, &channel.LastWasRevoke)
6,097✔
4630
                if err != nil {
6,097✔
4631
                        return err
×
4632
                }
×
4633
        }
4634

4635
        var auxData openChannelTlvData
7,516✔
4636
        if err := auxData.decode(r); err != nil {
7,516✔
4637
                return fmt.Errorf("unable to decode aux data: %w", err)
×
4638
        }
×
4639

4640
        // Assign all the relevant fields from the aux data into the actual
4641
        // open channel.
4642
        channel.amendTlvData(auxData)
7,516✔
4643

7,516✔
4644
        channel.Packager = NewChannelPackager(channel.ShortChannelID)
7,516✔
4645

7,516✔
4646
        // Finally, read the optional shutdown scripts.
7,516✔
4647
        if err := getOptionalUpfrontShutdownScript(
7,516✔
4648
                chanBucket, localUpfrontShutdownKey, &channel.LocalShutdownScript,
7,516✔
4649
        ); err != nil {
7,516✔
4650
                return err
×
4651
        }
×
4652

4653
        return getOptionalUpfrontShutdownScript(
7,516✔
4654
                chanBucket, remoteUpfrontShutdownKey, &channel.RemoteShutdownScript,
7,516✔
4655
        )
7,516✔
4656
}
4657

4658
func deserializeChanCommit(r io.Reader) (ChannelCommitment, error) {
17,195✔
4659
        var c ChannelCommitment
17,195✔
4660

17,195✔
4661
        err := ReadElements(r,
17,195✔
4662
                &c.CommitHeight, &c.LocalLogIndex, &c.LocalHtlcIndex, &c.RemoteLogIndex,
17,195✔
4663
                &c.RemoteHtlcIndex, &c.LocalBalance, &c.RemoteBalance,
17,195✔
4664
                &c.CommitFee, &c.FeePerKw, &c.CommitTx, &c.CommitSig,
17,195✔
4665
        )
17,195✔
4666
        if err != nil {
17,195✔
4667
                return c, err
×
4668
        }
×
4669

4670
        c.Htlcs, err = DeserializeHtlcs(r)
17,195✔
4671
        if err != nil {
17,195✔
4672
                return c, err
×
4673
        }
×
4674

4675
        return c, nil
17,195✔
4676
}
4677

4678
func fetchChanCommitment(chanBucket kvdb.RBucket,
4679
        local bool) (ChannelCommitment, error) {
15,056✔
4680

15,056✔
4681
        var commitKey []byte
15,056✔
4682
        if local {
22,586✔
4683
                commitKey = append(chanCommitmentKey, byte(0x00))
7,530✔
4684
        } else {
15,059✔
4685
                commitKey = append(chanCommitmentKey, byte(0x01))
7,529✔
4686
        }
7,529✔
4687

4688
        commitBytes := chanBucket.Get(commitKey)
15,056✔
4689
        if commitBytes == nil {
15,056✔
4690
                return ChannelCommitment{}, ErrNoCommitmentsFound
×
4691
        }
×
4692

4693
        r := bytes.NewReader(commitBytes)
15,056✔
4694
        chanCommit, err := deserializeChanCommit(r)
15,056✔
4695
        if err != nil {
15,056✔
4696
                return ChannelCommitment{}, fmt.Errorf("unable to decode "+
×
4697
                        "chan commit: %w", err)
×
4698
        }
×
4699

4700
        // We'll also check to see if we have any aux data stored as the end of
4701
        // the stream.
4702
        var auxData commitTlvData
15,056✔
4703
        if err := auxData.decode(r); err != nil {
15,056✔
4704
                return ChannelCommitment{}, fmt.Errorf("unable to decode "+
×
4705
                        "chan aux data: %w", err)
×
4706
        }
×
4707

4708
        chanCommit.amendTlvData(auxData)
15,056✔
4709

15,056✔
4710
        return chanCommit, nil
15,056✔
4711
}
4712

4713
func fetchChanCommitments(chanBucket kvdb.RBucket, channel *OpenChannel) error {
7,531✔
4714
        var err error
7,531✔
4715

7,531✔
4716
        // If this is a restored channel, then we don't have any commitments to
7,531✔
4717
        // read.
7,531✔
4718
        if channel.hasChanStatus(ChanStatusRestored) {
7,536✔
4719
                return nil
5✔
4720
        }
5✔
4721

4722
        channel.LocalCommitment, err = fetchChanCommitment(chanBucket, true)
7,529✔
4723
        if err != nil {
7,529✔
4724
                return err
×
4725
        }
×
4726
        channel.RemoteCommitment, err = fetchChanCommitment(chanBucket, false)
7,529✔
4727
        if err != nil {
7,529✔
4728
                return err
×
4729
        }
×
4730

4731
        return nil
7,529✔
4732
}
4733

4734
func fetchChanRevocationState(chanBucket kvdb.RBucket, channel *OpenChannel) error {
7,531✔
4735
        revBytes := chanBucket.Get(revocationStateKey)
7,531✔
4736
        if revBytes == nil {
7,531✔
4737
                return ErrNoRevocationsFound
×
4738
        }
×
4739
        r := bytes.NewReader(revBytes)
7,531✔
4740

7,531✔
4741
        err := ReadElements(
7,531✔
4742
                r, &channel.RemoteCurrentRevocation, &channel.RevocationProducer,
7,531✔
4743
                &channel.RevocationStore,
7,531✔
4744
        )
7,531✔
4745
        if err != nil {
7,531✔
4746
                return err
×
4747
        }
×
4748

4749
        // If there aren't any bytes left in the buffer, then we don't yet have
4750
        // the next remote revocation, so we can exit early here.
4751
        if r.Len() == 0 {
7,806✔
4752
                return nil
275✔
4753
        }
275✔
4754

4755
        // Otherwise we'll read the next revocation for the remote party which
4756
        // is always the last item within the buffer.
4757
        return ReadElements(r, &channel.RemoteNextRevocation)
7,259✔
4758
}
4759

4760
func deleteOpenChannel(chanBucket kvdb.RwBucket) error {
119✔
4761
        if err := chanBucket.Delete(chanInfoKey); err != nil {
119✔
4762
                return err
×
4763
        }
×
4764

4765
        err := chanBucket.Delete(append(chanCommitmentKey, byte(0x00)))
119✔
4766
        if err != nil {
119✔
4767
                return err
×
4768
        }
×
4769
        err = chanBucket.Delete(append(chanCommitmentKey, byte(0x01)))
119✔
4770
        if err != nil {
119✔
4771
                return err
×
4772
        }
×
4773

4774
        if err := chanBucket.Delete(revocationStateKey); err != nil {
119✔
4775
                return err
×
4776
        }
×
4777

4778
        if diff := chanBucket.Get(commitDiffKey); diff != nil {
122✔
4779
                return chanBucket.Delete(commitDiffKey)
3✔
4780
        }
3✔
4781

4782
        return nil
119✔
4783
}
4784

4785
// storePendingCleanup stores cleanup info for a channel to be processed at
4786
// startup. This is used by postgres backends to defer heavy deletion
4787
// operations.
4788
func storePendingCleanup(tx kvdb.RwTx, c *OpenChannel, nodePub []byte,
NEW
4789
        chanKey []byte) error {
×
NEW
4790

×
NEW
4791
        cleanupBucket, err := tx.CreateTopLevelBucket(pendingCleanupBucket)
×
NEW
4792
        if err != nil {
×
NEW
4793
                return err
×
NEW
4794
        }
×
4795

NEW
4796
        var nodePubKey [33]byte
×
NEW
4797
        copy(nodePubKey[:], nodePub)
×
NEW
4798

×
NEW
4799
        cleanupInfo := &PendingCleanupInfo{
×
NEW
4800
                ChanPoint:   c.FundingOutpoint,
×
NEW
4801
                ShortChanID: c.ShortChannelID,
×
NEW
4802
                NodePub:     nodePubKey,
×
NEW
4803
                ChainHash:   c.ChainHash,
×
NEW
4804
        }
×
NEW
4805

×
NEW
4806
        var cleanupBuf bytes.Buffer
×
NEW
4807
        if err := cleanupInfo.Encode(&cleanupBuf); err != nil {
×
NEW
4808
                return err
×
NEW
4809
        }
×
4810

NEW
4811
        return cleanupBucket.Put(chanKey, cleanupBuf.Bytes())
×
4812
}
4813

4814
// performImmediateCleanup handles the cleanup operations that are performed
4815
// immediately during channel close for non-postgres backends (bbolt, sqlite).
4816
// This includes wiping forwarding packages, deleting channel data, thaw height,
4817
// revocation logs, and the channel bucket itself.
4818
func performImmediateCleanup(tx kvdb.RwTx, chanState *OpenChannel,
4819
        chanBucket kvdb.RwBucket, chainBucket kvdb.RwBucket,
4820
        chanKey []byte) error {
119✔
4821

119✔
4822
        // Delete all the forwarding packages stored for this channel.
119✔
4823
        if err := chanState.Packager.Wipe(tx); err != nil {
119✔
NEW
4824
                return err
×
NEW
4825
        }
×
4826

4827
        // Purge the remaining channel metadata from the database.
4828
        if err := deleteOpenChannel(chanBucket); err != nil {
119✔
NEW
4829
                return err
×
NEW
4830
        }
×
4831

4832
        // Remove the channel from the frozen channel bucket if needed.
4833
        if chanState.ChanType.IsFrozen() ||
119✔
4834
                chanState.ChanType.HasLeaseExpiration() {
231✔
4835

112✔
4836
                if err := deleteThawHeight(chanBucket); err != nil {
112✔
NEW
4837
                        return err
×
NEW
4838
                }
×
4839
        }
4840

4841
        // Delete the information stored within the revocation log.
4842
        if err := deleteLogBucket(chanBucket); err != nil {
119✔
NEW
4843
                return err
×
NEW
4844
        }
×
4845

4846
        // Delete the channel bucket itself.
4847
        return chainBucket.DeleteNestedBucket(chanKey)
119✔
4848
}
4849

4850
// makeLogKey converts a uint64 into an 8 byte array.
4851
func makeLogKey(updateNum uint64) [8]byte {
10,343✔
4852
        var key [8]byte
10,343✔
4853
        byteOrder.PutUint64(key[:], updateNum)
10,343✔
4854
        return key
10,343✔
4855
}
10,343✔
4856

4857
func fetchThawHeight(chanBucket kvdb.RBucket) (uint32, error) {
350✔
4858
        var height uint32
350✔
4859

350✔
4860
        heightBytes := chanBucket.Get(frozenChanKey)
350✔
4861
        heightReader := bytes.NewReader(heightBytes)
350✔
4862

350✔
4863
        if err := ReadElements(heightReader, &height); err != nil {
350✔
4864
                return 0, err
×
4865
        }
×
4866

4867
        return height, nil
350✔
4868
}
4869

4870
func storeThawHeight(chanBucket kvdb.RwBucket, height uint32) error {
442✔
4871
        var heightBuf bytes.Buffer
442✔
4872
        if err := WriteElements(&heightBuf, height); err != nil {
442✔
4873
                return err
×
4874
        }
×
4875

4876
        return chanBucket.Put(frozenChanKey, heightBuf.Bytes())
442✔
4877
}
4878

4879
func deleteThawHeight(chanBucket kvdb.RwBucket) error {
112✔
4880
        return chanBucket.Delete(frozenChanKey)
112✔
4881
}
112✔
4882

4883
// keyLocRecord is a wrapper struct around keychain.KeyLocator to implement the
4884
// tlv.RecordProducer interface.
4885
type keyLocRecord struct {
4886
        keychain.KeyLocator
4887
}
4888

4889
// Record creates a Record out of a KeyLocator using the passed Type and the
4890
// EKeyLocator and DKeyLocator functions. The size will always be 8 as
4891
// KeyFamily is uint32 and the Index is uint32.
4892
//
4893
// NOTE: This is part of the tlv.RecordProducer interface.
4894
func (k *keyLocRecord) Record() tlv.Record {
10,899✔
4895
        // Note that we set the type here as zero, as when used with a
10,899✔
4896
        // tlv.RecordT, the type param will be used as the type.
10,899✔
4897
        return tlv.MakeStaticRecord(
10,899✔
4898
                0, &k.KeyLocator, 8, EKeyLocator, DKeyLocator,
10,899✔
4899
        )
10,899✔
4900
}
10,899✔
4901

4902
// EKeyLocator is an encoder for keychain.KeyLocator.
4903
func EKeyLocator(w io.Writer, val interface{}, buf *[8]byte) error {
3,387✔
4904
        if v, ok := val.(*keychain.KeyLocator); ok {
6,774✔
4905
                err := tlv.EUint32T(w, uint32(v.Family), buf)
3,387✔
4906
                if err != nil {
3,387✔
4907
                        return err
×
4908
                }
×
4909

4910
                return tlv.EUint32T(w, v.Index, buf)
3,387✔
4911
        }
4912
        return tlv.NewTypeForEncodingErr(val, "keychain.KeyLocator")
×
4913
}
4914

4915
// DKeyLocator is a decoder for keychain.KeyLocator.
4916
func DKeyLocator(r io.Reader, val interface{}, buf *[8]byte, l uint64) error {
7,517✔
4917
        if v, ok := val.(*keychain.KeyLocator); ok {
15,034✔
4918
                var family uint32
7,517✔
4919
                err := tlv.DUint32(r, &family, buf, 4)
7,517✔
4920
                if err != nil {
7,517✔
4921
                        return err
×
4922
                }
×
4923
                v.Family = keychain.KeyFamily(family)
7,517✔
4924

7,517✔
4925
                return tlv.DUint32(r, &v.Index, buf, 4)
7,517✔
4926
        }
4927
        return tlv.NewTypeForDecodingErr(val, "keychain.KeyLocator", l, 8)
×
4928
}
4929

4930
// ShutdownInfo contains various info about the shutdown initiation of a
4931
// channel.
4932
type ShutdownInfo struct {
4933
        // DeliveryScript is the address that we have included in any previous
4934
        // Shutdown message for a particular channel and so should include in
4935
        // any future re-sends of the Shutdown message.
4936
        DeliveryScript tlv.RecordT[tlv.TlvType0, lnwire.DeliveryAddress]
4937

4938
        // LocalInitiator is true if we sent a Shutdown message before ever
4939
        // receiving a Shutdown message from the remote peer.
4940
        LocalInitiator tlv.RecordT[tlv.TlvType1, bool]
4941
}
4942

4943
// NewShutdownInfo constructs a new ShutdownInfo object.
4944
func NewShutdownInfo(deliveryScript lnwire.DeliveryAddress,
4945
        locallyInitiated bool) *ShutdownInfo {
16✔
4946

16✔
4947
        return &ShutdownInfo{
16✔
4948
                DeliveryScript: tlv.NewRecordT[tlv.TlvType0](deliveryScript),
16✔
4949
                LocalInitiator: tlv.NewPrimitiveRecord[tlv.TlvType1](
16✔
4950
                        locallyInitiated,
16✔
4951
                ),
16✔
4952
        }
16✔
4953
}
16✔
4954

4955
// Closer identifies the ChannelParty that initiated the coop-closure process.
4956
func (s ShutdownInfo) Closer() lntypes.ChannelParty {
3✔
4957
        if s.LocalInitiator.Val {
6✔
4958
                return lntypes.Local
3✔
4959
        }
3✔
4960

4961
        return lntypes.Remote
3✔
4962
}
4963

4964
// encode serialises the ShutdownInfo to the given io.Writer.
4965
func (s *ShutdownInfo) encode(w io.Writer) error {
14✔
4966
        records := []tlv.Record{
14✔
4967
                s.DeliveryScript.Record(),
14✔
4968
                s.LocalInitiator.Record(),
14✔
4969
        }
14✔
4970

14✔
4971
        stream, err := tlv.NewStream(records...)
14✔
4972
        if err != nil {
14✔
4973
                return err
×
4974
        }
×
4975

4976
        return stream.Encode(w)
14✔
4977
}
4978

4979
// decodeShutdownInfo constructs a ShutdownInfo struct by decoding the given
4980
// byte slice.
4981
func decodeShutdownInfo(b []byte) (*ShutdownInfo, error) {
5✔
4982
        tlvStream := lnwire.ExtraOpaqueData(b)
5✔
4983

5✔
4984
        var info ShutdownInfo
5✔
4985
        records := []tlv.RecordProducer{
5✔
4986
                &info.DeliveryScript,
5✔
4987
                &info.LocalInitiator,
5✔
4988
        }
5✔
4989

5✔
4990
        _, err := tlvStream.ExtractRecords(records...)
5✔
4991

5✔
4992
        return &info, err
5✔
4993
}
5✔
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