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

lightningnetwork / lnd / 10426952143

16 Aug 2024 10:17PM UTC coverage: 49.856% (+0.01%) from 49.843%
10426952143

Pull #8512

github

Roasbeef
lnwallet/chancloser: add unit tests for new rbf coop close
Pull Request #8512: [3/4] - lnwallet/chancloser: add new protofsm based RBF chan closer

6 of 1064 new or added lines in 6 files covered. (0.56%)

159 existing lines in 21 files now uncovered.

96167 of 192890 relevant lines covered (49.86%)

1.55 hits per line

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

72.11
/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/lntypes"
29
        "github.com/lightningnetwork/lnd/lnwire"
30
        "github.com/lightningnetwork/lnd/shachain"
31
        "github.com/lightningnetwork/lnd/tlv"
32
)
33

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

398
// ChannelStateBounds are the parameters from OpenChannel and AcceptChannel
399
// that are responsible for providing bounds on the state space of the abstract
400
// channel state. These values must be remembered for normal channel operation
401
// but they do not impact how we compute the commitment transactions themselves.
402
type ChannelStateBounds struct {
403
        // ChanReserve is an absolute reservation on the channel for the
404
        // owner of this set of constraints. This means that the current
405
        // settled balance for this node CANNOT dip below the reservation
406
        // amount. This acts as a defense against costless attacks when
407
        // either side no longer has any skin in the game.
408
        ChanReserve btcutil.Amount
409

410
        // MaxPendingAmount is the maximum pending HTLC value that the
411
        // owner of these constraints can offer the remote node at a
412
        // particular time.
413
        MaxPendingAmount lnwire.MilliSatoshi
414

415
        // MinHTLC is the minimum HTLC value that the owner of these
416
        // constraints can offer the remote node. If any HTLCs below this
417
        // amount are offered, then the HTLC will be rejected. This, in
418
        // tandem with the dust limit allows a node to regulate the
419
        // smallest HTLC that it deems economically relevant.
420
        MinHTLC lnwire.MilliSatoshi
421

422
        // MaxAcceptedHtlcs is the maximum number of HTLCs that the owner of
423
        // this set of constraints can offer the remote node. This allows each
424
        // node to limit their over all exposure to HTLCs that may need to be
425
        // acted upon in the case of a unilateral channel closure or a contract
426
        // breach.
427
        MaxAcceptedHtlcs uint16
428
}
429

430
// CommitmentParams are the parameters from OpenChannel and
431
// AcceptChannel that are required to render an abstract channel state to a
432
// concrete commitment transaction. These values are necessary to (re)compute
433
// the commitment transaction. We treat these differently than the state space
434
// bounds because their history needs to be stored in order to properly handle
435
// chain resolution.
436
type CommitmentParams struct {
437
        // DustLimit is the threshold (in satoshis) below which any outputs
438
        // should be trimmed. When an output is trimmed, it isn't materialized
439
        // as an actual output, but is instead burned to miner's fees.
440
        DustLimit btcutil.Amount
441

442
        // CsvDelay is the relative time lock delay expressed in blocks. Any
443
        // settled outputs that pay to the owner of this channel configuration
444
        // MUST ensure that the delay branch uses this value as the relative
445
        // time lock. Similarly, any HTLC's offered by this node should use
446
        // this value as well.
447
        CsvDelay uint16
448
}
449

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

463
        // CommitmentParams is an embedding of the parameters
464
        // required to render an abstract channel state into a concrete
465
        // commitment transaction.
466
        CommitmentParams
467

468
        // MultiSigKey is the key to be used within the 2-of-2 output script
469
        // for the owner of this channel config.
470
        MultiSigKey keychain.KeyDescriptor
471

472
        // RevocationBasePoint is the base public key to be used when deriving
473
        // revocation keys for the remote node's commitment transaction. This
474
        // will be combined along with a per commitment secret to derive a
475
        // unique revocation key for each state.
476
        RevocationBasePoint keychain.KeyDescriptor
477

478
        // PaymentBasePoint is the base public key to be used when deriving
479
        // the key used within the non-delayed pay-to-self output on the
480
        // commitment transaction for a node. This will be combined with a
481
        // tweak derived from the per-commitment point to ensure unique keys
482
        // for each commitment transaction.
483
        PaymentBasePoint keychain.KeyDescriptor
484

485
        // DelayBasePoint is the base public key to be used when deriving the
486
        // key used within the delayed pay-to-self output on the commitment
487
        // transaction for a node. This will be combined with a tweak derived
488
        // from the per-commitment point to ensure unique keys for each
489
        // commitment transaction.
490
        DelayBasePoint keychain.KeyDescriptor
491

492
        // HtlcBasePoint is the base public key to be used when deriving the
493
        // local HTLC key. The derived key (combined with the tweak derived
494
        // from the per-commitment point) is used within the "to self" clause
495
        // within any HTLC output scripts.
496
        HtlcBasePoint keychain.KeyDescriptor
497
}
498

499
// ChannelCommitment is a snapshot of the commitment state at a particular
500
// point in the commitment chain. With each state transition, a snapshot of the
501
// current state along with all non-settled HTLCs are recorded. These snapshots
502
// detail the state of the _remote_ party's commitment at a particular state
503
// number.  For ourselves (the local node) we ONLY store our most recent
504
// (unrevoked) state for safety purposes.
505
type ChannelCommitment struct {
506
        // CommitHeight is the update number that this ChannelDelta represents
507
        // the total number of commitment updates to this point. This can be
508
        // viewed as sort of a "commitment height" as this number is
509
        // monotonically increasing.
510
        CommitHeight uint64
511

512
        // LocalLogIndex is the cumulative log index index of the local node at
513
        // this point in the commitment chain. This value will be incremented
514
        // for each _update_ added to the local update log.
515
        LocalLogIndex uint64
516

517
        // LocalHtlcIndex is the current local running HTLC index. This value
518
        // will be incremented for each outgoing HTLC the local node offers.
519
        LocalHtlcIndex uint64
520

521
        // RemoteLogIndex is the cumulative log index index of the remote node
522
        // at this point in the commitment chain. This value will be
523
        // incremented for each _update_ added to the remote update log.
524
        RemoteLogIndex uint64
525

526
        // RemoteHtlcIndex is the current remote running HTLC index. This value
527
        // will be incremented for each outgoing HTLC the remote node offers.
528
        RemoteHtlcIndex uint64
529

530
        // LocalBalance is the current available settled balance within the
531
        // channel directly spendable by us.
532
        //
533
        // NOTE: This is the balance *after* subtracting any commitment fee,
534
        // AND anchor output values.
535
        LocalBalance lnwire.MilliSatoshi
536

537
        // RemoteBalance is the current available settled balance within the
538
        // channel directly spendable by the remote node.
539
        //
540
        // NOTE: This is the balance *after* subtracting any commitment fee,
541
        // AND anchor output values.
542
        RemoteBalance lnwire.MilliSatoshi
543

544
        // CommitFee is the amount calculated to be paid in fees for the
545
        // current set of commitment transactions. The fee amount is persisted
546
        // with the channel in order to allow the fee amount to be removed and
547
        // recalculated with each channel state update, including updates that
548
        // happen after a system restart.
549
        CommitFee btcutil.Amount
550

551
        // FeePerKw is the min satoshis/kilo-weight that should be paid within
552
        // the commitment transaction for the entire duration of the channel's
553
        // lifetime. This field may be updated during normal operation of the
554
        // channel as on-chain conditions change.
555
        //
556
        // TODO(halseth): make this SatPerKWeight. Cannot be done atm because
557
        // this will cause the import cycle lnwallet<->channeldb. Fee
558
        // estimation stuff should be in its own package.
559
        FeePerKw btcutil.Amount
560

561
        // CommitTx is the latest version of the commitment state, broadcast
562
        // able by us.
563
        CommitTx *wire.MsgTx
564

565
        // CommitSig is one half of the signature required to fully complete
566
        // the script for the commitment transaction above. This is the
567
        // signature signed by the remote party for our version of the
568
        // commitment transactions.
569
        CommitSig []byte
570

571
        // Htlcs is the set of HTLC's that are pending at this particular
572
        // commitment height.
573
        Htlcs []HTLC
574

575
        // TODO(roasbeef): pending commit pointer?
576
        //  * lets just walk through
577
}
578

579
// ChannelStatus is a bit vector used to indicate whether an OpenChannel is in
580
// the default usable state, or a state where it shouldn't be used.
581
type ChannelStatus uint64
582

583
var (
584
        // ChanStatusDefault is the normal state of an open channel.
585
        ChanStatusDefault ChannelStatus
586

587
        // ChanStatusBorked indicates that the channel has entered an
588
        // irreconcilable state, triggered by a state desynchronization or
589
        // channel breach.  Channels in this state should never be added to the
590
        // htlc switch.
591
        ChanStatusBorked ChannelStatus = 1
592

593
        // ChanStatusCommitBroadcasted indicates that a commitment for this
594
        // channel has been broadcasted.
595
        ChanStatusCommitBroadcasted ChannelStatus = 1 << 1
596

597
        // ChanStatusLocalDataLoss indicates that we have lost channel state
598
        // for this channel, and broadcasting our latest commitment might be
599
        // considered a breach.
600
        //
601
        // TODO(halseh): actually enforce that we are not force closing such a
602
        // channel.
603
        ChanStatusLocalDataLoss ChannelStatus = 1 << 2
604

605
        // ChanStatusRestored is a status flag that signals that the channel
606
        // has been restored, and doesn't have all the fields a typical channel
607
        // will have.
608
        ChanStatusRestored ChannelStatus = 1 << 3
609

610
        // ChanStatusCoopBroadcasted indicates that a cooperative close for
611
        // this channel has been broadcasted. Older cooperatively closed
612
        // channels will only have this status set. Newer ones will also have
613
        // close initiator information stored using the local/remote initiator
614
        // status. This status is set in conjunction with the initiator status
615
        // so that we do not need to check multiple channel statues for
616
        // cooperative closes.
617
        ChanStatusCoopBroadcasted ChannelStatus = 1 << 4
618

619
        // ChanStatusLocalCloseInitiator indicates that we initiated closing
620
        // the channel.
621
        ChanStatusLocalCloseInitiator ChannelStatus = 1 << 5
622

623
        // ChanStatusRemoteCloseInitiator indicates that the remote node
624
        // initiated closing the channel.
625
        ChanStatusRemoteCloseInitiator ChannelStatus = 1 << 6
626
)
627

628
// chanStatusStrings maps a ChannelStatus to a human friendly string that
629
// describes that status.
630
var chanStatusStrings = map[ChannelStatus]string{
631
        ChanStatusDefault:              "ChanStatusDefault",
632
        ChanStatusBorked:               "ChanStatusBorked",
633
        ChanStatusCommitBroadcasted:    "ChanStatusCommitBroadcasted",
634
        ChanStatusLocalDataLoss:        "ChanStatusLocalDataLoss",
635
        ChanStatusRestored:             "ChanStatusRestored",
636
        ChanStatusCoopBroadcasted:      "ChanStatusCoopBroadcasted",
637
        ChanStatusLocalCloseInitiator:  "ChanStatusLocalCloseInitiator",
638
        ChanStatusRemoteCloseInitiator: "ChanStatusRemoteCloseInitiator",
639
}
640

641
// orderedChanStatusFlags is an in-order list of all that channel status flags.
642
var orderedChanStatusFlags = []ChannelStatus{
643
        ChanStatusBorked,
644
        ChanStatusCommitBroadcasted,
645
        ChanStatusLocalDataLoss,
646
        ChanStatusRestored,
647
        ChanStatusCoopBroadcasted,
648
        ChanStatusLocalCloseInitiator,
649
        ChanStatusRemoteCloseInitiator,
650
}
651

652
// String returns a human-readable representation of the ChannelStatus.
653
func (c ChannelStatus) String() string {
3✔
654
        // If no flags are set, then this is the default case.
3✔
655
        if c == ChanStatusDefault {
6✔
656
                return chanStatusStrings[ChanStatusDefault]
3✔
657
        }
3✔
658

659
        // Add individual bit flags.
660
        statusStr := ""
3✔
661
        for _, flag := range orderedChanStatusFlags {
6✔
662
                if c&flag == flag {
6✔
663
                        statusStr += chanStatusStrings[flag] + "|"
3✔
664
                        c -= flag
3✔
665
                }
3✔
666
        }
667

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

3✔
671
        // Add any remaining flags which aren't accounted for as hex.
3✔
672
        if c != 0 {
3✔
673
                statusStr += "|0x" + strconv.FormatUint(uint64(c), 16)
×
674
        }
×
675

676
        // If this was purely an unknown flag, then remove the extra bar at the
677
        // start of the string.
678
        statusStr = strings.TrimLeft(statusStr, "|")
3✔
679

3✔
680
        return statusStr
3✔
681
}
682

683
// FinalHtlcByte defines a byte type that encodes information about the final
684
// htlc resolution.
685
type FinalHtlcByte byte
686

687
const (
688
        // FinalHtlcSettledBit is the bit that encodes whether the htlc was
689
        // settled or failed.
690
        FinalHtlcSettledBit FinalHtlcByte = 1 << 0
691

692
        // FinalHtlcOffchainBit is the bit that encodes whether the htlc was
693
        // resolved offchain or onchain.
694
        FinalHtlcOffchainBit FinalHtlcByte = 1 << 1
695
)
696

697
// OpenChannel encapsulates the persistent and dynamic state of an open channel
698
// with a remote node. An open channel supports several options for on-disk
699
// serialization depending on the exact context. Full (upon channel creation)
700
// state commitments, and partial (due to a commitment update) writes are
701
// supported. Each partial write due to a state update appends the new update
702
// to an on-disk log, which can then subsequently be queried in order to
703
// "time-travel" to a prior state.
704
type OpenChannel struct {
705
        // ChanType denotes which type of channel this is.
706
        ChanType ChannelType
707

708
        // ChainHash is a hash which represents the blockchain that this
709
        // channel will be opened within. This value is typically the genesis
710
        // hash. In the case that the original chain went through a contentious
711
        // hard-fork, then this value will be tweaked using the unique fork
712
        // point on each branch.
713
        ChainHash chainhash.Hash
714

715
        // FundingOutpoint is the outpoint of the final funding transaction.
716
        // This value uniquely and globally identifies the channel within the
717
        // target blockchain as specified by the chain hash parameter.
718
        FundingOutpoint wire.OutPoint
719

720
        // ShortChannelID encodes the exact location in the chain in which the
721
        // channel was initially confirmed. This includes: the block height,
722
        // transaction index, and the output within the target transaction.
723
        //
724
        // If IsZeroConf(), then this will the "base" (very first) ALIAS scid
725
        // and the confirmed SCID will be stored in ConfirmedScid.
726
        ShortChannelID lnwire.ShortChannelID
727

728
        // IsPending indicates whether a channel's funding transaction has been
729
        // confirmed.
730
        IsPending bool
731

732
        // IsInitiator is a bool which indicates if we were the original
733
        // initiator for the channel. This value may affect how higher levels
734
        // negotiate fees, or close the channel.
735
        IsInitiator bool
736

737
        // chanStatus is the current status of this channel. If it is not in
738
        // the state Default, it should not be used for forwarding payments.
739
        chanStatus ChannelStatus
740

741
        // FundingBroadcastHeight is the height in which the funding
742
        // transaction was broadcast. This value can be used by higher level
743
        // sub-systems to determine if a channel is stale and/or should have
744
        // been confirmed before a certain height.
745
        FundingBroadcastHeight uint32
746

747
        // NumConfsRequired is the number of confirmations a channel's funding
748
        // transaction must have received in order to be considered available
749
        // for normal transactional use.
750
        NumConfsRequired uint16
751

752
        // ChannelFlags holds the flags that were sent as part of the
753
        // open_channel message.
754
        ChannelFlags lnwire.FundingFlag
755

756
        // IdentityPub is the identity public key of the remote node this
757
        // channel has been established with.
758
        IdentityPub *btcec.PublicKey
759

760
        // Capacity is the total capacity of this channel.
761
        Capacity btcutil.Amount
762

763
        // TotalMSatSent is the total number of milli-satoshis we've sent
764
        // within this channel.
765
        TotalMSatSent lnwire.MilliSatoshi
766

767
        // TotalMSatReceived is the total number of milli-satoshis we've
768
        // received within this channel.
769
        TotalMSatReceived lnwire.MilliSatoshi
770

771
        // InitialLocalBalance is the balance we have during the channel
772
        // opening. When we are not the initiator, this value represents the
773
        // push amount.
774
        InitialLocalBalance lnwire.MilliSatoshi
775

776
        // InitialRemoteBalance is the balance they have during the channel
777
        // opening.
778
        InitialRemoteBalance lnwire.MilliSatoshi
779

780
        // LocalChanCfg is the channel configuration for the local node.
781
        LocalChanCfg ChannelConfig
782

783
        // RemoteChanCfg is the channel configuration for the remote node.
784
        RemoteChanCfg ChannelConfig
785

786
        // LocalCommitment is the current local commitment state for the local
787
        // party. This is stored distinct from the state of the remote party
788
        // as there are certain asymmetric parameters which affect the
789
        // structure of each commitment.
790
        LocalCommitment ChannelCommitment
791

792
        // RemoteCommitment is the current remote commitment state for the
793
        // remote party. This is stored distinct from the state of the local
794
        // party as there are certain asymmetric parameters which affect the
795
        // structure of each commitment.
796
        RemoteCommitment ChannelCommitment
797

798
        // RemoteCurrentRevocation is the current revocation for their
799
        // commitment transaction. However, since this the derived public key,
800
        // we don't yet have the private key so we aren't yet able to verify
801
        // that it's actually in the hash chain.
802
        RemoteCurrentRevocation *btcec.PublicKey
803

804
        // RemoteNextRevocation is the revocation key to be used for the *next*
805
        // commitment transaction we create for the local node. Within the
806
        // specification, this value is referred to as the
807
        // per-commitment-point.
808
        RemoteNextRevocation *btcec.PublicKey
809

810
        // RevocationProducer is used to generate the revocation in such a way
811
        // that remote side might store it efficiently and have the ability to
812
        // restore the revocation by index if needed. Current implementation of
813
        // secret producer is shachain producer.
814
        RevocationProducer shachain.Producer
815

816
        // RevocationStore is used to efficiently store the revocations for
817
        // previous channels states sent to us by remote side. Current
818
        // implementation of secret store is shachain store.
819
        RevocationStore shachain.Store
820

821
        // Packager is used to create and update forwarding packages for this
822
        // channel, which encodes all necessary information to recover from
823
        // failures and reforward HTLCs that were not fully processed.
824
        Packager FwdPackager
825

826
        // FundingTxn is the transaction containing this channel's funding
827
        // outpoint. Upon restarts, this txn will be rebroadcast if the channel
828
        // is found to be pending.
829
        //
830
        // NOTE: This value will only be populated for single-funder channels
831
        // for which we are the initiator, and that we also have the funding
832
        // transaction for. One can check this by using the HasFundingTx()
833
        // method on the ChanType field.
834
        FundingTxn *wire.MsgTx
835

836
        // LocalShutdownScript is set to a pre-set script if the channel was opened
837
        // by the local node with option_upfront_shutdown_script set. If the option
838
        // was not set, the field is empty.
839
        LocalShutdownScript lnwire.DeliveryAddress
840

841
        // RemoteShutdownScript is set to a pre-set script if the channel was opened
842
        // by the remote node with option_upfront_shutdown_script set. If the option
843
        // was not set, the field is empty.
844
        RemoteShutdownScript lnwire.DeliveryAddress
845

846
        // ThawHeight is the height when a frozen channel once again becomes a
847
        // normal channel. If this is zero, then there're no restrictions on
848
        // this channel. If the value is lower than 500,000, then it's
849
        // interpreted as a relative height, or an absolute height otherwise.
850
        ThawHeight uint32
851

852
        // LastWasRevoke is a boolean that determines if the last update we sent
853
        // was a revocation (true) or a commitment signature (false).
854
        LastWasRevoke bool
855

856
        // RevocationKeyLocator stores the KeyLocator information that we will
857
        // need to derive the shachain root for this channel. This allows us to
858
        // have private key isolation from lnd.
859
        RevocationKeyLocator keychain.KeyLocator
860

861
        // confirmedScid is the confirmed ShortChannelID for a zero-conf
862
        // channel. If the channel is unconfirmed, then this will be the
863
        // default ShortChannelID. This is only set for zero-conf channels.
864
        confirmedScid lnwire.ShortChannelID
865

866
        // Memo is any arbitrary information we wish to store locally about the
867
        // channel that will be useful to our future selves.
868
        Memo []byte
869

870
        // TODO(roasbeef): eww
871
        Db *ChannelStateDB
872

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

875
        sync.RWMutex
876
}
877

878
// String returns a string representation of the channel.
879
func (c *OpenChannel) String() string {
3✔
880
        indexStr := "height=%v, local_htlc_index=%v, local_log_index=%v, " +
3✔
881
                "remote_htlc_index=%v, remote_log_index=%v"
3✔
882

3✔
883
        commit := c.LocalCommitment
3✔
884
        local := fmt.Sprintf(indexStr, commit.CommitHeight,
3✔
885
                commit.LocalHtlcIndex, commit.LocalLogIndex,
3✔
886
                commit.RemoteHtlcIndex, commit.RemoteLogIndex,
3✔
887
        )
3✔
888

3✔
889
        commit = c.RemoteCommitment
3✔
890
        remote := fmt.Sprintf(indexStr, commit.CommitHeight,
3✔
891
                commit.LocalHtlcIndex, commit.LocalLogIndex,
3✔
892
                commit.RemoteHtlcIndex, commit.RemoteLogIndex,
3✔
893
        )
3✔
894

3✔
895
        return fmt.Sprintf("SCID=%v, status=%v, initiator=%v, pending=%v, "+
3✔
896
                "local commitment has %s, remote commitment has %s",
3✔
897
                c.ShortChannelID, c.chanStatus, c.IsInitiator, c.IsPending,
3✔
898
                local, remote,
3✔
899
        )
3✔
900
}
3✔
901

