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

lightningnetwork / lnd / 12986279612

27 Jan 2025 09:51AM UTC coverage: 57.652% (-1.1%) from 58.788%
12986279612

Pull #9447

github

yyforyongyu
sweep: rename methods for clarity

We now rename "third party" to "unknown" as the inputs can be spent via
an older sweeping tx, a third party (anchor), or a remote party (pin).
In fee bumper we don't have the info to distinguish the above cases, and
leave them to be further handled by the sweeper as it has more context.
Pull Request #9447: sweep: start tracking input spending status in the fee bumper

83 of 87 new or added lines in 2 files covered. (95.4%)

19578 existing lines in 256 files now uncovered.

103448 of 179434 relevant lines covered (57.65%)

24884.58 hits per line

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

79.63
/contractcourt/taproot_briefcase.go
1
package contractcourt
2

3
import (
4
        "bytes"
5
        "io"
6

7
        "github.com/lightningnetwork/lnd/tlv"
8
)
9

10
const (
11
        commitCtrlBlockType       tlv.Type = 0
12
        revokeCtrlBlockType       tlv.Type = 1
13
        outgoingHtlcCtrlBlockType tlv.Type = 2
14
        incomingHtlcCtrlBlockType tlv.Type = 3
15
        secondLevelCtrlBlockType  tlv.Type = 4
16

17
        anchorTapTweakType                tlv.Type = 0
18
        htlcTweakCtrlBlockType            tlv.Type = 1
19
        secondLevelHtlcTweakCtrlBlockType tlv.Type = 2
20
)
21

22
// taprootBriefcase is a supplemental storage struct that contains all the
23
// information we need to sweep taproot outputs.
24
type taprootBriefcase struct {
25
        // CtrlBlock is the set of control block for the taproot outputs.
26
        CtrlBlocks tlv.RecordT[tlv.TlvType0, ctrlBlocks]
27

28
        // TapTweaks is the set of taproot tweaks for the taproot outputs that
29
        // are to be spent via a keyspend path. This includes anchors, and any
30
        // revocation paths.
31
        TapTweaks tlv.RecordT[tlv.TlvType1, tapTweaks]
32

33
        // SettledCommitBlob is an optional record that contains an opaque blob
34
        // that may be used to properly sweep commitment outputs on a force
35
        // close transaction.
36
        SettledCommitBlob tlv.OptionalRecordT[tlv.TlvType2, tlv.Blob]
37

38
        // BreachCommitBlob is an optional record that contains an opaque blob
39
        // used to sweep a remote party's breached output.
40
        BreachedCommitBlob tlv.OptionalRecordT[tlv.TlvType3, tlv.Blob]
41

42
        // HtlcBlobs is an optikonal record that contains the opaque blobs for
43
        // the set of active HTLCs on the commitment transaction.
44
        HtlcBlobs tlv.OptionalRecordT[tlv.TlvType4, htlcAuxBlobs]
45
}
46

47
// TODO(roasbeef): morph into new tlv record
48

49
// newTaprootBriefcase returns a new instance of the taproot specific briefcase
50
// variant.
UNCOV
51
func newTaprootBriefcase() *taprootBriefcase {
×
UNCOV
52
        return &taprootBriefcase{
×
UNCOV
53
                CtrlBlocks: tlv.NewRecordT[tlv.TlvType0](newCtrlBlocks()),
×
UNCOV
54
                TapTweaks:  tlv.NewRecordT[tlv.TlvType1](newTapTweaks()),
×
UNCOV
55
        }
×
UNCOV
56
}
×
57

58
// EncodeRecords returns a slice of TLV records that should be encoded.
59
func (t *taprootBriefcase) EncodeRecords() []tlv.Record {
1✔
60
        records := []tlv.Record{
1✔
61
                t.CtrlBlocks.Record(),
1✔
62
                t.TapTweaks.Record(),
1✔
63
        }
1✔
64

1✔
65
        t.SettledCommitBlob.WhenSome(
1✔
66
                func(r tlv.RecordT[tlv.TlvType2, tlv.Blob]) {
2✔
67
                        records = append(records, r.Record())
1✔
68
                },
1✔
69
        )
70
        t.BreachedCommitBlob.WhenSome(
1✔
71
                func(r tlv.RecordT[tlv.TlvType3, tlv.Blob]) {
2✔
72
                        records = append(records, r.Record())
1✔
73
                },
1✔
74
        )
75
        t.HtlcBlobs.WhenSome(func(r tlv.RecordT[tlv.TlvType4, htlcAuxBlobs]) {
2✔
76
                records = append(records, r.Record())
1✔
77
        })
1✔
78

79
        return records
1✔
80
}
81

