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

lightningnetwork / lnd / 14880107727

07 May 2025 09:35AM UTC coverage: 58.446% (-10.5%) from 68.992%
14880107727

Pull #9789

github

web-flow
Merge ed3471042 into 67a40c90a
Pull Request #9789: multi: use updated TLV SizeFunc signature

54 of 95 new or added lines in 19 files covered. (56.84%)

28462 existing lines in 449 files now uncovered.

97165 of 166247 relevant lines covered (58.45%)

1.81 hits per line

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

0.0
/channeldb/migration30/revocation_log.go
1
package migration30
2

3
import (
4
        "bytes"
5
        "errors"
6
        "io"
7
        "math"
8

9
        "github.com/btcsuite/btcd/btcutil"
10
        lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21"
11
        mig24 "github.com/lightningnetwork/lnd/channeldb/migration24"
12
        mig25 "github.com/lightningnetwork/lnd/channeldb/migration25"
13
        mig26 "github.com/lightningnetwork/lnd/channeldb/migration26"
14
        mig "github.com/lightningnetwork/lnd/channeldb/migration_01_to_11"
15
        "github.com/lightningnetwork/lnd/kvdb"
16
        "github.com/lightningnetwork/lnd/lntypes"
17
        "github.com/lightningnetwork/lnd/tlv"
18
)
19

20
const (
21
        // OutputIndexEmpty is used when the output index doesn't exist.
22
        OutputIndexEmpty = math.MaxUint16
23

24
        // A set of tlv type definitions used to serialize the body of
25
        // revocation logs to the database.
26
        //
27
        // NOTE: A migration should be added whenever this list changes.
28
        revLogOurOutputIndexType   tlv.Type = 0
29
        revLogTheirOutputIndexType tlv.Type = 1
30
        revLogCommitTxHashType     tlv.Type = 2
31
        revLogOurBalanceType       tlv.Type = 3
32
        revLogTheirBalanceType     tlv.Type = 4
33
)
34

35
var (
36
        // revocationLogBucketDeprecated is dedicated for storing the necessary
37
        // delta state between channel updates required to re-construct a past
38
        // state in order to punish a counterparty attempting a non-cooperative
39
        // channel closure. This key should be accessed from within the
40
        // sub-bucket of a target channel, identified by its channel point.
41
        //
42
        // Deprecated: This bucket is kept for read-only in case the user
43
        // choose not to migrate the old data.
44
        revocationLogBucketDeprecated = []byte("revocation-log-key")
45

46
        // revocationLogBucket is a sub-bucket under openChannelBucket. This
47
        // sub-bucket is dedicated for storing the minimal info required to
48
        // re-construct a past state in order to punish a counterparty
49
        // attempting a non-cooperative channel closure.
50
        revocationLogBucket = []byte("revocation-log")
51

52
        // revocationStateKey stores their current revocation hash, our
53
        // preimage producer and their preimage store.
54
        revocationStateKey = []byte("revocation-state-key")
55

56
        // ErrNoRevocationsFound is returned when revocation state for a
57
        // particular channel cannot be found.
58
        ErrNoRevocationsFound = errors.New("no revocations found")
59

60
        // ErrLogEntryNotFound is returned when we cannot find a log entry at
61
        // the height requested in the revocation log.
62
        ErrLogEntryNotFound = errors.New("log entry not found")
63

64
        // ErrOutputIndexTooBig is returned when the output index is greater
65
        // than uint16.
66
        ErrOutputIndexTooBig = errors.New("output index is over uint16")
67
)
68

