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

lightningnetwork / lnd / 9617502354

21 Jun 2024 05:27PM UTC coverage: 58.414% (+0.004%) from 58.41%
9617502354

Pull #8856

github

web-flow
[docs] Update go instructions

Building current lnd `0.18` fails with older go (`1.19.7`).

* Updated go download path to 1.22.4
* Updated hashes
* Added `rm -rf` instructions as per [go.dev instructions](https://go.dev/doc/install)
Pull Request #8856: [docs] Update go instructions

123389 of 211233 relevant lines covered (58.41%)

28572.17 hits per line

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

77.62
/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/channeldb/models"
23
        "github.com/lightningnetwork/lnd/fn"
24
        "github.com/lightningnetwork/lnd/htlcswitch/hop"
25
        "github.com/lightningnetwork/lnd/input"
26
        "github.com/lightningnetwork/lnd/keychain"
27
        "github.com/lightningnetwork/lnd/kvdb"
28
        "github.com/lightningnetwork/lnd/lnwire"
29
        "github.com/lightningnetwork/lnd/shachain"
30
        "github.com/lightningnetwork/lnd/tlv"
31
)
32

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

229
        // A tlv type definition used to serialize and deserialize a KeyLocator
230
        // from the database.
231
        keyLocType tlv.Type = 1
232

233
        // A tlv type used to serialize and deserialize the
234
        // `InitialLocalBalance` field.
235
        initialLocalBalanceType tlv.Type = 2
236

237
        // A tlv type used to serialize and deserialize the
238
        // `InitialRemoteBalance` field.
239
        initialRemoteBalanceType tlv.Type = 3
240

241
        // A tlv type definition used to serialize and deserialize the
242
        // confirmed ShortChannelID for a zero-conf channel.
243
        realScidType tlv.Type = 4
244

245
        // A tlv type definition used to serialize and deserialize the
246
        // Memo for the channel channel.
247
        channelMemoType tlv.Type = 5
248
)
249

250
// indexStatus is an enum-like type that describes what state the
251
// outpoint is in. Currently only two possible values.
252
type indexStatus uint8
253

254
const (
255
        // outpointOpen represents an outpoint that is open in the outpoint index.
256
        outpointOpen indexStatus = 0
257

258
        // outpointClosed represents an outpoint that is closed in the outpoint
259
        // index.
260
        outpointClosed indexStatus = 1
261
)
262

263
// ChannelType is an enum-like type that describes one of several possible
264
// channel types. Each open channel is associated with a particular type as the
265
// channel type may determine how higher level operations are conducted such as
266
// fee negotiation, channel closing, the format of HTLCs, etc. Structure-wise,
267
// a ChannelType is a bit field, with each bit denoting a modification from the
268
// base channel type of single funder.
269
type ChannelType uint64
270

271
const (
272
        // NOTE: iota isn't used here for this enum needs to be stable
273
        // long-term as it will be persisted to the database.
274

275
        // SingleFunderBit represents a channel wherein one party solely funds
276
        // the entire capacity of the channel.
277
        SingleFunderBit ChannelType = 0
278

279
        // DualFunderBit represents a channel wherein both parties contribute
280
        // funds towards the total capacity of the channel. The channel may be
281
        // funded symmetrically or asymmetrically.
282
        DualFunderBit ChannelType = 1 << 0
283

284
        // SingleFunderTweaklessBit is similar to the basic SingleFunder channel
285
        // type, but it omits the tweak for one's key in the commitment
286
        // transaction of the remote party.
287
        SingleFunderTweaklessBit ChannelType = 1 << 1
288

289
        // NoFundingTxBit denotes if we have the funding transaction locally on
290
        // disk. This bit may be on if the funding transaction was crafted by a
291
        // wallet external to the primary daemon.
292
        NoFundingTxBit ChannelType = 1 << 2
293

294
        // AnchorOutputsBit indicates that the channel makes use of anchor
295
        // outputs to bump the commitment transaction's effective feerate. This
296
        // channel type also uses a delayed to_remote output script.
297
        AnchorOutputsBit ChannelType = 1 << 3
298

299
        // FrozenBit indicates that the channel is a frozen channel, meaning
300
        // that only the responder can decide to cooperatively close the
301
        // channel.
302
        FrozenBit ChannelType = 1 << 4
303

304
        // ZeroHtlcTxFeeBit indicates that the channel should use zero-fee
305
        // second-level HTLC transactions.
306
        ZeroHtlcTxFeeBit ChannelType = 1 << 5
307

308
        // LeaseExpirationBit indicates that the channel has been leased for a
309
        // period of time, constraining every output that pays to the channel
310
        // initiator with an additional CLTV of the lease maturity.
311
        LeaseExpirationBit ChannelType = 1 << 6
312

313
        // ZeroConfBit indicates that the channel is a zero-conf channel.
314
        ZeroConfBit ChannelType = 1 << 7
315

316
        // ScidAliasChanBit indicates that the channel has negotiated the
317
        // scid-alias channel type.
318
        ScidAliasChanBit ChannelType = 1 << 8
319

320
        // ScidAliasFeatureBit indicates that the scid-alias feature bit was
321
        // negotiated during the lifetime of this channel.
322
        ScidAliasFeatureBit ChannelType = 1 << 9
323

324
        // SimpleTaprootFeatureBit indicates that the simple-taproot-chans
325
        // feature bit was negotiated during the lifetime of the channel.
326
        SimpleTaprootFeatureBit ChannelType = 1 << 10
327
)
328

329
// IsSingleFunder returns true if the channel type if one of the known single
330
// funder variants.
331
func (c ChannelType) IsSingleFunder() bool {
14,886✔
332
        return c&DualFunderBit == 0
14,886✔
333
}
14,886✔
334

335
// IsDualFunder returns true if the ChannelType has the DualFunderBit set.
336
func (c ChannelType) IsDualFunder() bool {
×
337
        return c&DualFunderBit == DualFunderBit
×
338
}
×
339

340
// IsTweakless returns true if the target channel uses a commitment that
341
// doesn't tweak the key for the remote party.
342
func (c ChannelType) IsTweakless() bool {
13,777✔
343
        return c&SingleFunderTweaklessBit == SingleFunderTweaklessBit
13,777✔
344
}
13,777✔
345

346
// HasFundingTx returns true if this channel type is one that has a funding
347
// transaction stored locally.
348
func (c ChannelType) HasFundingTx() bool {
14,896✔
349
        return c&NoFundingTxBit == 0
14,896✔
350
}
14,896✔
351

352
// HasAnchors returns true if this channel type has anchor outputs on its
353
// commitment.
354
func (c ChannelType) HasAnchors() bool {
7,888,216✔
355
        return c&AnchorOutputsBit == AnchorOutputsBit
7,888,216✔
356
}
7,888,216✔
357

358
// ZeroHtlcTxFee returns true if this channel type uses second-level HTLC
359
// transactions signed with zero-fee.
360
func (c ChannelType) ZeroHtlcTxFee() bool {
6,885,440✔
361
        return c&ZeroHtlcTxFeeBit == ZeroHtlcTxFeeBit
6,885,440✔
362
}
6,885,440✔
363

364
// IsFrozen returns true if the channel is considered to be "frozen". A frozen
365
// channel means that only the responder can initiate a cooperative channel
366
// closure.
367
func (c ChannelType) IsFrozen() bool {
11,816✔
368
        return c&FrozenBit == FrozenBit
11,816✔
369
}
11,816✔
370

371
// HasLeaseExpiration returns true if the channel originated from a lease.
372
func (c ChannelType) HasLeaseExpiration() bool {
279,228✔
373
        return c&LeaseExpirationBit == LeaseExpirationBit
279,228✔
374
}
279,228✔
375

376
// HasZeroConf returns true if the channel is a zero-conf channel.
377
func (c ChannelType) HasZeroConf() bool {
644✔
378
        return c&ZeroConfBit == ZeroConfBit
644✔
379
}
644✔
380

381
// HasScidAliasChan returns true if the scid-alias channel type was negotiated.
382
func (c ChannelType) HasScidAliasChan() bool {
×
383
        return c&ScidAliasChanBit == ScidAliasChanBit
×
384
}
×
385

386
// HasScidAliasFeature returns true if the scid-alias feature bit was
387
// negotiated during the lifetime of this channel.
388
func (c ChannelType) HasScidAliasFeature() bool {
483✔
389
        return c&ScidAliasFeatureBit == ScidAliasFeatureBit
483✔
390
}
483✔
391

392
// IsTaproot returns true if the channel is using taproot features.
393
func (c ChannelType) IsTaproot() bool {
8,623,679✔
394
        return c&SimpleTaprootFeatureBit == SimpleTaprootFeatureBit
8,623,679✔
395
}
8,623,679✔
396

397
// ChannelConstraints represents a set of constraints meant to allow a node to
398
// limit their exposure, enact flow control and ensure that all HTLCs are
399
// economically relevant. This struct will be mirrored for both sides of the
400
// channel, as each side will enforce various constraints that MUST be adhered
401
// to for the life time of the channel. The parameters for each of these
402
// constraints are static for the duration of the channel, meaning the channel
403
// must be torn down for them to change.
404
type ChannelConstraints struct {
405
        // DustLimit is the threshold (in satoshis) below which any outputs
406
        // should be trimmed. When an output is trimmed, it isn't materialized
407
        // as an actual output, but is instead burned to miner's fees.
408
        DustLimit btcutil.Amount
409

410
        // ChanReserve is an absolute reservation on the channel for the
411
        // owner of this set of constraints. This means that the current
412
        // settled balance for this node CANNOT dip below the reservation
413
        // amount. This acts as a defense against costless attacks when
414
        // either side no longer has any skin in the game.
415
        ChanReserve btcutil.Amount
416

417
        // MaxPendingAmount is the maximum pending HTLC value that the
418
        // owner of these constraints can offer the remote node at a
419
        // particular time.
420
        MaxPendingAmount lnwire.MilliSatoshi
421

422
        // MinHTLC is the minimum HTLC value that the owner of these
423
        // constraints can offer the remote node. If any HTLCs below this
424
        // amount are offered, then the HTLC will be rejected. This, in
425
        // tandem with the dust limit allows a node to regulate the
426
        // smallest HTLC that it deems economically relevant.
427
        MinHTLC lnwire.MilliSatoshi
428

429
        // MaxAcceptedHtlcs is the maximum number of HTLCs that the owner of
430
        // this set of constraints can offer the remote node. This allows each
431
        // node to limit their over all exposure to HTLCs that may need to be
432
        // acted upon in the case of a unilateral channel closure or a contract
433
        // breach.
434
        MaxAcceptedHtlcs uint16
435

436
        // CsvDelay is the relative time lock delay expressed in blocks. Any
437
        // settled outputs that pay to the owner of this channel configuration
438
        // MUST ensure that the delay branch uses this value as the relative
439
        // time lock. Similarly, any HTLC's offered by this node should use
440
        // this value as well.
441
        CsvDelay uint16
442
}
443

444
// ChannelConfig is a struct that houses the various configuration opens for
445
// channels. Each side maintains an instance of this configuration file as it
446
// governs: how the funding and commitment transaction to be created, the
447
// nature of HTLC's allotted, the keys to be used for delivery, and relative
448
// time lock parameters.
449
type ChannelConfig struct {
450
        // ChannelConstraints is the set of constraints that must be upheld for
451
        // the duration of the channel for the owner of this channel
452
        // configuration. Constraints govern a number of flow control related
453
        // parameters, also including the smallest HTLC that will be accepted
454
        // by a participant.
455
        ChannelConstraints
456

457
        // MultiSigKey is the key to be used within the 2-of-2 output script
458
        // for the owner of this channel config.
459
        MultiSigKey keychain.KeyDescriptor
460

461
        // RevocationBasePoint is the base public key to be used when deriving
462
        // revocation keys for the remote node's commitment transaction. This
463
        // will be combined along with a per commitment secret to derive a
464
        // unique revocation key for each state.
465
        RevocationBasePoint keychain.KeyDescriptor
466

467
        // PaymentBasePoint is the base public key to be used when deriving
468
        // the key used within the non-delayed pay-to-self output on the
469
        // commitment transaction for a node. This will be combined with a
470
        // tweak derived from the per-commitment point to ensure unique keys
471
        // for each commitment transaction.
472
        PaymentBasePoint keychain.KeyDescriptor
473

474
        // DelayBasePoint is the base public key to be used when deriving the
475
        // key used within the delayed pay-to-self output on the commitment
476
        // transaction for a node. This will be combined with a tweak derived
477
        // from the per-commitment point to ensure unique keys for each
478
        // commitment transaction.
479
        DelayBasePoint keychain.KeyDescriptor
480

481
        // HtlcBasePoint is the base public key to be used when deriving the
482
        // local HTLC key. The derived key (combined with the tweak derived
483
        // from the per-commitment point) is used within the "to self" clause
484
        // within any HTLC output scripts.
485
        HtlcBasePoint keychain.KeyDescriptor
486
}
487

488
// ChannelCommitment is a snapshot of the commitment state at a particular
489
// point in the commitment chain. With each state transition, a snapshot of the
490
// current state along with all non-settled HTLCs are recorded. These snapshots
491
// detail the state of the _remote_ party's commitment at a particular state
492
// number.  For ourselves (the local node) we ONLY store our most recent
493
// (unrevoked) state for safety purposes.
494
type ChannelCommitment struct {
495
        // CommitHeight is the update number that this ChannelDelta represents
496
        // the total number of commitment updates to this point. This can be
497
        // viewed as sort of a "commitment height" as this number is
498
        // monotonically increasing.
499
        CommitHeight uint64
500

501
        // LocalLogIndex is the cumulative log index index of the local node at
502
        // this point in the commitment chain. This value will be incremented
503
        // for each _update_ added to the local update log.
504
        LocalLogIndex uint64
505

506
        // LocalHtlcIndex is the current local running HTLC index. This value
507
        // will be incremented for each outgoing HTLC the local node offers.
508
        LocalHtlcIndex uint64
509

510
        // RemoteLogIndex is the cumulative log index index of the remote node
511
        // at this point in the commitment chain. This value will be
512
        // incremented for each _update_ added to the remote update log.
513
        RemoteLogIndex uint64
514

515
        // RemoteHtlcIndex is the current remote running HTLC index. This value
516
        // will be incremented for each outgoing HTLC the remote node offers.
517
        RemoteHtlcIndex uint64
518

519
        // LocalBalance is the current available settled balance within the
520
        // channel directly spendable by us.
521
        //
522
        // NOTE: This is the balance *after* subtracting any commitment fee,
523
        // AND anchor output values.
524
        LocalBalance lnwire.MilliSatoshi
525

526
        // RemoteBalance is the current available settled balance within the
527
        // channel directly spendable by the remote node.
528
        //
529
        // NOTE: This is the balance *after* subtracting any commitment fee,
530
        // AND anchor output values.
531
        RemoteBalance lnwire.MilliSatoshi
532

533
        // CommitFee is the amount calculated to be paid in fees for the
534
        // current set of commitment transactions. The fee amount is persisted
535
        // with the channel in order to allow the fee amount to be removed and
536
        // recalculated with each channel state update, including updates that
537
        // happen after a system restart.
538
        CommitFee btcutil.Amount
539

540
        // FeePerKw is the min satoshis/kilo-weight that should be paid within
541
        // the commitment transaction for the entire duration of the channel's
542
        // lifetime. This field may be updated during normal operation of the
543
        // channel as on-chain conditions change.
544
        //
545
        // TODO(halseth): make this SatPerKWeight. Cannot be done atm because
546
        // this will cause the import cycle lnwallet<->channeldb. Fee
547
        // estimation stuff should be in its own package.
548
        FeePerKw btcutil.Amount
549

550
        // CommitTx is the latest version of the commitment state, broadcast
551
        // able by us.
552
        CommitTx *wire.MsgTx
553

554
        // CommitSig is one half of the signature required to fully complete
555
        // the script for the commitment transaction above. This is the
556
        // signature signed by the remote party for our version of the
557
        // commitment transactions.
558
        CommitSig []byte
559

560
        // Htlcs is the set of HTLC's that are pending at this particular
561
        // commitment height.
562
        Htlcs []HTLC
563

564
        // TODO(roasbeef): pending commit pointer?
565
        //  * lets just walk through
566
}
567

568
// ChannelStatus is a bit vector used to indicate whether an OpenChannel is in
569
// the default usable state, or a state where it shouldn't be used.
570
type ChannelStatus uint64
571

572
var (
573
        // ChanStatusDefault is the normal state of an open channel.
574
        ChanStatusDefault ChannelStatus
575

576
        // ChanStatusBorked indicates that the channel has entered an
577
        // irreconcilable state, triggered by a state desynchronization or
578
        // channel breach.  Channels in this state should never be added to the
579
        // htlc switch.
580
        ChanStatusBorked ChannelStatus = 1
581

582
        // ChanStatusCommitBroadcasted indicates that a commitment for this
583
        // channel has been broadcasted.
584
        ChanStatusCommitBroadcasted ChannelStatus = 1 << 1
585

586
        // ChanStatusLocalDataLoss indicates that we have lost channel state
587
        // for this channel, and broadcasting our latest commitment might be
588
        // considered a breach.
589
        //
590
        // TODO(halseh): actually enforce that we are not force closing such a
591
        // channel.
592
        ChanStatusLocalDataLoss ChannelStatus = 1 << 2
593

594
        // ChanStatusRestored is a status flag that signals that the channel
595
        // has been restored, and doesn't have all the fields a typical channel
596
        // will have.
597
        ChanStatusRestored ChannelStatus = 1 << 3
598

599
        // ChanStatusCoopBroadcasted indicates that a cooperative close for
600
        // this channel has been broadcasted. Older cooperatively closed
601
        // channels will only have this status set. Newer ones will also have
602
        // close initiator information stored using the local/remote initiator
603
        // status. This status is set in conjunction with the initiator status
604
        // so that we do not need to check multiple channel statues for
605
        // cooperative closes.
606
        ChanStatusCoopBroadcasted ChannelStatus = 1 << 4
607

608
        // ChanStatusLocalCloseInitiator indicates that we initiated closing
609
        // the channel.
610
        ChanStatusLocalCloseInitiator ChannelStatus = 1 << 5
611

612
        // ChanStatusRemoteCloseInitiator indicates that the remote node
613
        // initiated closing the channel.
614
        ChanStatusRemoteCloseInitiator ChannelStatus = 1 << 6
615
)
616

617
// chanStatusStrings maps a ChannelStatus to a human friendly string that
618
// describes that status.
619
var chanStatusStrings = map[ChannelStatus]string{
620
        ChanStatusDefault:              "ChanStatusDefault",
621
        ChanStatusBorked:               "ChanStatusBorked",
622
        ChanStatusCommitBroadcasted:    "ChanStatusCommitBroadcasted",
623
        ChanStatusLocalDataLoss:        "ChanStatusLocalDataLoss",
624
        ChanStatusRestored:             "ChanStatusRestored",
625
        ChanStatusCoopBroadcasted:      "ChanStatusCoopBroadcasted",
626
        ChanStatusLocalCloseInitiator:  "ChanStatusLocalCloseInitiator",
627
        ChanStatusRemoteCloseInitiator: "ChanStatusRemoteCloseInitiator",
628
}
629

630
// orderedChanStatusFlags is an in-order list of all that channel status flags.
631
var orderedChanStatusFlags = []ChannelStatus{
632
        ChanStatusBorked,
633
        ChanStatusCommitBroadcasted,
634
        ChanStatusLocalDataLoss,
635
        ChanStatusRestored,
636
        ChanStatusCoopBroadcasted,
637
        ChanStatusLocalCloseInitiator,
638
        ChanStatusRemoteCloseInitiator,
639
}
640

641
// String returns a human-readable representation of the ChannelStatus.
642
func (c ChannelStatus) String() string {
5✔
643
        // If no flags are set, then this is the default case.
5✔
644
        if c == ChanStatusDefault {
9✔
645
                return chanStatusStrings[ChanStatusDefault]
4✔
646
        }
4✔
647

648
        // Add individual bit flags.
649
        statusStr := ""
5✔
650
        for _, flag := range orderedChanStatusFlags {
16✔
651
                if c&flag == flag {
16✔
652
                        statusStr += chanStatusStrings[flag] + "|"
5✔
653
                        c -= flag
5✔
654
                }
5✔
655
        }
656

657
        // Remove anything to the right of the final bar, including it as well.
658
        statusStr = strings.TrimRight(statusStr, "|")
5✔
659

5✔
660
        // Add any remaining flags which aren't accounted for as hex.
5✔
661
        if c != 0 {
5✔
662
                statusStr += "|0x" + strconv.FormatUint(uint64(c), 16)
×
663
        }
×
664

665
        // If this was purely an unknown flag, then remove the extra bar at the
666
        // start of the string.
667
        statusStr = strings.TrimLeft(statusStr, "|")
5✔
668

5✔
669
        return statusStr
5✔
670
}
671

672
// FinalHtlcByte defines a byte type that encodes information about the final
673
// htlc resolution.
674
type FinalHtlcByte byte
675

676
const (
677
        // FinalHtlcSettledBit is the bit that encodes whether the htlc was
678
        // settled or failed.
679
        FinalHtlcSettledBit FinalHtlcByte = 1 << 0
680

681
        // FinalHtlcOffchainBit is the bit that encodes whether the htlc was
682
        // resolved offchain or onchain.
683
        FinalHtlcOffchainBit FinalHtlcByte = 1 << 1
684
)
685

