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

lightningnetwork / lnd / 15736109134

18 Jun 2025 02:46PM UTC coverage: 58.197% (-10.1%) from 68.248%
15736109134

Pull #9752

github

web-flow
Merge d2634a68c into 31c74f20f
Pull Request #9752: routerrpc: reject payment to invoice that don't have payment secret or blinded paths

6 of 13 new or added lines in 2 files covered. (46.15%)

28331 existing lines in 455 files now uncovered.

97860 of 168153 relevant lines covered (58.2%)

1.81 hits per line

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

0.0
/channeldb/migration21/legacy/legacy_decoding.go
1
package legacy
2

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

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

UNCOV
14
func deserializeHtlcs(r io.Reader) ([]common.HTLC, error) {
×
UNCOV
15
        var numHtlcs uint16
×
UNCOV
16
        if err := ReadElement(r, &numHtlcs); err != nil {
×
17
                return nil, err
×
18
        }
×
19

UNCOV
20
        var htlcs []common.HTLC
×
UNCOV
21
        if numHtlcs == 0 {
×
UNCOV
22
                return htlcs, nil
×
UNCOV
23
        }
×
24

25
        htlcs = make([]common.HTLC, numHtlcs)
×
26
        for i := uint16(0); i < numHtlcs; i++ {
×
27
                if err := ReadElements(r,
×
28
                        &htlcs[i].Signature, &htlcs[i].RHash, &htlcs[i].Amt,
×
29
                        &htlcs[i].RefundTimeout, &htlcs[i].OutputIndex,
×
30
                        &htlcs[i].Incoming, &htlcs[i].OnionBlob,
×
31
                        &htlcs[i].HtlcIndex, &htlcs[i].LogIndex,
×
32
                ); err != nil {
×
33
                        return htlcs, err
×
34
                }
×
35
        }
36

37
        return htlcs, nil
×
38
}
39

UNCOV
40
func DeserializeLogUpdates(r io.Reader) ([]common.LogUpdate, error) {
×
UNCOV
41
        var numUpdates uint16
×
UNCOV
42
        if err := binary.Read(r, byteOrder, &numUpdates); err != nil {
×
43
                return nil, err
×
44
        }
×
45

UNCOV
46
        logUpdates := make([]common.LogUpdate, numUpdates)
×
UNCOV
47
        for i := 0; i < int(numUpdates); i++ {
×
UNCOV
48
                err := ReadElements(r,
×
UNCOV
49
                        &logUpdates[i].LogIndex, &logUpdates[i].UpdateMsg,
×
UNCOV
50
                )
×
UNCOV
51
                if err != nil {
×
52
                        return nil, err
×
53
                }
×
54
        }
55

UNCOV
56
        return logUpdates, nil
×
57
}
58

UNCOV
59
func deserializeChanCommit(r io.Reader) (common.ChannelCommitment, error) {
×
UNCOV
60
        var c common.ChannelCommitment
×
UNCOV
61

×
UNCOV
62
        err := ReadElements(r,
×
UNCOV
63
                &c.CommitHeight, &c.LocalLogIndex, &c.LocalHtlcIndex, &c.RemoteLogIndex,
×
UNCOV
64
                &c.RemoteHtlcIndex, &c.LocalBalance, &c.RemoteBalance,
×
UNCOV
65
                &c.CommitFee, &c.FeePerKw, &c.CommitTx, &c.CommitSig,
×
UNCOV
66
        )
×
UNCOV
67
        if err != nil {
×
68
                return c, err
×
69
        }
×
70

UNCOV
71
        c.Htlcs, err = deserializeHtlcs(r)
×
UNCOV
72
        if err != nil {
×
73
                return c, err
×
74
        }
×
75

UNCOV
76
        return c, nil
×
77
}
78

