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

lightningnetwork / lnd / 15838907453

24 Jun 2025 01:26AM UTC coverage: 57.079% (-11.1%) from 68.172%
15838907453

Pull #9982

github

web-flow
Merge e42780be2 into 45c15646c
Pull Request #9982: lnwire+lnwallet: add LocalNonces field for splice nonce coordination w/ taproot channels

103 of 167 new or added lines in 5 files covered. (61.68%)

30191 existing lines in 463 files now uncovered.

96331 of 168768 relevant lines covered (57.08%)

0.6 hits per line

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

71.77
/channeldb/channel.go
1
package channeldb
2

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

292
        return tlvStream.Encode(w)
1✔
293
}
294

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

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

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

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

330
        return nil
1✔
331
}
332

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

613
        return tlvStream.Encode(w)
1✔
614
}
615

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

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

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

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

636
        return nil
1✔
637
}
638

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1✔
732
        c.CustomBlob.WhenSome(func(blob tlv.Blob) {
1✔
UNCOV
733
                auxData.customBlob = tlv.SomeRecordT(
×
UNCOV
734
                        tlv.NewPrimitiveRecord[tlv.TlvType1](blob),
×
UNCOV
735
                )
×
UNCOV
736
        })
×
737

738
        return auxData
1✔
739
}
740

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1✔
842
        return statusStr
1✔
843
}
844

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1047
        sync.RWMutex
1048
}
1049

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

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

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

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

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

1✔
1079
        if c.IsInitiator {
2✔
1080
                return lntypes.Local
1✔
1081
        }
1✔
1082

1083
        return lntypes.Remote
1✔
1084
}
1085

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

1✔
1091
        return c.ShortChannelID
1✔
1092
}
1✔
1093

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

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

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

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

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

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

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

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

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

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

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

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

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

×
UNCOV
1152
        return c.putChanStatus(status)
×
UNCOV
1153
}
×
1154

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

×
UNCOV
1162
        return c.clearChanStatus(status)
×
UNCOV
1163
}
×
1164

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

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

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

1181
        return c.chanStatus&status == status
1✔
1182
}
1183

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

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

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

1✔
1197
        c.FundingBroadcastHeight = height
1✔
1198
}
1✔
1199

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

1✔
1211
        auxData.memo.WhenSomeV(func(memo []byte) {
2✔
1212
                c.Memo = memo
1✔
1213
        })
1✔
1214
        auxData.tapscriptRoot.WhenSomeV(func(h [32]byte) {
1✔
UNCOV
1215
                c.TapscriptRoot = fn.Some[chainhash.Hash](h)
×
UNCOV
1216
        })
×
1217
        auxData.customBlob.WhenSomeV(func(blob tlv.Blob) {
1✔
UNCOV
1218
                c.CustomBlob = fn.Some(blob)
×
UNCOV
1219
        })
×
1220
}
1221

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

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

1255
        return auxData
1✔
1256
}
1257

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

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

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

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

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

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

1297
        return nil
1✔
1298
}
1299

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

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

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

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

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

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

1342
        return chanBucket, nil
1✔
1343
}
1344

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

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

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

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

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

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

1389
        return chanBucket, nil
1✔
1390
}
1391

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

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

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

1409
        return chanBucket, nil
1✔
1410
}
1411

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

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

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

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

1441
        status := uint8(outpointOpen)
1✔
1442

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1✔
1535
        return nil
1✔
1536
}
1537

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

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

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

1559
                channel.confirmedScid = realScid
1✔
1560

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

1566
        c.confirmedScid = realScid
1✔
1567

1✔
1568
        return nil
1✔
1569
}
1570

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

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

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

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

1598
        c.ChanType |= ScidAliasFeatureBit
1✔
1599

1✔
1600
        return nil
1✔
1601
}
1602

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

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

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

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

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

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

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

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

UNCOV
1656
        return commitPoint, nil
×
1657
}
1658

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1839
                // Populate the legacy LocalNonce field for backwards compatibility.
1840
                nextTaprootNonce = lnwire.SomeMusig2Nonce(nextNonce.PubNonce)
1✔
1841

1✔
1842
                // Also populate the new LocalNonces field. For channel
1✔
1843
                // re-establishment, we use an empty hash as the key to indicate
1✔
1844
                // the primary commitment nonce.
1✔
1845
                noncesMap := make(map[chainhash.Hash]lnwire.Musig2Nonce)
1✔
1846
                noncesMap[chainhash.Hash{}] = nextNonce.PubNonce
1✔
1847
                nextLocalNonces = lnwire.SomeLocalNonces(
1✔
1848
                        lnwire.LocalNoncesData{NoncesMap: noncesMap},
1✔
1849
                )
1✔
1850
        }
1851

1852
        return &lnwire.ChannelReestablish{
1✔
1853
                ChanID: lnwire.NewChanIDFromOutPoint(
1✔
1854
                        c.FundingOutpoint,
1✔
1855
                ),
1✔
1856
                NextLocalCommitHeight:  nextLocalCommitHeight,
1✔
1857
                RemoteCommitTailHeight: remoteChainTipHeight,
1✔
1858
                LastRemoteCommitSecret: lastCommitSecret,
1✔
1859
                LocalUnrevokedCommitPoint: input.ComputeCommitmentPoint(
1✔
1860
                        currentCommitSecret[:],
1✔
1861
                ),
1✔
1862
                LocalNonce:  nextTaprootNonce,
1✔
1863
                LocalNonces: nextLocalNonces,
1✔
1864
        }, nil
1✔
1865
}
1866

1867
// MarkShutdownSent serialises and persist the given ShutdownInfo for this
1868
// channel. Persisting this info represents the fact that we have sent the
1869
// Shutdown message to the remote side and hence that we should re-transmit the
1870
// same Shutdown message on re-establish.
1871
func (c *OpenChannel) MarkShutdownSent(info *ShutdownInfo) error {
1✔
1872
        c.Lock()
1✔
1873
        defer c.Unlock()
1✔
1874

1✔
1875
        return c.storeShutdownInfo(info)
1✔
1876
}
1✔
1877

1878
// storeShutdownInfo serialises the ShutdownInfo and persists it under the
1879
// shutdownInfoKey.
1880
func (c *OpenChannel) storeShutdownInfo(info *ShutdownInfo) error {
1✔
1881
        var b bytes.Buffer
1✔
1882
        err := info.encode(&b)
1✔
1883
        if err != nil {
1✔
1884
                return err
×
1885
        }
×
1886

1887
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
1888
                chanBucket, err := fetchChanBucketRw(
1✔
1889
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
1890
                )
1✔
1891
                if err != nil {
1✔
1892
                        return err
×
1893
                }
×
1894

1895
                return chanBucket.Put(shutdownInfoKey, b.Bytes())
1✔
1896
        }, func() {})
1✔
1897
}
1898

1899
// ShutdownInfo decodes the shutdown info stored for this channel and returns
1900
// the result. If no shutdown info has been persisted for this channel then the
1901
// ErrNoShutdownInfo error is returned.
1902
func (c *OpenChannel) ShutdownInfo() (fn.Option[ShutdownInfo], error) {
1✔
1903
        c.RLock()
1✔
1904
        defer c.RUnlock()
1✔
1905

1✔
1906
        var shutdownInfo *ShutdownInfo
1✔
1907
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2✔
1908
                chanBucket, err := fetchChanBucket(
1✔
1909
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
1910
                )
1✔
1911
                switch {
1✔
1912
                case err == nil:
1✔
1913
                case errors.Is(err, ErrNoChanDBExists),
1914
                        errors.Is(err, ErrNoActiveChannels),
1915
                        errors.Is(err, ErrChannelNotFound):
1✔
1916

1✔
1917
                        return ErrNoShutdownInfo
1✔
1918
                default:
×
1919
                        return err
×
1920
                }
1921

1922
                shutdownInfoBytes := chanBucket.Get(shutdownInfoKey)
1✔
1923
                if shutdownInfoBytes == nil {
2✔
1924
                        return ErrNoShutdownInfo
1✔
1925
                }
1✔
1926

1927
                shutdownInfo, err = decodeShutdownInfo(shutdownInfoBytes)
1✔
1928

1✔
1929
                return err
1✔
1930
        }, func() {
1✔
1931
                shutdownInfo = nil
1✔
1932
        })
1✔
1933
        if err != nil {
2✔
1934
                return fn.None[ShutdownInfo](), err
1✔
1935
        }
1✔
1936

1937
        return fn.Some[ShutdownInfo](*shutdownInfo), nil
1✔
1938
}
1939

1940
// isBorked returns true if the channel has been marked as borked in the
1941
// database. This requires an existing database transaction to already be
1942
// active.
1943
//
1944
// NOTE: The primary mutex should already be held before this method is called.
1945
func (c *OpenChannel) isBorked(chanBucket kvdb.RBucket) (bool, error) {
1✔
1946
        channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
1✔
1947
        if err != nil {
1✔
1948
                return false, err
×
1949
        }
×
1950

1951
        return channel.chanStatus != ChanStatusDefault, nil
1✔
1952
}
1953

1954
// MarkCommitmentBroadcasted marks the channel as a commitment transaction has
1955
// been broadcast, either our own or the remote, and we should watch the chain
1956
// for it to confirm before taking any further action. It takes as argument the
1957
// closing tx _we believe_ will appear in the chain. This is only used to
1958
// republish this tx at startup to ensure propagation, and we should still
1959
// handle the case where a different tx actually hits the chain.
1960
func (c *OpenChannel) MarkCommitmentBroadcasted(closeTx *wire.MsgTx,
1961
        closer lntypes.ChannelParty) error {
1✔
1962

1✔
1963
        return c.markBroadcasted(
1✔
1964
                ChanStatusCommitBroadcasted, forceCloseTxKey, closeTx,
1✔
1965
                closer,
1✔
1966
        )
1✔
1967
}
1✔
1968

1969
// MarkCoopBroadcasted marks the channel to indicate that a cooperative close
1970
// transaction has been broadcast, either our own or the remote, and that we
1971
// should watch the chain for it to confirm before taking further action. It
1972
// takes as argument a cooperative close tx that could appear on chain, and
1973
// should be rebroadcast upon startup. This is only used to republish and
1974
// ensure propagation, and we should still handle the case where a different tx
1975
// actually hits the chain.
1976
func (c *OpenChannel) MarkCoopBroadcasted(closeTx *wire.MsgTx,
1977
        closer lntypes.ChannelParty) error {
1✔
1978

1✔
1979
        return c.markBroadcasted(
1✔
1980
                ChanStatusCoopBroadcasted, coopCloseTxKey, closeTx,
1✔
1981
                closer,
1✔
1982
        )
1✔
1983
}
1✔
1984

1985
// markBroadcasted is a helper function which modifies the channel status of the
1986
// receiving channel and inserts a close transaction under the requested key,
1987
// which should specify either a coop or force close. It adds a status which
1988
// indicates the party that initiated the channel close.
1989
func (c *OpenChannel) markBroadcasted(status ChannelStatus, key []byte,
1990
        closeTx *wire.MsgTx, closer lntypes.ChannelParty) error {
1✔
1991

1✔
1992
        c.Lock()
1✔
1993
        defer c.Unlock()
1✔
1994

1✔
1995
        // If a closing tx is provided, we'll generate a closure to write the
1✔
1996
        // transaction in the appropriate bucket under the given key.
1✔
1997
        var putClosingTx func(kvdb.RwBucket) error
1✔
1998
        if closeTx != nil {
2✔
1999
                var b bytes.Buffer
1✔
2000
                if err := WriteElement(&b, closeTx); err != nil {
1✔
2001
                        return err
×
2002
                }
×
2003

2004
                putClosingTx = func(chanBucket kvdb.RwBucket) error {
2✔
2005
                        return chanBucket.Put(key, b.Bytes())
1✔
2006
                }
1✔
2007
        }
2008

2009
        // Add the initiator status to the status provided. These statuses are
2010
        // set in addition to the broadcast status so that we do not need to
2011
        // migrate the original logic which does not store initiator.
2012
        if closer.IsLocal() {
2✔
2013
                status |= ChanStatusLocalCloseInitiator
1✔
2014
        } else {
2✔
2015
                status |= ChanStatusRemoteCloseInitiator
1✔
2016
        }
1✔
2017

2018
        return c.putChanStatus(status, putClosingTx)
1✔
2019
}
2020

2021
// BroadcastedCommitment retrieves the stored unilateral closing tx set during
2022
// MarkCommitmentBroadcasted. If not found ErrNoCloseTx is returned.
2023
func (c *OpenChannel) BroadcastedCommitment() (*wire.MsgTx, error) {
1✔
2024
        return c.getClosingTx(forceCloseTxKey)
1✔
2025
}
1✔
2026

2027
// BroadcastedCooperative retrieves the stored cooperative closing tx set during
2028
// MarkCoopBroadcasted. If not found ErrNoCloseTx is returned.
2029
func (c *OpenChannel) BroadcastedCooperative() (*wire.MsgTx, error) {
1✔
2030
        return c.getClosingTx(coopCloseTxKey)
1✔
2031
}
1✔
2032

2033
// getClosingTx is a helper method which returns the stored closing transaction
2034
// for key. The caller should use either the force or coop closing keys.
2035
func (c *OpenChannel) getClosingTx(key []byte) (*wire.MsgTx, error) {
1✔
2036
        var closeTx *wire.MsgTx
1✔
2037

1✔
2038
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2✔
2039
                chanBucket, err := fetchChanBucket(
1✔
2040
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
2041
                )
1✔
2042
                switch err {
1✔
2043
                case nil:
1✔
2044
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
×
2045
                        return ErrNoCloseTx
×
2046
                default:
×
2047
                        return err
×
2048
                }
2049

2050
                bs := chanBucket.Get(key)
1✔
2051
                if bs == nil {
2✔
2052
                        return ErrNoCloseTx
1✔
2053
                }
1✔
2054
                r := bytes.NewReader(bs)
1✔
2055
                return ReadElement(r, &closeTx)
1✔
2056
        }, func() {
1✔
2057
                closeTx = nil
1✔
2058
        })
1✔
2059
        if err != nil {
2✔
2060
                return nil, err
1✔
2061
        }
1✔
2062

2063
        return closeTx, nil
1✔
2064
}
2065

2066
// putChanStatus appends the given status to the channel. fs is an optional
2067
// list of closures that are given the chanBucket in order to atomically add
2068
// extra information together with the new status.
2069
func (c *OpenChannel) putChanStatus(status ChannelStatus,
2070
        fs ...func(kvdb.RwBucket) error) error {
1✔
2071

1✔
2072
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
2073
                chanBucket, err := fetchChanBucketRw(
1✔
2074
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
2075
                )
1✔
2076
                if err != nil {
1✔
UNCOV
2077
                        return err
×
UNCOV
2078
                }
×
2079

2080
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
1✔
2081
                if err != nil {
1✔
2082
                        return err
×
2083
                }
×
2084

2085
                // Add this status to the existing bitvector found in the DB.
2086
                status = channel.chanStatus | status
1✔
2087
                channel.chanStatus = status
1✔
2088

1✔
2089
                if err := putOpenChannel(chanBucket, channel); err != nil {
1✔
2090
                        return err
×
2091
                }
×
2092

2093
                for _, f := range fs {
2✔
2094
                        // Skip execution of nil closures.
1✔
2095
                        if f == nil {
2✔
2096
                                continue
1✔
2097
                        }
2098

2099
                        if err := f(chanBucket); err != nil {
1✔
2100
                                return err
×
2101
                        }
×
2102
                }
2103

2104
                return nil
1✔
2105
        }, func() {}); err != nil {
1✔
UNCOV
2106
                return err
×
UNCOV
2107
        }
×
2108

2109
        // Update the in-memory representation to keep it in sync with the DB.
2110
        c.chanStatus = status
1✔
2111

1✔
2112
        return nil
1✔
2113
}
2114

UNCOV
2115
func (c *OpenChannel) clearChanStatus(status ChannelStatus) error {
×
UNCOV
2116
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
UNCOV
2117
                chanBucket, err := fetchChanBucketRw(
×
UNCOV
2118
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
×
UNCOV
2119
                )
×
UNCOV
2120
                if err != nil {
×
2121
                        return err
×
2122
                }
×
2123

UNCOV
2124
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
×
UNCOV
2125
                if err != nil {
×
2126
                        return err
×
2127
                }
×
2128

2129
                // Unset this bit in the bitvector on disk.
UNCOV
2130
                status = channel.chanStatus & ^status
×
UNCOV
2131
                channel.chanStatus = status
×
UNCOV
2132

×
UNCOV
2133
                return putOpenChannel(chanBucket, channel)
×
UNCOV
2134
        }, func() {}); err != nil {
×
2135
                return err
×
2136
        }