686
// OpenChannel encapsulates the persistent and dynamic state of an open channel
687
// with a remote node. An open channel supports several options for on-disk
688
// serialization depending on the exact context. Full (upon channel creation)
689
// state commitments, and partial (due to a commitment update) writes are
690
// supported. Each partial write due to a state update appends the new update
691
// to an on-disk log, which can then subsequently be queried in order to
692
// "time-travel" to a prior state.
693
type OpenChannel struct {
694
        // ChanType denotes which type of channel this is.
695
        ChanType ChannelType
696

697
        // ChainHash is a hash which represents the blockchain that this
698
        // channel will be opened within. This value is typically the genesis
699
        // hash. In the case that the original chain went through a contentious
700
        // hard-fork, then this value will be tweaked using the unique fork
701
        // point on each branch.
702
        ChainHash chainhash.Hash
703

704
        // FundingOutpoint is the outpoint of the final funding transaction.
705
        // This value uniquely and globally identifies the channel within the
706
        // target blockchain as specified by the chain hash parameter.
707
        FundingOutpoint wire.OutPoint
708

709
        // ShortChannelID encodes the exact location in the chain in which the
710
        // channel was initially confirmed. This includes: the block height,
711
        // transaction index, and the output within the target transaction.
712
        //
713
        // If IsZeroConf(), then this will the "base" (very first) ALIAS scid
714
        // and the confirmed SCID will be stored in ConfirmedScid.
715
        ShortChannelID lnwire.ShortChannelID
716

717
        // IsPending indicates whether a channel's funding transaction has been
718
        // confirmed.
719
        IsPending bool
720

721
        // IsInitiator is a bool which indicates if we were the original
722
        // initiator for the channel. This value may affect how higher levels
723
        // negotiate fees, or close the channel.
724
        IsInitiator bool
725

726
        // chanStatus is the current status of this channel. If it is not in
727
        // the state Default, it should not be used for forwarding payments.
728
        chanStatus ChannelStatus
729

730
        // FundingBroadcastHeight is the height in which the funding
731
        // transaction was broadcast. This value can be used by higher level
732
        // sub-systems to determine if a channel is stale and/or should have
733
        // been confirmed before a certain height.
734
        FundingBroadcastHeight uint32
735

736
        // NumConfsRequired is the number of confirmations a channel's funding
737
        // transaction must have received in order to be considered available
738
        // for normal transactional use.
739
        NumConfsRequired uint16
740

741
        // ChannelFlags holds the flags that were sent as part of the
742
        // open_channel message.
743
        ChannelFlags lnwire.FundingFlag
744

745
        // IdentityPub is the identity public key of the remote node this
746
        // channel has been established with.
747
        IdentityPub *btcec.PublicKey
748

749
        // Capacity is the total capacity of this channel.
750
        Capacity btcutil.Amount
751

752
        // TotalMSatSent is the total number of milli-satoshis we've sent
753
        // within this channel.
754
        TotalMSatSent lnwire.MilliSatoshi
755

756
        // TotalMSatReceived is the total number of milli-satoshis we've
757
        // received within this channel.
758
        TotalMSatReceived lnwire.MilliSatoshi
759

760
        // InitialLocalBalance is the balance we have during the channel
761
        // opening. When we are not the initiator, this value represents the
762
        // push amount.
763
        InitialLocalBalance lnwire.MilliSatoshi
764

765
        // InitialRemoteBalance is the balance they have during the channel
766
        // opening.
767
        InitialRemoteBalance lnwire.MilliSatoshi
768

769
        // LocalChanCfg is the channel configuration for the local node.
770
        LocalChanCfg ChannelConfig
771

772
        // RemoteChanCfg is the channel configuration for the remote node.
773
        RemoteChanCfg ChannelConfig
774

775
        // LocalCommitment is the current local commitment state for the local
776
        // party. This is stored distinct from the state of the remote party
777
        // as there are certain asymmetric parameters which affect the
778
        // structure of each commitment.
779
        LocalCommitment ChannelCommitment
780

781
        // RemoteCommitment is the current remote commitment state for the
782
        // remote party. This is stored distinct from the state of the local
783
        // party as there are certain asymmetric parameters which affect the
784
        // structure of each commitment.
785
        RemoteCommitment ChannelCommitment
786

787
        // RemoteCurrentRevocation is the current revocation for their
788
        // commitment transaction. However, since this the derived public key,
789
        // we don't yet have the private key so we aren't yet able to verify
790
        // that it's actually in the hash chain.
791
        RemoteCurrentRevocation *btcec.PublicKey
792

793
        // RemoteNextRevocation is the revocation key to be used for the *next*
794
        // commitment transaction we create for the local node. Within the
795
        // specification, this value is referred to as the
796
        // per-commitment-point.
797
        RemoteNextRevocation *btcec.PublicKey
798

799
        // RevocationProducer is used to generate the revocation in such a way
800
        // that remote side might store it efficiently and have the ability to
801
        // restore the revocation by index if needed. Current implementation of
802
        // secret producer is shachain producer.
803
        RevocationProducer shachain.Producer
804

805
        // RevocationStore is used to efficiently store the revocations for
806
        // previous channels states sent to us by remote side. Current
807
        // implementation of secret store is shachain store.
808
        RevocationStore shachain.Store
809

810
        // Packager is used to create and update forwarding packages for this
811
        // channel, which encodes all necessary information to recover from
812
        // failures and reforward HTLCs that were not fully processed.
813
        Packager FwdPackager
814

815
        // FundingTxn is the transaction containing this channel's funding
816
        // outpoint. Upon restarts, this txn will be rebroadcast if the channel
817
        // is found to be pending.
818
        //
819
        // NOTE: This value will only be populated for single-funder channels
820
        // for which we are the initiator, and that we also have the funding
821
        // transaction for. One can check this by using the HasFundingTx()
822
        // method on the ChanType field.
823
        FundingTxn *wire.MsgTx
824

825
        // LocalShutdownScript is set to a pre-set script if the channel was opened
826
        // by the local node with option_upfront_shutdown_script set. If the option
827
        // was not set, the field is empty.
828
        LocalShutdownScript lnwire.DeliveryAddress
829

830
        // RemoteShutdownScript is set to a pre-set script if the channel was opened
831
        // by the remote node with option_upfront_shutdown_script set. If the option
832
        // was not set, the field is empty.
833
        RemoteShutdownScript lnwire.DeliveryAddress
834

835
        // ThawHeight is the height when a frozen channel once again becomes a
836
        // normal channel. If this is zero, then there're no restrictions on
837
        // this channel. If the value is lower than 500,000, then it's
838
        // interpreted as a relative height, or an absolute height otherwise.
839
        ThawHeight uint32
840

841
        // LastWasRevoke is a boolean that determines if the last update we sent
842
        // was a revocation (true) or a commitment signature (false).
843
        LastWasRevoke bool
844

845
        // RevocationKeyLocator stores the KeyLocator information that we will
846
        // need to derive the shachain root for this channel. This allows us to
847
        // have private key isolation from lnd.
848
        RevocationKeyLocator keychain.KeyLocator
849

850
        // confirmedScid is the confirmed ShortChannelID for a zero-conf
851
        // channel. If the channel is unconfirmed, then this will be the
852
        // default ShortChannelID. This is only set for zero-conf channels.
853
        confirmedScid lnwire.ShortChannelID
854

855
        // Memo is any arbitrary information we wish to store locally about the
856
        // channel that will be useful to our future selves.
857
        Memo []byte
858

859
        // TODO(roasbeef): eww
860
        Db *ChannelStateDB
861

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

864
        sync.RWMutex
865
}
866

867
// String returns a string representation of the channel.
868
func (c *OpenChannel) String() string {
4✔
869
        indexStr := "height=%v, local_htlc_index=%v, local_log_index=%v, " +
4✔
870
                "remote_htlc_index=%v, remote_log_index=%v"
4✔
871

4✔
872
        commit := c.LocalCommitment
4✔
873
        local := fmt.Sprintf(indexStr, commit.CommitHeight,
4✔
874
                commit.LocalHtlcIndex, commit.LocalLogIndex,
4✔
875
                commit.RemoteHtlcIndex, commit.RemoteLogIndex,
4✔
876
        )
4✔
877

4✔
878
        commit = c.RemoteCommitment
4✔
879
        remote := fmt.Sprintf(indexStr, commit.CommitHeight,
4✔
880
                commit.LocalHtlcIndex, commit.LocalLogIndex,
4✔
881
                commit.RemoteHtlcIndex, commit.RemoteLogIndex,
4✔
882
        )
4✔
883

4✔
884
        return fmt.Sprintf("SCID=%v, status=%v, initiator=%v, pending=%v, "+
4✔
885
                "local commitment has %s, remote commitment has %s",
4✔
886
                c.ShortChannelID, c.chanStatus, c.IsInitiator, c.IsPending,
4✔
887
                local, remote,
4✔
888
        )
4✔
889
}
4✔
890

891
// ShortChanID returns the current ShortChannelID of this channel.
892
func (c *OpenChannel) ShortChanID() lnwire.ShortChannelID {
14,158✔
893
        c.RLock()
14,158✔
894
        defer c.RUnlock()
14,158✔
895

14,158✔
896
        return c.ShortChannelID
14,158✔
897
}
14,158✔
898

899
// ZeroConfRealScid returns the zero-conf channel's confirmed scid. This should
900
// only be called if IsZeroConf returns true.
901
func (c *OpenChannel) ZeroConfRealScid() lnwire.ShortChannelID {
13✔
902
        c.RLock()
13✔
903
        defer c.RUnlock()
13✔
904

13✔
905
        return c.confirmedScid
13✔
906
}
13✔
907

908
// ZeroConfConfirmed returns whether the zero-conf channel has confirmed. This
909
// should only be called if IsZeroConf returns true.
910
func (c *OpenChannel) ZeroConfConfirmed() bool {
9✔
911
        c.RLock()
9✔
912
        defer c.RUnlock()
9✔
913

9✔
914
        return c.confirmedScid != hop.Source
9✔
915
}
9✔
916

917
// IsZeroConf returns whether the option_zeroconf channel type was negotiated.
918
func (c *OpenChannel) IsZeroConf() bool {
644✔
919
        c.RLock()
644✔
920
        defer c.RUnlock()
644✔
921

644✔
922
        return c.ChanType.HasZeroConf()
644✔
923
}
644✔
924

925
// IsOptionScidAlias returns whether the option_scid_alias channel type was
926
// negotiated.
927
func (c *OpenChannel) IsOptionScidAlias() bool {
×
928
        c.RLock()
×
929
        defer c.RUnlock()
×
930

×
931
        return c.ChanType.HasScidAliasChan()
×
932
}
×
933

934
// NegotiatedAliasFeature returns whether the option-scid-alias feature bit was
935
// negotiated.
936
func (c *OpenChannel) NegotiatedAliasFeature() bool {
482✔
937
        c.RLock()
482✔
938
        defer c.RUnlock()
482✔
939

482✔
940
        return c.ChanType.HasScidAliasFeature()
482✔
941
}
482✔
942

943
// ChanStatus returns the current ChannelStatus of this channel.
944
func (c *OpenChannel) ChanStatus() ChannelStatus {
212✔
945
        c.RLock()
212✔
946
        defer c.RUnlock()
212✔
947

212✔
948
        return c.chanStatus
212✔
949
}
212✔
950

951
// ApplyChanStatus allows the caller to modify the internal channel state in a
952
// thead-safe manner.
953
func (c *OpenChannel) ApplyChanStatus(status ChannelStatus) error {
3✔
954
        c.Lock()
3✔
955
        defer c.Unlock()
3✔
956

3✔
957
        return c.putChanStatus(status)
3✔
958
}
3✔
959

960
// ClearChanStatus allows the caller to clear a particular channel status from
961
// the primary channel status bit field. After this method returns, a call to
962
// HasChanStatus(status) should return false.
963
func (c *OpenChannel) ClearChanStatus(status ChannelStatus) error {
4✔
964
        c.Lock()
4✔
965
        defer c.Unlock()
4✔
966

4✔
967
        return c.clearChanStatus(status)
4✔
968
}
4✔
969

970
// HasChanStatus returns true if the internal bitfield channel status of the
971
// target channel has the specified status bit set.
972
func (c *OpenChannel) HasChanStatus(status ChannelStatus) bool {
350✔
973
        c.RLock()
350✔
974
        defer c.RUnlock()
350✔
975

350✔
976
        return c.hasChanStatus(status)
350✔
977
}
350✔
978

979
func (c *OpenChannel) hasChanStatus(status ChannelStatus) bool {
29,534✔
980
        // Special case ChanStatusDefualt since it isn't actually flag, but a
29,534✔
981
        // particular combination (or lack-there-of) of flags.
29,534✔
982
        if status == ChanStatusDefault {
29,542✔
983
                return c.chanStatus == ChanStatusDefault
8✔
984
        }
8✔
985

986
        return c.chanStatus&status == status
29,530✔
987
}
988

989
// BroadcastHeight returns the height at which the funding tx was broadcast.
990
func (c *OpenChannel) BroadcastHeight() uint32 {
107✔
991
        c.RLock()
107✔
992
        defer c.RUnlock()
107✔
993

107✔
994
        return c.FundingBroadcastHeight
107✔
995
}
107✔
996

997
// SetBroadcastHeight sets the FundingBroadcastHeight.
998
func (c *OpenChannel) SetBroadcastHeight(height uint32) {
4✔
999
        c.Lock()
4✔
1000
        defer c.Unlock()
4✔
1001

4✔
1002
        c.FundingBroadcastHeight = height
4✔
1003
}
4✔
1004

1005
// Refresh updates the in-memory channel state using the latest state observed
1006
// on disk.
1007
func (c *OpenChannel) Refresh() error {
9✔
1008
        c.Lock()
9✔
1009
        defer c.Unlock()
9✔
1010

9✔
1011
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
18✔
1012
                chanBucket, err := fetchChanBucket(
9✔
1013
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
9✔
1014
                )
9✔
1015
                if err != nil {
13✔
1016
                        return err
4✔
1017
                }
4✔
1018

1019
                // We'll re-populating the in-memory channel with the info
1020
                // fetched from disk.
1021
                if err := fetchChanInfo(chanBucket, c); err != nil {
9✔
1022
                        return fmt.Errorf("unable to fetch chan info: %w", err)
×
1023
                }
×
1024

1025
                // Also populate the channel's commitment states for both sides
1026
                // of the channel.
1027
                if err := fetchChanCommitments(chanBucket, c); err != nil {
9✔
1028
                        return fmt.Errorf("unable to fetch chan commitments: "+
×
1029
                                "%v", err)
×
1030
                }
×
1031

1032
                // Also retrieve the current revocation state.
1033
                if err := fetchChanRevocationState(chanBucket, c); err != nil {
9✔
1034
                        return fmt.Errorf("unable to fetch chan revocations: "+
×
1035
                                "%v", err)
×
1036
                }
×
1037

1038
                return nil
9✔
1039
        }, func() {})
9✔
1040
        if err != nil {
13✔
1041
                return err
4✔
1042
        }
4✔
1043

1044
        return nil
9✔
1045
}
1046

1047
// fetchChanBucket is a helper function that returns the bucket where a
1048
// channel's data resides in given: the public key for the node, the outpoint,
1049
// and the chainhash that the channel resides on.
1050
func fetchChanBucket(tx kvdb.RTx, nodeKey *btcec.PublicKey,
1051
        outPoint *wire.OutPoint, chainHash chainhash.Hash) (kvdb.RBucket, error) {
2,799✔
1052

2,799✔
1053
        // First fetch the top level bucket which stores all data related to
2,799✔
1054
        // current, active channels.
2,799✔
1055
        openChanBucket := tx.ReadBucket(openChannelBucket)
2,799✔
1056
        if openChanBucket == nil {
2,799✔
1057
                return nil, ErrNoChanDBExists
×
1058
        }
×
1059

1060
        // TODO(roasbeef): CreateTopLevelBucket on the interface isn't like
1061
        // CreateIfNotExists, will return error
1062

1063
        // Within this top level bucket, fetch the bucket dedicated to storing
1064
        // open channel data specific to the remote node.
1065
        nodePub := nodeKey.SerializeCompressed()
2,799✔
1066
        nodeChanBucket := openChanBucket.NestedReadBucket(nodePub)
2,799✔
1067
        if nodeChanBucket == nil {
3,819✔
1068
                return nil, ErrNoActiveChannels
1,020✔
1069
        }
1,020✔
1070

1071
        // We'll then recurse down an additional layer in order to fetch the
1072
        // bucket for this particular chain.
1073
        chainBucket := nodeChanBucket.NestedReadBucket(chainHash[:])
1,779✔
1074
        if chainBucket == nil {
1,779✔
1075
                return nil, ErrNoActiveChannels
×
1076
        }
×
1077

1078
        // With the bucket for the node and chain fetched, we can now go down
1079
        // another level, for this channel itself.
1080
        var chanPointBuf bytes.Buffer
1,779✔
1081
        if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
1,779✔
1082
                return nil, err
×
1083
        }
×
1084
        chanBucket := chainBucket.NestedReadBucket(chanPointBuf.Bytes())
1,779✔
1085
        if chanBucket == nil {
1,784✔
1086
                return nil, ErrChannelNotFound
5✔
1087
        }
5✔
1088

1089
        return chanBucket, nil
1,778✔
1090
}
1091

1092
// fetchChanBucketRw is a helper function that returns the bucket where a
1093
// channel's data resides in given: the public key for the node, the outpoint,
1094
// and the chainhash that the channel resides on. This differs from
1095
// fetchChanBucket in that it returns a writeable bucket.
1096
func fetchChanBucketRw(tx kvdb.RwTx, nodeKey *btcec.PublicKey,
1097
        outPoint *wire.OutPoint, chainHash chainhash.Hash) (kvdb.RwBucket,
1098
        error) {
10,204✔
1099

10,204✔
1100
        // First fetch the top level bucket which stores all data related to
10,204✔
1101
        // current, active channels.
10,204✔
1102
        openChanBucket := tx.ReadWriteBucket(openChannelBucket)
10,204✔
1103
        if openChanBucket == nil {
10,204✔
1104
                return nil, ErrNoChanDBExists
×
1105
        }
×
1106

1107
        // TODO(roasbeef): CreateTopLevelBucket on the interface isn't like
1108
        // CreateIfNotExists, will return error
1109

1110
        // Within this top level bucket, fetch the bucket dedicated to storing
1111
        // open channel data specific to the remote node.
1112
        nodePub := nodeKey.SerializeCompressed()
10,204✔
1113
        nodeChanBucket := openChanBucket.NestedReadWriteBucket(nodePub)
10,204✔
1114
        if nodeChanBucket == nil {
10,204✔
1115
                return nil, ErrNoActiveChannels
×
1116
        }
×
1117

1118
        // We'll then recurse down an additional layer in order to fetch the
1119
        // bucket for this particular chain.
1120
        chainBucket := nodeChanBucket.NestedReadWriteBucket(chainHash[:])
10,204✔
1121
        if chainBucket == nil {
10,204✔
1122
                return nil, ErrNoActiveChannels
×
1123
        }
×
1124

1125
        // With the bucket for the node and chain fetched, we can now go down
1126
        // another level, for this channel itself.
1127
        var chanPointBuf bytes.Buffer
10,204✔
1128
        if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
10,204✔
1129
                return nil, err
×
1130
        }
×
1131
        chanBucket := chainBucket.NestedReadWriteBucket(chanPointBuf.Bytes())
10,204✔
1132
        if chanBucket == nil {
10,204✔
1133
                return nil, ErrChannelNotFound
×
1134
        }
×
1135

1136
        return chanBucket, nil
10,204✔
1137
}
1138

1139
func fetchFinalHtlcsBucketRw(tx kvdb.RwTx,
1140
        chanID lnwire.ShortChannelID) (kvdb.RwBucket, error) {
7✔
1141

7✔
1142
        finalHtlcsBucket, err := tx.CreateTopLevelBucket(finalHtlcsBucket)
7✔
1143
        if err != nil {
7✔
1144
                return nil, err
×
1145
        }
×
1146

1147
        var chanIDBytes [8]byte
7✔
1148
        byteOrder.PutUint64(chanIDBytes[:], chanID.ToUint64())
7✔
1149
        chanBucket, err := finalHtlcsBucket.CreateBucketIfNotExists(
7✔
1150
                chanIDBytes[:],
7✔
1151
        )
7✔
1152
        if err != nil {
7✔
1153
                return nil, err
×
1154
        }
×
1155

1156
        return chanBucket, nil
7✔
1157
}
1158

1159
// fullSync syncs the contents of an OpenChannel while re-using an existing
1160
// database transaction.
1161
func (c *OpenChannel) fullSync(tx kvdb.RwTx) error {
847✔
1162
        // Fetch the outpoint bucket and check if the outpoint already exists.
847✔
1163
        opBucket := tx.ReadWriteBucket(outpointBucket)
847✔
1164
        if opBucket == nil {
847✔
1165
                return ErrNoChanDBExists
×
1166
        }
×
1167
        cidBucket := tx.ReadWriteBucket(chanIDBucket)
847✔
1168
        if cidBucket == nil {
847✔
1169
                return ErrNoChanDBExists
×
1170
        }
×
1171

1172
        var chanPointBuf bytes.Buffer
847✔
1173
        if err := writeOutpoint(&chanPointBuf, &c.FundingOutpoint); err != nil {
847✔
1174
                return err
×
1175
        }
×
1176

1177
        // Now, check if the outpoint exists in our index.
1178
        if opBucket.Get(chanPointBuf.Bytes()) != nil {
851✔
1179
                return ErrChanAlreadyExists
4✔
1180
        }
4✔
1181

1182
        cid := lnwire.NewChanIDFromOutPoint(c.FundingOutpoint)
847✔
1183
        if cidBucket.Get(cid[:]) != nil {
847✔
1184
                return ErrChanAlreadyExists
×
1185
        }
×
1186

1187
        status := uint8(outpointOpen)
847✔
1188

847✔
1189
        // Write the status of this outpoint as the first entry in a tlv
847✔
1190
        // stream.
847✔
1191
        statusRecord := tlv.MakePrimitiveRecord(indexStatusType, &status)
847✔
1192
        opStream, err := tlv.NewStream(statusRecord)
847✔
1193
        if err != nil {
847✔
1194
                return err
×
1195
        }
×
1196

1197
        var b bytes.Buffer
847✔
1198
        if err := opStream.Encode(&b); err != nil {
847✔
1199
                return err
×
1200
        }
×
1201

1202
        // Add the outpoint to our outpoint index with the tlv stream.
1203
        if err := opBucket.Put(chanPointBuf.Bytes(), b.Bytes()); err != nil {
847✔
1204
                return err
×
1205
        }
×
1206

1207
        if err := cidBucket.Put(cid[:], []byte{}); err != nil {
847✔
1208
                return err
×
1209
        }
×
1210

1211
        // First fetch the top level bucket which stores all data related to
1212
        // current, active channels.
1213
        openChanBucket, err := tx.CreateTopLevelBucket(openChannelBucket)
847✔
1214
        if err != nil {
847✔
1215
                return err
×
1216
        }
×
1217

1218
        // Within this top level bucket, fetch the bucket dedicated to storing
1219
        // open channel data specific to the remote node.
1220
        nodePub := c.IdentityPub.SerializeCompressed()
847✔
1221
        nodeChanBucket, err := openChanBucket.CreateBucketIfNotExists(nodePub)
847✔
1222
        if err != nil {
847✔
1223
                return err
×
1224
        }
×
1225

1226
        // We'll then recurse down an additional layer in order to fetch the
1227
        // bucket for this particular chain.
1228
        chainBucket, err := nodeChanBucket.CreateBucketIfNotExists(c.ChainHash[:])
847✔
1229
        if err != nil {
847✔
1230
                return err
×
1231
        }
×
1232

1233
        // With the bucket for the node fetched, we can now go down another
1234
        // level, creating the bucket for this channel itself.
1235
        chanBucket, err := chainBucket.CreateBucket(
847✔
1236
                chanPointBuf.Bytes(),
847✔
1237
        )
847✔
1238
        switch {
847✔
1239
        case err == kvdb.ErrBucketExists:
×
1240
                // If this channel already exists, then in order to avoid
×
1241
                // overriding it, we'll return an error back up to the caller.
×
1242
                return ErrChanAlreadyExists
×
1243
        case err != nil:
×
1244
                return err
×
1245
        }
1246

1247
        return putOpenChannel(chanBucket, c)
847✔
1248
}
1249

1250
// MarkAsOpen marks a channel as fully open given a locator that uniquely
1251
// describes its location within the chain.
1252
func (c *OpenChannel) MarkAsOpen(openLoc lnwire.ShortChannelID) error {
167✔
1253
        c.Lock()
167✔
1254
        defer c.Unlock()
167✔
1255

167✔
1256
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
334✔
1257
                chanBucket, err := fetchChanBucketRw(
167✔
1258
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
167✔
1259
                )
167✔
1260
                if err != nil {
167✔
1261
                        return err
×
1262
                }
×
1263

1264
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
167✔
1265
                if err != nil {
167✔
1266
                        return err
×
1267
                }
×
1268

1269
                channel.IsPending = false
167✔
1270
                channel.ShortChannelID = openLoc
167✔
1271

167✔
1272
                return putOpenChannel(chanBucket, channel)
167✔
1273
        }, func() {}); err != nil {
167✔
1274
                return err
×
1275
        }
×
1276

1277
        c.IsPending = false
167✔
1278
        c.ShortChannelID = openLoc
167✔
1279
        c.Packager = NewChannelPackager(openLoc)
167✔
1280

167✔
1281
        return nil
167✔
1282
}
1283