69
// HTLCEntry specifies the minimal info needed to be stored on disk for ALL the
70
// historical HTLCs, which is useful for constructing RevocationLog when a
71
// breach is detected.
72
// The actual size of each HTLCEntry varies based on its RHash and Amt(sat),
73
// summarized as follows,
74
//
75
//        | RHash empty | Amt<=252 | Amt<=65,535 | Amt<=4,294,967,295 | otherwise |
76
//        |:-----------:|:--------:|:-----------:|:------------------:|:---------:|
77
//        |     true    |    19    |      21     |         23         |     26    |
78
//        |     false   |    51    |      53     |         55         |     58    |
79
//
80
// So the size varies from 19 bytes to 58 bytes, where most likely to be 23 or
81
// 55 bytes.
82
//
83
// NOTE: all the fields saved to disk use the primitive go types so they can be
84
// made into tlv records without further conversion.
85
type HTLCEntry struct {
86
        // RHash is the payment hash of the HTLC.
87
        RHash [32]byte
88

89
        // RefundTimeout is the absolute timeout on the HTLC that the sender
90
        // must wait before reclaiming the funds in limbo.
91
        RefundTimeout uint32
92

93
        // OutputIndex is the output index for this particular HTLC output
94
        // within the commitment transaction.
95
        //
96
        // NOTE: we use uint16 instead of int32 here to save us 2 bytes, which
97
        // gives us a max number of HTLCs of 65K.
98
        OutputIndex uint16
99

100
        // Incoming denotes whether we're the receiver or the sender of this
101
        // HTLC.
102
        //
103
        // NOTE: this field is the memory representation of the field
104
        // incomingUint.
105
        Incoming bool
106

107
        // Amt is the amount of satoshis this HTLC escrows.
108
        //
109
        // NOTE: this field is the memory representation of the field amtUint.
110
        Amt btcutil.Amount
111

112
        // amtTlv is the uint64 format of Amt. This field is created so we can
113
        // easily make it into a tlv record and save it to disk.
114
        //
115
        // NOTE: we keep this field for accounting purpose only. If the disk
116
        // space becomes an issue, we could delete this field to save us extra
117
        // 8 bytes.
118
        amtTlv uint64
119

120
        // incomingTlv is the uint8 format of Incoming. This field is created
121
        // so we can easily make it into a tlv record and save it to disk.
122
        incomingTlv uint8
123
}
124

125
// RHashLen is used by MakeDynamicRecord to return the size of the RHash.
126
//
127
// NOTE: for zero hash, we return a length 0.
UNCOV
128
func (h *HTLCEntry) RHashLen() uint64 {
×
UNCOV
129
        if h.RHash == lntypes.ZeroHash {
×
130
                return 0
×
131
        }
×
UNCOV
132
        return 32
×
133
}
134

135
// RHashEncoder is the customized encoder which skips encoding the empty hash.
UNCOV
136
func RHashEncoder(w io.Writer, val interface{}, buf *[8]byte) error {
×
UNCOV
137
        v, ok := val.(*[32]byte)
×
UNCOV
138
        if !ok {
×
139
                return tlv.NewTypeForEncodingErr(val, "RHash")
×
140
        }
×
141

142
        // If the value is an empty hash, we will skip encoding it.
UNCOV
143
        if *v == lntypes.ZeroHash {
×
144
                return nil
×
145
        }
×
146

UNCOV
147
        return tlv.EBytes32(w, v, buf)
×
148
}
149

150
// RHashDecoder is the customized decoder which skips decoding the empty hash.
UNCOV
151
func RHashDecoder(r io.Reader, val interface{}, buf *[8]byte, l uint64) error {
×
UNCOV
152
        v, ok := val.(*[32]byte)
×
UNCOV
153
        if !ok {
×
154
                return tlv.NewTypeForEncodingErr(val, "RHash")
×
155
        }
×
156

157
        // If the length is zero, we will skip encoding the empty hash.
UNCOV
158
        if l == 0 {
×
159
                return nil
×
160
        }
×
161

UNCOV
162
        return tlv.DBytes32(r, v, buf, 32)
×
163
}
164