82
// DecodeRecords returns a slice of TLV records that should be decoded.
83
func (t *taprootBriefcase) DecodeRecords() []tlv.Record {
1✔
84
        return []tlv.Record{
1✔
85
                t.CtrlBlocks.Record(),
1✔
86
                t.TapTweaks.Record(),
1✔
87
        }
1✔
88
}
1✔
89

90
// Encode records returns a slice of TLV records that should be encoded.
91
func (t *taprootBriefcase) Encode(w io.Writer) error {
1✔
92
        stream, err := tlv.NewStream(t.EncodeRecords()...)
1✔
93
        if err != nil {
1✔
94
                return err
×
95
        }
×
96

97
        return stream.Encode(w)
1✔
98
}
99

100
// Decode decodes the given reader into the target struct.
101
func (t *taprootBriefcase) Decode(r io.Reader) error {
1✔
102
        settledCommitBlob := t.SettledCommitBlob.Zero()
1✔
103
        breachedCommitBlob := t.BreachedCommitBlob.Zero()
1✔
104
        htlcBlobs := t.HtlcBlobs.Zero()
1✔
105

1✔
106
        records := append(
1✔
107
                t.DecodeRecords(), settledCommitBlob.Record(),
1✔
108
                breachedCommitBlob.Record(), htlcBlobs.Record(),
1✔
109
        )
1✔
110
        stream, err := tlv.NewStream(records...)
1✔
111
        if err != nil {
1✔
112
                return err
×
113
        }
×
114

115
        typeMap, err := stream.DecodeWithParsedTypes(r)
1✔
116
        if err != nil {
1✔
117
                return err
×
118
        }
×
119

120
        if val, ok := typeMap[t.SettledCommitBlob.TlvType()]; ok && val == nil {
2✔
121
                t.SettledCommitBlob = tlv.SomeRecordT(settledCommitBlob)
1✔
122
        }
1✔
123
        if v, ok := typeMap[t.BreachedCommitBlob.TlvType()]; ok && v == nil {
2✔
124
                t.BreachedCommitBlob = tlv.SomeRecordT(breachedCommitBlob)
1✔
125
        }
1✔
126
        if v, ok := typeMap[t.HtlcBlobs.TlvType()]; ok && v == nil {
2✔
127
                t.HtlcBlobs = tlv.SomeRecordT(htlcBlobs)
1✔
128
        }
1✔
129

130
        return nil
1✔
131
}
132

133
// resolverCtrlBlocks is a map of resolver IDs to their corresponding control
134
// block.
135
type resolverCtrlBlocks map[resolverID][]byte
136

137
// newResolverCtrlBlockss returns a new instance of the resolverCtrlBlocks.
138
func newResolverCtrlBlocks() resolverCtrlBlocks {
3✔
139
        return make(resolverCtrlBlocks)
3✔
140
}
3✔
141

142
// recordSize returns the size of the record in bytes.
143
func (r *resolverCtrlBlocks) recordSize() uint64 {
6✔
144
        // Each record will be serialized as: <num_total_records> || <record>,
6✔
145
        // where <record> is serialized as: <resolver_key> || <length> ||
6✔
146
        // <ctrl_block>.
6✔
147
        numBlocks := uint64(len(*r))
6✔
148
        baseSize := tlv.VarIntSize(numBlocks)
6✔
149

6✔
150
        recordSize := baseSize
6✔
151
        for _, ctrlBlock := range *r {
666✔
152
                recordSize += resolverIDLen
660✔
153
                recordSize += tlv.VarIntSize(uint64(len(ctrlBlock)))
660✔
154
                recordSize += uint64(len(ctrlBlock))
660✔
155
        }
660✔
156

157
        return recordSize
6✔
158
}
159

160
// Encode encodes the control blocks into the target writer.
161
func (r *resolverCtrlBlocks) Encode(w io.Writer) error {
6✔
162
        numBlocks := uint64(len(*r))
6✔
163

6✔
164
        var buf [8]byte
6✔
165
        if err := tlv.WriteVarInt(w, numBlocks, &buf); err != nil {
6✔
166
                return err
×
167
        }
×
168

169
        for id, ctrlBlock := range *r {
666✔
170
                ctrlBlock := ctrlBlock
660✔
171

660✔
172
                if _, err := w.Write(id[:]); err != nil {
660✔
173
                        return err
×
174
                }
×
175

176
                if err := varBytesEncoder(w, &ctrlBlock, &buf); err != nil {
660✔
177
                        return err
×
178
                }
×
179
        }
180

181
        return nil
6✔
182
}
183

