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

lightningnetwork / lnd / 13035292482

29 Jan 2025 03:59PM UTC coverage: 49.3% (-9.5%) from 58.777%
13035292482

Pull #9456

github

mohamedawnallah
docs: update release-notes-0.19.0.md

In this commit, we warn users about the removal
of RPCs `SendToRoute`, `SendToRouteSync`, `SendPayment`,
and `SendPaymentSync` in the next release 0.20.
Pull Request #9456: lnrpc+docs: deprecate warning `SendToRoute`, `SendToRouteSync`, `SendPayment`, and `SendPaymentSync` in Release 0.19

100634 of 204126 relevant lines covered (49.3%)

1.54 hits per line

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

0.0
/channeldb/migration21/current/current_encoding.go
1
package current
2

3
import (
4
        "bytes"
5
        "encoding/binary"
6
        "errors"
7
        "fmt"
8
        "io"
9

10
        lnwire "github.com/lightningnetwork/lnd/channeldb/migration/lnwire21"
11
        "github.com/lightningnetwork/lnd/channeldb/migration21/common"
12
        "github.com/lightningnetwork/lnd/kvdb"
13
)
14

15
func serializeChanCommit(w io.Writer, c *common.ChannelCommitment) error { // nolint: dupl
×
16
        if err := WriteElements(w,
×
17
                c.CommitHeight, c.LocalLogIndex, c.LocalHtlcIndex,
×
18
                c.RemoteLogIndex, c.RemoteHtlcIndex, c.LocalBalance,
×
19
                c.RemoteBalance, c.CommitFee, c.FeePerKw, c.CommitTx,
×
20
                c.CommitSig,
×
21
        ); err != nil {
×
22
                return err
×
23
        }
×
24

25
        return serializeHtlcs(w, c.Htlcs...)
×
26
}
27

28
func SerializeLogUpdates(w io.Writer, logUpdates []common.LogUpdate) error { // nolint: dupl
×
29
        numUpdates := uint16(len(logUpdates))
×
30
        if err := binary.Write(w, byteOrder, numUpdates); err != nil {
×
31
                return err
×
32
        }
×
33

34
        for _, diff := range logUpdates {
×
35
                err := WriteElements(w, diff.LogIndex, diff.UpdateMsg)
×
36
                if err != nil {
×
37
                        return err
×
38
                }
×
39
        }
40

41
        return nil
×
42
}
43

44
func serializeHtlcs(b io.Writer, htlcs ...common.HTLC) error { // nolint: dupl
×
45
        numHtlcs := uint16(len(htlcs))
×
46
        if err := WriteElement(b, numHtlcs); err != nil {
×
47
                return err
×
48
        }
×
49

50
        for _, htlc := range htlcs {
×
51
                if err := WriteElements(b,
×
52
                        htlc.Signature, htlc.RHash, htlc.Amt, htlc.RefundTimeout,
×
53
                        htlc.OutputIndex, htlc.Incoming, htlc.OnionBlob,
×
54
                        htlc.HtlcIndex, htlc.LogIndex,
×
55
                ); err != nil {
×
56
                        return err
×
57
                }
×
58
        }
59

60
        return nil
×
61
}
62