1284
// MarkRealScid marks the zero-conf channel's confirmed ShortChannelID. This
1285
// should only be done if IsZeroConf returns true.
1286
func (c *OpenChannel) MarkRealScid(realScid lnwire.ShortChannelID) error {
11✔
1287
        c.Lock()
11✔
1288
        defer c.Unlock()
11✔
1289

11✔
1290
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
22✔
1291
                chanBucket, err := fetchChanBucketRw(
11✔
1292
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
11✔
1293
                )
11✔
1294
                if err != nil {
11✔
1295
                        return err
×
1296
                }
×
1297

1298
                channel, err := fetchOpenChannel(
11✔
1299
                        chanBucket, &c.FundingOutpoint,
11✔
1300
                )
11✔
1301
                if err != nil {
11✔
1302
                        return err
×
1303
                }
×
1304

1305
                channel.confirmedScid = realScid
11✔
1306

11✔
1307
                return putOpenChannel(chanBucket, channel)
11✔
1308
        }, func() {}); err != nil {
11✔
1309
                return err
×
1310
        }
×
1311

1312
        c.confirmedScid = realScid
11✔
1313

11✔
1314
        return nil
11✔
1315
}
1316

1317
// MarkScidAliasNegotiated adds ScidAliasFeatureBit to ChanType in-memory and
1318
// in the database.
1319
func (c *OpenChannel) MarkScidAliasNegotiated() error {
4✔
1320
        c.Lock()
4✔
1321
        defer c.Unlock()
4✔
1322

4✔
1323
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
8✔
1324
                chanBucket, err := fetchChanBucketRw(
4✔
1325
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
4✔
1326
                )
4✔
1327
                if err != nil {
4✔
1328
                        return err
×
1329
                }
×
1330

1331
                channel, err := fetchOpenChannel(
4✔
1332
                        chanBucket, &c.FundingOutpoint,
4✔
1333
                )
4✔
1334
                if err != nil {
4✔
1335
                        return err
×
1336
                }
×
1337

1338
                channel.ChanType |= ScidAliasFeatureBit
4✔
1339
                return putOpenChannel(chanBucket, channel)
4✔
1340
        }, func() {}); err != nil {
4✔
1341
                return err
×
1342
        }
×
1343

1344
        c.ChanType |= ScidAliasFeatureBit
4✔
1345

4✔
1346
        return nil
4✔
1347
}
1348

1349
// MarkDataLoss marks sets the channel status to LocalDataLoss and stores the
1350
// passed commitPoint for use to retrieve funds in case the remote force closes
1351
// the channel.
1352
func (c *OpenChannel) MarkDataLoss(commitPoint *btcec.PublicKey) error {
8✔
1353
        c.Lock()
8✔
1354
        defer c.Unlock()
8✔
1355

8✔
1356
        var b bytes.Buffer
8✔
1357
        if err := WriteElement(&b, commitPoint); err != nil {
8✔
1358
                return err
×
1359
        }
×
1360

1361
        putCommitPoint := func(chanBucket kvdb.RwBucket) error {
16✔
1362
                return chanBucket.Put(dataLossCommitPointKey, b.Bytes())
8✔
1363
        }
8✔
1364

1365
        return c.putChanStatus(ChanStatusLocalDataLoss, putCommitPoint)
8✔
1366
}
1367

1368
// DataLossCommitPoint retrieves the stored commit point set during
1369
// MarkDataLoss. If not found ErrNoCommitPoint is returned.
1370
func (c *OpenChannel) DataLossCommitPoint() (*btcec.PublicKey, error) {
4✔
1371
        var commitPoint *btcec.PublicKey
4✔
1372

4✔
1373
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
8✔
1374
                chanBucket, err := fetchChanBucket(
4✔
1375
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
4✔
1376
                )
4✔
1377
                switch err {
4✔
1378
                case nil:
4✔
1379
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
×
1380
                        return ErrNoCommitPoint
×
1381
                default:
×
1382
                        return err
×
1383
                }
1384

1385
                bs := chanBucket.Get(dataLossCommitPointKey)
4✔
1386
                if bs == nil {
4✔
1387
                        return ErrNoCommitPoint
×
1388
                }
×
1389
                r := bytes.NewReader(bs)
4✔
1390
                if err := ReadElements(r, &commitPoint); err != nil {
4✔
1391
                        return err
×
1392
                }
×
1393

1394
                return nil
4✔
1395
        }, func() {
4✔
1396
                commitPoint = nil
4✔
1397
        })
4✔
1398
        if err != nil {
4✔
1399
                return nil, err
×
1400
        }
×
1401

1402
        return commitPoint, nil
4✔
1403
}
1404

1405
// MarkBorked marks the event when the channel as reached an irreconcilable
1406
// state, such as a channel breach or state desynchronization. Borked channels
1407
// should never be added to the switch.
1408
func (c *OpenChannel) MarkBorked() error {
5✔
1409
        c.Lock()
5✔
1410
        defer c.Unlock()
5✔
1411

5✔
1412
        return c.putChanStatus(ChanStatusBorked)
5✔
1413
}
5✔
1414

1415
// SecondCommitmentPoint returns the second per-commitment-point for use in the
1416
// channel_ready message.
1417
func (c *OpenChannel) SecondCommitmentPoint() (*btcec.PublicKey, error) {
4✔
1418
        c.RLock()
4✔
1419
        defer c.RUnlock()
4✔
1420

4✔
1421
        // Since we start at commitment height = 0, the second per commitment
4✔
1422
        // point is actually at the 1st index.
4✔
1423
        revocation, err := c.RevocationProducer.AtIndex(1)
4✔
1424
        if err != nil {
4✔
1425
                return nil, err
×
1426
        }
×
1427

1428
        return input.ComputeCommitmentPoint(revocation[:]), nil
4✔
1429
}
1430

1431
var (
1432
        // taprootRevRootKey is the key used to derive the revocation root for
1433
        // the taproot nonces. This is done via HMAC of the existing revocation
1434
        // root.
1435
        taprootRevRootKey = []byte("taproot-rev-root")
1436
)
1437

1438
// DeriveMusig2Shachain derives a shachain producer for the taproot channel
1439
// from normal shachain revocation root.
1440
func DeriveMusig2Shachain(revRoot shachain.Producer) (shachain.Producer, error) { //nolint:lll
923✔
1441
        // In order to obtain the revocation root hash to create the taproot
923✔
1442
        // revocation, we'll encode the producer into a buffer, then use that
923✔
1443
        // to derive the shachain root needed.
923✔
1444
        var rootHashBuf bytes.Buffer
923✔
1445
        if err := revRoot.Encode(&rootHashBuf); err != nil {
923✔
1446
                return nil, fmt.Errorf("unable to encode producer: %w", err)
×
1447
        }
×
1448

1449
        revRootHash := chainhash.HashH(rootHashBuf.Bytes())
923✔
1450

923✔
1451
        // For taproot channel types, we'll also generate a distinct shachain
923✔
1452
        // root using the same seed information. We'll use this to generate
923✔
1453
        // verification nonces for the channel. We'll bind with this a simple
923✔
1454
        // hmac.
923✔
1455
        taprootRevHmac := hmac.New(sha256.New, taprootRevRootKey)
923✔
1456
        if _, err := taprootRevHmac.Write(revRootHash[:]); err != nil {
923✔
1457
                return nil, err
×
1458
        }
×
1459

1460
        taprootRevRoot := taprootRevHmac.Sum(nil)
923✔
1461

923✔
1462
        // Once we have the root, we can then generate our shachain producer
923✔
1463
        // and from that generate the per-commitment point.
923✔
1464
        return shachain.NewRevocationProducerFromBytes(
923✔
1465
                taprootRevRoot,
923✔
1466
        )
923✔
1467
}
1468

1469
// NewMusigVerificationNonce generates the local or verification nonce for
1470
// another musig2 session. In order to permit our implementation to not have to
1471
// write any secret nonce state to disk, we'll use the _next_ shachain
1472
// pre-image as our primary randomness source. When used to generate the nonce
1473
// again to broadcast our commitment hte current height will be used.
1474
func NewMusigVerificationNonce(pubKey *btcec.PublicKey, targetHeight uint64,
1475
        shaGen shachain.Producer) (*musig2.Nonces, error) {
90✔
1476

90✔
1477
        // Now that we know what height we need, we'll grab the shachain
90✔
1478
        // pre-image at the target destination.
90✔
1479
        nextPreimage, err := shaGen.AtIndex(targetHeight)
90✔
1480
        if err != nil {
90✔
1481
                return nil, err
×
1482
        }
×
1483

1484
        shaChainRand := musig2.WithCustomRand(bytes.NewBuffer(nextPreimage[:]))
90✔
1485
        pubKeyOpt := musig2.WithPublicKey(pubKey)
90✔
1486

90✔
1487
        return musig2.GenNonces(pubKeyOpt, shaChainRand)
90✔
1488
}
1489

1490
// ChanSyncMsg returns the ChannelReestablish message that should be sent upon
1491
// reconnection with the remote peer that we're maintaining this channel with.
1492
// The information contained within this message is necessary to re-sync our
1493
// commitment chains in the case of a last or only partially processed message.
1494
// When the remote party receives this message one of three things may happen:
1495
//
1496
//  1. We're fully synced and no messages need to be sent.
1497
//  2. We didn't get the last CommitSig message they sent, so they'll re-send
1498
//     it.
1499
//  3. We didn't get the last RevokeAndAck message they sent, so they'll
1500
//     re-send it.
1501
//
1502
// If this is a restored channel, having status ChanStatusRestored, then we'll
1503
// modify our typical chan sync message to ensure they force close even if
1504
// we're on the very first state.
1505
func (c *OpenChannel) ChanSyncMsg() (*lnwire.ChannelReestablish, error) {
240✔
1506
        c.Lock()
240✔
1507
        defer c.Unlock()
240✔
1508

240✔
1509
        // The remote commitment height that we'll send in the
240✔
1510
        // ChannelReestablish message is our current commitment height plus
240✔
1511
        // one. If the receiver thinks that our commitment height is actually
240✔
1512
        // *equal* to this value, then they'll re-send the last commitment that
240✔
1513
        // they sent but we never fully processed.
240✔
1514
        localHeight := c.LocalCommitment.CommitHeight
240✔
1515
        nextLocalCommitHeight := localHeight + 1
240✔
1516

240✔
1517
        // The second value we'll send is the height of the remote commitment
240✔
1518
        // from our PoV. If the receiver thinks that their height is actually
240✔
1519
        // *one plus* this value, then they'll re-send their last revocation.
240✔
1520
        remoteChainTipHeight := c.RemoteCommitment.CommitHeight
240✔
1521

240✔
1522
        // If this channel has undergone a commitment update, then in order to
240✔
1523
        // prove to the remote party our knowledge of their prior commitment
240✔
1524
        // state, we'll also send over the last commitment secret that the
240✔
1525
        // remote party sent.
240✔
1526
        var lastCommitSecret [32]byte
240✔
1527
        if remoteChainTipHeight != 0 {
298✔
1528
                remoteSecret, err := c.RevocationStore.LookUp(
58✔
1529
                        remoteChainTipHeight - 1,
58✔
1530
                )
58✔
1531
                if err != nil {
58✔
1532
                        return nil, err
×
1533
                }
×
1534
                lastCommitSecret = [32]byte(*remoteSecret)
58✔
1535
        }
1536

1537
        // Additionally, we'll send over the current unrevoked commitment on
1538
        // our local commitment transaction.
1539
        currentCommitSecret, err := c.RevocationProducer.AtIndex(
240✔
1540
                localHeight,
240✔
1541
        )
240✔
1542
        if err != nil {
240✔
1543
                return nil, err
×
1544
        }
×
1545

1546
        // If we've restored this channel, then we'll purposefully give them an
1547
        // invalid LocalUnrevokedCommitPoint so they'll force close the channel
1548
        // allowing us to sweep our funds.
1549
        if c.hasChanStatus(ChanStatusRestored) {
244✔
1550
                currentCommitSecret[0] ^= 1
4✔
1551

4✔
1552
                // If this is a tweakless channel, then we'll purposefully send
4✔
1553
                // a next local height taht's invalid to trigger a force close
4✔
1554
                // on their end. We do this as tweakless channels don't require
4✔
1555
                // that the commitment point is valid, only that it's present.
4✔
1556
                if c.ChanType.IsTweakless() {
8✔
1557
                        nextLocalCommitHeight = 0
4✔
1558
                }
4✔
1559
        }
1560

1561
        // If this is a taproot channel, then we'll need to generate our next
1562
        // verification nonce to send to the remote party. They'll use this to
1563
        // sign the next update to our commitment transaction.
1564
        var nextTaprootNonce lnwire.OptMusig2NonceTLV
240✔
1565
        if c.ChanType.IsTaproot() {
252✔
1566
                taprootRevProducer, err := DeriveMusig2Shachain(
12✔
1567
                        c.RevocationProducer,
12✔
1568
                )
12✔
1569
                if err != nil {
12✔
1570
                        return nil, err
×
1571
                }
×
1572

1573
                nextNonce, err := NewMusigVerificationNonce(
12✔
1574
                        c.LocalChanCfg.MultiSigKey.PubKey,
12✔
1575
                        nextLocalCommitHeight, taprootRevProducer,
12✔
1576
                )
12✔
1577
                if err != nil {
12✔
1578
                        return nil, fmt.Errorf("unable to gen next "+
×
1579
                                "nonce: %w", err)
×
1580
                }
×
1581

1582
                nextTaprootNonce = lnwire.SomeMusig2Nonce(nextNonce.PubNonce)
12✔
1583
        }
1584

1585
        return &lnwire.ChannelReestablish{
240✔
1586
                ChanID: lnwire.NewChanIDFromOutPoint(
240✔
1587
                        c.FundingOutpoint,
240✔
1588
                ),
240✔
1589
                NextLocalCommitHeight:  nextLocalCommitHeight,
240✔
1590
                RemoteCommitTailHeight: remoteChainTipHeight,
240✔
1591
                LastRemoteCommitSecret: lastCommitSecret,
240✔
1592
                LocalUnrevokedCommitPoint: input.ComputeCommitmentPoint(
240✔
1593
                        currentCommitSecret[:],
240✔
1594
                ),
240✔
1595
                LocalNonce: nextTaprootNonce,
240✔
1596
        }, nil
240✔
1597
}
1598

1599
// MarkShutdownSent serialises and persist the given ShutdownInfo for this
1600
// channel. Persisting this info represents the fact that we have sent the
1601
// Shutdown message to the remote side and hence that we should re-transmit the
1602
// same Shutdown message on re-establish.
1603
func (c *OpenChannel) MarkShutdownSent(info *ShutdownInfo) error {
15✔
1604
        c.Lock()
15✔
1605
        defer c.Unlock()
15✔
1606

15✔
1607
        return c.storeShutdownInfo(info)
15✔
1608
}
15✔
1609

1610
// storeShutdownInfo serialises the ShutdownInfo and persists it under the
1611
// shutdownInfoKey.
1612
func (c *OpenChannel) storeShutdownInfo(info *ShutdownInfo) error {
15✔
1613
        var b bytes.Buffer
15✔
1614
        err := info.encode(&b)
15✔
1615
        if err != nil {
15✔
1616
                return err
×
1617
        }
×
1618

1619
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
30✔
1620
                chanBucket, err := fetchChanBucketRw(
15✔
1621
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
15✔
1622
                )
15✔
1623
                if err != nil {
15✔
1624
                        return err
×
1625
                }
×
1626

1627
                return chanBucket.Put(shutdownInfoKey, b.Bytes())
15✔
1628
        }, func() {})
15✔
1629
}
1630

1631
// ShutdownInfo decodes the shutdown info stored for this channel and returns
1632
// the result. If no shutdown info has been persisted for this channel then the
1633
// ErrNoShutdownInfo error is returned.
1634
func (c *OpenChannel) ShutdownInfo() (fn.Option[ShutdownInfo], error) {
8✔
1635
        c.RLock()
8✔
1636
        defer c.RUnlock()
8✔
1637

8✔
1638
        var shutdownInfo *ShutdownInfo
8✔
1639
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
16✔
1640
                chanBucket, err := fetchChanBucket(
8✔
1641
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
8✔
1642
                )
8✔
1643
                switch {
8✔
1644
                case err == nil:
8✔
1645
                case errors.Is(err, ErrNoChanDBExists),
1646
                        errors.Is(err, ErrNoActiveChannels),
1647
                        errors.Is(err, ErrChannelNotFound):
2✔
1648

2✔
1649
                        return ErrNoShutdownInfo
2✔
1650
                default:
×
1651
                        return err
×
1652
                }
1653

1654
                shutdownInfoBytes := chanBucket.Get(shutdownInfoKey)
8✔
1655
                if shutdownInfoBytes == nil {
14✔
1656
                        return ErrNoShutdownInfo
6✔
1657
                }
6✔
1658

1659
                shutdownInfo, err = decodeShutdownInfo(shutdownInfoBytes)
6✔
1660

6✔
1661
                return err
6✔
1662
        }, func() {
8✔
1663
                shutdownInfo = nil
8✔
1664
        })
8✔
1665
        if err != nil {
14✔
1666
                return fn.None[ShutdownInfo](), err
6✔
1667
        }
6✔
1668

1669
        return fn.Some[ShutdownInfo](*shutdownInfo), nil
6✔
1670
}
1671

1672
// isBorked returns true if the channel has been marked as borked in the
1673
// database. This requires an existing database transaction to already be
1674
// active.
1675
//
1676
// NOTE: The primary mutex should already be held before this method is called.
1677
func (c *OpenChannel) isBorked(chanBucket kvdb.RBucket) (bool, error) {
9,376✔
1678
        channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
9,376✔
1679
        if err != nil {
9,376✔
1680
                return false, err
×
1681
        }
×
1682

1683
        return channel.chanStatus != ChanStatusDefault, nil
9,376✔
1684
}
1685

1686
// MarkCommitmentBroadcasted marks the channel as a commitment transaction has
1687
// been broadcast, either our own or the remote, and we should watch the chain
1688
// for it to confirm before taking any further action. It takes as argument the
1689
// closing tx _we believe_ will appear in the chain. This is only used to
1690
// republish this tx at startup to ensure propagation, and we should still
1691
// handle the case where a different tx actually hits the chain.
1692
func (c *OpenChannel) MarkCommitmentBroadcasted(closeTx *wire.MsgTx,
1693
        locallyInitiated bool) error {
12✔
1694

12✔
1695
        return c.markBroadcasted(
12✔
1696
                ChanStatusCommitBroadcasted, forceCloseTxKey, closeTx,
12✔
1697
                locallyInitiated,
12✔
1698
        )
12✔
1699
}
12✔
1700

1701
// MarkCoopBroadcasted marks the channel to indicate that a cooperative close
1702
// transaction has been broadcast, either our own or the remote, and that we
1703
// should watch the chain for it to confirm before taking further action. It
1704
// takes as argument a cooperative close tx that could appear on chain, and
1705
// should be rebroadcast upon startup. This is only used to republish and
1706
// ensure propagation, and we should still handle the case where a different tx
1707
// actually hits the chain.
1708
func (c *OpenChannel) MarkCoopBroadcasted(closeTx *wire.MsgTx,
1709
        locallyInitiated bool) error {
42✔
1710

42✔
1711
        return c.markBroadcasted(
42✔
1712
                ChanStatusCoopBroadcasted, coopCloseTxKey, closeTx,
42✔
1713
                locallyInitiated,
42✔
1714
        )
42✔
1715
}
42✔
1716

1717
// markBroadcasted is a helper function which modifies the channel status of the
1718
// receiving channel and inserts a close transaction under the requested key,
1719
// which should specify either a coop or force close. It adds a status which
1720
// indicates the party that initiated the channel close.
1721
func (c *OpenChannel) markBroadcasted(status ChannelStatus, key []byte,
1722
        closeTx *wire.MsgTx, locallyInitiated bool) error {
50✔
1723

50✔
1724
        c.Lock()
50✔
1725
        defer c.Unlock()
50✔
1726

50✔
1727
        // If a closing tx is provided, we'll generate a closure to write the
50✔
1728
        // transaction in the appropriate bucket under the given key.
50✔
1729
        var putClosingTx func(kvdb.RwBucket) error
50✔
1730
        if closeTx != nil {
75✔
1731
                var b bytes.Buffer
25✔
1732
                if err := WriteElement(&b, closeTx); err != nil {
25✔
1733
                        return err
×
1734
                }
×
1735

1736
                putClosingTx = func(chanBucket kvdb.RwBucket) error {
50✔
1737
                        return chanBucket.Put(key, b.Bytes())
25✔
1738
                }
25✔
1739
        }
1740

1741
        // Add the initiator status to the status provided. These statuses are
1742
        // set in addition to the broadcast status so that we do not need to
1743
        // migrate the original logic which does not store initiator.
1744
        if locallyInitiated {
94✔
1745
                status |= ChanStatusLocalCloseInitiator
44✔
1746
        } else {
54✔
1747
                status |= ChanStatusRemoteCloseInitiator
10✔
1748
        }
10✔
1749

1750
        return c.putChanStatus(status, putClosingTx)
50✔
1751
}
1752

1753
// BroadcastedCommitment retrieves the stored unilateral closing tx set during
1754
// MarkCommitmentBroadcasted. If not found ErrNoCloseTx is returned.
1755
func (c *OpenChannel) BroadcastedCommitment() (*wire.MsgTx, error) {
11✔
1756
        return c.getClosingTx(forceCloseTxKey)
11✔
1757
}
11✔
1758

1759
// BroadcastedCooperative retrieves the stored cooperative closing tx set during
1760
// MarkCoopBroadcasted. If not found ErrNoCloseTx is returned.
1761
func (c *OpenChannel) BroadcastedCooperative() (*wire.MsgTx, error) {
13✔
1762
        return c.getClosingTx(coopCloseTxKey)
13✔
1763
}
13✔
1764

1765
// getClosingTx is a helper method which returns the stored closing transaction
1766
// for key. The caller should use either the force or coop closing keys.
1767
func (c *OpenChannel) getClosingTx(key []byte) (*wire.MsgTx, error) {
20✔
1768
        var closeTx *wire.MsgTx
20✔
1769

20✔
1770
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
40✔
1771
                chanBucket, err := fetchChanBucket(
20✔
1772
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
20✔
1773
                )
20✔
1774
                switch err {
20✔
1775
                case nil:
20✔
1776
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
×
1777
                        return ErrNoCloseTx
×
1778
                default:
×
1779
                        return err
×
1780
                }
1781

1782
                bs := chanBucket.Get(key)
20✔
1783
                if bs == nil {
26✔
1784
                        return ErrNoCloseTx
6✔
1785
                }
6✔
1786
                r := bytes.NewReader(bs)
18✔
1787
                return ReadElement(r, &closeTx)
18✔
1788
        }, func() {
20✔
1789
                closeTx = nil
20✔
1790
        })
20✔
1791
        if err != nil {
26✔
1792
                return nil, err
6✔
1793
        }
6✔
1794

1795
        return closeTx, nil
18✔
1796
}
1797

1798
// putChanStatus appends the given status to the channel. fs is an optional
1799
// list of closures that are given the chanBucket in order to atomically add
1800
// extra information together with the new status.
1801
func (c *OpenChannel) putChanStatus(status ChannelStatus,
1802
        fs ...func(kvdb.RwBucket) error) error {
58✔
1803

58✔
1804
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
115✔
1805
                chanBucket, err := fetchChanBucketRw(
57✔
1806
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
57✔
1807
                )
57✔
1808
                if err != nil {
57✔
1809
                        return err
×
1810
                }
×
1811

1812
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
57✔
1813
                if err != nil {
57✔
1814
                        return err
×
1815
                }
×
1816

1817
                // Add this status to the existing bitvector found in the DB.
1818
                status = channel.chanStatus | status
57✔
1819
                channel.chanStatus = status
57✔
1820

57✔
1821
                if err := putOpenChannel(chanBucket, channel); err != nil {
57✔
1822
                        return err
×
1823
                }
×
1824

1825
                for _, f := range fs {
110✔
1826
                        // Skip execution of nil closures.
53✔
1827
                        if f == nil {
81✔
1828
                                continue
28✔
1829
                        }
1830

1831
                        if err := f(chanBucket); err != nil {
29✔
1832
                                return err
×
1833
                        }
×
1834
                }
1835

1836
                return nil
57✔
1837
        }, func() {}); err != nil {
59✔
1838
                return err
1✔
1839
        }