×
2137

2138
        // Update the in-memory representation to keep it in sync with the DB.
UNCOV
2139
        c.chanStatus = status
×
UNCOV
2140

×
UNCOV
2141
        return nil
×
2142
}
2143

2144
// putOpenChannel serializes, and stores the current state of the channel in its
2145
// entirety.
2146
func putOpenChannel(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
1✔
2147
        // First, we'll write out all the relatively static fields, that are
1✔
2148
        // decided upon initial channel creation.
1✔
2149
        if err := putChanInfo(chanBucket, channel); err != nil {
1✔
2150
                return fmt.Errorf("unable to store chan info: %w", err)
×
2151
        }
×
2152

2153
        // With the static channel info written out, we'll now write out the
2154
        // current commitment state for both parties.
2155
        if err := putChanCommitments(chanBucket, channel); err != nil {
1✔
2156
                return fmt.Errorf("unable to store chan commitments: %w", err)
×
2157
        }
×
2158

2159
        // Next, if this is a frozen channel, we'll add in the axillary
2160
        // information we need to store.
2161
        if channel.ChanType.IsFrozen() || channel.ChanType.HasLeaseExpiration() {
2✔
2162
                err := storeThawHeight(
1✔
2163
                        chanBucket, channel.ThawHeight,
1✔
2164
                )
1✔
2165
                if err != nil {
1✔
2166
                        return fmt.Errorf("unable to store thaw height: %w",
×
2167
                                err)
×
2168
                }
×
2169
        }
2170

2171
        // Finally, we'll write out the revocation state for both parties
2172
        // within a distinct key space.
2173
        if err := putChanRevocationState(chanBucket, channel); err != nil {
1✔
2174
                return fmt.Errorf("unable to store chan revocations: %w", err)
×
2175
        }
×
2176

2177
        return nil
1✔
2178
}
2179

2180
// fetchOpenChannel retrieves, and deserializes (including decrypting
2181
// sensitive) the complete channel currently active with the passed nodeID.
2182
func fetchOpenChannel(chanBucket kvdb.RBucket,
2183
        chanPoint *wire.OutPoint) (*OpenChannel, error) {
1✔
2184

1✔
2185
        channel := &OpenChannel{
1✔
2186
                FundingOutpoint: *chanPoint,
1✔
2187
        }
1✔
2188

1✔
2189
        // First, we'll read all the static information that changes less
1✔
2190
        // frequently from disk.
1✔
2191
        if err := fetchChanInfo(chanBucket, channel); err != nil {
1✔
2192
                return nil, fmt.Errorf("unable to fetch chan info: %w", err)
×
2193
        }
×
2194

2195
        // With the static information read, we'll now read the current
2196
        // commitment state for both sides of the channel.
2197
        if err := fetchChanCommitments(chanBucket, channel); err != nil {
1✔
2198
                return nil, fmt.Errorf("unable to fetch chan commitments: %w",
×
2199
                        err)
×
2200
        }
×
2201

2202
        // Next, if this is a frozen channel, we'll add in the axillary
2203
        // information we need to store.
2204
        if channel.ChanType.IsFrozen() || channel.ChanType.HasLeaseExpiration() {
2✔
2205
                thawHeight, err := fetchThawHeight(chanBucket)
1✔
2206
                if err != nil {
1✔
2207
                        return nil, fmt.Errorf("unable to store thaw "+
×
2208
                                "height: %v", err)
×
2209
                }
×
2210

2211
                channel.ThawHeight = thawHeight
1✔
2212
        }
2213

2214
        // Finally, we'll retrieve the current revocation state so we can
2215
        // properly
2216
        if err := fetchChanRevocationState(chanBucket, channel); err != nil {
1✔
2217
                return nil, fmt.Errorf("unable to fetch chan revocations: %w",
×
2218
                        err)
×
2219
        }
×
2220

2221
        channel.Packager = NewChannelPackager(channel.ShortChannelID)
1✔
2222

1✔
2223
        return channel, nil
1✔
2224
}
2225

2226
// SyncPending writes the contents of the channel to the database while it's in
2227
// the pending (waiting for funding confirmation) state. The IsPending flag
2228
// will be set to true. When the channel's funding transaction is confirmed,
2229
// the channel should be marked as "open" and the IsPending flag set to false.
2230
// Note that this function also creates a LinkNode relationship between this
2231
// newly created channel and a new LinkNode instance. This allows listing all
2232
// channels in the database globally, or according to the LinkNode they were
2233
// created with.
2234
//
2235
// TODO(roasbeef): addr param should eventually be an lnwire.NetAddress type
2236
// that includes service bits.
2237
func (c *OpenChannel) SyncPending(addr net.Addr, pendingHeight uint32) error {
1✔
2238
        c.Lock()
1✔
2239
        defer c.Unlock()
1✔
2240

1✔
2241
        c.FundingBroadcastHeight = pendingHeight
1✔
2242

1✔
2243
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
2244
                return syncNewChannel(tx, c, []net.Addr{addr})
1✔
2245
        }, func() {})
2✔
2246
}
2247

2248
// syncNewChannel will write the passed channel to disk, and also create a
2249
// LinkNode (if needed) for the channel peer.
2250
func syncNewChannel(tx kvdb.RwTx, c *OpenChannel, addrs []net.Addr) error {
1✔
2251
        // First, sync all the persistent channel state to disk.
1✔
2252
        if err := c.fullSync(tx); err != nil {
2✔
2253
                return err
1✔
2254
        }
1✔
2255

2256
        nodeInfoBucket, err := tx.CreateTopLevelBucket(nodeInfoBucket)
1✔
2257
        if err != nil {
1✔
2258
                return err
×
2259
        }
×
2260

2261
        // If a LinkNode for this identity public key already exists,
2262
        // then we can exit early.
2263
        nodePub := c.IdentityPub.SerializeCompressed()
1✔
2264
        if nodeInfoBucket.Get(nodePub) != nil {
2✔
2265
                return nil
1✔
2266
        }
1✔
2267

2268
        // Next, we need to establish a (possibly) new LinkNode relationship
2269
        // for this channel. The LinkNode metadata contains reachability,
2270
        // up-time, and service bits related information.
2271
        linkNode := NewLinkNode(
1✔
2272
                &LinkNodeDB{backend: c.Db.backend},
1✔
2273
                wire.MainNet, c.IdentityPub, addrs...,
1✔
2274
        )
1✔
2275

1✔
2276
        // TODO(roasbeef): do away with link node all together?
1✔
2277

1✔
2278
        return putLinkNode(nodeInfoBucket, linkNode)
1✔
2279
}
2280

2281
// UpdateCommitment updates the local commitment state. It locks in the pending
2282
// local updates that were received by us from the remote party. The commitment
2283
// state completely describes the balance state at this point in the commitment
2284
// chain. In addition to that, it persists all the remote log updates that we
2285
// have acked, but not signed a remote commitment for yet. These need to be
2286
// persisted to be able to produce a valid commit signature if a restart would
2287
// occur. This method its to be called when we revoke our prior commitment
2288
// state.
2289
//
2290
// A map is returned of all the htlc resolutions that were locked in this
2291
// commitment. Keys correspond to htlc indices and values indicate whether the
2292
// htlc was settled or failed.
2293
func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
2294
        unsignedAckedUpdates []LogUpdate) (map[uint64]bool, error) {
1✔
2295

1✔
2296
        c.Lock()
1✔
2297
        defer c.Unlock()
1✔
2298

1✔
2299
        // If this is a restored channel, then we want to avoid mutating the
1✔
2300
        // state as all, as it's impossible to do so in a protocol compliant
1✔
2301
        // manner.
1✔
2302
        if c.hasChanStatus(ChanStatusRestored) {
1✔
UNCOV
2303
                return nil, ErrNoRestoredChannelMutation
×
UNCOV
2304
        }
×
2305

2306
        var finalHtlcs = make(map[uint64]bool)
1✔
2307

1✔
2308
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
2309
                chanBucket, err := fetchChanBucketRw(
1✔
2310
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
2311
                )
1✔
2312
                if err != nil {
1✔
2313
                        return err
×
2314
                }
×
2315

2316
                // If the channel is marked as borked, then for safety reasons,
2317
                // we shouldn't attempt any further updates.
2318
                isBorked, err := c.isBorked(chanBucket)
1✔
2319
                if err != nil {
1✔
2320
                        return err
×
2321
                }
×
2322
                if isBorked {
1✔
UNCOV
2323
                        return ErrChanBorked
×
UNCOV
2324
                }
×
2325

2326
                if err = putChanInfo(chanBucket, c); err != nil {
1✔
2327
                        return fmt.Errorf("unable to store chan info: %w", err)
×
2328
                }
×
2329

2330
                // With the proper bucket fetched, we'll now write the latest
2331
                // commitment state to disk for the target party.
2332
                err = putChanCommitment(
1✔
2333
                        chanBucket, newCommitment, true,
1✔
2334
                )
1✔
2335
                if err != nil {
1✔
2336
                        return fmt.Errorf("unable to store chan "+
×
2337
                                "revocations: %v", err)
×
2338
                }
×
2339

2340
                // Persist unsigned but acked remote updates that need to be
2341
                // restored after a restart.
2342
                var b bytes.Buffer
1✔
2343
                err = serializeLogUpdates(&b, unsignedAckedUpdates)
1✔
2344
                if err != nil {
1✔
2345
                        return err
×
2346
                }
×
2347

2348
                err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes())
1✔
2349
                if err != nil {
1✔
2350
                        return fmt.Errorf("unable to store dangline remote "+
×
2351
                                "updates: %v", err)
×
2352
                }
×
2353

2354
                // Since we have just sent the counterparty a revocation, store true
2355
                // under lastWasRevokeKey.
2356
                var b2 bytes.Buffer
1✔
2357
                if err := WriteElements(&b2, true); err != nil {
1✔
2358
                        return err
×
2359
                }
×
2360

2361
                if err := chanBucket.Put(lastWasRevokeKey, b2.Bytes()); err != nil {
1✔
2362
                        return err
×
2363
                }
×
2364

2365
                // Persist the remote unsigned local updates that are not included
2366
                // in our new commitment.
2367
                updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
1✔
2368
                if updateBytes == nil {
2✔
2369
                        return nil
1✔
2370
                }
1✔
2371

2372
                r := bytes.NewReader(updateBytes)
1✔
2373
                updates, err := deserializeLogUpdates(r)
1✔
2374
                if err != nil {
1✔
2375
                        return err
×
2376
                }
×
2377

2378
                // Get the bucket where settled htlcs are recorded if the user
2379
                // opted in to storing this information.
2380
                var finalHtlcsBucket kvdb.RwBucket
1✔
2381
                if c.Db.parent.storeFinalHtlcResolutions {
2✔
2382
                        bucket, err := fetchFinalHtlcsBucketRw(
1✔
2383
                                tx, c.ShortChannelID,
1✔
2384
                        )
1✔
2385
                        if err != nil {
1✔
2386
                                return err
×
2387
                        }
×
2388

2389
                        finalHtlcsBucket = bucket
1✔
2390
                }
2391

2392
                var unsignedUpdates []LogUpdate
1✔
2393
                for _, upd := range updates {
2✔
2394
                        // Gather updates that are not on our local commitment.
1✔
2395
                        if upd.LogIndex >= newCommitment.LocalLogIndex {
1✔
2396
                                unsignedUpdates = append(unsignedUpdates, upd)
×
2397

×
2398
                                continue
×
2399
                        }
2400

2401
                        // The update was locked in. If the update was a
2402
                        // resolution, then store it in the database.
2403
                        err := processFinalHtlc(
1✔
2404
                                finalHtlcsBucket, upd, finalHtlcs,
1✔
2405
                        )
1✔
2406
                        if err != nil {
1✔
2407
                                return err
×
2408
                        }
×
2409
                }
2410

2411
                var b3 bytes.Buffer
1✔
2412
                err = serializeLogUpdates(&b3, unsignedUpdates)
1✔
2413
                if err != nil {
1✔
2414
                        return fmt.Errorf("unable to serialize log updates: %w",
×
2415
                                err)
×
2416
                }
×
2417

2418
                err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b3.Bytes())
1✔
2419
                if err != nil {
1✔
2420
                        return fmt.Errorf("unable to restore chanbucket: %w",
×
2421
                                err)
×
2422
                }
×
2423

2424
                return nil
1✔
2425
        }, func() {
1✔
2426
                finalHtlcs = make(map[uint64]bool)
1✔
2427
        })
1✔
2428
        if err != nil {
1✔
UNCOV
2429
                return nil, err
×
UNCOV
2430
        }
×
2431

2432
        c.LocalCommitment = *newCommitment
1✔
2433

1✔
2434
        return finalHtlcs, nil
1✔
2435
}
2436

2437
// processFinalHtlc stores a final htlc outcome in the database if signaled via
2438
// the supplied log update. An in-memory htlcs map is updated too.
2439
func processFinalHtlc(finalHtlcsBucket walletdb.ReadWriteBucket, upd LogUpdate,
2440
        finalHtlcs map[uint64]bool) error {
1✔
2441

1✔
2442
        var (
1✔
2443
                settled bool
1✔
2444
                id      uint64
1✔
2445
        )
1✔
2446

1✔
2447
        switch msg := upd.UpdateMsg.(type) {
1✔
2448
        case *lnwire.UpdateFulfillHTLC:
1✔
2449
                settled = true
1✔
2450
                id = msg.ID
1✔
2451

2452
        case *lnwire.UpdateFailHTLC:
1✔
2453
                settled = false
1✔
2454
                id = msg.ID
1✔
2455

2456
        case *lnwire.UpdateFailMalformedHTLC:
1✔
2457
                settled = false
1✔
2458
                id = msg.ID
1✔
2459

UNCOV
2460
        default:
×
UNCOV
2461
                return nil
×
2462
        }
2463

2464
        // Store the final resolution in the database if a bucket is provided.
2465
        if finalHtlcsBucket != nil {
2✔
2466
                err := putFinalHtlc(
1✔
2467
                        finalHtlcsBucket, id,
1✔
2468
                        FinalHtlcInfo{
1✔
2469
                                Settled:  settled,
1✔
2470
                                Offchain: true,
1✔
2471
                        },
1✔
2472
                )
1✔
2473
                if err != nil {
1✔
2474
                        return err
×
2475
                }
×
2476
        }
2477

2478
        finalHtlcs[id] = settled
1✔
2479

1✔
2480
        return nil
1✔
2481
}
2482

2483
// ActiveHtlcs returns a slice of HTLC's which are currently active on *both*
2484
// commitment transactions.
2485
func (c *OpenChannel) ActiveHtlcs() []HTLC {
1✔
2486
        c.RLock()
1✔
2487
        defer c.RUnlock()
1✔
2488

1✔
2489
        // We'll only return HTLC's that are locked into *both* commitment
1✔
2490
        // transactions. So we'll iterate through their set of HTLC's to note
1✔
2491
        // which ones are present on their commitment.
1✔
2492
        remoteHtlcs := make(map[[32]byte]struct{})
1✔
2493
        for _, htlc := range c.RemoteCommitment.Htlcs {
2✔
2494
                log.Tracef("RemoteCommitment has htlc: id=%v, update=%v "+
1✔
2495
                        "incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
1✔
2496
                        htlc.Incoming)
1✔
2497

1✔
2498
                onionHash := sha256.Sum256(htlc.OnionBlob[:])
1✔
2499
                remoteHtlcs[onionHash] = struct{}{}
1✔
2500
        }
1✔
2501

2502
        // Now that we know which HTLC's they have, we'll only mark the HTLC's
2503
        // as active if *we* know them as well.
2504
        activeHtlcs := make([]HTLC, 0, len(remoteHtlcs))
1✔
2505
        for _, htlc := range c.LocalCommitment.Htlcs {
2✔
2506
                log.Tracef("LocalCommitment has htlc: id=%v, update=%v "+
1✔
2507
                        "incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
1✔
2508
                        htlc.Incoming)
1✔
2509

1✔
2510
                onionHash := sha256.Sum256(htlc.OnionBlob[:])
1✔
2511
                if _, ok := remoteHtlcs[onionHash]; !ok {
2✔
2512
                        log.Tracef("Skipped htlc due to onion mismatched: "+
1✔
2513
                                "id=%v, update=%v incoming=%v",
1✔
2514
                                htlc.HtlcIndex, htlc.LogIndex, htlc.Incoming)
1✔
2515

1✔
2516
                        continue
1✔
2517
                }
2518

2519
                activeHtlcs = append(activeHtlcs, htlc)
1✔
2520
        }
2521

2522
        return activeHtlcs
1✔
2523
}
2524