UNCOV
79
func DeserializeCommitDiff(r io.Reader) (*common.CommitDiff, error) {
×
UNCOV
80
        var (
×
UNCOV
81
                d   common.CommitDiff
×
UNCOV
82
                err error
×
UNCOV
83
        )
×
UNCOV
84

×
UNCOV
85
        d.Commitment, err = deserializeChanCommit(r)
×
UNCOV
86
        if err != nil {
×
87
                return nil, err
×
88
        }
×
89

UNCOV
90
        d.CommitSig = &lnwire.CommitSig{}
×
UNCOV
91
        if err := d.CommitSig.Decode(r, 0); err != nil {
×
92
                return nil, err
×
93
        }
×
94

UNCOV
95
        d.LogUpdates, err = DeserializeLogUpdates(r)
×
UNCOV
96
        if err != nil {
×
97
                return nil, err
×
98
        }
×
99

UNCOV
100
        var numOpenRefs uint16
×
UNCOV
101
        if err := binary.Read(r, byteOrder, &numOpenRefs); err != nil {
×
102
                return nil, err
×
103
        }
×
104

UNCOV
105
        d.OpenedCircuitKeys = make([]common.CircuitKey, numOpenRefs)
×
UNCOV
106
        for i := 0; i < int(numOpenRefs); i++ {
×
107
                err := ReadElements(r,
×
108
                        &d.OpenedCircuitKeys[i].ChanID,
×
109
                        &d.OpenedCircuitKeys[i].HtlcID)
×
110
                if err != nil {
×
111
                        return nil, err
×
112
                }
×
113
        }
114

UNCOV
115
        var numClosedRefs uint16
×
UNCOV
116
        if err := binary.Read(r, byteOrder, &numClosedRefs); err != nil {
×
117
                return nil, err
×
118
        }
×
119

UNCOV
120
        d.ClosedCircuitKeys = make([]common.CircuitKey, numClosedRefs)
×
UNCOV
121
        for i := 0; i < int(numClosedRefs); i++ {
×
122
                err := ReadElements(r,
×
123
                        &d.ClosedCircuitKeys[i].ChanID,
×
124
                        &d.ClosedCircuitKeys[i].HtlcID)
×
125
                if err != nil {
×
126
                        return nil, err
×
127
                }
×
128
        }
129

UNCOV
130
        return &d, nil
×
131
}
132

UNCOV
133
func serializeHtlcs(b io.Writer, htlcs ...common.HTLC) error {
×
UNCOV
134
        numHtlcs := uint16(len(htlcs))
×
UNCOV
135
        if err := WriteElement(b, numHtlcs); err != nil {
×
136
                return err
×
137
        }
×
138

UNCOV
139
        for _, htlc := range htlcs {
×
140
                if err := WriteElements(b,
×
141
                        htlc.Signature, htlc.RHash, htlc.Amt, htlc.RefundTimeout,
×
142
                        htlc.OutputIndex, htlc.Incoming, htlc.OnionBlob,
×
143
                        htlc.HtlcIndex, htlc.LogIndex,
×
144
                ); err != nil {
×
145
                        return err
×
146
                }
×
147
        }
148

UNCOV
149
        return nil
×
150
}
151

UNCOV
152
func serializeChanCommit(w io.Writer, c *common.ChannelCommitment) error {
×
UNCOV
153
        if err := WriteElements(w,
×
UNCOV
154
                c.CommitHeight, c.LocalLogIndex, c.LocalHtlcIndex,
×
UNCOV
155
                c.RemoteLogIndex, c.RemoteHtlcIndex, c.LocalBalance,
×
UNCOV
156
                c.RemoteBalance, c.CommitFee, c.FeePerKw, c.CommitTx,
×
UNCOV
157
                c.CommitSig,
×
UNCOV
158
        ); err != nil {
×
159
                return err
×
160
        }
×
161

UNCOV
162
        return serializeHtlcs(w, c.Htlcs...)
×
163
}
164

UNCOV
165
func SerializeLogUpdates(w io.Writer, logUpdates []common.LogUpdate) error {
×
UNCOV
166
        numUpdates := uint16(len(logUpdates))
×
UNCOV
167
        if err := binary.Write(w, byteOrder, numUpdates); err != nil {
×
168
                return err
×
169
        }
×
170

UNCOV
171
        for _, diff := range logUpdates {
×
UNCOV
172
                err := WriteElements(w, diff.LogIndex, diff.UpdateMsg)
×
UNCOV
173
                if err != nil {
×
174
                        return err
×
175
                }
×
176
        }
177

UNCOV
178
        return nil
×
179
}
180