165
// toTlvStream converts an HTLCEntry record into a tlv representation.
UNCOV
166
func (h *HTLCEntry) toTlvStream() (*tlv.Stream, error) {
×
UNCOV
167
        const (
×
UNCOV
168
                // A set of tlv type definitions used to serialize htlc entries
×
UNCOV
169
                // to the database. We define it here instead of the head of
×
UNCOV
170
                // the file to avoid naming conflicts.
×
UNCOV
171
                //
×
UNCOV
172
                // NOTE: A migration should be added whenever this list
×
UNCOV
173
                // changes.
×
UNCOV
174
                rHashType         tlv.Type = 0
×
UNCOV
175
                refundTimeoutType tlv.Type = 1
×
UNCOV
176
                outputIndexType   tlv.Type = 2
×
UNCOV
177
                incomingType      tlv.Type = 3
×
UNCOV
178
                amtType           tlv.Type = 4
×
UNCOV
179
        )
×
UNCOV
180

×
UNCOV
181
        return tlv.NewStream(
×
UNCOV
182
                tlv.MakeDynamicRecord(
×
NEW
183
                        rHashType, &h.RHash, func() (uint64, error) {
×
NEW
184
                                return h.RHashLen(), nil
×
NEW
185
                        },
×
186
                        RHashEncoder, RHashDecoder,
187
                ),
188
                tlv.MakePrimitiveRecord(
189
                        refundTimeoutType, &h.RefundTimeout,
190
                ),
191
                tlv.MakePrimitiveRecord(
192
                        outputIndexType, &h.OutputIndex,
193
                ),
194
                tlv.MakePrimitiveRecord(incomingType, &h.incomingTlv),
195
                // We will save 3 bytes if the amount is less or equal to
196
                // 4,294,967,295 msat, or roughly 0.043 bitcoin.
197
                tlv.MakeBigSizeRecord(amtType, &h.amtTlv),
198
        )
199
}
200

201
// RevocationLog stores the info needed to construct a breach retribution. Its
202
// fields can be viewed as a subset of a ChannelCommitment's. In the database,
203
// all historical versions of the RevocationLog are saved using the
204
// CommitHeight as the key.
205
type RevocationLog struct {
206
        // OurOutputIndex specifies our output index in this commitment. In a
207
        // remote commitment transaction, this is the to remote output index.
208
        OurOutputIndex uint16
209

210
        // TheirOutputIndex specifies their output index in this commitment. In
211
        // a remote commitment transaction, this is the to local output index.
212
        TheirOutputIndex uint16
213

214
        // CommitTxHash is the hash of the latest version of the commitment
215
        // state, broadcast able by us.
216
        CommitTxHash [32]byte
217

218
        // HTLCEntries is the set of HTLCEntry's that are pending at this
219
        // particular commitment height.
220
        HTLCEntries []*HTLCEntry
221

222
        // OurBalance is the current available balance within the channel
223
        // directly spendable by us. In other words, it is the value of the
224
        // to_remote output on the remote parties' commitment transaction.
225
        //
226
        // NOTE: this is a pointer so that it is clear if the value is zero or
227
        // nil. Since migration 30 of the channeldb initially did not include
228
        // this field, it could be the case that the field is not present for
229
        // all revocation logs.
230
        OurBalance *lnwire.MilliSatoshi
231

232
        // TheirBalance is the current available balance within the channel
233
        // directly spendable by the remote node. In other words, it is the
234
        // value of the to_local output on the remote parties' commitment.
235
        //
236
        // NOTE: this is a pointer so that it is clear if the value is zero or
237
        // nil. Since migration 30 of the channeldb initially did not include
238
        // this field, it could be the case that the field is not present for
239
        // all revocation logs.
240
        TheirBalance *lnwire.MilliSatoshi
241
}
242