2525
// HTLC is the on-disk representation of a hash time-locked contract. HTLCs are
2526
// contained within ChannelDeltas which encode the current state of the
2527
// commitment between state updates.
2528
//
2529
// TODO(roasbeef): save space by using smaller ints at tail end?
2530
type HTLC struct {
2531
        // TODO(yy): can embed an HTLCEntry here.
2532

2533
        // Signature is the signature for the second level covenant transaction
2534
        // for this HTLC. The second level transaction is a timeout tx in the
2535
        // case that this is an outgoing HTLC, and a success tx in the case
2536
        // that this is an incoming HTLC.
2537
        //
2538
        // TODO(roasbeef): make [64]byte instead?
2539
        Signature []byte
2540

2541
        // RHash is the payment hash of the HTLC.
2542
        RHash [32]byte
2543

2544
        // Amt is the amount of milli-satoshis this HTLC escrows.
2545
        Amt lnwire.MilliSatoshi
2546

2547
        // RefundTimeout is the absolute timeout on the HTLC that the sender
2548
        // must wait before reclaiming the funds in limbo.
2549
        RefundTimeout uint32
2550

2551
        // OutputIndex is the output index for this particular HTLC output
2552
        // within the commitment transaction.
2553
        OutputIndex int32
2554

2555
        // Incoming denotes whether we're the receiver or the sender of this
2556
        // HTLC.
2557
        Incoming bool
2558

2559
        // OnionBlob is an opaque blob which is used to complete multi-hop
2560
        // routing.
2561
        OnionBlob [lnwire.OnionPacketSize]byte
2562

2563
        // HtlcIndex is the HTLC counter index of this active, outstanding
2564
        // HTLC. This differs from the LogIndex, as the HtlcIndex is only
2565
        // incremented for each offered HTLC, while they LogIndex is
2566
        // incremented for each update (includes settle+fail).
2567
        HtlcIndex uint64
2568

2569
        // LogIndex is the cumulative log index of this HTLC. This differs
2570
        // from the HtlcIndex as this will be incremented for each new log
2571
        // update added.
2572
        LogIndex uint64
2573

2574
        // ExtraData contains any additional information that was transmitted
2575
        // with the HTLC via TLVs. This data *must* already be encoded as a
2576
        // TLV stream, and may be empty. The length of this data is naturally
2577
        // limited by the space available to TLVs in update_add_htlc:
2578
        // = 65535 bytes (bolt 8 maximum message size):
2579
        // - 2 bytes (bolt 1 message_type)
2580
        // - 32 bytes (channel_id)
2581
        // - 8 bytes (id)
2582
        // - 8 bytes (amount_msat)
2583
        // - 32 bytes (payment_hash)
2584
        // - 4 bytes (cltv_expiry)
2585
        // - 1366 bytes (onion_routing_packet)
2586
        // = 64083 bytes maximum possible TLV stream
2587
        //
2588
        // Note that this extra data is stored inline with the OnionBlob for
2589
        // legacy reasons, see serialization/deserialization functions for
2590
        // detail.
2591
        ExtraData lnwire.ExtraOpaqueData
2592

2593
        // BlindingPoint is an optional blinding point included with the HTLC.
2594
        //
2595
        // Note: this field is not a part of on-disk representation of the
2596
        // HTLC. It is stored in the ExtraData field, which is used to store
2597
        // a TLV stream of additional information associated with the HTLC.
2598
        BlindingPoint lnwire.BlindingPointRecord
2599

2600
        // CustomRecords is a set of custom TLV records that are associated with
2601
        // this HTLC. These records are used to store additional information
2602
        // about the HTLC that is not part of the standard HTLC fields. This
2603
        // field is encoded within the ExtraData field.
2604
        CustomRecords lnwire.CustomRecords
2605
}
2606

2607
// serializeExtraData encodes a TLV stream of extra data to be stored with a
2608
// HTLC. It uses the update_add_htlc TLV types, because this is where extra
2609
// data is passed with a HTLC. At present blinding points are the only extra
2610
// data that we will store, and the function is a no-op if a nil blinding
2611
// point is provided.
2612
//
2613
// This function MUST be called to persist all HTLC values when they are
2614
// serialized.
2615
func (h *HTLC) serializeExtraData() error {
1✔
2616
        var records []tlv.RecordProducer
1✔
2617
        h.BlindingPoint.WhenSome(func(b tlv.RecordT[lnwire.BlindingPointTlvType,
1✔
2618
                *btcec.PublicKey]) {
2✔
2619

1✔
2620
                records = append(records, &b)
1✔
2621
        })
1✔
2622

2623
        records, err := h.CustomRecords.ExtendRecordProducers(records)
1✔
2624
        if err != nil {
1✔
2625
                return err
×
2626
        }
×
2627

2628
        return h.ExtraData.PackRecords(records...)
1✔
2629
}
2630

2631
// deserializeExtraData extracts TLVs from the extra data persisted for the
2632
// htlc and populates values in the struct accordingly.
2633
//
2634
// This function MUST be called to populate the struct properly when HTLCs
2635
// are deserialized.
2636
func (h *HTLC) deserializeExtraData() error {
1✔
2637
        if len(h.ExtraData) == 0 {
2✔
2638
                return nil
1✔
2639
        }
1✔
2640

2641
        blindingPoint := h.BlindingPoint.Zero()
1✔
2642
        tlvMap, err := h.ExtraData.ExtractRecords(&blindingPoint)
1✔
2643
        if err != nil {
1✔
2644
                return err
×
2645
        }
×
2646

2647
        if val, ok := tlvMap[h.BlindingPoint.TlvType()]; ok && val == nil {
2✔
2648
                h.BlindingPoint = tlv.SomeRecordT(blindingPoint)
1✔
2649

1✔
2650
                // Remove the entry from the TLV map. Anything left in the map
1✔
2651
                // will be included in the custom records field.
1✔
2652
                delete(tlvMap, h.BlindingPoint.TlvType())
1✔
2653
        }
1✔
2654

2655
        // Set the custom records field to the remaining TLV records.
2656
        customRecords, err := lnwire.NewCustomRecords(tlvMap)
1✔
2657
        if err != nil {
1✔
2658
                return err
×
2659
        }
×
2660
        h.CustomRecords = customRecords
1✔
2661

1✔
2662
        return nil
1✔
2663
}
2664

2665
// SerializeHtlcs writes out the passed set of HTLC's into the passed writer
2666
// using the current default on-disk serialization format.
2667
//
2668
// This inline serialization has been extended to allow storage of extra data
2669
// associated with a HTLC in the following way:
2670
//   - The known-length onion blob (1366 bytes) is serialized as var bytes in
2671
//     WriteElements (ie, the length 1366 was written, followed by the 1366
2672
//     onion bytes).
2673
//   - To include extra data, we append any extra data present to this one
2674
//     variable length of data. Since we know that the onion is strictly 1366
2675
//     bytes, any length after that should be considered to be extra data.
2676
//
2677
// NOTE: This API is NOT stable, the on-disk format will likely change in the
2678
// future.
2679
func SerializeHtlcs(b io.Writer, htlcs ...HTLC) error {
1✔
2680
        numHtlcs := uint16(len(htlcs))
1✔
2681
        if err := WriteElement(b, numHtlcs); err != nil {
1✔
2682
                return err
×
2683
        }
×
2684

2685
        for _, htlc := range htlcs {
2✔
2686
                // Populate TLV stream for any additional fields contained
1✔
2687
                // in the TLV.
1✔
2688
                if err := htlc.serializeExtraData(); err != nil {
1✔
2689
                        return err
×
2690
                }
×
2691

2692
                // The onion blob and hltc data are stored as a single var
2693
                // bytes blob.
2694
                onionAndExtraData := make(
1✔
2695
                        []byte, lnwire.OnionPacketSize+len(htlc.ExtraData),
1✔
2696
                )
1✔
2697
                copy(onionAndExtraData, htlc.OnionBlob[:])
1✔
2698
                copy(onionAndExtraData[lnwire.OnionPacketSize:], htlc.ExtraData)
1✔
2699

1✔
2700
                if err := WriteElements(b,
1✔
2701
                        htlc.Signature, htlc.RHash, htlc.Amt, htlc.RefundTimeout,
1✔
2702
                        htlc.OutputIndex, htlc.Incoming, onionAndExtraData,
1✔
2703
                        htlc.HtlcIndex, htlc.LogIndex,
1✔
2704
                ); err != nil {
1✔
2705
                        return err
×
2706
                }
×
2707
        }
2708

2709
        return nil
1✔
2710
}
2711

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

2735
        var htlcs []HTLC
1✔
2736
        if numHtlcs == 0 {
2✔
2737
                return htlcs, nil
1✔
2738
        }
1✔
2739

2740
        htlcs = make([]HTLC, numHtlcs)
1✔
2741
        for i := uint16(0); i < numHtlcs; i++ {
2✔
2742
                var onionAndExtraData []byte
1✔
2743
                if err := ReadElements(r,
1✔
2744
                        &htlcs[i].Signature, &htlcs[i].RHash, &htlcs[i].Amt,
1✔
2745
                        &htlcs[i].RefundTimeout, &htlcs[i].OutputIndex,
1✔
2746
                        &htlcs[i].Incoming, &onionAndExtraData,
1✔
2747
                        &htlcs[i].HtlcIndex, &htlcs[i].LogIndex,
1✔
2748
                ); err != nil {
1✔
2749
                        return htlcs, err
×
2750
                }
×
2751

2752
                // Sanity check that we have at least the onion blob size we
2753
                // expect.
2754
                if len(onionAndExtraData) < lnwire.OnionPacketSize {
1✔
UNCOV
2755
                        return nil, ErrOnionBlobLength
×
UNCOV
2756
                }
×
2757

2758
                // First OnionPacketSize bytes are our fixed length onion
2759
                // packet.
2760
                copy(
1✔
2761
                        htlcs[i].OnionBlob[:],
1✔
2762
                        onionAndExtraData[0:lnwire.OnionPacketSize],
1✔
2763
                )
1✔
2764

1✔
2765
                // Any additional bytes belong to extra data. ExtraDataLen
1✔
2766
                // will be >= 0, because we know that we always have a fixed
1✔
2767
                // length onion packet.
1✔
2768
                extraDataLen := len(onionAndExtraData) - lnwire.OnionPacketSize
1✔
2769
                if extraDataLen > 0 {
2✔
2770
                        htlcs[i].ExtraData = make([]byte, extraDataLen)
1✔
2771

1✔
2772
                        copy(
1✔
2773
                                htlcs[i].ExtraData,
1✔
2774
                                onionAndExtraData[lnwire.OnionPacketSize:],
1✔
2775
                        )
1✔
2776
                }
1✔
2777

2778
                // Finally, deserialize any TLVs contained in that extra data
2779
                // if they are present.
2780
                if err := htlcs[i].deserializeExtraData(); err != nil {
1✔
2781
                        return nil, err
×
2782
                }
×
2783
        }
2784

2785
        return htlcs, nil
1✔
2786
}
2787

2788
// Copy returns a full copy of the target HTLC.
2789
func (h *HTLC) Copy() HTLC {
1✔
2790
        clone := HTLC{
1✔
2791
                Incoming:      h.Incoming,
1✔
2792
                Amt:           h.Amt,
1✔
2793
                RefundTimeout: h.RefundTimeout,
1✔
2794
                OutputIndex:   h.OutputIndex,
1✔
2795
        }
1✔
2796
        copy(clone.Signature[:], h.Signature)
1✔
2797
        copy(clone.RHash[:], h.RHash[:])
1✔
2798
        copy(clone.ExtraData, h.ExtraData)
1✔
2799
        clone.BlindingPoint = h.BlindingPoint
1✔
2800
        clone.CustomRecords = h.CustomRecords.Copy()
1✔
2801

1✔
2802
        return clone
1✔
2803
}
1✔
2804

2805
// LogUpdate represents a pending update to the remote commitment chain. The
2806
// log update may be an add, fail, or settle entry. We maintain this data in
2807
// order to be able to properly retransmit our proposed state if necessary.
2808
type LogUpdate struct {
2809
        // LogIndex is the log index of this proposed commitment update entry.
2810
        LogIndex uint64
2811

2812
        // UpdateMsg is the update message that was included within our
2813
        // local update log. The LogIndex value denotes the log index of this
2814
        // update which will be used when restoring our local update log if
2815
        // we're left with a dangling update on restart.
2816
        UpdateMsg lnwire.Message
2817
}
2818

2819
// serializeLogUpdate writes a log update to the provided io.Writer.
2820
func serializeLogUpdate(w io.Writer, l *LogUpdate) error {
1✔
2821
        return WriteElements(w, l.LogIndex, l.UpdateMsg)
1✔
2822
}
1✔
2823

2824
// deserializeLogUpdate reads a log update from the provided io.Reader.
2825
func deserializeLogUpdate(r io.Reader) (*LogUpdate, error) {
1✔
2826
        l := &LogUpdate{}
1✔
2827
        if err := ReadElements(r, &l.LogIndex, &l.UpdateMsg); err != nil {
1✔
2828
                return nil, err
×
2829
        }
×
2830

2831
        return l, nil
1✔
2832
}
2833

2834
// CommitDiff represents the delta needed to apply the state transition between
2835
// two subsequent commitment states. Given state N and state N+1, one is able
2836
// to apply the set of messages contained within the CommitDiff to N to arrive
2837
// at state N+1. Each time a new commitment is extended, we'll write a new
2838
// commitment (along with the full commitment state) to disk so we can
2839
// re-transmit the state in the case of a connection loss or message drop.
2840
type CommitDiff struct {
2841
        // ChannelCommitment is the full commitment state that one would arrive
2842
        // at by applying the set of messages contained in the UpdateDiff to
2843
        // the prior accepted commitment.
2844
        Commitment ChannelCommitment
2845

2846
        // LogUpdates is the set of messages sent prior to the commitment state
2847
        // transition in question. Upon reconnection, if we detect that they
2848
        // don't have the commitment, then we re-send this along with the
2849
        // proper signature.
2850
        LogUpdates []LogUpdate
2851

2852
        // CommitSig is the exact CommitSig message that should be sent after
2853
        // the set of LogUpdates above has been retransmitted. The signatures
2854
        // within this message should properly cover the new commitment state
2855
        // and also the HTLC's within the new commitment state.
2856
        CommitSig *lnwire.CommitSig
2857

2858
        // OpenedCircuitKeys is a set of unique identifiers for any downstream
2859
        // Add packets included in this commitment txn. After a restart, this
2860
        // set of htlcs is acked from the link's incoming mailbox to ensure
2861
        // there isn't an attempt to re-add them to this commitment txn.
2862
        OpenedCircuitKeys []models.CircuitKey
2863

2864
        // ClosedCircuitKeys records the unique identifiers for any settle/fail
2865
        // packets that were resolved by this commitment txn. After a restart,
2866
        // this is used to ensure those circuits are removed from the circuit
2867
        // map, and the downstream packets in the link's mailbox are removed.
2868
        ClosedCircuitKeys []models.CircuitKey
2869

2870
        // AddAcks specifies the locations (commit height, pkg index) of any
2871
        // Adds that were failed/settled in this commit diff. This will ack
2872
        // entries in *this* channel's forwarding packages.
2873
        //
2874
        // NOTE: This value is not serialized, it is used to atomically mark the
2875
        // resolution of adds, such that they will not be reprocessed after a
2876
        // restart.
2877
        AddAcks []AddRef
2878

2879
        // SettleFailAcks specifies the locations (chan id, commit height, pkg
2880
        // index) of any Settles or Fails that were locked into this commit
2881
        // diff, and originate from *another* channel, i.e. the outgoing link.
2882
        //
2883
        // NOTE: This value is not serialized, it is used to atomically acks
2884
        // settles and fails from the forwarding packages of other channels,
2885
        // such that they will not be reforwarded internally after a restart.
2886
        SettleFailAcks []SettleFailRef
2887
}
2888