63
func SerializeCommitDiff(w io.Writer, diff *common.CommitDiff) error { // nolint: dupl
×
64
        if err := serializeChanCommit(w, &diff.Commitment); err != nil {
×
65
                return err
×
66
        }
×
67

68
        if err := WriteElements(w, diff.CommitSig); err != nil {
×
69
                return err
×
70
        }
×
71

72
        if err := SerializeLogUpdates(w, diff.LogUpdates); err != nil {
×
73
                return err
×
74
        }
×
75

76
        numOpenRefs := uint16(len(diff.OpenedCircuitKeys))
×
77
        if err := binary.Write(w, byteOrder, numOpenRefs); err != nil {
×
78
                return err
×
79
        }
×
80

81
        for _, openRef := range diff.OpenedCircuitKeys {
×
82
                err := WriteElements(w, openRef.ChanID, openRef.HtlcID)
×
83
                if err != nil {
×
84
                        return err
×
85
                }
×
86
        }
87

88
        numClosedRefs := uint16(len(diff.ClosedCircuitKeys))
×
89
        if err := binary.Write(w, byteOrder, numClosedRefs); err != nil {
×
90
                return err
×
91
        }
×
92

93
        for _, closedRef := range diff.ClosedCircuitKeys {
×
94
                err := WriteElements(w, closedRef.ChanID, closedRef.HtlcID)
×
95
                if err != nil {
×
96
                        return err
×
97
                }
×
98
        }
99

100
        return nil
×
101
}
102

103
func deserializeHtlcs(r io.Reader) ([]common.HTLC, error) { // nolint: dupl
×
104
        var numHtlcs uint16
×
105
        if err := ReadElement(r, &numHtlcs); err != nil {
×
106
                return nil, err
×
107
        }
×
108

109
        var htlcs []common.HTLC
×
110
        if numHtlcs == 0 {
×
111
                return htlcs, nil
×
112
        }
×
113

114
        htlcs = make([]common.HTLC, numHtlcs)
×
115
        for i := uint16(0); i < numHtlcs; i++ {
×
116
                if err := ReadElements(r,
×
117
                        &htlcs[i].Signature, &htlcs[i].RHash, &htlcs[i].Amt,
×
118
                        &htlcs[i].RefundTimeout, &htlcs[i].OutputIndex,
×
119
                        &htlcs[i].Incoming, &htlcs[i].OnionBlob,
×
120
                        &htlcs[i].HtlcIndex, &htlcs[i].LogIndex,
×
121
                ); err != nil {
×
122
                        return htlcs, err
×
123
                }
×
124
        }
125

126
        return htlcs, nil
×
127
}
128

129
func deserializeChanCommit(r io.Reader) (common.ChannelCommitment, error) { // nolint: dupl
×
130
        var c common.ChannelCommitment
×
131

×
132
        err := ReadElements(r,
×
133
                &c.CommitHeight, &c.LocalLogIndex, &c.LocalHtlcIndex, &c.RemoteLogIndex,
×
134
                &c.RemoteHtlcIndex, &c.LocalBalance, &c.RemoteBalance,
×
135
                &c.CommitFee, &c.FeePerKw, &c.CommitTx, &c.CommitSig,
×
136
        )
×
137
        if err != nil {
×
138
                return c, err
×
139
        }
×
140

141
        c.Htlcs, err = deserializeHtlcs(r)
×
142
        if err != nil {
×
143
                return c, err
×
144
        }
×
145

146
        return c, nil
×
147
}
148

149
func DeserializeLogUpdates(r io.Reader) ([]common.LogUpdate, error) { // nolint: dupl
×
150
        var numUpdates uint16
×
151
        if err := binary.Read(r, byteOrder, &numUpdates); err != nil {
×
152
                return nil, err
×
153
        }
×
154

155
        logUpdates := make([]common.LogUpdate, numUpdates)
×
156
        for i := 0; i < int(numUpdates); i++ {
×
157
                err := ReadElements(r,
×
158
                        &logUpdates[i].LogIndex, &logUpdates[i].UpdateMsg,
×
159
                )
×
160
                if err != nil {
×
161
                        return nil, err
×
162
                }
×
163
        }
164
        return logUpdates, nil
×
165
}
166