1✔
1840

1841
        // Update the in-memory representation to keep it in sync with the DB.
1842
        c.chanStatus = status
57✔
1843

57✔
1844
        return nil
57✔
1845
}
1846

1847
func (c *OpenChannel) clearChanStatus(status ChannelStatus) error {
4✔
1848
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
8✔
1849
                chanBucket, err := fetchChanBucketRw(
4✔
1850
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
4✔
1851
                )
4✔
1852
                if err != nil {
4✔
1853
                        return err
×
1854
                }
×
1855

1856
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
4✔
1857
                if err != nil {
4✔
1858
                        return err
×
1859
                }
×
1860

1861
                // Unset this bit in the bitvector on disk.
1862
                status = channel.chanStatus & ^status
4✔
1863
                channel.chanStatus = status
4✔
1864

4✔
1865
                return putOpenChannel(chanBucket, channel)
4✔
1866
        }, func() {}); err != nil {
4✔
1867
                return err
×
1868
        }
×
1869

1870
        // Update the in-memory representation to keep it in sync with the DB.
1871
        c.chanStatus = status
4✔
1872

4✔
1873
        return nil
4✔
1874
}
1875

1876
// putOpenChannel serializes, and stores the current state of the channel in its
1877
// entirety.
1878
func putOpenChannel(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
1,188✔
1879
        // First, we'll write out all the relatively static fields, that are
1,188✔
1880
        // decided upon initial channel creation.
1,188✔
1881
        if err := putChanInfo(chanBucket, channel); err != nil {
1,188✔
1882
                return fmt.Errorf("unable to store chan info: %w", err)
×
1883
        }
×
1884

1885
        // With the static channel info written out, we'll now write out the
1886
        // current commitment state for both parties.
1887
        if err := putChanCommitments(chanBucket, channel); err != nil {
1,188✔
1888
                return fmt.Errorf("unable to store chan commitments: %w", err)
×
1889
        }
×
1890

1891
        // Next, if this is a frozen channel, we'll add in the axillary
1892
        // information we need to store.
1893
        if channel.ChanType.IsFrozen() || channel.ChanType.HasLeaseExpiration() {
1,620✔
1894
                err := storeThawHeight(
432✔
1895
                        chanBucket, channel.ThawHeight,
432✔
1896
                )
432✔
1897
                if err != nil {
432✔
1898
                        return fmt.Errorf("unable to store thaw height: %w",
×
1899
                                err)
×
1900
                }
×
1901
        }
1902

1903
        // Finally, we'll write out the revocation state for both parties
1904
        // within a distinct key space.
1905
        if err := putChanRevocationState(chanBucket, channel); err != nil {
1,188✔
1906
                return fmt.Errorf("unable to store chan revocations: %w", err)
×
1907
        }
×
1908

1909
        return nil
1,188✔
1910
}
1911

1912
// fetchOpenChannel retrieves, and deserializes (including decrypting
1913
// sensitive) the complete channel currently active with the passed nodeID.
1914
func fetchOpenChannel(chanBucket kvdb.RBucket,
1915
        chanPoint *wire.OutPoint) (*OpenChannel, error) {
10,486✔
1916

10,486✔
1917
        channel := &OpenChannel{
10,486✔
1918
                FundingOutpoint: *chanPoint,
10,486✔
1919
        }
10,486✔
1920

10,486✔
1921
        // First, we'll read all the static information that changes less
10,486✔
1922
        // frequently from disk.
10,486✔
1923
        if err := fetchChanInfo(chanBucket, channel); err != nil {
10,486✔
1924
                return nil, fmt.Errorf("unable to fetch chan info: %w", err)
×
1925
        }
×
1926

1927
        // With the static information read, we'll now read the current
1928
        // commitment state for both sides of the channel.
1929
        if err := fetchChanCommitments(chanBucket, channel); err != nil {
10,486✔
1930
                return nil, fmt.Errorf("unable to fetch chan commitments: %w",
×
1931
                        err)
×
1932
        }
×
1933

1934
        // Next, if this is a frozen channel, we'll add in the axillary
1935
        // information we need to store.
1936
        if channel.ChanType.IsFrozen() || channel.ChanType.HasLeaseExpiration() {
10,824✔
1937
                thawHeight, err := fetchThawHeight(chanBucket)
338✔
1938
                if err != nil {
338✔
1939
                        return nil, fmt.Errorf("unable to store thaw "+
×
1940
                                "height: %v", err)
×
1941
                }
×
1942

1943
                channel.ThawHeight = thawHeight
338✔
1944
        }
1945

1946
        // Finally, we'll retrieve the current revocation state so we can
1947
        // properly
1948
        if err := fetchChanRevocationState(chanBucket, channel); err != nil {
10,486✔
1949
                return nil, fmt.Errorf("unable to fetch chan revocations: %w",
×
1950
                        err)
×
1951
        }
×
1952

1953
        channel.Packager = NewChannelPackager(channel.ShortChannelID)
10,486✔
1954

10,486✔
1955
        return channel, nil
10,486✔
1956
}
1957

1958
// SyncPending writes the contents of the channel to the database while it's in
1959
// the pending (waiting for funding confirmation) state. The IsPending flag
1960
// will be set to true. When the channel's funding transaction is confirmed,
1961
// the channel should be marked as "open" and the IsPending flag set to false.
1962
// Note that this function also creates a LinkNode relationship between this
1963
// newly created channel and a new LinkNode instance. This allows listing all
1964
// channels in the database globally, or according to the LinkNode they were
1965
// created with.
1966
//
1967
// TODO(roasbeef): addr param should eventually be an lnwire.NetAddress type
1968
// that includes service bits.
1969
func (c *OpenChannel) SyncPending(addr net.Addr, pendingHeight uint32) error {
846✔
1970
        c.Lock()
846✔
1971
        defer c.Unlock()
846✔
1972

846✔
1973
        c.FundingBroadcastHeight = pendingHeight
846✔
1974

846✔
1975
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
1,692✔
1976
                return syncNewChannel(tx, c, []net.Addr{addr})
846✔
1977
        }, func() {})
1,692✔
1978
}
1979

1980
// syncNewChannel will write the passed channel to disk, and also create a
1981
// LinkNode (if needed) for the channel peer.
1982
func syncNewChannel(tx kvdb.RwTx, c *OpenChannel, addrs []net.Addr) error {
847✔
1983
        // First, sync all the persistent channel state to disk.
847✔
1984
        if err := c.fullSync(tx); err != nil {
851✔
1985
                return err
4✔
1986
        }
4✔
1987

1988
        nodeInfoBucket, err := tx.CreateTopLevelBucket(nodeInfoBucket)
847✔
1989
        if err != nil {
847✔
1990
                return err
×
1991
        }
×
1992

1993
        // If a LinkNode for this identity public key already exists,
1994
        // then we can exit early.
1995
        nodePub := c.IdentityPub.SerializeCompressed()
847✔
1996
        if nodeInfoBucket.Get(nodePub) != nil {
994✔
1997
                return nil
147✔
1998
        }
147✔
1999

2000
        // Next, we need to establish a (possibly) new LinkNode relationship
2001
        // for this channel. The LinkNode metadata contains reachability,
2002
        // up-time, and service bits related information.
2003
        linkNode := NewLinkNode(
704✔
2004
                &LinkNodeDB{backend: c.Db.backend},
704✔
2005
                wire.MainNet, c.IdentityPub, addrs...,
704✔
2006
        )
704✔
2007

704✔
2008
        // TODO(roasbeef): do away with link node all together?
704✔
2009

704✔
2010
        return putLinkNode(nodeInfoBucket, linkNode)
704✔
2011
}
2012

2013
// UpdateCommitment updates the local commitment state. It locks in the pending
2014
// local updates that were received by us from the remote party. The commitment
2015
// state completely describes the balance state at this point in the commitment
2016
// chain. In addition to that, it persists all the remote log updates that we
2017
// have acked, but not signed a remote commitment for yet. These need to be
2018
// persisted to be able to produce a valid commit signature if a restart would
2019
// occur. This method its to be called when we revoke our prior commitment
2020
// state.
2021
//
2022
// A map is returned of all the htlc resolutions that were locked in this
2023
// commitment. Keys correspond to htlc indices and values indicate whether the
2024
// htlc was settled or failed.
2025
func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
2026
        unsignedAckedUpdates []LogUpdate) (map[uint64]bool, error) {
3,131✔
2027

3,131✔
2028
        c.Lock()
3,131✔
2029
        defer c.Unlock()
3,131✔
2030

3,131✔
2031
        // If this is a restored channel, then we want to avoid mutating the
3,131✔
2032
        // state as all, as it's impossible to do so in a protocol compliant
3,131✔
2033
        // manner.
3,131✔
2034
        if c.hasChanStatus(ChanStatusRestored) {
3,132✔
2035
                return nil, ErrNoRestoredChannelMutation
1✔
2036
        }
1✔
2037

2038
        var finalHtlcs = make(map[uint64]bool)
3,130✔
2039

3,130✔
2040
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6,260✔
2041
                chanBucket, err := fetchChanBucketRw(
3,130✔
2042
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3,130✔
2043
                )
3,130✔
2044
                if err != nil {
3,130✔
2045
                        return err
×
2046
                }
×
2047

2048
                // If the channel is marked as borked, then for safety reasons,
2049
                // we shouldn't attempt any further updates.
2050
                isBorked, err := c.isBorked(chanBucket)
3,130✔
2051
                if err != nil {
3,130✔
2052
                        return err
×
2053
                }
×
2054
                if isBorked {
3,131✔
2055
                        return ErrChanBorked
1✔
2056
                }
1✔
2057

2058
                if err = putChanInfo(chanBucket, c); err != nil {
3,129✔
2059
                        return fmt.Errorf("unable to store chan info: %w", err)
×
2060
                }
×
2061

2062
                // With the proper bucket fetched, we'll now write the latest
2063
                // commitment state to disk for the target party.
2064
                err = putChanCommitment(
3,129✔
2065
                        chanBucket, newCommitment, true,
3,129✔
2066
                )
3,129✔
2067
                if err != nil {
3,129✔
2068
                        return fmt.Errorf("unable to store chan "+
×
2069
                                "revocations: %v", err)
×
2070
                }
×
2071

2072
                // Persist unsigned but acked remote updates that need to be
2073
                // restored after a restart.
2074
                var b bytes.Buffer
3,129✔
2075
                err = serializeLogUpdates(&b, unsignedAckedUpdates)
3,129✔
2076
                if err != nil {
3,129✔
2077
                        return err
×
2078
                }
×
2079

2080
                err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes())
3,129✔
2081
                if err != nil {
3,129✔
2082
                        return fmt.Errorf("unable to store dangline remote "+
×
2083
                                "updates: %v", err)
×
2084
                }
×
2085

2086
                // Since we have just sent the counterparty a revocation, store true
2087
                // under lastWasRevokeKey.
2088
                var b2 bytes.Buffer
3,129✔
2089
                if err := WriteElements(&b2, true); err != nil {
3,129✔
2090
                        return err
×
2091
                }
×
2092

2093
                if err := chanBucket.Put(lastWasRevokeKey, b2.Bytes()); err != nil {
3,129✔
2094
                        return err
×
2095
                }
×
2096

2097
                // Persist the remote unsigned local updates that are not included
2098
                // in our new commitment.
2099
                updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
3,129✔
2100
                if updateBytes == nil {
3,612✔
2101
                        return nil
483✔
2102
                }
483✔
2103

2104
                r := bytes.NewReader(updateBytes)
2,650✔
2105
                updates, err := deserializeLogUpdates(r)
2,650✔
2106
                if err != nil {
2,650✔
2107
                        return err
×
2108
                }
×
2109

2110
                // Get the bucket where settled htlcs are recorded if the user
2111
                // opted in to storing this information.
2112
                var finalHtlcsBucket kvdb.RwBucket
2,650✔
2113
                if c.Db.parent.storeFinalHtlcResolutions {
2,655✔
2114
                        bucket, err := fetchFinalHtlcsBucketRw(
5✔
2115
                                tx, c.ShortChannelID,
5✔
2116
                        )
5✔
2117
                        if err != nil {
5✔
2118
                                return err
×
2119
                        }
×
2120

2121
                        finalHtlcsBucket = bucket
5✔
2122
                }
2123

2124
                var unsignedUpdates []LogUpdate
2,650✔
2125
                for _, upd := range updates {
3,498✔
2126
                        // Gather updates that are not on our local commitment.
848✔
2127
                        if upd.LogIndex >= newCommitment.LocalLogIndex {
848✔
2128
                                unsignedUpdates = append(unsignedUpdates, upd)
×
2129

×
2130
                                continue
×
2131
                        }
2132

2133
                        // The update was locked in. If the update was a
2134
                        // resolution, then store it in the database.
2135
                        err := processFinalHtlc(
848✔
2136
                                finalHtlcsBucket, upd, finalHtlcs,
848✔
2137
                        )
848✔
2138
                        if err != nil {
848✔
2139
                                return err
×
2140
                        }
×
2141
                }
2142

2143
                var b3 bytes.Buffer
2,650✔
2144
                err = serializeLogUpdates(&b3, unsignedUpdates)
2,650✔
2145
                if err != nil {
2,650✔
2146
                        return fmt.Errorf("unable to serialize log updates: %w",
×
2147
                                err)
×
2148
                }
×
2149

2150
                err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b3.Bytes())
2,650✔
2151
                if err != nil {
2,650✔
2152
                        return fmt.Errorf("unable to restore chanbucket: %w",
×
2153
                                err)
×
2154
                }
×
2155

2156
                return nil
2,650✔
2157
        }, func() {
3,130✔
2158
                finalHtlcs = make(map[uint64]bool)
3,130✔
2159
        })
3,130✔
2160
        if err != nil {
3,131✔
2161
                return nil, err
1✔
2162
        }
1✔
2163

2164
        c.LocalCommitment = *newCommitment
3,129✔
2165

3,129✔
2166
        return finalHtlcs, nil
3,129✔
2167
}
2168

2169
// processFinalHtlc stores a final htlc outcome in the database if signaled via
2170
// the supplied log update. An in-memory htlcs map is updated too.
2171
func processFinalHtlc(finalHtlcsBucket walletdb.ReadWriteBucket, upd LogUpdate,
2172
        finalHtlcs map[uint64]bool) error {
848✔
2173

848✔
2174
        var (
848✔
2175
                settled bool
848✔
2176
                id      uint64
848✔
2177
        )
848✔
2178

848✔
2179
        switch msg := upd.UpdateMsg.(type) {
848✔
2180
        case *lnwire.UpdateFulfillHTLC:
706✔
2181
                settled = true
706✔
2182
                id = msg.ID
706✔
2183

2184
        case *lnwire.UpdateFailHTLC:
135✔
2185
                settled = false
135✔
2186
                id = msg.ID
135✔
2187

2188
        case *lnwire.UpdateFailMalformedHTLC:
7✔
2189
                settled = false
7✔
2190
                id = msg.ID
7✔
2191

2192
        default:
8✔
2193
                return nil
8✔
2194
        }
2195

2196
        // Store the final resolution in the database if a bucket is provided.
2197
        if finalHtlcsBucket != nil {
845✔
2198
                err := putFinalHtlc(
5✔
2199
                        finalHtlcsBucket, id,
5✔
2200
                        FinalHtlcInfo{
5✔
2201
                                Settled:  settled,
5✔
2202
                                Offchain: true,
5✔
2203
                        },
5✔
2204
                )
5✔
2205
                if err != nil {
5✔
2206
                        return err
×
2207
                }
×
2208
        }
2209

2210
        finalHtlcs[id] = settled
840✔
2211

840✔
2212
        return nil
840✔
2213
}
2214

2215
// ActiveHtlcs returns a slice of HTLC's which are currently active on *both*
2216
// commitment transactions.
2217
func (c *OpenChannel) ActiveHtlcs() []HTLC {
3,419✔
2218
        c.RLock()
3,419✔
2219
        defer c.RUnlock()
3,419✔
2220

3,419✔
2221
        // We'll only return HTLC's that are locked into *both* commitment
3,419✔
2222
        // transactions. So we'll iterate through their set of HTLC's to note
3,419✔
2223
        // which ones are present on their commitment.
3,419✔
2224
        remoteHtlcs := make(map[[32]byte]struct{})
3,419✔
2225
        for _, htlc := range c.RemoteCommitment.Htlcs {
474,241✔
2226
                log.Tracef("RemoteCommitment has htlc: id=%v, update=%v "+
470,822✔
2227
                        "incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
470,822✔
2228
                        htlc.Incoming)
470,822✔
2229

470,822✔
2230
                onionHash := sha256.Sum256(htlc.OnionBlob[:])
470,822✔
2231
                remoteHtlcs[onionHash] = struct{}{}
470,822✔
2232
        }
470,822✔
2233

2234
        // Now that we know which HTLC's they have, we'll only mark the HTLC's
2235
        // as active if *we* know them as well.
2236
        activeHtlcs := make([]HTLC, 0, len(remoteHtlcs))
3,419✔
2237
        for _, htlc := range c.LocalCommitment.Htlcs {
474,508✔
2238
                log.Tracef("LocalCommitment has htlc: id=%v, update=%v "+
471,089✔
2239
                        "incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
471,089✔
2240
                        htlc.Incoming)
471,089✔
2241

471,089✔
2242
                onionHash := sha256.Sum256(htlc.OnionBlob[:])
471,089✔
2243
                if _, ok := remoteHtlcs[onionHash]; !ok {
471,380✔
2244
                        log.Tracef("Skipped htlc due to onion mismatched: "+
291✔
2245
                                "id=%v, update=%v incoming=%v",
291✔
2246
                                htlc.HtlcIndex, htlc.LogIndex, htlc.Incoming)
291✔
2247

291✔
2248
                        continue
291✔
2249
                }
2250

2251
                activeHtlcs = append(activeHtlcs, htlc)
470,802✔
2252
        }
2253

2254
        return activeHtlcs
3,419✔
2255
}
2256

2257
// HTLC is the on-disk representation of a hash time-locked contract. HTLCs are
2258
// contained within ChannelDeltas which encode the current state of the
2259
// commitment between state updates.
2260
//
2261
// TODO(roasbeef): save space by using smaller ints at tail end?
2262
type HTLC struct {
2263
        // TODO(yy): can embed an HTLCEntry here.
2264

2265
        // Signature is the signature for the second level covenant transaction
2266
        // for this HTLC. The second level transaction is a timeout tx in the
2267
        // case that this is an outgoing HTLC, and a success tx in the case
2268
        // that this is an incoming HTLC.
2269
        //
2270
        // TODO(roasbeef): make [64]byte instead?
2271
        Signature []byte
2272

2273
        // RHash is the payment hash of the HTLC.
2274
        RHash [32]byte
2275

2276
        // Amt is the amount of milli-satoshis this HTLC escrows.
2277
        Amt lnwire.MilliSatoshi
2278

2279
        // RefundTimeout is the absolute timeout on the HTLC that the sender
2280
        // must wait before reclaiming the funds in limbo.
2281
        RefundTimeout uint32
2282

2283
        // OutputIndex is the output index for this particular HTLC output
2284
        // within the commitment transaction.
2285
        OutputIndex int32
2286

2287
        // Incoming denotes whether we're the receiver or the sender of this
2288
        // HTLC.
2289
        Incoming bool
2290

2291
        // OnionBlob is an opaque blob which is used to complete multi-hop
2292
        // routing.
2293
        OnionBlob [lnwire.OnionPacketSize]byte
2294

2295
        // HtlcIndex is the HTLC counter index of this active, outstanding
2296
        // HTLC. This differs from the LogIndex, as the HtlcIndex is only
2297
        // incremented for each offered HTLC, while they LogIndex is
2298
        // incremented for each update (includes settle+fail).
2299
        HtlcIndex uint64
2300

2301
        // LogIndex is the cumulative log index of this HTLC. This differs
2302
        // from the HtlcIndex as this will be incremented for each new log
2303
        // update added.
2304
        LogIndex uint64
2305

2306
        // ExtraData contains any additional information that was transmitted
2307
        // with the HTLC via TLVs. This data *must* already be encoded as a
2308
        // TLV stream, and may be empty. The length of this data is naturally
2309
        // limited by the space available to TLVs in update_add_htlc:
2310
        // = 65535 bytes (bolt 8 maximum message size):
2311
        // - 2 bytes (bolt 1 message_type)
2312
        // - 32 bytes (channel_id)
2313
        // - 8 bytes (id)
2314
        // - 8 bytes (amount_msat)
2315
        // - 32 bytes (payment_hash)
2316
        // - 4 bytes (cltv_expiry)
2317
        // - 1366 bytes (onion_routing_packet)
2318
        // = 64083 bytes maximum possible TLV stream
2319
        //
2320
        // Note that this extra data is stored inline with the OnionBlob for
2321
        // legacy reasons, see serialization/deserialization functions for
2322
        // detail.
2323
        ExtraData lnwire.ExtraOpaqueData
2324

2325
        // BlindingPoint is an optional blinding point included with the HTLC.
2326
        //
2327
        // Note: this field is not a part of on-disk representation of the
2328
        // HTLC. It is stored in the ExtraData field, which is used to store
2329
        // a TLV stream of additional information associated with the HTLC.
2330
        BlindingPoint lnwire.BlindingPointRecord
2331
}
2332

2333
// serializeExtraData encodes a TLV stream of extra data to be stored with a
2334
// HTLC. It uses the update_add_htlc TLV types, because this is where extra
2335
// data is passed with a HTLC. At present blinding points are the only extra
2336
// data that we will store, and the function is a no-op if a nil blinding
2337
// point is provided.
2338
//
2339
// This function MUST be called to persist all HTLC values when they are
2340
// serialized.
2341
func (h *HTLC) serializeExtraData() error {
1,072,645✔
2342
        var records []tlv.RecordProducer
1,072,645✔
2343
        h.BlindingPoint.WhenSome(func(b tlv.RecordT[lnwire.BlindingPointTlvType,
1,072,645✔
2344
                *btcec.PublicKey]) {
1,072,652✔
2345

7✔
2346
                records = append(records, &b)
7✔
2347
        })
7✔
2348

2349
        return h.ExtraData.PackRecords(records...)
1,072,645✔
2350
}
2351

2352
// deserializeExtraData extracts TLVs from the extra data persisted for the
2353
// htlc and populates values in the struct accordingly.
2354
//
2355
// This function MUST be called to populate the struct properly when HTLCs
2356
// are deserialized.
2357
func (h *HTLC) deserializeExtraData() error {
2,494,744✔
2358
        if len(h.ExtraData) == 0 {
4,989,485✔
2359
                return nil
2,494,741✔
2360
        }
2,494,741✔
2361

2362
        blindingPoint := h.BlindingPoint.Zero()
7✔
2363
        tlvMap, err := h.ExtraData.ExtractRecords(&blindingPoint)
7✔
2364
        if err != nil {
7✔
2365
                return err
×
2366
        }
×
2367

2368
        if val, ok := tlvMap[h.BlindingPoint.TlvType()]; ok && val == nil {
14✔
2369
                h.BlindingPoint = tlv.SomeRecordT(blindingPoint)
7✔
2370
        }
7✔
2371

2372
        return nil
7✔
2373
}
2374