UNCOV
181
func SerializeCommitDiff(w io.Writer, diff *common.CommitDiff) error { // nolint: dupl
×
UNCOV
182
        if err := serializeChanCommit(w, &diff.Commitment); err != nil {
×
183
                return err
×
184
        }
×
185

UNCOV
186
        if err := diff.CommitSig.Encode(w, 0); err != nil {
×
187
                return err
×
188
        }
×
189

UNCOV
190
        if err := SerializeLogUpdates(w, diff.LogUpdates); err != nil {
×
191
                return err
×
192
        }
×
193

UNCOV
194
        numOpenRefs := uint16(len(diff.OpenedCircuitKeys))
×
UNCOV
195
        if err := binary.Write(w, byteOrder, numOpenRefs); err != nil {
×
196
                return err
×
197
        }
×
198

UNCOV
199
        for _, openRef := range diff.OpenedCircuitKeys {
×
200
                err := WriteElements(w, openRef.ChanID, openRef.HtlcID)
×
201
                if err != nil {
×
202
                        return err
×
203
                }
×
204
        }
205

UNCOV
206
        numClosedRefs := uint16(len(diff.ClosedCircuitKeys))
×
UNCOV
207
        if err := binary.Write(w, byteOrder, numClosedRefs); err != nil {
×
208
                return err
×
209
        }
×
210

UNCOV
211
        for _, closedRef := range diff.ClosedCircuitKeys {
×
212
                err := WriteElements(w, closedRef.ChanID, closedRef.HtlcID)
×
213
                if err != nil {
×
214
                        return err
×
215
                }
×
216
        }
217

UNCOV
218
        return nil
×
219
}
220

UNCOV
221
func DeserializeNetworkResult(r io.Reader) (*common.NetworkResult, error) {
×
UNCOV
222
        var (
×
UNCOV
223
                err error
×
UNCOV
224
        )
×
UNCOV
225

×
UNCOV
226
        n := &common.NetworkResult{}
×
UNCOV
227

×
UNCOV
228
        n.Msg, err = lnwire.ReadMessage(r, 0)
×
UNCOV
229
        if err != nil {
×
230
                return nil, err
×
231
        }
×
232

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

UNCOV
239
        return n, nil
×
240
}
241

UNCOV
242
func SerializeNetworkResult(w io.Writer, n *common.NetworkResult) error {
×
UNCOV
243
        if _, err := lnwire.WriteMessage(w, n.Msg, 0); err != nil {
×
244
                return err
×
245
        }
×
246

UNCOV
247
        return WriteElements(w, n.Unencrypted, n.IsResolution)
×
248
}
249

UNCOV
250
func readChanConfig(b io.Reader, c *common.ChannelConfig) error { // nolint: dupl
×
UNCOV
251
        return ReadElements(b,
×
UNCOV
252
                &c.DustLimit, &c.MaxPendingAmount, &c.ChanReserve,
×
UNCOV
253
                &c.MinHTLC, &c.MaxAcceptedHtlcs, &c.CsvDelay,
×
UNCOV
254
                &c.MultiSigKey, &c.RevocationBasePoint,
×
UNCOV
255
                &c.PaymentBasePoint, &c.DelayBasePoint,
×
UNCOV
256
                &c.HtlcBasePoint,
×
UNCOV
257
        )
×
UNCOV
258
}
×
259