167
func DeserializeCommitDiff(r io.Reader) (*common.CommitDiff, error) { // nolint: dupl
×
168
        var (
×
169
                d   common.CommitDiff
×
170
                err error
×
171
        )
×
172

×
173
        d.Commitment, err = deserializeChanCommit(r)
×
174
        if err != nil {
×
175
                return nil, err
×
176
        }
×
177

178
        var msg lnwire.Message
×
179
        if err := ReadElements(r, &msg); err != nil {
×
180
                return nil, err
×
181
        }
×
182
        commitSig, ok := msg.(*lnwire.CommitSig)
×
183
        if !ok {
×
184
                return nil, fmt.Errorf("expected lnwire.CommitSig, instead "+
×
185
                        "read: %T", msg)
×
186
        }
×
187
        d.CommitSig = commitSig
×
188

×
189
        d.LogUpdates, err = DeserializeLogUpdates(r)
×
190
        if err != nil {
×
191
                return nil, err
×
192
        }
×
193

194
        var numOpenRefs uint16
×
195
        if err := binary.Read(r, byteOrder, &numOpenRefs); err != nil {
×
196
                return nil, err
×
197
        }
×
198

199
        d.OpenedCircuitKeys = make([]common.CircuitKey, numOpenRefs)
×
200
        for i := 0; i < int(numOpenRefs); i++ {
×
201
                err := ReadElements(r,
×
202
                        &d.OpenedCircuitKeys[i].ChanID,
×
203
                        &d.OpenedCircuitKeys[i].HtlcID)
×
204
                if err != nil {
×
205
                        return nil, err
×
206
                }
×
207
        }
208

209
        var numClosedRefs uint16
×
210
        if err := binary.Read(r, byteOrder, &numClosedRefs); err != nil {
×
211
                return nil, err
×
212
        }
×
213

214
        d.ClosedCircuitKeys = make([]common.CircuitKey, numClosedRefs)
×
215
        for i := 0; i < int(numClosedRefs); i++ {
×
216
                err := ReadElements(r,
×
217
                        &d.ClosedCircuitKeys[i].ChanID,
×
218
                        &d.ClosedCircuitKeys[i].HtlcID)
×
219
                if err != nil {
×
220
                        return nil, err
×
221
                }
×
222
        }
223

224
        return &d, nil
×
225
}
226

227
func SerializeNetworkResult(w io.Writer, n *common.NetworkResult) error { // nolint: dupl
×
228
        return WriteElements(w, n.Msg, n.Unencrypted, n.IsResolution)
×
229
}
×
230

231
func DeserializeNetworkResult(r io.Reader) (*common.NetworkResult, error) { // nolint: dupl
×
232
        n := &common.NetworkResult{}
×
233

×
234
        if err := ReadElements(r,
×
235
                &n.Msg, &n.Unencrypted, &n.IsResolution,
×
236
        ); err != nil {
×
237
                return nil, err
×
238
        }
×
239

240
        return n, nil
×
241
}
242

243
func writeChanConfig(b io.Writer, c *common.ChannelConfig) error { // nolint: dupl
×
244
        return WriteElements(b,
×
245
                c.DustLimit, c.MaxPendingAmount, c.ChanReserve, c.MinHTLC,
×
246
                c.MaxAcceptedHtlcs, c.CsvDelay, c.MultiSigKey,
×
247
                c.RevocationBasePoint, c.PaymentBasePoint, c.DelayBasePoint,
×
248
                c.HtlcBasePoint,
×
249
        )
×
250
}
×
251