2375
// SerializeHtlcs writes out the passed set of HTLC's into the passed writer
2376
// using the current default on-disk serialization format.
2377
//
2378
// This inline serialization has been extended to allow storage of extra data
2379
// associated with a HTLC in the following way:
2380
//   - The known-length onion blob (1366 bytes) is serialized as var bytes in
2381
//     WriteElements (ie, the length 1366 was written, followed by the 1366
2382
//     onion bytes).
2383
//   - To include extra data, we append any extra data present to this one
2384
//     variable length of data. Since we know that the onion is strictly 1366
2385
//     bytes, any length after that should be considered to be extra data.
2386
//
2387
// NOTE: This API is NOT stable, the on-disk format will likely change in the
2388
// future.
2389
func SerializeHtlcs(b io.Writer, htlcs ...HTLC) error {
11,760✔
2390
        numHtlcs := uint16(len(htlcs))
11,760✔
2391
        if err := WriteElement(b, numHtlcs); err != nil {
11,760✔
2392
                return err
×
2393
        }
×
2394

2395
        for _, htlc := range htlcs {
1,084,405✔
2396
                // Populate TLV stream for any additional fields contained
1,072,645✔
2397
                // in the TLV.
1,072,645✔
2398
                if err := htlc.serializeExtraData(); err != nil {
1,072,645✔
2399
                        return err
×
2400
                }
×
2401

2402
                // The onion blob and hltc data are stored as a single var
2403
                // bytes blob.
2404
                onionAndExtraData := make(
1,072,645✔
2405
                        []byte, lnwire.OnionPacketSize+len(htlc.ExtraData),
1,072,645✔
2406
                )
1,072,645✔
2407
                copy(onionAndExtraData, htlc.OnionBlob[:])
1,072,645✔
2408
                copy(onionAndExtraData[lnwire.OnionPacketSize:], htlc.ExtraData)
1,072,645✔
2409

1,072,645✔
2410
                if err := WriteElements(b,
1,072,645✔
2411
                        htlc.Signature, htlc.RHash, htlc.Amt, htlc.RefundTimeout,
1,072,645✔
2412
                        htlc.OutputIndex, htlc.Incoming, onionAndExtraData,
1,072,645✔
2413
                        htlc.HtlcIndex, htlc.LogIndex,
1,072,645✔
2414
                ); err != nil {
1,072,645✔
2415
                        return err
×
2416
                }
×
2417
        }
2418

2419
        return nil
11,760✔
2420
}
2421

2422
// DeserializeHtlcs attempts to read out a slice of HTLC's from the passed
2423
// io.Reader. The bytes within the passed reader MUST have been previously
2424
// written to using the SerializeHtlcs function.
2425
//
2426
// This inline deserialization has been extended to allow storage of extra data
2427
// associated with a HTLC in the following way:
2428
//   - The known-length onion blob (1366 bytes) and any additional data present
2429
//     are read out as a single blob of variable byte data.
2430
//   - They are stored like this to take advantage of the variable space
2431
//     available for extension without migration (see SerializeHtlcs).
2432
//   - The first 1366 bytes are interpreted as the onion blob, and any remaining
2433
//     bytes as extra HTLC data.
2434
//   - This extra HTLC data is expected to be serialized as a TLV stream, and
2435
//     its parsing is left to higher layers.
2436
//
2437
// NOTE: This API is NOT stable, the on-disk format will likely change in the
2438
// future.
2439
func DeserializeHtlcs(r io.Reader) ([]HTLC, error) {
24,172✔
2440
        var numHtlcs uint16
24,172✔
2441
        if err := ReadElement(r, &numHtlcs); err != nil {
24,172✔
2442
                return nil, err
×
2443
        }
×
2444

2445
        var htlcs []HTLC
24,172✔
2446
        if numHtlcs == 0 {
31,220✔
2447
                return htlcs, nil
7,048✔
2448
        }
7,048✔
2449

2450
        htlcs = make([]HTLC, numHtlcs)
17,128✔
2451
        for i := uint16(0); i < numHtlcs; i++ {
2,511,873✔
2452
                var onionAndExtraData []byte
2,494,745✔
2453
                if err := ReadElements(r,
2,494,745✔
2454
                        &htlcs[i].Signature, &htlcs[i].RHash, &htlcs[i].Amt,
2,494,745✔
2455
                        &htlcs[i].RefundTimeout, &htlcs[i].OutputIndex,
2,494,745✔
2456
                        &htlcs[i].Incoming, &onionAndExtraData,
2,494,745✔
2457
                        &htlcs[i].HtlcIndex, &htlcs[i].LogIndex,
2,494,745✔
2458
                ); err != nil {
2,494,745✔
2459
                        return htlcs, err
×
2460
                }
×
2461

2462
                // Sanity check that we have at least the onion blob size we
2463
                // expect.
2464
                if len(onionAndExtraData) < lnwire.OnionPacketSize {
2,494,746✔
2465
                        return nil, ErrOnionBlobLength
1✔
2466
                }
1✔
2467

2468
                // First OnionPacketSize bytes are our fixed length onion
2469
                // packet.
2470
                copy(
2,494,744✔
2471
                        htlcs[i].OnionBlob[:],
2,494,744✔
2472
                        onionAndExtraData[0:lnwire.OnionPacketSize],
2,494,744✔
2473
                )
2,494,744✔
2474

2,494,744✔
2475
                // Any additional bytes belong to extra data. ExtraDataLen
2,494,744✔
2476
                // will be >= 0, because we know that we always have a fixed
2,494,744✔
2477
                // length onion packet.
2,494,744✔
2478
                extraDataLen := len(onionAndExtraData) - lnwire.OnionPacketSize
2,494,744✔
2479
                if extraDataLen > 0 {
2,494,751✔
2480
                        htlcs[i].ExtraData = make([]byte, extraDataLen)
7✔
2481

7✔
2482
                        copy(
7✔
2483
                                htlcs[i].ExtraData,
7✔
2484
                                onionAndExtraData[lnwire.OnionPacketSize:],
7✔
2485
                        )
7✔
2486
                }
7✔
2487

2488
                // Finally, deserialize any TLVs contained in that extra data
2489
                // if they are present.
2490
                if err := htlcs[i].deserializeExtraData(); err != nil {
2,494,744✔
2491
                        return nil, err
×
2492
                }
×
2493
        }
2494

2495
        return htlcs, nil
17,127✔
2496
}
2497

2498
// Copy returns a full copy of the target HTLC.
2499
func (h *HTLC) Copy() HTLC {
4,623✔
2500
        clone := HTLC{
4,623✔
2501
                Incoming:      h.Incoming,
4,623✔
2502
                Amt:           h.Amt,
4,623✔
2503
                RefundTimeout: h.RefundTimeout,
4,623✔
2504
                OutputIndex:   h.OutputIndex,
4,623✔
2505
        }
4,623✔
2506
        copy(clone.Signature[:], h.Signature)
4,623✔
2507
        copy(clone.RHash[:], h.RHash[:])
4,623✔
2508
        copy(clone.ExtraData, h.ExtraData)
4,623✔
2509

4,623✔
2510
        return clone
4,623✔
2511
}
4,623✔
2512

2513
// LogUpdate represents a pending update to the remote commitment chain. The
2514
// log update may be an add, fail, or settle entry. We maintain this data in
2515
// order to be able to properly retransmit our proposed state if necessary.
2516
type LogUpdate struct {
2517
        // LogIndex is the log index of this proposed commitment update entry.
2518
        LogIndex uint64
2519

2520
        // UpdateMsg is the update message that was included within our
2521
        // local update log. The LogIndex value denotes the log index of this
2522
        // update which will be used when restoring our local update log if
2523
        // we're left with a dangling update on restart.
2524
        UpdateMsg lnwire.Message
2525
}
2526

2527
// serializeLogUpdate writes a log update to the provided io.Writer.
2528
func serializeLogUpdate(w io.Writer, l *LogUpdate) error {
2,684✔
2529
        return WriteElements(w, l.LogIndex, l.UpdateMsg)
2,684✔
2530
}
2,684✔
2531

2532
// deserializeLogUpdate reads a log update from the provided io.Reader.
2533
func deserializeLogUpdate(r io.Reader) (*LogUpdate, error) {
3,320✔
2534
        l := &LogUpdate{}
3,320✔
2535
        if err := ReadElements(r, &l.LogIndex, &l.UpdateMsg); err != nil {
3,320✔
2536
                return nil, err
×
2537
        }
×
2538

2539
        return l, nil
3,320✔
2540
}
2541

2542
// CommitDiff represents the delta needed to apply the state transition between
2543
// two subsequent commitment states. Given state N and state N+1, one is able
2544
// to apply the set of messages contained within the CommitDiff to N to arrive
2545
// at state N+1. Each time a new commitment is extended, we'll write a new
2546
// commitment (along with the full commitment state) to disk so we can
2547
// re-transmit the state in the case of a connection loss or message drop.
2548
type CommitDiff struct {
2549
        // ChannelCommitment is the full commitment state that one would arrive
2550
        // at by applying the set of messages contained in the UpdateDiff to
2551
        // the prior accepted commitment.
2552
        Commitment ChannelCommitment
2553

2554
        // LogUpdates is the set of messages sent prior to the commitment state
2555
        // transition in question. Upon reconnection, if we detect that they
2556
        // don't have the commitment, then we re-send this along with the
2557
        // proper signature.
2558
        LogUpdates []LogUpdate
2559

2560
        // CommitSig is the exact CommitSig message that should be sent after
2561
        // the set of LogUpdates above has been retransmitted. The signatures
2562
        // within this message should properly cover the new commitment state
2563
        // and also the HTLC's within the new commitment state.
2564
        CommitSig *lnwire.CommitSig
2565

2566
        // OpenedCircuitKeys is a set of unique identifiers for any downstream
2567
        // Add packets included in this commitment txn. After a restart, this
2568
        // set of htlcs is acked from the link's incoming mailbox to ensure
2569
        // there isn't an attempt to re-add them to this commitment txn.
2570
        OpenedCircuitKeys []models.CircuitKey
2571

2572
        // ClosedCircuitKeys records the unique identifiers for any settle/fail
2573
        // packets that were resolved by this commitment txn. After a restart,
2574
        // this is used to ensure those circuits are removed from the circuit
2575
        // map, and the downstream packets in the link's mailbox are removed.
2576
        ClosedCircuitKeys []models.CircuitKey
2577

2578
        // AddAcks specifies the locations (commit height, pkg index) of any
2579
        // Adds that were failed/settled in this commit diff. This will ack
2580
        // entries in *this* channel's forwarding packages.
2581
        //
2582
        // NOTE: This value is not serialized, it is used to atomically mark the
2583
        // resolution of adds, such that they will not be reprocessed after a
2584
        // restart.
2585
        AddAcks []AddRef
2586

2587
        // SettleFailAcks specifies the locations (chan id, commit height, pkg
2588
        // index) of any Settles or Fails that were locked into this commit
2589
        // diff, and originate from *another* channel, i.e. the outgoing link.
2590
        //
2591
        // NOTE: This value is not serialized, it is used to atomically acks
2592
        // settles and fails from the forwarding packages of other channels,
2593
        // such that they will not be reforwarded internally after a restart.
2594
        SettleFailAcks []SettleFailRef
2595
}
2596

2597
// serializeLogUpdates serializes provided list of updates to a stream.
2598
func serializeLogUpdates(w io.Writer, logUpdates []LogUpdate) error {
14,705✔
2599
        numUpdates := uint16(len(logUpdates))
14,705✔
2600
        if err := binary.Write(w, byteOrder, numUpdates); err != nil {
14,705✔
2601
                return err
×
2602
        }
×
2603

2604
        for _, diff := range logUpdates {
23,695✔
2605
                err := WriteElements(w, diff.LogIndex, diff.UpdateMsg)
8,990✔
2606
                if err != nil {
8,990✔
2607
                        return err
×
2608
                }
×
2609
        }
2610

2611
        return nil
14,705✔
2612
}
2613

2614
// deserializeLogUpdates deserializes a list of updates from a stream.
2615
func deserializeLogUpdates(r io.Reader) ([]LogUpdate, error) {
8,780✔
2616
        var numUpdates uint16
8,780✔
2617
        if err := binary.Read(r, byteOrder, &numUpdates); err != nil {
8,780✔
2618
                return nil, err
×
2619
        }
×
2620

2621
        logUpdates := make([]LogUpdate, numUpdates)
8,780✔
2622
        for i := 0; i < int(numUpdates); i++ {
16,459✔
2623
                err := ReadElements(r,
7,679✔
2624
                        &logUpdates[i].LogIndex, &logUpdates[i].UpdateMsg,
7,679✔
2625
                )
7,679✔
2626
                if err != nil {
7,679✔
2627
                        return nil, err
×
2628
                }
×
2629
        }
2630
        return logUpdates, nil
8,780✔
2631
}
2632

2633
func serializeCommitDiff(w io.Writer, diff *CommitDiff) error { // nolint: dupl
3,168✔
2634
        if err := serializeChanCommit(w, &diff.Commitment); err != nil {
3,168✔
2635
                return err
×
2636
        }
×
2637

2638
        if err := WriteElements(w, diff.CommitSig); err != nil {
3,168✔
2639
                return err
×
2640
        }
×
2641

2642
        if err := serializeLogUpdates(w, diff.LogUpdates); err != nil {
3,168✔
2643
                return err
×
2644
        }
×
2645

2646
        numOpenRefs := uint16(len(diff.OpenedCircuitKeys))
3,168✔
2647
        if err := binary.Write(w, byteOrder, numOpenRefs); err != nil {
3,168✔
2648
                return err
×
2649
        }
×
2650

2651
        for _, openRef := range diff.OpenedCircuitKeys {
4,680✔
2652
                err := WriteElements(w, openRef.ChanID, openRef.HtlcID)
1,512✔
2653
                if err != nil {
1,512✔
2654
                        return err
×
2655
                }
×
2656
        }
2657

2658
        numClosedRefs := uint16(len(diff.ClosedCircuitKeys))
3,168✔
2659
        if err := binary.Write(w, byteOrder, numClosedRefs); err != nil {
3,168✔
2660
                return err
×
2661
        }
×
2662

2663
        for _, closedRef := range diff.ClosedCircuitKeys {
3,211✔
2664
                err := WriteElements(w, closedRef.ChanID, closedRef.HtlcID)
43✔
2665
                if err != nil {
43✔
2666
                        return err
×
2667
                }
×
2668
        }
2669

2670
        return nil
3,168✔
2671
}
2672

2673
func deserializeCommitDiff(r io.Reader) (*CommitDiff, error) {
3,151✔
2674
        var (
3,151✔
2675
                d   CommitDiff
3,151✔
2676
                err error
3,151✔
2677
        )
3,151✔
2678

3,151✔
2679
        d.Commitment, err = deserializeChanCommit(r)
3,151✔
2680
        if err != nil {
3,151✔
2681
                return nil, err
×
2682
        }
×
2683

2684
        var msg lnwire.Message
3,151✔
2685
        if err := ReadElements(r, &msg); err != nil {
3,151✔
2686
                return nil, err
×
2687
        }
×
2688
        commitSig, ok := msg.(*lnwire.CommitSig)
3,151✔
2689
        if !ok {
3,151✔
2690
                return nil, fmt.Errorf("expected lnwire.CommitSig, instead "+
×
2691
                        "read: %T", msg)
×
2692
        }
×
2693
        d.CommitSig = commitSig
3,151✔
2694

3,151✔
2695
        d.LogUpdates, err = deserializeLogUpdates(r)
3,151✔
2696
        if err != nil {
3,151✔
2697
                return nil, err
×
2698
        }
×
2699

2700
        var numOpenRefs uint16
3,151✔
2701
        if err := binary.Read(r, byteOrder, &numOpenRefs); err != nil {
3,151✔
2702
                return nil, err
×
2703
        }
×
2704

2705
        d.OpenedCircuitKeys = make([]models.CircuitKey, numOpenRefs)
3,151✔
2706
        for i := 0; i < int(numOpenRefs); i++ {
4,690✔
2707
                err := ReadElements(r,
1,539✔
2708
                        &d.OpenedCircuitKeys[i].ChanID,
1,539✔
2709
                        &d.OpenedCircuitKeys[i].HtlcID)
1,539✔
2710
                if err != nil {
1,539✔
2711
                        return nil, err
×
2712
                }
×
2713
        }
2714

2715
        var numClosedRefs uint16
3,151✔
2716
        if err := binary.Read(r, byteOrder, &numClosedRefs); err != nil {
3,151✔
2717
                return nil, err
×
2718
        }
×
2719

2720
        d.ClosedCircuitKeys = make([]models.CircuitKey, numClosedRefs)
3,151✔
2721
        for i := 0; i < int(numClosedRefs); i++ {
3,194✔
2722
                err := ReadElements(r,
43✔
2723
                        &d.ClosedCircuitKeys[i].ChanID,
43✔
2724
                        &d.ClosedCircuitKeys[i].HtlcID)
43✔
2725
                if err != nil {
43✔
2726
                        return nil, err
×
2727
                }
×
2728
        }
2729

2730
        return &d, nil
3,151✔
2731
}
2732

2733
// AppendRemoteCommitChain appends a new CommitDiff to the end of the
2734
// commitment chain for the remote party. This method is to be used once we
2735
// have prepared a new commitment state for the remote party, but before we
2736
// transmit it to the remote party. The contents of the argument should be
2737
// sufficient to retransmit the updates and signature needed to reconstruct the
2738
// state in full, in the case that we need to retransmit.
2739
func (c *OpenChannel) AppendRemoteCommitChain(diff *CommitDiff) error {
3,170✔
2740
        c.Lock()
3,170✔
2741
        defer c.Unlock()
3,170✔
2742

3,170✔
2743
        // If this is a restored channel, then we want to avoid mutating the
3,170✔
2744
        // state at all, as it's impossible to do so in a protocol compliant
3,170✔
2745
        // manner.
3,170✔
2746
        if c.hasChanStatus(ChanStatusRestored) {
3,171✔
2747
                return ErrNoRestoredChannelMutation
1✔
2748
        }
1✔
2749

2750
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6,338✔
2751
                // First, we'll grab the writable bucket where this channel's
3,169✔
2752
                // data resides.
3,169✔
2753
                chanBucket, err := fetchChanBucketRw(
3,169✔
2754
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3,169✔
2755
                )
3,169✔
2756
                if err != nil {
3,169✔
2757
                        return err
×
2758
                }
×
2759

2760
                // If the channel is marked as borked, then for safety reasons,
2761
                // we shouldn't attempt any further updates.
2762
                isBorked, err := c.isBorked(chanBucket)
3,169✔
2763
                if err != nil {
3,169✔
2764
                        return err
×
2765
                }
×
2766
                if isBorked {
3,170✔
2767
                        return ErrChanBorked
1✔
2768
                }
1✔
2769

2770
                // Any outgoing settles and fails necessarily have a
2771
                // corresponding adds in this channel's forwarding packages.
2772
                // Mark all of these as being fully processed in our forwarding
2773
                // package, which prevents us from reprocessing them after
2774
                // startup.
2775
                err = c.Packager.AckAddHtlcs(tx, diff.AddAcks...)
3,168✔
2776
                if err != nil {
3,168✔
2777
                        return err
×
2778
                }
×
2779

2780
                // Additionally, we ack from any fails or settles that are
2781
                // persisted in another channel's forwarding package. This
2782
                // prevents the same fails and settles from being retransmitted
2783
                // after restarts. The actual fail or settle we need to
2784
                // propagate to the remote party is now in the commit diff.
2785
                err = c.Packager.AckSettleFails(tx, diff.SettleFailAcks...)
3,168✔
2786
                if err != nil {
3,168✔
2787
                        return err
×
2788
                }
×
2789

2790
                // We are sending a commitment signature so lastWasRevokeKey should
2791
                // store false.
2792
                var b bytes.Buffer
3,168✔
2793
                if err := WriteElements(&b, false); err != nil {
3,168✔
2794
                        return err
×
2795
                }
×
2796
                if err := chanBucket.Put(lastWasRevokeKey, b.Bytes()); err != nil {
3,168✔
2797
                        return err
×
2798
                }
×
2799

2800
                // TODO(roasbeef): use seqno to derive key for later LCP
2801

2802
                // With the bucket retrieved, we'll now serialize the commit
2803
                // diff itself, and write it to disk.
2804
                var b2 bytes.Buffer
3,168✔
2805
                if err := serializeCommitDiff(&b2, diff); err != nil {
3,168✔
2806
                        return err
×
2807
                }
×
2808
                return chanBucket.Put(commitDiffKey, b2.Bytes())
3,168✔
2809
        }, func() {})
3,169✔
2810
}
2811

2812
// RemoteCommitChainTip returns the "tip" of the current remote commitment
2813
// chain. This value will be non-nil iff, we've created a new commitment for
2814
// the remote party that they haven't yet ACK'd. In this case, their commitment
2815
// chain will have a length of two: their current unrevoked commitment, and
2816
// this new pending commitment. Once they revoked their prior state, we'll swap
2817
// these pointers, causing the tip and the tail to point to the same entry.
2818
func (c *OpenChannel) RemoteCommitChainTip() (*CommitDiff, error) {
1,185✔
2819
        var cd *CommitDiff
1,185✔
2820
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2,370✔
2821
                chanBucket, err := fetchChanBucket(
1,185✔
2822
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1,185✔
2823
                )
1,185✔
2824
                switch err {
1,185✔
2825
                case nil:
845✔
2826
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
343✔
2827
                        return ErrNoPendingCommit
343✔
2828
                default:
×
2829
                        return err
×
2830
                }
2831

2832
                tipBytes := chanBucket.Get(commitDiffKey)
845✔
2833
                if tipBytes == nil {
1,623✔
2834
                        return ErrNoPendingCommit
778✔
2835
                }
778✔
2836

2837
                tipReader := bytes.NewReader(tipBytes)
71✔
2838
                dcd, err := deserializeCommitDiff(tipReader)
71✔
2839
                if err != nil {
71✔
2840
                        return err
×
2841
                }
×
2842

2843
                cd = dcd
71✔
2844
                return nil
71✔
2845
        }, func() {
1,185✔
2846
                cd = nil
1,185✔
2847
        })
1,185✔
2848
        if err != nil {
2,303✔
2849
                return nil, err
1,118✔
2850
        }
1,118✔
2851

2852
        return cd, err
71✔
2853
}
2854

2855
// UnsignedAckedUpdates retrieves the persisted unsigned acked remote log
2856
// updates that still need to be signed for.
2857
func (c *OpenChannel) UnsignedAckedUpdates() ([]LogUpdate, error) {
765✔
2858
        var updates []LogUpdate
765✔
2859
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
1,530✔
2860
                chanBucket, err := fetchChanBucket(
765✔
2861
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
765✔
2862
                )
765✔
2863
                switch err {
765✔
2864
                case nil:
425✔
2865
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
342✔
2866
                        return nil
342✔
2867
                default:
×
2868
                        return err
×
2869
                }
2870

2871
                updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
425✔
2872
                if updateBytes == nil {
786✔
2873
                        return nil
361✔
2874
                }
361✔
2875

2876
                r := bytes.NewReader(updateBytes)
68✔
2877
                updates, err = deserializeLogUpdates(r)
68✔
2878
                return err
68✔
2879
        }, func() {
765✔
2880
                updates = nil
765✔
2881
        })
765✔
2882
        if err != nil {
765✔
2883
                return nil, err
×
2884
        }
×
2885

2886
        return updates, nil
765✔
2887
}
2888

2889
// RemoteUnsignedLocalUpdates retrieves the persisted, unsigned local log
2890
// updates that the remote still needs to sign for.
2891
func (c *OpenChannel) RemoteUnsignedLocalUpdates() ([]LogUpdate, error) {
764✔
2892
        var updates []LogUpdate
764✔
2893
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
1,528✔
2894
                chanBucket, err := fetchChanBucket(
764✔
2895
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
764✔
2896
                )
764✔
2897
                switch err {
764✔
2898
                case nil:
424✔
2899
                        break
424✔
2900
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
342✔
2901
                        return nil
342✔
2902
                default:
×
2903
                        return err
×
2904
                }
2905

2906
                updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
424✔
2907
                if updateBytes == nil {
812✔
2908
                        return nil
388✔
2909
                }
388✔
2910

2911
                r := bytes.NewReader(updateBytes)
40✔
2912
                updates, err = deserializeLogUpdates(r)
40✔
2913
                return err
40✔
2914
        }, func() {
764✔
2915
                updates = nil
764✔
2916
        })
