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

lightningnetwork / lnd / 15561477203

10 Jun 2025 01:54PM UTC coverage: 58.351% (-10.1%) from 68.487%
15561477203

Pull #9356

github

web-flow
Merge 6440b25db into c6d6d4c0b
Pull Request #9356: lnrpc: add incoming/outgoing channel ids filter to forwarding history request

33 of 36 new or added lines in 2 files covered. (91.67%)

28366 existing lines in 455 files now uncovered.

97715 of 167461 relevant lines covered (58.35%)

1.81 hits per line

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

0.0
/channeldb/migration_01_to_11/channel.go
1
package migration_01_to_11
2

3
import (
4
        "errors"
5
        "fmt"
6
        "io"
7
        "strconv"
8
        "strings"
9
        "sync"
10

11
        "github.com/btcsuite/btcd/btcec/v2"
12
        "github.com/btcsuite/btcd/btcutil"
13
        "github.com/btcsuite/btcd/chaincfg/chainhash"
14
        "github.com/btcsuite/btcd/wire"
15
        lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21"
16
        "github.com/lightningnetwork/lnd/keychain"
17
        "github.com/lightningnetwork/lnd/shachain"
18
)
19

20
var (
21
        // closedChannelBucket stores summarization information concerning
22
        // previously open, but now closed channels.
23
        closedChannelBucket = []byte("closed-chan-bucket")
24

25
        // openChanBucket stores all the currently open channels. This bucket
26
        // has a second, nested bucket which is keyed by a node's ID. Within
27
        // that node ID bucket, all attributes required to track, update, and
28
        // close a channel are stored.
29
        //
30
        // openChan -> nodeID -> chanPoint
31
        //
32
        // TODO(roasbeef): flesh out comment
33
        openChannelBucket = []byte("open-chan-bucket")
34
)
35

36
// ChannelType is an enum-like type that describes one of several possible
37
// channel types. Each open channel is associated with a particular type as the
38
// channel type may determine how higher level operations are conducted such as
39
// fee negotiation, channel closing, the format of HTLCs, etc.
40
// TODO(roasbeef): split up per-chain?
41
type ChannelType uint8
42

43
const (
44
        // NOTE: iota isn't used here for this enum needs to be stable
45
        // long-term as it will be persisted to the database.
46

47
        // SingleFunder represents a channel wherein one party solely funds the
48
        // entire capacity of the channel.
49
        SingleFunder ChannelType = 0
50
)
51

52
// ChannelConstraints represents a set of constraints meant to allow a node to
53
// limit their exposure, enact flow control and ensure that all HTLCs are
54
// economically relevant. This struct will be mirrored for both sides of the
55
// channel, as each side will enforce various constraints that MUST be adhered
56
// to for the life time of the channel. The parameters for each of these
57
// constraints are static for the duration of the channel, meaning the channel
58
// must be torn down for them to change.
59
type ChannelConstraints struct {
60
        // DustLimit is the threshold (in satoshis) below which any outputs
61
        // should be trimmed. When an output is trimmed, it isn't materialized
62
        // as an actual output, but is instead burned to miner's fees.
63
        DustLimit btcutil.Amount
64

65
        // ChanReserve is an absolute reservation on the channel for the
66
        // owner of this set of constraints. This means that the current
67
        // settled balance for this node CANNOT dip below the reservation
68
        // amount. This acts as a defense against costless attacks when
69
        // either side no longer has any skin in the game.
70
        ChanReserve btcutil.Amount
71

72
        // MaxPendingAmount is the maximum pending HTLC value that the
73
        // owner of these constraints can offer the remote node at a
74
        // particular time.
75
        MaxPendingAmount lnwire.MilliSatoshi
76

77
        // MinHTLC is the minimum HTLC value that the owner of these
78
        // constraints can offer the remote node. If any HTLCs below this
79
        // amount are offered, then the HTLC will be rejected. This, in
80
        // tandem with the dust limit allows a node to regulate the
81
        // smallest HTLC that it deems economically relevant.
82
        MinHTLC lnwire.MilliSatoshi
83

84
        // MaxAcceptedHtlcs is the maximum number of HTLCs that the owner of
85
        // this set of constraints can offer the remote node. This allows each
86
        // node to limit their over all exposure to HTLCs that may need to be
87
        // acted upon in the case of a unilateral channel closure or a contract
88
        // breach.
89
        MaxAcceptedHtlcs uint16
90

91
        // CsvDelay is the relative time lock delay expressed in blocks. Any
92
        // settled outputs that pay to the owner of this channel configuration
93
        // MUST ensure that the delay branch uses this value as the relative
94
        // time lock. Similarly, any HTLC's offered by this node should use
95
        // this value as well.
96
        CsvDelay uint16
97
}
98