260
func DeserializeCloseChannelSummary(
UNCOV
261
        r io.Reader) (*common.ChannelCloseSummary, error) { // nolint: dupl
×
UNCOV
262

×
UNCOV
263
        c := &common.ChannelCloseSummary{}
×
UNCOV
264

×
UNCOV
265
        err := ReadElements(r,
×
UNCOV
266
                &c.ChanPoint, &c.ShortChanID, &c.ChainHash, &c.ClosingTXID,
×
UNCOV
267
                &c.CloseHeight, &c.RemotePub, &c.Capacity, &c.SettledBalance,
×
UNCOV
268
                &c.TimeLockedBalance, &c.CloseType, &c.IsPending,
×
UNCOV
269
        )
×
UNCOV
270
        if err != nil {
×
271
                return nil, err
×
272
        }
×
273

274
        // We'll now check to see if the channel close summary was encoded with
275
        // any of the additional optional fields.
UNCOV
276
        var hasNewFields bool
×
UNCOV
277
        err = ReadElements(r, &hasNewFields)
×
UNCOV
278
        if err != nil {
×
279
                return nil, err
×
280
        }
×
281

282
        // If fields are not present, we can return.
UNCOV
283
        if !hasNewFields {
×
284
                return c, nil
×
285
        }
×
286

287
        // Otherwise read the new fields.
UNCOV
288
        if err := ReadElements(r, &c.RemoteCurrentRevocation); err != nil {
×
289
                return nil, err
×
290
        }
×
291

UNCOV
292
        if err := readChanConfig(r, &c.LocalChanConfig); err != nil {
×
293
                return nil, err
×
294
        }
×
295

296
        // Finally, we'll attempt to read the next unrevoked commitment point
297
        // for the remote party. If we closed the channel before receiving a
298
        // funding locked message then this might not be present. A boolean
299
        // indicating whether the field is present will come first.
UNCOV
300
        var hasRemoteNextRevocation bool
×
UNCOV
301
        err = ReadElements(r, &hasRemoteNextRevocation)
×
UNCOV
302
        if err != nil {
×
303
                return nil, err
×
304
        }
×
305

306
        // If this field was written, read it.
UNCOV
307
        if hasRemoteNextRevocation {
×
UNCOV
308
                err = ReadElements(r, &c.RemoteNextRevocation)
×
UNCOV
309
                if err != nil {
×
310
                        return nil, err
×
311
                }
×
312
        }
313

314
        // Check if we have a channel sync message to read.
UNCOV
315
        var hasChanSyncMsg bool
×
UNCOV
316
        err = ReadElements(r, &hasChanSyncMsg)
×
UNCOV
317
        if err == io.EOF {
×
318
                return c, nil
×
UNCOV
319
        } else if err != nil {
×
320
                return nil, err
×
321
        }
×
322

323
        // If a chan sync message is present, read it.
UNCOV
324
        if hasChanSyncMsg {
×
UNCOV
325
                // We must pass in reference to a lnwire.Message for the codec
×
UNCOV
326
                // to support it.
×
UNCOV
327
                msg, err := lnwire.ReadMessage(r, 0)
×
UNCOV
328
                if err != nil {
×
329
                        return nil, err
×
330
                }
×
331

UNCOV
332
                chanSync, ok := msg.(*lnwire.ChannelReestablish)
×
UNCOV
333
                if !ok {
×
334
                        return nil, errors.New("unable cast db Message to " +
×
335
                                "ChannelReestablish")
×
336
                }
×
UNCOV
337
                c.LastChanSyncMsg = chanSync
×
338
        }
339

UNCOV
340
        return c, nil
×
341
}
342

UNCOV
343
func writeChanConfig(b io.Writer, c *common.ChannelConfig) error { // nolint: dupl
×
UNCOV
344
        return WriteElements(b,
×
UNCOV
345
                c.DustLimit, c.MaxPendingAmount, c.ChanReserve, c.MinHTLC,
×
UNCOV
346
                c.MaxAcceptedHtlcs, c.CsvDelay, c.MultiSigKey,
×
UNCOV
347
                c.RevocationBasePoint, c.PaymentBasePoint, c.DelayBasePoint,
×
UNCOV
348
                c.HtlcBasePoint,
×
UNCOV
349
        )
×
UNCOV
350
}
×
351

UNCOV
352
func SerializeChannelCloseSummary(w io.Writer, cs *common.ChannelCloseSummary) error {
×
UNCOV
353
        err := WriteElements(w,
×
UNCOV
354
                cs.ChanPoint, cs.ShortChanID, cs.ChainHash, cs.ClosingTXID,
×
UNCOV
355
                cs.CloseHeight, cs.RemotePub, cs.Capacity, cs.SettledBalance,
×
UNCOV
356
                cs.TimeLockedBalance, cs.CloseType, cs.IsPending,
×
UNCOV
357
        )
×
UNCOV
358
        if err != nil {
×
359
                return err
×
360
        }
×
361

362
        // If this is a close channel summary created before the addition of
363
        // the new fields, then we can exit here.
UNCOV
364
        if cs.RemoteCurrentRevocation == nil {
×
365
                return WriteElements(w, false)
×
366
        }
×
367

368
        // If fields are present, write boolean to indicate this, and continue.
UNCOV
369
        if err := WriteElements(w, true); err != nil {
×
370
                return err
×
371
        }
×
372

UNCOV
373
        if err := WriteElements(w, cs.RemoteCurrentRevocation); err != nil {
×
374
                return err
×
375
        }
×
376

UNCOV
377
        if err := writeChanConfig(w, &cs.LocalChanConfig); err != nil {
×
378
                return err
×
379
        }
×
380

381
        // The RemoteNextRevocation field is optional, as it's possible for a
382
        // channel to be closed before we learn of the next unrevoked
383
        // revocation point for the remote party. Write a boolean indicating
384
        // whether this field is present or not.
UNCOV
385
        if err := WriteElements(w, cs.RemoteNextRevocation != nil); err != nil {
×
386
                return err
×
387
        }
×
388

389
        // Write the field, if present.
UNCOV
390
        if cs.RemoteNextRevocation != nil {
×
UNCOV
391
                if err = WriteElements(w, cs.RemoteNextRevocation); err != nil {
×
392
                        return err
×
393
                }
×
394
        }
395

396
        // Write whether the channel sync message is present.
UNCOV
397
        if err := WriteElements(w, cs.LastChanSyncMsg != nil); err != nil {
×
398
                return err
×
399
        }
×
400

401
        // Write the channel sync message, if present.
UNCOV
402
        if cs.LastChanSyncMsg != nil {
×
UNCOV
403
                _, err = lnwire.WriteMessage(w, cs.LastChanSyncMsg, 0)
×
UNCOV
404
                if err != nil {
×
405
                        return err
×
406
                }
×
407
        }
408

UNCOV
409
        return nil
×
410
}
411