252
func SerializeChannelCloseSummary(w io.Writer, cs *common.ChannelCloseSummary) error { // nolint: dupl
×
253
        err := WriteElements(w,
×
254
                cs.ChanPoint, cs.ShortChanID, cs.ChainHash, cs.ClosingTXID,
×
255
                cs.CloseHeight, cs.RemotePub, cs.Capacity, cs.SettledBalance,
×
256
                cs.TimeLockedBalance, cs.CloseType, cs.IsPending,
×
257
        )
×
258
        if err != nil {
×
259
                return err
×
260
        }
×
261

262
        // If this is a close channel summary created before the addition of
263
        // the new fields, then we can exit here.
264
        if cs.RemoteCurrentRevocation == nil {
×
265
                return WriteElements(w, false)
×
266
        }
×
267

268
        // If fields are present, write boolean to indicate this, and continue.
269
        if err := WriteElements(w, true); err != nil {
×
270
                return err
×
271
        }
×
272

273
        if err := WriteElements(w, cs.RemoteCurrentRevocation); err != nil {
×
274
                return err
×
275
        }
×
276

277
        if err := writeChanConfig(w, &cs.LocalChanConfig); err != nil {
×
278
                return err
×
279
        }
×
280

281
        // The RemoteNextRevocation field is optional, as it's possible for a
282
        // channel to be closed before we learn of the next unrevoked
283
        // revocation point for the remote party. Write a boolean indicating
284
        // whether this field is present or not.
285
        if err := WriteElements(w, cs.RemoteNextRevocation != nil); err != nil {
×
286
                return err
×
287
        }
×
288

289
        // Write the field, if present.
290
        if cs.RemoteNextRevocation != nil {
×
291
                if err = WriteElements(w, cs.RemoteNextRevocation); err != nil {
×
292
                        return err
×
293
                }
×
294
        }
295

296
        // Write whether the channel sync message is present.
297
        if err := WriteElements(w, cs.LastChanSyncMsg != nil); err != nil {
×
298
                return err
×
299
        }
×
300

301
        // Write the channel sync message, if present.
302
        if cs.LastChanSyncMsg != nil {
×
303
                if err := WriteElements(w, cs.LastChanSyncMsg); err != nil {
×
304
                        return err
×
305
                }
×
306
        }
307

308
        return nil
×
309
}
310

311
func readChanConfig(b io.Reader, c *common.ChannelConfig) error {
×
312
        return ReadElements(b,
×
313
                &c.DustLimit, &c.MaxPendingAmount, &c.ChanReserve,
×
314
                &c.MinHTLC, &c.MaxAcceptedHtlcs, &c.CsvDelay,
×
315
                &c.MultiSigKey, &c.RevocationBasePoint,
×
316
                &c.PaymentBasePoint, &c.DelayBasePoint,
×
317
                &c.HtlcBasePoint,
×
318
        )
×
319
}
×
320

321
func DeserializeCloseChannelSummary(r io.Reader) (*common.ChannelCloseSummary, error) { // nolint: dupl
×
322
        c := &common.ChannelCloseSummary{}
×
323

×
324
        err := ReadElements(r,
×
325
                &c.ChanPoint, &c.ShortChanID, &c.ChainHash, &c.ClosingTXID,
×
326
                &c.CloseHeight, &c.RemotePub, &c.Capacity, &c.SettledBalance,
×
327
                &c.TimeLockedBalance, &c.CloseType, &c.IsPending,
×
328
        )
×
329
        if err != nil {
×
330
                return nil, err
×
331
        }
×
332

333
        // We'll now check to see if the channel close summary was encoded with
334
        // any of the additional optional fields.
335
        var hasNewFields bool
×
336
        err = ReadElements(r, &hasNewFields)
×
337
        if err != nil {
×
338
                return nil, err
×
339
        }
×
340

341
        // If fields are not present, we can return.
342
        if !hasNewFields {
×
343
                return c, nil
×
344
        }
×
345

346
        // Otherwise read the new fields.
347
        if err := ReadElements(r, &c.RemoteCurrentRevocation); err != nil {
×
348
                return nil, err
×
349
        }
×
350

351
        if err := readChanConfig(r, &c.LocalChanConfig); err != nil {
×
352
                return nil, err
×
353
        }
×
354

355
        // Finally, we'll attempt to read the next unrevoked commitment point
356
        // for the remote party. If we closed the channel before receiving a
357
        // funding locked message then this might not be present. A boolean
358
        // indicating whether the field is present will come first.
359
        var hasRemoteNextRevocation bool
×
360
        err = ReadElements(r, &hasRemoteNextRevocation)
×
361
        if err != nil {
×
362
                return nil, err
×
363
        }
×
364

365
        // If this field was written, read it.
366
        if hasRemoteNextRevocation {
×
367
                err = ReadElements(r, &c.RemoteNextRevocation)
×
368
                if err != nil {
×
369
                        return nil, err
×
370
                }
×
371
        }
372

373
        // Check if we have a channel sync message to read.
374
        var hasChanSyncMsg bool
×
375
        err = ReadElements(r, &hasChanSyncMsg)
×
376
        if err == io.EOF {
×
377
                return c, nil
×
378
        } else if err != nil {
×
379
                return nil, err
×
380
        }
×
381

382
        // If a chan sync message is present, read it.
383
        if hasChanSyncMsg {
×
384
                // We must pass in reference to a lnwire.Message for the codec
×
385
                // to support it.
×
386
                var msg lnwire.Message
×
387
                if err := ReadElements(r, &msg); err != nil {
×
388
                        return nil, err
×
389
                }
×
390

391
                chanSync, ok := msg.(*lnwire.ChannelReestablish)
×
392
                if !ok {
×
393
                        return nil, errors.New("unable cast db Message to " +
×
394
                                "ChannelReestablish")
×
395
                }
×
396
                c.LastChanSyncMsg = chanSync
×
397
        }
398

399
        return c, nil
×
400
}
401