99
// ChannelConfig is a struct that houses the various configuration opens for
100
// channels. Each side maintains an instance of this configuration file as it
101
// governs: how the funding and commitment transaction to be created, the
102
// nature of HTLC's allotted, the keys to be used for delivery, and relative
103
// time lock parameters.
104
type ChannelConfig struct {
105
        // ChannelConstraints is the set of constraints that must be upheld for
106
        // the duration of the channel for the owner of this channel
107
        // configuration. Constraints govern a number of flow control related
108
        // parameters, also including the smallest HTLC that will be accepted
109
        // by a participant.
110
        ChannelConstraints
111

112
        // MultiSigKey is the key to be used within the 2-of-2 output script
113
        // for the owner of this channel config.
114
        MultiSigKey keychain.KeyDescriptor
115

116
        // RevocationBasePoint is the base public key to be used when deriving
117
        // revocation keys for the remote node's commitment transaction. This
118
        // will be combined along with a per commitment secret to derive a
119
        // unique revocation key for each state.
120
        RevocationBasePoint keychain.KeyDescriptor
121

122
        // PaymentBasePoint is the base public key to be used when deriving
123
        // the key used within the non-delayed pay-to-self output on the
124
        // commitment transaction for a node. This will be combined with a
125
        // tweak derived from the per-commitment point to ensure unique keys
126
        // for each commitment transaction.
127
        PaymentBasePoint keychain.KeyDescriptor
128

129
        // DelayBasePoint is the base public key to be used when deriving the
130
        // key used within the delayed pay-to-self output on the commitment
131
        // transaction for a node. This will be combined with a tweak derived
132
        // from the per-commitment point to ensure unique keys for each
133
        // commitment transaction.
134
        DelayBasePoint keychain.KeyDescriptor
135

136
        // HtlcBasePoint is the base public key to be used when deriving the
137
        // local HTLC key. The derived key (combined with the tweak derived
138
        // from the per-commitment point) is used within the "to self" clause
139
        // within any HTLC output scripts.
140
        HtlcBasePoint keychain.KeyDescriptor
141
}
142

143
// ChannelCommitment is a snapshot of the commitment state at a particular
144
// point in the commitment chain. With each state transition, a snapshot of the
145
// current state along with all non-settled HTLCs are recorded. These snapshots
146
// detail the state of the _remote_ party's commitment at a particular state
147
// number.  For ourselves (the local node) we ONLY store our most recent
148
// (unrevoked) state for safety purposes.
149
type ChannelCommitment struct {
150
        // CommitHeight is the update number that this ChannelDelta represents
151
        // the total number of commitment updates to this point. This can be
152
        // viewed as sort of a "commitment height" as this number is
153
        // monotonically increasing.
154
        CommitHeight uint64
155

156
        // LocalLogIndex is the cumulative log index index of the local node at
157
        // this point in the commitment chain. This value will be incremented
158
        // for each _update_ added to the local update log.
159
        LocalLogIndex uint64
160

161
        // LocalHtlcIndex is the current local running HTLC index. This value
162
        // will be incremented for each outgoing HTLC the local node offers.
163
        LocalHtlcIndex uint64
164

165
        // RemoteLogIndex is the cumulative log index index of the remote node
166
        // at this point in the commitment chain. This value will be
167
        // incremented for each _update_ added to the remote update log.
168
        RemoteLogIndex uint64
169

170
        // RemoteHtlcIndex is the current remote running HTLC index. This value
171
        // will be incremented for each outgoing HTLC the remote node offers.
172
        RemoteHtlcIndex uint64
173

174
        // LocalBalance is the current available settled balance within the
175
        // channel directly spendable by us.
176
        LocalBalance lnwire.MilliSatoshi
177

178
        // RemoteBalance is the current available settled balance within the
179
        // channel directly spendable by the remote node.
180
        RemoteBalance lnwire.MilliSatoshi
181

182
        // CommitFee is the amount calculated to be paid in fees for the
183
        // current set of commitment transactions. The fee amount is persisted
184
        // with the channel in order to allow the fee amount to be removed and
185
        // recalculated with each channel state update, including updates that
186
        // happen after a system restart.
187
        CommitFee btcutil.Amount
188

189
        // FeePerKw is the min satoshis/kilo-weight that should be paid within
190
        // the commitment transaction for the entire duration of the channel's
191
        // lifetime. This field may be updated during normal operation of the
192
        // channel as on-chain conditions change.
193
        //
194
        // TODO(halseth): make this SatPerKWeight. Cannot be done atm because
195
        // this will cause the import cycle lnwallet<->channeldb. Fee
196
        // estimation stuff should be in its own package.
197
        FeePerKw btcutil.Amount
198

199
        // CommitTx is the latest version of the commitment state, broadcast
200
        // able by us.
201
        CommitTx *wire.MsgTx
202

203
        // CommitSig is one half of the signature required to fully complete
204
        // the script for the commitment transaction above. This is the
205
        // signature signed by the remote party for our version of the
206
        // commitment transactions.
207
        CommitSig []byte
208

209
        // Htlcs is the set of HTLC's that are pending at this particular
210
        // commitment height.
211
        Htlcs []HTLC
212

213
        // TODO(roasbeef): pending commit pointer?
214
        //  * lets just walk through
215
}
216