412
// ErrCorruptedFwdPkg signals that the on-disk structure of the forwarding
413
// package has potentially been mangled.
414
var ErrCorruptedFwdPkg = errors.New("fwding package db has been corrupted")
415

416
var (
417
        // fwdPackagesKey is the root-level bucket that all forwarding packages
418
        // are written. This bucket is further subdivided based on the short
419
        // channel ID of each channel.
420
        fwdPackagesKey = []byte("fwd-packages")
421

422
        // addBucketKey is the bucket to which all Add log updates are written.
423
        addBucketKey = []byte("add-updates")
424

425
        // failSettleBucketKey is the bucket to which all Settle/Fail log
426
        // updates are written.
427
        failSettleBucketKey = []byte("fail-settle-updates")
428

429
        // fwdFilterKey is a key used to write the set of Adds that passed
430
        // validation and are to be forwarded to the switch.
431
        // NOTE: The presence of this key within a forwarding package indicates
432
        // that the package has reached FwdStateProcessed.
433
        fwdFilterKey = []byte("fwd-filter-key")
434

435
        // ackFilterKey is a key used to access the PkgFilter indicating which
436
        // Adds have received a Settle/Fail. This response may come from a
437
        // number of sources, including: exitHop settle/fails, switch failures,
438
        // chain arbiter interjections, as well as settle/fails from the
439
        // next hop in the route.
440
        ackFilterKey = []byte("ack-filter-key")
441

442
        // settleFailFilterKey is a key used to access the PkgFilter indicating
443
        // which Settles/Fails in have been received and processed by the link
444
        // that originally received the Add.
445
        settleFailFilterKey = []byte("settle-fail-filter-key")
446
)
447

UNCOV
448
func makeLogKey(updateNum uint64) [8]byte {
×
UNCOV
449
        var key [8]byte
×
UNCOV
450
        byteOrder.PutUint64(key[:], updateNum)
×
UNCOV
451
        return key
×
UNCOV
452
}
×
453

454
// uint16Key writes the provided 16-bit unsigned integer to a 2-byte slice.
UNCOV
455
func uint16Key(i uint16) []byte {
×
UNCOV
456
        key := make([]byte, 2)
×
UNCOV
457
        byteOrder.PutUint16(key, i)
×
UNCOV
458
        return key
×
UNCOV
459
}
×
460

461
// ChannelPackager is used by a channel to manage the lifecycle of its forwarding
462
// packages. The packager is tied to a particular source channel ID, allowing it
463
// to create and edit its own packages. Each packager also has the ability to
464
// remove fail/settle htlcs that correspond to an add contained in one of
465
// source's packages.
466
type ChannelPackager struct {
467
        source lnwire.ShortChannelID
468
}
469

470
// NewChannelPackager creates a new packager for a single channel.
UNCOV
471
func NewChannelPackager(source lnwire.ShortChannelID) *ChannelPackager {
×
UNCOV
472
        return &ChannelPackager{
×
UNCOV
473
                source: source,
×
UNCOV
474
        }
×
UNCOV
475
}
×
476

