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

lightningnetwork / lnd / 16569502135

28 Jul 2025 12:50PM UTC coverage: 67.251% (+0.02%) from 67.227%
16569502135

Pull #9455

github

web-flow
Merge b3899c4fd into 2e36f9b8b
Pull Request #9455: discovery+lnwire: add support for DNS host name in NodeAnnouncement msg

179 of 208 new or added lines in 6 files covered. (86.06%)

105 existing lines in 23 files now uncovered.

135676 of 201746 relevant lines covered (67.25%)

21711.59 hits per line

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

72.87
/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.
128
func (h *HTLCEntry) RHashLen() uint64 {
2,291✔
129
        if h.RHash == lntypes.ZeroHash {
2,291✔
130
                return 0
×
131
        }
×
132
        return 32
2,291✔
133
}
134

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

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

147
        return tlv.EBytes32(w, v, buf)
2,291✔
148
}
149

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

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

162
        return tlv.DBytes32(r, v, buf, 32)
1,980✔
163
}
164

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

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

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

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

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

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

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

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

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

2,013✔
248
        // Sanity check that the output indexes can be safely converted.
2,013✔
249
        if ourOutputIndex > math.MaxUint16 {
2,013✔
250
                return ErrOutputIndexTooBig
×
251
        }
×
252
        if theirOutputIndex > math.MaxUint16 {
2,013✔
253
                return ErrOutputIndexTooBig
×
254
        }
×
255

256
        rl := &RevocationLog{
2,013✔
257
                OurOutputIndex:   uint16(ourOutputIndex),
2,013✔
258
                TheirOutputIndex: uint16(theirOutputIndex),
2,013✔
259
                CommitTxHash:     commit.CommitTx.TxHash(),
2,013✔
260
                HTLCEntries:      make([]*HTLCEntry, 0, len(commit.Htlcs)),
2,013✔
261
        }
2,013✔
262

2,013✔
263
        if !noAmtData {
2,013✔
UNCOV
264
                rl.OurBalance = &commit.LocalBalance
×
UNCOV
265
                rl.TheirBalance = &commit.RemoteBalance
×
UNCOV
266
        }
×
267

268
        for _, htlc := range commit.Htlcs {
2,702✔
269
                // Skip dust HTLCs.
689✔
270
                if htlc.OutputIndex < 0 {
689✔
271
                        continue
×
272
                }
273

274
                // Sanity check that the output indexes can be safely
275
                // converted.
276
                if htlc.OutputIndex > math.MaxUint16 {
689✔
277
                        return ErrOutputIndexTooBig
×
278
                }
×
279

280
                entry := &HTLCEntry{
689✔
281
                        RHash:         htlc.RHash,
689✔
282
                        RefundTimeout: htlc.RefundTimeout,
689✔
283
                        Incoming:      htlc.Incoming,
689✔
284
                        OutputIndex:   uint16(htlc.OutputIndex),
689✔
285
                        Amt:           htlc.Amt.ToSatoshis(),
689✔
286
                }
689✔
287
                rl.HTLCEntries = append(rl.HTLCEntries, entry)
689✔
288
        }
289

290
        var b bytes.Buffer
2,013✔
291
        err := serializeRevocationLog(&b, rl)
2,013✔
292
        if err != nil {
2,013✔
293
                return err
×
294
        }
×
295

296
        logEntrykey := mig24.MakeLogKey(commit.CommitHeight)
2,013✔
297
        return bucket.Put(logEntrykey[:], b.Bytes())
2,013✔
298
}
299

300
// fetchRevocationLog queries the revocation log bucket to find an log entry.
301
// Return an error if not found.
302
func fetchRevocationLog(log kvdb.RBucket,
303
        updateNum uint64) (RevocationLog, error) {
3,960✔
304

3,960✔
305
        logEntrykey := mig24.MakeLogKey(updateNum)
3,960✔
306
        commitBytes := log.Get(logEntrykey[:])
3,960✔
307
        if commitBytes == nil {
3,960✔
308
                return RevocationLog{}, ErrLogEntryNotFound
×
309
        }
×
310

311
        commitReader := bytes.NewReader(commitBytes)
3,960✔
312

3,960✔
313
        return deserializeRevocationLog(commitReader)
3,960✔
314
}
315

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

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

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

347
        // Create the tlv stream.
348
        tlvStream, err := tlv.NewStream(records...)
4,839✔
349
        if err != nil {
4,839✔
350
                return err
×
351
        }
×
352

353
        // Write the tlv stream.
354
        if err := writeTlvStream(w, tlvStream); err != nil {
4,839✔
355
                return err
×
356
        }
×
357

358
        // Write the HTLCs.
359
        return serializeHTLCEntries(w, rl.HTLCEntries)
4,839✔
360
}
361

362
// serializeHTLCEntries serializes a list of HTLCEntry records based on tlv
363
// format.
364
func serializeHTLCEntries(w io.Writer, htlcs []*HTLCEntry) error {
4,839✔
365
        for _, htlc := range htlcs {
7,130✔
366
                // Patch the incomingTlv field.
2,291✔
367
                if htlc.Incoming {
2,316✔
368
                        htlc.incomingTlv = 1
25✔
369
                }
25✔
370

371
                // Patch the amtTlv field.
372
                htlc.amtTlv = uint64(htlc.Amt)
2,291✔
373

2,291✔
374
                // Create the tlv stream.
2,291✔
375
                tlvStream, err := htlc.toTlvStream()
2,291✔
376
                if err != nil {
2,291✔
377
                        return err
×
378
                }
×
379

380
                // Write the tlv stream.
381
                if err := writeTlvStream(w, tlvStream); err != nil {
2,291✔
382
                        return err
×
383
                }
×
384
        }
385

386
        return nil
4,839✔
387
}
388