217
// ChannelStatus is a bit vector used to indicate whether an OpenChannel is in
218
// the default usable state, or a state where it shouldn't be used.
219
type ChannelStatus uint8
220

221
var (
222
        // ChanStatusDefault is the normal state of an open channel.
223
        ChanStatusDefault ChannelStatus
224

225
        // ChanStatusBorked indicates that the channel has entered an
226
        // irreconcilable state, triggered by a state desynchronization or
227
        // channel breach.  Channels in this state should never be added to the
228
        // htlc switch.
229
        ChanStatusBorked ChannelStatus = 1
230

231
        // ChanStatusCommitBroadcasted indicates that a commitment for this
232
        // channel has been broadcasted.
233
        ChanStatusCommitBroadcasted ChannelStatus = 1 << 1
234

235
        // ChanStatusLocalDataLoss indicates that we have lost channel state
236
        // for this channel, and broadcasting our latest commitment might be
237
        // considered a breach.
238
        //
239
        // TODO(halseh): actually enforce that we are not force closing such a
240
        // channel.
241
        ChanStatusLocalDataLoss ChannelStatus = 1 << 2
242

243
        // ChanStatusRestored is a status flag that signals that the channel
244
        // has been restored, and doesn't have all the fields a typical channel
245
        // will have.
246
        ChanStatusRestored ChannelStatus = 1 << 3
247
)
248

249
// chanStatusStrings maps a ChannelStatus to a human friendly string that
250
// describes that status.
251
var chanStatusStrings = map[ChannelStatus]string{
252
        ChanStatusDefault:           "ChanStatusDefault",
253
        ChanStatusBorked:            "ChanStatusBorked",
254
        ChanStatusCommitBroadcasted: "ChanStatusCommitBroadcasted",
255
        ChanStatusLocalDataLoss:     "ChanStatusLocalDataLoss",
256
        ChanStatusRestored:          "ChanStatusRestored",
257
}
258

259
// orderedChanStatusFlags is an in-order list of all that channel status flags.
260
var orderedChanStatusFlags = []ChannelStatus{
261
        ChanStatusDefault,
262
        ChanStatusBorked,
263
        ChanStatusCommitBroadcasted,
264
        ChanStatusLocalDataLoss,
265
        ChanStatusRestored,
266
}
267

268
// String returns a human-readable representation of the ChannelStatus.
269
func (c ChannelStatus) String() string {
×
270
        // If no flags are set, then this is the default case.
×
271
        if c == 0 {
×
272
                return chanStatusStrings[ChanStatusDefault]
×
273
        }
×
274

275
        // Add individual bit flags.
276
        statusStr := ""
×
277
        for _, flag := range orderedChanStatusFlags {
×
278
                if c&flag == flag {
×
279
                        statusStr += chanStatusStrings[flag] + "|"
×
280
                        c -= flag
×
281
                }
×
282
        }
283

284
        // Remove anything to the right of the final bar, including it as well.
285
        statusStr = strings.TrimRight(statusStr, "|")
×
286

×
287
        // Add any remaining flags which aren't accounted for as hex.
×
288
        if c != 0 {
×
289
                statusStr += "|0x" + strconv.FormatUint(uint64(c), 16)
×
290
        }
×
291

292
        // If this was purely an unknown flag, then remove the extra bar at the
293
        // start of the string.
294
        statusStr = strings.TrimLeft(statusStr, "|")
×
295

×
296
        return statusStr
×
297
}
298