477
// AddFwdPkg writes a newly locked in forwarding package to disk.
UNCOV
478
func (*ChannelPackager) AddFwdPkg(tx kvdb.RwTx, fwdPkg *common.FwdPkg) error { // nolint: dupl
×
UNCOV
479
        fwdPkgBkt, err := tx.CreateTopLevelBucket(fwdPackagesKey)
×
UNCOV
480
        if err != nil {
×
481
                return err
×
482
        }
×
483

UNCOV
484
        source := makeLogKey(fwdPkg.Source.ToUint64())
×
UNCOV
485
        sourceBkt, err := fwdPkgBkt.CreateBucketIfNotExists(source[:])
×
UNCOV
486
        if err != nil {
×
487
                return err
×
488
        }
×
489

UNCOV
490
        heightKey := makeLogKey(fwdPkg.Height)
×
UNCOV
491
        heightBkt, err := sourceBkt.CreateBucketIfNotExists(heightKey[:])
×
UNCOV
492
        if err != nil {
×
493
                return err
×
494
        }
×
495

496
        // Write ADD updates we received at this commit height.
UNCOV
497
        addBkt, err := heightBkt.CreateBucketIfNotExists(addBucketKey)
×
UNCOV
498
        if err != nil {
×
499
                return err
×
500
        }
×
501

502
        // Write SETTLE/FAIL updates we received at this commit height.
UNCOV
503
        failSettleBkt, err := heightBkt.CreateBucketIfNotExists(failSettleBucketKey)
×
UNCOV
504
        if err != nil {
×
505
                return err
×
506
        }
×
507

UNCOV
508
        for i := range fwdPkg.Adds {
×
UNCOV
509
                err = putLogUpdate(addBkt, uint16(i), &fwdPkg.Adds[i])
×
UNCOV
510
                if err != nil {
×
511
                        return err
×
512
                }
×
513
        }
514

515
        // Persist the initialized pkg filter, which will be used to determine
516
        // when we can remove this forwarding package from disk.
UNCOV
517
        var ackFilterBuf bytes.Buffer
×
UNCOV
518
        if err := fwdPkg.AckFilter.Encode(&ackFilterBuf); err != nil {
×
519
                return err
×
520
        }
×
521

UNCOV
522
        if err := heightBkt.Put(ackFilterKey, ackFilterBuf.Bytes()); err != nil {
×
523
                return err
×
524
        }
×
525

UNCOV
526
        for i := range fwdPkg.SettleFails {
×
UNCOV
527
                err = putLogUpdate(failSettleBkt, uint16(i), &fwdPkg.SettleFails[i])
×
UNCOV
528
                if err != nil {
×
529
                        return err
×
530
                }
×
531
        }
532

UNCOV
533
        var settleFailFilterBuf bytes.Buffer
×
UNCOV
534
        err = fwdPkg.SettleFailFilter.Encode(&settleFailFilterBuf)
×
UNCOV
535
        if err != nil {
×
536
                return err
×
537
        }
×
538

UNCOV
539
        return heightBkt.Put(settleFailFilterKey, settleFailFilterBuf.Bytes())
×
540
}
541

542
// putLogUpdate writes an htlc to the provided `bkt`, using `index` as the key.
UNCOV
543
func putLogUpdate(bkt kvdb.RwBucket, idx uint16, htlc *common.LogUpdate) error {
×
UNCOV
544
        var b bytes.Buffer
×
UNCOV
545
        if err := serializeLogUpdate(&b, htlc); err != nil {
×
546
                return err
×
547
        }
×
548

UNCOV
549
        return bkt.Put(uint16Key(idx), b.Bytes())
×
550
}
551

552
// LoadFwdPkgs scans the forwarding log for any packages that haven't been
553
// processed, and returns their deserialized log updates in a map indexed by the
554
// remote commitment height at which the updates were locked in.
UNCOV
555
func (p *ChannelPackager) LoadFwdPkgs(tx kvdb.RTx) ([]*common.FwdPkg, error) {
×
UNCOV
556
        return loadChannelFwdPkgs(tx, p.source)
×
UNCOV
557
}
×
558