902
// Initiator returns the ChannelParty that originally opened this channel.
903
func (c *OpenChannel) Initiator() lntypes.ChannelParty {
×
904
        c.RLock()
×
905
        defer c.RUnlock()
×
906

×
907
        if c.IsInitiator {
×
908
                return lntypes.Local
×
909
        }
×
910

911
        return lntypes.Remote
×
912
}
913

914
// ShortChanID returns the current ShortChannelID of this channel.
915
func (c *OpenChannel) ShortChanID() lnwire.ShortChannelID {
3✔
916
        c.RLock()
3✔
917
        defer c.RUnlock()
3✔
918

3✔
919
        return c.ShortChannelID
3✔
920
}
3✔
921

922
// ZeroConfRealScid returns the zero-conf channel's confirmed scid. This should
923
// only be called if IsZeroConf returns true.
924
func (c *OpenChannel) ZeroConfRealScid() lnwire.ShortChannelID {
3✔
925
        c.RLock()
3✔
926
        defer c.RUnlock()
3✔
927

3✔
928
        return c.confirmedScid
3✔
929
}
3✔
930

931
// ZeroConfConfirmed returns whether the zero-conf channel has confirmed. This
932
// should only be called if IsZeroConf returns true.
933
func (c *OpenChannel) ZeroConfConfirmed() bool {
3✔
934
        c.RLock()
3✔
935
        defer c.RUnlock()
3✔
936

3✔
937
        return c.confirmedScid != hop.Source
3✔
938
}
3✔
939

940
// IsZeroConf returns whether the option_zeroconf channel type was negotiated.
941
func (c *OpenChannel) IsZeroConf() bool {
3✔
942
        c.RLock()
3✔
943
        defer c.RUnlock()
3✔
944

3✔
945
        return c.ChanType.HasZeroConf()
3✔
946
}
3✔
947

948
// IsOptionScidAlias returns whether the option_scid_alias channel type was
949
// negotiated.
950
func (c *OpenChannel) IsOptionScidAlias() bool {
×
951
        c.RLock()
×
952
        defer c.RUnlock()
×
953

×
954
        return c.ChanType.HasScidAliasChan()
×
955
}
×
956

957
// NegotiatedAliasFeature returns whether the option-scid-alias feature bit was
958
// negotiated.
959
func (c *OpenChannel) NegotiatedAliasFeature() bool {
3✔
960
        c.RLock()
3✔
961
        defer c.RUnlock()
3✔
962

3✔
963
        return c.ChanType.HasScidAliasFeature()
3✔
964
}
3✔
965

966
// ChanStatus returns the current ChannelStatus of this channel.
967
func (c *OpenChannel) ChanStatus() ChannelStatus {
3✔
968
        c.RLock()
3✔
969
        defer c.RUnlock()
3✔
970

3✔
971
        return c.chanStatus
3✔
972
}
3✔
973

974
// ApplyChanStatus allows the caller to modify the internal channel state in a
975
// thead-safe manner.
976
func (c *OpenChannel) ApplyChanStatus(status ChannelStatus) error {
×
977
        c.Lock()
×
978
        defer c.Unlock()
×
979

×
980
        return c.putChanStatus(status)
×
981
}
×
982

983
// ClearChanStatus allows the caller to clear a particular channel status from
984
// the primary channel status bit field. After this method returns, a call to
985
// HasChanStatus(status) should return false.
986
func (c *OpenChannel) ClearChanStatus(status ChannelStatus) error {
×
987
        c.Lock()
×
988
        defer c.Unlock()
×
989

×
990
        return c.clearChanStatus(status)
×
991
}
×
992

993
// HasChanStatus returns true if the internal bitfield channel status of the
994
// target channel has the specified status bit set.
995
func (c *OpenChannel) HasChanStatus(status ChannelStatus) bool {
3✔
996
        c.RLock()
3✔
997
        defer c.RUnlock()
3✔
998

3✔
999
        return c.hasChanStatus(status)
3✔
1000
}
3✔
1001

1002
func (c *OpenChannel) hasChanStatus(status ChannelStatus) bool {
3✔
1003
        // Special case ChanStatusDefualt since it isn't actually flag, but a
3✔
1004
        // particular combination (or lack-there-of) of flags.
3✔
1005
        if status == ChanStatusDefault {
6✔
1006
                return c.chanStatus == ChanStatusDefault
3✔
1007
        }
3✔
1008

1009
        return c.chanStatus&status == status
3✔
1010
}
1011

1012
// BroadcastHeight returns the height at which the funding tx was broadcast.
1013
func (c *OpenChannel) BroadcastHeight() uint32 {
3✔
1014
        c.RLock()
3✔
1015
        defer c.RUnlock()
3✔
1016

3✔
1017
        return c.FundingBroadcastHeight
3✔
1018
}
3✔
1019

1020
// SetBroadcastHeight sets the FundingBroadcastHeight.
1021
func (c *OpenChannel) SetBroadcastHeight(height uint32) {
3✔
1022
        c.Lock()
3✔
1023
        defer c.Unlock()
3✔
1024

3✔
1025
        c.FundingBroadcastHeight = height
3✔
1026
}
3✔
1027

1028
// Refresh updates the in-memory channel state using the latest state observed
1029
// on disk.
1030
func (c *OpenChannel) Refresh() error {
3✔
1031
        c.Lock()
3✔
1032
        defer c.Unlock()
3✔
1033

3✔
1034
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
1035
                chanBucket, err := fetchChanBucket(
3✔
1036
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1037
                )
3✔
1038
                if err != nil {
6✔
1039
                        return err
3✔
1040
                }
3✔
1041

1042
                // We'll re-populating the in-memory channel with the info
1043
                // fetched from disk.
1044
                if err := fetchChanInfo(chanBucket, c); err != nil {
3✔
1045
                        return fmt.Errorf("unable to fetch chan info: %w", err)
×
1046
                }
×
1047

1048
                // Also populate the channel's commitment states for both sides
1049
                // of the channel.
1050
                if err := fetchChanCommitments(chanBucket, c); err != nil {
3✔
1051
                        return fmt.Errorf("unable to fetch chan commitments: "+
×
1052
                                "%v", err)
×
1053
                }
×
1054

1055
                // Also retrieve the current revocation state.
1056
                if err := fetchChanRevocationState(chanBucket, c); err != nil {
3✔
1057
                        return fmt.Errorf("unable to fetch chan revocations: "+
×
1058
                                "%v", err)
×
1059
                }
×
1060

1061
                return nil
3✔
1062
        }, func() {})
3✔
1063
        if err != nil {
6✔
1064
                return err
3✔
1065
        }
3✔
1066

1067
        return nil
3✔
1068
}
1069

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

3✔
1076
        // First fetch the top level bucket which stores all data related to
3✔
1077
        // current, active channels.
3✔
1078
        openChanBucket := tx.ReadBucket(openChannelBucket)
3✔
1079
        if openChanBucket == nil {
3✔
1080
                return nil, ErrNoChanDBExists
×
1081
        }
×
1082

1083
        // TODO(roasbeef): CreateTopLevelBucket on the interface isn't like
1084
        // CreateIfNotExists, will return error
1085

1086
        // Within this top level bucket, fetch the bucket dedicated to storing
1087
        // open channel data specific to the remote node.
1088
        nodePub := nodeKey.SerializeCompressed()
3✔
1089
        nodeChanBucket := openChanBucket.NestedReadBucket(nodePub)
3✔
1090
        if nodeChanBucket == nil {
3✔
1091
                return nil, ErrNoActiveChannels
×
1092
        }
×
1093

1094
        // We'll then recurse down an additional layer in order to fetch the
1095
        // bucket for this particular chain.
1096
        chainBucket := nodeChanBucket.NestedReadBucket(chainHash[:])
3✔
1097
        if chainBucket == nil {
3✔
1098
                return nil, ErrNoActiveChannels
×
1099
        }
×
1100

1101
        // With the bucket for the node and chain fetched, we can now go down
1102
        // another level, for this channel itself.
1103
        var chanPointBuf bytes.Buffer
3✔
1104
        if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
3✔
1105
                return nil, err
×
1106
        }
×
1107
        chanBucket := chainBucket.NestedReadBucket(chanPointBuf.Bytes())
3✔
1108
        if chanBucket == nil {
6✔
1109
                return nil, ErrChannelNotFound
3✔
1110
        }
3✔
1111

1112
        return chanBucket, nil
3✔
1113
}
1114

1115
// fetchChanBucketRw is a helper function that returns the bucket where a
1116
// channel's data resides in given: the public key for the node, the outpoint,
1117
// and the chainhash that the channel resides on. This differs from
1118
// fetchChanBucket in that it returns a writeable bucket.
1119
func fetchChanBucketRw(tx kvdb.RwTx, nodeKey *btcec.PublicKey,
1120
        outPoint *wire.OutPoint, chainHash chainhash.Hash) (kvdb.RwBucket,
1121
        error) {
3✔
1122

3✔
1123
        // First fetch the top level bucket which stores all data related to
3✔
1124
        // current, active channels.
3✔
1125
        openChanBucket := tx.ReadWriteBucket(openChannelBucket)
3✔
1126
        if openChanBucket == nil {
3✔
1127
                return nil, ErrNoChanDBExists
×
1128
        }
×
1129

1130
        // TODO(roasbeef): CreateTopLevelBucket on the interface isn't like
1131
        // CreateIfNotExists, will return error
1132

1133
        // Within this top level bucket, fetch the bucket dedicated to storing
1134
        // open channel data specific to the remote node.
1135
        nodePub := nodeKey.SerializeCompressed()
3✔
1136
        nodeChanBucket := openChanBucket.NestedReadWriteBucket(nodePub)
3✔
1137
        if nodeChanBucket == nil {
3✔
1138
                return nil, ErrNoActiveChannels
×
1139
        }
×
1140

1141
        // We'll then recurse down an additional layer in order to fetch the
1142
        // bucket for this particular chain.
1143
        chainBucket := nodeChanBucket.NestedReadWriteBucket(chainHash[:])
3✔
1144
        if chainBucket == nil {
3✔
1145
                return nil, ErrNoActiveChannels
×
1146
        }
×
1147

1148
        // With the bucket for the node and chain fetched, we can now go down
1149
        // another level, for this channel itself.
1150
        var chanPointBuf bytes.Buffer
3✔
1151
        if err := writeOutpoint(&chanPointBuf, outPoint); err != nil {
3✔
1152
                return nil, err
×
1153
        }
×
1154
        chanBucket := chainBucket.NestedReadWriteBucket(chanPointBuf.Bytes())
3✔
1155
        if chanBucket == nil {
4✔
1156
                return nil, ErrChannelNotFound
1✔
1157
        }
1✔
1158

1159
        return chanBucket, nil
3✔
1160
}
1161

1162
func fetchFinalHtlcsBucketRw(tx kvdb.RwTx,
1163
        chanID lnwire.ShortChannelID) (kvdb.RwBucket, error) {
3✔
1164

3✔
1165
        finalHtlcsBucket, err := tx.CreateTopLevelBucket(finalHtlcsBucket)
3✔
1166
        if err != nil {
3✔
1167
                return nil, err
×
1168
        }
×
1169

1170
        var chanIDBytes [8]byte
3✔
1171
        byteOrder.PutUint64(chanIDBytes[:], chanID.ToUint64())
3✔
1172
        chanBucket, err := finalHtlcsBucket.CreateBucketIfNotExists(
3✔
1173
                chanIDBytes[:],
3✔
1174
        )
3✔
1175
        if err != nil {
3✔
1176
                return nil, err
×
1177
        }
×
1178

1179
        return chanBucket, nil
3✔
1180
}
1181

1182
// fullSync syncs the contents of an OpenChannel while re-using an existing
1183
// database transaction.
1184
func (c *OpenChannel) fullSync(tx kvdb.RwTx) error {
3✔
1185
        // Fetch the outpoint bucket and check if the outpoint already exists.
3✔
1186
        opBucket := tx.ReadWriteBucket(outpointBucket)
3✔
1187
        if opBucket == nil {
3✔
1188
                return ErrNoChanDBExists
×
1189
        }
×
1190
        cidBucket := tx.ReadWriteBucket(chanIDBucket)
3✔
1191
        if cidBucket == nil {
3✔
1192
                return ErrNoChanDBExists
×
1193
        }
×
1194

1195
        var chanPointBuf bytes.Buffer
3✔
1196
        if err := writeOutpoint(&chanPointBuf, &c.FundingOutpoint); err != nil {
3✔
1197
                return err
×
1198
        }
×
1199

1200
        // Now, check if the outpoint exists in our index.
1201
        if opBucket.Get(chanPointBuf.Bytes()) != nil {
6✔
1202
                return ErrChanAlreadyExists
3✔
1203
        }
3✔
1204

1205
        cid := lnwire.NewChanIDFromOutPoint(c.FundingOutpoint)
3✔
1206
        if cidBucket.Get(cid[:]) != nil {
3✔
1207
                return ErrChanAlreadyExists
×
1208
        }
×
1209

1210
        status := uint8(outpointOpen)
3✔
1211

3✔
1212
        // Write the status of this outpoint as the first entry in a tlv
3✔
1213
        // stream.
3✔
1214
        statusRecord := tlv.MakePrimitiveRecord(indexStatusType, &status)
3✔
1215
        opStream, err := tlv.NewStream(statusRecord)
3✔
1216
        if err != nil {
3✔
1217
                return err
×
1218
        }
×
1219

1220
        var b bytes.Buffer
3✔
1221
        if err := opStream.Encode(&b); err != nil {
3✔
1222
                return err
×
1223
        }
×
1224

1225
        // Add the outpoint to our outpoint index with the tlv stream.
1226
        if err := opBucket.Put(chanPointBuf.Bytes(), b.Bytes()); err != nil {
3✔
1227
                return err
×
1228
        }
×
1229

1230
        if err := cidBucket.Put(cid[:], []byte{}); err != nil {
3✔
1231
                return err
×
1232
        }
×
1233

1234
        // First fetch the top level bucket which stores all data related to
1235
        // current, active channels.
1236
        openChanBucket, err := tx.CreateTopLevelBucket(openChannelBucket)
3✔
1237
        if err != nil {
3✔
1238
                return err
×
1239
        }
×
1240

1241
        // Within this top level bucket, fetch the bucket dedicated to storing
1242
        // open channel data specific to the remote node.
1243
        nodePub := c.IdentityPub.SerializeCompressed()
3✔
1244
        nodeChanBucket, err := openChanBucket.CreateBucketIfNotExists(nodePub)
3✔
1245
        if err != nil {
3✔
1246
                return err
×
1247
        }
×
1248

1249
        // We'll then recurse down an additional layer in order to fetch the
1250
        // bucket for this particular chain.
1251
        chainBucket, err := nodeChanBucket.CreateBucketIfNotExists(c.ChainHash[:])
3✔
1252
        if err != nil {
3✔
1253
                return err
×
1254
        }
×
1255

1256
        // With the bucket for the node fetched, we can now go down another
1257
        // level, creating the bucket for this channel itself.
1258
        chanBucket, err := chainBucket.CreateBucket(
3✔
1259
                chanPointBuf.Bytes(),
3✔
1260
        )
3✔
1261
        switch {
3✔
1262
        case err == kvdb.ErrBucketExists:
×
1263
                // If this channel already exists, then in order to avoid
×
1264
                // overriding it, we'll return an error back up to the caller.
×
1265
                return ErrChanAlreadyExists
×
1266
        case err != nil:
×
1267
                return err
×
1268
        }
1269

1270
        return putOpenChannel(chanBucket, c)
3✔
1271
}
1272

1273
// MarkAsOpen marks a channel as fully open given a locator that uniquely
1274
// describes its location within the chain.
1275
func (c *OpenChannel) MarkAsOpen(openLoc lnwire.ShortChannelID) error {
3✔
1276
        c.Lock()
3✔
1277
        defer c.Unlock()
3✔
1278

3✔
1279
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
1280
                chanBucket, err := fetchChanBucketRw(
3✔
1281
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1282
                )
3✔
1283
                if err != nil {
3✔
1284
                        return err
×
1285
                }
×
1286

1287
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
3✔
1288
                if err != nil {
3✔
1289
                        return err
×
1290
                }
×
1291

1292
                channel.IsPending = false
3✔
1293
                channel.ShortChannelID = openLoc
3✔
1294

3✔
1295
                return putOpenChannel(chanBucket, channel)
3✔
1296
        }, func() {}); err != nil {
3✔
1297
                return err
×
1298
        }
×
1299

1300
        c.IsPending = false
3✔
1301
        c.ShortChannelID = openLoc
3✔
1302
        c.Packager = NewChannelPackager(openLoc)
3✔
1303

3✔
1304
        return nil
3✔
1305
}
1306

1307
// MarkRealScid marks the zero-conf channel's confirmed ShortChannelID. This
1308
// should only be done if IsZeroConf returns true.
1309
func (c *OpenChannel) MarkRealScid(realScid lnwire.ShortChannelID) error {
3✔
1310
        c.Lock()
3✔
1311
        defer c.Unlock()
3✔
1312

3✔
1313
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
1314
                chanBucket, err := fetchChanBucketRw(
3✔
1315
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1316
                )
3✔
1317
                if err != nil {
3✔
1318
                        return err
×
1319
                }
×
1320

1321
                channel, err := fetchOpenChannel(
3✔
1322
                        chanBucket, &c.FundingOutpoint,
3✔
1323
                )
3✔
1324
                if err != nil {
3✔
1325
                        return err
×
1326
                }
×
1327

1328
                channel.confirmedScid = realScid
3✔
1329

3✔
1330
                return putOpenChannel(chanBucket, channel)
3✔
1331
        }, func() {}); err != nil {
3✔
1332
                return err
×
1333
        }
×
1334

1335
        c.confirmedScid = realScid
3✔
1336

3✔
1337
        return nil
3✔
1338
}
1339

1340
// MarkScidAliasNegotiated adds ScidAliasFeatureBit to ChanType in-memory and
1341
// in the database.
1342
func (c *OpenChannel) MarkScidAliasNegotiated() error {
3✔
1343
        c.Lock()
3✔
1344
        defer c.Unlock()
3✔
1345

3✔
1346
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
1347
                chanBucket, err := fetchChanBucketRw(
3✔
1348
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1349
                )
3✔
1350
                if err != nil {
3✔
1351
                        return err
×
1352
                }
×
1353

1354
                channel, err := fetchOpenChannel(
3✔
1355
                        chanBucket, &c.FundingOutpoint,
3✔
1356
                )
3✔
1357
                if err != nil {
3✔
1358
                        return err
×
1359
                }
×
1360

1361
                channel.ChanType |= ScidAliasFeatureBit
3✔
1362
                return putOpenChannel(chanBucket, channel)
3✔
1363
        }, func() {}); err != nil {
3✔
1364
                return err
×
1365
        }
×
1366

1367
        c.ChanType |= ScidAliasFeatureBit
3✔
1368

3✔
1369
        return nil
3✔
1370
}
1371

1372
// MarkDataLoss marks sets the channel status to LocalDataLoss and stores the
1373
// passed commitPoint for use to retrieve funds in case the remote force closes
1374
// the channel.
1375
func (c *OpenChannel) MarkDataLoss(commitPoint *btcec.PublicKey) error {
3✔
1376
        c.Lock()
3✔
1377
        defer c.Unlock()
3✔
1378

3✔
1379
        var b bytes.Buffer
3✔
1380
        if err := WriteElement(&b, commitPoint); err != nil {
3✔
1381
                return err
×
1382
        }
×
1383

1384
        putCommitPoint := func(chanBucket kvdb.RwBucket) error {
6✔
1385
                return chanBucket.Put(dataLossCommitPointKey, b.Bytes())
3✔
1386
        }
3✔
1387

1388
        return c.putChanStatus(ChanStatusLocalDataLoss, putCommitPoint)
3✔
1389
}
1390

1391
// DataLossCommitPoint retrieves the stored commit point set during
1392
// MarkDataLoss. If not found ErrNoCommitPoint is returned.
1393
func (c *OpenChannel) DataLossCommitPoint() (*btcec.PublicKey, error) {
×
1394
        var commitPoint *btcec.PublicKey
×
1395

×
1396
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
×
1397
                chanBucket, err := fetchChanBucket(
×
1398
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
×
1399
                )
×
1400
                switch err {
×
1401
                case nil:
×
1402
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
×
1403
                        return ErrNoCommitPoint
×
1404
                default:
×
1405
                        return err
×
1406
                }
1407

1408
                bs := chanBucket.Get(dataLossCommitPointKey)
×
1409
                if bs == nil {
×
1410
                        return ErrNoCommitPoint
×
1411
                }
×
1412
                r := bytes.NewReader(bs)
×
1413
                if err := ReadElements(r, &commitPoint); err != nil {
×
1414
                        return err
×
1415
                }
×
1416

1417
                return nil
×
1418
        }, func() {
×
1419
                commitPoint = nil
×
1420
        })
×
1421
        if err != nil {
×
1422
                return nil, err
×
1423
        }
×
1424

1425
        return commitPoint, nil
×
1426
}
1427

1428
// MarkBorked marks the event when the channel as reached an irreconcilable
1429
// state, such as a channel breach or state desynchronization. Borked channels
1430
// should never be added to the switch.
1431
func (c *OpenChannel) MarkBorked() error {
3✔
1432
        c.Lock()
3✔
1433
        defer c.Unlock()
3✔
1434

3✔
1435
        return c.putChanStatus(ChanStatusBorked)
3✔
1436
}
3✔
1437

1438
// SecondCommitmentPoint returns the second per-commitment-point for use in the
1439
// channel_ready message.
1440
func (c *OpenChannel) SecondCommitmentPoint() (*btcec.PublicKey, error) {
3✔
1441
        c.RLock()
3✔
1442
        defer c.RUnlock()
3✔
1443

3✔
1444
        // Since we start at commitment height = 0, the second per commitment
3✔
1445
        // point is actually at the 1st index.
3✔
1446
        revocation, err := c.RevocationProducer.AtIndex(1)
3✔
1447
        if err != nil {
3✔
1448
                return nil, err
×
1449
        }
×
1450

1451
        return input.ComputeCommitmentPoint(revocation[:]), nil
3✔
1452
}
1453