299
// OpenChannel encapsulates the persistent and dynamic state of an open channel
300
// with a remote node. An open channel supports several options for on-disk
301
// serialization depending on the exact context. Full (upon channel creation)
302
// state commitments, and partial (due to a commitment update) writes are
303
// supported. Each partial write due to a state update appends the new update
304
// to an on-disk log, which can then subsequently be queried in order to
305
// "time-travel" to a prior state.
306
type OpenChannel struct {
307
        // ChanType denotes which type of channel this is.
308
        ChanType ChannelType
309

310
        // ChainHash is a hash which represents the blockchain that this
311
        // channel will be opened within. This value is typically the genesis
312
        // hash. In the case that the original chain went through a contentious
313
        // hard-fork, then this value will be tweaked using the unique fork
314
        // point on each branch.
315
        ChainHash chainhash.Hash
316

317
        // FundingOutpoint is the outpoint of the final funding transaction.
318
        // This value uniquely and globally identifies the channel within the
319
        // target blockchain as specified by the chain hash parameter.
320
        FundingOutpoint wire.OutPoint
321

322
        // ShortChannelID encodes the exact location in the chain in which the
323
        // channel was initially confirmed. This includes: the block height,
324
        // transaction index, and the output within the target transaction.
325
        ShortChannelID lnwire.ShortChannelID
326

327
        // IsPending indicates whether a channel's funding transaction has been
328
        // confirmed.
329
        IsPending bool
330

331
        // IsInitiator is a bool which indicates if we were the original
332
        // initiator for the channel. This value may affect how higher levels
333
        // negotiate fees, or close the channel.
334
        IsInitiator bool
335

336
        // FundingBroadcastHeight is the height in which the funding
337
        // transaction was broadcast. This value can be used by higher level
338
        // sub-systems to determine if a channel is stale and/or should have
339
        // been confirmed before a certain height.
340
        FundingBroadcastHeight uint32
341

342
        // NumConfsRequired is the number of confirmations a channel's funding
343
        // transaction must have received in order to be considered available
344
        // for normal transactional use.
345
        NumConfsRequired uint16
346

347
        // ChannelFlags holds the flags that were sent as part of the
348
        // open_channel message.
349
        ChannelFlags lnwire.FundingFlag
350

351
        // IdentityPub is the identity public key of the remote node this
352
        // channel has been established with.
353
        IdentityPub *btcec.PublicKey
354

355
        // Capacity is the total capacity of this channel.
356
        Capacity btcutil.Amount
357

358
        // TotalMSatSent is the total number of milli-satoshis we've sent
359
        // within this channel.
360
        TotalMSatSent lnwire.MilliSatoshi
361

362
        // TotalMSatReceived is the total number of milli-satoshis we've
363
        // received within this channel.
364
        TotalMSatReceived lnwire.MilliSatoshi
365

366
        // LocalChanCfg is the channel configuration for the local node.
367
        LocalChanCfg ChannelConfig
368

369
        // RemoteChanCfg is the channel configuration for the remote node.
370
        RemoteChanCfg ChannelConfig
371

372
        // LocalCommitment is the current local commitment state for the local
373
        // party. This is stored distinct from the state of the remote party
374
        // as there are certain asymmetric parameters which affect the
375
        // structure of each commitment.
376
        LocalCommitment ChannelCommitment
377

378
        // RemoteCommitment is the current remote commitment state for the
379
        // remote party. This is stored distinct from the state of the local
380
        // party as there are certain asymmetric parameters which affect the
381
        // structure of each commitment.
382
        RemoteCommitment ChannelCommitment
383

384
        // RemoteCurrentRevocation is the current revocation for their
385
        // commitment transaction. However, since this the derived public key,
386
        // we don't yet have the private key so we aren't yet able to verify
387
        // that it's actually in the hash chain.
388
        RemoteCurrentRevocation *btcec.PublicKey
389

390
        // RemoteNextRevocation is the revocation key to be used for the *next*
391
        // commitment transaction we create for the local node. Within the
392
        // specification, this value is referred to as the
393
        // per-commitment-point.
394
        RemoteNextRevocation *btcec.PublicKey
395

396
        // RevocationProducer is used to generate the revocation in such a way
397
        // that remote side might store it efficiently and have the ability to
398
        // restore the revocation by index if needed. Current implementation of
399
        // secret producer is shachain producer.
400
        RevocationProducer shachain.Producer
401

402
        // RevocationStore is used to efficiently store the revocations for
403
        // previous channels states sent to us by remote side. Current
404
        // implementation of secret store is shachain store.
405
        RevocationStore shachain.Store
406

407
        // FundingTxn is the transaction containing this channel's funding
408
        // outpoint. Upon restarts, this txn will be rebroadcast if the channel
409
        // is found to be pending.
410
        //
411
        // NOTE: This value will only be populated for single-funder channels
412
        // for which we are the initiator.
413
        FundingTxn *wire.MsgTx
414

415
        // TODO(roasbeef): eww
416
        Db *DB
417

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

420
        sync.RWMutex
421
}
422

423
// ShortChanID returns the current ShortChannelID of this channel.
UNCOV
424
func (c *OpenChannel) ShortChanID() lnwire.ShortChannelID {
×
UNCOV
425
        c.RLock()
×
UNCOV
426
        defer c.RUnlock()
×
UNCOV
427

×
UNCOV
428
        return c.ShortChannelID
×
UNCOV
429
}
×
430