2889
// serializeLogUpdates serializes provided list of updates to a stream.
2890
func serializeLogUpdates(w io.Writer, logUpdates []LogUpdate) error {
1✔
2891
        numUpdates := uint16(len(logUpdates))
1✔
2892
        if err := binary.Write(w, byteOrder, numUpdates); err != nil {
1✔
2893
                return err
×
2894
        }
×
2895

2896
        for _, diff := range logUpdates {
2✔
2897
                err := WriteElements(w, diff.LogIndex, diff.UpdateMsg)
1✔
2898
                if err != nil {
1✔
2899
                        return err
×
2900
                }
×
2901
        }
2902

2903
        return nil
1✔
2904
}
2905

2906
// deserializeLogUpdates deserializes a list of updates from a stream.
2907
func deserializeLogUpdates(r io.Reader) ([]LogUpdate, error) {
1✔
2908
        var numUpdates uint16
1✔
2909
        if err := binary.Read(r, byteOrder, &numUpdates); err != nil {
1✔
2910
                return nil, err
×
2911
        }
×
2912

2913
        logUpdates := make([]LogUpdate, numUpdates)
1✔
2914
        for i := 0; i < int(numUpdates); i++ {
2✔
2915
                err := ReadElements(r,
1✔
2916
                        &logUpdates[i].LogIndex, &logUpdates[i].UpdateMsg,
1✔
2917
                )
1✔
2918
                if err != nil {
1✔
2919
                        return nil, err
×
2920
                }
×
2921
        }
2922
        return logUpdates, nil
1✔
2923
}
2924

2925
func serializeCommitDiff(w io.Writer, diff *CommitDiff) error { // nolint: dupl
1✔
2926
        if err := serializeChanCommit(w, &diff.Commitment); err != nil {
1✔
2927
                return err
×
2928
        }
×
2929

2930
        if err := WriteElements(w, diff.CommitSig); err != nil {
1✔
2931
                return err
×
2932
        }
×
2933

2934
        if err := serializeLogUpdates(w, diff.LogUpdates); err != nil {
1✔
2935
                return err
×
2936
        }
×
2937

2938
        numOpenRefs := uint16(len(diff.OpenedCircuitKeys))
1✔
2939
        if err := binary.Write(w, byteOrder, numOpenRefs); err != nil {
1✔
2940
                return err
×
2941
        }
×
2942

2943
        for _, openRef := range diff.OpenedCircuitKeys {
2✔
2944
                err := WriteElements(w, openRef.ChanID, openRef.HtlcID)
1✔
2945
                if err != nil {
1✔
2946
                        return err
×
2947
                }
×
2948
        }
2949

2950
        numClosedRefs := uint16(len(diff.ClosedCircuitKeys))
1✔
2951
        if err := binary.Write(w, byteOrder, numClosedRefs); err != nil {
1✔
2952
                return err
×
2953
        }
×
2954

2955
        for _, closedRef := range diff.ClosedCircuitKeys {
2✔
2956
                err := WriteElements(w, closedRef.ChanID, closedRef.HtlcID)
1✔
2957
                if err != nil {
1✔
2958
                        return err
×
2959
                }
×
2960
        }
2961

2962
        // We'll also encode the commit aux data stream here. We do this here
2963
        // rather than above (at the call to serializeChanCommit), to ensure
2964
        // backwards compat for reads to existing non-custom channels.
2965
        auxData := diff.Commitment.extractTlvData()
1✔
2966
        if err := auxData.encode(w); err != nil {
1✔
2967
                return fmt.Errorf("unable to write aux data: %w", err)
×
2968
        }
×
2969

2970
        return nil
1✔
2971
}
2972

2973
func deserializeCommitDiff(r io.Reader) (*CommitDiff, error) {
1✔
2974
        var (
1✔
2975
                d   CommitDiff
1✔
2976
                err error
1✔
2977
        )
1✔
2978

1✔
2979
        d.Commitment, err = deserializeChanCommit(r)
1✔
2980
        if err != nil {
1✔
2981
                return nil, err
×
2982
        }
×
2983

2984
        var msg lnwire.Message
1✔
2985
        if err := ReadElements(r, &msg); err != nil {
1✔
2986
                return nil, err
×
2987
        }
×
2988
        commitSig, ok := msg.(*lnwire.CommitSig)
1✔
2989
        if !ok {
1✔
2990
                return nil, fmt.Errorf("expected lnwire.CommitSig, instead "+
×
2991
                        "read: %T", msg)
×
2992
        }
×
2993
        d.CommitSig = commitSig
1✔
2994

1✔
2995
        d.LogUpdates, err = deserializeLogUpdates(r)
1✔
2996
        if err != nil {
1✔
2997
                return nil, err
×
2998
        }
×
2999

3000
        var numOpenRefs uint16
1✔
3001
        if err := binary.Read(r, byteOrder, &numOpenRefs); err != nil {
1✔
3002
                return nil, err
×
3003
        }
×
3004

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

3015
        var numClosedRefs uint16
1✔
3016
        if err := binary.Read(r, byteOrder, &numClosedRefs); err != nil {
1✔
3017
                return nil, err
×
3018
        }
×
3019

3020
        d.ClosedCircuitKeys = make([]models.CircuitKey, numClosedRefs)
1✔
3021
        for i := 0; i < int(numClosedRefs); i++ {
2✔
3022
                err := ReadElements(r,
1✔
3023
                        &d.ClosedCircuitKeys[i].ChanID,
1✔
3024
                        &d.ClosedCircuitKeys[i].HtlcID)
1✔
3025
                if err != nil {
1✔
3026
                        return nil, err
×
3027
                }
×
3028
        }
3029

3030
        // As a final step, we'll read out any aux commit data that we have at
3031
        // the end of this byte stream. We do this here to ensure backward
3032
        // compatibility, as otherwise we risk erroneously reading into the
3033
        // wrong field.
3034
        var auxData commitTlvData
1✔
3035
        if err := auxData.decode(r); err != nil {
1✔
3036
                return nil, fmt.Errorf("unable to decode aux data: %w", err)
×
3037
        }
×
3038

3039
        d.Commitment.amendTlvData(auxData)
1✔
3040

1✔
3041
        return &d, nil
1✔
3042
}
3043

3044
// AppendRemoteCommitChain appends a new CommitDiff to the end of the
3045
// commitment chain for the remote party. This method is to be used once we
3046
// have prepared a new commitment state for the remote party, but before we
3047
// transmit it to the remote party. The contents of the argument should be
3048
// sufficient to retransmit the updates and signature needed to reconstruct the
3049
// state in full, in the case that we need to retransmit.
3050
func (c *OpenChannel) AppendRemoteCommitChain(diff *CommitDiff) error {
1✔
3051
        c.Lock()
1✔
3052
        defer c.Unlock()
1✔
3053

1✔
3054
        // If this is a restored channel, then we want to avoid mutating the
1✔
3055
        // state at all, as it's impossible to do so in a protocol compliant
1✔
3056
        // manner.
1✔
3057
        if c.hasChanStatus(ChanStatusRestored) {
1✔
UNCOV
3058
                return ErrNoRestoredChannelMutation
×
UNCOV
3059
        }
×
3060

3061
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
3062
                // First, we'll grab the writable bucket where this channel's
1✔
3063
                // data resides.
1✔
3064
                chanBucket, err := fetchChanBucketRw(
1✔
3065
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
3066
                )
1✔
3067
                if err != nil {
1✔
3068
                        return err
×
3069
                }
×
3070

3071
                // If the channel is marked as borked, then for safety reasons,
3072
                // we shouldn't attempt any further updates.
3073
                isBorked, err := c.isBorked(chanBucket)
1✔
3074
                if err != nil {
1✔
3075
                        return err
×
3076
                }
×
3077
                if isBorked {
1✔
UNCOV
3078
                        return ErrChanBorked
×
UNCOV
3079
                }
×
3080

3081
                // Any outgoing settles and fails necessarily have a
3082
                // corresponding adds in this channel's forwarding packages.
3083
                // Mark all of these as being fully processed in our forwarding
3084
                // package, which prevents us from reprocessing them after
3085
                // startup.
3086
                err = c.Packager.AckAddHtlcs(tx, diff.AddAcks...)
1✔
3087
                if err != nil {
1✔
3088
                        return err
×
3089
                }
×
3090

3091
                // Additionally, we ack from any fails or settles that are
3092
                // persisted in another channel's forwarding package. This
3093
                // prevents the same fails and settles from being retransmitted
3094
                // after restarts. The actual fail or settle we need to
3095
                // propagate to the remote party is now in the commit diff.
3096
                err = c.Packager.AckSettleFails(tx, diff.SettleFailAcks...)
1✔
3097
                if err != nil {
1✔
3098
                        return err
×
3099
                }
×
3100

3101
                // We are sending a commitment signature so lastWasRevokeKey should
3102
                // store false.
3103
                var b bytes.Buffer
1✔
3104
                if err := WriteElements(&b, false); err != nil {
1✔
3105
                        return err
×
3106
                }
×
3107
                if err := chanBucket.Put(lastWasRevokeKey, b.Bytes()); err != nil {
1✔
3108
                        return err
×
3109
                }
×
3110

3111
                // TODO(roasbeef): use seqno to derive key for later LCP
3112

3113
                // With the bucket retrieved, we'll now serialize the commit
3114
                // diff itself, and write it to disk.
3115
                var b2 bytes.Buffer
1✔
3116
                if err := serializeCommitDiff(&b2, diff); err != nil {
1✔
3117
                        return err
×
3118
                }
×
3119
                return chanBucket.Put(commitDiffKey, b2.Bytes())
1✔
3120
        }, func() {})
1✔
3121
}
3122

3123
// RemoteCommitChainTip returns the "tip" of the current remote commitment
3124
// chain. This value will be non-nil iff, we've created a new commitment for
3125
// the remote party that they haven't yet ACK'd. In this case, their commitment
3126
// chain will have a length of two: their current unrevoked commitment, and
3127
// this new pending commitment. Once they revoked their prior state, we'll swap
3128
// these pointers, causing the tip and the tail to point to the same entry.
3129
func (c *OpenChannel) RemoteCommitChainTip() (*CommitDiff, error) {
1✔
3130
        var cd *CommitDiff
1✔
3131
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2✔
3132
                chanBucket, err := fetchChanBucket(
1✔
3133
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
3134
                )
1✔
3135
                switch err {
1✔
3136
                case nil:
1✔
3137
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
1✔
3138
                        return ErrNoPendingCommit
1✔
3139
                default:
×
3140
                        return err
×
3141
                }
3142

3143
                tipBytes := chanBucket.Get(commitDiffKey)
1✔
3144
                if tipBytes == nil {
2✔
3145
                        return ErrNoPendingCommit
1✔
3146
                }
1✔
3147

3148
                tipReader := bytes.NewReader(tipBytes)
1✔
3149
                dcd, err := deserializeCommitDiff(tipReader)
1✔
3150
                if err != nil {
1✔
3151
                        return err
×
3152
                }
×
3153

3154
                cd = dcd
1✔
3155
                return nil
1✔
3156
        }, func() {
1✔
3157
                cd = nil
1✔
3158
        })
1✔
3159
        if err != nil {
2✔
3160
                return nil, err
1✔
3161
        }
1✔
3162

3163
        return cd, nil
1✔
3164
}
3165

3166
// UnsignedAckedUpdates retrieves the persisted unsigned acked remote log
3167
// updates that still need to be signed for.
3168
func (c *OpenChannel) UnsignedAckedUpdates() ([]LogUpdate, error) {
1✔
3169
        var updates []LogUpdate
1✔
3170
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2✔
3171
                chanBucket, err := fetchChanBucket(
1✔
3172
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
3173
                )
1✔
3174
                switch err {
1✔
3175
                case nil:
1✔
3176
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
1✔
3177
                        return nil
1✔
3178
                default:
×
3179
                        return err
×
3180
                }
3181

3182
                updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
1✔
3183
                if updateBytes == nil {
2✔
3184
                        return nil
1✔
3185
                }
1✔
3186

3187
                r := bytes.NewReader(updateBytes)
1✔
3188
                updates, err = deserializeLogUpdates(r)
1✔
3189
                return err
1✔
3190
        }, func() {
1✔
3191
                updates = nil
1✔
3192
        })
1✔
3193
        if err != nil {
1✔
3194
                return nil, err
×
3195
        }
×
3196

3197
        return updates, nil
1✔
3198
}
3199

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

3217
                updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
1✔
3218
                if updateBytes == nil {
2✔
3219
                        return nil
1✔
3220
                }
1✔
3221

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

3232
        return updates, nil
1✔
3233
}
3234

3235
// InsertNextRevocation inserts the _next_ commitment point (revocation) into
3236
// the database, and also modifies the internal RemoteNextRevocation attribute
3237
// to point to the passed key. This method is to be using during final channel
3238
// set up, _after_ the channel has been fully confirmed.
3239
//
3240
// NOTE: If this method isn't called, then the target channel won't be able to
3241
// propose new states for the commitment state of the remote party.
3242
func (c *OpenChannel) InsertNextRevocation(revKey *btcec.PublicKey) error {
1✔
3243
        c.Lock()
1✔
3244
        defer c.Unlock()
1✔
3245

1✔
3246
        c.RemoteNextRevocation = revKey
1✔
3247

1✔
3248
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
3249
                chanBucket, err := fetchChanBucketRw(
1✔
3250
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
3251
                )
1✔
3252
                if err != nil {
1✔
3253
                        return err
×
3254
                }
×
3255

3256
                return putChanRevocationState(chanBucket, c)
1✔
3257
        }, func() {})
1✔
3258
        if err != nil {
1✔
3259
                return err
×
3260
        }
×
3261

3262
        return nil
1✔
3263
}
3264

3265
// AdvanceCommitChainTail records the new state transition within an on-disk
3266
// append-only log which records all state transitions by the remote peer. In
3267
// the case of an uncooperative broadcast of a prior state by the remote peer,
3268
// this log can be consulted in order to reconstruct the state needed to
3269
// rectify the situation. This method will add the current commitment for the
3270
// remote party to the revocation log, and promote the current pending
3271
// commitment to the current remote commitment. The updates parameter is the
3272
// set of local updates that the peer still needs to send us a signature for.
3273
// We store this set of updates in case we go down.
3274
func (c *OpenChannel) AdvanceCommitChainTail(fwdPkg *FwdPkg,
3275
        updates []LogUpdate, ourOutputIndex, theirOutputIndex uint32) error {
1✔
3276

1✔
3277
        c.Lock()
1✔
3278
        defer c.Unlock()
1✔
3279

1✔
3280
        // If this is a restored channel, then we want to avoid mutating the
1✔
3281
        // state at all, as it's impossible to do so in a protocol compliant
1✔
3282
        // manner.
1✔
3283
        if c.hasChanStatus(ChanStatusRestored) {
1✔
UNCOV
3284
                return ErrNoRestoredChannelMutation
×
UNCOV
3285
        }
×
3286

3287
        var newRemoteCommit *ChannelCommitment
1✔
3288

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

3297
                // If the channel is marked as borked, then for safety reasons,
3298
                // we shouldn't attempt any further updates.
3299
                isBorked, err := c.isBorked(chanBucket)
1✔
3300
                if err != nil {
1✔
3301
                        return err
×
3302
                }
×
3303
                if isBorked {
1✔
UNCOV
3304
                        return ErrChanBorked
×
UNCOV
3305
                }
×
3306

3307
                // Persist the latest preimage state to disk as the remote peer
3308
                // has just added to our local preimage store, and given us a
3309
                // new pending revocation key.
3310
                if err := putChanRevocationState(chanBucket, c); err != nil {
1✔
3311
                        return err
×
3312
                }
×
3313

3314
                // With the current preimage producer/store state updated,
3315
                // append a new log entry recording this the delta of this
3316
                // state transition.
3317
                //
3318
                // TODO(roasbeef): could make the deltas relative, would save
3319
                // space, but then tradeoff for more disk-seeks to recover the
3320
                // full state.
3321
                logKey := revocationLogBucket
1✔
3322
                logBucket, err := chanBucket.CreateBucketIfNotExists(logKey)
1✔
3323
                if err != nil {
1✔
3324
                        return err
×
3325
                }
×
3326

3327
                // Before we append this revoked state to the revocation log,
3328
                // we'll swap out what's currently the tail of the commit tip,
3329
                // with the current locked-in commitment for the remote party.
3330
                tipBytes := chanBucket.Get(commitDiffKey)
1✔
3331
                tipReader := bytes.NewReader(tipBytes)
1✔
3332
                newCommit, err := deserializeCommitDiff(tipReader)
1✔
3333
                if err != nil {
1✔
3334
                        return err
×
3335
                }
×
3336
                err = putChanCommitment(
1✔
3337
                        chanBucket, &newCommit.Commitment, false,
1✔
3338
                )
1✔
3339
                if err != nil {
1✔
3340
                        return err
×
3341
                }
×
3342
                if err := chanBucket.Delete(commitDiffKey); err != nil {
1✔
3343
                        return err
×
3344
                }
×
3345

3346
                // With the commitment pointer swapped, we can now add the
3347
                // revoked (prior) state to the revocation log.
3348
                err = putRevocationLog(
1✔
3349
                        logBucket, &c.RemoteCommitment, ourOutputIndex,
1✔
3350
                        theirOutputIndex, c.Db.parent.noRevLogAmtData,
1✔
3351
                )
1✔
3352
                if err != nil {
1✔
3353
                        return err
×
3354
                }
×
3355

3356
                // Lastly, we write the forwarding package to disk so that we
3357
                // can properly recover from failures and reforward HTLCs that
3358
                // have not received a corresponding settle/fail.
3359
                if err := c.Packager.AddFwdPkg(tx, fwdPkg); err != nil {
1✔
3360
                        return err
×
3361
                }
×
3362

3363
                // Persist the unsigned acked updates that are not included
3364
                // in their new commitment.
3365
                updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
1✔
3366
                if updateBytes == nil {
2✔
3367
                        // This shouldn't normally happen as we always store
1✔
3368
                        // the number of updates, but could still be
1✔
3369
                        // encountered by nodes that are upgrading.
1✔
3370
                        newRemoteCommit = &newCommit.Commitment
1✔
3371
                        return nil
1✔
3372
                }
1✔
3373

3374
                r := bytes.NewReader(updateBytes)
1✔
3375
                unsignedUpdates, err := deserializeLogUpdates(r)
1✔
3376
                if err != nil {
1✔
3377
                        return err
×
3378
                }
×
3379

3380
                var validUpdates []LogUpdate
1✔
3381
                for _, upd := range unsignedUpdates {
2✔
3382
                        lIdx := upd.LogIndex
1✔
3383

1✔
3384
                        // Filter for updates that are not on the remote
1✔
3385
                        // commitment.
1✔
3386
                        if lIdx >= newCommit.Commitment.RemoteLogIndex {
2✔
3387
                                validUpdates = append(validUpdates, upd)
1✔
3388
                        }
1✔
3389
                }
3390

3391
                var b bytes.Buffer
1✔
3392
                err = serializeLogUpdates(&b, validUpdates)
1✔
3393
                if err != nil {
1✔
3394
                        return fmt.Errorf("unable to serialize log updates: %w",
×
3395
                                err)
×
3396
                }
×
3397

3398
                err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes())