184
// Decode decodes the given reader into the target struct.
185
func (r *resolverCtrlBlocks) Decode(reader io.Reader) error {
3✔
186
        var buf [8]byte
3✔
187

3✔
188
        numBlocks, err := tlv.ReadVarInt(reader, &buf)
3✔
189
        if err != nil {
3✔
190
                return err
×
191
        }
×
192

193
        for i := uint64(0); i < numBlocks; i++ {
333✔
194
                var id resolverID
330✔
195
                if _, err := io.ReadFull(reader, id[:]); err != nil {
330✔
196
                        return err
×
197
                }
×
198

199
                var ctrlBlock []byte
330✔
200
                err := varBytesDecoder(reader, &ctrlBlock, &buf, 0)
330✔
201
                if err != nil {
330✔
202
                        return err
×
203
                }
×
204

205
                (*r)[id] = ctrlBlock
330✔
206
        }
207

208
        return nil
3✔
209
}
210

211
// resolverCtrlBlocksEncoder is a custom TLV encoder for the
212
// resolverCtrlBlocks.
213
func resolverCtrlBlocksEncoder(w io.Writer, val any, _ *[8]byte) error {
6✔
214
        if typ, ok := val.(*resolverCtrlBlocks); ok {
12✔
215
                return (*typ).Encode(w)
6✔
216
        }
6✔
217

218
        return tlv.NewTypeForEncodingErr(val, "resolverCtrlBlocks")
×
219
}
220

221
// rsolverCtrlBlocksDecoder is a custom TLV decoder for the resolverCtrlBlocks.
222
func resolverCtrlBlocksDecoder(r io.Reader, val any, _ *[8]byte,
223
        l uint64) error {
3✔
224

3✔
225
        if typ, ok := val.(*resolverCtrlBlocks); ok {
6✔
226
                blockReader := io.LimitReader(r, int64(l))
3✔
227

3✔
228
                resolverBlocks := newResolverCtrlBlocks()
3✔
229
                err := resolverBlocks.Decode(blockReader)
3✔
230
                if err != nil {
3✔
231
                        return err
×
232
                }
×
233

234
                *typ = resolverBlocks
3✔
235

3✔
236
                return nil
3✔
237
        }
238

239
        return tlv.NewTypeForDecodingErr(val, "resolverCtrlBlocks", l, l)
×
240
}
241

242
// ctrlBlocks is the set of control blocks we need to sweep all the output for
243
// a taproot/musig2 channel.
244
type ctrlBlocks struct {
245
        // CommitSweepCtrlBlock is the serialized control block needed to sweep
246
        // our commitment output.
247
        CommitSweepCtrlBlock []byte
248

249
        // RevokeSweepCtrlBlock is the serialized control block that's used to
250
        // sweep the reovked output of a breaching party.
251
        RevokeSweepCtrlBlock []byte
252

253
        // OutgoingHtlcCtrlBlocks is the set of serialized control blocks for
254
        // all outgoing HTLCs. This is the set of HTLCs that we offered to the
255
        // remote party. Depending on which commitment transaction was
256
        // broadcast, we'll either sweep here and be done, or also need to go
257
        // to the second level.
258
        OutgoingHtlcCtrlBlocks resolverCtrlBlocks
259

260
        // IncomingHtlcCtrlBlocks is the set of serialized control blocks for
261
        // all incoming HTLCs
262
        IncomingHtlcCtrlBlocks resolverCtrlBlocks
263

264
        // SecondLevelCtrlBlocks is the set of serialized control blocks for
265
        // need to sweep the second level HTLCs on our commitment transaction.
266
        SecondLevelCtrlBlocks resolverCtrlBlocks
267
}
268

269
// newCtrlBlocks returns a new instance of the ctrlBlocks struct.
UNCOV
270
func newCtrlBlocks() ctrlBlocks {
×
UNCOV
271
        return ctrlBlocks{
×
UNCOV
272
                OutgoingHtlcCtrlBlocks: newResolverCtrlBlocks(),
×
UNCOV
273
                IncomingHtlcCtrlBlocks: newResolverCtrlBlocks(),
×
UNCOV
274
                SecondLevelCtrlBlocks:  newResolverCtrlBlocks(),
×
UNCOV
275
        }
×
UNCOV
276
}
×
277

278
// varBytesEncoder is a custom TLV encoder for a variable length byte slice.
279
func varBytesEncoder(w io.Writer, val any, buf *[8]byte) error {
1,421✔
280
        if t, ok := val.(*[]byte); ok {
2,842✔
281
                if err := tlv.WriteVarInt(w, uint64(len(*t)), buf); err != nil {
1,421✔
282
                        return err
×
283
                }
×
284

285
                return tlv.EVarBytes(w, t, buf)
1,421✔
286
        }
287

288
        return tlv.NewTypeForEncodingErr(val, "[]byte")
×
289
}
290