431
// HTLC is the on-disk representation of a hash time-locked contract. HTLCs are
432
// contained within ChannelDeltas which encode the current state of the
433
// commitment between state updates.
434
//
435
// TODO(roasbeef): save space by using smaller ints at tail end?
436
type HTLC struct {
437
        // Signature is the signature for the second level covenant transaction
438
        // for this HTLC. The second level transaction is a timeout tx in the
439
        // case that this is an outgoing HTLC, and a success tx in the case
440
        // that this is an incoming HTLC.
441
        //
442
        // TODO(roasbeef): make [64]byte instead?
443
        Signature []byte
444

445
        // RHash is the payment hash of the HTLC.
446
        RHash [32]byte
447

448
        // Amt is the amount of milli-satoshis this HTLC escrows.
449
        Amt lnwire.MilliSatoshi
450

451
        // RefundTimeout is the absolute timeout on the HTLC that the sender
452
        // must wait before reclaiming the funds in limbo.
453
        RefundTimeout uint32
454

455
        // OutputIndex is the output index for this particular HTLC output
456
        // within the commitment transaction.
457
        OutputIndex int32
458

459
        // Incoming denotes whether we're the receiver or the sender of this
460
        // HTLC.
461
        Incoming bool
462

463
        // OnionBlob is an opaque blob which is used to complete multi-hop
464
        // routing.
465
        OnionBlob []byte
466

467
        // HtlcIndex is the HTLC counter index of this active, outstanding
468
        // HTLC. This differs from the LogIndex, as the HtlcIndex is only
469
        // incremented for each offered HTLC, while they LogIndex is
470
        // incremented for each update (includes settle+fail).
471
        HtlcIndex uint64
472

473
        // LogIndex is the cumulative log index of this HTLC. This differs
474
        // from the HtlcIndex as this will be incremented for each new log
475
        // update added.
476
        LogIndex uint64
477
}
478

479
// CircuitKey is used by a channel to uniquely identify the HTLCs it receives
480
// from the switch, and is used to purge our in-memory state of HTLCs that have
481
// already been processed by a link. Two list of CircuitKeys are included in
482
// each CommitDiff to allow a link to determine which in-memory htlcs directed
483
// the opening and closing of circuits in the switch's circuit map.
484
type CircuitKey struct {
485
        // ChanID is the short chanid indicating the HTLC's origin.
486
        //
487
        // NOTE: It is fine for this value to be blank, as this indicates a
488
        // locally-sourced payment.
489
        ChanID lnwire.ShortChannelID
490

491
        // HtlcID is the unique htlc index predominately assigned by links,
492
        // though can also be assigned by switch in the case of locally-sourced
493
        // payments.
494
        HtlcID uint64
495
}
496

497
// String returns a string representation of the CircuitKey.
498
func (k CircuitKey) String() string {
×
499
        return fmt.Sprintf("(Chan ID=%s, HTLC ID=%d)", k.ChanID, k.HtlcID)
×
500
}
×
501

502
// ClosureType is an enum like structure that details exactly _how_ a channel
503
// was closed. Three closure types are currently possible: none, cooperative,
504
// local force close, remote force close, and (remote) breach.
505
type ClosureType uint8
506

507
const (
508
        // RemoteForceClose indicates that the remote peer has unilaterally
509
        // broadcast their current commitment state on-chain.
510
        RemoteForceClose ClosureType = 4
511
)
512