764✔
2917
        if err != nil {
764✔
2918
                return nil, err
×
2919
        }
×
2920

2921
        return updates, nil
764✔
2922
}
2923

2924
// InsertNextRevocation inserts the _next_ commitment point (revocation) into
2925
// the database, and also modifies the internal RemoteNextRevocation attribute
2926
// to point to the passed key. This method is to be using during final channel
2927
// set up, _after_ the channel has been fully confirmed.
2928
//
2929
// NOTE: If this method isn't called, then the target channel won't be able to
2930
// propose new states for the commitment state of the remote party.
2931
func (c *OpenChannel) InsertNextRevocation(revKey *btcec.PublicKey) error {
594✔
2932
        c.Lock()
594✔
2933
        defer c.Unlock()
594✔
2934

594✔
2935
        c.RemoteNextRevocation = revKey
594✔
2936

594✔
2937
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
1,188✔
2938
                chanBucket, err := fetchChanBucketRw(
594✔
2939
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
594✔
2940
                )
594✔
2941
                if err != nil {
594✔
2942
                        return err
×
2943
                }
×
2944

2945
                return putChanRevocationState(chanBucket, c)
594✔
2946
        }, func() {})
594✔
2947
        if err != nil {
594✔
2948
                return err
×
2949
        }
×
2950

2951
        return nil
594✔
2952
}
2953

2954
// AdvanceCommitChainTail records the new state transition within an on-disk
2955
// append-only log which records all state transitions by the remote peer. In
2956
// the case of an uncooperative broadcast of a prior state by the remote peer,
2957
// this log can be consulted in order to reconstruct the state needed to
2958
// rectify the situation. This method will add the current commitment for the
2959
// remote party to the revocation log, and promote the current pending
2960
// commitment to the current remote commitment. The updates parameter is the
2961
// set of local updates that the peer still needs to send us a signature for.
2962
// We store this set of updates in case we go down.
2963
func (c *OpenChannel) AdvanceCommitChainTail(fwdPkg *FwdPkg,
2964
        updates []LogUpdate, ourOutputIndex, theirOutputIndex uint32) error {
3,086✔
2965

3,086✔
2966
        c.Lock()
3,086✔
2967
        defer c.Unlock()
3,086✔
2968

3,086✔
2969
        // If this is a restored channel, then we want to avoid mutating the
3,086✔
2970
        // state at all, as it's impossible to do so in a protocol compliant
3,086✔
2971
        // manner.
3,086✔
2972
        if c.hasChanStatus(ChanStatusRestored) {
3,087✔
2973
                return ErrNoRestoredChannelMutation
1✔
2974
        }
1✔
2975

2976
        var newRemoteCommit *ChannelCommitment
3,085✔
2977

3,085✔
2978
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6,170✔
2979
                chanBucket, err := fetchChanBucketRw(
3,085✔
2980
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3,085✔
2981
                )
3,085✔
2982
                if err != nil {
3,085✔
2983
                        return err
×
2984
                }
×
2985

2986
                // If the channel is marked as borked, then for safety reasons,
2987
                // we shouldn't attempt any further updates.
2988
                isBorked, err := c.isBorked(chanBucket)
3,085✔
2989
                if err != nil {
3,085✔
2990
                        return err
×
2991
                }
×
2992
                if isBorked {
3,086✔
2993
                        return ErrChanBorked
1✔
2994
                }
1✔
2995

2996
                // Persist the latest preimage state to disk as the remote peer
2997
                // has just added to our local preimage store, and given us a
2998
                // new pending revocation key.
2999
                if err := putChanRevocationState(chanBucket, c); err != nil {
3,084✔
3000
                        return err
×
3001
                }
×
3002

3003
                // With the current preimage producer/store state updated,
3004
                // append a new log entry recording this the delta of this
3005
                // state transition.
3006
                //
3007
                // TODO(roasbeef): could make the deltas relative, would save
3008
                // space, but then tradeoff for more disk-seeks to recover the
3009
                // full state.
3010
                logKey := revocationLogBucket
3,084✔
3011
                logBucket, err := chanBucket.CreateBucketIfNotExists(logKey)
3,084✔
3012
                if err != nil {
3,084✔
3013
                        return err
×
3014
                }
×
3015

3016
                // Before we append this revoked state to the revocation log,
3017
                // we'll swap out what's currently the tail of the commit tip,
3018
                // with the current locked-in commitment for the remote party.
3019
                tipBytes := chanBucket.Get(commitDiffKey)
3,084✔
3020
                tipReader := bytes.NewReader(tipBytes)
3,084✔
3021
                newCommit, err := deserializeCommitDiff(tipReader)
3,084✔
3022
                if err != nil {
3,084✔
3023
                        return err
×
3024
                }
×
3025
                err = putChanCommitment(
3,084✔
3026
                        chanBucket, &newCommit.Commitment, false,
3,084✔
3027
                )
3,084✔
3028
                if err != nil {
3,084✔
3029
                        return err
×
3030
                }
×
3031
                if err := chanBucket.Delete(commitDiffKey); err != nil {
3,084✔
3032
                        return err
×
3033
                }
×
3034

3035
                // With the commitment pointer swapped, we can now add the
3036
                // revoked (prior) state to the revocation log.
3037
                err = putRevocationLog(
3,084✔
3038
                        logBucket, &c.RemoteCommitment, ourOutputIndex,
3,084✔
3039
                        theirOutputIndex, c.Db.parent.noRevLogAmtData,
3,084✔
3040
                )
3,084✔
3041
                if err != nil {
3,084✔
3042
                        return err
×
3043
                }
×
3044

3045
                // Lastly, we write the forwarding package to disk so that we
3046
                // can properly recover from failures and reforward HTLCs that
3047
                // have not received a corresponding settle/fail.
3048
                if err := c.Packager.AddFwdPkg(tx, fwdPkg); err != nil {
3,084✔
3049
                        return err
×
3050
                }
×
3051

3052
                // Persist the unsigned acked updates that are not included
3053
                // in their new commitment.
3054
                updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
3,084✔
3055
                if updateBytes == nil {
3,285✔
3056
                        // This shouldn't normally happen as we always store
201✔
3057
                        // the number of updates, but could still be
201✔
3058
                        // encountered by nodes that are upgrading.
201✔
3059
                        newRemoteCommit = &newCommit.Commitment
201✔
3060
                        return nil
201✔
3061
                }
201✔
3062

3063
                r := bytes.NewReader(updateBytes)
2,887✔
3064
                unsignedUpdates, err := deserializeLogUpdates(r)
2,887✔
3065
                if err != nil {
2,887✔
3066
                        return err
×
3067
                }
×
3068

3069
                var validUpdates []LogUpdate
2,887✔
3070
                for _, upd := range unsignedUpdates {
6,778✔
3071
                        lIdx := upd.LogIndex
3,891✔
3072

3,891✔
3073
                        // Filter for updates that are not on the remote
3,891✔
3074
                        // commitment.
3,891✔
3075
                        if lIdx >= newCommit.Commitment.RemoteLogIndex {
5,092✔
3076
                                validUpdates = append(validUpdates, upd)
1,201✔
3077
                        }
1,201✔
3078
                }
3079

3080
                var b bytes.Buffer
2,887✔
3081
                err = serializeLogUpdates(&b, validUpdates)
2,887✔
3082
                if err != nil {
2,887✔
3083
                        return fmt.Errorf("unable to serialize log updates: %w",
×
3084
                                err)
×
3085
                }
×
3086

3087
                err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes())
2,887✔
3088
                if err != nil {
2,887✔
3089
                        return fmt.Errorf("unable to store under "+
×
3090
                                "unsignedAckedUpdatesKey: %w", err)
×
3091
                }
×
3092

3093
                // Persist the local updates the peer hasn't yet signed so they
3094
                // can be restored after restart.
3095
                var b2 bytes.Buffer
2,887✔
3096
                err = serializeLogUpdates(&b2, updates)
2,887✔
3097
                if err != nil {
2,887✔
3098
                        return err
×
3099
                }
×
3100

3101
                err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b2.Bytes())
2,887✔
3102
                if err != nil {
2,887✔
3103
                        return fmt.Errorf("unable to restore remote unsigned "+
×
3104
                                "local updates: %v", err)
×
3105
                }
×
3106

3107
                newRemoteCommit = &newCommit.Commitment
2,887✔
3108

2,887✔
3109
                return nil
2,887✔
3110
        }, func() {
3,085✔
3111
                newRemoteCommit = nil
3,085✔
3112
        })
3,085✔
3113
        if err != nil {
3,086✔
3114
                return err
1✔
3115
        }
1✔
3116

3117
        // With the db transaction complete, we'll swap over the in-memory
3118
        // pointer of the new remote commitment, which was previously the tip
3119
        // of the commit chain.
3120
        c.RemoteCommitment = *newRemoteCommit
3,084✔
3121

3,084✔
3122
        return nil
3,084✔
3123
}
3124

3125
// FinalHtlcInfo contains information about the final outcome of an htlc.
3126
type FinalHtlcInfo struct {
3127
        // Settled is true is the htlc was settled. If false, the htlc was
3128
        // failed.
3129
        Settled bool
3130

3131
        // Offchain indicates whether the htlc was resolved off-chain or
3132
        // on-chain.
3133
        Offchain bool
3134
}
3135

3136
// putFinalHtlc writes the final htlc outcome to the database. Additionally it
3137
// records whether the htlc was resolved off-chain or on-chain.
3138
func putFinalHtlc(finalHtlcsBucket kvdb.RwBucket, id uint64,
3139
        info FinalHtlcInfo) error {
7✔
3140

7✔
3141
        var key [8]byte
7✔
3142
        byteOrder.PutUint64(key[:], id)
7✔
3143

7✔
3144
        var finalHtlcByte FinalHtlcByte
7✔
3145
        if info.Settled {
14✔
3146
                finalHtlcByte |= FinalHtlcSettledBit
7✔
3147
        }
7✔
3148
        if info.Offchain {
13✔
3149
                finalHtlcByte |= FinalHtlcOffchainBit
6✔
3150
        }
6✔
3151

3152
        return finalHtlcsBucket.Put(key[:], []byte{byte(finalHtlcByte)})
7✔
3153
}
3154

3155
// NextLocalHtlcIndex returns the next unallocated local htlc index. To ensure
3156
// this always returns the next index that has been not been allocated, this
3157
// will first try to examine any pending commitments, before falling back to the
3158
// last locked-in remote commitment.
3159
func (c *OpenChannel) NextLocalHtlcIndex() (uint64, error) {
379✔
3160
        // First, load the most recent commit diff that we initiated for the
379✔
3161
        // remote party. If no pending commit is found, this is not treated as
379✔
3162
        // a critical error, since we can always fall back.
379✔
3163
        pendingRemoteCommit, err := c.RemoteCommitChainTip()
379✔
3164
        if err != nil && err != ErrNoPendingCommit {
379✔
3165
                return 0, err
×
3166
        }
×
3167

3168
        // If a pending commit was found, its local htlc index will be at least
3169
        // as large as the one on our local commitment.
3170
        if pendingRemoteCommit != nil {
395✔
3171
                return pendingRemoteCommit.Commitment.LocalHtlcIndex, nil
16✔
3172
        }
16✔
3173

3174
        // Otherwise, fallback to using the local htlc index of their commitment.
3175
        return c.RemoteCommitment.LocalHtlcIndex, nil
363✔
3176
}
3177

3178
// LoadFwdPkgs scans the forwarding log for any packages that haven't been
3179
// processed, and returns their deserialized log updates in map indexed by the
3180
// remote commitment height at which the updates were locked in.
3181
func (c *OpenChannel) LoadFwdPkgs() ([]*FwdPkg, error) {
507✔
3182
        c.RLock()
507✔
3183
        defer c.RUnlock()
507✔
3184

507✔
3185
        var fwdPkgs []*FwdPkg
507✔
3186
        if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
951✔
3187
                var err error
444✔
3188
                fwdPkgs, err = c.Packager.LoadFwdPkgs(tx)
444✔
3189
                return err
444✔
3190
        }, func() {
951✔
3191
                fwdPkgs = nil
507✔
3192
        }); err != nil {
570✔
3193
                return nil, err
63✔
3194
        }
63✔
3195

3196
        return fwdPkgs, nil
444✔
3197
}
3198

3199
// AckAddHtlcs updates the AckAddFilter containing any of the provided AddRefs
3200
// indicating that a response to this Add has been committed to the remote party.
3201
// Doing so will prevent these Add HTLCs from being reforwarded internally.
3202
func (c *OpenChannel) AckAddHtlcs(addRefs ...AddRef) error {
1✔
3203
        c.Lock()
1✔
3204
        defer c.Unlock()
1✔
3205

1✔
3206
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
2✔
3207
                return c.Packager.AckAddHtlcs(tx, addRefs...)
1✔
3208
        }, func() {})
2✔
3209
}
3210

3211
// AckSettleFails updates the SettleFailFilter containing any of the provided
3212
// SettleFailRefs, indicating that the response has been delivered to the
3213
// incoming link, corresponding to a particular AddRef. Doing so will prevent
3214
// the responses from being retransmitted internally.
3215
func (c *OpenChannel) AckSettleFails(settleFailRefs ...SettleFailRef) error {
×
3216
        c.Lock()
×
3217
        defer c.Unlock()
×
3218

×
3219
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
3220
                return c.Packager.AckSettleFails(tx, settleFailRefs...)
×
3221
        }, func() {})
×
3222
}
3223

3224
// SetFwdFilter atomically sets the forwarding filter for the forwarding package
3225
// identified by `height`.
3226
func (c *OpenChannel) SetFwdFilter(height uint64, fwdFilter *PkgFilter) error {
2,358✔
3227
        c.Lock()
2,358✔
3228
        defer c.Unlock()
2,358✔
3229

2,358✔
3230
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
4,716✔
3231
                return c.Packager.SetFwdFilter(tx, height, fwdFilter)
2,358✔
3232
        }, func() {})
4,716✔
3233
}
3234

3235
// RemoveFwdPkgs atomically removes forwarding packages specified by the remote
3236
// commitment heights. If one of the intermediate RemovePkg calls fails, then the
3237
// later packages won't be removed.
3238
//
3239
// NOTE: This method should only be called on packages marked FwdStateCompleted.
3240
func (c *OpenChannel) RemoveFwdPkgs(heights ...uint64) error {
17✔
3241
        c.Lock()
17✔
3242
        defer c.Unlock()
17✔
3243

17✔
3244
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
34✔
3245
                for _, height := range heights {
913✔
3246
                        err := c.Packager.RemovePkg(tx, height)
896✔
3247
                        if err != nil {
896✔
3248
                                return err
×
3249
                        }
×
3250
                }
3251

3252
                return nil
17✔
3253
        }, func() {})
17✔
3254
}
3255

3256
// revocationLogTailCommitHeight returns the commit height at the end of the
3257
// revocation log. This entry represents the last previous state for the remote
3258
// node's commitment chain. The ChannelDelta returned by this method will
3259
// always lag one state behind the most current (unrevoked) state of the remote
3260
// node's commitment chain.
3261
// NOTE: used in unit test only.
3262
func (c *OpenChannel) revocationLogTailCommitHeight() (uint64, error) {
2✔
3263
        c.RLock()
2✔
3264
        defer c.RUnlock()
2✔
3265

2✔
3266
        var height uint64
2✔
3267

2✔
3268
        // If we haven't created any state updates yet, then we'll exit early as
2✔
3269
        // there's nothing to be found on disk in the revocation bucket.
2✔
3270
        if c.RemoteCommitment.CommitHeight == 0 {
2✔
3271
                return height, nil
×
3272
        }
×
3273

3274
        if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
4✔
3275
                chanBucket, err := fetchChanBucket(
2✔
3276
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
2✔
3277
                )
2✔
3278
                if err != nil {
2✔
3279
                        return err
×
3280
                }
×
3281

3282
                logBucket, err := fetchLogBucket(chanBucket)
2✔
3283
                if err != nil {
2✔
3284
                        return err
×
3285
                }
×
3286

3287
                // Once we have the bucket that stores the revocation log from
3288
                // this channel, we'll jump to the _last_ key in bucket. Since
3289
                // the key is the commit height, we'll decode the bytes and
3290
                // return it.
3291
                cursor := logBucket.ReadCursor()
2✔
3292
                rawHeight, _ := cursor.Last()
2✔
3293
                height = byteOrder.Uint64(rawHeight)
2✔
3294

2✔
3295
                return nil
2✔
3296
        }, func() {}); err != nil {
2✔
3297
                return height, err
×
3298
        }
×
3299

3300
        return height, nil
2✔
3301
}
3302

3303
// CommitmentHeight returns the current commitment height. The commitment
3304
// height represents the number of updates to the commitment state to date.
3305
// This value is always monotonically increasing. This method is provided in
3306
// order to allow multiple instances of a particular open channel to obtain a
3307
// consistent view of the number of channel updates to date.
3308
func (c *OpenChannel) CommitmentHeight() (uint64, error) {
1✔
3309
        c.RLock()
1✔
3310
        defer c.RUnlock()
1✔
3311

1✔
3312
        var height uint64
1✔
3313
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
2✔
3314
                // Get the bucket dedicated to storing the metadata for open
1✔
3315
                // channels.
1✔
3316
                chanBucket, err := fetchChanBucket(
1✔
3317
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
1✔
3318
                )
1✔
3319
                if err != nil {
1✔
3320
                        return err
×
3321
                }
×
3322

3323
                commit, err := fetchChanCommitment(chanBucket, true)
1✔
3324
                if err != nil {
1✔
3325
                        return err
×
3326
                }
×
3327

3328
                height = commit.CommitHeight
1✔
3329
                return nil
1✔
3330
        }, func() {
1✔
3331
                height = 0
1✔
3332
        })
1✔
3333
        if err != nil {
1✔
3334
                return 0, err
×
3335
        }
×
3336

3337
        return height, nil
1✔
3338
}
3339

3340
// FindPreviousState scans through the append-only log in an attempt to recover
3341
// the previous channel state indicated by the update number. This method is
3342
// intended to be used for obtaining the relevant data needed to claim all
3343
// funds rightfully spendable in the case of an on-chain broadcast of the
3344
// commitment transaction.
3345
func (c *OpenChannel) FindPreviousState(
3346
        updateNum uint64) (*RevocationLog, *ChannelCommitment, error) {
35✔
3347

35✔
3348
        c.RLock()
35✔
3349
        defer c.RUnlock()
35✔
3350

35✔
3351
        commit := &ChannelCommitment{}
35✔
3352
        rl := &RevocationLog{}
35✔
3353

35✔
3354
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
70✔
3355
                chanBucket, err := fetchChanBucket(
35✔
3356
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
35✔
3357
                )
35✔
3358
                if err != nil {
36✔
3359
                        return err
1✔
3360
                }
1✔
3361

3362
                // Find the revocation log from both the new and the old
3363
                // bucket.
3364
                r, c, err := fetchRevocationLogCompatible(chanBucket, updateNum)
34✔
3365
                if err != nil {
57✔
3366
                        return err
23✔
3367
                }
23✔
3368

3369
                rl = r
15✔
3370
                commit = c
15✔
3371
                return nil
15✔
3372
        }, func() {})
35✔
3373
        if err != nil {
59✔
3374
                return nil, nil, err
24✔
3375
        }
24✔
3376

3377
        // Either the `rl` or the `commit` is nil here. We return them as-is
3378
        // and leave it to the caller to decide its following action.
3379
        return rl, commit, nil
15✔
3380
}
3381

3382
// ClosureType is an enum like structure that details exactly _how_ a channel
3383
// was closed. Three closure types are currently possible: none, cooperative,
3384
// local force close, remote force close, and (remote) breach.
3385
type ClosureType uint8
3386

3387
const (
3388
        // CooperativeClose indicates that a channel has been closed
3389
        // cooperatively.  This means that both channel peers were online and
3390
        // signed a new transaction paying out the settled balance of the
3391
        // contract.
3392
        CooperativeClose ClosureType = 0
3393

3394
        // LocalForceClose indicates that we have unilaterally broadcast our
3395
        // current commitment state on-chain.
3396
        LocalForceClose ClosureType = 1
3397

3398
        // RemoteForceClose indicates that the remote peer has unilaterally
3399
        // broadcast their current commitment state on-chain.
3400
        RemoteForceClose ClosureType = 4
3401

3402
        // BreachClose indicates that the remote peer attempted to broadcast a
3403
        // prior _revoked_ channel state.
3404
        BreachClose ClosureType = 2
3405

3406
        // FundingCanceled indicates that the channel never was fully opened
3407
        // before it was marked as closed in the database. This can happen if
3408
        // we or the remote fail at some point during the opening workflow, or
3409
        // we timeout waiting for the funding transaction to be confirmed.
3410
        FundingCanceled ClosureType = 3
3411

3412
        // Abandoned indicates that the channel state was removed without
3413
        // any further actions. This is intended to clean up unusable
3414
        // channels during development.
3415
        Abandoned ClosureType = 5
3416
)
3417

3418
// ChannelCloseSummary contains the final state of a channel at the point it
3419
// was closed. Once a channel is closed, all the information pertaining to that
3420
// channel within the openChannelBucket is deleted, and a compact summary is
3421
// put in place instead.
3422
type ChannelCloseSummary struct {
3423
        // ChanPoint is the outpoint for this channel's funding transaction,
3424
        // and is used as a unique identifier for the channel.
3425
        ChanPoint wire.OutPoint
3426

3427
        // ShortChanID encodes the exact location in the chain in which the
3428
        // channel was initially confirmed. This includes: the block height,
3429
        // transaction index, and the output within the target transaction.
3430
        ShortChanID lnwire.ShortChannelID
3431

3432
        // ChainHash is the hash of the genesis block that this channel resides
3433
        // within.
3434
        ChainHash chainhash.Hash
3435

3436
        // ClosingTXID is the txid of the transaction which ultimately closed
3437
        // this channel.
3438
        ClosingTXID chainhash.Hash
3439

3440
        // RemotePub is the public key of the remote peer that we formerly had
3441
        // a channel with.
3442
        RemotePub *btcec.PublicKey
3443

3444
        // Capacity was the total capacity of the channel.
3445
        Capacity btcutil.Amount
3446

3447
        // CloseHeight is the height at which the funding transaction was
3448
        // spent.
3449
        CloseHeight uint32
3450

3451
        // SettledBalance is our total balance settled balance at the time of
3452
        // channel closure. This _does not_ include the sum of any outputs that
3453
        // have been time-locked as a result of the unilateral channel closure.
3454
        SettledBalance btcutil.Amount
3455

3456
        // TimeLockedBalance is the sum of all the time-locked outputs at the
3457
        // time of channel closure. If we triggered the force closure of this
3458
        // channel, then this value will be non-zero if our settled output is
3459
        // above the dust limit. If we were on the receiving side of a channel
3460
        // force closure, then this value will be non-zero if we had any
3461
        // outstanding outgoing HTLC's at the time of channel closure.
3462
        TimeLockedBalance btcutil.Amount
3463

3464
        // CloseType details exactly _how_ the channel was closed. Five closure
3465
        // types are possible: cooperative, local force, remote force, breach
3466
        // and funding canceled.
3467
        CloseType ClosureType
3468

3469
        // IsPending indicates whether this channel is in the 'pending close'
3470
        // state, which means the channel closing transaction has been
3471
        // confirmed, but not yet been fully resolved. In the case of a channel
3472
        // that has been cooperatively closed, it will go straight into the
3473
        // fully resolved state as soon as the closing transaction has been
3474
        // confirmed. However, for channels that have been force closed, they'll
3475
        // stay marked as "pending" until _all_ the pending funds have been
3476
        // swept.
3477
        IsPending bool
3478

3479
        // RemoteCurrentRevocation is the current revocation for their
3480
        // commitment transaction. However, since this is the derived public key,
3481
        // we don't yet have the private key so we aren't yet able to verify
3482
        // that it's actually in the hash chain.
3483
        RemoteCurrentRevocation *btcec.PublicKey
3484

3485
        // RemoteNextRevocation is the revocation key to be used for the *next*
3486
        // commitment transaction we create for the local node. Within the
3487
        // specification, this value is referred to as the
3488
        // per-commitment-point.
3489
        RemoteNextRevocation *btcec.PublicKey
3490

3491
        // LocalChanCfg is the channel configuration for the local node.
3492
        LocalChanConfig ChannelConfig
3493

3494
        // LastChanSyncMsg is the ChannelReestablish message for this channel
3495
        // for the state at the point where it was closed.
3496
        LastChanSyncMsg *lnwire.ChannelReestablish
3497
}
3498