559
// loadChannelFwdPkgs loads all forwarding packages owned by `source`.
UNCOV
560
func loadChannelFwdPkgs(tx kvdb.RTx, source lnwire.ShortChannelID) ([]*common.FwdPkg, error) { // nolint: dupl
×
UNCOV
561
        fwdPkgBkt := tx.ReadBucket(fwdPackagesKey)
×
UNCOV
562
        if fwdPkgBkt == nil {
×
563
                return nil, nil
×
564
        }
×
565

UNCOV
566
        sourceKey := makeLogKey(source.ToUint64())
×
UNCOV
567
        sourceBkt := fwdPkgBkt.NestedReadBucket(sourceKey[:])
×
UNCOV
568
        if sourceBkt == nil {
×
569
                return nil, nil
×
570
        }
×
571

UNCOV
572
        var heights []uint64
×
UNCOV
573
        if err := sourceBkt.ForEach(func(k, _ []byte) error {
×
UNCOV
574
                if len(k) != 8 {
×
575
                        return ErrCorruptedFwdPkg
×
576
                }
×
577

UNCOV
578
                heights = append(heights, byteOrder.Uint64(k))
×
UNCOV
579

×
UNCOV
580
                return nil
×
581
        }); err != nil {
×
582
                return nil, err
×
583
        }
×
584

585
        // Load the forwarding package for each retrieved height.
UNCOV
586
        fwdPkgs := make([]*common.FwdPkg, 0, len(heights))
×
UNCOV
587
        for _, height := range heights {
×
UNCOV
588
                fwdPkg, err := loadFwdPkg(fwdPkgBkt, source, height)
×
UNCOV
589
                if err != nil {
×
590
                        return nil, err
×
591
                }
×
592

UNCOV
593
                fwdPkgs = append(fwdPkgs, fwdPkg)
×
594
        }
595

UNCOV
596
        return fwdPkgs, nil
×
597
}
598

599
// loadFwdPkg reads the packager's fwd pkg at a given height, and determines the
600
// appropriate FwdState.
601
func loadFwdPkg(fwdPkgBkt kvdb.RBucket, source lnwire.ShortChannelID,
UNCOV
602
        height uint64) (*common.FwdPkg, error) {
×
UNCOV
603

×
UNCOV
604
        sourceKey := makeLogKey(source.ToUint64())
×
UNCOV
605
        sourceBkt := fwdPkgBkt.NestedReadBucket(sourceKey[:])
×
UNCOV
606
        if sourceBkt == nil {
×
607
                return nil, ErrCorruptedFwdPkg
×
608
        }
×
609

UNCOV
610
        heightKey := makeLogKey(height)
×
UNCOV
611
        heightBkt := sourceBkt.NestedReadBucket(heightKey[:])
×
UNCOV
612
        if heightBkt == nil {
×
613
                return nil, ErrCorruptedFwdPkg
×
614
        }
×
615

616
        // Load ADDs from disk.
UNCOV
617
        addBkt := heightBkt.NestedReadBucket(addBucketKey)
×
UNCOV
618
        if addBkt == nil {
×
619
                return nil, ErrCorruptedFwdPkg
×
620
        }
×
621

UNCOV
622
        adds, err := loadHtlcs(addBkt)
×
UNCOV
623
        if err != nil {
×
624
                return nil, err
×
625
        }
×
626

627
        // Load ack filter from disk.
UNCOV
628
        ackFilterBytes := heightBkt.Get(ackFilterKey)
×
UNCOV
629
        if ackFilterBytes == nil {
×
630
                return nil, ErrCorruptedFwdPkg
×
631
        }
×
UNCOV
632
        ackFilterReader := bytes.NewReader(ackFilterBytes)
×
UNCOV
633

×
UNCOV
634
        ackFilter := &common.PkgFilter{}
×
UNCOV
635
        if err := ackFilter.Decode(ackFilterReader); err != nil {
×
636
                return nil, err
×
637
        }
×
638

639
        // Load SETTLE/FAILs from disk.
UNCOV
640
        failSettleBkt := heightBkt.NestedReadBucket(failSettleBucketKey)
×
UNCOV
641
        if failSettleBkt == nil {
×
642
                return nil, ErrCorruptedFwdPkg
×
643
        }
×
644

UNCOV
645
        failSettles, err := loadHtlcs(failSettleBkt)
×
UNCOV
646
        if err != nil {
×
647
                return nil, err
×
648
        }
×
649

650
        // Load settle fail filter from disk.
UNCOV
651
        settleFailFilterBytes := heightBkt.Get(settleFailFilterKey)
×
UNCOV
652
        if settleFailFilterBytes == nil {
×
653
                return nil, ErrCorruptedFwdPkg
×
654
        }
×
UNCOV
655
        settleFailFilterReader := bytes.NewReader(settleFailFilterBytes)
×
UNCOV
656

×
UNCOV
657
        settleFailFilter := &common.PkgFilter{}
×
UNCOV
658
        if err := settleFailFilter.Decode(settleFailFilterReader); err != nil {
×
659
                return nil, err
×
660
        }
×
661

662
        // Initialize the fwding package, which always starts in the
663
        // FwdStateLockedIn. We can determine what state the package was left in
664
        // by examining constraints on the information loaded from disk.
UNCOV
665
        fwdPkg := &common.FwdPkg{
×
UNCOV
666
                Source:           source,
×
UNCOV
667
                State:            common.FwdStateLockedIn,
×
UNCOV
668
                Height:           height,
×
UNCOV
669
                Adds:             adds,
×
UNCOV
670
                AckFilter:        ackFilter,
×
UNCOV
671
                SettleFails:      failSettles,
×
UNCOV
672
                SettleFailFilter: settleFailFilter,
×
UNCOV
673
        }
×
UNCOV
674

×
UNCOV
675
        // Check to see if we have written the set exported filter adds to
×
UNCOV
676
        // disk. If we haven't, processing of this package was never started, or
×
UNCOV
677
        // failed during the last attempt.
×
UNCOV
678
        fwdFilterBytes := heightBkt.Get(fwdFilterKey)
×
UNCOV
679
        if fwdFilterBytes == nil {
×
UNCOV
680
                nAdds := uint16(len(adds))
×
UNCOV
681
                fwdPkg.FwdFilter = common.NewPkgFilter(nAdds)
×
UNCOV
682
                return fwdPkg, nil
×
UNCOV
683
        }
×
684

685
        fwdFilterReader := bytes.NewReader(fwdFilterBytes)
×
686
        fwdPkg.FwdFilter = &common.PkgFilter{}
×
687
        if err := fwdPkg.FwdFilter.Decode(fwdFilterReader); err != nil {
×
688
                return nil, err
×
689
        }
×
690

691
        // Otherwise, a complete round of processing was completed, and we
692
        // advance the package to FwdStateProcessed.
693
        fwdPkg.State = common.FwdStateProcessed
×
694

×
695
        // If every add, settle, and fail has been fully acknowledged, we can
×
696
        // safely set the package's state to FwdStateCompleted, signalling that
×
697
        // it can be garbage collected.
×
698
        if fwdPkg.AckFilter.IsFull() && fwdPkg.SettleFailFilter.IsFull() {
×
699
                fwdPkg.State = common.FwdStateCompleted
×
700
        }
×
701

702
        return fwdPkg, nil
×
703
}
704