513
// ChannelCloseSummary contains the final state of a channel at the point it
514
// was closed. Once a channel is closed, all the information pertaining to that
515
// channel within the openChannelBucket is deleted, and a compact summary is
516
// put in place instead.
517
type ChannelCloseSummary struct {
518
        // ChanPoint is the outpoint for this channel's funding transaction,
519
        // and is used as a unique identifier for the channel.
520
        ChanPoint wire.OutPoint
521

522
        // ShortChanID encodes the exact location in the chain in which the
523
        // channel was initially confirmed. This includes: the block height,
524
        // transaction index, and the output within the target transaction.
525
        ShortChanID lnwire.ShortChannelID
526

527
        // ChainHash is the hash of the genesis block that this channel resides
528
        // within.
529
        ChainHash chainhash.Hash
530

531
        // ClosingTXID is the txid of the transaction which ultimately closed
532
        // this channel.
533
        ClosingTXID chainhash.Hash
534

535
        // RemotePub is the public key of the remote peer that we formerly had
536
        // a channel with.
537
        RemotePub *btcec.PublicKey
538

539
        // Capacity was the total capacity of the channel.
540
        Capacity btcutil.Amount
541

542
        // CloseHeight is the height at which the funding transaction was
543
        // spent.
544
        CloseHeight uint32
545

546
        // SettledBalance is our total balance settled balance at the time of
547
        // channel closure. This _does not_ include the sum of any outputs that
548
        // have been time-locked as a result of the unilateral channel closure.
549
        SettledBalance btcutil.Amount
550

551
        // TimeLockedBalance is the sum of all the time-locked outputs at the
552
        // time of channel closure. If we triggered the force closure of this
553
        // channel, then this value will be non-zero if our settled output is
554
        // above the dust limit. If we were on the receiving side of a channel
555
        // force closure, then this value will be non-zero if we had any
556
        // outstanding outgoing HTLC's at the time of channel closure.
557
        TimeLockedBalance btcutil.Amount
558

559
        // CloseType details exactly _how_ the channel was closed. Five closure
560
        // types are possible: cooperative, local force, remote force, breach
561
        // and funding canceled.
562
        CloseType ClosureType
563

564
        // IsPending indicates whether this channel is in the 'pending close'
565
        // state, which means the channel closing transaction has been
566
        // confirmed, but not yet been fully resolved. In the case of a channel
567
        // that has been cooperatively closed, it will go straight into the
568
        // fully resolved state as soon as the closing transaction has been
569
        // confirmed. However, for channels that have been force closed, they'll
570
        // stay marked as "pending" until _all_ the pending funds have been
571
        // swept.
572
        IsPending bool
573

574
        // RemoteCurrentRevocation is the current revocation for their
575
        // commitment transaction. However, since this is the derived public key,
576
        // we don't yet have the private key so we aren't yet able to verify
577
        // that it's actually in the hash chain.
578
        RemoteCurrentRevocation *btcec.PublicKey
579

580
        // RemoteNextRevocation is the revocation key to be used for the *next*
581
        // commitment transaction we create for the local node. Within the
582
        // specification, this value is referred to as the
583
        // per-commitment-point.
584
        RemoteNextRevocation *btcec.PublicKey
585

586
        // LocalChanConfig is the channel configuration for the local node.
587
        LocalChanConfig ChannelConfig
588

589
        // LastChanSyncMsg is the ChannelReestablish message for this channel
590
        // for the state at the point where it was closed.
591
        LastChanSyncMsg *lnwire.ChannelReestablish
592
}
593

UNCOV
594
func serializeChannelCloseSummary(w io.Writer, cs *ChannelCloseSummary) error {
×
UNCOV
595
        err := WriteElements(w,
×
UNCOV
596
                cs.ChanPoint, cs.ShortChanID, cs.ChainHash, cs.ClosingTXID,
×
UNCOV
597
                cs.CloseHeight, cs.RemotePub, cs.Capacity, cs.SettledBalance,
×
UNCOV
598
                cs.TimeLockedBalance, cs.CloseType, cs.IsPending,
×
UNCOV
599
        )
×
UNCOV
600
        if err != nil {
×
601
                return err
×
602
        }
×
603

604
        // If this is a close channel summary created before the addition of
605
        // the new fields, then we can exit here.
UNCOV
606
        if cs.RemoteCurrentRevocation == nil {
×
UNCOV
607
                return WriteElements(w, false)
×
UNCOV
608
        }
×
609

610
        // If fields are present, write boolean to indicate this, and continue.
UNCOV
611
        if err := WriteElements(w, true); err != nil {
×
612
                return err
×
613
        }
×
614

UNCOV
615
        if err := WriteElements(w, cs.RemoteCurrentRevocation); err != nil {
×
616
                return err
×
617
        }
×
618

UNCOV
619
        if err := WriteChanConfig(w, &cs.LocalChanConfig); err != nil {
×
620
                return err
×
621
        }
×
622

623
        // The RemoteNextRevocation field is optional, as it's possible for a
624
        // channel to be closed before we learn of the next unrevoked
625
        // revocation point for the remote party. Write a boolean indicating
626
        // whether this field is present or not.
UNCOV
627
        if err := WriteElements(w, cs.RemoteNextRevocation != nil); err != nil {
×
628
                return err
×
629
        }
×
630

631
        // Write the field, if present.
UNCOV
632
        if cs.RemoteNextRevocation != nil {
×
UNCOV
633
                if err = WriteElements(w, cs.RemoteNextRevocation); err != nil {
×
634
                        return err
×
635
                }
×
636
        }
637

638
        // Write whether the channel sync message is present.
UNCOV
639
        if err := WriteElements(w, cs.LastChanSyncMsg != nil); err != nil {
×
640
                return err
×
641
        }
×
642

643
        // Write the channel sync message, if present.
UNCOV
644
        if cs.LastChanSyncMsg != nil {
×
645
                if err := WriteElements(w, cs.LastChanSyncMsg); err != nil {
×
646
                        return err
×
647
                }
×
648
        }
649

UNCOV
650
        return nil
×
651
}
652