291
// varBytesDecoder is a custom TLV decoder for a variable length byte slice.
292
func varBytesDecoder(r io.Reader, val any, buf *[8]byte, l uint64) error {
932✔
293
        if typ, ok := val.(*[]byte); ok {
1,864✔
294
                bytesLen, err := tlv.ReadVarInt(r, buf)
932✔
295
                if err != nil {
932✔
296
                        return err
×
297
                }
×
298

299
                var bytes []byte
932✔
300
                if err := tlv.DVarBytes(r, &bytes, buf, bytesLen); err != nil {
932✔
301
                        return err
×
302
                }
×
303

304
                *typ = bytes
932✔
305

932✔
306
                return nil
932✔
307
        }
308

309
        return tlv.NewTypeForDecodingErr(val, "[]byte", l, l)
×
310
}
311

312
// ctrlBlockEncoder is a custom TLV encoder for the ctrlBlocks struct.
313
func ctrlBlockEncoder(w io.Writer, val any, _ *[8]byte) error {
2✔
314
        if t, ok := val.(*ctrlBlocks); ok {
4✔
315
                return (*t).Encode(w)
2✔
316
        }
2✔
317

318
        return tlv.NewTypeForEncodingErr(val, "ctrlBlocks")
×
319
}
320

321
// ctrlBlockDecoder is a custom TLV decoder for the ctrlBlocks struct.
322
func ctrlBlockDecoder(r io.Reader, val any, _ *[8]byte, l uint64) error {
1✔
323
        if typ, ok := val.(*ctrlBlocks); ok {
2✔
324
                ctrlReader := io.LimitReader(r, int64(l))
1✔
325

1✔
326
                var ctrlBlocks ctrlBlocks
1✔
327
                err := ctrlBlocks.Decode(ctrlReader)
1✔
328
                if err != nil {
1✔
329
                        return err
×
330
                }
×
331

332
                *typ = ctrlBlocks
1✔
333

1✔
334
                return nil
1✔
335
        }
336

337
        return tlv.NewTypeForDecodingErr(val, "ctrlBlocks", l, l)
×
338
}
339

340
// EncodeRecords returns the set of TLV records that encode the control block
341
// for the commitment transaction.
342
func (c *ctrlBlocks) EncodeRecords() []tlv.Record {
2✔
343
        var records []tlv.Record
2✔
344

2✔
345
        if len(c.CommitSweepCtrlBlock) > 0 {
4✔
346
                records = append(records, tlv.MakePrimitiveRecord(
2✔
347
                        commitCtrlBlockType, &c.CommitSweepCtrlBlock,
2✔
348
                ))
2✔
349
        }
2✔
350

351
        if len(c.RevokeSweepCtrlBlock) > 0 {
4✔
352
                records = append(records, tlv.MakePrimitiveRecord(
2✔
353
                        revokeCtrlBlockType, &c.RevokeSweepCtrlBlock,
2✔
354
                ))
2✔
355
        }
2✔
356

357
        if c.OutgoingHtlcCtrlBlocks != nil {
4✔
358
                records = append(records, tlv.MakeDynamicRecord(
2✔
359
                        outgoingHtlcCtrlBlockType, &c.OutgoingHtlcCtrlBlocks,
2✔
360
                        c.OutgoingHtlcCtrlBlocks.recordSize,
2✔
361
                        resolverCtrlBlocksEncoder, resolverCtrlBlocksDecoder,
2✔
362
                ))
2✔
363
        }
2✔
364

365
        if c.IncomingHtlcCtrlBlocks != nil {
4✔
366
                records = append(records, tlv.MakeDynamicRecord(
2✔
367
                        incomingHtlcCtrlBlockType, &c.IncomingHtlcCtrlBlocks,
2✔
368
                        c.IncomingHtlcCtrlBlocks.recordSize,
2✔
369
                        resolverCtrlBlocksEncoder, resolverCtrlBlocksDecoder,
2✔
370
                ))
2✔
371
        }
2✔
372

373
        if c.SecondLevelCtrlBlocks != nil {
4✔
374
                records = append(records, tlv.MakeDynamicRecord(
2✔
375
                        secondLevelCtrlBlockType, &c.SecondLevelCtrlBlocks,
2✔
376
                        c.SecondLevelCtrlBlocks.recordSize,
2✔
377
                        resolverCtrlBlocksEncoder, resolverCtrlBlocksDecoder,
2✔
378
                ))
2✔
379
        }
2✔
380

381
        return records
2✔
382
}
383

