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

lightningnetwork / lnd / 14060408908

25 Mar 2025 01:08PM UTC coverage: 68.744% (-0.3%) from 69.02%
14060408908

push

github

web-flow
Merge pull request #9621 from jjjike2021/exp/maps

multi: remove x/exp/maps dependency

4 of 4 new or added lines in 4 files covered. (100.0%)

561 existing lines in 39 files now uncovered.

132512 of 192761 relevant lines covered (68.74%)

42821.37 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 {
4,582✔
129
        if h.RHash == lntypes.ZeroHash {
4,582✔
130
                return 0
×
131
        }
×
132
        return 32
4,582✔
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 {
4,582✔
137
        v, ok := val.(*[32]byte)
4,582✔
138
        if !ok {
4,582✔
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 {
4,582✔
144
                return nil
×
145
        }
×
146

147
        return tlv.EBytes32(w, v, buf)
4,582✔
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 {
3,960✔
152
        v, ok := val.(*[32]byte)
3,960✔
153
        if !ok {
3,960✔
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 {
3,960✔
159
                return nil
×
160
        }
×
161

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

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

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

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

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

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

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

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

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

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

296
        logEntrykey := mig24.MakeLogKey(commit.CommitHeight)
4,026✔
297
        return bucket.Put(logEntrykey[:], b.Bytes())
4,026✔
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) {
7,920✔
304

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

311
        commitReader := bytes.NewReader(commitBytes)
7,920✔
312

7,920✔
313
        return deserializeRevocationLog(commitReader)
7,920✔
314
}
315

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

9,678✔
332
        // Now we add any optional fields that are non-nil.
9,678✔
333
        if rl.OurBalance != nil {
9,678✔
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 {
9,678✔
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...)
9,678✔
349
        if err != nil {
9,678✔
350
                return err
×
351
        }
×
352

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

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

362
// serializeHTLCEntries serializes a list of HTLCEntry records based on tlv
363
// format.
364
func serializeHTLCEntries(w io.Writer, htlcs []*HTLCEntry) error {
9,678✔
365
        for _, htlc := range htlcs {
14,260✔
366
                // Patch the incomingTlv field.
4,582✔
367
                if htlc.Incoming {
4,632✔
368
                        htlc.incomingTlv = 1
50✔
369
                }
50✔
370

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

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

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

386
        return nil
9,678✔
387
}
388

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

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

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

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

428
        if t, ok := parsedTypes[revLogTheirBalanceType]; ok && t == nil {
7,920✔
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)
7,920✔
435

7,920✔
436
        return rl, err
7,920✔
437
}
438

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

7,920✔
444
        for {
19,800✔
445
                var htlc HTLCEntry
11,880✔
446

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

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

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

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

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

474
        return htlcs, nil
7,920✔
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 {
14,260✔
480
        var b bytes.Buffer
14,260✔
481
        if err := s.Encode(&b); err != nil {
14,260✔
482
                return err
×
483
        }
×
484
        // Write the stream's length as a varint.
485
        err := tlv.WriteVarInt(w, uint64(b.Len()), &[8]byte{})
14,260✔
486
        if err != nil {
14,260✔
487
                return err
×
488
        }
×
489

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

494
        return nil
14,260✔
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) {
19,800✔
500
        var bodyLen uint64
19,800✔
501

19,800✔
502
        // Read the stream's length.
19,800✔
503
        bodyLen, err := tlv.ReadVarInt(r, &[8]byte{})
19,800✔
504
        switch {
19,800✔
505
        // We'll convert any EOFs to ErrUnexpectedEOF, since this results in an
506
        // invalid record.
507
        case err == io.EOF:
7,920✔
508
                return nil, io.ErrUnexpectedEOF
7,920✔
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))
11,880✔
517

11,880✔
518
        return s.DecodeWithParsedTypes(lr)
11,880✔
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) {
7,920✔
524
        logBucket := chanBucket.NestedReadBucket(revocationLogBucket)
7,920✔
525
        if logBucket == nil {
7,920✔
526
                logBucket = chanBucket.NestedReadBucket(
×
527
                        revocationLogBucketDeprecated,
×
528
                )
×
529
                if logBucket == nil {
×
530
                        return nil, mig25.ErrNoPastDeltas
×
531
                }
×
532
        }
533

534
        return logBucket, nil
7,920✔
535
}
536

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

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

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

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

5,318✔
553
        var b bytes.Buffer
5,318✔
554
        err := mig.WriteElements(
5,318✔
555
                &b, channel.RemoteCurrentRevocation, channel.RevocationProducer,
5,318✔
556
                channel.RevocationStore,
5,318✔
557
        )
5,318✔
558
        if err != nil {
5,318✔
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 {
5,318✔
567
                err = mig.WriteElements(&b, channel.RemoteNextRevocation)
×
568
                if err != nil {
×
569
                        return err
×
570
                }
×
571
        }
572

573
        return chanBucket.Put(revocationStateKey, b.Bytes())
5,318✔
574
}
575

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

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

3,768✔
585
        err := mig.ReadElements(
3,768✔
586
                r, &c.RemoteCurrentRevocation, &c.RevocationProducer,
3,768✔
587
                &c.RevocationStore,
3,768✔
588
        )
3,768✔
589
        if err != nil {
3,768✔
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 {
7,536✔
596
                return nil
3,768✔
597
        }
3,768✔
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) {
5,652✔
606

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

617
        return findOutputIndexesFromRemote(
5,652✔
618
                revocationPreimage, chanState, oldLog,
5,652✔
619
        )
5,652✔
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