705
// loadHtlcs retrieves all serialized htlcs in a bucket, returning
706
// them in order of the indexes they were written under.
UNCOV
707
func loadHtlcs(bkt kvdb.RBucket) ([]common.LogUpdate, error) {
×
UNCOV
708
        var htlcs []common.LogUpdate
×
UNCOV
709
        if err := bkt.ForEach(func(_, v []byte) error {
×
UNCOV
710
                htlc, err := deserializeLogUpdate(bytes.NewReader(v))
×
UNCOV
711
                if err != nil {
×
712
                        return err
×
713
                }
×
714

UNCOV
715
                htlcs = append(htlcs, *htlc)
×
UNCOV
716

×
UNCOV
717
                return nil
×
718
        }); err != nil {
×
719
                return nil, err
×
720
        }
×
721

UNCOV
722
        return htlcs, nil
×
723
}
724

725
// serializeLogUpdate writes a log update to the provided io.Writer.
UNCOV
726
func serializeLogUpdate(w io.Writer, l *common.LogUpdate) error {
×
UNCOV
727
        return WriteElements(w, l.LogIndex, l.UpdateMsg)
×
UNCOV
728
}
×
729

730
// deserializeLogUpdate reads a log update from the provided io.Reader.
UNCOV
731
func deserializeLogUpdate(r io.Reader) (*common.LogUpdate, error) {
×
UNCOV
732
        l := &common.LogUpdate{}
×
UNCOV
733
        if err := ReadElements(r, &l.LogIndex, &l.UpdateMsg); err != nil {
×
734
                return nil, err
×
735
        }
×
736

UNCOV
737
        return l, nil
×
738
}
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