1✔
3399
                if err != nil {
1✔
3400
                        return fmt.Errorf("unable to store under "+
×
3401
                                "unsignedAckedUpdatesKey: %w", err)
×
3402
                }
×
3403

3404
                // Persist the local updates the peer hasn't yet signed so they
3405
                // can be restored after restart.
3406
                var b2 bytes.Buffer
1✔
3407
                err = serializeLogUpdates(&b2, updates)
1✔
3408
                if err != nil {
1✔
3409
                        return err
×
3410
                }
×
3411

3412
                err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b2.Bytes())
1✔
3413
                if err != nil {
1✔
3414
                        return fmt.Errorf("unable to restore remote unsigned "+
×
3415
                                "local updates: %v", err)
×
3416
                }
×
3417

3418
                newRemoteCommit = &newCommit.Commitment
1✔
3419

1✔
3420
                return nil
1✔
3421
        }, func() {
1✔
3422
                newRemoteCommit = nil
1✔
3423
        })
1✔
3424
        if err != nil {
1✔
UNCOV
3425
                return err
×
UNCOV
3426
        }
×
3427

3428
        // With the db transaction complete, we'll swap over the in-memory
3429
        // pointer of the new remote commitment, which was previously the tip
3430
        // of the commit chain.
3431
        c.RemoteCommitment = *newRemoteCommit
1✔
3432

1✔
3433
        return nil
1✔
3434
}
3435

3436
// FinalHtlcInfo contains information about the final outcome of an htlc.
3437
type FinalHtlcInfo struct {
3438
        // Settled is true is the htlc was settled. If false, the htlc was
3439
        // failed.
3440
        Settled bool
3441

3442
        // Offchain indicates whether the htlc was resolved off-chain or
3443
        // on-chain.
3444
        Offchain bool
3445
}
3446

3447
// putFinalHtlc writes the final htlc outcome to the database. Additionally it
3448
// records whether the htlc was resolved off-chain or on-chain.
3449
func putFinalHtlc(finalHtlcsBucket kvdb.RwBucket, id uint64,
3450
        info FinalHtlcInfo) error {
1✔
3451

1✔
3452
        var key [8]byte
1✔
3453
        byteOrder.PutUint64(key[:], id)
1✔
3454

1✔
3455
        var finalHtlcByte FinalHtlcByte
1✔
3456
        if info.Settled {
2✔
3457
                finalHtlcByte |= FinalHtlcSettledBit
1✔
3458
        }
1✔
3459
        if info.Offchain {
2✔
3460
                finalHtlcByte |= FinalHtlcOffchainBit
1✔
3461
        }
1✔
3462

3463
        return finalHtlcsBucket.Put(key[:], []byte{byte(finalHtlcByte)})
1✔
3464
}
3465

3466
// NextLocalHtlcIndex returns the next unallocated local htlc index. To ensure
3467
// this always returns the next index that has been not been allocated, this
3468
// will first try to examine any pending commitments, before falling back to the
3469
// last locked-in remote commitment.
3470
func (c *OpenChannel) NextLocalHtlcIndex() (uint64, error) {
1✔
3471
        // First, load the most recent commit diff that we initiated for the
1✔
3472
        // remote party. If no pending commit is found, this is not treated as
1✔
3473
        // a critical error, since we can always fall back.
1✔
3474
        pendingRemoteCommit, err := c.RemoteCommitChainTip()
1✔
3475
        if err != nil && err != ErrNoPendingCommit {
1✔
3476
                return 0, err
×
3477
        }
×
3478

3479
        // If a pending commit was found, its local htlc index will be at least
3480
        // as large as the one on our local commitment.
3481
        if pendingRemoteCommit != nil {
1✔
UNCOV
3482
                return pendingRemoteCommit.Commitment.LocalHtlcIndex, nil
×
UNCOV
3483
        }
×
3484

3485
        // Otherwise, fallback to using the local htlc index of their commitment.
3486
        return c.RemoteCommitment.LocalHtlcIndex, nil
1✔
3487
}
3488

3489
// LoadFwdPkgs scans the forwarding log for any packages that haven't been
3490
// processed, and returns their deserialized log updates in map indexed by the
3491
// remote commitment height at which the updates were locked in.
3492
func (c *OpenChannel) LoadFwdPkgs() ([]*FwdPkg, error) {
1✔
3493
        c.RLock()
1✔
3494
        defer c.RUnlock()
1✔
3495

1✔
3496
        var fwdPkgs []*FwdPkg
1✔
3497
        if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2✔
3498
                var err error
1✔
3499
                fwdPkgs, err = c.Packager.LoadFwdPkgs(tx)
1✔
3500
                return err
1✔
3501
        }, func() {
2✔
3502
                fwdPkgs = nil
1✔
3503
        }); err != nil {
1✔
UNCOV
3504
                return nil, err
×
UNCOV
3505
        }
×
3506

3507
        return fwdPkgs, nil
1✔
3508
}
3509

3510
// AckAddHtlcs updates the AckAddFilter containing any of the provided AddRefs
3511
// indicating that a response to this Add has been committed to the remote party.
3512
// Doing so will prevent these Add HTLCs from being reforwarded internally.
UNCOV
3513
func (c *OpenChannel) AckAddHtlcs(addRefs ...AddRef) error {
×
UNCOV
3514
        c.Lock()
×
UNCOV
3515
        defer c.Unlock()
×
UNCOV
3516

×
UNCOV
3517
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
UNCOV
3518
                return c.Packager.AckAddHtlcs(tx, addRefs...)
×
UNCOV
3519
        }, func() {})
×
3520
}
3521

3522
// AckSettleFails updates the SettleFailFilter containing any of the provided
3523
// SettleFailRefs, indicating that the response has been delivered to the
3524
// incoming link, corresponding to a particular AddRef. Doing so will prevent
3525
// the responses from being retransmitted internally.
3526
func (c *OpenChannel) AckSettleFails(settleFailRefs ...SettleFailRef) error {
×
3527
        c.Lock()
×
3528
        defer c.Unlock()
×
3529

×
3530
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
3531
                return c.Packager.AckSettleFails(tx, settleFailRefs...)
×
3532
        }, func() {})
×
3533
}
3534

3535
// SetFwdFilter atomically sets the forwarding filter for the forwarding package
3536
// identified by `height`.
3537
func (c *OpenChannel) SetFwdFilter(height uint64, fwdFilter *PkgFilter) error {
1✔
3538
        c.Lock()
1✔
3539
        defer c.Unlock()
1✔
3540

1✔
3541
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
3542
                return c.Packager.SetFwdFilter(tx, height, fwdFilter)
1✔
3543
        }, func() {})
2✔
3544
}
3545

3546
// RemoveFwdPkgs atomically removes forwarding packages specified by the remote
3547
// commitment heights. If one of the intermediate RemovePkg calls fails, then the
3548
// later packages won't be removed.
3549
//
3550
// NOTE: This method should only be called on packages marked FwdStateCompleted.
3551
func (c *OpenChannel) RemoveFwdPkgs(heights ...uint64) error {
1✔
3552
        c.Lock()
1✔
3553
        defer c.Unlock()
1✔
3554

1✔
3555
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
3556
                for _, height := range heights {
2✔
3557
                        err := c.Packager.RemovePkg(tx, height)
1✔
3558
                        if err != nil {
1✔
3559
                                return err
×
3560
                        }
×
3561
                }
3562

3563
                return nil
1✔
3564
        }, func() {})
1✔
3565
}
3566

3567
// revocationLogTailCommitHeight returns the commit height at the end of the
3568
// revocation log. This entry represents the last previous state for the remote
3569
// node's commitment chain. The ChannelDelta returned by this method will
3570
// always lag one state behind the most current (unrevoked) state of the remote
3571
// node's commitment chain.
3572
// NOTE: used in unit test only.
UNCOV
3573
func (c *OpenChannel) revocationLogTailCommitHeight() (uint64, error) {
×
UNCOV
3574
        c.RLock()
×
UNCOV
3575
        defer c.RUnlock()
×
UNCOV
3576

×
UNCOV
3577
        var height uint64
×
UNCOV
3578

×
UNCOV
3579
        // If we haven't created any state updates yet, then we'll exit early as
×
UNCOV
3580
        // there's nothing to be found on disk in the revocation bucket.
×
UNCOV
3581
        if c.RemoteCommitment.CommitHeight == 0 {
×
3582
                return height, nil
×
3583
        }
×
3584

UNCOV
3585
        if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
×
UNCOV
3586
                chanBucket, err := fetchChanBucket(
×
UNCOV
3587
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
×
UNCOV
3588
                )
×
UNCOV
3589
                if err != nil {
×
3590
                        return err
×
3591
                }
×
3592

UNCOV
3593
                logBucket, err := fetchLogBucket(chanBucket)
×
UNCOV
3594
                if err != nil {
×
3595
                        return err
×
3596
                }
×
3597

3598
                // Once we have the bucket that stores the revocation log from
3599
                // this channel, we'll jump to the _last_ key in bucket. Since
3600
                // the key is the commit height, we'll decode the bytes and
3601
                // return it.
UNCOV
3602
                cursor := logBucket.ReadCursor()
×
UNCOV
3603
                rawHeight, _ := cursor.Last()
×
UNCOV
3604
                height = byteOrder.Uint64(rawHeight)
×
UNCOV
3605

×
UNCOV
3606
                return nil
×
UNCOV
3607
        }, func() {}); err != nil {
×
3608
                return height, err
×
3609
        }
×
3610

UNCOV
3611
        return height, nil
×
3612
}
3613

3614
// CommitmentHeight returns the current commitment height. The commitment
3615
// height represents the number of updates to the commitment state to date.
3616
// This value is always monotonically increasing. This method is provided in
3617
// order to allow multiple instances of a particular open channel to obtain a
3618
// consistent view of the number of channel updates to date.
UNCOV
3619
func (c *OpenChannel) CommitmentHeight() (uint64, error) {
×
UNCOV
3620
        c.RLock()
×
UNCOV
3621
        defer c.RUnlock()
×
UNCOV
3622

×
UNCOV
3623
        var height uint64
×
UNCOV
3624
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
×
UNCOV
3625
                // Get the bucket dedicated to storing the metadata for open
×
UNCOV
3626
                // channels.
×
UNCOV
3627
                chanBucket, err := fetchChanBucket(
×
UNCOV
3628
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
×
UNCOV
3629
                )
×
UNCOV
3630
                if err != nil {
×
3631
                        return err
×
3632
                }
×
3633

UNCOV
3634
                commit, err := fetchChanCommitment(chanBucket, true)
×
UNCOV
3635
                if err != nil {
×
3636
                        return err
×
3637
                }
×
3638

UNCOV
3639
                height = commit.CommitHeight
×
UNCOV
3640
                return nil
×
UNCOV
3641
        }, func() {
×
UNCOV
3642
                height = 0
×
UNCOV
3643
        })
×
UNCOV
3644
        if err != nil {
×
3645
                return 0, err
×
3646
        }
×
3647

UNCOV
3648
        return height, nil
×
3649
}
3650

3651
// FindPreviousState scans through the append-only log in an attempt to recover
3652
// the previous channel state indicated by the update number. This method is
3653
// intended to be used for obtaining the relevant data needed to claim all
3654
// funds rightfully spendable in the case of an on-chain broadcast of the
3655
// commitment transaction.
3656
func (c *OpenChannel) FindPreviousState(
3657
        updateNum uint64) (*RevocationLog, *ChannelCommitment, error) {
1✔
3658

1✔
3659
        c.RLock()
1✔
3660
        defer c.RUnlock()
1✔
3661

1✔
3662
        commit := &ChannelCommitment{}
1✔
3663
        rl := &RevocationLog{}
1✔
3664

1✔
3665
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2✔
3666
                chanBucket, err := fetchChanBucket(
1✔
3667
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
3668
                )
1✔
3669
                if err != nil {
1✔
UNCOV
3670
                        return err
×
UNCOV
3671
                }
×
3672

3673
                // Find the revocation log from both the new and the old
3674
                // bucket.
3675
                r, c, err := fetchRevocationLogCompatible(chanBucket, updateNum)
1✔
3676
                if err != nil {
2✔
3677
                        return err
1✔
3678
                }
1✔
3679

3680
                rl = r
1✔
3681
                commit = c
1✔
3682
                return nil
1✔
3683
        }, func() {})
1✔
3684
        if err != nil {
2✔
3685
                return nil, nil, err
1✔
3686
        }
1✔
3687

3688
        // Either the `rl` or the `commit` is nil here. We return them as-is
3689
        // and leave it to the caller to decide its following action.
3690
        return rl, commit, nil
1✔
3691
}
3692

3693
// ClosureType is an enum like structure that details exactly _how_ a channel
3694
// was closed. Three closure types are currently possible: none, cooperative,
3695
// local force close, remote force close, and (remote) breach.
3696
type ClosureType uint8
3697

3698
const (
3699
        // CooperativeClose indicates that a channel has been closed
3700
        // cooperatively.  This means that both channel peers were online and
3701
        // signed a new transaction paying out the settled balance of the
3702
        // contract.
3703
        CooperativeClose ClosureType = 0
3704

3705
        // LocalForceClose indicates that we have unilaterally broadcast our
3706
        // current commitment state on-chain.
3707
        LocalForceClose ClosureType = 1
3708

3709
        // RemoteForceClose indicates that the remote peer has unilaterally
3710
        // broadcast their current commitment state on-chain.
3711
        RemoteForceClose ClosureType = 4
3712

3713
        // BreachClose indicates that the remote peer attempted to broadcast a
3714
        // prior _revoked_ channel state.
3715
        BreachClose ClosureType = 2
3716

3717
        // FundingCanceled indicates that the channel never was fully opened
3718
        // before it was marked as closed in the database. This can happen if
3719
        // we or the remote fail at some point during the opening workflow, or
3720
        // we timeout waiting for the funding transaction to be confirmed.
3721
        FundingCanceled ClosureType = 3
3722

3723
        // Abandoned indicates that the channel state was removed without
3724
        // any further actions. This is intended to clean up unusable
3725
        // channels during development.
3726
        Abandoned ClosureType = 5
3727
)
3728