243
// putRevocationLog uses the fields `CommitTx` and `Htlcs` from a
244
// ChannelCommitment to construct a revocation log entry and saves them to
245
// disk. It also saves our output index and their output index, which are
246
// useful when creating breach retribution.
247
func putRevocationLog(bucket kvdb.RwBucket, commit *mig.ChannelCommitment,
UNCOV
248
        ourOutputIndex, theirOutputIndex uint32, noAmtData bool) error {
×
UNCOV
249

×
UNCOV
250
        // Sanity check that the output indexes can be safely converted.
×
UNCOV
251
        if ourOutputIndex > math.MaxUint16 {
×
252
                return ErrOutputIndexTooBig
×
253
        }
×
UNCOV
254
        if theirOutputIndex > math.MaxUint16 {
×
255
                return ErrOutputIndexTooBig
×
256
        }
×
257

UNCOV
258
        rl := &RevocationLog{
×
UNCOV
259
                OurOutputIndex:   uint16(ourOutputIndex),
×
UNCOV
260
                TheirOutputIndex: uint16(theirOutputIndex),
×
UNCOV
261
                CommitTxHash:     commit.CommitTx.TxHash(),
×
UNCOV
262
                HTLCEntries:      make([]*HTLCEntry, 0, len(commit.Htlcs)),
×
UNCOV
263
        }
×
UNCOV
264

×
UNCOV
265
        if !noAmtData {
×
266
                rl.OurBalance = &commit.LocalBalance
×
267
                rl.TheirBalance = &commit.RemoteBalance
×
268
        }
×
269

UNCOV
270
        for _, htlc := range commit.Htlcs {
×
UNCOV
271
                // Skip dust HTLCs.
×
UNCOV
272
                if htlc.OutputIndex < 0 {
×
273
                        continue
×
274
                }
275

276
                // Sanity check that the output indexes can be safely
277
                // converted.
UNCOV
278
                if htlc.OutputIndex > math.MaxUint16 {
×
279
                        return ErrOutputIndexTooBig
×
280
                }
×
281

UNCOV
282
                entry := &HTLCEntry{
×
UNCOV
283
                        RHash:         htlc.RHash,
×
UNCOV
284
                        RefundTimeout: htlc.RefundTimeout,
×
UNCOV
285
                        Incoming:      htlc.Incoming,
×
UNCOV
286
                        OutputIndex:   uint16(htlc.OutputIndex),
×
UNCOV
287
                        Amt:           htlc.Amt.ToSatoshis(),
×
UNCOV
288
                }
×
UNCOV
289
                rl.HTLCEntries = append(rl.HTLCEntries, entry)
×
290
        }
291

UNCOV
292
        var b bytes.Buffer
×
UNCOV
293
        err := serializeRevocationLog(&b, rl)
×
UNCOV
294
        if err != nil {
×
295
                return err
×
296
        }
×
297

UNCOV
298
        logEntrykey := mig24.MakeLogKey(commit.CommitHeight)
×
UNCOV
299
        return bucket.Put(logEntrykey[:], b.Bytes())
×
300
}
301

302
// fetchRevocationLog queries the revocation log bucket to find an log entry.
303
// Return an error if not found.
304
func fetchRevocationLog(log kvdb.RBucket,
UNCOV
305
        updateNum uint64) (RevocationLog, error) {
×
UNCOV
306

×
UNCOV
307
        logEntrykey := mig24.MakeLogKey(updateNum)
×
UNCOV
308
        commitBytes := log.Get(logEntrykey[:])
×
UNCOV
309
        if commitBytes == nil {
×
310
                return RevocationLog{}, ErrLogEntryNotFound
×
311
        }
×
312

UNCOV
313
        commitReader := bytes.NewReader(commitBytes)
×
UNCOV
314

×
UNCOV
315
        return deserializeRevocationLog(commitReader)
×
316
}
317

318
// serializeRevocationLog serializes a RevocationLog record based on tlv
319
// format.
UNCOV
320
func serializeRevocationLog(w io.Writer, rl *RevocationLog) error {
×
UNCOV
321
        // Add the tlv records for all non-optional fields.
×
UNCOV
322
        records := []tlv.Record{
×
UNCOV
323
                tlv.MakePrimitiveRecord(
×
UNCOV
324
                        revLogOurOutputIndexType, &rl.OurOutputIndex,
×
UNCOV
325
                ),
×
UNCOV
326
                tlv.MakePrimitiveRecord(
×
UNCOV
327
                        revLogTheirOutputIndexType, &rl.TheirOutputIndex,
×
UNCOV
328
                ),
×
UNCOV
329
                tlv.MakePrimitiveRecord(
×
UNCOV
330
                        revLogCommitTxHashType, &rl.CommitTxHash,
×
UNCOV
331
                ),
×
UNCOV
332
        }
×
UNCOV
333

×
UNCOV
334
        // Now we add any optional fields that are non-nil.
×
UNCOV
335
        if rl.OurBalance != nil {
×
336
                lb := uint64(*rl.OurBalance)
×
337
                records = append(records, tlv.MakeBigSizeRecord(
×
338
                        revLogOurBalanceType, &lb,
×
339
                ))
×
340
        }
×
341

UNCOV
342
        if rl.TheirBalance != nil {
×
343
                rb := uint64(*rl.TheirBalance)
×
344
                records = append(records, tlv.MakeBigSizeRecord(
×
345
                        revLogTheirBalanceType, &rb,
×
346
                ))
×
347
        }
×
348

349
        // Create the tlv stream.
UNCOV
350
        tlvStream, err := tlv.NewStream(records...)
×
UNCOV
351
        if err != nil {
×
352
                return err
×
353
        }
×
354

355
        // Write the tlv stream.
UNCOV
356
        if err := writeTlvStream(w, tlvStream); err != nil {
×
357
                return err
×
358
        }
×
359

360
        // Write the HTLCs.
UNCOV
361
        return serializeHTLCEntries(w, rl.HTLCEntries)
×
362
}
363