384
// DecodeRecords returns the set of TLV records that decode the control block.
385
func (c *ctrlBlocks) DecodeRecords() []tlv.Record {
1✔
386
        return []tlv.Record{
1✔
387
                tlv.MakePrimitiveRecord(
1✔
388
                        commitCtrlBlockType, &c.CommitSweepCtrlBlock,
1✔
389
                ),
1✔
390
                tlv.MakePrimitiveRecord(
1✔
391
                        revokeCtrlBlockType, &c.RevokeSweepCtrlBlock,
1✔
392
                ),
1✔
393
                tlv.MakeDynamicRecord(
1✔
394
                        outgoingHtlcCtrlBlockType, &c.OutgoingHtlcCtrlBlocks,
1✔
395
                        c.OutgoingHtlcCtrlBlocks.recordSize,
1✔
396
                        resolverCtrlBlocksEncoder, resolverCtrlBlocksDecoder,
1✔
397
                ),
1✔
398
                tlv.MakeDynamicRecord(
1✔
399
                        incomingHtlcCtrlBlockType, &c.IncomingHtlcCtrlBlocks,
1✔
400
                        c.IncomingHtlcCtrlBlocks.recordSize,
1✔
401
                        resolverCtrlBlocksEncoder, resolverCtrlBlocksDecoder,
1✔
402
                ),
1✔
403
                tlv.MakeDynamicRecord(
1✔
404
                        secondLevelCtrlBlockType, &c.SecondLevelCtrlBlocks,
1✔
405
                        c.SecondLevelCtrlBlocks.recordSize,
1✔
406
                        resolverCtrlBlocksEncoder, resolverCtrlBlocksDecoder,
1✔
407
                ),
1✔
408
        }
1✔
409
}
1✔
410

411
// Record returns a TLV record that can be used to encode/decode the control
412
// blocks.  type from a given TLV stream.
413
func (c *ctrlBlocks) Record() tlv.Record {
2✔
414
        recordSize := func() uint64 {
3✔
415
                var (
1✔
416
                        b   bytes.Buffer
1✔
417
                        buf [8]byte
1✔
418
                )
1✔
419
                if err := ctrlBlockEncoder(&b, c, &buf); err != nil {
1✔
420
                        panic(err)
×
421
                }
422

423
                return uint64(len(b.Bytes()))
1✔
424
        }
425

426
        return tlv.MakeDynamicRecord(
2✔
427
                0, c, recordSize, ctrlBlockEncoder, ctrlBlockDecoder,
2✔
428
        )
2✔
429
}
430

431
// Encode encodes the set of control blocks.
432
func (c *ctrlBlocks) Encode(w io.Writer) error {
2✔
433
        stream, err := tlv.NewStream(c.EncodeRecords()...)
2✔
434
        if err != nil {
2✔
435
                return err
×
436
        }
×
437

438
        return stream.Encode(w)
2✔
439
}
440

441
// Decode decodes the set of control blocks.
442
func (c *ctrlBlocks) Decode(r io.Reader) error {
1✔
443
        stream, err := tlv.NewStream(c.DecodeRecords()...)
1✔
444
        if err != nil {
1✔
445
                return err
×
446
        }
×
447

448
        return stream.Decode(r)
1✔
449
}
450

451
// htlcTapTweakss maps an outpoint (the same format as the resolver ID) to the
452
// tap tweak needed to sweep a breached HTLC output. This is used for both the
453
// first and second level HTLC outputs.
454
type htlcTapTweaks map[resolverID][32]byte
455

456
// newHtlcTapTweaks returns a new instance of the htlcTapTweaks struct.
457
func newHtlcTapTweaks() htlcTapTweaks {
2✔
458
        return make(htlcTapTweaks)
2✔
459
}
2✔
460

461
// recordSize returns the size of the record in bytes.
462
func (h *htlcTapTweaks) recordSize() uint64 {
4✔
463
        // Each record will be serialized as: <num_tweaks> || <tweak>, where
4✔
464
        // <tweak> is serialized as: <resolver_key> || <tweak>.
4✔
465
        numTweaks := uint64(len(*h))
4✔
466
        baseSize := tlv.VarIntSize(numTweaks)
4✔
467

4✔
468
        recordSize := baseSize
4✔
469
        for range *h {
604✔
470
                // Each tweak is a fixed 32 bytes, so we just tally that an the
600✔
471
                // size of the resolver ID.
600✔
472
                recordSize += resolverIDLen
600✔
473
                recordSize += 32
600✔
474
        }
600✔
475

476
        return recordSize
4✔
477
}
478