3729
// ChannelCloseSummary contains the final state of a channel at the point it
3730
// was closed. Once a channel is closed, all the information pertaining to that
3731
// channel within the openChannelBucket is deleted, and a compact summary is
3732
// put in place instead.
3733
type ChannelCloseSummary struct {
3734
        // ChanPoint is the outpoint for this channel's funding transaction,
3735
        // and is used as a unique identifier for the channel.
3736
        ChanPoint wire.OutPoint
3737

3738
        // ShortChanID encodes the exact location in the chain in which the
3739
        // channel was initially confirmed. This includes: the block height,
3740
        // transaction index, and the output within the target transaction.
3741
        ShortChanID lnwire.ShortChannelID
3742

3743
        // ChainHash is the hash of the genesis block that this channel resides
3744
        // within.
3745
        ChainHash chainhash.Hash
3746

3747
        // ClosingTXID is the txid of the transaction which ultimately closed
3748
        // this channel.
3749
        ClosingTXID chainhash.Hash
3750

3751
        // RemotePub is the public key of the remote peer that we formerly had
3752
        // a channel with.
3753
        RemotePub *btcec.PublicKey
3754

3755
        // Capacity was the total capacity of the channel.
3756
        Capacity btcutil.Amount
3757

3758
        // CloseHeight is the height at which the funding transaction was
3759
        // spent.
3760
        CloseHeight uint32
3761

3762
        // SettledBalance is our total balance settled balance at the time of
3763
        // channel closure. This _does not_ include the sum of any outputs that
3764
        // have been time-locked as a result of the unilateral channel closure.
3765
        SettledBalance btcutil.Amount
3766

3767
        // TimeLockedBalance is the sum of all the time-locked outputs at the
3768
        // time of channel closure. If we triggered the force closure of this
3769
        // channel, then this value will be non-zero if our settled output is
3770
        // above the dust limit. If we were on the receiving side of a channel
3771
        // force closure, then this value will be non-zero if we had any
3772
        // outstanding outgoing HTLC's at the time of channel closure.
3773
        TimeLockedBalance btcutil.Amount
3774

3775
        // CloseType details exactly _how_ the channel was closed. Five closure
3776
        // types are possible: cooperative, local force, remote force, breach
3777
        // and funding canceled.
3778
        CloseType ClosureType
3779

3780
        // IsPending indicates whether this channel is in the 'pending close'
3781
        // state, which means the channel closing transaction has been
3782
        // confirmed, but not yet been fully resolved. In the case of a channel
3783
        // that has been cooperatively closed, it will go straight into the
3784
        // fully resolved state as soon as the closing transaction has been
3785
        // confirmed. However, for channels that have been force closed, they'll
3786
        // stay marked as "pending" until _all_ the pending funds have been
3787
        // swept.
3788
        IsPending bool
3789

3790
        // RemoteCurrentRevocation is the current revocation for their
3791
        // commitment transaction. However, since this is the derived public key,
3792
        // we don't yet have the private key so we aren't yet able to verify
3793
        // that it's actually in the hash chain.
3794
        RemoteCurrentRevocation *btcec.PublicKey
3795

3796
        // RemoteNextRevocation is the revocation key to be used for the *next*
3797
        // commitment transaction we create for the local node. Within the
3798
        // specification, this value is referred to as the
3799
        // per-commitment-point.
3800
        RemoteNextRevocation *btcec.PublicKey
3801

3802
        // LocalChanConfig is the channel configuration for the local node.
3803
        LocalChanConfig ChannelConfig
3804

3805
        // LastChanSyncMsg is the ChannelReestablish message for this channel
3806
        // for the state at the point where it was closed.
3807
        LastChanSyncMsg *lnwire.ChannelReestablish
3808
}
3809

3810
// CloseChannel closes a previously active Lightning channel. Closing a channel
3811
// entails deleting all saved state within the database concerning this
3812
// channel. This method also takes a struct that summarizes the state of the
3813
// channel at closing, this compact representation will be the only component
3814
// of a channel left over after a full closing. It takes an optional set of
3815
// channel statuses which will be written to the historical channel bucket.
3816
// These statuses are used to record close initiators.
3817
func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary,
3818
        statuses ...ChannelStatus) error {
1✔
3819

1✔
3820
        c.Lock()
1✔
3821
        defer c.Unlock()
1✔
3822

1✔
3823
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
3824
                openChanBucket := tx.ReadWriteBucket(openChannelBucket)
1✔
3825
                if openChanBucket == nil {
1✔
3826
                        return ErrNoChanDBExists
×
3827
                }
×
3828

3829
                nodePub := c.IdentityPub.SerializeCompressed()
1✔
3830
                nodeChanBucket := openChanBucket.NestedReadWriteBucket(nodePub)
1✔
3831
                if nodeChanBucket == nil {
1✔
3832
                        return ErrNoActiveChannels
×
3833
                }
×
3834

3835
                chainBucket := nodeChanBucket.NestedReadWriteBucket(c.ChainHash[:])
1✔
3836
                if chainBucket == nil {
1✔
3837
                        return ErrNoActiveChannels
×
3838
                }
×
3839

3840
                var chanPointBuf bytes.Buffer
1✔
3841
                err := graphdb.WriteOutpoint(&chanPointBuf, &c.FundingOutpoint)
1✔
3842
                if err != nil {
1✔
3843
                        return err
×
3844
                }
×
3845
                chanKey := chanPointBuf.Bytes()
1✔
3846
                chanBucket := chainBucket.NestedReadWriteBucket(
1✔
3847
                        chanKey,
1✔
3848
                )
1✔
3849
                if chanBucket == nil {
1✔
3850
                        return ErrNoActiveChannels
×
3851
                }
×
3852

3853
                // Before we delete the channel state, we'll read out the full
3854
                // details, as we'll also store portions of this information
3855
                // for record keeping.
3856
                chanState, err := fetchOpenChannel(
1✔
3857
                        chanBucket, &c.FundingOutpoint,
1✔
3858
                )
1✔
3859
                if err != nil {
1✔
3860
                        return err
×
3861
                }
×
3862

3863
                // Delete all the forwarding packages stored for this particular
3864
                // channel.
3865
                if err = chanState.Packager.Wipe(tx); err != nil {
1✔
3866
                        return err
×
3867
                }
×
3868

3869
                // Now that the index to this channel has been deleted, purge
3870
                // the remaining channel metadata from the database.
3871
                err = deleteOpenChannel(chanBucket)
1✔
3872
                if err != nil {
1✔
3873
                        return err
×
3874
                }
×
3875

3876
                // We'll also remove the channel from the frozen channel bucket
3877
                // if we need to.
3878
                if c.ChanType.IsFrozen() || c.ChanType.HasLeaseExpiration() {
2✔
3879
                        err := deleteThawHeight(chanBucket)
1✔
3880
                        if err != nil {
1✔
3881
                                return err
×
3882
                        }
×
3883
                }
3884

3885
                // With the base channel data deleted, attempt to delete the
3886
                // information stored within the revocation log.
3887
                if err := deleteLogBucket(chanBucket); err != nil {
1✔
3888
                        return err
×
3889
                }
×
3890

3891
                err = chainBucket.DeleteNestedBucket(chanPointBuf.Bytes())
1✔
3892
                if err != nil {
1✔
3893
                        return err
×
3894
                }
×
3895

3896
                // Fetch the outpoint bucket to see if the outpoint exists or
3897
                // not.
3898
                opBucket := tx.ReadWriteBucket(outpointBucket)
1✔
3899
                if opBucket == nil {
1✔
3900
                        return ErrNoChanDBExists
×
3901
                }
×
3902

3903
                // Add the closed outpoint to our outpoint index. This should
3904
                // replace an open outpoint in the index.
3905
                if opBucket.Get(chanPointBuf.Bytes()) == nil {
1✔
3906
                        return ErrMissingIndexEntry
×
3907
                }
×
3908

3909
                status := uint8(outpointClosed)
1✔
3910

1✔
3911
                // Write the IndexStatus of this outpoint as the first entry in a tlv
1✔
3912
                // stream.
1✔
3913
                statusRecord := tlv.MakePrimitiveRecord(indexStatusType, &status)
1✔
3914
                opStream, err := tlv.NewStream(statusRecord)
1✔
3915
                if err != nil {
1✔
3916
                        return err
×
3917
                }
×
3918

3919
                var b bytes.Buffer
1✔
3920
                if err := opStream.Encode(&b); err != nil {
1✔
3921
                        return err
×
3922
                }
×
3923

3924
                // Finally add the closed outpoint and tlv stream to the index.
3925
                if err := opBucket.Put(chanPointBuf.Bytes(), b.Bytes()); err != nil {
1✔
3926
                        return err
×
3927
                }
×
3928

3929
                // Add channel state to the historical channel bucket.
3930
                historicalBucket, err := tx.CreateTopLevelBucket(
1✔
3931
                        historicalChannelBucket,
1✔
3932
                )
1✔
3933
                if err != nil {
1✔
3934
                        return err
×
3935
                }
×
3936

3937
                historicalChanBucket, err :=
1✔
3938
                        historicalBucket.CreateBucketIfNotExists(chanKey)
1✔
3939
                if err != nil {
1✔
3940
                        return err
×
3941
                }
×
3942

3943
                // Apply any additional statuses to the channel state.
3944
                for _, status := range statuses {
2✔
3945
                        chanState.chanStatus |= status
1✔
3946
                }
1✔
3947

3948
                err = putOpenChannel(historicalChanBucket, chanState)
1✔
3949
                if err != nil {
1✔
3950
                        return err
×
3951
                }
×
3952

3953
                // Finally, create a summary of this channel in the closed
3954
                // channel bucket for this node.
3955
                return putChannelCloseSummary(
1✔
3956
                        tx, chanPointBuf.Bytes(), summary, chanState,
1✔
3957
                )
1✔
3958
        }, func() {})
1✔
3959
}
3960

3961
// ChannelSnapshot is a frozen snapshot of the current channel state. A
3962
// snapshot is detached from the original channel that generated it, providing
3963
// read-only access to the current or prior state of an active channel.
3964
//
3965
// TODO(roasbeef): remove all together? pretty much just commitment
3966
type ChannelSnapshot struct {
3967
        // RemoteIdentity is the identity public key of the remote node that we
3968
        // are maintaining the open channel with.
3969
        RemoteIdentity btcec.PublicKey
3970

3971
        // ChanPoint is the outpoint that created the channel. This output is
3972
        // found within the funding transaction and uniquely identified the
3973
        // channel on the resident chain.
3974
        ChannelPoint wire.OutPoint
3975

3976
        // ChainHash is the genesis hash of the chain that the channel resides
3977
        // within.
3978
        ChainHash chainhash.Hash
3979

3980
        // Capacity is the total capacity of the channel.
3981
        Capacity btcutil.Amount
3982

3983
        // TotalMSatSent is the total number of milli-satoshis we've sent
3984
        // within this channel.
3985
        TotalMSatSent lnwire.MilliSatoshi
3986

3987
        // TotalMSatReceived is the total number of milli-satoshis we've
3988
        // received within this channel.
3989
        TotalMSatReceived lnwire.MilliSatoshi
3990

3991
        // ChannelCommitment is the current up-to-date commitment for the
3992
        // target channel.
3993
        ChannelCommitment
3994
}
3995

3996
// Snapshot returns a read-only snapshot of the current channel state. This
3997
// snapshot includes information concerning the current settled balance within
3998
// the channel, metadata detailing total flows, and any outstanding HTLCs.
3999
func (c *OpenChannel) Snapshot() *ChannelSnapshot {
1✔
4000
        c.RLock()
1✔
4001
        defer c.RUnlock()
1✔
4002

1✔
4003
        localCommit := c.LocalCommitment
1✔
4004
        snapshot := &ChannelSnapshot{
1✔
4005
                RemoteIdentity:    *c.IdentityPub,
1✔
4006
                ChannelPoint:      c.FundingOutpoint,
1✔
4007
                Capacity:          c.Capacity,
1✔
4008
                TotalMSatSent:     c.TotalMSatSent,
1✔
4009
                TotalMSatReceived: c.TotalMSatReceived,
1✔
4010
                ChainHash:         c.ChainHash,
1✔
4011
                ChannelCommitment: ChannelCommitment{
1✔
4012
                        LocalBalance:  localCommit.LocalBalance,
1✔
4013
                        RemoteBalance: localCommit.RemoteBalance,
1✔
4014
                        CommitHeight:  localCommit.CommitHeight,
1✔
4015
                        CommitFee:     localCommit.CommitFee,
1✔
4016
                },
1✔
4017
        }
1✔
4018

1✔
4019
        localCommit.CustomBlob.WhenSome(func(blob tlv.Blob) {
1✔
4020
                blobCopy := make([]byte, len(blob))
×
4021
                copy(blobCopy, blob)
×
4022

×
4023
                snapshot.ChannelCommitment.CustomBlob = fn.Some(blobCopy)
×
4024
        })
×
4025

4026
        // Copy over the current set of HTLCs to ensure the caller can't mutate
4027
        // our internal state.
4028
        snapshot.Htlcs = make([]HTLC, len(localCommit.Htlcs))
1✔
4029
        for i, h := range localCommit.Htlcs {
2✔
4030
                snapshot.Htlcs[i] = h.Copy()
1✔
4031
        }
1✔
4032

4033
        return snapshot
1✔
4034
}
4035

4036
// LatestCommitments returns the two latest commitments for both the local and
4037
// remote party. These commitments are read from disk to ensure that only the
4038
// latest fully committed state is returned. The first commitment returned is
4039
// the local commitment, and the second returned is the remote commitment.
4040
func (c *OpenChannel) LatestCommitments() (*ChannelCommitment, *ChannelCommitment, error) {
1✔
4041
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2✔
4042
                chanBucket, err := fetchChanBucket(
1✔
4043
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
4044
                )
1✔
4045
                if err != nil {
1✔
4046
                        return err
×
4047
                }
×
4048

4049
                return fetchChanCommitments(chanBucket, c)
1✔
4050
        }, func() {})
1✔
4051
        if err != nil {
1✔
4052
                return nil, nil, err
×
4053
        }
×
4054

4055
        return &c.LocalCommitment, &c.RemoteCommitment, nil
1✔
4056
}
4057

4058
// RemoteRevocationStore returns the most up to date commitment version of the
4059
// revocation storage tree for the remote party. This method can be used when
4060
// acting on a possible contract breach to ensure, that the caller has the most
4061
// up to date information required to deliver justice.
4062
func (c *OpenChannel) RemoteRevocationStore() (shachain.Store, error) {
1✔
4063
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2✔
4064
                chanBucket, err := fetchChanBucket(
1✔
4065
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
4066
                )
1✔
4067
                if err != nil {
1✔
4068
                        return err
×
4069
                }
×
4070

4071
                return fetchChanRevocationState(chanBucket, c)
1✔
4072
        }, func() {})
1✔
4073
        if err != nil {
1✔
4074
                return nil, err
×
4075
        }
×
4076

4077
        return c.RevocationStore, nil
1✔
4078
}
4079

4080
// AbsoluteThawHeight determines a frozen channel's absolute thaw height. If the
4081
// channel is not frozen, then 0 is returned.
4082
func (c *OpenChannel) AbsoluteThawHeight() (uint32, error) {
1✔
4083
        // Only frozen channels have a thaw height.
1✔
4084
        if !c.ChanType.IsFrozen() && !c.ChanType.HasLeaseExpiration() {
2✔
4085
                return 0, nil
1✔
4086
        }
1✔
4087

4088
        // If the channel has the frozen bit set and it's thaw height is below
4089
        // the absolute threshold, then it's interpreted as a relative height to
4090
        // the chain's current height.
4091
        if c.ChanType.IsFrozen() && c.ThawHeight < AbsoluteThawHeightThreshold {
2✔
4092
                // We'll only known of the channel's short ID once it's
1✔
4093
                // confirmed.
1✔
4094
                if c.IsPending {
1✔
4095
                        return 0, errors.New("cannot use relative thaw " +
×
4096
                                "height for unconfirmed channel")
×
4097
                }
×
4098

4099
                // For non-zero-conf channels, this is the base height to use.
4100
                blockHeightBase := c.ShortChannelID.BlockHeight
1✔
4101

1✔
4102
                // If this is a zero-conf channel, the ShortChannelID will be
1✔
4103
                // an alias.
1✔
4104
                if c.IsZeroConf() {
1✔
4105
                        if !c.ZeroConfConfirmed() {
×
4106
                                return 0, errors.New("cannot use relative " +
×
4107
                                        "height for unconfirmed zero-conf " +
×
4108
                                        "channel")
×
4109
                        }
×
4110

4111
                        // Use the confirmed SCID's BlockHeight.
4112
                        blockHeightBase = c.confirmedScid.BlockHeight
×
4113
                }
4114

4115
                return blockHeightBase + c.ThawHeight, nil
1✔
4116
        }
4117

4118
        return c.ThawHeight, nil
×
4119
}
4120