UNCOV
653
func deserializeCloseChannelSummary(r io.Reader) (*ChannelCloseSummary, error) {
×
UNCOV
654
        c := &ChannelCloseSummary{}
×
UNCOV
655

×
UNCOV
656
        err := ReadElements(r,
×
UNCOV
657
                &c.ChanPoint, &c.ShortChanID, &c.ChainHash, &c.ClosingTXID,
×
UNCOV
658
                &c.CloseHeight, &c.RemotePub, &c.Capacity, &c.SettledBalance,
×
UNCOV
659
                &c.TimeLockedBalance, &c.CloseType, &c.IsPending,
×
UNCOV
660
        )
×
UNCOV
661
        if err != nil {
×
662
                return nil, err
×
663
        }
×
664

665
        // We'll now check to see if the channel close summary was encoded with
666
        // any of the additional optional fields.
UNCOV
667
        var hasNewFields bool
×
UNCOV
668
        err = ReadElements(r, &hasNewFields)
×
UNCOV
669
        if err != nil {
×
670
                return nil, err
×
671
        }
×
672

673
        // If fields are not present, we can return.
UNCOV
674
        if !hasNewFields {
×
UNCOV
675
                return c, nil
×
UNCOV
676
        }
×
677

678
        // Otherwise read the new fields.
UNCOV
679
        if err := ReadElements(r, &c.RemoteCurrentRevocation); err != nil {
×
680
                return nil, err
×
681
        }
×
682

UNCOV
683
        if err := ReadChanConfig(r, &c.LocalChanConfig); err != nil {
×
684
                return nil, err
×
685
        }
×
686

687
        // Finally, we'll attempt to read the next unrevoked commitment point
688
        // for the remote party. If we closed the channel before receiving a
689
        // funding locked message then this might not be present. A boolean
690
        // indicating whether the field is present will come first.
UNCOV
691
        var hasRemoteNextRevocation bool
×
UNCOV
692
        err = ReadElements(r, &hasRemoteNextRevocation)
×
UNCOV
693
        if err != nil {
×
694
                return nil, err
×
695
        }
×
696

697
        // If this field was written, read it.
UNCOV
698
        if hasRemoteNextRevocation {
×
UNCOV
699
                err = ReadElements(r, &c.RemoteNextRevocation)
×
UNCOV
700
                if err != nil {
×
701
                        return nil, err
×
702
                }
×
703
        }
704

705
        // Check if we have a channel sync message to read.
UNCOV
706
        var hasChanSyncMsg bool
×
UNCOV
707
        err = ReadElements(r, &hasChanSyncMsg)
×
UNCOV
708
        if err == io.EOF {
×
709
                return c, nil
×
UNCOV
710
        } else if err != nil {
×
711
                return nil, err
×
712
        }
×
713

714
        // If a chan sync message is present, read it.
UNCOV
715
        if hasChanSyncMsg {
×
716
                // We must pass in reference to a lnwire.Message for the codec
×
717
                // to support it.
×
718
                var msg lnwire.Message
×
719
                if err := ReadElements(r, &msg); err != nil {
×
720
                        return nil, err
×
721
                }
×
722

723
                chanSync, ok := msg.(*lnwire.ChannelReestablish)
×
724
                if !ok {
×
725
                        return nil, errors.New("unable cast db Message to " +
×
726
                                "ChannelReestablish")
×
727
                }
×
728
                c.LastChanSyncMsg = chanSync
×
729
        }
730

UNCOV
731
        return c, nil
×
732
}
733

UNCOV
734
func WriteChanConfig(b io.Writer, c *ChannelConfig) error {
×
UNCOV
735
        return WriteElements(b,
×
UNCOV
736
                c.DustLimit, c.MaxPendingAmount, c.ChanReserve, c.MinHTLC,
×
UNCOV
737
                c.MaxAcceptedHtlcs, c.CsvDelay, c.MultiSigKey,
×
UNCOV
738
                c.RevocationBasePoint, c.PaymentBasePoint, c.DelayBasePoint,
×
UNCOV
739
                c.HtlcBasePoint,
×
UNCOV
740
        )
×
UNCOV
741
}
×
742

UNCOV
743
func ReadChanConfig(b io.Reader, c *ChannelConfig) error {
×
UNCOV
744
        return ReadElements(b,
×
UNCOV
745
                &c.DustLimit, &c.MaxPendingAmount, &c.ChanReserve,
×
UNCOV
746
                &c.MinHTLC, &c.MaxAcceptedHtlcs, &c.CsvDelay,
×
UNCOV
747
                &c.MultiSigKey, &c.RevocationBasePoint,
×
UNCOV
748
                &c.PaymentBasePoint, &c.DelayBasePoint,
×
UNCOV
749
                &c.HtlcBasePoint,
×
UNCOV
750
        )
×
UNCOV
751
}
×
752

