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

lightningnetwork / lnd / 13536249039

26 Feb 2025 03:42AM UTC coverage: 57.462% (-1.4%) from 58.835%
13536249039

Pull #8453

github

Roasbeef
peer: update chooseDeliveryScript to gen script if needed

In this commit, we update `chooseDeliveryScript` to generate a new
script if needed. This allows us to fold in a few other lines that
always followed this function into this expanded function.

The tests have been updated accordingly.
Pull Request #8453: [4/4] - multi: integrate new rbf coop close FSM into the existing peer flow

275 of 1318 new or added lines in 22 files covered. (20.86%)

19521 existing lines in 257 files now uncovered.

103858 of 180741 relevant lines covered (57.46%)

24750.23 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 {
818✔
152
                recordSize += resolverIDLen
812✔
153
                recordSize += tlv.VarIntSize(uint64(len(ctrlBlock)))
812✔
154
                recordSize += uint64(len(ctrlBlock))
812✔
155
        }
812✔
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 {
818✔
170
                ctrlBlock := ctrlBlock
812✔
171

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

176
                if err := varBytesEncoder(w, &ctrlBlock, &buf); err != nil {
812✔
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++ {
409✔
194
                var id resolverID
406✔
195
                if _, err := io.ReadFull(reader, id[:]); err != nil {
406✔
196
                        return err
×
197
                }
×
198

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

205
                (*r)[id] = ctrlBlock
406✔
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,805✔
280
        if t, ok := val.(*[]byte); ok {
3,610✔
281
                if err := tlv.WriteVarInt(w, uint64(len(*t)), buf); err != nil {
1,805✔
282
                        return err
×
283
                }
×
284

285
                return tlv.EVarBytes(w, t, buf)
1,805✔
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 {
1,160✔
293
        if typ, ok := val.(*[]byte); ok {
2,320✔
294
                bytesLen, err := tlv.ReadVarInt(r, buf)
1,160✔
295
                if err != nil {
1,160✔
296
                        return err
×
297
                }
×
298

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

304
                *typ = bytes
1,160✔
305

1,160✔
306
                return nil
1,160✔
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 {
536✔
470
                // Each tweak is a fixed 32 bytes, so we just tally that an the
532✔
471
                // size of the resolver ID.
532✔
472
                recordSize += resolverIDLen
532✔
473
                recordSize += 32
532✔
474
        }
532✔
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 {
536✔
489
                tweak := tweak
532✔
490

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

495
                if _, err := w.Write(tweak[:]); err != nil {
532✔
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++ {
268✔
543
                var id resolverID
266✔
544
                if _, err := io.ReadFull(reader, id[:]); err != nil {
266✔
545
                        return err
×
546
                }
×
547

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

553
                (*h)[id] = tweak
266✔
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 {
1,096✔
719
                if _, err := w.Write(id[:]); err != nil {
993✔
720
                        return err
×
721
                }
×
722

723
                if err := varBytesEncoder(w, &blob, &buf); err != nil {
993✔
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++ {
856✔
741
                var id resolverID
754✔
742
                if _, err := io.ReadFull(r, id[:]); err != nil {
754✔
743
                        return err
×
744
                }
×
745

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

751
                (*h)[id] = blob
754✔
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