389
// deserializeRevocationLog deserializes a RevocationLog based on tlv format.
390
func deserializeRevocationLog(r io.Reader) (RevocationLog, error) {
3,960✔
391
        var (
3,960✔
392
                rl            RevocationLog
3,960✔
393
                localBalance  uint64
3,960✔
394
                remoteBalance uint64
3,960✔
395
        )
3,960✔
396

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

417
        // Read the tlv stream.
418
        parsedTypes, err := readTlvStream(r, tlvStream)
3,960✔
419
        if err != nil {
3,960✔
420
                return rl, err
×
421
        }
×
422

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

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

433
        // Read the HTLC entries.
434
        rl.HTLCEntries, err = deserializeHTLCEntries(r)
3,960✔
435

3,960✔
436
        return rl, err
3,960✔
437
}
438

439
// deserializeHTLCEntries deserializes a list of HTLC entries based on tlv
440
// format.
441
func deserializeHTLCEntries(r io.Reader) ([]*HTLCEntry, error) {
3,960✔
442
        var htlcs []*HTLCEntry
3,960✔
443

3,960✔
444
        for {
9,900✔
445
                var htlc HTLCEntry
5,940✔
446

5,940✔
447
                // Create the tlv stream.
5,940✔
448
                tlvStream, err := htlc.toTlvStream()
5,940✔
449
                if err != nil {
5,940✔
450
                        return nil, err
×
451
                }
×
452

453
                // Read the HTLC entry.
454
                if _, err := readTlvStream(r, tlvStream); err != nil {
9,900✔
455
                        // We've reached the end when hitting an EOF.
3,960✔
456
                        if err == io.ErrUnexpectedEOF {
7,920✔
457
                                break
3,960✔
458
                        }
459
                        return nil, err
×
460
                }
461

462
                // Patch the Incoming field.
463
                if htlc.incomingTlv == 1 {
1,980✔
464
                        htlc.Incoming = true
×
465
                }
×
466

467
                // Patch the Amt field.
468
                htlc.Amt = btcutil.Amount(htlc.amtTlv)
1,980✔
469

1,980✔
470
                // Append the entry.
1,980✔
471
                htlcs = append(htlcs, &htlc)
1,980✔
472
        }
473

474
        return htlcs, nil
3,960✔
475
}
476

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

490
        if _, err = w.Write(b.Bytes()); err != nil {
7,130✔
491
                return err
×
492
        }
×
493

494
        return nil
7,130✔
495
}
496

497
// readTlvStream is a helper function that decodes the tlv stream from the
498
// reader.
499
func readTlvStream(r io.Reader, s *tlv.Stream) (tlv.TypeMap, error) {
9,900✔
500
        var bodyLen uint64
9,900✔
501

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

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

515
        // TODO(yy): add overflow check.
516
        lr := io.LimitReader(r, int64(bodyLen))
5,940✔
517

5,940✔
518
        return s.DecodeWithParsedTypes(lr)
5,940✔
519
}
520

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

534
        return logBucket, nil
3,960✔
535
}
536

537
// putOldRevocationLog saves a revocation log using the old format.
538
func putOldRevocationLog(log kvdb.RwBucket,
539
        commit *mig.ChannelCommitment) error {
3,994✔
540

3,994✔
541
        var b bytes.Buffer
3,994✔
542
        if err := mig.SerializeChanCommit(&b, commit); err != nil {
3,994✔
543
                return err
×
544
        }
×
545

546
        logEntrykey := mig24.MakeLogKey(commit.CommitHeight)
3,994✔
547
        return log.Put(logEntrykey[:], b.Bytes())
3,994✔
548
}
549

550
func putChanRevocationState(chanBucket kvdb.RwBucket,
551
        channel *mig26.OpenChannel) error {
2,659✔
552

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

562
        // TODO(roasbeef): don't keep producer on disk
563

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

573
        return chanBucket.Put(revocationStateKey, b.Bytes())
2,659✔
574
}
575

576
func fetchChanRevocationState(chanBucket kvdb.RBucket,
577
        c *mig26.OpenChannel) error {
1,884✔
578

1,884✔
579
        revBytes := chanBucket.Get(revocationStateKey)
1,884✔
580
        if revBytes == nil {
1,884✔
581
                return ErrNoRevocationsFound
×
582
        }
×
583
        r := bytes.NewReader(revBytes)
1,884✔
584

1,884✔
585
        err := mig.ReadElements(
1,884✔
586
                r, &c.RemoteCurrentRevocation, &c.RevocationProducer,
1,884✔
587
                &c.RevocationStore,
1,884✔
588
        )
1,884✔
589
        if err != nil {
1,884✔
590
                return err
×
591
        }
×
592

593
        // If there aren't any bytes left in the buffer, then we don't yet have
594
        // the next remote revocation, so we can exit early here.
595
        if r.Len() == 0 {
3,768✔
596
                return nil
1,884✔
597
        }
1,884✔
598

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

604
func findOutputIndexes(chanState *mig26.OpenChannel,
605
        oldLog *mig.ChannelCommitment) (uint32, uint32, error) {
2,826✔
606

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

617
        return findOutputIndexesFromRemote(
2,826✔
618
                revocationPreimage, chanState, oldLog,
2,826✔
619
        )
2,826✔
620
}
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