4121
// DeriveHeightHint derives the block height for the channel opening.
4122
func (c *OpenChannel) DeriveHeightHint() uint32 {
1✔
4123
        // As a height hint, we'll try to use the opening height, but if the
1✔
4124
        // channel isn't yet open, then we'll use the height it was broadcast
1✔
4125
        // at. This may be an unconfirmed zero-conf channel.
1✔
4126
        heightHint := c.ShortChanID().BlockHeight
1✔
4127
        if heightHint == 0 {
2✔
4128
                heightHint = c.BroadcastHeight()
1✔
4129
        }
1✔
4130

4131
        // Since no zero-conf state is stored in a channel backup, the below
4132
        // logic will not be triggered for restored, zero-conf channels. Set
4133
        // the height hint for zero-conf channels.
4134
        if c.IsZeroConf() {
2✔
4135
                if c.ZeroConfConfirmed() {
2✔
4136
                        // If the zero-conf channel is confirmed, we'll use the
1✔
4137
                        // confirmed SCID's block height.
1✔
4138
                        heightHint = c.ZeroConfRealScid().BlockHeight
1✔
4139
                } else {
2✔
4140
                        // The zero-conf channel is unconfirmed. We'll need to
1✔
4141
                        // use the FundingBroadcastHeight.
1✔
4142
                        heightHint = c.BroadcastHeight()
1✔
4143
                }
1✔
4144
        }
4145

4146
        return heightHint
1✔
4147
}
4148

4149
func putChannelCloseSummary(tx kvdb.RwTx, chanID []byte,
4150
        summary *ChannelCloseSummary, lastChanState *OpenChannel) error {
1✔
4151

1✔
4152
        closedChanBucket, err := tx.CreateTopLevelBucket(closedChannelBucket)
1✔
4153
        if err != nil {
1✔
4154
                return err
×
4155
        }
×
4156

4157
        summary.RemoteCurrentRevocation = lastChanState.RemoteCurrentRevocation
1✔
4158
        summary.RemoteNextRevocation = lastChanState.RemoteNextRevocation
1✔
4159
        summary.LocalChanConfig = lastChanState.LocalChanCfg
1✔
4160

1✔
4161
        var b bytes.Buffer
1✔
4162
        if err := serializeChannelCloseSummary(&b, summary); err != nil {
1✔
4163
                return err
×
4164
        }
×
4165

4166
        return closedChanBucket.Put(chanID, b.Bytes())
1✔
4167
}
4168

4169
func serializeChannelCloseSummary(w io.Writer, cs *ChannelCloseSummary) error {
1✔
4170
        err := WriteElements(w,
1✔
4171
                cs.ChanPoint, cs.ShortChanID, cs.ChainHash, cs.ClosingTXID,
1✔
4172
                cs.CloseHeight, cs.RemotePub, cs.Capacity, cs.SettledBalance,
1✔
4173
                cs.TimeLockedBalance, cs.CloseType, cs.IsPending,
1✔
4174
        )
1✔
4175
        if err != nil {
1✔
4176
                return err
×
4177
        }
×
4178

4179
        // If this is a close channel summary created before the addition of
4180
        // the new fields, then we can exit here.
4181
        if cs.RemoteCurrentRevocation == nil {
1✔
4182
                return WriteElements(w, false)
×
4183
        }
×
4184

4185
        // If fields are present, write boolean to indicate this, and continue.
4186
        if err := WriteElements(w, true); err != nil {
1✔
4187
                return err
×
4188
        }
×
4189

4190
        if err := WriteElements(w, cs.RemoteCurrentRevocation); err != nil {
1✔
4191
                return err
×
4192
        }
×
4193

4194
        if err := writeChanConfig(w, &cs.LocalChanConfig); err != nil {
1✔
4195
                return err
×
4196
        }
×
4197

4198
        // The RemoteNextRevocation field is optional, as it's possible for a
4199
        // channel to be closed before we learn of the next unrevoked
4200
        // revocation point for the remote party. Write a boolean indicating
4201
        // whether this field is present or not.
4202
        if err := WriteElements(w, cs.RemoteNextRevocation != nil); err != nil {
1✔
4203
                return err
×
4204
        }
×
4205

4206
        // Write the field, if present.
4207
        if cs.RemoteNextRevocation != nil {
2✔
4208
                if err = WriteElements(w, cs.RemoteNextRevocation); err != nil {
1✔
4209
                        return err
×
4210
                }
×
4211
        }
4212

4213
        // Write whether the channel sync message is present.
4214
        if err := WriteElements(w, cs.LastChanSyncMsg != nil); err != nil {
1✔
4215
                return err
×
4216
        }
×
4217

4218
        // Write the channel sync message, if present.
4219
        if cs.LastChanSyncMsg != nil {
2✔
4220
                if err := WriteElements(w, cs.LastChanSyncMsg); err != nil {
1✔
4221
                        return err
×
4222
                }
×
4223
        }
4224

4225
        return nil
1✔
4226
}
4227

4228
func deserializeCloseChannelSummary(r io.Reader) (*ChannelCloseSummary, error) {
1✔
4229
        c := &ChannelCloseSummary{}
1✔
4230

1✔
4231
        err := ReadElements(r,
1✔
4232
                &c.ChanPoint, &c.ShortChanID, &c.ChainHash, &c.ClosingTXID,
1✔
4233
                &c.CloseHeight, &c.RemotePub, &c.Capacity, &c.SettledBalance,
1✔
4234
                &c.TimeLockedBalance, &c.CloseType, &c.IsPending,
1✔
4235
        )
1✔
4236
        if err != nil {
1✔
4237
                return nil, err
×
4238
        }
×
4239

4240
        // We'll now check to see if the channel close summary was encoded with
4241
        // any of the additional optional fields.
4242
        var hasNewFields bool
1✔
4243
        err = ReadElements(r, &hasNewFields)
1✔
4244
        if err != nil {
1✔
4245
                return nil, err
×
4246
        }
×
4247

4248
        // If fields are not present, we can return.
4249
        if !hasNewFields {
1✔
UNCOV
4250
                return c, nil
×
UNCOV
4251
        }
×
4252

4253
        // Otherwise read the new fields.
4254
        if err := ReadElements(r, &c.RemoteCurrentRevocation); err != nil {
1✔
4255
                return nil, err
×
4256
        }
×
4257

4258
        if err := readChanConfig(r, &c.LocalChanConfig); err != nil {
1✔
4259
                return nil, err
×
4260
        }
×
4261

4262
        // Finally, we'll attempt to read the next unrevoked commitment point
4263
        // for the remote party. If we closed the channel before receiving a
4264
        // channel_ready message then this might not be present. A boolean
4265
        // indicating whether the field is present will come first.
4266
        var hasRemoteNextRevocation bool
1✔
4267
        err = ReadElements(r, &hasRemoteNextRevocation)
1✔
4268
        if err != nil {
1✔
4269
                return nil, err
×
4270
        }
×
4271

4272
        // If this field was written, read it.
4273
        if hasRemoteNextRevocation {
2✔
4274
                err = ReadElements(r, &c.RemoteNextRevocation)
1✔
4275
                if err != nil {
1✔
4276
                        return nil, err
×
4277
                }
×
4278
        }
4279

4280
        // Check if we have a channel sync message to read.
4281
        var hasChanSyncMsg bool
1✔
4282
        err = ReadElements(r, &hasChanSyncMsg)
1✔
4283
        if err == io.EOF {
1✔
4284
                return c, nil
×
4285
        } else if err != nil {
1✔
4286
                return nil, err
×
4287
        }
×
4288

4289
        // If a chan sync message is present, read it.
4290
        if hasChanSyncMsg {
2✔
4291
                // We must pass in reference to a lnwire.Message for the codec
1✔
4292
                // to support it.
1✔
4293
                var msg lnwire.Message
1✔
4294
                if err := ReadElements(r, &msg); err != nil {
1✔
4295
                        return nil, err
×
4296
                }
×
4297

4298
                chanSync, ok := msg.(*lnwire.ChannelReestablish)
1✔
4299
                if !ok {
1✔
4300
                        return nil, errors.New("unable cast db Message to " +
×
4301
                                "ChannelReestablish")
×
4302
                }
×
4303
                c.LastChanSyncMsg = chanSync
1✔
4304
        }
4305

4306
        return c, nil
1✔
4307
}
4308

4309
func writeChanConfig(b io.Writer, c *ChannelConfig) error {
1✔
4310
        return WriteElements(b,
1✔
4311
                c.DustLimit, c.MaxPendingAmount, c.ChanReserve, c.MinHTLC,
1✔
4312
                c.MaxAcceptedHtlcs, c.CsvDelay, c.MultiSigKey,
1✔
4313
                c.RevocationBasePoint, c.PaymentBasePoint, c.DelayBasePoint,
1✔
4314
                c.HtlcBasePoint,
1✔
4315
        )
1✔
4316
}
1✔
4317

4318
// fundingTxPresent returns true if expect the funding transcation to be found
4319
// on disk or already populated within the passed open channel struct.
4320
func fundingTxPresent(channel *OpenChannel) bool {
1✔
4321
        chanType := channel.ChanType
1✔
4322

1✔
4323
        return chanType.IsSingleFunder() && chanType.HasFundingTx() &&
1✔
4324
                channel.IsInitiator &&
1✔
4325
                !channel.hasChanStatus(ChanStatusRestored)
1✔
4326
}
1✔
4327

4328
func putChanInfo(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
1✔
4329
        var w bytes.Buffer
1✔
4330
        if err := WriteElements(&w,
1✔
4331
                channel.ChanType, channel.ChainHash, channel.FundingOutpoint,
1✔
4332
                channel.ShortChannelID, channel.IsPending, channel.IsInitiator,
1✔
4333
                channel.chanStatus, channel.FundingBroadcastHeight,
1✔
4334
                channel.NumConfsRequired, channel.ChannelFlags,
1✔
4335
                channel.IdentityPub, channel.Capacity, channel.TotalMSatSent,
1✔
4336
                channel.TotalMSatReceived,
1✔
4337
        ); err != nil {
1✔
4338
                return err
×
4339
        }
×
4340

4341
        // For single funder channels that we initiated, and we have the
4342
        // funding transaction, then write the funding txn.
4343
        if fundingTxPresent(channel) {
2✔
4344
                if err := WriteElement(&w, channel.FundingTxn); err != nil {
1✔
4345
                        return err
×
4346
                }
×
4347
        }
4348

4349
        if err := writeChanConfig(&w, &channel.LocalChanCfg); err != nil {
1✔
4350
                return err
×
4351
        }
×
4352
        if err := writeChanConfig(&w, &channel.RemoteChanCfg); err != nil {
1✔
4353
                return err
×
4354
        }
×
4355

4356
        auxData := channel.extractTlvData()
1✔
4357
        if err := auxData.encode(&w); err != nil {
1✔
4358
                return fmt.Errorf("unable to encode aux data: %w", err)
×
4359
        }
×
4360

4361
        if err := chanBucket.Put(chanInfoKey, w.Bytes()); err != nil {
1✔
4362
                return err
×
4363
        }
×
4364

4365
        // Finally, add optional shutdown scripts for the local and remote peer if
4366
        // they are present.
4367
        if err := putOptionalUpfrontShutdownScript(
1✔
4368
                chanBucket, localUpfrontShutdownKey, channel.LocalShutdownScript,
1✔
4369
        ); err != nil {
1✔
4370
                return err
×
4371
        }
×
4372

4373
        return putOptionalUpfrontShutdownScript(
1✔
4374
                chanBucket, remoteUpfrontShutdownKey, channel.RemoteShutdownScript,
1✔
4375
        )
1✔
4376
}
4377

4378
// putOptionalUpfrontShutdownScript adds a shutdown script under the key
4379
// provided if it has a non-zero length.
4380
func putOptionalUpfrontShutdownScript(chanBucket kvdb.RwBucket, key []byte,
4381
        script []byte) error {
1✔
4382
        // If the script is empty, we do not need to add anything.
1✔
4383
        if len(script) == 0 {
2✔
4384
                return nil
1✔
4385
        }
1✔
4386

4387
        var w bytes.Buffer
1✔
4388
        if err := WriteElement(&w, script); err != nil {
1✔
4389
                return err
×
4390
        }
×
4391

4392
        return chanBucket.Put(key, w.Bytes())
1✔
4393
}
4394

4395
// getOptionalUpfrontShutdownScript reads the shutdown script stored under the
4396
// key provided if it is present. Upfront shutdown scripts are optional, so the
4397
// function returns with no error if the key is not present.
4398
func getOptionalUpfrontShutdownScript(chanBucket kvdb.RBucket, key []byte,
4399
        script *lnwire.DeliveryAddress) error {
1✔
4400

1✔
4401
        // Return early if the bucket does not exit, a shutdown script was not set.
1✔
4402
        bs := chanBucket.Get(key)
1✔
4403
        if bs == nil {
2✔
4404
                return nil
1✔
4405
        }
1✔
4406

4407
        var tempScript []byte
1✔
4408
        r := bytes.NewReader(bs)
1✔
4409
        if err := ReadElement(r, &tempScript); err != nil {
1✔
4410
                return err
×
4411
        }
×
4412
        *script = tempScript
1✔
4413

1✔
4414
        return nil
1✔
4415
}
4416

4417
func serializeChanCommit(w io.Writer, c *ChannelCommitment) error {
1✔
4418
        if err := WriteElements(w,
1✔
4419
                c.CommitHeight, c.LocalLogIndex, c.LocalHtlcIndex,
1✔
4420
                c.RemoteLogIndex, c.RemoteHtlcIndex, c.LocalBalance,
1✔
4421
                c.RemoteBalance, c.CommitFee, c.FeePerKw, c.CommitTx,
1✔
4422
                c.CommitSig,
1✔
4423
        ); err != nil {
1✔
4424
                return err
×
4425
        }
×
4426

4427
        return SerializeHtlcs(w, c.Htlcs...)
1✔
4428
}
4429

4430
func putChanCommitment(chanBucket kvdb.RwBucket, c *ChannelCommitment,
4431
        local bool) error {
1✔
4432

1✔
4433
        var commitKey []byte
1✔
4434
        if local {
2✔
4435
                commitKey = append(chanCommitmentKey, byte(0x00))
1✔
4436
        } else {
2✔
4437
                commitKey = append(chanCommitmentKey, byte(0x01))
1✔
4438
        }
1✔
4439

4440
        var b bytes.Buffer
1✔
4441
        if err := serializeChanCommit(&b, c); err != nil {
1✔
4442
                return err
×
4443
        }
×
4444

4445
        // Before we write to disk, we'll also write our aux data as well.
4446
        auxData := c.extractTlvData()
1✔
4447
        if err := auxData.encode(&b); err != nil {
1✔
4448
                return fmt.Errorf("unable to write aux data: %w", err)
×
4449
        }
×
4450

4451
        return chanBucket.Put(commitKey, b.Bytes())
1✔
4452
}
4453

4454
func putChanCommitments(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
1✔
4455
        // If this is a restored channel, then we don't have any commitments to
1✔
4456
        // write.
1✔
4457
        if channel.hasChanStatus(ChanStatusRestored) {
2✔
4458
                return nil
1✔
4459
        }
1✔
4460

4461
        err := putChanCommitment(
1✔
4462
                chanBucket, &channel.LocalCommitment, true,
1✔
4463
        )
1✔
4464
        if err != nil {
1✔
4465
                return err
×
4466
        }
×
4467

4468
        return putChanCommitment(
1✔
4469
                chanBucket, &channel.RemoteCommitment, false,
1✔
4470
        )
1✔
4471
}
4472