364
// serializeHTLCEntries serializes a list of HTLCEntry records based on tlv
365
// format.
UNCOV
366
func serializeHTLCEntries(w io.Writer, htlcs []*HTLCEntry) error {
×
UNCOV
367
        for _, htlc := range htlcs {
×
UNCOV
368
                // Patch the incomingTlv field.
×
UNCOV
369
                if htlc.Incoming {
×
UNCOV
370
                        htlc.incomingTlv = 1
×
UNCOV
371
                }
×
372

373
                // Patch the amtTlv field.
UNCOV
374
                htlc.amtTlv = uint64(htlc.Amt)
×
UNCOV
375

×
UNCOV
376
                // Create the tlv stream.
×
UNCOV
377
                tlvStream, err := htlc.toTlvStream()
×
UNCOV
378
                if err != nil {
×
379
                        return err
×
380
                }
×
381

382
                // Write the tlv stream.
UNCOV
383
                if err := writeTlvStream(w, tlvStream); err != nil {
×
384
                        return err
×
385
                }
×
386
        }
387

UNCOV
388
        return nil
×
389
}
390

391
// deserializeRevocationLog deserializes a RevocationLog based on tlv format.
UNCOV
392
func deserializeRevocationLog(r io.Reader) (RevocationLog, error) {
×
UNCOV
393
        var (
×
UNCOV
394
                rl            RevocationLog
×
UNCOV
395
                localBalance  uint64
×
UNCOV
396
                remoteBalance uint64
×
UNCOV
397
        )
×
UNCOV
398

×
UNCOV
399
        // Create the tlv stream.
×
UNCOV
400
        tlvStream, err := tlv.NewStream(
×
UNCOV
401
                tlv.MakePrimitiveRecord(
×
UNCOV
402
                        revLogOurOutputIndexType, &rl.OurOutputIndex,
×
UNCOV
403
                ),
×
UNCOV
404
                tlv.MakePrimitiveRecord(
×
UNCOV
405
                        revLogTheirOutputIndexType, &rl.TheirOutputIndex,
×
UNCOV
406
                ),
×
UNCOV
407
                tlv.MakePrimitiveRecord(
×
UNCOV
408
                        revLogCommitTxHashType, &rl.CommitTxHash,
×
UNCOV
409
                ),
×
UNCOV
410
                tlv.MakeBigSizeRecord(revLogOurBalanceType, &localBalance),
×
UNCOV
411
                tlv.MakeBigSizeRecord(
×
UNCOV
412
                        revLogTheirBalanceType, &remoteBalance,
×
UNCOV
413
                ),
×
UNCOV
414
        )
×
UNCOV
415
        if err != nil {
×
416
                return rl, err
×
417
        }
×
418

419
        // Read the tlv stream.
UNCOV
420
        parsedTypes, err := readTlvStream(r, tlvStream)
×
UNCOV
421
        if err != nil {
×
422
                return rl, err
×
423
        }
×
424

UNCOV
425
        if t, ok := parsedTypes[revLogOurBalanceType]; ok && t == nil {
×
426
                lb := lnwire.MilliSatoshi(localBalance)
×
427
                rl.OurBalance = &lb
×
428
        }
×
429

UNCOV
430
        if t, ok := parsedTypes[revLogTheirBalanceType]; ok && t == nil {
×
431
                rb := lnwire.MilliSatoshi(remoteBalance)
×
432
                rl.TheirBalance = &rb
×
433
        }
×
434

435
        // Read the HTLC entries.
UNCOV
436
        rl.HTLCEntries, err = deserializeHTLCEntries(r)
×
UNCOV
437

×
UNCOV
438
        return rl, err
×
439
}
440