402
// ErrCorruptedFwdPkg signals that the on-disk structure of the forwarding
403
// package has potentially been mangled.
404
var ErrCorruptedFwdPkg = errors.New("fwding package db has been corrupted")
405

406
var (
407
        // fwdPackagesKey is the root-level bucket that all forwarding packages
408
        // are written. This bucket is further subdivided based on the short
409
        // channel ID of each channel.
410
        fwdPackagesKey = []byte("fwd-packages")
411

412
        // addBucketKey is the bucket to which all Add log updates are written.
413
        addBucketKey = []byte("add-updates")
414

415
        // failSettleBucketKey is the bucket to which all Settle/Fail log
416
        // updates are written.
417
        failSettleBucketKey = []byte("fail-settle-updates")
418

419
        // fwdFilterKey is a key used to write the set of Adds that passed
420
        // validation and are to be forwarded to the switch.
421
        // NOTE: The presence of this key within a forwarding package indicates
422
        // that the package has reached FwdStateProcessed.
423
        fwdFilterKey = []byte("fwd-filter-key")
424

425
        // ackFilterKey is a key used to access the PkgFilter indicating which
426
        // Adds have received a Settle/Fail. This response may come from a
427
        // number of sources, including: exitHop settle/fails, switch failures,
428
        // chain arbiter interjections, as well as settle/fails from the
429
        // next hop in the route.
430
        ackFilterKey = []byte("ack-filter-key")
431

432
        // settleFailFilterKey is a key used to access the PkgFilter indicating
433
        // which Settles/Fails in have been received and processed by the link
434
        // that originally received the Add.
435
        settleFailFilterKey = []byte("settle-fail-filter-key")
436
)
437

438
func makeLogKey(updateNum uint64) [8]byte {
×
439
        var key [8]byte
×
440
        byteOrder.PutUint64(key[:], updateNum)
×
441
        return key
×
442
}
×
443

444
// uint16Key writes the provided 16-bit unsigned integer to a 2-byte slice.
445
func uint16Key(i uint16) []byte {
×
446
        key := make([]byte, 2)
×
447
        byteOrder.PutUint16(key, i)
×
448
        return key
×
449
}
×
450

451
// ChannelPackager is used by a channel to manage the lifecycle of its forwarding
452
// packages. The packager is tied to a particular source channel ID, allowing it
453
// to create and edit its own packages. Each packager also has the ability to
454
// remove fail/settle htlcs that correspond to an add contained in one of
455
// source's packages.
456
type ChannelPackager struct {
457
        source lnwire.ShortChannelID
458
}
459