1454
var (
1455
        // taprootRevRootKey is the key used to derive the revocation root for
1456
        // the taproot nonces. This is done via HMAC of the existing revocation
1457
        // root.
1458
        taprootRevRootKey = []byte("taproot-rev-root")
1459
)
1460

1461
// DeriveMusig2Shachain derives a shachain producer for the taproot channel
1462
// from normal shachain revocation root.
1463
func DeriveMusig2Shachain(revRoot shachain.Producer) (shachain.Producer, error) { //nolint:lll
3✔
1464
        // In order to obtain the revocation root hash to create the taproot
3✔
1465
        // revocation, we'll encode the producer into a buffer, then use that
3✔
1466
        // to derive the shachain root needed.
3✔
1467
        var rootHashBuf bytes.Buffer
3✔
1468
        if err := revRoot.Encode(&rootHashBuf); err != nil {
3✔
1469
                return nil, fmt.Errorf("unable to encode producer: %w", err)
×
1470
        }
×
1471

1472
        revRootHash := chainhash.HashH(rootHashBuf.Bytes())
3✔
1473

3✔
1474
        // For taproot channel types, we'll also generate a distinct shachain
3✔
1475
        // root using the same seed information. We'll use this to generate
3✔
1476
        // verification nonces for the channel. We'll bind with this a simple
3✔
1477
        // hmac.
3✔
1478
        taprootRevHmac := hmac.New(sha256.New, taprootRevRootKey)
3✔
1479
        if _, err := taprootRevHmac.Write(revRootHash[:]); err != nil {
3✔
1480
                return nil, err
×
1481
        }
×
1482

1483
        taprootRevRoot := taprootRevHmac.Sum(nil)
3✔
1484

3✔
1485
        // Once we have the root, we can then generate our shachain producer
3✔
1486
        // and from that generate the per-commitment point.
3✔
1487
        return shachain.NewRevocationProducerFromBytes(
3✔
1488
                taprootRevRoot,
3✔
1489
        )
3✔
1490
}
1491

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

3✔
1500
        // Now that we know what height we need, we'll grab the shachain
3✔
1501
        // pre-image at the target destination.
3✔
1502
        nextPreimage, err := shaGen.AtIndex(targetHeight)
3✔
1503
        if err != nil {
3✔
1504
                return nil, err
×
1505
        }
×
1506

1507
        shaChainRand := musig2.WithCustomRand(bytes.NewBuffer(nextPreimage[:]))
3✔
1508
        pubKeyOpt := musig2.WithPublicKey(pubKey)
3✔
1509

3✔
1510
        return musig2.GenNonces(pubKeyOpt, shaChainRand)
3✔
1511
}
1512

1513
// ChanSyncMsg returns the ChannelReestablish message that should be sent upon
1514
// reconnection with the remote peer that we're maintaining this channel with.
1515
// The information contained within this message is necessary to re-sync our
1516
// commitment chains in the case of a last or only partially processed message.
1517
// When the remote party receives this message one of three things may happen:
1518
//
1519
//  1. We're fully synced and no messages need to be sent.
1520
//  2. We didn't get the last CommitSig message they sent, so they'll re-send
1521
//     it.
1522
//  3. We didn't get the last RevokeAndAck message they sent, so they'll
1523
//     re-send it.
1524
//
1525
// If this is a restored channel, having status ChanStatusRestored, then we'll
1526
// modify our typical chan sync message to ensure they force close even if
1527
// we're on the very first state.
1528
func (c *OpenChannel) ChanSyncMsg() (*lnwire.ChannelReestablish, error) {
3✔
1529
        c.Lock()
3✔
1530
        defer c.Unlock()
3✔
1531

3✔
1532
        // The remote commitment height that we'll send in the
3✔
1533
        // ChannelReestablish message is our current commitment height plus
3✔
1534
        // one. If the receiver thinks that our commitment height is actually
3✔
1535
        // *equal* to this value, then they'll re-send the last commitment that
3✔
1536
        // they sent but we never fully processed.
3✔
1537
        localHeight := c.LocalCommitment.CommitHeight
3✔
1538
        nextLocalCommitHeight := localHeight + 1
3✔
1539

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

3✔
1545
        // If this channel has undergone a commitment update, then in order to
3✔
1546
        // prove to the remote party our knowledge of their prior commitment
3✔
1547
        // state, we'll also send over the last commitment secret that the
3✔
1548
        // remote party sent.
3✔
1549
        var lastCommitSecret [32]byte
3✔
1550
        if remoteChainTipHeight != 0 {
6✔
1551
                remoteSecret, err := c.RevocationStore.LookUp(
3✔
1552
                        remoteChainTipHeight - 1,
3✔
1553
                )
3✔
1554
                if err != nil {
3✔
1555
                        return nil, err
×
1556
                }
×
1557
                lastCommitSecret = [32]byte(*remoteSecret)
3✔
1558
        }
1559

1560
        // Additionally, we'll send over the current unrevoked commitment on
1561
        // our local commitment transaction.
1562
        currentCommitSecret, err := c.RevocationProducer.AtIndex(
3✔
1563
                localHeight,
3✔
1564
        )
3✔
1565
        if err != nil {
3✔
1566
                return nil, err
×
1567
        }
×
1568

1569
        // If we've restored this channel, then we'll purposefully give them an
1570
        // invalid LocalUnrevokedCommitPoint so they'll force close the channel
1571
        // allowing us to sweep our funds.
1572
        if c.hasChanStatus(ChanStatusRestored) {
6✔
1573
                currentCommitSecret[0] ^= 1
3✔
1574

3✔
1575
                // If this is a tweakless channel, then we'll purposefully send
3✔
1576
                // a next local height taht's invalid to trigger a force close
3✔
1577
                // on their end. We do this as tweakless channels don't require
3✔
1578
                // that the commitment point is valid, only that it's present.
3✔
1579
                if c.ChanType.IsTweakless() {
6✔
1580
                        nextLocalCommitHeight = 0
3✔
1581
                }
3✔
1582
        }
1583

1584
        // If this is a taproot channel, then we'll need to generate our next
1585
        // verification nonce to send to the remote party. They'll use this to
1586
        // sign the next update to our commitment transaction.
1587
        var nextTaprootNonce lnwire.OptMusig2NonceTLV
3✔
1588
        if c.ChanType.IsTaproot() {
6✔
1589
                taprootRevProducer, err := DeriveMusig2Shachain(
3✔
1590
                        c.RevocationProducer,
3✔
1591
                )
3✔
1592
                if err != nil {
3✔
1593
                        return nil, err
×
1594
                }
×
1595

1596
                nextNonce, err := NewMusigVerificationNonce(
3✔
1597
                        c.LocalChanCfg.MultiSigKey.PubKey,
3✔
1598
                        nextLocalCommitHeight, taprootRevProducer,
3✔
1599
                )
3✔
1600
                if err != nil {
3✔
1601
                        return nil, fmt.Errorf("unable to gen next "+
×
1602
                                "nonce: %w", err)
×
1603
                }
×
1604

1605
                nextTaprootNonce = lnwire.SomeMusig2Nonce(nextNonce.PubNonce)
3✔
1606
        }
1607

1608
        return &lnwire.ChannelReestablish{
3✔
1609
                ChanID: lnwire.NewChanIDFromOutPoint(
3✔
1610
                        c.FundingOutpoint,
3✔
1611
                ),
3✔
1612
                NextLocalCommitHeight:  nextLocalCommitHeight,
3✔
1613
                RemoteCommitTailHeight: remoteChainTipHeight,
3✔
1614
                LastRemoteCommitSecret: lastCommitSecret,
3✔
1615
                LocalUnrevokedCommitPoint: input.ComputeCommitmentPoint(
3✔
1616
                        currentCommitSecret[:],
3✔
1617
                ),
3✔
1618
                LocalNonce: nextTaprootNonce,
3✔
1619
        }, nil
3✔
1620
}
1621

1622
// MarkShutdownSent serialises and persist the given ShutdownInfo for this
1623
// channel. Persisting this info represents the fact that we have sent the
1624
// Shutdown message to the remote side and hence that we should re-transmit the
1625
// same Shutdown message on re-establish.
1626
func (c *OpenChannel) MarkShutdownSent(info *ShutdownInfo) error {
3✔
1627
        c.Lock()
3✔
1628
        defer c.Unlock()
3✔
1629

3✔
1630
        return c.storeShutdownInfo(info)
3✔
1631
}
3✔
1632

1633
// storeShutdownInfo serialises the ShutdownInfo and persists it under the
1634
// shutdownInfoKey.
1635
func (c *OpenChannel) storeShutdownInfo(info *ShutdownInfo) error {
3✔
1636
        var b bytes.Buffer
3✔
1637
        err := info.encode(&b)
3✔
1638
        if err != nil {
3✔
1639
                return err
×
1640
        }
×
1641

1642
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
1643
                chanBucket, err := fetchChanBucketRw(
3✔
1644
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1645
                )
3✔
1646
                if err != nil {
3✔
1647
                        return err
×
1648
                }
×
1649

1650
                return chanBucket.Put(shutdownInfoKey, b.Bytes())
3✔
1651
        }, func() {})
3✔
1652
}
1653

1654
// ShutdownInfo decodes the shutdown info stored for this channel and returns
1655
// the result. If no shutdown info has been persisted for this channel then the
1656
// ErrNoShutdownInfo error is returned.
1657
func (c *OpenChannel) ShutdownInfo() (fn.Option[ShutdownInfo], error) {
3✔
1658
        c.RLock()
3✔
1659
        defer c.RUnlock()
3✔
1660

3✔
1661
        var shutdownInfo *ShutdownInfo
3✔
1662
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
1663
                chanBucket, err := fetchChanBucket(
3✔
1664
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1665
                )
3✔
1666
                switch {
3✔
1667
                case err == nil:
3✔
1668
                case errors.Is(err, ErrNoChanDBExists),
1669
                        errors.Is(err, ErrNoActiveChannels),
1670
                        errors.Is(err, ErrChannelNotFound):
2✔
1671

2✔
1672
                        return ErrNoShutdownInfo
2✔
1673
                default:
×
1674
                        return err
×
1675
                }
1676

1677
                shutdownInfoBytes := chanBucket.Get(shutdownInfoKey)
3✔
1678
                if shutdownInfoBytes == nil {
6✔
1679
                        return ErrNoShutdownInfo
3✔
1680
                }
3✔
1681

1682
                shutdownInfo, err = decodeShutdownInfo(shutdownInfoBytes)
3✔
1683

3✔
1684
                return err
3✔
1685
        }, func() {
3✔
1686
                shutdownInfo = nil
3✔
1687
        })
3✔
1688
        if err != nil {
6✔
1689
                return fn.None[ShutdownInfo](), err
3✔
1690
        }
3✔
1691

1692
        return fn.Some[ShutdownInfo](*shutdownInfo), nil
3✔
1693
}
1694

1695
// isBorked returns true if the channel has been marked as borked in the
1696
// database. This requires an existing database transaction to already be
1697
// active.
1698
//
1699
// NOTE: The primary mutex should already be held before this method is called.
1700
func (c *OpenChannel) isBorked(chanBucket kvdb.RBucket) (bool, error) {
3✔
1701
        channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
3✔
1702
        if err != nil {
3✔
1703
                return false, err
×
1704
        }
×
1705

1706
        return channel.chanStatus != ChanStatusDefault, nil
3✔
1707
}
1708

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

3✔
1718
        return c.markBroadcasted(
3✔
1719
                ChanStatusCommitBroadcasted, forceCloseTxKey, closeTx,
3✔
1720
                closer,
3✔
1721
        )
3✔
1722
}
3✔
1723

1724
// MarkCoopBroadcasted marks the channel to indicate that a cooperative close
1725
// transaction has been broadcast, either our own or the remote, and that we
1726
// should watch the chain for it to confirm before taking further action. It
1727
// takes as argument a cooperative close tx that could appear on chain, and
1728
// should be rebroadcast upon startup. This is only used to republish and
1729
// ensure propagation, and we should still handle the case where a different tx
1730
// actually hits the chain.
1731
func (c *OpenChannel) MarkCoopBroadcasted(closeTx *wire.MsgTx,
1732
        closer lntypes.ChannelParty) error {
3✔
1733

3✔
1734
        return c.markBroadcasted(
3✔
1735
                ChanStatusCoopBroadcasted, coopCloseTxKey, closeTx,
3✔
1736
                closer,
3✔
1737
        )
3✔
1738
}
3✔
1739

1740
// markBroadcasted is a helper function which modifies the channel status of the
1741
// receiving channel and inserts a close transaction under the requested key,
1742
// which should specify either a coop or force close. It adds a status which
1743
// indicates the party that initiated the channel close.
1744
func (c *OpenChannel) markBroadcasted(status ChannelStatus, key []byte,
1745
        closeTx *wire.MsgTx, closer lntypes.ChannelParty) error {
3✔
1746

3✔
1747
        c.Lock()
3✔
1748
        defer c.Unlock()
3✔
1749

3✔
1750
        // If a closing tx is provided, we'll generate a closure to write the
3✔
1751
        // transaction in the appropriate bucket under the given key.
3✔
1752
        var putClosingTx func(kvdb.RwBucket) error
3✔
1753
        if closeTx != nil {
6✔
1754
                var b bytes.Buffer
3✔
1755
                if err := WriteElement(&b, closeTx); err != nil {
3✔
1756
                        return err
×
1757
                }
×
1758

1759
                putClosingTx = func(chanBucket kvdb.RwBucket) error {
6✔
1760
                        return chanBucket.Put(key, b.Bytes())
3✔
1761
                }
3✔
1762
        }
1763

1764
        // Add the initiator status to the status provided. These statuses are
1765
        // set in addition to the broadcast status so that we do not need to
1766
        // migrate the original logic which does not store initiator.
1767
        if closer.IsLocal() {
6✔
1768
                status |= ChanStatusLocalCloseInitiator
3✔
1769
        } else {
6✔
1770
                status |= ChanStatusRemoteCloseInitiator
3✔
1771
        }
3✔
1772

1773
        return c.putChanStatus(status, putClosingTx)
3✔
1774
}
1775

1776
// BroadcastedCommitment retrieves the stored unilateral closing tx set during
1777
// MarkCommitmentBroadcasted. If not found ErrNoCloseTx is returned.
1778
func (c *OpenChannel) BroadcastedCommitment() (*wire.MsgTx, error) {
3✔
1779
        return c.getClosingTx(forceCloseTxKey)
3✔
1780
}
3✔
1781

1782
// BroadcastedCooperative retrieves the stored cooperative closing tx set during
1783
// MarkCoopBroadcasted. If not found ErrNoCloseTx is returned.
1784
func (c *OpenChannel) BroadcastedCooperative() (*wire.MsgTx, error) {
3✔
1785
        return c.getClosingTx(coopCloseTxKey)
3✔
1786
}
3✔
1787

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

3✔
1793
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
1794
                chanBucket, err := fetchChanBucket(
3✔
1795
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1796
                )
3✔
1797
                switch err {
3✔
1798
                case nil:
3✔
1799
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
×
1800
                        return ErrNoCloseTx
×
1801
                default:
×
1802
                        return err
×
1803
                }
1804

1805
                bs := chanBucket.Get(key)
3✔
1806
                if bs == nil {
6✔
1807
                        return ErrNoCloseTx
3✔
1808
                }
3✔
1809
                r := bytes.NewReader(bs)
3✔
1810
                return ReadElement(r, &closeTx)
3✔
1811
        }, func() {
3✔
1812
                closeTx = nil
3✔
1813
        })
3✔
1814
        if err != nil {
6✔
1815
                return nil, err
3✔
1816
        }
3✔
1817

1818
        return closeTx, nil
3✔
1819
}
1820

1821
// putChanStatus appends the given status to the channel. fs is an optional
1822
// list of closures that are given the chanBucket in order to atomically add
1823
// extra information together with the new status.
1824
func (c *OpenChannel) putChanStatus(status ChannelStatus,
1825
        fs ...func(kvdb.RwBucket) error) error {
3✔
1826

3✔
1827
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
1828
                chanBucket, err := fetchChanBucketRw(
3✔
1829
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
1830
                )
3✔
1831
                if err != nil {
4✔
1832
                        return err
1✔
1833
                }
1✔
1834

1835
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
3✔
1836
                if err != nil {
3✔
1837
                        return err
×
1838
                }
×
1839

1840
                // Add this status to the existing bitvector found in the DB.
1841
                status = channel.chanStatus | status
3✔
1842
                channel.chanStatus = status
3✔
1843

3✔
1844
                if err := putOpenChannel(chanBucket, channel); err != nil {
3✔
1845
                        return err
×
1846
                }
×
1847

1848
                for _, f := range fs {
6✔
1849
                        // Skip execution of nil closures.
3✔
1850
                        if f == nil {
6✔
1851
                                continue
3✔
1852
                        }
1853

1854
                        if err := f(chanBucket); err != nil {
3✔
1855
                                return err
×
1856
                        }
×
1857
                }
1858

1859
                return nil
3✔
1860
        }, func() {}); err != nil {
4✔
1861
                return err
1✔
1862
        }
1✔
1863

1864
        // Update the in-memory representation to keep it in sync with the DB.
1865
        c.chanStatus = status
3✔
1866

3✔
1867
        return nil
3✔
1868
}
1869

1870
func (c *OpenChannel) clearChanStatus(status ChannelStatus) error {
×
1871
        if err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
1872
                chanBucket, err := fetchChanBucketRw(
×
1873
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
×
1874
                )
×
1875
                if err != nil {
×
1876
                        return err
×
1877
                }
×
1878

1879
                channel, err := fetchOpenChannel(chanBucket, &c.FundingOutpoint)
×
1880
                if err != nil {
×
1881
                        return err
×
1882
                }
×
1883

1884
                // Unset this bit in the bitvector on disk.
1885
                status = channel.chanStatus & ^status
×
1886
                channel.chanStatus = status
×
1887

×
1888
                return putOpenChannel(chanBucket, channel)
×
1889
        }, func() {}); err != nil {
×
1890
                return err
×
1891
        }
×
1892

1893
        // Update the in-memory representation to keep it in sync with the DB.
1894
        c.chanStatus = status
×
1895

×
1896
        return nil
×
1897
}
1898

1899
// putOpenChannel serializes, and stores the current state of the channel in its
1900
// entirety.
1901
func putOpenChannel(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
3✔
1902
        // First, we'll write out all the relatively static fields, that are
3✔
1903
        // decided upon initial channel creation.
3✔
1904
        if err := putChanInfo(chanBucket, channel); err != nil {
3✔
1905
                return fmt.Errorf("unable to store chan info: %w", err)
×
1906
        }
×
1907

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

1914
        // Next, if this is a frozen channel, we'll add in the axillary
1915
        // information we need to store.
1916
        if channel.ChanType.IsFrozen() || channel.ChanType.HasLeaseExpiration() {
6✔
1917
                err := storeThawHeight(
3✔
1918
                        chanBucket, channel.ThawHeight,
3✔
1919
                )
3✔
1920
                if err != nil {
3✔
1921
                        return fmt.Errorf("unable to store thaw height: %w",
×
1922
                                err)
×
1923
                }
×
1924
        }
1925

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

1932
        return nil
3✔
1933
}
1934

1935
// fetchOpenChannel retrieves, and deserializes (including decrypting
1936
// sensitive) the complete channel currently active with the passed nodeID.
1937
func fetchOpenChannel(chanBucket kvdb.RBucket,
1938
        chanPoint *wire.OutPoint) (*OpenChannel, error) {
3✔
1939

3✔
1940
        channel := &OpenChannel{
3✔
1941
                FundingOutpoint: *chanPoint,
3✔
1942
        }
3✔
1943

3✔
1944
        // First, we'll read all the static information that changes less
3✔
1945
        // frequently from disk.
3✔
1946
        if err := fetchChanInfo(chanBucket, channel); err != nil {
3✔
1947
                return nil, fmt.Errorf("unable to fetch chan info: %w", err)
×
1948
        }
×
1949

1950
        // With the static information read, we'll now read the current
1951
        // commitment state for both sides of the channel.
1952
        if err := fetchChanCommitments(chanBucket, channel); err != nil {
3✔
1953
                return nil, fmt.Errorf("unable to fetch chan commitments: %w",
×
1954
                        err)
×
1955
        }
×
1956

1957
        // Next, if this is a frozen channel, we'll add in the axillary
1958
        // information we need to store.
1959
        if channel.ChanType.IsFrozen() || channel.ChanType.HasLeaseExpiration() {
6✔
1960
                thawHeight, err := fetchThawHeight(chanBucket)
3✔
1961
                if err != nil {
3✔
1962
                        return nil, fmt.Errorf("unable to store thaw "+
×
1963
                                "height: %v", err)
×
1964
                }
×
1965

1966
                channel.ThawHeight = thawHeight
3✔
1967
        }
1968

1969
        // Finally, we'll retrieve the current revocation state so we can
1970
        // properly
1971
        if err := fetchChanRevocationState(chanBucket, channel); err != nil {
3✔
1972
                return nil, fmt.Errorf("unable to fetch chan revocations: %w",
×
1973
                        err)
×
1974
        }
×
1975

1976
        channel.Packager = NewChannelPackager(channel.ShortChannelID)
3✔
1977

3✔
1978
        return channel, nil
3✔
1979
}
1980

1981
// SyncPending writes the contents of the channel to the database while it's in
1982
// the pending (waiting for funding confirmation) state. The IsPending flag
1983
// will be set to true. When the channel's funding transaction is confirmed,
1984
// the channel should be marked as "open" and the IsPending flag set to false.
1985
// Note that this function also creates a LinkNode relationship between this
1986
// newly created channel and a new LinkNode instance. This allows listing all
1987
// channels in the database globally, or according to the LinkNode they were
1988
// created with.
1989
//
1990
// TODO(roasbeef): addr param should eventually be an lnwire.NetAddress type
1991
// that includes service bits.
1992
func (c *OpenChannel) SyncPending(addr net.Addr, pendingHeight uint32) error {
3✔
1993
        c.Lock()
3✔
1994
        defer c.Unlock()
3✔
1995

3✔
1996
        c.FundingBroadcastHeight = pendingHeight
3✔
1997

3✔
1998
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
1999
                return syncNewChannel(tx, c, []net.Addr{addr})
3✔
2000
        }, func() {})