441
// deserializeHTLCEntries deserializes a list of HTLC entries based on tlv
442
// format.
UNCOV
443
func deserializeHTLCEntries(r io.Reader) ([]*HTLCEntry, error) {
×
UNCOV
444
        var htlcs []*HTLCEntry
×
UNCOV
445

×
UNCOV
446
        for {
×
UNCOV
447
                var htlc HTLCEntry
×
UNCOV
448

×
UNCOV
449
                // Create the tlv stream.
×
UNCOV
450
                tlvStream, err := htlc.toTlvStream()
×
UNCOV
451
                if err != nil {
×
452
                        return nil, err
×
453
                }
×
454

455
                // Read the HTLC entry.
UNCOV
456
                if _, err := readTlvStream(r, tlvStream); err != nil {
×
UNCOV
457
                        // We've reached the end when hitting an EOF.
×
UNCOV
458
                        if err == io.ErrUnexpectedEOF {
×
UNCOV
459
                                break
×
460
                        }
461
                        return nil, err
×
462
                }
463

464
                // Patch the Incoming field.
UNCOV
465
                if htlc.incomingTlv == 1 {
×
466
                        htlc.Incoming = true
×
467
                }
×
468

469
                // Patch the Amt field.
UNCOV
470
                htlc.Amt = btcutil.Amount(htlc.amtTlv)
×
UNCOV
471

×
UNCOV
472
                // Append the entry.
×
UNCOV
473
                htlcs = append(htlcs, &htlc)
×
474
        }
475

UNCOV
476
        return htlcs, nil
×
477
}
478

479
// writeTlvStream is a helper function that encodes the tlv stream into the
480
// writer.
UNCOV
481
func writeTlvStream(w io.Writer, s *tlv.Stream) error {
×
UNCOV
482
        var b bytes.Buffer
×
UNCOV
483
        if err := s.Encode(&b); err != nil {
×
484
                return err
×
485
        }
×
486
        // Write the stream's length as a varint.
UNCOV
487
        err := tlv.WriteVarInt(w, uint64(b.Len()), &[8]byte{})
×
UNCOV
488
        if err != nil {
×
489
                return err
×
490
        }
×
491

UNCOV
492
        if _, err = w.Write(b.Bytes()); err != nil {
×
493
                return err
×
494
        }
×
495

UNCOV
496
        return nil
×
497
}
498

499
// readTlvStream is a helper function that decodes the tlv stream from the
500
// reader.
UNCOV
501
func readTlvStream(r io.Reader, s *tlv.Stream) (tlv.TypeMap, error) {
×
UNCOV
502
        var bodyLen uint64
×
UNCOV
503

×
UNCOV
504
        // Read the stream's length.
×
UNCOV
505
        bodyLen, err := tlv.ReadVarInt(r, &[8]byte{})
×
UNCOV
506
        switch {
×
507
        // We'll convert any EOFs to ErrUnexpectedEOF, since this results in an
508
        // invalid record.
UNCOV
509
        case err == io.EOF:
×
UNCOV
510
                return nil, io.ErrUnexpectedEOF
×
511

512
        // Other unexpected errors.
513
        case err != nil:
×
514
                return nil, err
×
515
        }
516

517
        // TODO(yy): add overflow check.
UNCOV
518
        lr := io.LimitReader(r, int64(bodyLen))
×
UNCOV
519

×
UNCOV
520
        return s.DecodeWithParsedTypes(lr)
×
521
}
522

523
// fetchLogBucket returns a read bucket by visiting both the new and the old
524
// bucket.
UNCOV
525
func fetchLogBucket(chanBucket kvdb.RBucket) (kvdb.RBucket, error) {
×
UNCOV
526
        logBucket := chanBucket.NestedReadBucket(revocationLogBucket)
×
UNCOV
527
        if logBucket == nil {
×
528
                logBucket = chanBucket.NestedReadBucket(
×
529
                        revocationLogBucketDeprecated,
×
530
                )
×
531
                if logBucket == nil {
×
532
                        return nil, mig25.ErrNoPastDeltas
×
533
                }
×
534
        }
535

UNCOV
536
        return logBucket, nil
×
537
}
538