460
// NewChannelPackager creates a new packager for a single channel.
461
func NewChannelPackager(source lnwire.ShortChannelID) *ChannelPackager {
×
462
        return &ChannelPackager{
×
463
                source: source,
×
464
        }
×
465
}
×
466

467
// AddFwdPkg writes a newly locked in forwarding package to disk.
468
func (*ChannelPackager) AddFwdPkg(tx kvdb.RwTx, fwdPkg *common.FwdPkg) error { // nolint: dupl
×
469
        fwdPkgBkt, err := tx.CreateTopLevelBucket(fwdPackagesKey)
×
470
        if err != nil {
×
471
                return err
×
472
        }
×
473

474
        source := makeLogKey(fwdPkg.Source.ToUint64())
×
475
        sourceBkt, err := fwdPkgBkt.CreateBucketIfNotExists(source[:])
×
476
        if err != nil {
×
477
                return err
×
478
        }
×
479

480
        heightKey := makeLogKey(fwdPkg.Height)
×
481
        heightBkt, err := sourceBkt.CreateBucketIfNotExists(heightKey[:])
×
482
        if err != nil {
×
483
                return err
×
484
        }
×
485

486
        // Write ADD updates we received at this commit height.
487
        addBkt, err := heightBkt.CreateBucketIfNotExists(addBucketKey)
×
488
        if err != nil {
×
489
                return err
×
490
        }
×
491

492
        // Write SETTLE/FAIL updates we received at this commit height.
493
        failSettleBkt, err := heightBkt.CreateBucketIfNotExists(failSettleBucketKey)
×
494
        if err != nil {
×
495
                return err
×
496
        }
×
497

498
        for i := range fwdPkg.Adds {
×
499
                err = putLogUpdate(addBkt, uint16(i), &fwdPkg.Adds[i])
×
500
                if err != nil {
×
501
                        return err
×
502
                }
×
503
        }
504

505
        // Persist the initialized pkg filter, which will be used to determine
506
        // when we can remove this forwarding package from disk.
507
        var ackFilterBuf bytes.Buffer
×
508
        if err := fwdPkg.AckFilter.Encode(&ackFilterBuf); err != nil {
×
509
                return err
×
510
        }
×
511

512
        if err := heightBkt.Put(ackFilterKey, ackFilterBuf.Bytes()); err != nil {
×
513
                return err
×
514
        }
×
515

516
        for i := range fwdPkg.SettleFails {
×
517
                err = putLogUpdate(failSettleBkt, uint16(i), &fwdPkg.SettleFails[i])
×
518
                if err != nil {
×
519
                        return err
×
520
                }
×
521
        }
522

523
        var settleFailFilterBuf bytes.Buffer
×
524
        err = fwdPkg.SettleFailFilter.Encode(&settleFailFilterBuf)
×
525
        if err != nil {
×
526
                return err
×
527
        }
×
528

529
        return heightBkt.Put(settleFailFilterKey, settleFailFilterBuf.Bytes())
×
530
}
531

532
// putLogUpdate writes an htlc to the provided `bkt`, using `index` as the key.
533
func putLogUpdate(bkt kvdb.RwBucket, idx uint16, htlc *common.LogUpdate) error {
×
534
        var b bytes.Buffer
×
535
        if err := serializeLogUpdate(&b, htlc); err != nil {
×
536
                return err
×
537
        }
×
538

539
        return bkt.Put(uint16Key(idx), b.Bytes())
×
540
}
541

542
// LoadFwdPkgs scans the forwarding log for any packages that haven't been
543
// processed, and returns their deserialized log updates in a map indexed by the
544
// remote commitment height at which the updates were locked in.
545
func (p *ChannelPackager) LoadFwdPkgs(tx kvdb.RTx) ([]*common.FwdPkg, error) {
×
546
        return loadChannelFwdPkgs(tx, p.source)
×
547
}
×
548