4473
func putChanRevocationState(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
1✔
4474
        var b bytes.Buffer
1✔
4475
        err := WriteElements(
1✔
4476
                &b, channel.RemoteCurrentRevocation, channel.RevocationProducer,
1✔
4477
                channel.RevocationStore,
1✔
4478
        )
1✔
4479
        if err != nil {
1✔
4480
                return err
×
4481
        }
×
4482

4483
        // If the next revocation is present, which is only the case after the
4484
        // ChannelReady message has been sent, then we'll write it to disk.
4485
        if channel.RemoteNextRevocation != nil {
2✔
4486
                err = WriteElements(&b, channel.RemoteNextRevocation)
1✔
4487
                if err != nil {
1✔
4488
                        return err
×
4489
                }
×
4490
        }
4491

4492
        return chanBucket.Put(revocationStateKey, b.Bytes())
1✔
4493
}
4494

4495
func readChanConfig(b io.Reader, c *ChannelConfig) error {
1✔
4496
        return ReadElements(b,
1✔
4497
                &c.DustLimit, &c.MaxPendingAmount, &c.ChanReserve,
1✔
4498
                &c.MinHTLC, &c.MaxAcceptedHtlcs, &c.CsvDelay,
1✔
4499
                &c.MultiSigKey, &c.RevocationBasePoint,
1✔
4500
                &c.PaymentBasePoint, &c.DelayBasePoint,
1✔
4501
                &c.HtlcBasePoint,
1✔
4502
        )
1✔
4503
}
1✔
4504

4505
func fetchChanInfo(chanBucket kvdb.RBucket, channel *OpenChannel) error {
1✔
4506
        infoBytes := chanBucket.Get(chanInfoKey)
1✔
4507
        if infoBytes == nil {
1✔
4508
                return ErrNoChanInfoFound
×
4509
        }
×
4510
        r := bytes.NewReader(infoBytes)
1✔
4511

1✔
4512
        if err := ReadElements(r,
1✔
4513
                &channel.ChanType, &channel.ChainHash, &channel.FundingOutpoint,
1✔
4514
                &channel.ShortChannelID, &channel.IsPending, &channel.IsInitiator,
1✔
4515
                &channel.chanStatus, &channel.FundingBroadcastHeight,
1✔
4516
                &channel.NumConfsRequired, &channel.ChannelFlags,
1✔
4517
                &channel.IdentityPub, &channel.Capacity, &channel.TotalMSatSent,
1✔
4518
                &channel.TotalMSatReceived,
1✔
4519
        ); err != nil {
1✔
4520
                return err
×
4521
        }
×
4522

4523
        // For single funder channels that we initiated and have the funding
4524
        // transaction to, read the funding txn.
4525
        if fundingTxPresent(channel) {
2✔
4526
                if err := ReadElement(r, &channel.FundingTxn); err != nil {
1✔
4527
                        return err
×
4528
                }
×
4529
        }
4530

4531
        if err := readChanConfig(r, &channel.LocalChanCfg); err != nil {
1✔
4532
                return err
×
4533
        }
×
4534
        if err := readChanConfig(r, &channel.RemoteChanCfg); err != nil {
1✔
4535
                return err
×
4536
        }
×
4537

4538
        // Retrieve the boolean stored under lastWasRevokeKey.
4539
        lastWasRevokeBytes := chanBucket.Get(lastWasRevokeKey)
1✔
4540
        if lastWasRevokeBytes == nil {
2✔
4541
                // If nothing has been stored under this key, we store false in the
1✔
4542
                // OpenChannel struct.
1✔
4543
                channel.LastWasRevoke = false
1✔
4544
        } else {
2✔
4545
                // Otherwise, read the value into the LastWasRevoke field.
1✔
4546
                revokeReader := bytes.NewReader(lastWasRevokeBytes)
1✔
4547
                err := ReadElements(revokeReader, &channel.LastWasRevoke)
1✔
4548
                if err != nil {
1✔
4549
                        return err
×
4550
                }
×
4551
        }
4552

4553
        var auxData openChannelTlvData
1✔
4554
        if err := auxData.decode(r); err != nil {
1✔
4555
                return fmt.Errorf("unable to decode aux data: %w", err)
×
4556
        }
×
4557

4558
        // Assign all the relevant fields from the aux data into the actual
4559
        // open channel.
4560
        channel.amendTlvData(auxData)
1✔
4561

1✔
4562
        channel.Packager = NewChannelPackager(channel.ShortChannelID)
1✔
4563

1✔
4564
        // Finally, read the optional shutdown scripts.
1✔
4565
        if err := getOptionalUpfrontShutdownScript(
1✔
4566
                chanBucket, localUpfrontShutdownKey, &channel.LocalShutdownScript,
1✔
4567
        ); err != nil {
1✔
4568
                return err
×
4569
        }
×
4570

4571
        return getOptionalUpfrontShutdownScript(
1✔
4572
                chanBucket, remoteUpfrontShutdownKey, &channel.RemoteShutdownScript,
1✔
4573
        )
1✔
4574
}
4575

4576
func deserializeChanCommit(r io.Reader) (ChannelCommitment, error) {
1✔
4577
        var c ChannelCommitment
1✔
4578

1✔
4579
        err := ReadElements(r,
1✔
4580
                &c.CommitHeight, &c.LocalLogIndex, &c.LocalHtlcIndex, &c.RemoteLogIndex,
1✔
4581
                &c.RemoteHtlcIndex, &c.LocalBalance, &c.RemoteBalance,
1✔
4582
                &c.CommitFee, &c.FeePerKw, &c.CommitTx, &c.CommitSig,
1✔
4583
        )
1✔
4584
        if err != nil {
1✔
4585
                return c, err
×
4586
        }
×
4587

4588
        c.Htlcs, err = DeserializeHtlcs(r)
1✔
4589
        if err != nil {
1✔
4590
                return c, err
×
4591
        }
×
4592

4593
        return c, nil
1✔
4594
}
4595

4596
func fetchChanCommitment(chanBucket kvdb.RBucket,
4597
        local bool) (ChannelCommitment, error) {
1✔
4598

1✔
4599
        var commitKey []byte
1✔
4600
        if local {
2✔
4601
                commitKey = append(chanCommitmentKey, byte(0x00))
1✔
4602
        } else {
2✔
4603
                commitKey = append(chanCommitmentKey, byte(0x01))
1✔
4604
        }
1✔
4605

4606
        commitBytes := chanBucket.Get(commitKey)
1✔
4607
        if commitBytes == nil {
1✔
4608
                return ChannelCommitment{}, ErrNoCommitmentsFound
×
4609
        }
×
4610

4611
        r := bytes.NewReader(commitBytes)
1✔
4612
        chanCommit, err := deserializeChanCommit(r)
1✔
4613
        if err != nil {
1✔
4614
                return ChannelCommitment{}, fmt.Errorf("unable to decode "+
×
4615
                        "chan commit: %w", err)
×
4616
        }
×
4617

4618
        // We'll also check to see if we have any aux data stored as the end of
4619
        // the stream.
4620
        var auxData commitTlvData
1✔
4621
        if err := auxData.decode(r); err != nil {
1✔
4622
                return ChannelCommitment{}, fmt.Errorf("unable to decode "+
×
4623
                        "chan aux data: %w", err)
×
4624
        }
×
4625

4626
        chanCommit.amendTlvData(auxData)
1✔
4627

1✔
4628
        return chanCommit, nil
1✔
4629
}
4630

4631
func fetchChanCommitments(chanBucket kvdb.RBucket, channel *OpenChannel) error {
1✔
4632
        var err error
1✔
4633

1✔
4634
        // If this is a restored channel, then we don't have any commitments to
1✔
4635
        // read.
1✔
4636
        if channel.hasChanStatus(ChanStatusRestored) {
2✔
4637
                return nil
1✔
4638
        }
1✔
4639

4640
        channel.LocalCommitment, err = fetchChanCommitment(chanBucket, true)
1✔
4641
        if err != nil {
1✔
4642
                return err
×
4643
        }
×
4644
        channel.RemoteCommitment, err = fetchChanCommitment(chanBucket, false)
1✔
4645
        if err != nil {
1✔
4646
                return err
×
4647
        }
×
4648

4649
        return nil
1✔
4650
}
4651

4652
func fetchChanRevocationState(chanBucket kvdb.RBucket, channel *OpenChannel) error {
1✔
4653
        revBytes := chanBucket.Get(revocationStateKey)
1✔
4654
        if revBytes == nil {
1✔
4655
                return ErrNoRevocationsFound
×
4656
        }
×
4657
        r := bytes.NewReader(revBytes)
1✔
4658

1✔
4659
        err := ReadElements(
1✔
4660
                r, &channel.RemoteCurrentRevocation, &channel.RevocationProducer,
1✔
4661
                &channel.RevocationStore,
1✔
4662
        )
1✔
4663
        if err != nil {
1✔
4664
                return err
×
4665
        }
×
4666

4667
        // If there aren't any bytes left in the buffer, then we don't yet have
4668
        // the next remote revocation, so we can exit early here.
4669
        if r.Len() == 0 {
2✔
4670
                return nil
1✔
4671
        }
1✔
4672

4673
        // Otherwise we'll read the next revocation for the remote party which
4674
        // is always the last item within the buffer.
4675
        return ReadElements(r, &channel.RemoteNextRevocation)
1✔
4676
}
4677

4678
func deleteOpenChannel(chanBucket kvdb.RwBucket) error {
1✔
4679
        if err := chanBucket.Delete(chanInfoKey); err != nil {
1✔
4680
                return err
×
4681
        }
×
4682

4683
        err := chanBucket.Delete(append(chanCommitmentKey, byte(0x00)))
1✔
4684
        if err != nil {
1✔
4685
                return err
×
4686
        }
×
4687
        err = chanBucket.Delete(append(chanCommitmentKey, byte(0x01)))
1✔
4688
        if err != nil {
1✔
4689
                return err
×
4690
        }
×
4691

4692
        if err := chanBucket.Delete(revocationStateKey); err != nil {
1✔
4693
                return err
×
4694
        }
×
4695

4696
        if diff := chanBucket.Get(commitDiffKey); diff != nil {
2✔
4697
                return chanBucket.Delete(commitDiffKey)
1✔
4698
        }
1✔
4699

4700
        return nil
1✔
4701
}
4702

4703
// makeLogKey converts a uint64 into an 8 byte array.
4704
func makeLogKey(updateNum uint64) [8]byte {
1✔
4705
        var key [8]byte
1✔
4706
        byteOrder.PutUint64(key[:], updateNum)
1✔
4707
        return key
1✔
4708
}
1✔
4709

4710
func fetchThawHeight(chanBucket kvdb.RBucket) (uint32, error) {
1✔
4711
        var height uint32
1✔
4712

1✔
4713
        heightBytes := chanBucket.Get(frozenChanKey)
1✔
4714
        heightReader := bytes.NewReader(heightBytes)
1✔
4715

1✔
4716
        if err := ReadElements(heightReader, &height); err != nil {
1✔
4717
                return 0, err
×
4718
        }
×
4719

4720
        return height, nil
1✔
4721
}
4722

4723
func storeThawHeight(chanBucket kvdb.RwBucket, height uint32) error {
1✔
4724
        var heightBuf bytes.Buffer
1✔
4725
        if err := WriteElements(&heightBuf, height); err != nil {
1✔
4726
                return err
×
4727
        }
×
4728

4729
        return chanBucket.Put(frozenChanKey, heightBuf.Bytes())
1✔
4730
}
4731

4732
func deleteThawHeight(chanBucket kvdb.RwBucket) error {
1✔
4733
        return chanBucket.Delete(frozenChanKey)
1✔
4734
}
1✔
4735

4736
// keyLocRecord is a wrapper struct around keychain.KeyLocator to implement the
4737
// tlv.RecordProducer interface.
4738
type keyLocRecord struct {
4739
        keychain.KeyLocator
4740
}
4741

4742
// Record creates a Record out of a KeyLocator using the passed Type and the
4743
// EKeyLocator and DKeyLocator functions. The size will always be 8 as
4744
// KeyFamily is uint32 and the Index is uint32.
4745
//
4746
// NOTE: This is part of the tlv.RecordProducer interface.
4747
func (k *keyLocRecord) Record() tlv.Record {
1✔
4748
        // Note that we set the type here as zero, as when used with a
1✔
4749
        // tlv.RecordT, the type param will be used as the type.
1✔
4750
        return tlv.MakeStaticRecord(
1✔
4751
                0, &k.KeyLocator, 8, EKeyLocator, DKeyLocator,
1✔
4752
        )
1✔
4753
}
1✔
4754

4755
// EKeyLocator is an encoder for keychain.KeyLocator.
4756
func EKeyLocator(w io.Writer, val interface{}, buf *[8]byte) error {
1✔
4757
        if v, ok := val.(*keychain.KeyLocator); ok {
2✔
4758
                err := tlv.EUint32T(w, uint32(v.Family), buf)
1✔
4759
                if err != nil {
1✔
4760
                        return err
×
4761
                }
×
4762

4763
                return tlv.EUint32T(w, v.Index, buf)
1✔
4764
        }
4765
        return tlv.NewTypeForEncodingErr(val, "keychain.KeyLocator")
×
4766
}
4767

4768
// DKeyLocator is a decoder for keychain.KeyLocator.
4769
func DKeyLocator(r io.Reader, val interface{}, buf *[8]byte, l uint64) error {
1✔
4770
        if v, ok := val.(*keychain.KeyLocator); ok {
2✔
4771
                var family uint32
1✔
4772
                err := tlv.DUint32(r, &family, buf, 4)
1✔
4773
                if err != nil {
1✔
4774
                        return err
×
4775
                }
×
4776
                v.Family = keychain.KeyFamily(family)
1✔
4777

1✔
4778
                return tlv.DUint32(r, &v.Index, buf, 4)
1✔
4779
        }
4780
        return tlv.NewTypeForDecodingErr(val, "keychain.KeyLocator", l, 8)
×
4781
}
4782

4783
// ShutdownInfo contains various info about the shutdown initiation of a
4784
// channel.
4785
type ShutdownInfo struct {
4786
        // DeliveryScript is the address that we have included in any previous
4787
        // Shutdown message for a particular channel and so should include in
4788
        // any future re-sends of the Shutdown message.
4789
        DeliveryScript tlv.RecordT[tlv.TlvType0, lnwire.DeliveryAddress]
4790

4791
        // LocalInitiator is true if we sent a Shutdown message before ever
4792
        // receiving a Shutdown message from the remote peer.
4793
        LocalInitiator tlv.RecordT[tlv.TlvType1, bool]
4794
}
4795

4796
// NewShutdownInfo constructs a new ShutdownInfo object.
4797
func NewShutdownInfo(deliveryScript lnwire.DeliveryAddress,
4798
        locallyInitiated bool) *ShutdownInfo {
1✔
4799

1✔
4800
        return &ShutdownInfo{
1✔
4801
                DeliveryScript: tlv.NewRecordT[tlv.TlvType0](deliveryScript),
1✔
4802
                LocalInitiator: tlv.NewPrimitiveRecord[tlv.TlvType1](
1✔
4803
                        locallyInitiated,
1✔
4804
                ),
1✔
4805
        }
1✔
4806
}
1✔
4807

4808
// Closer identifies the ChannelParty that initiated the coop-closure process.
4809
func (s ShutdownInfo) Closer() lntypes.ChannelParty {
1✔
4810
        if s.LocalInitiator.Val {
2✔
4811
                return lntypes.Local
1✔
4812
        }
1✔
4813

4814
        return lntypes.Remote
1✔
4815
}
4816

4817
// encode serialises the ShutdownInfo to the given io.Writer.
4818
func (s *ShutdownInfo) encode(w io.Writer) error {
1✔
4819
        records := []tlv.Record{
1✔
4820
                s.DeliveryScript.Record(),
1✔
4821
                s.LocalInitiator.Record(),
1✔
4822
        }
1✔
4823

1✔
4824
        stream, err := tlv.NewStream(records...)
1✔
4825
        if err != nil {
1✔
4826
                return err
×
4827
        }
×
4828

4829
        return stream.Encode(w)
1✔
4830
}
4831

4832
// decodeShutdownInfo constructs a ShutdownInfo struct by decoding the given
4833
// byte slice.
4834
func decodeShutdownInfo(b []byte) (*ShutdownInfo, error) {
1✔
4835
        tlvStream := lnwire.ExtraOpaqueData(b)
1✔
4836

1✔
4837
        var info ShutdownInfo
1✔
4838
        records := []tlv.RecordProducer{
1✔
4839
                &info.DeliveryScript,
1✔
4840
                &info.LocalInitiator,
1✔
4841
        }
1✔
4842

1✔
4843
        _, err := tlvStream.ExtractRecords(records...)
1✔
4844

1✔
4845
        return &info, err
1✔
4846
}
1✔
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