6✔
2001
}
2002

2003
// syncNewChannel will write the passed channel to disk, and also create a
2004
// LinkNode (if needed) for the channel peer.
2005
func syncNewChannel(tx kvdb.RwTx, c *OpenChannel, addrs []net.Addr) error {
3✔
2006
        // First, sync all the persistent channel state to disk.
3✔
2007
        if err := c.fullSync(tx); err != nil {
6✔
2008
                return err
3✔
2009
        }
3✔
2010

2011
        nodeInfoBucket, err := tx.CreateTopLevelBucket(nodeInfoBucket)
3✔
2012
        if err != nil {
3✔
2013
                return err
×
2014
        }
×
2015

2016
        // If a LinkNode for this identity public key already exists,
2017
        // then we can exit early.
2018
        nodePub := c.IdentityPub.SerializeCompressed()
3✔
2019
        if nodeInfoBucket.Get(nodePub) != nil {
6✔
2020
                return nil
3✔
2021
        }
3✔
2022

2023
        // Next, we need to establish a (possibly) new LinkNode relationship
2024
        // for this channel. The LinkNode metadata contains reachability,
2025
        // up-time, and service bits related information.
2026
        linkNode := NewLinkNode(
3✔
2027
                &LinkNodeDB{backend: c.Db.backend},
3✔
2028
                wire.MainNet, c.IdentityPub, addrs...,
3✔
2029
        )
3✔
2030

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

3✔
2033
        return putLinkNode(nodeInfoBucket, linkNode)
3✔
2034
}
2035

2036
// UpdateCommitment updates the local commitment state. It locks in the pending
2037
// local updates that were received by us from the remote party. The commitment
2038
// state completely describes the balance state at this point in the commitment
2039
// chain. In addition to that, it persists all the remote log updates that we
2040
// have acked, but not signed a remote commitment for yet. These need to be
2041
// persisted to be able to produce a valid commit signature if a restart would
2042
// occur. This method its to be called when we revoke our prior commitment
2043
// state.
2044
//
2045
// A map is returned of all the htlc resolutions that were locked in this
2046
// commitment. Keys correspond to htlc indices and values indicate whether the
2047
// htlc was settled or failed.
2048
func (c *OpenChannel) UpdateCommitment(newCommitment *ChannelCommitment,
2049
        unsignedAckedUpdates []LogUpdate) (map[uint64]bool, error) {
3✔
2050

3✔
2051
        c.Lock()
3✔
2052
        defer c.Unlock()
3✔
2053

3✔
2054
        // If this is a restored channel, then we want to avoid mutating the
3✔
2055
        // state as all, as it's impossible to do so in a protocol compliant
3✔
2056
        // manner.
3✔
2057
        if c.hasChanStatus(ChanStatusRestored) {
3✔
2058
                return nil, ErrNoRestoredChannelMutation
×
2059
        }
×
2060

2061
        var finalHtlcs = make(map[uint64]bool)
3✔
2062

3✔
2063
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
2064
                chanBucket, err := fetchChanBucketRw(
3✔
2065
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
2066
                )
3✔
2067
                if err != nil {
3✔
2068
                        return err
×
2069
                }
×
2070

2071
                // If the channel is marked as borked, then for safety reasons,
2072
                // we shouldn't attempt any further updates.
2073
                isBorked, err := c.isBorked(chanBucket)
3✔
2074
                if err != nil {
3✔
2075
                        return err
×
2076
                }
×
2077
                if isBorked {
3✔
2078
                        return ErrChanBorked
×
2079
                }
×
2080

2081
                if err = putChanInfo(chanBucket, c); err != nil {
3✔
2082
                        return fmt.Errorf("unable to store chan info: %w", err)
×
2083
                }
×
2084

2085
                // With the proper bucket fetched, we'll now write the latest
2086
                // commitment state to disk for the target party.
2087
                err = putChanCommitment(
3✔
2088
                        chanBucket, newCommitment, true,
3✔
2089
                )
3✔
2090
                if err != nil {
3✔
2091
                        return fmt.Errorf("unable to store chan "+
×
2092
                                "revocations: %v", err)
×
2093
                }
×
2094

2095
                // Persist unsigned but acked remote updates that need to be
2096
                // restored after a restart.
2097
                var b bytes.Buffer
3✔
2098
                err = serializeLogUpdates(&b, unsignedAckedUpdates)
3✔
2099
                if err != nil {
3✔
2100
                        return err
×
2101
                }
×
2102

2103
                err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes())
3✔
2104
                if err != nil {
3✔
2105
                        return fmt.Errorf("unable to store dangline remote "+
×
2106
                                "updates: %v", err)
×
2107
                }
×
2108

2109
                // Since we have just sent the counterparty a revocation, store true
2110
                // under lastWasRevokeKey.
2111
                var b2 bytes.Buffer
3✔
2112
                if err := WriteElements(&b2, true); err != nil {
3✔
2113
                        return err
×
2114
                }
×
2115

2116
                if err := chanBucket.Put(lastWasRevokeKey, b2.Bytes()); err != nil {
3✔
2117
                        return err
×
2118
                }
×
2119

2120
                // Persist the remote unsigned local updates that are not included
2121
                // in our new commitment.
2122
                updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
3✔
2123
                if updateBytes == nil {
6✔
2124
                        return nil
3✔
2125
                }
3✔
2126

2127
                r := bytes.NewReader(updateBytes)
3✔
2128
                updates, err := deserializeLogUpdates(r)
3✔
2129
                if err != nil {
3✔
2130
                        return err
×
2131
                }
×
2132

2133
                // Get the bucket where settled htlcs are recorded if the user
2134
                // opted in to storing this information.
2135
                var finalHtlcsBucket kvdb.RwBucket
3✔
2136
                if c.Db.parent.storeFinalHtlcResolutions {
6✔
2137
                        bucket, err := fetchFinalHtlcsBucketRw(
3✔
2138
                                tx, c.ShortChannelID,
3✔
2139
                        )
3✔
2140
                        if err != nil {
3✔
2141
                                return err
×
2142
                        }
×
2143

2144
                        finalHtlcsBucket = bucket
3✔
2145
                }
2146

2147
                var unsignedUpdates []LogUpdate
3✔
2148
                for _, upd := range updates {
6✔
2149
                        // Gather updates that are not on our local commitment.
3✔
2150
                        if upd.LogIndex >= newCommitment.LocalLogIndex {
3✔
2151
                                unsignedUpdates = append(unsignedUpdates, upd)
×
2152

×
2153
                                continue
×
2154
                        }
2155

2156
                        // The update was locked in. If the update was a
2157
                        // resolution, then store it in the database.
2158
                        err := processFinalHtlc(
3✔
2159
                                finalHtlcsBucket, upd, finalHtlcs,
3✔
2160
                        )
3✔
2161
                        if err != nil {
3✔
2162
                                return err
×
2163
                        }
×
2164
                }
2165

2166
                var b3 bytes.Buffer
3✔
2167
                err = serializeLogUpdates(&b3, unsignedUpdates)
3✔
2168
                if err != nil {
3✔
2169
                        return fmt.Errorf("unable to serialize log updates: %w",
×
2170
                                err)
×
2171
                }
×
2172

2173
                err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b3.Bytes())
3✔
2174
                if err != nil {
3✔
2175
                        return fmt.Errorf("unable to restore chanbucket: %w",
×
2176
                                err)
×
2177
                }
×
2178

2179
                return nil
3✔
2180
        }, func() {
3✔
2181
                finalHtlcs = make(map[uint64]bool)
3✔
2182
        })
3✔
2183
        if err != nil {
3✔
2184
                return nil, err
×
2185
        }
×
2186

2187
        c.LocalCommitment = *newCommitment
3✔
2188

3✔
2189
        return finalHtlcs, nil
3✔
2190
}
2191

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

3✔
2197
        var (
3✔
2198
                settled bool
3✔
2199
                id      uint64
3✔
2200
        )
3✔
2201

3✔
2202
        switch msg := upd.UpdateMsg.(type) {
3✔
2203
        case *lnwire.UpdateFulfillHTLC:
3✔
2204
                settled = true
3✔
2205
                id = msg.ID
3✔
2206

2207
        case *lnwire.UpdateFailHTLC:
3✔
2208
                settled = false
3✔
2209
                id = msg.ID
3✔
2210

2211
        case *lnwire.UpdateFailMalformedHTLC:
3✔
2212
                settled = false
3✔
2213
                id = msg.ID
3✔
2214

2215
        default:
×
2216
                return nil
×
2217
        }
2218

2219
        // Store the final resolution in the database if a bucket is provided.
2220
        if finalHtlcsBucket != nil {
6✔
2221
                err := putFinalHtlc(
3✔
2222
                        finalHtlcsBucket, id,
3✔
2223
                        FinalHtlcInfo{
3✔
2224
                                Settled:  settled,
3✔
2225
                                Offchain: true,
3✔
2226
                        },
3✔
2227
                )
3✔
2228
                if err != nil {
3✔
2229
                        return err
×
2230
                }
×
2231
        }
2232

2233
        finalHtlcs[id] = settled
3✔
2234

3✔
2235
        return nil
3✔
2236
}
2237

2238
// ActiveHtlcs returns a slice of HTLC's which are currently active on *both*
2239
// commitment transactions.
2240
func (c *OpenChannel) ActiveHtlcs() []HTLC {
3✔
2241
        c.RLock()
3✔
2242
        defer c.RUnlock()
3✔
2243

3✔
2244
        // We'll only return HTLC's that are locked into *both* commitment
3✔
2245
        // transactions. So we'll iterate through their set of HTLC's to note
3✔
2246
        // which ones are present on their commitment.
3✔
2247
        remoteHtlcs := make(map[[32]byte]struct{})
3✔
2248
        for _, htlc := range c.RemoteCommitment.Htlcs {
6✔
2249
                log.Tracef("RemoteCommitment has htlc: id=%v, update=%v "+
3✔
2250
                        "incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
3✔
2251
                        htlc.Incoming)
3✔
2252

3✔
2253
                onionHash := sha256.Sum256(htlc.OnionBlob[:])
3✔
2254
                remoteHtlcs[onionHash] = struct{}{}
3✔
2255
        }
3✔
2256

2257
        // Now that we know which HTLC's they have, we'll only mark the HTLC's
2258
        // as active if *we* know them as well.
2259
        activeHtlcs := make([]HTLC, 0, len(remoteHtlcs))
3✔
2260
        for _, htlc := range c.LocalCommitment.Htlcs {
6✔
2261
                log.Tracef("LocalCommitment has htlc: id=%v, update=%v "+
3✔
2262
                        "incoming=%v", htlc.HtlcIndex, htlc.LogIndex,
3✔
2263
                        htlc.Incoming)
3✔
2264

3✔
2265
                onionHash := sha256.Sum256(htlc.OnionBlob[:])
3✔
2266
                if _, ok := remoteHtlcs[onionHash]; !ok {
6✔
2267
                        log.Tracef("Skipped htlc due to onion mismatched: "+
3✔
2268
                                "id=%v, update=%v incoming=%v",
3✔
2269
                                htlc.HtlcIndex, htlc.LogIndex, htlc.Incoming)
3✔
2270

3✔
2271
                        continue
3✔
2272
                }
2273

2274
                activeHtlcs = append(activeHtlcs, htlc)
3✔
2275
        }
2276

2277
        return activeHtlcs
3✔
2278
}
2279

2280
// HTLC is the on-disk representation of a hash time-locked contract. HTLCs are
2281
// contained within ChannelDeltas which encode the current state of the
2282
// commitment between state updates.
2283
//
2284
// TODO(roasbeef): save space by using smaller ints at tail end?
2285
type HTLC struct {
2286
        // TODO(yy): can embed an HTLCEntry here.
2287

2288
        // Signature is the signature for the second level covenant transaction
2289
        // for this HTLC. The second level transaction is a timeout tx in the
2290
        // case that this is an outgoing HTLC, and a success tx in the case
2291
        // that this is an incoming HTLC.
2292
        //
2293
        // TODO(roasbeef): make [64]byte instead?
2294
        Signature []byte
2295

2296
        // RHash is the payment hash of the HTLC.
2297
        RHash [32]byte
2298

2299
        // Amt is the amount of milli-satoshis this HTLC escrows.
2300
        Amt lnwire.MilliSatoshi
2301

2302
        // RefundTimeout is the absolute timeout on the HTLC that the sender
2303
        // must wait before reclaiming the funds in limbo.
2304
        RefundTimeout uint32
2305

2306
        // OutputIndex is the output index for this particular HTLC output
2307
        // within the commitment transaction.
2308
        OutputIndex int32
2309

2310
        // Incoming denotes whether we're the receiver or the sender of this
2311
        // HTLC.
2312
        Incoming bool
2313

2314
        // OnionBlob is an opaque blob which is used to complete multi-hop
2315
        // routing.
2316
        OnionBlob [lnwire.OnionPacketSize]byte
2317

2318
        // HtlcIndex is the HTLC counter index of this active, outstanding
2319
        // HTLC. This differs from the LogIndex, as the HtlcIndex is only
2320
        // incremented for each offered HTLC, while they LogIndex is
2321
        // incremented for each update (includes settle+fail).
2322
        HtlcIndex uint64
2323

2324
        // LogIndex is the cumulative log index of this HTLC. This differs
2325
        // from the HtlcIndex as this will be incremented for each new log
2326
        // update added.
2327
        LogIndex uint64
2328

2329
        // ExtraData contains any additional information that was transmitted
2330
        // with the HTLC via TLVs. This data *must* already be encoded as a
2331
        // TLV stream, and may be empty. The length of this data is naturally
2332
        // limited by the space available to TLVs in update_add_htlc:
2333
        // = 65535 bytes (bolt 8 maximum message size):
2334
        // - 2 bytes (bolt 1 message_type)
2335
        // - 32 bytes (channel_id)
2336
        // - 8 bytes (id)
2337
        // - 8 bytes (amount_msat)
2338
        // - 32 bytes (payment_hash)
2339
        // - 4 bytes (cltv_expiry)
2340
        // - 1366 bytes (onion_routing_packet)
2341
        // = 64083 bytes maximum possible TLV stream
2342
        //
2343
        // Note that this extra data is stored inline with the OnionBlob for
2344
        // legacy reasons, see serialization/deserialization functions for
2345
        // detail.
2346
        ExtraData lnwire.ExtraOpaqueData
2347

2348
        // BlindingPoint is an optional blinding point included with the HTLC.
2349
        //
2350
        // Note: this field is not a part of on-disk representation of the
2351
        // HTLC. It is stored in the ExtraData field, which is used to store
2352
        // a TLV stream of additional information associated with the HTLC.
2353
        BlindingPoint lnwire.BlindingPointRecord
2354
}
2355

2356
// serializeExtraData encodes a TLV stream of extra data to be stored with a
2357
// HTLC. It uses the update_add_htlc TLV types, because this is where extra
2358
// data is passed with a HTLC. At present blinding points are the only extra
2359
// data that we will store, and the function is a no-op if a nil blinding
2360
// point is provided.
2361
//
2362
// This function MUST be called to persist all HTLC values when they are
2363
// serialized.
2364
func (h *HTLC) serializeExtraData() error {
3✔
2365
        var records []tlv.RecordProducer
3✔
2366
        h.BlindingPoint.WhenSome(func(b tlv.RecordT[lnwire.BlindingPointTlvType,
3✔
2367
                *btcec.PublicKey]) {
6✔
2368

3✔
2369
                records = append(records, &b)
3✔
2370
        })
3✔
2371

2372
        return h.ExtraData.PackRecords(records...)
3✔
2373
}
2374

2375
// deserializeExtraData extracts TLVs from the extra data persisted for the
2376
// htlc and populates values in the struct accordingly.
2377
//
2378
// This function MUST be called to populate the struct properly when HTLCs
2379
// are deserialized.
2380
func (h *HTLC) deserializeExtraData() error {
3✔
2381
        if len(h.ExtraData) == 0 {
6✔
2382
                return nil
3✔
2383
        }
3✔
2384

2385
        blindingPoint := h.BlindingPoint.Zero()
3✔
2386
        tlvMap, err := h.ExtraData.ExtractRecords(&blindingPoint)
3✔
2387
        if err != nil {
3✔
2388
                return err
×
2389
        }
×
2390

2391
        if val, ok := tlvMap[h.BlindingPoint.TlvType()]; ok && val == nil {
6✔
2392
                h.BlindingPoint = tlv.SomeRecordT(blindingPoint)
3✔
2393
        }
3✔
2394

2395
        return nil
3✔
2396
}
2397

2398
// SerializeHtlcs writes out the passed set of HTLC's into the passed writer
2399
// using the current default on-disk serialization format.
2400
//
2401
// This inline serialization has been extended to allow storage of extra data
2402
// associated with a HTLC in the following way:
2403
//   - The known-length onion blob (1366 bytes) is serialized as var bytes in
2404
//     WriteElements (ie, the length 1366 was written, followed by the 1366
2405
//     onion bytes).
2406
//   - To include extra data, we append any extra data present to this one
2407
//     variable length of data. Since we know that the onion is strictly 1366
2408
//     bytes, any length after that should be considered to be extra data.
2409
//
2410
// NOTE: This API is NOT stable, the on-disk format will likely change in the
2411
// future.
2412
func SerializeHtlcs(b io.Writer, htlcs ...HTLC) error {
3✔
2413
        numHtlcs := uint16(len(htlcs))
3✔
2414
        if err := WriteElement(b, numHtlcs); err != nil {
3✔
2415
                return err
×
2416
        }
×
2417

2418
        for _, htlc := range htlcs {
6✔
2419
                // Populate TLV stream for any additional fields contained
3✔
2420
                // in the TLV.
3✔
2421
                if err := htlc.serializeExtraData(); err != nil {
3✔
2422
                        return err
×
2423
                }
×
2424

2425
                // The onion blob and hltc data are stored as a single var
2426
                // bytes blob.
2427
                onionAndExtraData := make(
3✔
2428
                        []byte, lnwire.OnionPacketSize+len(htlc.ExtraData),
3✔
2429
                )
3✔
2430
                copy(onionAndExtraData, htlc.OnionBlob[:])
3✔
2431
                copy(onionAndExtraData[lnwire.OnionPacketSize:], htlc.ExtraData)
3✔
2432

3✔
2433
                if err := WriteElements(b,
3✔
2434
                        htlc.Signature, htlc.RHash, htlc.Amt, htlc.RefundTimeout,
3✔
2435
                        htlc.OutputIndex, htlc.Incoming, onionAndExtraData,
3✔
2436
                        htlc.HtlcIndex, htlc.LogIndex,
3✔
2437
                ); err != nil {
3✔
2438
                        return err
×
2439
                }
×
2440
        }
2441

2442
        return nil
3✔
2443
}
2444

2445
// DeserializeHtlcs attempts to read out a slice of HTLC's from the passed
2446
// io.Reader. The bytes within the passed reader MUST have been previously
2447
// written to using the SerializeHtlcs function.
2448
//
2449
// This inline deserialization has been extended to allow storage of extra data
2450
// associated with a HTLC in the following way:
2451
//   - The known-length onion blob (1366 bytes) and any additional data present
2452
//     are read out as a single blob of variable byte data.
2453
//   - They are stored like this to take advantage of the variable space
2454
//     available for extension without migration (see SerializeHtlcs).
2455
//   - The first 1366 bytes are interpreted as the onion blob, and any remaining
2456
//     bytes as extra HTLC data.
2457
//   - This extra HTLC data is expected to be serialized as a TLV stream, and
2458
//     its parsing is left to higher layers.
2459
//
2460
// NOTE: This API is NOT stable, the on-disk format will likely change in the
2461
// future.
2462
func DeserializeHtlcs(r io.Reader) ([]HTLC, error) {
3✔
2463
        var numHtlcs uint16
3✔
2464
        if err := ReadElement(r, &numHtlcs); err != nil {
3✔
2465
                return nil, err
×
2466
        }
×
2467

2468
        var htlcs []HTLC
3✔
2469
        if numHtlcs == 0 {
6✔
2470
                return htlcs, nil
3✔
2471
        }
3✔
2472

2473
        htlcs = make([]HTLC, numHtlcs)
3✔
2474
        for i := uint16(0); i < numHtlcs; i++ {
6✔
2475
                var onionAndExtraData []byte
3✔
2476
                if err := ReadElements(r,
3✔
2477
                        &htlcs[i].Signature, &htlcs[i].RHash, &htlcs[i].Amt,
3✔
2478
                        &htlcs[i].RefundTimeout, &htlcs[i].OutputIndex,
3✔
2479
                        &htlcs[i].Incoming, &onionAndExtraData,
3✔
2480
                        &htlcs[i].HtlcIndex, &htlcs[i].LogIndex,
3✔
2481
                ); err != nil {
3✔
2482
                        return htlcs, err
×
2483
                }
×
2484

2485
                // Sanity check that we have at least the onion blob size we
2486
                // expect.
2487
                if len(onionAndExtraData) < lnwire.OnionPacketSize {
3✔
2488
                        return nil, ErrOnionBlobLength
×
2489
                }
×
2490

2491
                // First OnionPacketSize bytes are our fixed length onion
2492
                // packet.
2493
                copy(
3✔
2494
                        htlcs[i].OnionBlob[:],
3✔
2495
                        onionAndExtraData[0:lnwire.OnionPacketSize],
3✔
2496
                )
3✔
2497

3✔
2498
                // Any additional bytes belong to extra data. ExtraDataLen
3✔
2499
                // will be >= 0, because we know that we always have a fixed
3✔
2500
                // length onion packet.
3✔
2501
                extraDataLen := len(onionAndExtraData) - lnwire.OnionPacketSize
3✔
2502
                if extraDataLen > 0 {
6✔
2503
                        htlcs[i].ExtraData = make([]byte, extraDataLen)
3✔
2504

3✔
2505
                        copy(
3✔
2506
                                htlcs[i].ExtraData,
3✔
2507
                                onionAndExtraData[lnwire.OnionPacketSize:],
3✔
2508
                        )
3✔
2509
                }
3✔
2510

2511
                // Finally, deserialize any TLVs contained in that extra data
2512
                // if they are present.
2513
                if err := htlcs[i].deserializeExtraData(); err != nil {
3✔
2514
                        return nil, err
×
2515
                }
×
2516
        }
2517

2518
        return htlcs, nil
3✔
2519
}
2520