UNCOV
753
func DeserializeChanCommit(r io.Reader) (ChannelCommitment, error) {
×
UNCOV
754
        var c ChannelCommitment
×
UNCOV
755

×
UNCOV
756
        err := ReadElements(r,
×
UNCOV
757
                &c.CommitHeight, &c.LocalLogIndex, &c.LocalHtlcIndex, &c.RemoteLogIndex,
×
UNCOV
758
                &c.RemoteHtlcIndex, &c.LocalBalance, &c.RemoteBalance,
×
UNCOV
759
                &c.CommitFee, &c.FeePerKw, &c.CommitTx, &c.CommitSig,
×
UNCOV
760
        )
×
UNCOV
761
        if err != nil {
×
762
                return c, err
×
763
        }
×
764

UNCOV
765
        c.Htlcs, err = DeserializeHtlcs(r)
×
UNCOV
766
        if err != nil {
×
767
                return c, err
×
768
        }
×
769

UNCOV
770
        return c, nil
×
771
}
772

773
// DeserializeHtlcs attempts to read out a slice of HTLC's from the passed
774
// io.Reader. The bytes within the passed reader MUST have been previously
775
// written to using the SerializeHtlcs function.
776
//
777
// NOTE: This API is NOT stable, the on-disk format will likely change in the
778
// future.
UNCOV
779
func DeserializeHtlcs(r io.Reader) ([]HTLC, error) {
×
UNCOV
780
        var numHtlcs uint16
×
UNCOV
781
        if err := ReadElement(r, &numHtlcs); err != nil {
×
782
                return nil, err
×
783
        }
×
784

UNCOV
785
        var htlcs []HTLC
×
UNCOV
786
        if numHtlcs == 0 {
×
UNCOV
787
                return htlcs, nil
×
UNCOV
788
        }
×
789

UNCOV
790
        htlcs = make([]HTLC, numHtlcs)
×
UNCOV
791
        for i := uint16(0); i < numHtlcs; i++ {
×
UNCOV
792
                if err := ReadElements(r,
×
UNCOV
793
                        &htlcs[i].Signature, &htlcs[i].RHash, &htlcs[i].Amt,
×
UNCOV
794
                        &htlcs[i].RefundTimeout, &htlcs[i].OutputIndex,
×
UNCOV
795
                        &htlcs[i].Incoming, &htlcs[i].OnionBlob,
×
UNCOV
796
                        &htlcs[i].HtlcIndex, &htlcs[i].LogIndex,
×
UNCOV
797
                ); err != nil {
×
798
                        return htlcs, err
×
799
                }
×
800
        }
801

UNCOV
802
        return htlcs, nil
×
803
}
804

UNCOV
805
func SerializeChanCommit(w io.Writer, c *ChannelCommitment) error {
×
UNCOV
806
        if err := WriteElements(w,
×
UNCOV
807
                c.CommitHeight, c.LocalLogIndex, c.LocalHtlcIndex,
×
UNCOV
808
                c.RemoteLogIndex, c.RemoteHtlcIndex, c.LocalBalance,
×
UNCOV
809
                c.RemoteBalance, c.CommitFee, c.FeePerKw, c.CommitTx,
×
UNCOV
810
                c.CommitSig,
×
UNCOV
811
        ); err != nil {
×
812
                return err
×
813
        }
×
814

UNCOV
815
        return SerializeHtlcs(w, c.Htlcs...)
×
816
}
817

818
// SerializeHtlcs writes out the passed set of HTLC's into the passed writer
819
// using the current default on-disk serialization format.
820
//
821
// NOTE: This API is NOT stable, the on-disk format will likely change in the
822
// future.
UNCOV
823
func SerializeHtlcs(b io.Writer, htlcs ...HTLC) error {
×
UNCOV
824
        numHtlcs := uint16(len(htlcs))
×
UNCOV
825
        if err := WriteElement(b, numHtlcs); err != nil {
×
826
                return err
×
827
        }
×
828

UNCOV
829
        for _, htlc := range htlcs {
×
UNCOV
830
                if err := WriteElements(b,
×
UNCOV
831
                        htlc.Signature, htlc.RHash, htlc.Amt, htlc.RefundTimeout,
×
UNCOV
832
                        htlc.OutputIndex, htlc.Incoming, htlc.OnionBlob[:],
×
UNCOV
833
                        htlc.HtlcIndex, htlc.LogIndex,
×
UNCOV
834
                ); err != nil {
×
835
                        return err
×
836
                }
×
837
        }
838

UNCOV
839
        return nil
×
840
}
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