539
// putOldRevocationLog saves a revocation log using the old format.
540
func putOldRevocationLog(log kvdb.RwBucket,
UNCOV
541
        commit *mig.ChannelCommitment) error {
×
UNCOV
542

×
UNCOV
543
        var b bytes.Buffer
×
UNCOV
544
        if err := mig.SerializeChanCommit(&b, commit); err != nil {
×
545
                return err
×
546
        }
×
547

UNCOV
548
        logEntrykey := mig24.MakeLogKey(commit.CommitHeight)
×
UNCOV
549
        return log.Put(logEntrykey[:], b.Bytes())
×
550
}
551

552
func putChanRevocationState(chanBucket kvdb.RwBucket,
UNCOV
553
        channel *mig26.OpenChannel) error {
×
UNCOV
554

×
UNCOV
555
        var b bytes.Buffer
×
UNCOV
556
        err := mig.WriteElements(
×
UNCOV
557
                &b, channel.RemoteCurrentRevocation, channel.RevocationProducer,
×
UNCOV
558
                channel.RevocationStore,
×
UNCOV
559
        )
×
UNCOV
560
        if err != nil {
×
561
                return err
×
562
        }
×
563

564
        // TODO(roasbeef): don't keep producer on disk
565

566
        // If the next revocation is present, which is only the case after the
567
        // FundingLocked message has been sent, then we'll write it to disk.
UNCOV
568
        if channel.RemoteNextRevocation != nil {
×
569
                err = mig.WriteElements(&b, channel.RemoteNextRevocation)
×
570
                if err != nil {
×
571
                        return err
×
572
                }
×
573
        }
574

UNCOV
575
        return chanBucket.Put(revocationStateKey, b.Bytes())
×
576
}
577

578
func fetchChanRevocationState(chanBucket kvdb.RBucket,
UNCOV
579
        c *mig26.OpenChannel) error {
×
UNCOV
580

×
UNCOV
581
        revBytes := chanBucket.Get(revocationStateKey)
×
UNCOV
582
        if revBytes == nil {
×
583
                return ErrNoRevocationsFound
×
584
        }
×
UNCOV
585
        r := bytes.NewReader(revBytes)
×
UNCOV
586

×
UNCOV
587
        err := mig.ReadElements(
×
UNCOV
588
                r, &c.RemoteCurrentRevocation, &c.RevocationProducer,
×
UNCOV
589
                &c.RevocationStore,
×
UNCOV
590
        )
×
UNCOV
591
        if err != nil {
×
592
                return err
×
593
        }
×
594

595
        // If there aren't any bytes left in the buffer, then we don't yet have
596
        // the next remote revocation, so we can exit early here.
UNCOV
597
        if r.Len() == 0 {
×
UNCOV
598
                return nil
×
UNCOV
599
        }
×
600

601
        // Otherwise we'll read the next revocation for the remote party which
602
        // is always the last item within the buffer.
603
        return mig.ReadElements(r, &c.RemoteNextRevocation)
×
604
}
605

606
func findOutputIndexes(chanState *mig26.OpenChannel,
UNCOV
607
        oldLog *mig.ChannelCommitment) (uint32, uint32, error) {
×
UNCOV
608

×
UNCOV
609
        // With the state number broadcast known, we can now derive/restore the
×
UNCOV
610
        // proper revocation preimage necessary to sweep the remote party's
×
UNCOV
611
        // output.
×
UNCOV
612
        revocationPreimage, err := chanState.RevocationStore.LookUp(
×
UNCOV
613
                oldLog.CommitHeight,
×
UNCOV
614
        )
×
UNCOV
615
        if err != nil {
×
616
                return 0, 0, err
×
617
        }
×
618

UNCOV
619
        return findOutputIndexesFromRemote(
×
UNCOV
620
                revocationPreimage, chanState, oldLog,
×
UNCOV
621
        )
×
622
}
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