3499
// CloseChannel closes a previously active Lightning channel. Closing a channel
3500
// entails deleting all saved state within the database concerning this
3501
// channel. This method also takes a struct that summarizes the state of the
3502
// channel at closing, this compact representation will be the only component
3503
// of a channel left over after a full closing. It takes an optional set of
3504
// channel statuses which will be written to the historical channel bucket.
3505
// These statuses are used to record close initiators.
3506
func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary,
3507
        statuses ...ChannelStatus) error {
118✔
3508

118✔
3509
        c.Lock()
118✔
3510
        defer c.Unlock()
118✔
3511

118✔
3512
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
236✔
3513
                openChanBucket := tx.ReadWriteBucket(openChannelBucket)
118✔
3514
                if openChanBucket == nil {
118✔
3515
                        return ErrNoChanDBExists
×
3516
                }
×
3517

3518
                nodePub := c.IdentityPub.SerializeCompressed()
118✔
3519
                nodeChanBucket := openChanBucket.NestedReadWriteBucket(nodePub)
118✔
3520
                if nodeChanBucket == nil {
118✔
3521
                        return ErrNoActiveChannels
×
3522
                }
×
3523

3524
                chainBucket := nodeChanBucket.NestedReadWriteBucket(c.ChainHash[:])
118✔
3525
                if chainBucket == nil {
118✔
3526
                        return ErrNoActiveChannels
×
3527
                }
×
3528

3529
                var chanPointBuf bytes.Buffer
118✔
3530
                err := writeOutpoint(&chanPointBuf, &c.FundingOutpoint)
118✔
3531
                if err != nil {
118✔
3532
                        return err
×
3533
                }
×
3534
                chanKey := chanPointBuf.Bytes()
118✔
3535
                chanBucket := chainBucket.NestedReadWriteBucket(
118✔
3536
                        chanKey,
118✔
3537
                )
118✔
3538
                if chanBucket == nil {
118✔
3539
                        return ErrNoActiveChannels
×
3540
                }
×
3541

3542
                // Before we delete the channel state, we'll read out the full
3543
                // details, as we'll also store portions of this information
3544
                // for record keeping.
3545
                chanState, err := fetchOpenChannel(
118✔
3546
                        chanBucket, &c.FundingOutpoint,
118✔
3547
                )
118✔
3548
                if err != nil {
118✔
3549
                        return err
×
3550
                }
×
3551

3552
                // Delete all the forwarding packages stored for this particular
3553
                // channel.
3554
                if err = chanState.Packager.Wipe(tx); err != nil {
118✔
3555
                        return err
×
3556
                }
×
3557

3558
                // Now that the index to this channel has been deleted, purge
3559
                // the remaining channel metadata from the database.
3560
                err = deleteOpenChannel(chanBucket)
118✔
3561
                if err != nil {
118✔
3562
                        return err
×
3563
                }
×
3564

3565
                // We'll also remove the channel from the frozen channel bucket
3566
                // if we need to.
3567
                if c.ChanType.IsFrozen() || c.ChanType.HasLeaseExpiration() {
229✔
3568
                        err := deleteThawHeight(chanBucket)
111✔
3569
                        if err != nil {
111✔
3570
                                return err
×
3571
                        }
×
3572
                }
3573

3574
                // With the base channel data deleted, attempt to delete the
3575
                // information stored within the revocation log.
3576
                if err := deleteLogBucket(chanBucket); err != nil {
118✔
3577
                        return err
×
3578
                }
×
3579

3580
                err = chainBucket.DeleteNestedBucket(chanPointBuf.Bytes())
118✔
3581
                if err != nil {
118✔
3582
                        return err
×
3583
                }
×
3584

3585
                // Fetch the outpoint bucket to see if the outpoint exists or
3586
                // not.
3587
                opBucket := tx.ReadWriteBucket(outpointBucket)
118✔
3588
                if opBucket == nil {
118✔
3589
                        return ErrNoChanDBExists
×
3590
                }
×
3591

3592
                // Add the closed outpoint to our outpoint index. This should
3593
                // replace an open outpoint in the index.
3594
                if opBucket.Get(chanPointBuf.Bytes()) == nil {
118✔
3595
                        return ErrMissingIndexEntry
×
3596
                }
×
3597

3598
                status := uint8(outpointClosed)
118✔
3599

118✔
3600
                // Write the IndexStatus of this outpoint as the first entry in a tlv
118✔
3601
                // stream.
118✔
3602
                statusRecord := tlv.MakePrimitiveRecord(indexStatusType, &status)
118✔
3603
                opStream, err := tlv.NewStream(statusRecord)
118✔
3604
                if err != nil {
118✔
3605
                        return err
×
3606
                }
×
3607

3608
                var b bytes.Buffer
118✔
3609
                if err := opStream.Encode(&b); err != nil {
118✔
3610
                        return err
×
3611
                }
×
3612

3613
                // Finally add the closed outpoint and tlv stream to the index.
3614
                if err := opBucket.Put(chanPointBuf.Bytes(), b.Bytes()); err != nil {
118✔
3615
                        return err
×
3616
                }
×
3617

3618
                // Add channel state to the historical channel bucket.
3619
                historicalBucket, err := tx.CreateTopLevelBucket(
118✔
3620
                        historicalChannelBucket,
118✔
3621
                )
118✔
3622
                if err != nil {
118✔
3623
                        return err
×
3624
                }
×
3625

3626
                historicalChanBucket, err :=
118✔
3627
                        historicalBucket.CreateBucketIfNotExists(chanKey)
118✔
3628
                if err != nil {
118✔
3629
                        return err
×
3630
                }
×
3631

3632
                // Apply any additional statuses to the channel state.
3633
                for _, status := range statuses {
127✔
3634
                        chanState.chanStatus |= status
9✔
3635
                }
9✔
3636

3637
                err = putOpenChannel(historicalChanBucket, chanState)
118✔
3638
                if err != nil {
118✔
3639
                        return err
×
3640
                }
×
3641

3642
                // Finally, create a summary of this channel in the closed
3643
                // channel bucket for this node.
3644
                return putChannelCloseSummary(
118✔
3645
                        tx, chanPointBuf.Bytes(), summary, chanState,
118✔
3646
                )
118✔
3647
        }, func() {})
118✔
3648
}
3649

3650
// ChannelSnapshot is a frozen snapshot of the current channel state. A
3651
// snapshot is detached from the original channel that generated it, providing
3652
// read-only access to the current or prior state of an active channel.
3653
//
3654
// TODO(roasbeef): remove all together? pretty much just commitment
3655
type ChannelSnapshot struct {
3656
        // RemoteIdentity is the identity public key of the remote node that we
3657
        // are maintaining the open channel with.
3658
        RemoteIdentity btcec.PublicKey
3659

3660
        // ChanPoint is the outpoint that created the channel. This output is
3661
        // found within the funding transaction and uniquely identified the
3662
        // channel on the resident chain.
3663
        ChannelPoint wire.OutPoint
3664

3665
        // ChainHash is the genesis hash of the chain that the channel resides
3666
        // within.
3667
        ChainHash chainhash.Hash
3668

3669
        // Capacity is the total capacity of the channel.
3670
        Capacity btcutil.Amount
3671

3672
        // TotalMSatSent is the total number of milli-satoshis we've sent
3673
        // within this channel.
3674
        TotalMSatSent lnwire.MilliSatoshi
3675

3676
        // TotalMSatReceived is the total number of milli-satoshis we've
3677
        // received within this channel.
3678
        TotalMSatReceived lnwire.MilliSatoshi
3679

3680
        // ChannelCommitment is the current up-to-date commitment for the
3681
        // target channel.
3682
        ChannelCommitment
3683
}
3684

3685
// Snapshot returns a read-only snapshot of the current channel state. This
3686
// snapshot includes information concerning the current settled balance within
3687
// the channel, metadata detailing total flows, and any outstanding HTLCs.
3688
func (c *OpenChannel) Snapshot() *ChannelSnapshot {
90✔
3689
        c.RLock()
90✔
3690
        defer c.RUnlock()
90✔
3691

90✔
3692
        localCommit := c.LocalCommitment
90✔
3693
        snapshot := &ChannelSnapshot{
90✔
3694
                RemoteIdentity:    *c.IdentityPub,
90✔
3695
                ChannelPoint:      c.FundingOutpoint,
90✔
3696
                Capacity:          c.Capacity,
90✔
3697
                TotalMSatSent:     c.TotalMSatSent,
90✔
3698
                TotalMSatReceived: c.TotalMSatReceived,
90✔
3699
                ChainHash:         c.ChainHash,
90✔
3700
                ChannelCommitment: ChannelCommitment{
90✔
3701
                        LocalBalance:  localCommit.LocalBalance,
90✔
3702
                        RemoteBalance: localCommit.RemoteBalance,
90✔
3703
                        CommitHeight:  localCommit.CommitHeight,
90✔
3704
                        CommitFee:     localCommit.CommitFee,
90✔
3705
                },
90✔
3706
        }
90✔
3707

90✔
3708
        // Copy over the current set of HTLCs to ensure the caller can't mutate
90✔
3709
        // our internal state.
90✔
3710
        snapshot.Htlcs = make([]HTLC, len(localCommit.Htlcs))
90✔
3711
        for i, h := range localCommit.Htlcs {
4,713✔
3712
                snapshot.Htlcs[i] = h.Copy()
4,623✔
3713
        }
4,623✔
3714

3715
        return snapshot
90✔
3716
}
3717

3718
// LatestCommitments returns the two latest commitments for both the local and
3719
// remote party. These commitments are read from disk to ensure that only the
3720
// latest fully committed state is returned. The first commitment returned is
3721
// the local commitment, and the second returned is the remote commitment.
3722
func (c *OpenChannel) LatestCommitments() (*ChannelCommitment, *ChannelCommitment, error) {
19✔
3723
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
38✔
3724
                chanBucket, err := fetchChanBucket(
19✔
3725
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
19✔
3726
                )
19✔
3727
                if err != nil {
19✔
3728
                        return err
×
3729
                }
×
3730

3731
                return fetchChanCommitments(chanBucket, c)
19✔
3732
        }, func() {})
19✔
3733
        if err != nil {
19✔
3734
                return nil, nil, err
×
3735
        }
×
3736

3737
        return &c.LocalCommitment, &c.RemoteCommitment, nil
19✔
3738
}
3739

3740
// RemoteRevocationStore returns the most up to date commitment version of the
3741
// revocation storage tree for the remote party. This method can be used when
3742
// acting on a possible contract breach to ensure, that the caller has the most
3743
// up to date information required to deliver justice.
3744
func (c *OpenChannel) RemoteRevocationStore() (shachain.Store, error) {
19✔
3745
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
38✔
3746
                chanBucket, err := fetchChanBucket(
19✔
3747
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
19✔
3748
                )
19✔
3749
                if err != nil {
19✔
3750
                        return err
×
3751
                }
×
3752

3753
                return fetchChanRevocationState(chanBucket, c)
19✔
3754
        }, func() {})
19✔
3755
        if err != nil {
19✔
3756
                return nil, err
×
3757
        }
×
3758

3759
        return c.RevocationStore, nil
19✔
3760
}
3761

3762
// AbsoluteThawHeight determines a frozen channel's absolute thaw height. If the
3763
// channel is not frozen, then 0 is returned.
3764
func (c *OpenChannel) AbsoluteThawHeight() (uint32, error) {
4✔
3765
        // Only frozen channels have a thaw height.
4✔
3766
        if !c.ChanType.IsFrozen() && !c.ChanType.HasLeaseExpiration() {
8✔
3767
                return 0, nil
4✔
3768
        }
4✔
3769

3770
        // If the channel has the frozen bit set and it's thaw height is below
3771
        // the absolute threshold, then it's interpreted as a relative height to
3772
        // the chain's current height.
3773
        if c.ChanType.IsFrozen() && c.ThawHeight < AbsoluteThawHeightThreshold {
8✔
3774
                // We'll only known of the channel's short ID once it's
4✔
3775
                // confirmed.
4✔
3776
                if c.IsPending {
4✔
3777
                        return 0, errors.New("cannot use relative thaw " +
×
3778
                                "height for unconfirmed channel")
×
3779
                }
×
3780

3781
                // For non-zero-conf channels, this is the base height to use.
3782
                blockHeightBase := c.ShortChannelID.BlockHeight
4✔
3783

4✔
3784
                // If this is a zero-conf channel, the ShortChannelID will be
4✔
3785
                // an alias.
4✔
3786
                if c.IsZeroConf() {
4✔
3787
                        if !c.ZeroConfConfirmed() {
×
3788
                                return 0, errors.New("cannot use relative " +
×
3789
                                        "height for unconfirmed zero-conf " +
×
3790
                                        "channel")
×
3791
                        }
×
3792

3793
                        // Use the confirmed SCID's BlockHeight.
3794
                        blockHeightBase = c.confirmedScid.BlockHeight
×
3795
                }
3796

3797
                return blockHeightBase + c.ThawHeight, nil
4✔
3798
        }
3799

3800
        return c.ThawHeight, nil
4✔
3801
}
3802

3803
func putChannelCloseSummary(tx kvdb.RwTx, chanID []byte,
3804
        summary *ChannelCloseSummary, lastChanState *OpenChannel) error {
118✔
3805

118✔
3806
        closedChanBucket, err := tx.CreateTopLevelBucket(closedChannelBucket)
118✔
3807
        if err != nil {
118✔
3808
                return err
×
3809
        }
×
3810

3811
        summary.RemoteCurrentRevocation = lastChanState.RemoteCurrentRevocation
118✔
3812
        summary.RemoteNextRevocation = lastChanState.RemoteNextRevocation
118✔
3813
        summary.LocalChanConfig = lastChanState.LocalChanCfg
118✔
3814

118✔
3815
        var b bytes.Buffer
118✔
3816
        if err := serializeChannelCloseSummary(&b, summary); err != nil {
118✔
3817
                return err
×
3818
        }
×
3819

3820
        return closedChanBucket.Put(chanID, b.Bytes())
118✔
3821
}
3822

3823
func serializeChannelCloseSummary(w io.Writer, cs *ChannelCloseSummary) error {
125✔
3824
        err := WriteElements(w,
125✔
3825
                cs.ChanPoint, cs.ShortChanID, cs.ChainHash, cs.ClosingTXID,
125✔
3826
                cs.CloseHeight, cs.RemotePub, cs.Capacity, cs.SettledBalance,
125✔
3827
                cs.TimeLockedBalance, cs.CloseType, cs.IsPending,
125✔
3828
        )
125✔
3829
        if err != nil {
125✔
3830
                return err
×
3831
        }
×
3832

3833
        // If this is a close channel summary created before the addition of
3834
        // the new fields, then we can exit here.
3835
        if cs.RemoteCurrentRevocation == nil {
125✔
3836
                return WriteElements(w, false)
×
3837
        }
×
3838

3839
        // If fields are present, write boolean to indicate this, and continue.
3840
        if err := WriteElements(w, true); err != nil {
125✔
3841
                return err
×
3842
        }
×
3843

3844
        if err := WriteElements(w, cs.RemoteCurrentRevocation); err != nil {
125✔
3845
                return err
×
3846
        }
×
3847

3848
        if err := writeChanConfig(w, &cs.LocalChanConfig); err != nil {
125✔
3849
                return err
×
3850
        }
×
3851

3852
        // The RemoteNextRevocation field is optional, as it's possible for a
3853
        // channel to be closed before we learn of the next unrevoked
3854
        // revocation point for the remote party. Write a boolean indicating
3855
        // whether this field is present or not.
3856
        if err := WriteElements(w, cs.RemoteNextRevocation != nil); err != nil {
125✔
3857
                return err
×
3858
        }
×
3859

3860
        // Write the field, if present.
3861
        if cs.RemoteNextRevocation != nil {
248✔
3862
                if err = WriteElements(w, cs.RemoteNextRevocation); err != nil {
123✔
3863
                        return err
×
3864
                }
×
3865
        }
3866

3867
        // Write whether the channel sync message is present.
3868
        if err := WriteElements(w, cs.LastChanSyncMsg != nil); err != nil {
125✔
3869
                return err
×
3870
        }
×
3871

3872
        // Write the channel sync message, if present.
3873
        if cs.LastChanSyncMsg != nil {
129✔
3874
                if err := WriteElements(w, cs.LastChanSyncMsg); err != nil {
4✔
3875
                        return err
×
3876
                }
×
3877
        }
3878

3879
        return nil
125✔
3880
}
3881

3882
func deserializeCloseChannelSummary(r io.Reader) (*ChannelCloseSummary, error) {
134✔
3883
        c := &ChannelCloseSummary{}
134✔
3884

134✔
3885
        err := ReadElements(r,
134✔
3886
                &c.ChanPoint, &c.ShortChanID, &c.ChainHash, &c.ClosingTXID,
134✔
3887
                &c.CloseHeight, &c.RemotePub, &c.Capacity, &c.SettledBalance,
134✔
3888
                &c.TimeLockedBalance, &c.CloseType, &c.IsPending,
134✔
3889
        )
134✔
3890
        if err != nil {
134✔
3891
                return nil, err
×
3892
        }
×
3893

3894
        // We'll now check to see if the channel close summary was encoded with
3895
        // any of the additional optional fields.
3896
        var hasNewFields bool
134✔
3897
        err = ReadElements(r, &hasNewFields)
134✔
3898
        if err != nil {
134✔
3899
                return nil, err
×
3900
        }
×
3901

3902
        // If fields are not present, we can return.
3903
        if !hasNewFields {
142✔
3904
                return c, nil
8✔
3905
        }
8✔
3906

3907
        // Otherwise read the new fields.
3908
        if err := ReadElements(r, &c.RemoteCurrentRevocation); err != nil {
126✔
3909
                return nil, err
×
3910
        }
×
3911

3912
        if err := readChanConfig(r, &c.LocalChanConfig); err != nil {
126✔
3913
                return nil, err
×
3914
        }
×
3915

3916
        // Finally, we'll attempt to read the next unrevoked commitment point
3917
        // for the remote party. If we closed the channel before receiving a
3918
        // channel_ready message then this might not be present. A boolean
3919
        // indicating whether the field is present will come first.
3920
        var hasRemoteNextRevocation bool
126✔
3921
        err = ReadElements(r, &hasRemoteNextRevocation)
126✔
3922
        if err != nil {
126✔
3923
                return nil, err
×
3924
        }
×
3925

3926
        // If this field was written, read it.
3927
        if hasRemoteNextRevocation {
252✔
3928
                err = ReadElements(r, &c.RemoteNextRevocation)
126✔
3929
                if err != nil {
126✔
3930
                        return nil, err
×
3931
                }
×
3932
        }
3933

3934
        // Check if we have a channel sync message to read.
3935
        var hasChanSyncMsg bool
126✔
3936
        err = ReadElements(r, &hasChanSyncMsg)
126✔
3937
        if err == io.EOF {
126✔
3938
                return c, nil
×
3939
        } else if err != nil {
126✔
3940
                return nil, err
×
3941
        }
×
3942

3943
        // If a chan sync message is present, read it.
3944
        if hasChanSyncMsg {
130✔
3945
                // We must pass in reference to a lnwire.Message for the codec
4✔
3946
                // to support it.
4✔
3947
                var msg lnwire.Message
4✔
3948
                if err := ReadElements(r, &msg); err != nil {
4✔
3949
                        return nil, err
×
3950
                }
×
3951

3952
                chanSync, ok := msg.(*lnwire.ChannelReestablish)
4✔
3953
                if !ok {
4✔
3954
                        return nil, errors.New("unable cast db Message to " +
×
3955
                                "ChannelReestablish")
×
3956
                }
×
3957
                c.LastChanSyncMsg = chanSync
4✔
3958
        }
3959

3960
        return c, nil
126✔
3961
}
3962

3963
func writeChanConfig(b io.Writer, c *ChannelConfig) error {
8,743✔
3964
        return WriteElements(b,
8,743✔
3965
                c.DustLimit, c.MaxPendingAmount, c.ChanReserve, c.MinHTLC,
8,743✔
3966
                c.MaxAcceptedHtlcs, c.CsvDelay, c.MultiSigKey,
8,743✔
3967
                c.RevocationBasePoint, c.PaymentBasePoint, c.DelayBasePoint,
8,743✔
3968
                c.HtlcBasePoint,
8,743✔
3969
        )
8,743✔
3970
}
8,743✔
3971

3972
// fundingTxPresent returns true if expect the funding transcation to be found
3973
// on disk or already populated within the passed open channel struct.
3974
func fundingTxPresent(channel *OpenChannel) bool {
14,800✔
3975
        chanType := channel.ChanType
14,800✔
3976

14,800✔
3977
        return chanType.IsSingleFunder() && chanType.HasFundingTx() &&
14,800✔
3978
                channel.IsInitiator &&
14,800✔
3979
                !channel.hasChanStatus(ChanStatusRestored)
14,800✔
3980
}
14,800✔
3981