2521
// Copy returns a full copy of the target HTLC.
2522
func (h *HTLC) Copy() HTLC {
3✔
2523
        clone := HTLC{
3✔
2524
                Incoming:      h.Incoming,
3✔
2525
                Amt:           h.Amt,
3✔
2526
                RefundTimeout: h.RefundTimeout,
3✔
2527
                OutputIndex:   h.OutputIndex,
3✔
2528
        }
3✔
2529
        copy(clone.Signature[:], h.Signature)
3✔
2530
        copy(clone.RHash[:], h.RHash[:])
3✔
2531
        copy(clone.ExtraData, h.ExtraData)
3✔
2532

3✔
2533
        return clone
3✔
2534
}
3✔
2535

2536
// LogUpdate represents a pending update to the remote commitment chain. The
2537
// log update may be an add, fail, or settle entry. We maintain this data in
2538
// order to be able to properly retransmit our proposed state if necessary.
2539
type LogUpdate struct {
2540
        // LogIndex is the log index of this proposed commitment update entry.
2541
        LogIndex uint64
2542

2543
        // UpdateMsg is the update message that was included within our
2544
        // local update log. The LogIndex value denotes the log index of this
2545
        // update which will be used when restoring our local update log if
2546
        // we're left with a dangling update on restart.
2547
        UpdateMsg lnwire.Message
2548
}
2549

2550
// serializeLogUpdate writes a log update to the provided io.Writer.
2551
func serializeLogUpdate(w io.Writer, l *LogUpdate) error {
3✔
2552
        return WriteElements(w, l.LogIndex, l.UpdateMsg)
3✔
2553
}
3✔
2554

2555
// deserializeLogUpdate reads a log update from the provided io.Reader.
2556
func deserializeLogUpdate(r io.Reader) (*LogUpdate, error) {
3✔
2557
        l := &LogUpdate{}
3✔
2558
        if err := ReadElements(r, &l.LogIndex, &l.UpdateMsg); err != nil {
3✔
2559
                return nil, err
×
2560
        }
×
2561

2562
        return l, nil
3✔
2563
}
2564

2565
// CommitDiff represents the delta needed to apply the state transition between
2566
// two subsequent commitment states. Given state N and state N+1, one is able
2567
// to apply the set of messages contained within the CommitDiff to N to arrive
2568
// at state N+1. Each time a new commitment is extended, we'll write a new
2569
// commitment (along with the full commitment state) to disk so we can
2570
// re-transmit the state in the case of a connection loss or message drop.
2571
type CommitDiff struct {
2572
        // ChannelCommitment is the full commitment state that one would arrive
2573
        // at by applying the set of messages contained in the UpdateDiff to
2574
        // the prior accepted commitment.
2575
        Commitment ChannelCommitment
2576

2577
        // LogUpdates is the set of messages sent prior to the commitment state
2578
        // transition in question. Upon reconnection, if we detect that they
2579
        // don't have the commitment, then we re-send this along with the
2580
        // proper signature.
2581
        LogUpdates []LogUpdate
2582

2583
        // CommitSig is the exact CommitSig message that should be sent after
2584
        // the set of LogUpdates above has been retransmitted. The signatures
2585
        // within this message should properly cover the new commitment state
2586
        // and also the HTLC's within the new commitment state.
2587
        CommitSig *lnwire.CommitSig
2588

2589
        // OpenedCircuitKeys is a set of unique identifiers for any downstream
2590
        // Add packets included in this commitment txn. After a restart, this
2591
        // set of htlcs is acked from the link's incoming mailbox to ensure
2592
        // there isn't an attempt to re-add them to this commitment txn.
2593
        OpenedCircuitKeys []models.CircuitKey
2594

2595
        // ClosedCircuitKeys records the unique identifiers for any settle/fail
2596
        // packets that were resolved by this commitment txn. After a restart,
2597
        // this is used to ensure those circuits are removed from the circuit
2598
        // map, and the downstream packets in the link's mailbox are removed.
2599
        ClosedCircuitKeys []models.CircuitKey
2600

2601
        // AddAcks specifies the locations (commit height, pkg index) of any
2602
        // Adds that were failed/settled in this commit diff. This will ack
2603
        // entries in *this* channel's forwarding packages.
2604
        //
2605
        // NOTE: This value is not serialized, it is used to atomically mark the
2606
        // resolution of adds, such that they will not be reprocessed after a
2607
        // restart.
2608
        AddAcks []AddRef
2609

2610
        // SettleFailAcks specifies the locations (chan id, commit height, pkg
2611
        // index) of any Settles or Fails that were locked into this commit
2612
        // diff, and originate from *another* channel, i.e. the outgoing link.
2613
        //
2614
        // NOTE: This value is not serialized, it is used to atomically acks
2615
        // settles and fails from the forwarding packages of other channels,
2616
        // such that they will not be reforwarded internally after a restart.
2617
        SettleFailAcks []SettleFailRef
2618
}
2619

2620
// serializeLogUpdates serializes provided list of updates to a stream.
2621
func serializeLogUpdates(w io.Writer, logUpdates []LogUpdate) error {
3✔
2622
        numUpdates := uint16(len(logUpdates))
3✔
2623
        if err := binary.Write(w, byteOrder, numUpdates); err != nil {
3✔
2624
                return err
×
2625
        }
×
2626

2627
        for _, diff := range logUpdates {
6✔
2628
                err := WriteElements(w, diff.LogIndex, diff.UpdateMsg)
3✔
2629
                if err != nil {
3✔
2630
                        return err
×
2631
                }
×
2632
        }
2633

2634
        return nil
3✔
2635
}
2636

2637
// deserializeLogUpdates deserializes a list of updates from a stream.
2638
func deserializeLogUpdates(r io.Reader) ([]LogUpdate, error) {
3✔
2639
        var numUpdates uint16
3✔
2640
        if err := binary.Read(r, byteOrder, &numUpdates); err != nil {
3✔
2641
                return nil, err
×
2642
        }
×
2643

2644
        logUpdates := make([]LogUpdate, numUpdates)
3✔
2645
        for i := 0; i < int(numUpdates); i++ {
6✔
2646
                err := ReadElements(r,
3✔
2647
                        &logUpdates[i].LogIndex, &logUpdates[i].UpdateMsg,
3✔
2648
                )
3✔
2649
                if err != nil {
3✔
2650
                        return nil, err
×
2651
                }
×
2652
        }
2653
        return logUpdates, nil
3✔
2654
}
2655

2656
func serializeCommitDiff(w io.Writer, diff *CommitDiff) error { // nolint: dupl
3✔
2657
        if err := serializeChanCommit(w, &diff.Commitment); err != nil {
3✔
2658
                return err
×
2659
        }
×
2660

2661
        if err := WriteElements(w, diff.CommitSig); err != nil {
3✔
2662
                return err
×
2663
        }
×
2664

2665
        if err := serializeLogUpdates(w, diff.LogUpdates); err != nil {
3✔
2666
                return err
×
2667
        }
×
2668

2669
        numOpenRefs := uint16(len(diff.OpenedCircuitKeys))
3✔
2670
        if err := binary.Write(w, byteOrder, numOpenRefs); err != nil {
3✔
2671
                return err
×
2672
        }
×
2673

2674
        for _, openRef := range diff.OpenedCircuitKeys {
6✔
2675
                err := WriteElements(w, openRef.ChanID, openRef.HtlcID)
3✔
2676
                if err != nil {
3✔
2677
                        return err
×
2678
                }
×
2679
        }
2680

2681
        numClosedRefs := uint16(len(diff.ClosedCircuitKeys))
3✔
2682
        if err := binary.Write(w, byteOrder, numClosedRefs); err != nil {
3✔
2683
                return err
×
2684
        }
×
2685

2686
        for _, closedRef := range diff.ClosedCircuitKeys {
6✔
2687
                err := WriteElements(w, closedRef.ChanID, closedRef.HtlcID)
3✔
2688
                if err != nil {
3✔
2689
                        return err
×
2690
                }
×
2691
        }
2692

2693
        return nil
3✔
2694
}
2695

2696
func deserializeCommitDiff(r io.Reader) (*CommitDiff, error) {
3✔
2697
        var (
3✔
2698
                d   CommitDiff
3✔
2699
                err error
3✔
2700
        )
3✔
2701

3✔
2702
        d.Commitment, err = deserializeChanCommit(r)
3✔
2703
        if err != nil {
3✔
2704
                return nil, err
×
2705
        }
×
2706

2707
        var msg lnwire.Message
3✔
2708
        if err := ReadElements(r, &msg); err != nil {
3✔
2709
                return nil, err
×
2710
        }
×
2711
        commitSig, ok := msg.(*lnwire.CommitSig)
3✔
2712
        if !ok {
3✔
2713
                return nil, fmt.Errorf("expected lnwire.CommitSig, instead "+
×
2714
                        "read: %T", msg)
×
2715
        }
×
2716
        d.CommitSig = commitSig
3✔
2717

3✔
2718
        d.LogUpdates, err = deserializeLogUpdates(r)
3✔
2719
        if err != nil {
3✔
2720
                return nil, err
×
2721
        }
×
2722

2723
        var numOpenRefs uint16
3✔
2724
        if err := binary.Read(r, byteOrder, &numOpenRefs); err != nil {
3✔
2725
                return nil, err
×
2726
        }
×
2727

2728
        d.OpenedCircuitKeys = make([]models.CircuitKey, numOpenRefs)
3✔
2729
        for i := 0; i < int(numOpenRefs); i++ {
6✔
2730
                err := ReadElements(r,
3✔
2731
                        &d.OpenedCircuitKeys[i].ChanID,
3✔
2732
                        &d.OpenedCircuitKeys[i].HtlcID)
3✔
2733
                if err != nil {
3✔
2734
                        return nil, err
×
2735
                }
×
2736
        }
2737

2738
        var numClosedRefs uint16
3✔
2739
        if err := binary.Read(r, byteOrder, &numClosedRefs); err != nil {
3✔
2740
                return nil, err
×
2741
        }
×
2742

2743
        d.ClosedCircuitKeys = make([]models.CircuitKey, numClosedRefs)
3✔
2744
        for i := 0; i < int(numClosedRefs); i++ {
6✔
2745
                err := ReadElements(r,
3✔
2746
                        &d.ClosedCircuitKeys[i].ChanID,
3✔
2747
                        &d.ClosedCircuitKeys[i].HtlcID)
3✔
2748
                if err != nil {
3✔
2749
                        return nil, err
×
2750
                }
×
2751
        }
2752

2753
        return &d, nil
3✔
2754
}
2755

2756
// AppendRemoteCommitChain appends a new CommitDiff to the end of the
2757
// commitment chain for the remote party. This method is to be used once we
2758
// have prepared a new commitment state for the remote party, but before we
2759
// transmit it to the remote party. The contents of the argument should be
2760
// sufficient to retransmit the updates and signature needed to reconstruct the
2761
// state in full, in the case that we need to retransmit.
2762
func (c *OpenChannel) AppendRemoteCommitChain(diff *CommitDiff) error {
3✔
2763
        c.Lock()
3✔
2764
        defer c.Unlock()
3✔
2765

3✔
2766
        // If this is a restored channel, then we want to avoid mutating the
3✔
2767
        // state at all, as it's impossible to do so in a protocol compliant
3✔
2768
        // manner.
3✔
2769
        if c.hasChanStatus(ChanStatusRestored) {
3✔
2770
                return ErrNoRestoredChannelMutation
×
2771
        }
×
2772

2773
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
2774
                // First, we'll grab the writable bucket where this channel's
3✔
2775
                // data resides.
3✔
2776
                chanBucket, err := fetchChanBucketRw(
3✔
2777
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
2778
                )
3✔
2779
                if err != nil {
3✔
2780
                        return err
×
2781
                }
×
2782

2783
                // If the channel is marked as borked, then for safety reasons,
2784
                // we shouldn't attempt any further updates.
2785
                isBorked, err := c.isBorked(chanBucket)
3✔
2786
                if err != nil {
3✔
2787
                        return err
×
2788
                }
×
2789
                if isBorked {
3✔
2790
                        return ErrChanBorked
×
2791
                }
×
2792

2793
                // Any outgoing settles and fails necessarily have a
2794
                // corresponding adds in this channel's forwarding packages.
2795
                // Mark all of these as being fully processed in our forwarding
2796
                // package, which prevents us from reprocessing them after
2797
                // startup.
2798
                err = c.Packager.AckAddHtlcs(tx, diff.AddAcks...)
3✔
2799
                if err != nil {
3✔
2800
                        return err
×
2801
                }
×
2802

2803
                // Additionally, we ack from any fails or settles that are
2804
                // persisted in another channel's forwarding package. This
2805
                // prevents the same fails and settles from being retransmitted
2806
                // after restarts. The actual fail or settle we need to
2807
                // propagate to the remote party is now in the commit diff.
2808
                err = c.Packager.AckSettleFails(tx, diff.SettleFailAcks...)
3✔
2809
                if err != nil {
3✔
2810
                        return err
×
2811
                }
×
2812

2813
                // We are sending a commitment signature so lastWasRevokeKey should
2814
                // store false.
2815
                var b bytes.Buffer
3✔
2816
                if err := WriteElements(&b, false); err != nil {
3✔
2817
                        return err
×
2818
                }
×
2819
                if err := chanBucket.Put(lastWasRevokeKey, b.Bytes()); err != nil {
3✔
2820
                        return err
×
2821
                }
×
2822

2823
                // TODO(roasbeef): use seqno to derive key for later LCP
2824

2825
                // With the bucket retrieved, we'll now serialize the commit
2826
                // diff itself, and write it to disk.
2827
                var b2 bytes.Buffer
3✔
2828
                if err := serializeCommitDiff(&b2, diff); err != nil {
3✔
2829
                        return err
×
2830
                }
×
2831
                return chanBucket.Put(commitDiffKey, b2.Bytes())
3✔
2832
        }, func() {})
3✔
2833
}
2834

2835
// RemoteCommitChainTip returns the "tip" of the current remote commitment
2836
// chain. This value will be non-nil iff, we've created a new commitment for
2837
// the remote party that they haven't yet ACK'd. In this case, their commitment
2838
// chain will have a length of two: their current unrevoked commitment, and
2839
// this new pending commitment. Once they revoked their prior state, we'll swap
2840
// these pointers, causing the tip and the tail to point to the same entry.
2841
func (c *OpenChannel) RemoteCommitChainTip() (*CommitDiff, error) {
3✔
2842
        var cd *CommitDiff
3✔
2843
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
2844
                chanBucket, err := fetchChanBucket(
3✔
2845
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
2846
                )
3✔
2847
                switch err {
3✔
2848
                case nil:
3✔
2849
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
2✔
2850
                        return ErrNoPendingCommit
2✔
2851
                default:
×
2852
                        return err
×
2853
                }
2854

2855
                tipBytes := chanBucket.Get(commitDiffKey)
3✔
2856
                if tipBytes == nil {
6✔
2857
                        return ErrNoPendingCommit
3✔
2858
                }
3✔
2859

2860
                tipReader := bytes.NewReader(tipBytes)
3✔
2861
                dcd, err := deserializeCommitDiff(tipReader)
3✔
2862
                if err != nil {
3✔
2863
                        return err
×
2864
                }
×
2865

2866
                cd = dcd
3✔
2867
                return nil
3✔
2868
        }, func() {
3✔
2869
                cd = nil
3✔
2870
        })
3✔
2871
        if err != nil {
6✔
2872
                return nil, err
3✔
2873
        }
3✔
2874

2875
        return cd, err
3✔
2876
}
2877

2878
// UnsignedAckedUpdates retrieves the persisted unsigned acked remote log
2879
// updates that still need to be signed for.
2880
func (c *OpenChannel) UnsignedAckedUpdates() ([]LogUpdate, error) {
3✔
2881
        var updates []LogUpdate
3✔
2882
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
2883
                chanBucket, err := fetchChanBucket(
3✔
2884
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
2885
                )
3✔
2886
                switch err {
3✔
2887
                case nil:
3✔
2888
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
2✔
2889
                        return nil
2✔
2890
                default:
×
2891
                        return err
×
2892
                }
2893

2894
                updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
3✔
2895
                if updateBytes == nil {
6✔
2896
                        return nil
3✔
2897
                }
3✔
2898

2899
                r := bytes.NewReader(updateBytes)
3✔
2900
                updates, err = deserializeLogUpdates(r)
3✔
2901
                return err
3✔
2902
        }, func() {
3✔
2903
                updates = nil
3✔
2904
        })
3✔
2905
        if err != nil {
3✔
2906
                return nil, err
×
2907
        }
×
2908

2909
        return updates, nil
3✔
2910
}
2911

2912
// RemoteUnsignedLocalUpdates retrieves the persisted, unsigned local log
2913
// updates that the remote still needs to sign for.
2914
func (c *OpenChannel) RemoteUnsignedLocalUpdates() ([]LogUpdate, error) {
3✔
2915
        var updates []LogUpdate
3✔
2916
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
2917
                chanBucket, err := fetchChanBucket(
3✔
2918
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
2919
                )
3✔
2920
                switch err {
3✔
2921
                case nil:
3✔
2922
                        break
3✔
2923
                case ErrNoChanDBExists, ErrNoActiveChannels, ErrChannelNotFound:
2✔
2924
                        return nil
2✔
2925
                default:
×
2926
                        return err
×
2927
                }
2928

2929
                updateBytes := chanBucket.Get(remoteUnsignedLocalUpdatesKey)
3✔
2930
                if updateBytes == nil {
6✔
2931
                        return nil
3✔
2932
                }
3✔
2933

2934
                r := bytes.NewReader(updateBytes)
3✔
2935
                updates, err = deserializeLogUpdates(r)
3✔
2936
                return err
3✔
2937
        }, func() {
3✔
2938
                updates = nil
3✔
2939
        })
3✔
2940
        if err != nil {
3✔
2941
                return nil, err
×
2942
        }
×
2943

2944
        return updates, nil
3✔
2945
}
2946

2947
// InsertNextRevocation inserts the _next_ commitment point (revocation) into
2948
// the database, and also modifies the internal RemoteNextRevocation attribute
2949
// to point to the passed key. This method is to be using during final channel
2950
// set up, _after_ the channel has been fully confirmed.
2951
//
2952
// NOTE: If this method isn't called, then the target channel won't be able to
2953
// propose new states for the commitment state of the remote party.
2954
func (c *OpenChannel) InsertNextRevocation(revKey *btcec.PublicKey) error {
3✔
2955
        c.Lock()
3✔
2956
        defer c.Unlock()
3✔
2957

3✔
2958
        c.RemoteNextRevocation = revKey
3✔
2959

3✔
2960
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
2961
                chanBucket, err := fetchChanBucketRw(
3✔
2962
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
2963
                )
3✔
2964
                if err != nil {
3✔
2965
                        return err
×
2966
                }
×
2967

2968
                return putChanRevocationState(chanBucket, c)
3✔
2969
        }, func() {})
3✔
2970
        if err != nil {
3✔
2971
                return err
×
2972
        }
×
2973

2974
        return nil
3✔
2975
}
2976