479
// Encode encodes the tap tweaks into the target writer.
480
func (h *htlcTapTweaks) Encode(w io.Writer) error {
4✔
481
        numTweaks := uint64(len(*h))
4✔
482

4✔
483
        var buf [8]byte
4✔
484
        if err := tlv.WriteVarInt(w, numTweaks, &buf); err != nil {
4✔
485
                return err
×
486
        }
×
487

488
        for id, tweak := range *h {
604✔
489
                tweak := tweak
600✔
490

600✔
491
                if _, err := w.Write(id[:]); err != nil {
600✔
492
                        return err
×
493
                }
×
494

495
                if _, err := w.Write(tweak[:]); err != nil {
600✔
496
                        return err
×
497
                }
×
498
        }
499

500
        return nil
4✔
501
}
502

503
// htlcTapTweaksEncoder is a custom TLV encoder for the htlcTapTweaks struct.
504
func htlcTapTweaksEncoder(w io.Writer, val any, _ *[8]byte) error {
4✔
505
        if t, ok := val.(*htlcTapTweaks); ok {
8✔
506
                return (*t).Encode(w)
4✔
507
        }
4✔
508

509
        return tlv.NewTypeForEncodingErr(val, "htlcTapTweaks")
×
510
}
511

512
// htlcTapTweaksDecoder is a custom TLV decoder for the htlcTapTweaks struct.
513
func htlcTapTweaksDecoder(r io.Reader, val any, _ *[8]byte,
514
        l uint64) error {
2✔
515

2✔
516
        if typ, ok := val.(*htlcTapTweaks); ok {
4✔
517
                tweakReader := io.LimitReader(r, int64(l))
2✔
518

2✔
519
                htlcTweaks := newHtlcTapTweaks()
2✔
520
                err := htlcTweaks.Decode(tweakReader)
2✔
521
                if err != nil {
2✔
522
                        return err
×
523
                }
×
524

525
                *typ = htlcTweaks
2✔
526

2✔
527
                return nil
2✔
528
        }
529

530
        return tlv.NewTypeForDecodingErr(val, "htlcTapTweaks", l, l)
×
531
}
532

533
// Decode decodes the tap tweaks into the target struct.
534
func (h *htlcTapTweaks) Decode(reader io.Reader) error {
2✔
535
        var buf [8]byte
2✔
536

2✔
537
        numTweaks, err := tlv.ReadVarInt(reader, &buf)
2✔
538
        if err != nil {
2✔
539
                return err
×
540
        }
×
541

542
        for i := uint64(0); i < numTweaks; i++ {
302✔
543
                var id resolverID
300✔
544
                if _, err := io.ReadFull(reader, id[:]); err != nil {
300✔
545
                        return err
×
546
                }
×
547

548
                var tweak [32]byte
300✔
549
                if _, err := io.ReadFull(reader, tweak[:]); err != nil {
300✔
550
                        return err
×
551
                }
×
552

553
                (*h)[id] = tweak
300✔
554
        }
555

556
        return nil
2✔
557
}
558

559
// tapTweaks stores the set of taptweaks needed to perform keyspends for the
560
// commitment outputs.
561
type tapTweaks struct {
562
        // AnchorTweak is the tweak used to derive the key used to spend the
563
        // anchor output.
564
        AnchorTweak []byte
565

566
        // BreachedHtlcTweaks stores the set of tweaks needed to sweep the
567
        // revoked first level output of an HTLC.
568
        BreachedHtlcTweaks htlcTapTweaks
569

570
        // BreachedSecondLevelHtlcTweaks stores the set of tweaks needed to
571
        // sweep the revoked *second* level output of an HTLC.
572
        BreachedSecondLevelHltcTweaks htlcTapTweaks
573
}
574

575
// newTapTweaks returns a new tapTweaks struct.
UNCOV
576
func newTapTweaks() tapTweaks {
×
UNCOV
577
        return tapTweaks{
×
UNCOV
578
                BreachedHtlcTweaks:            make(htlcTapTweaks),
×
UNCOV
579
                BreachedSecondLevelHltcTweaks: make(htlcTapTweaks),
×
UNCOV
580
        }
×
UNCOV
581
}
×
582

583
// tapTweaksEncoder is a custom TLV encoder for the tapTweaks struct.
584
func tapTweaksEncoder(w io.Writer, val any, _ *[8]byte) error {
2✔
585
        if t, ok := val.(*tapTweaks); ok {
4✔
586
                return (*t).Encode(w)
2✔
587
        }
2✔
588

589
        return tlv.NewTypeForEncodingErr(val, "tapTweaks")
×
590
}
591