3982
func putChanInfo(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
4,313✔
3983
        var w bytes.Buffer
4,313✔
3984
        if err := WriteElements(&w,
4,313✔
3985
                channel.ChanType, channel.ChainHash, channel.FundingOutpoint,
4,313✔
3986
                channel.ShortChannelID, channel.IsPending, channel.IsInitiator,
4,313✔
3987
                channel.chanStatus, channel.FundingBroadcastHeight,
4,313✔
3988
                channel.NumConfsRequired, channel.ChannelFlags,
4,313✔
3989
                channel.IdentityPub, channel.Capacity, channel.TotalMSatSent,
4,313✔
3990
                channel.TotalMSatReceived,
4,313✔
3991
        ); err != nil {
4,313✔
3992
                return err
×
3993
        }
×
3994

3995
        // For single funder channels that we initiated, and we have the
3996
        // funding transaction, then write the funding txn.
3997
        if fundingTxPresent(channel) {
6,726✔
3998
                if err := WriteElement(&w, channel.FundingTxn); err != nil {
2,413✔
3999
                        return err
×
4000
                }
×
4001
        }
4002

4003
        if err := writeChanConfig(&w, &channel.LocalChanCfg); err != nil {
4,313✔
4004
                return err
×
4005
        }
×
4006
        if err := writeChanConfig(&w, &channel.RemoteChanCfg); err != nil {
4,313✔
4007
                return err
×
4008
        }
×
4009

4010
        // Convert balance fields into uint64.
4011
        localBalance := uint64(channel.InitialLocalBalance)
4,313✔
4012
        remoteBalance := uint64(channel.InitialRemoteBalance)
4,313✔
4013

4,313✔
4014
        // Create the tlv stream.
4,313✔
4015
        tlvStream, err := tlv.NewStream(
4,313✔
4016
                // Write the RevocationKeyLocator as the first entry in a tlv
4,313✔
4017
                // stream.
4,313✔
4018
                MakeKeyLocRecord(
4,313✔
4019
                        keyLocType, &channel.RevocationKeyLocator,
4,313✔
4020
                ),
4,313✔
4021
                tlv.MakePrimitiveRecord(
4,313✔
4022
                        initialLocalBalanceType, &localBalance,
4,313✔
4023
                ),
4,313✔
4024
                tlv.MakePrimitiveRecord(
4,313✔
4025
                        initialRemoteBalanceType, &remoteBalance,
4,313✔
4026
                ),
4,313✔
4027
                MakeScidRecord(realScidType, &channel.confirmedScid),
4,313✔
4028
                tlv.MakePrimitiveRecord(channelMemoType, &channel.Memo),
4,313✔
4029
        )
4,313✔
4030
        if err != nil {
4,313✔
4031
                return err
×
4032
        }
×
4033

4034
        if err := tlvStream.Encode(&w); err != nil {
4,313✔
4035
                return err
×
4036
        }
×
4037

4038
        if err := chanBucket.Put(chanInfoKey, w.Bytes()); err != nil {
4,313✔
4039
                return err
×
4040
        }
×
4041

4042
        // Finally, add optional shutdown scripts for the local and remote peer if
4043
        // they are present.
4044
        if err := putOptionalUpfrontShutdownScript(
4,313✔
4045
                chanBucket, localUpfrontShutdownKey, channel.LocalShutdownScript,
4,313✔
4046
        ); err != nil {
4,313✔
4047
                return err
×
4048
        }
×
4049

4050
        return putOptionalUpfrontShutdownScript(
4,313✔
4051
                chanBucket, remoteUpfrontShutdownKey, channel.RemoteShutdownScript,
4,313✔
4052
        )
4,313✔
4053
}
4054

4055
// putOptionalUpfrontShutdownScript adds a shutdown script under the key
4056
// provided if it has a non-zero length.
4057
func putOptionalUpfrontShutdownScript(chanBucket kvdb.RwBucket, key []byte,
4058
        script []byte) error {
8,622✔
4059
        // If the script is empty, we do not need to add anything.
8,622✔
4060
        if len(script) == 0 {
17,234✔
4061
                return nil
8,612✔
4062
        }
8,612✔
4063

4064
        var w bytes.Buffer
14✔
4065
        if err := WriteElement(&w, script); err != nil {
14✔
4066
                return err
×
4067
        }
×
4068

4069
        return chanBucket.Put(key, w.Bytes())
14✔
4070
}
4071

4072
// getOptionalUpfrontShutdownScript reads the shutdown script stored under the
4073
// key provided if it is present. Upfront shutdown scripts are optional, so the
4074
// function returns with no error if the key is not present.
4075
func getOptionalUpfrontShutdownScript(chanBucket kvdb.RBucket, key []byte,
4076
        script *lnwire.DeliveryAddress) error {
20,978✔
4077

20,978✔
4078
        // Return early if the bucket does not exit, a shutdown script was not set.
20,978✔
4079
        bs := chanBucket.Get(key)
20,978✔
4080
        if bs == nil {
41,952✔
4081
                return nil
20,974✔
4082
        }
20,974✔
4083

4084
        var tempScript []byte
8✔
4085
        r := bytes.NewReader(bs)
8✔
4086
        if err := ReadElement(r, &tempScript); err != nil {
8✔
4087
                return err
×
4088
        }
×
4089
        *script = tempScript
8✔
4090

8✔
4091
        return nil
8✔
4092
}
4093

4094
func serializeChanCommit(w io.Writer, c *ChannelCommitment) error {
11,742✔
4095
        if err := WriteElements(w,
11,742✔
4096
                c.CommitHeight, c.LocalLogIndex, c.LocalHtlcIndex,
11,742✔
4097
                c.RemoteLogIndex, c.RemoteHtlcIndex, c.LocalBalance,
11,742✔
4098
                c.RemoteBalance, c.CommitFee, c.FeePerKw, c.CommitTx,
11,742✔
4099
                c.CommitSig,
11,742✔
4100
        ); err != nil {
11,742✔
4101
                return err
×
4102
        }
×
4103

4104
        return SerializeHtlcs(w, c.Htlcs...)
11,742✔
4105
}
4106

4107
func putChanCommitment(chanBucket kvdb.RwBucket, c *ChannelCommitment,
4108
        local bool) error {
8,575✔
4109

8,575✔
4110
        var commitKey []byte
8,575✔
4111
        if local {
12,887✔
4112
                commitKey = append(chanCommitmentKey, byte(0x00))
4,312✔
4113
        } else {
8,579✔
4114
                commitKey = append(chanCommitmentKey, byte(0x01))
4,267✔
4115
        }
4,267✔
4116

4117
        var b bytes.Buffer
8,575✔
4118
        if err := serializeChanCommit(&b, c); err != nil {
8,575✔
4119
                return err
×
4120
        }
×
4121

4122
        return chanBucket.Put(commitKey, b.Bytes())
8,575✔
4123
}
4124

4125
func putChanCommitments(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
1,188✔
4126
        // If this is a restored channel, then we don't have any commitments to
1,188✔
4127
        // write.
1,188✔
4128
        if channel.hasChanStatus(ChanStatusRestored) {
1,193✔
4129
                return nil
5✔
4130
        }
5✔
4131

4132
        err := putChanCommitment(
1,187✔
4133
                chanBucket, &channel.LocalCommitment, true,
1,187✔
4134
        )
1,187✔
4135
        if err != nil {
1,187✔
4136
                return err
×
4137
        }
×
4138

4139
        return putChanCommitment(
1,187✔
4140
                chanBucket, &channel.RemoteCommitment, false,
1,187✔
4141
        )
1,187✔
4142
}
4143

4144
func putChanRevocationState(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
4,858✔
4145
        var b bytes.Buffer
4,858✔
4146
        err := WriteElements(
4,858✔
4147
                &b, channel.RemoteCurrentRevocation, channel.RevocationProducer,
4,858✔
4148
                channel.RevocationStore,
4,858✔
4149
        )
4,858✔
4150
        if err != nil {
4,858✔
4151
                return err
×
4152
        }
×
4153

4154
        // If the next revocation is present, which is only the case after the
4155
        // ChannelReady message has been sent, then we'll write it to disk.
4156
        if channel.RemoteNextRevocation != nil {
8,995✔
4157
                err = WriteElements(&b, channel.RemoteNextRevocation)
4,137✔
4158
                if err != nil {
4,137✔
4159
                        return err
×
4160
                }
×
4161
        }
4162

4163
        return chanBucket.Put(revocationStateKey, b.Bytes())
4,858✔
4164
}
4165

4166
func readChanConfig(b io.Reader, c *ChannelConfig) error {
21,100✔
4167
        return ReadElements(b,
21,100✔
4168
                &c.DustLimit, &c.MaxPendingAmount, &c.ChanReserve,
21,100✔
4169
                &c.MinHTLC, &c.MaxAcceptedHtlcs, &c.CsvDelay,
21,100✔
4170
                &c.MultiSigKey, &c.RevocationBasePoint,
21,100✔
4171
                &c.PaymentBasePoint, &c.DelayBasePoint,
21,100✔
4172
                &c.HtlcBasePoint,
21,100✔
4173
        )
21,100✔
4174
}
21,100✔
4175

4176
func fetchChanInfo(chanBucket kvdb.RBucket, channel *OpenChannel) error {
10,491✔
4177
        infoBytes := chanBucket.Get(chanInfoKey)
10,491✔
4178
        if infoBytes == nil {
10,491✔
4179
                return ErrNoChanInfoFound
×
4180
        }
×
4181
        r := bytes.NewReader(infoBytes)
10,491✔
4182

10,491✔
4183
        if err := ReadElements(r,
10,491✔
4184
                &channel.ChanType, &channel.ChainHash, &channel.FundingOutpoint,
10,491✔
4185
                &channel.ShortChannelID, &channel.IsPending, &channel.IsInitiator,
10,491✔
4186
                &channel.chanStatus, &channel.FundingBroadcastHeight,
10,491✔
4187
                &channel.NumConfsRequired, &channel.ChannelFlags,
10,491✔
4188
                &channel.IdentityPub, &channel.Capacity, &channel.TotalMSatSent,
10,491✔
4189
                &channel.TotalMSatReceived,
10,491✔
4190
        ); err != nil {
10,491✔
4191
                return err
×
4192
        }
×
4193

4194
        // For single funder channels that we initiated and have the funding
4195
        // transaction to, read the funding txn.
4196
        if fundingTxPresent(channel) {
15,973✔
4197
                if err := ReadElement(r, &channel.FundingTxn); err != nil {
5,482✔
4198
                        return err
×
4199
                }
×
4200
        }
4201

4202
        if err := readChanConfig(r, &channel.LocalChanCfg); err != nil {
10,491✔
4203
                return err
×
4204
        }
×
4205
        if err := readChanConfig(r, &channel.RemoteChanCfg); err != nil {
10,491✔
4206
                return err
×
4207
        }
×
4208

4209
        // Retrieve the boolean stored under lastWasRevokeKey.
4210
        lastWasRevokeBytes := chanBucket.Get(lastWasRevokeKey)
10,491✔
4211
        if lastWasRevokeBytes == nil {
11,790✔
4212
                // If nothing has been stored under this key, we store false in the
1,299✔
4213
                // OpenChannel struct.
1,299✔
4214
                channel.LastWasRevoke = false
1,299✔
4215
        } else {
10,495✔
4216
                // Otherwise, read the value into the LastWasRevoke field.
9,196✔
4217
                revokeReader := bytes.NewReader(lastWasRevokeBytes)
9,196✔
4218
                err := ReadElements(revokeReader, &channel.LastWasRevoke)
9,196✔
4219
                if err != nil {
9,196✔
4220
                        return err
×
4221
                }
×
4222
        }
4223

4224
        // Create balance fields in uint64, and Memo field as byte slice.
4225
        var (
10,491✔
4226
                localBalance  uint64
10,491✔
4227
                remoteBalance uint64
10,491✔
4228
                memo          []byte
10,491✔
4229
        )
10,491✔
4230

10,491✔
4231
        // Create the tlv stream.
10,491✔
4232
        tlvStream, err := tlv.NewStream(
10,491✔
4233
                // Write the RevocationKeyLocator as the first entry in a tlv
10,491✔
4234
                // stream.
10,491✔
4235
                MakeKeyLocRecord(
10,491✔
4236
                        keyLocType, &channel.RevocationKeyLocator,
10,491✔
4237
                ),
10,491✔
4238
                tlv.MakePrimitiveRecord(
10,491✔
4239
                        initialLocalBalanceType, &localBalance,
10,491✔
4240
                ),
10,491✔
4241
                tlv.MakePrimitiveRecord(
10,491✔
4242
                        initialRemoteBalanceType, &remoteBalance,
10,491✔
4243
                ),
10,491✔
4244
                MakeScidRecord(realScidType, &channel.confirmedScid),
10,491✔
4245
                tlv.MakePrimitiveRecord(channelMemoType, &memo),
10,491✔
4246
        )
10,491✔
4247
        if err != nil {
10,491✔
4248
                return err
×
4249
        }
×
4250

4251
        if err := tlvStream.Decode(r); err != nil {
10,491✔
4252
                return err
×
4253
        }
×
4254

4255
        // Attach the balance fields.
4256
        channel.InitialLocalBalance = lnwire.MilliSatoshi(localBalance)
10,491✔
4257
        channel.InitialRemoteBalance = lnwire.MilliSatoshi(remoteBalance)
10,491✔
4258

10,491✔
4259
        // Attach the memo field if non-empty.
10,491✔
4260
        if len(memo) > 0 {
10,495✔
4261
                channel.Memo = memo
4✔
4262
        }
4✔
4263

4264
        channel.Packager = NewChannelPackager(channel.ShortChannelID)
10,491✔
4265

10,491✔
4266
        // Finally, read the optional shutdown scripts.
10,491✔
4267
        if err := getOptionalUpfrontShutdownScript(
10,491✔
4268
                chanBucket, localUpfrontShutdownKey, &channel.LocalShutdownScript,
10,491✔
4269
        ); err != nil {
10,491✔
4270
                return err
×
4271
        }
×
4272

4273
        return getOptionalUpfrontShutdownScript(
10,491✔
4274
                chanBucket, remoteUpfrontShutdownKey, &channel.RemoteShutdownScript,
10,491✔
4275
        )
10,491✔
4276
}
4277

4278
func deserializeChanCommit(r io.Reader) (ChannelCommitment, error) {
24,153✔
4279
        var c ChannelCommitment
24,153✔
4280

24,153✔
4281
        err := ReadElements(r,
24,153✔
4282
                &c.CommitHeight, &c.LocalLogIndex, &c.LocalHtlcIndex, &c.RemoteLogIndex,
24,153✔
4283
                &c.RemoteHtlcIndex, &c.LocalBalance, &c.RemoteBalance,
24,153✔
4284
                &c.CommitFee, &c.FeePerKw, &c.CommitTx, &c.CommitSig,
24,153✔
4285
        )
24,153✔
4286
        if err != nil {
24,153✔
4287
                return c, err
×
4288
        }
×
4289

4290
        c.Htlcs, err = DeserializeHtlcs(r)
24,153✔
4291
        if err != nil {
24,153✔
4292
                return c, err
×
4293
        }
×
4294

4295
        return c, nil
24,153✔
4296
}
4297

4298
func fetchChanCommitment(chanBucket kvdb.RBucket, local bool) (ChannelCommitment, error) {
21,005✔
4299
        var commitKey []byte
21,005✔
4300
        if local {
31,510✔
4301
                commitKey = append(chanCommitmentKey, byte(0x00))
10,505✔
4302
        } else {
21,009✔
4303
                commitKey = append(chanCommitmentKey, byte(0x01))
10,504✔
4304
        }
10,504✔
4305

4306
        commitBytes := chanBucket.Get(commitKey)
21,005✔
4307
        if commitBytes == nil {
21,005✔
4308
                return ChannelCommitment{}, ErrNoCommitmentsFound
×
4309
        }
×
4310

4311
        r := bytes.NewReader(commitBytes)
21,005✔
4312
        return deserializeChanCommit(r)
21,005✔
4313
}
4314

4315
func fetchChanCommitments(chanBucket kvdb.RBucket, channel *OpenChannel) error {
10,506✔
4316
        var err error
10,506✔
4317

10,506✔
4318
        // If this is a restored channel, then we don't have any commitments to
10,506✔
4319
        // read.
10,506✔
4320
        if channel.hasChanStatus(ChanStatusRestored) {
10,512✔
4321
                return nil
6✔
4322
        }
6✔
4323

4324
        channel.LocalCommitment, err = fetchChanCommitment(chanBucket, true)
10,504✔
4325
        if err != nil {
10,504✔
4326
                return err
×
4327
        }
×
4328
        channel.RemoteCommitment, err = fetchChanCommitment(chanBucket, false)
10,504✔
4329
        if err != nil {
10,504✔
4330
                return err
×
4331
        }
×
4332

4333
        return nil
10,504✔
4334
}
4335

4336
func fetchChanRevocationState(chanBucket kvdb.RBucket, channel *OpenChannel) error {
10,506✔
4337
        revBytes := chanBucket.Get(revocationStateKey)
10,506✔
4338
        if revBytes == nil {
10,506✔
4339
                return ErrNoRevocationsFound
×
4340
        }
×
4341
        r := bytes.NewReader(revBytes)
10,506✔
4342

10,506✔
4343
        err := ReadElements(
10,506✔
4344
                r, &channel.RemoteCurrentRevocation, &channel.RevocationProducer,
10,506✔
4345
                &channel.RevocationStore,
10,506✔
4346
        )
10,506✔
4347
        if err != nil {
10,506✔
4348
                return err
×
4349
        }
×
4350

4351
        // If there aren't any bytes left in the buffer, then we don't yet have
4352
        // the next remote revocation, so we can exit early here.
4353
        if r.Len() == 0 {
10,716✔
4354
                return nil
210✔
4355
        }
210✔
4356

4357
        // Otherwise we'll read the next revocation for the remote party which
4358
        // is always the last item within the buffer.
4359
        return ReadElements(r, &channel.RemoteNextRevocation)
10,300✔
4360
}
4361

4362
func deleteOpenChannel(chanBucket kvdb.RwBucket) error {
118✔
4363
        if err := chanBucket.Delete(chanInfoKey); err != nil {
118✔
4364
                return err
×
4365
        }
×
4366

4367
        err := chanBucket.Delete(append(chanCommitmentKey, byte(0x00)))
118✔
4368
        if err != nil {
118✔
4369
                return err
×
4370
        }
×
4371
        err = chanBucket.Delete(append(chanCommitmentKey, byte(0x01)))
118✔
4372
        if err != nil {
118✔
4373
                return err
×
4374
        }
×
4375

4376
        if err := chanBucket.Delete(revocationStateKey); err != nil {
118✔
4377
                return err
×
4378
        }
×
4379

4380
        if diff := chanBucket.Get(commitDiffKey); diff != nil {
122✔
4381
                return chanBucket.Delete(commitDiffKey)
4✔
4382
        }
4✔
4383

4384
        return nil
118✔
4385
}
4386

4387
// makeLogKey converts a uint64 into an 8 byte array.
4388
func makeLogKey(updateNum uint64) [8]byte {
20,710✔
4389
        var key [8]byte
20,710✔
4390
        byteOrder.PutUint64(key[:], updateNum)
20,710✔
4391
        return key
20,710✔
4392
}
20,710✔
4393

4394
func fetchThawHeight(chanBucket kvdb.RBucket) (uint32, error) {
338✔
4395
        var height uint32
338✔
4396

338✔
4397
        heightBytes := chanBucket.Get(frozenChanKey)
338✔
4398
        heightReader := bytes.NewReader(heightBytes)
338✔
4399

338✔
4400
        if err := ReadElements(heightReader, &height); err != nil {
338✔
4401
                return 0, err
×
4402
        }
×
4403

4404
        return height, nil
338✔
4405
}
4406

4407
func storeThawHeight(chanBucket kvdb.RwBucket, height uint32) error {
432✔
4408
        var heightBuf bytes.Buffer
432✔
4409
        if err := WriteElements(&heightBuf, height); err != nil {
432✔
4410
                return err
×
4411
        }
×
4412

4413
        return chanBucket.Put(frozenChanKey, heightBuf.Bytes())
432✔
4414
}
4415

4416
func deleteThawHeight(chanBucket kvdb.RwBucket) error {
111✔
4417
        return chanBucket.Delete(frozenChanKey)
111✔
4418
}
111✔
4419

4420
// EKeyLocator is an encoder for keychain.KeyLocator.
4421
func EKeyLocator(w io.Writer, val interface{}, buf *[8]byte) error {
4,314✔
4422
        if v, ok := val.(*keychain.KeyLocator); ok {
8,628✔
4423
                err := tlv.EUint32T(w, uint32(v.Family), buf)
4,314✔
4424
                if err != nil {
4,314✔
4425
                        return err
×
4426
                }
×
4427

4428
                return tlv.EUint32T(w, v.Index, buf)
4,314✔
4429
        }
4430
        return tlv.NewTypeForEncodingErr(val, "keychain.KeyLocator")
×
4431
}
4432

4433
// DKeyLocator is a decoder for keychain.KeyLocator.
4434
func DKeyLocator(r io.Reader, val interface{}, buf *[8]byte, l uint64) error {
10,492✔
4435
        if v, ok := val.(*keychain.KeyLocator); ok {
20,984✔
4436
                var family uint32
10,492✔
4437
                err := tlv.DUint32(r, &family, buf, 4)
10,492✔
4438
                if err != nil {
10,492✔
4439
                        return err
×
4440
                }
×
4441
                v.Family = keychain.KeyFamily(family)
10,492✔
4442

10,492✔
4443
                return tlv.DUint32(r, &v.Index, buf, 4)
10,492✔
4444
        }
4445
        return tlv.NewTypeForDecodingErr(val, "keychain.KeyLocator", l, 8)
×
4446
}
4447

4448
// MakeKeyLocRecord creates a Record out of a KeyLocator using the passed
4449
// Type and the EKeyLocator and DKeyLocator functions. The size will always be
4450
// 8 as KeyFamily is uint32 and the Index is uint32.
4451
func MakeKeyLocRecord(typ tlv.Type, keyLoc *keychain.KeyLocator) tlv.Record {
14,800✔
4452
        return tlv.MakeStaticRecord(typ, keyLoc, 8, EKeyLocator, DKeyLocator)
14,800✔
4453
}
14,800✔
4454

4455
// MakeScidRecord creates a Record out of a ShortChannelID using the passed
4456
// Type and the EShortChannelID and DShortChannelID functions. The size will
4457
// always be 8 for the ShortChannelID.
4458
func MakeScidRecord(typ tlv.Type, scid *lnwire.ShortChannelID) tlv.Record {
14,800✔
4459
        return tlv.MakeStaticRecord(
14,800✔
4460
                typ, scid, 8, lnwire.EShortChannelID, lnwire.DShortChannelID,
14,800✔
4461
        )
14,800✔
4462
}
14,800✔
4463

4464
// ShutdownInfo contains various info about the shutdown initiation of a
4465
// channel.
4466
type ShutdownInfo struct {
4467
        // DeliveryScript is the address that we have included in any previous
4468
        // Shutdown message for a particular channel and so should include in
4469
        // any future re-sends of the Shutdown message.
4470
        DeliveryScript tlv.RecordT[tlv.TlvType0, lnwire.DeliveryAddress]
4471

4472
        // LocalInitiator is true if we sent a Shutdown message before ever
4473
        // receiving a Shutdown message from the remote peer.
4474
        LocalInitiator tlv.RecordT[tlv.TlvType1, bool]
4475
}
4476

4477
// NewShutdownInfo constructs a new ShutdownInfo object.
4478
func NewShutdownInfo(deliveryScript lnwire.DeliveryAddress,
4479
        locallyInitiated bool) *ShutdownInfo {
17✔
4480

17✔
4481
        return &ShutdownInfo{
17✔
4482
                DeliveryScript: tlv.NewRecordT[tlv.TlvType0](deliveryScript),
17✔
4483
                LocalInitiator: tlv.NewPrimitiveRecord[tlv.TlvType1](
17✔
4484
                        locallyInitiated,
17✔
4485
                ),
17✔
4486
        }
17✔
4487
}
17✔
4488

4489
// encode serialises the ShutdownInfo to the given io.Writer.
4490
func (s *ShutdownInfo) encode(w io.Writer) error {
15✔
4491
        records := []tlv.Record{
15✔
4492
                s.DeliveryScript.Record(),
15✔
4493
                s.LocalInitiator.Record(),
15✔
4494
        }
15✔
4495

15✔
4496
        stream, err := tlv.NewStream(records...)
15✔
4497
        if err != nil {
15✔
4498
                return err
×
4499
        }
×
4500

4501
        return stream.Encode(w)
15✔
4502
}
4503

4504
// decodeShutdownInfo constructs a ShutdownInfo struct by decoding the given
4505
// byte slice.
4506
func decodeShutdownInfo(b []byte) (*ShutdownInfo, error) {
6✔
4507
        tlvStream := lnwire.ExtraOpaqueData(b)
6✔
4508

6✔
4509
        var info ShutdownInfo
6✔
4510
        records := []tlv.RecordProducer{
6✔
4511
                &info.DeliveryScript,
6✔
4512
                &info.LocalInitiator,
6✔
4513
        }
6✔
4514

6✔
4515
        _, err := tlvStream.ExtractRecords(records...)
6✔
4516

6✔
4517
        return &info, err
6✔
4518
}
6✔
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