2977
// AdvanceCommitChainTail records the new state transition within an on-disk
2978
// append-only log which records all state transitions by the remote peer. In
2979
// the case of an uncooperative broadcast of a prior state by the remote peer,
2980
// this log can be consulted in order to reconstruct the state needed to
2981
// rectify the situation. This method will add the current commitment for the
2982
// remote party to the revocation log, and promote the current pending
2983
// commitment to the current remote commitment. The updates parameter is the
2984
// set of local updates that the peer still needs to send us a signature for.
2985
// We store this set of updates in case we go down.
2986
func (c *OpenChannel) AdvanceCommitChainTail(fwdPkg *FwdPkg,
2987
        updates []LogUpdate, ourOutputIndex, theirOutputIndex uint32) error {
3✔
2988

3✔
2989
        c.Lock()
3✔
2990
        defer c.Unlock()
3✔
2991

3✔
2992
        // If this is a restored channel, then we want to avoid mutating the
3✔
2993
        // state at all, as it's impossible to do so in a protocol compliant
3✔
2994
        // manner.
3✔
2995
        if c.hasChanStatus(ChanStatusRestored) {
3✔
2996
                return ErrNoRestoredChannelMutation
×
2997
        }
×
2998

2999
        var newRemoteCommit *ChannelCommitment
3✔
3000

3✔
3001
        err := kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
3002
                chanBucket, err := fetchChanBucketRw(
3✔
3003
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
3004
                )
3✔
3005
                if err != nil {
3✔
3006
                        return err
×
3007
                }
×
3008

3009
                // If the channel is marked as borked, then for safety reasons,
3010
                // we shouldn't attempt any further updates.
3011
                isBorked, err := c.isBorked(chanBucket)
3✔
3012
                if err != nil {
3✔
3013
                        return err
×
3014
                }
×
3015
                if isBorked {
3✔
3016
                        return ErrChanBorked
×
3017
                }
×
3018

3019
                // Persist the latest preimage state to disk as the remote peer
3020
                // has just added to our local preimage store, and given us a
3021
                // new pending revocation key.
3022
                if err := putChanRevocationState(chanBucket, c); err != nil {
3✔
3023
                        return err
×
3024
                }
×
3025

3026
                // With the current preimage producer/store state updated,
3027
                // append a new log entry recording this the delta of this
3028
                // state transition.
3029
                //
3030
                // TODO(roasbeef): could make the deltas relative, would save
3031
                // space, but then tradeoff for more disk-seeks to recover the
3032
                // full state.
3033
                logKey := revocationLogBucket
3✔
3034
                logBucket, err := chanBucket.CreateBucketIfNotExists(logKey)
3✔
3035
                if err != nil {
3✔
3036
                        return err
×
3037
                }
×
3038

3039
                // Before we append this revoked state to the revocation log,
3040
                // we'll swap out what's currently the tail of the commit tip,
3041
                // with the current locked-in commitment for the remote party.
3042
                tipBytes := chanBucket.Get(commitDiffKey)
3✔
3043
                tipReader := bytes.NewReader(tipBytes)
3✔
3044
                newCommit, err := deserializeCommitDiff(tipReader)
3✔
3045
                if err != nil {
3✔
3046
                        return err
×
3047
                }
×
3048
                err = putChanCommitment(
3✔
3049
                        chanBucket, &newCommit.Commitment, false,
3✔
3050
                )
3✔
3051
                if err != nil {
3✔
3052
                        return err
×
3053
                }
×
3054
                if err := chanBucket.Delete(commitDiffKey); err != nil {
3✔
3055
                        return err
×
3056
                }
×
3057

3058
                // With the commitment pointer swapped, we can now add the
3059
                // revoked (prior) state to the revocation log.
3060
                err = putRevocationLog(
3✔
3061
                        logBucket, &c.RemoteCommitment, ourOutputIndex,
3✔
3062
                        theirOutputIndex, c.Db.parent.noRevLogAmtData,
3✔
3063
                )
3✔
3064
                if err != nil {
3✔
3065
                        return err
×
3066
                }
×
3067

3068
                // Lastly, we write the forwarding package to disk so that we
3069
                // can properly recover from failures and reforward HTLCs that
3070
                // have not received a corresponding settle/fail.
3071
                if err := c.Packager.AddFwdPkg(tx, fwdPkg); err != nil {
3✔
3072
                        return err
×
3073
                }
×
3074

3075
                // Persist the unsigned acked updates that are not included
3076
                // in their new commitment.
3077
                updateBytes := chanBucket.Get(unsignedAckedUpdatesKey)
3✔
3078
                if updateBytes == nil {
6✔
3079
                        // This shouldn't normally happen as we always store
3✔
3080
                        // the number of updates, but could still be
3✔
3081
                        // encountered by nodes that are upgrading.
3✔
3082
                        newRemoteCommit = &newCommit.Commitment
3✔
3083
                        return nil
3✔
3084
                }
3✔
3085

3086
                r := bytes.NewReader(updateBytes)
3✔
3087
                unsignedUpdates, err := deserializeLogUpdates(r)
3✔
3088
                if err != nil {
3✔
3089
                        return err
×
3090
                }
×
3091

3092
                var validUpdates []LogUpdate
3✔
3093
                for _, upd := range unsignedUpdates {
6✔
3094
                        lIdx := upd.LogIndex
3✔
3095

3✔
3096
                        // Filter for updates that are not on the remote
3✔
3097
                        // commitment.
3✔
3098
                        if lIdx >= newCommit.Commitment.RemoteLogIndex {
6✔
3099
                                validUpdates = append(validUpdates, upd)
3✔
3100
                        }
3✔
3101
                }
3102

3103
                var b bytes.Buffer
3✔
3104
                err = serializeLogUpdates(&b, validUpdates)
3✔
3105
                if err != nil {
3✔
3106
                        return fmt.Errorf("unable to serialize log updates: %w",
×
3107
                                err)
×
3108
                }
×
3109

3110
                err = chanBucket.Put(unsignedAckedUpdatesKey, b.Bytes())
3✔
3111
                if err != nil {
3✔
3112
                        return fmt.Errorf("unable to store under "+
×
3113
                                "unsignedAckedUpdatesKey: %w", err)
×
3114
                }
×
3115

3116
                // Persist the local updates the peer hasn't yet signed so they
3117
                // can be restored after restart.
3118
                var b2 bytes.Buffer
3✔
3119
                err = serializeLogUpdates(&b2, updates)
3✔
3120
                if err != nil {
3✔
3121
                        return err
×
3122
                }
×
3123

3124
                err = chanBucket.Put(remoteUnsignedLocalUpdatesKey, b2.Bytes())
3✔
3125
                if err != nil {
3✔
3126
                        return fmt.Errorf("unable to restore remote unsigned "+
×
3127
                                "local updates: %v", err)
×
3128
                }
×
3129

3130
                newRemoteCommit = &newCommit.Commitment
3✔
3131

3✔
3132
                return nil
3✔
3133
        }, func() {
3✔
3134
                newRemoteCommit = nil
3✔
3135
        })
3✔
3136
        if err != nil {
3✔
3137
                return err
×
3138
        }
×
3139

3140
        // With the db transaction complete, we'll swap over the in-memory
3141
        // pointer of the new remote commitment, which was previously the tip
3142
        // of the commit chain.
3143
        c.RemoteCommitment = *newRemoteCommit
3✔
3144

3✔
3145
        return nil
3✔
3146
}
3147

3148
// FinalHtlcInfo contains information about the final outcome of an htlc.
3149
type FinalHtlcInfo struct {
3150
        // Settled is true is the htlc was settled. If false, the htlc was
3151
        // failed.
3152
        Settled bool
3153

3154
        // Offchain indicates whether the htlc was resolved off-chain or
3155
        // on-chain.
3156
        Offchain bool
3157
}
3158

3159
// putFinalHtlc writes the final htlc outcome to the database. Additionally it
3160
// records whether the htlc was resolved off-chain or on-chain.
3161
func putFinalHtlc(finalHtlcsBucket kvdb.RwBucket, id uint64,
3162
        info FinalHtlcInfo) error {
3✔
3163

3✔
3164
        var key [8]byte
3✔
3165
        byteOrder.PutUint64(key[:], id)
3✔
3166

3✔
3167
        var finalHtlcByte FinalHtlcByte
3✔
3168
        if info.Settled {
6✔
3169
                finalHtlcByte |= FinalHtlcSettledBit
3✔
3170
        }
3✔
3171
        if info.Offchain {
6✔
3172
                finalHtlcByte |= FinalHtlcOffchainBit
3✔
3173
        }
3✔
3174

3175
        return finalHtlcsBucket.Put(key[:], []byte{byte(finalHtlcByte)})
3✔
3176
}
3177

3178
// NextLocalHtlcIndex returns the next unallocated local htlc index. To ensure
3179
// this always returns the next index that has been not been allocated, this
3180
// will first try to examine any pending commitments, before falling back to the
3181
// last locked-in remote commitment.
3182
func (c *OpenChannel) NextLocalHtlcIndex() (uint64, error) {
3✔
3183
        // First, load the most recent commit diff that we initiated for the
3✔
3184
        // remote party. If no pending commit is found, this is not treated as
3✔
3185
        // a critical error, since we can always fall back.
3✔
3186
        pendingRemoteCommit, err := c.RemoteCommitChainTip()
3✔
3187
        if err != nil && err != ErrNoPendingCommit {
3✔
3188
                return 0, err
×
3189
        }
×
3190

3191
        // If a pending commit was found, its local htlc index will be at least
3192
        // as large as the one on our local commitment.
3193
        if pendingRemoteCommit != nil {
3✔
3194
                return pendingRemoteCommit.Commitment.LocalHtlcIndex, nil
×
3195
        }
×
3196

3197
        // Otherwise, fallback to using the local htlc index of their commitment.
3198
        return c.RemoteCommitment.LocalHtlcIndex, nil
3✔
3199
}
3200

3201
// LoadFwdPkgs scans the forwarding log for any packages that haven't been
3202
// processed, and returns their deserialized log updates in map indexed by the
3203
// remote commitment height at which the updates were locked in.
3204
func (c *OpenChannel) LoadFwdPkgs() ([]*FwdPkg, error) {
3✔
3205
        c.RLock()
3✔
3206
        defer c.RUnlock()
3✔
3207

3✔
3208
        var fwdPkgs []*FwdPkg
3✔
3209
        if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
3210
                var err error
3✔
3211
                fwdPkgs, err = c.Packager.LoadFwdPkgs(tx)
3✔
3212
                return err
3✔
3213
        }, func() {
6✔
3214
                fwdPkgs = nil
3✔
3215
        }); err != nil {
3✔
3216
                return nil, err
×
3217
        }
×
3218

3219
        return fwdPkgs, nil
3✔
3220
}
3221

3222
// AckAddHtlcs updates the AckAddFilter containing any of the provided AddRefs
3223
// indicating that a response to this Add has been committed to the remote party.
3224
// Doing so will prevent these Add HTLCs from being reforwarded internally.
3225
func (c *OpenChannel) AckAddHtlcs(addRefs ...AddRef) error {
×
3226
        c.Lock()
×
3227
        defer c.Unlock()
×
3228

×
3229
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
3230
                return c.Packager.AckAddHtlcs(tx, addRefs...)
×
3231
        }, func() {})
×
3232
}
3233

3234
// AckSettleFails updates the SettleFailFilter containing any of the provided
3235
// SettleFailRefs, indicating that the response has been delivered to the
3236
// incoming link, corresponding to a particular AddRef. Doing so will prevent
3237
// the responses from being retransmitted internally.
3238
func (c *OpenChannel) AckSettleFails(settleFailRefs ...SettleFailRef) error {
×
3239
        c.Lock()
×
3240
        defer c.Unlock()
×
3241

×
3242
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
×
3243
                return c.Packager.AckSettleFails(tx, settleFailRefs...)
×
3244
        }, func() {})
×
3245
}
3246

3247
// SetFwdFilter atomically sets the forwarding filter for the forwarding package
3248
// identified by `height`.
3249
func (c *OpenChannel) SetFwdFilter(height uint64, fwdFilter *PkgFilter) error {
3✔
3250
        c.Lock()
3✔
3251
        defer c.Unlock()
3✔
3252

3✔
3253
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
3254
                return c.Packager.SetFwdFilter(tx, height, fwdFilter)
3✔
3255
        }, func() {})
6✔
3256
}
3257

3258
// RemoveFwdPkgs atomically removes forwarding packages specified by the remote
3259
// commitment heights. If one of the intermediate RemovePkg calls fails, then the
3260
// later packages won't be removed.
3261
//
3262
// NOTE: This method should only be called on packages marked FwdStateCompleted.
3263
func (c *OpenChannel) RemoveFwdPkgs(heights ...uint64) error {
3✔
3264
        c.Lock()
3✔
3265
        defer c.Unlock()
3✔
3266

3✔
3267
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
3268
                for _, height := range heights {
6✔
3269
                        err := c.Packager.RemovePkg(tx, height)
3✔
3270
                        if err != nil {
3✔
UNCOV
3271
                                return err
×
UNCOV
3272
                        }
×
3273
                }
3274

3275
                return nil
3✔
3276
        }, func() {})
3✔
3277
}
3278

3279
// revocationLogTailCommitHeight returns the commit height at the end of the
3280
// revocation log. This entry represents the last previous state for the remote
3281
// node's commitment chain. The ChannelDelta returned by this method will
3282
// always lag one state behind the most current (unrevoked) state of the remote
3283
// node's commitment chain.
3284
// NOTE: used in unit test only.
3285
func (c *OpenChannel) revocationLogTailCommitHeight() (uint64, error) {
×
3286
        c.RLock()
×
3287
        defer c.RUnlock()
×
3288

×
3289
        var height uint64
×
3290

×
3291
        // If we haven't created any state updates yet, then we'll exit early as
×
3292
        // there's nothing to be found on disk in the revocation bucket.
×
3293
        if c.RemoteCommitment.CommitHeight == 0 {
×
3294
                return height, nil
×
3295
        }
×
3296

3297
        if err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
×
3298
                chanBucket, err := fetchChanBucket(
×
3299
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
×
3300
                )
×
3301
                if err != nil {
×
3302
                        return err
×
3303
                }
×
3304

3305
                logBucket, err := fetchLogBucket(chanBucket)
×
3306
                if err != nil {
×
3307
                        return err
×
3308
                }
×
3309

3310
                // Once we have the bucket that stores the revocation log from
3311
                // this channel, we'll jump to the _last_ key in bucket. Since
3312
                // the key is the commit height, we'll decode the bytes and
3313
                // return it.
3314
                cursor := logBucket.ReadCursor()
×
3315
                rawHeight, _ := cursor.Last()
×
3316
                height = byteOrder.Uint64(rawHeight)
×
3317

×
3318
                return nil
×
3319
        }, func() {}); err != nil {
×
3320
                return height, err
×
3321
        }
×
3322

3323
        return height, nil
×
3324
}
3325

3326
// CommitmentHeight returns the current commitment height. The commitment
3327
// height represents the number of updates to the commitment state to date.
3328
// This value is always monotonically increasing. This method is provided in
3329
// order to allow multiple instances of a particular open channel to obtain a
3330
// consistent view of the number of channel updates to date.
3331
func (c *OpenChannel) CommitmentHeight() (uint64, error) {
×
3332
        c.RLock()
×
3333
        defer c.RUnlock()
×
3334

×
3335
        var height uint64
×
3336
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
×
3337
                // Get the bucket dedicated to storing the metadata for open
×
3338
                // channels.
×
3339
                chanBucket, err := fetchChanBucket(
×
3340
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
×
3341
                )
×
3342
                if err != nil {
×
3343
                        return err
×
3344
                }
×
3345

3346
                commit, err := fetchChanCommitment(chanBucket, true)
×
3347
                if err != nil {
×
3348
                        return err
×
3349
                }
×
3350

3351
                height = commit.CommitHeight
×
3352
                return nil
×
3353
        }, func() {
×
3354
                height = 0
×
3355
        })
×
3356
        if err != nil {
×
3357
                return 0, err
×
3358
        }
×
3359

3360
        return height, nil
×
3361
}
3362

3363
// FindPreviousState scans through the append-only log in an attempt to recover
3364
// the previous channel state indicated by the update number. This method is
3365
// intended to be used for obtaining the relevant data needed to claim all
3366
// funds rightfully spendable in the case of an on-chain broadcast of the
3367
// commitment transaction.
3368
func (c *OpenChannel) FindPreviousState(
3369
        updateNum uint64) (*RevocationLog, *ChannelCommitment, error) {
3✔
3370

3✔
3371
        c.RLock()
3✔
3372
        defer c.RUnlock()
3✔
3373

3✔
3374
        commit := &ChannelCommitment{}
3✔
3375
        rl := &RevocationLog{}
3✔
3376

3✔
3377
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
3378
                chanBucket, err := fetchChanBucket(
3✔
3379
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
3380
                )
3✔
3381
                if err != nil {
3✔
3382
                        return err
×
3383
                }
×
3384

3385
                // Find the revocation log from both the new and the old
3386
                // bucket.
3387
                r, c, err := fetchRevocationLogCompatible(chanBucket, updateNum)
3✔
3388
                if err != nil {
6✔
3389
                        return err
3✔
3390
                }
3✔
3391

3392
                rl = r
3✔
3393
                commit = c
3✔
3394
                return nil
3✔
3395
        }, func() {})
3✔
3396
        if err != nil {
6✔
3397
                return nil, nil, err
3✔
3398
        }
3✔
3399

3400
        // Either the `rl` or the `commit` is nil here. We return them as-is
3401
        // and leave it to the caller to decide its following action.
3402
        return rl, commit, nil
3✔
3403
}
3404

3405
// ClosureType is an enum like structure that details exactly _how_ a channel
3406
// was closed. Three closure types are currently possible: none, cooperative,
3407
// local force close, remote force close, and (remote) breach.
3408
type ClosureType uint8
3409

3410
const (
3411
        // CooperativeClose indicates that a channel has been closed
3412
        // cooperatively.  This means that both channel peers were online and
3413
        // signed a new transaction paying out the settled balance of the
3414
        // contract.
3415
        CooperativeClose ClosureType = 0
3416

3417
        // LocalForceClose indicates that we have unilaterally broadcast our
3418
        // current commitment state on-chain.
3419
        LocalForceClose ClosureType = 1
3420

3421
        // RemoteForceClose indicates that the remote peer has unilaterally
3422
        // broadcast their current commitment state on-chain.
3423
        RemoteForceClose ClosureType = 4
3424

3425
        // BreachClose indicates that the remote peer attempted to broadcast a
3426
        // prior _revoked_ channel state.
3427
        BreachClose ClosureType = 2
3428

3429
        // FundingCanceled indicates that the channel never was fully opened
3430
        // before it was marked as closed in the database. This can happen if
3431
        // we or the remote fail at some point during the opening workflow, or
3432
        // we timeout waiting for the funding transaction to be confirmed.
3433
        FundingCanceled ClosureType = 3
3434

3435
        // Abandoned indicates that the channel state was removed without
3436
        // any further actions. This is intended to clean up unusable
3437
        // channels during development.
3438
        Abandoned ClosureType = 5
3439
)
3440

3441
// ChannelCloseSummary contains the final state of a channel at the point it
3442
// was closed. Once a channel is closed, all the information pertaining to that
3443
// channel within the openChannelBucket is deleted, and a compact summary is
3444
// put in place instead.
3445
type ChannelCloseSummary struct {
3446
        // ChanPoint is the outpoint for this channel's funding transaction,
3447
        // and is used as a unique identifier for the channel.
3448
        ChanPoint wire.OutPoint
3449

3450
        // ShortChanID encodes the exact location in the chain in which the
3451
        // channel was initially confirmed. This includes: the block height,
3452
        // transaction index, and the output within the target transaction.
3453
        ShortChanID lnwire.ShortChannelID
3454

3455
        // ChainHash is the hash of the genesis block that this channel resides
3456
        // within.
3457
        ChainHash chainhash.Hash
3458

3459
        // ClosingTXID is the txid of the transaction which ultimately closed
3460
        // this channel.
3461
        ClosingTXID chainhash.Hash
3462

3463
        // RemotePub is the public key of the remote peer that we formerly had
3464
        // a channel with.
3465
        RemotePub *btcec.PublicKey
3466

3467
        // Capacity was the total capacity of the channel.
3468
        Capacity btcutil.Amount
3469

3470
        // CloseHeight is the height at which the funding transaction was
3471
        // spent.
3472
        CloseHeight uint32
3473

3474
        // SettledBalance is our total balance settled balance at the time of
3475
        // channel closure. This _does not_ include the sum of any outputs that
3476
        // have been time-locked as a result of the unilateral channel closure.
3477
        SettledBalance btcutil.Amount
3478

3479
        // TimeLockedBalance is the sum of all the time-locked outputs at the
3480
        // time of channel closure. If we triggered the force closure of this
3481
        // channel, then this value will be non-zero if our settled output is
3482
        // above the dust limit. If we were on the receiving side of a channel
3483
        // force closure, then this value will be non-zero if we had any
3484
        // outstanding outgoing HTLC's at the time of channel closure.
3485
        TimeLockedBalance btcutil.Amount
3486

3487
        // CloseType details exactly _how_ the channel was closed. Five closure
3488
        // types are possible: cooperative, local force, remote force, breach
3489
        // and funding canceled.
3490
        CloseType ClosureType
3491

3492
        // IsPending indicates whether this channel is in the 'pending close'
3493
        // state, which means the channel closing transaction has been
3494
        // confirmed, but not yet been fully resolved. In the case of a channel
3495
        // that has been cooperatively closed, it will go straight into the
3496
        // fully resolved state as soon as the closing transaction has been
3497
        // confirmed. However, for channels that have been force closed, they'll
3498
        // stay marked as "pending" until _all_ the pending funds have been
3499
        // swept.
3500
        IsPending bool
3501

3502
        // RemoteCurrentRevocation is the current revocation for their
3503
        // commitment transaction. However, since this is the derived public key,
3504
        // we don't yet have the private key so we aren't yet able to verify
3505
        // that it's actually in the hash chain.
3506
        RemoteCurrentRevocation *btcec.PublicKey
3507

3508
        // RemoteNextRevocation is the revocation key to be used for the *next*
3509
        // commitment transaction we create for the local node. Within the
3510
        // specification, this value is referred to as the
3511
        // per-commitment-point.
3512
        RemoteNextRevocation *btcec.PublicKey
3513

3514
        // LocalChanConfig is the channel configuration for the local node.
3515
        LocalChanConfig ChannelConfig
3516

3517
        // LastChanSyncMsg is the ChannelReestablish message for this channel
3518
        // for the state at the point where it was closed.
3519
        LastChanSyncMsg *lnwire.ChannelReestablish
3520
}
3521