592
// tapTweaksDecoder is a custom TLV decoder for the tapTweaks struct.
593
func tapTweaksDecoder(r io.Reader, val any, _ *[8]byte, l uint64) error {
1✔
594
        if typ, ok := val.(*tapTweaks); ok {
2✔
595
                tweakReader := io.LimitReader(r, int64(l))
1✔
596

1✔
597
                var tapTweaks tapTweaks
1✔
598
                err := tapTweaks.Decode(tweakReader)
1✔
599
                if err != nil {
1✔
600
                        return err
×
601
                }
×
602

603
                *typ = tapTweaks
1✔
604

1✔
605
                return nil
1✔
606
        }
607

608
        return tlv.NewTypeForDecodingErr(val, "tapTweaks", l, l)
×
609
}
610

611
// EncodeRecords returns the set of TLV records that encode the tweaks.
612
func (t *tapTweaks) EncodeRecords() []tlv.Record {
2✔
613
        var records []tlv.Record
2✔
614

2✔
615
        if len(t.AnchorTweak) > 0 {
4✔
616
                records = append(records, tlv.MakePrimitiveRecord(
2✔
617
                        anchorTapTweakType, &t.AnchorTweak,
2✔
618
                ))
2✔
619
        }
2✔
620

621
        if len(t.BreachedHtlcTweaks) > 0 {
4✔
622
                records = append(records, tlv.MakeDynamicRecord(
2✔
623
                        htlcTweakCtrlBlockType, &t.BreachedHtlcTweaks,
2✔
624
                        t.BreachedHtlcTweaks.recordSize,
2✔
625
                        htlcTapTweaksEncoder, htlcTapTweaksDecoder,
2✔
626
                ))
2✔
627
        }
2✔
628

629
        if len(t.BreachedSecondLevelHltcTweaks) > 0 {
4✔
630
                records = append(records, tlv.MakeDynamicRecord(
2✔
631
                        secondLevelHtlcTweakCtrlBlockType,
2✔
632
                        &t.BreachedSecondLevelHltcTweaks,
2✔
633
                        t.BreachedSecondLevelHltcTweaks.recordSize,
2✔
634
                        htlcTapTweaksEncoder, htlcTapTweaksDecoder,
2✔
635
                ))
2✔
636
        }
2✔
637

638
        return records
2✔
639
}
640

641
// DecodeRecords returns the set of TLV records that decode the tweaks.
642
func (t *tapTweaks) DecodeRecords() []tlv.Record {
1✔
643
        return []tlv.Record{
1✔
644
                tlv.MakePrimitiveRecord(anchorTapTweakType, &t.AnchorTweak),
1✔
645
                tlv.MakeDynamicRecord(
1✔
646
                        htlcTweakCtrlBlockType, &t.BreachedHtlcTweaks,
1✔
647
                        t.BreachedHtlcTweaks.recordSize,
1✔
648
                        htlcTapTweaksEncoder, htlcTapTweaksDecoder,
1✔
649
                ),
1✔
650
                tlv.MakeDynamicRecord(
1✔
651
                        secondLevelHtlcTweakCtrlBlockType,
1✔
652
                        &t.BreachedSecondLevelHltcTweaks,
1✔
653
                        t.BreachedSecondLevelHltcTweaks.recordSize,
1✔
654
                        htlcTapTweaksEncoder, htlcTapTweaksDecoder,
1✔
655
                ),
1✔
656
        }
1✔
657
}
1✔
658

659
// Record returns a TLV record that can be used to encode/decode the tap
660
// tweaks.
661
func (t *tapTweaks) Record() tlv.Record {
2✔
662
        recordSize := func() uint64 {
3✔
663
                var (
1✔
664
                        b   bytes.Buffer
1✔
665
                        buf [8]byte
1✔
666
                )
1✔
667
                if err := tapTweaksEncoder(&b, t, &buf); err != nil {
1✔
668
                        panic(err)
×
669
                }
670

671
                return uint64(len(b.Bytes()))
1✔
672
        }
673

674
        return tlv.MakeDynamicRecord(
2✔
675
                0, t, recordSize, tapTweaksEncoder, tapTweaksDecoder,
2✔
676
        )
2✔
677
}
678

679
// Encode encodes the set of tap tweaks.
680
func (t *tapTweaks) Encode(w io.Writer) error {
2✔
681
        stream, err := tlv.NewStream(t.EncodeRecords()...)
2✔
682
        if err != nil {
2✔
683
                return err
×
684
        }
×
685

686
        return stream.Encode(w)
2✔
687
}
688