549
// loadChannelFwdPkgs loads all forwarding packages owned by `source`.
550
func loadChannelFwdPkgs(tx kvdb.RTx, source lnwire.ShortChannelID) ([]*common.FwdPkg, error) { // nolint: dupl
×
551
        fwdPkgBkt := tx.ReadBucket(fwdPackagesKey)
×
552
        if fwdPkgBkt == nil {
×
553
                return nil, nil
×
554
        }
×
555

556
        sourceKey := makeLogKey(source.ToUint64())
×
557
        sourceBkt := fwdPkgBkt.NestedReadBucket(sourceKey[:])
×
558
        if sourceBkt == nil {
×
559
                return nil, nil
×
560
        }
×
561

562
        var heights []uint64
×
563
        if err := sourceBkt.ForEach(func(k, _ []byte) error {
×
564
                if len(k) != 8 {
×
565
                        return ErrCorruptedFwdPkg
×
566
                }
×
567

568
                heights = append(heights, byteOrder.Uint64(k))
×
569

×
570
                return nil
×
571
        }); err != nil {
×
572
                return nil, err
×
573
        }
×
574

575
        // Load the forwarding package for each retrieved height.
576
        fwdPkgs := make([]*common.FwdPkg, 0, len(heights))
×
577
        for _, height := range heights {
×
578
                fwdPkg, err := loadFwdPkg(fwdPkgBkt, source, height)
×
579
                if err != nil {
×
580
                        return nil, err
×
581
                }
×
582

583
                fwdPkgs = append(fwdPkgs, fwdPkg)
×
584
        }
585

586
        return fwdPkgs, nil
×
587
}
588