3522
// CloseChannel closes a previously active Lightning channel. Closing a channel
3523
// entails deleting all saved state within the database concerning this
3524
// channel. This method also takes a struct that summarizes the state of the
3525
// channel at closing, this compact representation will be the only component
3526
// of a channel left over after a full closing. It takes an optional set of
3527
// channel statuses which will be written to the historical channel bucket.
3528
// These statuses are used to record close initiators.
3529
func (c *OpenChannel) CloseChannel(summary *ChannelCloseSummary,
3530
        statuses ...ChannelStatus) error {
3✔
3531

3✔
3532
        c.Lock()
3✔
3533
        defer c.Unlock()
3✔
3534

3✔
3535
        return kvdb.Update(c.Db.backend, func(tx kvdb.RwTx) error {
6✔
3536
                openChanBucket := tx.ReadWriteBucket(openChannelBucket)
3✔
3537
                if openChanBucket == nil {
3✔
3538
                        return ErrNoChanDBExists
×
3539
                }
×
3540

3541
                nodePub := c.IdentityPub.SerializeCompressed()
3✔
3542
                nodeChanBucket := openChanBucket.NestedReadWriteBucket(nodePub)
3✔
3543
                if nodeChanBucket == nil {
3✔
3544
                        return ErrNoActiveChannels
×
3545
                }
×
3546

3547
                chainBucket := nodeChanBucket.NestedReadWriteBucket(c.ChainHash[:])
3✔
3548
                if chainBucket == nil {
3✔
3549
                        return ErrNoActiveChannels
×
3550
                }
×
3551

3552
                var chanPointBuf bytes.Buffer
3✔
3553
                err := writeOutpoint(&chanPointBuf, &c.FundingOutpoint)
3✔
3554
                if err != nil {
3✔
3555
                        return err
×
3556
                }
×
3557
                chanKey := chanPointBuf.Bytes()
3✔
3558
                chanBucket := chainBucket.NestedReadWriteBucket(
3✔
3559
                        chanKey,
3✔
3560
                )
3✔
3561
                if chanBucket == nil {
3✔
3562
                        return ErrNoActiveChannels
×
3563
                }
×
3564

3565
                // Before we delete the channel state, we'll read out the full
3566
                // details, as we'll also store portions of this information
3567
                // for record keeping.
3568
                chanState, err := fetchOpenChannel(
3✔
3569
                        chanBucket, &c.FundingOutpoint,
3✔
3570
                )
3✔
3571
                if err != nil {
3✔
3572
                        return err
×
3573
                }
×
3574

3575
                // Delete all the forwarding packages stored for this particular
3576
                // channel.
3577
                if err = chanState.Packager.Wipe(tx); err != nil {
3✔
3578
                        return err
×
3579
                }
×
3580

3581
                // Now that the index to this channel has been deleted, purge
3582
                // the remaining channel metadata from the database.
3583
                err = deleteOpenChannel(chanBucket)
3✔
3584
                if err != nil {
3✔
3585
                        return err
×
3586
                }
×
3587

3588
                // We'll also remove the channel from the frozen channel bucket
3589
                // if we need to.
3590
                if c.ChanType.IsFrozen() || c.ChanType.HasLeaseExpiration() {
6✔
3591
                        err := deleteThawHeight(chanBucket)
3✔
3592
                        if err != nil {
3✔
3593
                                return err
×
3594
                        }
×
3595
                }
3596

3597
                // With the base channel data deleted, attempt to delete the
3598
                // information stored within the revocation log.
3599
                if err := deleteLogBucket(chanBucket); err != nil {
3✔
3600
                        return err
×
3601
                }
×
3602

3603
                err = chainBucket.DeleteNestedBucket(chanPointBuf.Bytes())
3✔
3604
                if err != nil {
3✔
3605
                        return err
×
3606
                }
×
3607

3608
                // Fetch the outpoint bucket to see if the outpoint exists or
3609
                // not.
3610
                opBucket := tx.ReadWriteBucket(outpointBucket)
3✔
3611
                if opBucket == nil {
3✔
3612
                        return ErrNoChanDBExists
×
3613
                }
×
3614

3615
                // Add the closed outpoint to our outpoint index. This should
3616
                // replace an open outpoint in the index.
3617
                if opBucket.Get(chanPointBuf.Bytes()) == nil {
3✔
3618
                        return ErrMissingIndexEntry
×
3619
                }
×
3620

3621
                status := uint8(outpointClosed)
3✔
3622

3✔
3623
                // Write the IndexStatus of this outpoint as the first entry in a tlv
3✔
3624
                // stream.
3✔
3625
                statusRecord := tlv.MakePrimitiveRecord(indexStatusType, &status)
3✔
3626
                opStream, err := tlv.NewStream(statusRecord)
3✔
3627
                if err != nil {
3✔
3628
                        return err
×
3629
                }
×
3630

3631
                var b bytes.Buffer
3✔
3632
                if err := opStream.Encode(&b); err != nil {
3✔
3633
                        return err
×
3634
                }
×
3635

3636
                // Finally add the closed outpoint and tlv stream to the index.
3637
                if err := opBucket.Put(chanPointBuf.Bytes(), b.Bytes()); err != nil {
3✔
3638
                        return err
×
3639
                }
×
3640

3641
                // Add channel state to the historical channel bucket.
3642
                historicalBucket, err := tx.CreateTopLevelBucket(
3✔
3643
                        historicalChannelBucket,
3✔
3644
                )
3✔
3645
                if err != nil {
3✔
3646
                        return err
×
3647
                }
×
3648

3649
                historicalChanBucket, err :=
3✔
3650
                        historicalBucket.CreateBucketIfNotExists(chanKey)
3✔
3651
                if err != nil {
3✔
3652
                        return err
×
3653
                }
×
3654

3655
                // Apply any additional statuses to the channel state.
3656
                for _, status := range statuses {
6✔
3657
                        chanState.chanStatus |= status
3✔
3658
                }
3✔
3659

3660
                err = putOpenChannel(historicalChanBucket, chanState)
3✔
3661
                if err != nil {
3✔
3662
                        return err
×
3663
                }
×
3664

3665
                // Finally, create a summary of this channel in the closed
3666
                // channel bucket for this node.
3667
                return putChannelCloseSummary(
3✔
3668
                        tx, chanPointBuf.Bytes(), summary, chanState,
3✔
3669
                )
3✔
3670
        }, func() {})
3✔
3671
}
3672

3673
// ChannelSnapshot is a frozen snapshot of the current channel state. A
3674
// snapshot is detached from the original channel that generated it, providing
3675
// read-only access to the current or prior state of an active channel.
3676
//
3677
// TODO(roasbeef): remove all together? pretty much just commitment
3678
type ChannelSnapshot struct {
3679
        // RemoteIdentity is the identity public key of the remote node that we
3680
        // are maintaining the open channel with.
3681
        RemoteIdentity btcec.PublicKey
3682

3683
        // ChanPoint is the outpoint that created the channel. This output is
3684
        // found within the funding transaction and uniquely identified the
3685
        // channel on the resident chain.
3686
        ChannelPoint wire.OutPoint
3687

3688
        // ChainHash is the genesis hash of the chain that the channel resides
3689
        // within.
3690
        ChainHash chainhash.Hash
3691

3692
        // Capacity is the total capacity of the channel.
3693
        Capacity btcutil.Amount
3694

3695
        // TotalMSatSent is the total number of milli-satoshis we've sent
3696
        // within this channel.
3697
        TotalMSatSent lnwire.MilliSatoshi
3698

3699
        // TotalMSatReceived is the total number of milli-satoshis we've
3700
        // received within this channel.
3701
        TotalMSatReceived lnwire.MilliSatoshi
3702

3703
        // ChannelCommitment is the current up-to-date commitment for the
3704
        // target channel.
3705
        ChannelCommitment
3706
}
3707

3708
// Snapshot returns a read-only snapshot of the current channel state. This
3709
// snapshot includes information concerning the current settled balance within
3710
// the channel, metadata detailing total flows, and any outstanding HTLCs.
3711
func (c *OpenChannel) Snapshot() *ChannelSnapshot {
3✔
3712
        c.RLock()
3✔
3713
        defer c.RUnlock()
3✔
3714

3✔
3715
        localCommit := c.LocalCommitment
3✔
3716
        snapshot := &ChannelSnapshot{
3✔
3717
                RemoteIdentity:    *c.IdentityPub,
3✔
3718
                ChannelPoint:      c.FundingOutpoint,
3✔
3719
                Capacity:          c.Capacity,
3✔
3720
                TotalMSatSent:     c.TotalMSatSent,
3✔
3721
                TotalMSatReceived: c.TotalMSatReceived,
3✔
3722
                ChainHash:         c.ChainHash,
3✔
3723
                ChannelCommitment: ChannelCommitment{
3✔
3724
                        LocalBalance:  localCommit.LocalBalance,
3✔
3725
                        RemoteBalance: localCommit.RemoteBalance,
3✔
3726
                        CommitHeight:  localCommit.CommitHeight,
3✔
3727
                        CommitFee:     localCommit.CommitFee,
3✔
3728
                },
3✔
3729
        }
3✔
3730

3✔
3731
        // Copy over the current set of HTLCs to ensure the caller can't mutate
3✔
3732
        // our internal state.
3✔
3733
        snapshot.Htlcs = make([]HTLC, len(localCommit.Htlcs))
3✔
3734
        for i, h := range localCommit.Htlcs {
6✔
3735
                snapshot.Htlcs[i] = h.Copy()
3✔
3736
        }
3✔
3737

3738
        return snapshot
3✔
3739
}
3740

3741
// LatestCommitments returns the two latest commitments for both the local and
3742
// remote party. These commitments are read from disk to ensure that only the
3743
// latest fully committed state is returned. The first commitment returned is
3744
// the local commitment, and the second returned is the remote commitment.
3745
func (c *OpenChannel) LatestCommitments() (*ChannelCommitment, *ChannelCommitment, error) {
3✔
3746
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
3747
                chanBucket, err := fetchChanBucket(
3✔
3748
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
3749
                )
3✔
3750
                if err != nil {
3✔
3751
                        return err
×
3752
                }
×
3753

3754
                return fetchChanCommitments(chanBucket, c)
3✔
3755
        }, func() {})
3✔
3756
        if err != nil {
3✔
3757
                return nil, nil, err
×
3758
        }
×
3759

3760
        return &c.LocalCommitment, &c.RemoteCommitment, nil
3✔
3761
}
3762

3763
// RemoteRevocationStore returns the most up to date commitment version of the
3764
// revocation storage tree for the remote party. This method can be used when
3765
// acting on a possible contract breach to ensure, that the caller has the most
3766
// up to date information required to deliver justice.
3767
func (c *OpenChannel) RemoteRevocationStore() (shachain.Store, error) {
3✔
3768
        err := kvdb.View(c.Db.backend, func(tx kvdb.RTx) error {
6✔
3769
                chanBucket, err := fetchChanBucket(
3✔
3770
                        tx, c.IdentityPub, &c.FundingOutpoint, c.ChainHash,
3✔
3771
                )
3✔
3772
                if err != nil {
3✔
3773
                        return err
×
3774
                }
×
3775

3776
                return fetchChanRevocationState(chanBucket, c)
3✔
3777
        }, func() {})
3✔
3778
        if err != nil {
3✔
3779
                return nil, err
×
3780
        }
×
3781

3782
        return c.RevocationStore, nil
3✔
3783
}
3784

3785
// AbsoluteThawHeight determines a frozen channel's absolute thaw height. If the
3786
// channel is not frozen, then 0 is returned.
3787
func (c *OpenChannel) AbsoluteThawHeight() (uint32, error) {
3✔
3788
        // Only frozen channels have a thaw height.
3✔
3789
        if !c.ChanType.IsFrozen() && !c.ChanType.HasLeaseExpiration() {
6✔
3790
                return 0, nil
3✔
3791
        }
3✔
3792

3793
        // If the channel has the frozen bit set and it's thaw height is below
3794
        // the absolute threshold, then it's interpreted as a relative height to
3795
        // the chain's current height.
3796
        if c.ChanType.IsFrozen() && c.ThawHeight < AbsoluteThawHeightThreshold {
6✔
3797
                // We'll only known of the channel's short ID once it's
3✔
3798
                // confirmed.
3✔
3799
                if c.IsPending {
3✔
3800
                        return 0, errors.New("cannot use relative thaw " +
×
3801
                                "height for unconfirmed channel")
×
3802
                }
×
3803

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

3✔
3807
                // If this is a zero-conf channel, the ShortChannelID will be
3✔
3808
                // an alias.
3✔
3809
                if c.IsZeroConf() {
3✔
3810
                        if !c.ZeroConfConfirmed() {
×
3811
                                return 0, errors.New("cannot use relative " +
×
3812
                                        "height for unconfirmed zero-conf " +
×
3813
                                        "channel")
×
3814
                        }
×
3815

3816
                        // Use the confirmed SCID's BlockHeight.
3817
                        blockHeightBase = c.confirmedScid.BlockHeight
×
3818
                }
3819

3820
                return blockHeightBase + c.ThawHeight, nil
3✔
3821
        }
3822

3823
        return c.ThawHeight, nil
3✔
3824
}
3825

3826
func putChannelCloseSummary(tx kvdb.RwTx, chanID []byte,
3827
        summary *ChannelCloseSummary, lastChanState *OpenChannel) error {
3✔
3828

3✔
3829
        closedChanBucket, err := tx.CreateTopLevelBucket(closedChannelBucket)
3✔
3830
        if err != nil {
3✔
3831
                return err
×
3832
        }
×
3833

3834
        summary.RemoteCurrentRevocation = lastChanState.RemoteCurrentRevocation
3✔
3835
        summary.RemoteNextRevocation = lastChanState.RemoteNextRevocation
3✔
3836
        summary.LocalChanConfig = lastChanState.LocalChanCfg
3✔
3837

3✔
3838
        var b bytes.Buffer
3✔
3839
        if err := serializeChannelCloseSummary(&b, summary); err != nil {
3✔
3840
                return err
×
3841
        }
×
3842

3843
        return closedChanBucket.Put(chanID, b.Bytes())
3✔
3844
}
3845

3846
func serializeChannelCloseSummary(w io.Writer, cs *ChannelCloseSummary) error {
3✔
3847
        err := WriteElements(w,
3✔
3848
                cs.ChanPoint, cs.ShortChanID, cs.ChainHash, cs.ClosingTXID,
3✔
3849
                cs.CloseHeight, cs.RemotePub, cs.Capacity, cs.SettledBalance,
3✔
3850
                cs.TimeLockedBalance, cs.CloseType, cs.IsPending,
3✔
3851
        )
3✔
3852
        if err != nil {
3✔
3853
                return err
×
3854
        }
×
3855

3856
        // If this is a close channel summary created before the addition of
3857
        // the new fields, then we can exit here.
3858
        if cs.RemoteCurrentRevocation == nil {
3✔
3859
                return WriteElements(w, false)
×
3860
        }
×
3861

3862
        // If fields are present, write boolean to indicate this, and continue.
3863
        if err := WriteElements(w, true); err != nil {
3✔
3864
                return err
×
3865
        }
×
3866

3867
        if err := WriteElements(w, cs.RemoteCurrentRevocation); err != nil {
3✔
3868
                return err
×
3869
        }
×
3870

3871
        if err := writeChanConfig(w, &cs.LocalChanConfig); err != nil {
3✔
3872
                return err
×
3873
        }
×
3874

3875
        // The RemoteNextRevocation field is optional, as it's possible for a
3876
        // channel to be closed before we learn of the next unrevoked
3877
        // revocation point for the remote party. Write a boolean indicating
3878
        // whether this field is present or not.
3879
        if err := WriteElements(w, cs.RemoteNextRevocation != nil); err != nil {
3✔
3880
                return err
×
3881
        }
×
3882

3883
        // Write the field, if present.
3884
        if cs.RemoteNextRevocation != nil {
6✔
3885
                if err = WriteElements(w, cs.RemoteNextRevocation); err != nil {
3✔
3886
                        return err
×
3887
                }
×
3888
        }
3889

3890
        // Write whether the channel sync message is present.
3891
        if err := WriteElements(w, cs.LastChanSyncMsg != nil); err != nil {
3✔
3892
                return err
×
3893
        }
×
3894

3895
        // Write the channel sync message, if present.
3896
        if cs.LastChanSyncMsg != nil {
6✔
3897
                if err := WriteElements(w, cs.LastChanSyncMsg); err != nil {
3✔
3898
                        return err
×
3899
                }
×
3900
        }
3901

3902
        return nil
3✔
3903
}
3904

3905
func deserializeCloseChannelSummary(r io.Reader) (*ChannelCloseSummary, error) {
3✔
3906
        c := &ChannelCloseSummary{}
3✔
3907

3✔
3908
        err := ReadElements(r,
3✔
3909
                &c.ChanPoint, &c.ShortChanID, &c.ChainHash, &c.ClosingTXID,
3✔
3910
                &c.CloseHeight, &c.RemotePub, &c.Capacity, &c.SettledBalance,
3✔
3911
                &c.TimeLockedBalance, &c.CloseType, &c.IsPending,
3✔
3912
        )
3✔
3913
        if err != nil {
3✔
3914
                return nil, err
×
3915
        }
×
3916

3917
        // We'll now check to see if the channel close summary was encoded with
3918
        // any of the additional optional fields.
3919
        var hasNewFields bool
3✔
3920
        err = ReadElements(r, &hasNewFields)
3✔
3921
        if err != nil {
3✔
3922
                return nil, err
×
3923
        }
×
3924

3925
        // If fields are not present, we can return.
3926
        if !hasNewFields {
3✔
3927
                return c, nil
×
3928
        }
×
3929

3930
        // Otherwise read the new fields.
3931
        if err := ReadElements(r, &c.RemoteCurrentRevocation); err != nil {
3✔
3932
                return nil, err
×
3933
        }
×
3934

3935
        if err := readChanConfig(r, &c.LocalChanConfig); err != nil {
3✔
3936
                return nil, err
×
3937
        }
×
3938

3939
        // Finally, we'll attempt to read the next unrevoked commitment point
3940
        // for the remote party. If we closed the channel before receiving a
3941
        // channel_ready message then this might not be present. A boolean
3942
        // indicating whether the field is present will come first.
3943
        var hasRemoteNextRevocation bool
3✔
3944
        err = ReadElements(r, &hasRemoteNextRevocation)
3✔
3945
        if err != nil {
3✔
3946
                return nil, err
×
3947
        }
×
3948

3949
        // If this field was written, read it.
3950
        if hasRemoteNextRevocation {
6✔
3951
                err = ReadElements(r, &c.RemoteNextRevocation)
3✔
3952
                if err != nil {
3✔
3953
                        return nil, err
×
3954
                }
×
3955
        }
3956

3957
        // Check if we have a channel sync message to read.
3958
        var hasChanSyncMsg bool
3✔
3959
        err = ReadElements(r, &hasChanSyncMsg)
3✔
3960
        if err == io.EOF {
3✔
3961
                return c, nil
×
3962
        } else if err != nil {
3✔
3963
                return nil, err
×
3964
        }
×
3965

3966
        // If a chan sync message is present, read it.
3967
        if hasChanSyncMsg {
6✔
3968
                // We must pass in reference to a lnwire.Message for the codec
3✔
3969
                // to support it.
3✔
3970
                var msg lnwire.Message
3✔
3971
                if err := ReadElements(r, &msg); err != nil {
3✔
3972
                        return nil, err
×
3973
                }
×
3974

3975
                chanSync, ok := msg.(*lnwire.ChannelReestablish)
3✔
3976
                if !ok {
3✔
3977
                        return nil, errors.New("unable cast db Message to " +
×
3978
                                "ChannelReestablish")
×
3979
                }
×
3980
                c.LastChanSyncMsg = chanSync
3✔
3981
        }
3982

3983
        return c, nil
3✔
3984
}
3985

3986
func writeChanConfig(b io.Writer, c *ChannelConfig) error {
3✔
3987
        return WriteElements(b,
3✔
3988
                c.DustLimit, c.MaxPendingAmount, c.ChanReserve, c.MinHTLC,
3✔
3989
                c.MaxAcceptedHtlcs, c.CsvDelay, c.MultiSigKey,
3✔
3990
                c.RevocationBasePoint, c.PaymentBasePoint, c.DelayBasePoint,
3✔
3991
                c.HtlcBasePoint,
3✔
3992
        )
3✔
3993
}
3✔
3994

3995
// fundingTxPresent returns true if expect the funding transcation to be found
3996
// on disk or already populated within the passed open channel struct.
3997
func fundingTxPresent(channel *OpenChannel) bool {
3✔
3998
        chanType := channel.ChanType
3✔
3999

3✔
4000
        return chanType.IsSingleFunder() && chanType.HasFundingTx() &&
3✔
4001
                channel.IsInitiator &&
3✔
4002
                !channel.hasChanStatus(ChanStatusRestored)
3✔
4003
}
3✔
4004

4005
func putChanInfo(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
3✔
4006
        var w bytes.Buffer
3✔
4007
        if err := WriteElements(&w,
3✔
4008
                channel.ChanType, channel.ChainHash, channel.FundingOutpoint,
3✔
4009
                channel.ShortChannelID, channel.IsPending, channel.IsInitiator,
3✔
4010
                channel.chanStatus, channel.FundingBroadcastHeight,
3✔
4011
                channel.NumConfsRequired, channel.ChannelFlags,
3✔
4012
                channel.IdentityPub, channel.Capacity, channel.TotalMSatSent,
3✔
4013
                channel.TotalMSatReceived,
3✔
4014
        ); err != nil {
3✔
4015
                return err
×
4016
        }
×
4017

4018
        // For single funder channels that we initiated, and we have the
4019
        // funding transaction, then write the funding txn.
4020
        if fundingTxPresent(channel) {
6✔
4021
                if err := WriteElement(&w, channel.FundingTxn); err != nil {
3✔
4022
                        return err
×
4023
                }
×
4024
        }
4025

4026
        if err := writeChanConfig(&w, &channel.LocalChanCfg); err != nil {
3✔
4027
                return err
×
4028
        }
×
4029
        if err := writeChanConfig(&w, &channel.RemoteChanCfg); err != nil {
3✔
4030
                return err
×
4031
        }
×
4032

4033
        // Convert balance fields into uint64.
4034
        localBalance := uint64(channel.InitialLocalBalance)
3✔
4035
        remoteBalance := uint64(channel.InitialRemoteBalance)
3✔
4036

3✔
4037
        // Create the tlv stream.
3✔
4038
        tlvStream, err := tlv.NewStream(
3✔
4039
                // Write the RevocationKeyLocator as the first entry in a tlv
3✔
4040
                // stream.
3✔
4041
                MakeKeyLocRecord(
3✔
4042
                        keyLocType, &channel.RevocationKeyLocator,
3✔
4043
                ),
3✔
4044
                tlv.MakePrimitiveRecord(
3✔
4045
                        initialLocalBalanceType, &localBalance,
3✔
4046
                ),
3✔
4047
                tlv.MakePrimitiveRecord(
3✔
4048
                        initialRemoteBalanceType, &remoteBalance,
3✔
4049
                ),
3✔
4050
                MakeScidRecord(realScidType, &channel.confirmedScid),
3✔
4051
                tlv.MakePrimitiveRecord(channelMemoType, &channel.Memo),
3✔
4052
        )
3✔
4053
        if err != nil {
3✔
4054
                return err
×
4055
        }
×
4056

4057
        if err := tlvStream.Encode(&w); err != nil {
3✔
4058
                return err
×
4059
        }
×
4060

4061
        if err := chanBucket.Put(chanInfoKey, w.Bytes()); err != nil {
3✔
4062
                return err
×
4063
        }
×
4064

4065
        // Finally, add optional shutdown scripts for the local and remote peer if
4066
        // they are present.
4067
        if err := putOptionalUpfrontShutdownScript(
3✔
4068
                chanBucket, localUpfrontShutdownKey, channel.LocalShutdownScript,
3✔
4069
        ); err != nil {
3✔
4070
                return err
×
4071
        }
×
4072

4073
        return putOptionalUpfrontShutdownScript(
3✔
4074
                chanBucket, remoteUpfrontShutdownKey, channel.RemoteShutdownScript,
3✔
4075
        )
3✔
4076
}
4077