689
// Decode decodes the set of tap tweaks.
690
func (t *tapTweaks) Decode(r io.Reader) error {
1✔
691
        stream, err := tlv.NewStream(t.DecodeRecords()...)
1✔
692
        if err != nil {
1✔
693
                return err
×
694
        }
×
695

696
        return stream.Decode(r)
1✔
697
}
698

699
// htlcAuxBlobs is a map of resolver IDs to their corresponding HTLC blobs.
700
// This is used to store the resolution blobs for HTLCs that are not yet
701
// resolved.
702
type htlcAuxBlobs map[resolverID]tlv.Blob
703

704
// newAuxHtlcBlobs returns a new instance of the htlcAuxBlobs struct.
705
func newAuxHtlcBlobs() htlcAuxBlobs {
102✔
706
        return make(htlcAuxBlobs)
102✔
707
}
102✔
708

709
// Encode encodes the set of HTLC blobs into the target writer.
710
func (h *htlcAuxBlobs) Encode(w io.Writer) error {
103✔
711
        var buf [8]byte
103✔
712

103✔
713
        numBlobs := uint64(len(*h))
103✔
714
        if err := tlv.WriteVarInt(w, numBlobs, &buf); err != nil {
103✔
715
                return err
×
716
        }
×
717

718
        for id, blob := range *h {
864✔
719
                if _, err := w.Write(id[:]); err != nil {
761✔
720
                        return err
×
721
                }
×
722

723
                if err := varBytesEncoder(w, &blob, &buf); err != nil {
761✔
724
                        return err
×
725
                }
×
726
        }
727

728
        return nil
103✔
729
}
730

731
// Decode decodes the set of HTLC blobs from the target reader.
732
func (h *htlcAuxBlobs) Decode(r io.Reader) error {
102✔
733
        var buf [8]byte
102✔
734

102✔
735
        numBlobs, err := tlv.ReadVarInt(r, &buf)
102✔
736
        if err != nil {
102✔
737
                return err
×
738
        }
×
739

740
        for i := uint64(0); i < numBlobs; i++ {
704✔
741
                var id resolverID
602✔
742
                if _, err := io.ReadFull(r, id[:]); err != nil {
602✔
743
                        return err
×
744
                }
×
745

746
                var blob tlv.Blob
602✔
747
                if err := varBytesDecoder(r, &blob, &buf, 0); err != nil {
602✔
748
                        return err
×
749
                }
×
750

751
                (*h)[id] = blob
602✔
752
        }
753

754
        return nil
102✔
755
}
756

757
// eHtlcAuxBlobsEncoder is a custom TLV encoder for the htlcAuxBlobs struct.
758
func htlcAuxBlobsEncoder(w io.Writer, val any, _ *[8]byte) error {
2✔
759
        if t, ok := val.(*htlcAuxBlobs); ok {
4✔
760
                return (*t).Encode(w)
2✔
761
        }
2✔
762

763
        return tlv.NewTypeForEncodingErr(val, "htlcAuxBlobs")
×
764
}
765

766
// dHtlcAuxBlobsDecoder is a custom TLV decoder for the htlcAuxBlobs struct.
767
func htlcAuxBlobsDecoder(r io.Reader, val any, _ *[8]byte,
768
        l uint64) error {
1✔
769

1✔
770
        if typ, ok := val.(*htlcAuxBlobs); ok {
2✔
771
                blobReader := io.LimitReader(r, int64(l))
1✔
772

1✔
773
                htlcBlobs := newAuxHtlcBlobs()
1✔
774
                err := htlcBlobs.Decode(blobReader)
1✔
775
                if err != nil {
1✔
776
                        return err
×
777
                }
×
778

779
                *typ = htlcBlobs
1✔
780

1✔
781
                return nil
1✔
782
        }
783

784
        return tlv.NewTypeForDecodingErr(val, "htlcAuxBlobs", l, l)
×
785
}
786

787
// Record returns a tlv.Record for the htlcAuxBlobs struct.
788
func (h *htlcAuxBlobs) Record() tlv.Record {
2✔
789
        recordSize := func() uint64 {
3✔
790
                var (
1✔
791
                        b   bytes.Buffer
1✔
792
                        buf [8]byte
1✔
793
                )
1✔
794
                if err := htlcAuxBlobsEncoder(&b, h, &buf); err != nil {
1✔
795
                        panic(err)
×
796
                }
797

798
                return uint64(len(b.Bytes()))
1✔
799
        }
800

801
        return tlv.MakeDynamicRecord(
2✔
802
                0, h, recordSize, htlcAuxBlobsEncoder, htlcAuxBlobsDecoder,
2✔
803
        )
2✔
804
}
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