589
// loadFwdPkg reads the packager's fwd pkg at a given height, and determines the
590
// appropriate FwdState.
591
func loadFwdPkg(fwdPkgBkt kvdb.RBucket, source lnwire.ShortChannelID,
592
        height uint64) (*common.FwdPkg, error) {
×
593

×
594
        sourceKey := makeLogKey(source.ToUint64())
×
595
        sourceBkt := fwdPkgBkt.NestedReadBucket(sourceKey[:])
×
596
        if sourceBkt == nil {
×
597
                return nil, ErrCorruptedFwdPkg
×
598
        }
×
599

600
        heightKey := makeLogKey(height)
×
601
        heightBkt := sourceBkt.NestedReadBucket(heightKey[:])
×
602
        if heightBkt == nil {
×
603
                return nil, ErrCorruptedFwdPkg
×
604
        }
×
605

606
        // Load ADDs from disk.
607
        addBkt := heightBkt.NestedReadBucket(addBucketKey)
×
608
        if addBkt == nil {
×
609
                return nil, ErrCorruptedFwdPkg
×
610
        }
×
611

612
        adds, err := loadHtlcs(addBkt)
×
613
        if err != nil {
×
614
                return nil, err
×
615
        }
×
616

617
        // Load ack filter from disk.
618
        ackFilterBytes := heightBkt.Get(ackFilterKey)
×
619
        if ackFilterBytes == nil {
×
620
                return nil, ErrCorruptedFwdPkg
×
621
        }
×
622
        ackFilterReader := bytes.NewReader(ackFilterBytes)
×
623

×
624
        ackFilter := &common.PkgFilter{}
×
625
        if err := ackFilter.Decode(ackFilterReader); err != nil {
×
626
                return nil, err
×
627
        }
×
628

629
        // Load SETTLE/FAILs from disk.
630
        failSettleBkt := heightBkt.NestedReadBucket(failSettleBucketKey)
×
631
        if failSettleBkt == nil {
×
632
                return nil, ErrCorruptedFwdPkg
×
633
        }
×
634

635
        failSettles, err := loadHtlcs(failSettleBkt)
×
636
        if err != nil {
×
637
                return nil, err
×
638
        }
×
639

640
        // Load settle fail filter from disk.
641
        settleFailFilterBytes := heightBkt.Get(settleFailFilterKey)
×
642
        if settleFailFilterBytes == nil {
×
643
                return nil, ErrCorruptedFwdPkg
×
644
        }
×
645
        settleFailFilterReader := bytes.NewReader(settleFailFilterBytes)
×
646

×
647
        settleFailFilter := &common.PkgFilter{}
×
648
        if err := settleFailFilter.Decode(settleFailFilterReader); err != nil {
×
649
                return nil, err
×
650
        }
×
651

652
        // Initialize the fwding package, which always starts in the
653
        // FwdStateLockedIn. We can determine what state the package was left in
654
        // by examining constraints on the information loaded from disk.
655
        fwdPkg := &common.FwdPkg{
×
656
                Source:           source,
×
657
                State:            common.FwdStateLockedIn,
×
658
                Height:           height,
×
659
                Adds:             adds,
×
660
                AckFilter:        ackFilter,
×
661
                SettleFails:      failSettles,
×
662
                SettleFailFilter: settleFailFilter,
×
663
        }
×
664

×
665
        // Check to see if we have written the set exported filter adds to
×
666
        // disk. If we haven't, processing of this package was never started, or
×
667
        // failed during the last attempt.
×
668
        fwdFilterBytes := heightBkt.Get(fwdFilterKey)
×
669
        if fwdFilterBytes == nil {
×
670
                nAdds := uint16(len(adds))
×
671
                fwdPkg.FwdFilter = common.NewPkgFilter(nAdds)
×
672
                return fwdPkg, nil
×
673
        }
×
674

675
        fwdFilterReader := bytes.NewReader(fwdFilterBytes)
×
676
        fwdPkg.FwdFilter = &common.PkgFilter{}
×
677
        if err := fwdPkg.FwdFilter.Decode(fwdFilterReader); err != nil {
×
678
                return nil, err
×
679
        }
×
680

681
        // Otherwise, a complete round of processing was completed, and we
682
        // advance the package to FwdStateProcessed.
683
        fwdPkg.State = common.FwdStateProcessed
×
684

×
685
        // If every add, settle, and fail has been fully acknowledged, we can
×
686
        // safely set the package's state to FwdStateCompleted, signalling that
×
687
        // it can be garbage collected.
×
688
        if fwdPkg.AckFilter.IsFull() && fwdPkg.SettleFailFilter.IsFull() {
×
689
                fwdPkg.State = common.FwdStateCompleted
×
690
        }
×
691

692
        return fwdPkg, nil
×
693
}
694

695
// loadHtlcs retrieves all serialized htlcs in a bucket, returning
696
// them in order of the indexes they were written under.
697
func loadHtlcs(bkt kvdb.RBucket) ([]common.LogUpdate, error) {
×
698
        var htlcs []common.LogUpdate
×
699
        if err := bkt.ForEach(func(_, v []byte) error {
×
700
                htlc, err := deserializeLogUpdate(bytes.NewReader(v))
×
701
                if err != nil {
×
702
                        return err
×
703
                }
×
704

705
                htlcs = append(htlcs, *htlc)
×
706

×
707
                return nil
×
708
        }); err != nil {
×
709
                return nil, err
×
710
        }
×
711

712
        return htlcs, nil
×
713
}
714

715
// serializeLogUpdate writes a log update to the provided io.Writer.
716
func serializeLogUpdate(w io.Writer, l *common.LogUpdate) error {
×
717
        return WriteElements(w, l.LogIndex, l.UpdateMsg)
×
718
}
×
719

720
// deserializeLogUpdate reads a log update from the provided io.Reader.
721
func deserializeLogUpdate(r io.Reader) (*common.LogUpdate, error) {
×
722
        l := &common.LogUpdate{}
×
723
        if err := ReadElements(r, &l.LogIndex, &l.UpdateMsg); err != nil {
×
724
                return nil, err
×
725
        }
×
726

727
        return l, nil
×
728
}
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