4078
// putOptionalUpfrontShutdownScript adds a shutdown script under the key
4079
// provided if it has a non-zero length.
4080
func putOptionalUpfrontShutdownScript(chanBucket kvdb.RwBucket, key []byte,
4081
        script []byte) error {
3✔
4082
        // If the script is empty, we do not need to add anything.
3✔
4083
        if len(script) == 0 {
6✔
4084
                return nil
3✔
4085
        }
3✔
4086

4087
        var w bytes.Buffer
3✔
4088
        if err := WriteElement(&w, script); err != nil {
3✔
4089
                return err
×
4090
        }
×
4091

4092
        return chanBucket.Put(key, w.Bytes())
3✔
4093
}
4094

4095
// getOptionalUpfrontShutdownScript reads the shutdown script stored under the
4096
// key provided if it is present. Upfront shutdown scripts are optional, so the
4097
// function returns with no error if the key is not present.
4098
func getOptionalUpfrontShutdownScript(chanBucket kvdb.RBucket, key []byte,
4099
        script *lnwire.DeliveryAddress) error {
3✔
4100

3✔
4101
        // Return early if the bucket does not exit, a shutdown script was not set.
3✔
4102
        bs := chanBucket.Get(key)
3✔
4103
        if bs == nil {
6✔
4104
                return nil
3✔
4105
        }
3✔
4106

4107
        var tempScript []byte
3✔
4108
        r := bytes.NewReader(bs)
3✔
4109
        if err := ReadElement(r, &tempScript); err != nil {
3✔
4110
                return err
×
4111
        }
×
4112
        *script = tempScript
3✔
4113

3✔
4114
        return nil
3✔
4115
}
4116

4117
func serializeChanCommit(w io.Writer, c *ChannelCommitment) error {
3✔
4118
        if err := WriteElements(w,
3✔
4119
                c.CommitHeight, c.LocalLogIndex, c.LocalHtlcIndex,
3✔
4120
                c.RemoteLogIndex, c.RemoteHtlcIndex, c.LocalBalance,
3✔
4121
                c.RemoteBalance, c.CommitFee, c.FeePerKw, c.CommitTx,
3✔
4122
                c.CommitSig,
3✔
4123
        ); err != nil {
3✔
4124
                return err
×
4125
        }
×
4126

4127
        return SerializeHtlcs(w, c.Htlcs...)
3✔
4128
}
4129

4130
func putChanCommitment(chanBucket kvdb.RwBucket, c *ChannelCommitment,
4131
        local bool) error {
3✔
4132

3✔
4133
        var commitKey []byte
3✔
4134
        if local {
6✔
4135
                commitKey = append(chanCommitmentKey, byte(0x00))
3✔
4136
        } else {
6✔
4137
                commitKey = append(chanCommitmentKey, byte(0x01))
3✔
4138
        }
3✔
4139

4140
        var b bytes.Buffer
3✔
4141
        if err := serializeChanCommit(&b, c); err != nil {
3✔
4142
                return err
×
4143
        }
×
4144

4145
        return chanBucket.Put(commitKey, b.Bytes())
3✔
4146
}
4147

4148
func putChanCommitments(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
3✔
4149
        // If this is a restored channel, then we don't have any commitments to
3✔
4150
        // write.
3✔
4151
        if channel.hasChanStatus(ChanStatusRestored) {
6✔
4152
                return nil
3✔
4153
        }
3✔
4154

4155
        err := putChanCommitment(
3✔
4156
                chanBucket, &channel.LocalCommitment, true,
3✔
4157
        )
3✔
4158
        if err != nil {
3✔
4159
                return err
×
4160
        }
×
4161

4162
        return putChanCommitment(
3✔
4163
                chanBucket, &channel.RemoteCommitment, false,
3✔
4164
        )
3✔
4165
}
4166

4167
func putChanRevocationState(chanBucket kvdb.RwBucket, channel *OpenChannel) error {
3✔
4168
        var b bytes.Buffer
3✔
4169
        err := WriteElements(
3✔
4170
                &b, channel.RemoteCurrentRevocation, channel.RevocationProducer,
3✔
4171
                channel.RevocationStore,
3✔
4172
        )
3✔
4173
        if err != nil {
3✔
4174
                return err
×
4175
        }
×
4176

4177
        // If the next revocation is present, which is only the case after the
4178
        // ChannelReady message has been sent, then we'll write it to disk.
4179
        if channel.RemoteNextRevocation != nil {
6✔
4180
                err = WriteElements(&b, channel.RemoteNextRevocation)
3✔
4181
                if err != nil {
3✔
4182
                        return err
×
4183
                }
×
4184
        }
4185

4186
        return chanBucket.Put(revocationStateKey, b.Bytes())
3✔
4187
}
4188

4189
func readChanConfig(b io.Reader, c *ChannelConfig) error {
3✔
4190
        return ReadElements(b,
3✔
4191
                &c.DustLimit, &c.MaxPendingAmount, &c.ChanReserve,
3✔
4192
                &c.MinHTLC, &c.MaxAcceptedHtlcs, &c.CsvDelay,
3✔
4193
                &c.MultiSigKey, &c.RevocationBasePoint,
3✔
4194
                &c.PaymentBasePoint, &c.DelayBasePoint,
3✔
4195
                &c.HtlcBasePoint,
3✔
4196
        )
3✔
4197
}
3✔
4198

4199
func fetchChanInfo(chanBucket kvdb.RBucket, channel *OpenChannel) error {
3✔
4200
        infoBytes := chanBucket.Get(chanInfoKey)
3✔
4201
        if infoBytes == nil {
3✔
4202
                return ErrNoChanInfoFound
×
4203
        }
×
4204
        r := bytes.NewReader(infoBytes)
3✔
4205

3✔
4206
        if err := ReadElements(r,
3✔
4207
                &channel.ChanType, &channel.ChainHash, &channel.FundingOutpoint,
3✔
4208
                &channel.ShortChannelID, &channel.IsPending, &channel.IsInitiator,
3✔
4209
                &channel.chanStatus, &channel.FundingBroadcastHeight,
3✔
4210
                &channel.NumConfsRequired, &channel.ChannelFlags,
3✔
4211
                &channel.IdentityPub, &channel.Capacity, &channel.TotalMSatSent,
3✔
4212
                &channel.TotalMSatReceived,
3✔
4213
        ); err != nil {
3✔
4214
                return err
×
4215
        }
×
4216

4217
        // For single funder channels that we initiated and have the funding
4218
        // transaction to, read the funding txn.
4219
        if fundingTxPresent(channel) {
6✔
4220
                if err := ReadElement(r, &channel.FundingTxn); err != nil {
3✔
4221
                        return err
×
4222
                }
×
4223
        }
4224

4225
        if err := readChanConfig(r, &channel.LocalChanCfg); err != nil {
3✔
4226
                return err
×
4227
        }
×
4228
        if err := readChanConfig(r, &channel.RemoteChanCfg); err != nil {
3✔
4229
                return err
×
4230
        }
×
4231

4232
        // Retrieve the boolean stored under lastWasRevokeKey.
4233
        lastWasRevokeBytes := chanBucket.Get(lastWasRevokeKey)
3✔
4234
        if lastWasRevokeBytes == nil {
6✔
4235
                // If nothing has been stored under this key, we store false in the
3✔
4236
                // OpenChannel struct.
3✔
4237
                channel.LastWasRevoke = false
3✔
4238
        } else {
6✔
4239
                // Otherwise, read the value into the LastWasRevoke field.
3✔
4240
                revokeReader := bytes.NewReader(lastWasRevokeBytes)
3✔
4241
                err := ReadElements(revokeReader, &channel.LastWasRevoke)
3✔
4242
                if err != nil {
3✔
4243
                        return err
×
4244
                }
×
4245
        }
4246

4247
        // Create balance fields in uint64, and Memo field as byte slice.
4248
        var (
3✔
4249
                localBalance  uint64
3✔
4250
                remoteBalance uint64
3✔
4251
                memo          []byte
3✔
4252
        )
3✔
4253

3✔
4254
        // Create the tlv stream.
3✔
4255
        tlvStream, err := tlv.NewStream(
3✔
4256
                // Write the RevocationKeyLocator as the first entry in a tlv
3✔
4257
                // stream.
3✔
4258
                MakeKeyLocRecord(
3✔
4259
                        keyLocType, &channel.RevocationKeyLocator,
3✔
4260
                ),
3✔
4261
                tlv.MakePrimitiveRecord(
3✔
4262
                        initialLocalBalanceType, &localBalance,
3✔
4263
                ),
3✔
4264
                tlv.MakePrimitiveRecord(
3✔
4265
                        initialRemoteBalanceType, &remoteBalance,
3✔
4266
                ),
3✔
4267
                MakeScidRecord(realScidType, &channel.confirmedScid),
3✔
4268
                tlv.MakePrimitiveRecord(channelMemoType, &memo),
3✔
4269
        )
3✔
4270
        if err != nil {
3✔
4271
                return err
×
4272
        }
×
4273

4274
        if err := tlvStream.Decode(r); err != nil {
3✔
4275
                return err
×
4276
        }
×
4277

4278
        // Attach the balance fields.
4279
        channel.InitialLocalBalance = lnwire.MilliSatoshi(localBalance)
3✔
4280
        channel.InitialRemoteBalance = lnwire.MilliSatoshi(remoteBalance)
3✔
4281

3✔
4282
        // Attach the memo field if non-empty.
3✔
4283
        if len(memo) > 0 {
6✔
4284
                channel.Memo = memo
3✔
4285
        }
3✔
4286

4287
        channel.Packager = NewChannelPackager(channel.ShortChannelID)
3✔
4288

3✔
4289
        // Finally, read the optional shutdown scripts.
3✔
4290
        if err := getOptionalUpfrontShutdownScript(
3✔
4291
                chanBucket, localUpfrontShutdownKey, &channel.LocalShutdownScript,
3✔
4292
        ); err != nil {
3✔
4293
                return err
×
4294
        }
×
4295

4296
        return getOptionalUpfrontShutdownScript(
3✔
4297
                chanBucket, remoteUpfrontShutdownKey, &channel.RemoteShutdownScript,
3✔
4298
        )
3✔
4299
}
4300

4301
func deserializeChanCommit(r io.Reader) (ChannelCommitment, error) {
3✔
4302
        var c ChannelCommitment
3✔
4303

3✔
4304
        err := ReadElements(r,
3✔
4305
                &c.CommitHeight, &c.LocalLogIndex, &c.LocalHtlcIndex, &c.RemoteLogIndex,
3✔
4306
                &c.RemoteHtlcIndex, &c.LocalBalance, &c.RemoteBalance,
3✔
4307
                &c.CommitFee, &c.FeePerKw, &c.CommitTx, &c.CommitSig,
3✔
4308
        )
3✔
4309
        if err != nil {
3✔
4310
                return c, err
×
4311
        }
×
4312

4313
        c.Htlcs, err = DeserializeHtlcs(r)
3✔
4314
        if err != nil {
3✔
4315
                return c, err
×
4316
        }
×
4317

4318
        return c, nil
3✔
4319
}
4320

4321
func fetchChanCommitment(chanBucket kvdb.RBucket, local bool) (ChannelCommitment, error) {
3✔
4322
        var commitKey []byte
3✔
4323
        if local {
6✔
4324
                commitKey = append(chanCommitmentKey, byte(0x00))
3✔
4325
        } else {
6✔
4326
                commitKey = append(chanCommitmentKey, byte(0x01))
3✔
4327
        }
3✔
4328

4329
        commitBytes := chanBucket.Get(commitKey)
3✔
4330
        if commitBytes == nil {
3✔
4331
                return ChannelCommitment{}, ErrNoCommitmentsFound
×
4332
        }
×
4333

4334
        r := bytes.NewReader(commitBytes)
3✔
4335
        return deserializeChanCommit(r)
3✔
4336
}
4337

4338
func fetchChanCommitments(chanBucket kvdb.RBucket, channel *OpenChannel) error {
3✔
4339
        var err error
3✔
4340

3✔
4341
        // If this is a restored channel, then we don't have any commitments to
3✔
4342
        // read.
3✔
4343
        if channel.hasChanStatus(ChanStatusRestored) {
6✔
4344
                return nil
3✔
4345
        }
3✔
4346

4347
        channel.LocalCommitment, err = fetchChanCommitment(chanBucket, true)
3✔
4348
        if err != nil {
3✔
4349
                return err
×
4350
        }
×
4351
        channel.RemoteCommitment, err = fetchChanCommitment(chanBucket, false)
3✔
4352
        if err != nil {
3✔
4353
                return err
×
4354
        }
×
4355

4356
        return nil
3✔
4357
}
4358

4359
func fetchChanRevocationState(chanBucket kvdb.RBucket, channel *OpenChannel) error {
3✔
4360
        revBytes := chanBucket.Get(revocationStateKey)
3✔
4361
        if revBytes == nil {
3✔
4362
                return ErrNoRevocationsFound
×
4363
        }
×
4364
        r := bytes.NewReader(revBytes)
3✔
4365

3✔
4366
        err := ReadElements(
3✔
4367
                r, &channel.RemoteCurrentRevocation, &channel.RevocationProducer,
3✔
4368
                &channel.RevocationStore,
3✔
4369
        )
3✔
4370
        if err != nil {
3✔
4371
                return err
×
4372
        }
×
4373

4374
        // If there aren't any bytes left in the buffer, then we don't yet have
4375
        // the next remote revocation, so we can exit early here.
4376
        if r.Len() == 0 {
6✔
4377
                return nil
3✔
4378
        }
3✔
4379

4380
        // Otherwise we'll read the next revocation for the remote party which
4381
        // is always the last item within the buffer.
4382
        return ReadElements(r, &channel.RemoteNextRevocation)
3✔
4383
}
4384

4385
func deleteOpenChannel(chanBucket kvdb.RwBucket) error {
3✔
4386
        if err := chanBucket.Delete(chanInfoKey); err != nil {
3✔
4387
                return err
×
4388
        }
×
4389

4390
        err := chanBucket.Delete(append(chanCommitmentKey, byte(0x00)))
3✔
4391
        if err != nil {
3✔
4392
                return err
×
4393
        }
×
4394
        err = chanBucket.Delete(append(chanCommitmentKey, byte(0x01)))
3✔
4395
        if err != nil {
3✔
4396
                return err
×
4397
        }
×
4398

4399
        if err := chanBucket.Delete(revocationStateKey); err != nil {
3✔
4400
                return err
×
4401
        }
×
4402

4403
        if diff := chanBucket.Get(commitDiffKey); diff != nil {
6✔
4404
                return chanBucket.Delete(commitDiffKey)
3✔
4405
        }
3✔
4406

4407
        return nil
3✔
4408
}
4409

4410
// makeLogKey converts a uint64 into an 8 byte array.
4411
func makeLogKey(updateNum uint64) [8]byte {
3✔
4412
        var key [8]byte
3✔
4413
        byteOrder.PutUint64(key[:], updateNum)
3✔
4414
        return key
3✔
4415
}
3✔
4416

4417
func fetchThawHeight(chanBucket kvdb.RBucket) (uint32, error) {
3✔
4418
        var height uint32
3✔
4419

3✔
4420
        heightBytes := chanBucket.Get(frozenChanKey)
3✔
4421
        heightReader := bytes.NewReader(heightBytes)
3✔
4422

3✔
4423
        if err := ReadElements(heightReader, &height); err != nil {
3✔
4424
                return 0, err
×
4425
        }
×
4426

4427
        return height, nil
3✔
4428
}
4429

4430
func storeThawHeight(chanBucket kvdb.RwBucket, height uint32) error {
3✔
4431
        var heightBuf bytes.Buffer
3✔
4432
        if err := WriteElements(&heightBuf, height); err != nil {
3✔
4433
                return err
×
4434
        }
×
4435

4436
        return chanBucket.Put(frozenChanKey, heightBuf.Bytes())
3✔
4437
}
4438

4439
func deleteThawHeight(chanBucket kvdb.RwBucket) error {
3✔
4440
        return chanBucket.Delete(frozenChanKey)
3✔
4441
}
3✔
4442

4443
// EKeyLocator is an encoder for keychain.KeyLocator.
4444
func EKeyLocator(w io.Writer, val interface{}, buf *[8]byte) error {
3✔
4445
        if v, ok := val.(*keychain.KeyLocator); ok {
6✔
4446
                err := tlv.EUint32T(w, uint32(v.Family), buf)
3✔
4447
                if err != nil {
3✔
4448
                        return err
×
4449
                }
×
4450

4451
                return tlv.EUint32T(w, v.Index, buf)
3✔
4452
        }
4453
        return tlv.NewTypeForEncodingErr(val, "keychain.KeyLocator")
×
4454
}
4455

4456
// DKeyLocator is a decoder for keychain.KeyLocator.
4457
func DKeyLocator(r io.Reader, val interface{}, buf *[8]byte, l uint64) error {
3✔
4458
        if v, ok := val.(*keychain.KeyLocator); ok {
6✔
4459
                var family uint32
3✔
4460
                err := tlv.DUint32(r, &family, buf, 4)
3✔
4461
                if err != nil {
3✔
4462
                        return err
×
4463
                }
×
4464
                v.Family = keychain.KeyFamily(family)
3✔
4465

3✔
4466
                return tlv.DUint32(r, &v.Index, buf, 4)
3✔
4467
        }
4468
        return tlv.NewTypeForDecodingErr(val, "keychain.KeyLocator", l, 8)
×
4469
}
4470

4471
// MakeKeyLocRecord creates a Record out of a KeyLocator using the passed
4472
// Type and the EKeyLocator and DKeyLocator functions. The size will always be
4473
// 8 as KeyFamily is uint32 and the Index is uint32.
4474
func MakeKeyLocRecord(typ tlv.Type, keyLoc *keychain.KeyLocator) tlv.Record {
3✔
4475
        return tlv.MakeStaticRecord(typ, keyLoc, 8, EKeyLocator, DKeyLocator)
3✔
4476
}
3✔
4477

4478
// MakeScidRecord creates a Record out of a ShortChannelID using the passed
4479
// Type and the EShortChannelID and DShortChannelID functions. The size will
4480
// always be 8 for the ShortChannelID.
4481
func MakeScidRecord(typ tlv.Type, scid *lnwire.ShortChannelID) tlv.Record {
3✔
4482
        return tlv.MakeStaticRecord(
3✔
4483
                typ, scid, 8, lnwire.EShortChannelID, lnwire.DShortChannelID,
3✔
4484
        )
3✔
4485
}
3✔
4486

4487
// ShutdownInfo contains various info about the shutdown initiation of a
4488
// channel.
4489
type ShutdownInfo struct {
4490
        // DeliveryScript is the address that we have included in any previous
4491
        // Shutdown message for a particular channel and so should include in
4492
        // any future re-sends of the Shutdown message.
4493
        DeliveryScript tlv.RecordT[tlv.TlvType0, lnwire.DeliveryAddress]
4494

4495
        // LocalInitiator is true if we sent a Shutdown message before ever
4496
        // receiving a Shutdown message from the remote peer.
4497
        LocalInitiator tlv.RecordT[tlv.TlvType1, bool]
4498
}
4499

4500
// NewShutdownInfo constructs a new ShutdownInfo object.
4501
func NewShutdownInfo(deliveryScript lnwire.DeliveryAddress,
4502
        locallyInitiated bool) *ShutdownInfo {
3✔
4503

3✔
4504
        return &ShutdownInfo{
3✔
4505
                DeliveryScript: tlv.NewRecordT[tlv.TlvType0](deliveryScript),
3✔
4506
                LocalInitiator: tlv.NewPrimitiveRecord[tlv.TlvType1](
3✔
4507
                        locallyInitiated,
3✔
4508
                ),
3✔
4509
        }
3✔
4510
}
3✔
4511

4512
// Closer identifies the ChannelParty that initiated the coop-closure process.
4513
func (s ShutdownInfo) Closer() lntypes.ChannelParty {
3✔
4514
        if s.LocalInitiator.Val {
6✔
4515
                return lntypes.Local
3✔
4516
        }
3✔
4517

4518
        return lntypes.Remote
3✔
4519
}
4520

4521
// encode serialises the ShutdownInfo to the given io.Writer.
4522
func (s *ShutdownInfo) encode(w io.Writer) error {
3✔
4523
        records := []tlv.Record{
3✔
4524
                s.DeliveryScript.Record(),
3✔
4525
                s.LocalInitiator.Record(),
3✔
4526
        }
3✔
4527

3✔
4528
        stream, err := tlv.NewStream(records...)
3✔
4529
        if err != nil {
3✔
4530
                return err
×
4531
        }
×
4532

4533
        return stream.Encode(w)
3✔
4534
}
4535

4536
// decodeShutdownInfo constructs a ShutdownInfo struct by decoding the given
4537
// byte slice.
4538
func decodeShutdownInfo(b []byte) (*ShutdownInfo, error) {
3✔
4539
        tlvStream := lnwire.ExtraOpaqueData(b)
3✔
4540

3✔
4541
        var info ShutdownInfo
3✔
4542
        records := []tlv.RecordProducer{
3✔
4543
                &info.DeliveryScript,
3✔
4544
                &info.LocalInitiator,
3✔
4545
        }
3✔
4546

3✔
4547
        _, err := tlvStream.ExtractRecords(records...)
3✔
4548

3✔
4549
        return &info, err
3✔
4550
}
3✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc