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

lightningnetwork / lnd / 13211764208

08 Feb 2025 03:08AM UTC coverage: 49.288% (-9.5%) from 58.815%
13211764208

Pull #9489

github

calvinrzachman
itest: verify switchrpc server enforces send then track

We prevent the rpc server from allowing onion dispatches for
attempt IDs which have already been tracked by rpc clients.

This helps protect the client from leaking a duplicate onion
attempt. NOTE: This is not the only method for solving this
issue! The issue could be addressed via careful client side
programming which accounts for the uncertainty and async
nature of dispatching onions to a remote process via RPC.
This would require some lnd ChannelRouter changes for how
we intend to use these RPCs though.
Pull Request #9489: multi: add BuildOnion, SendOnion, and TrackOnion RPCs

474 of 990 new or added lines in 11 files covered. (47.88%)

27321 existing lines in 435 files now uncovered.

101192 of 205306 relevant lines covered (49.29%)

1.54 hits per line

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

65.47
/watchtower/blob/justice_kit_packet.go
1
package blob
2

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

11
        "github.com/btcsuite/btcd/btcec/v2"
12
        "github.com/btcsuite/btcd/btcec/v2/schnorr"
13
        "github.com/btcsuite/btcd/chaincfg/chainhash"
14
        "github.com/lightningnetwork/lnd/lnwire"
15
        "golang.org/x/crypto/chacha20poly1305"
16
)
17

18
const (
19
        // NonceSize is the length of a chacha20poly1305 nonce, 24 bytes.
20
        NonceSize = chacha20poly1305.NonceSizeX
21

22
        // KeySize is the length of a chacha20poly1305 key, 32 bytes.
23
        KeySize = chacha20poly1305.KeySize
24

25
        // CiphertextExpansion is the number of bytes padded to a plaintext
26
        // encrypted with chacha20poly1305, which comes from a 16-byte MAC.
27
        CiphertextExpansion = 16
28

29
        // V0PlaintextSize is the plaintext size of a version 0 encoded blob.
30
        //    sweep address length:            1 byte
31
        //    padded sweep address:           42 bytes
32
        //    revocation pubkey:              33 bytes
33
        //    local delay pubkey:             33 bytes
34
        //    csv delay:                       4 bytes
35
        //    commit to-local revocation sig: 64 bytes
36
        //    commit to-remote pubkey:        33 bytes, maybe blank
37
        //    commit to-remote sig:           64 bytes, maybe blank
38
        V0PlaintextSize = 274
39

40
        // V1PlaintextSize is the plaintext size of a version 1 encoded blob.
41
        //    sweep address length:            1 byte
42
        //    padded sweep address:           42 bytes
43
        //    revocation pubkey:              32 bytes
44
        //    local delay pubkey:             32 bytes
45
        //    commit to-local revocation sig: 64 bytes
46
        //    hash of to-local delay script:  32 bytes
47
        //    commit to-remote pubkey:        33 bytes, maybe blank
48
        //    commit to-remote sig:           64 bytes, maybe blank
49
        V1PlaintextSize = 300
50

51
        // MaxSweepAddrSize defines the maximum sweep address size that can be
52
        // encoded in a blob.
53
        MaxSweepAddrSize = 42
54
)
55

56
var (
57
        // byteOrder specifies a big-endian encoding of all integer values.
58
        byteOrder = binary.BigEndian
59

60
        // ErrUnknownBlobType signals that we don't understand the requested
61
        // blob encoding scheme.
62
        ErrUnknownBlobType = errors.New("unknown blob type")
63

64
        // ErrCiphertextTooSmall is a decryption error signaling that the
65
        // ciphertext is smaller than the ciphertext expansion factor.
66
        ErrCiphertextTooSmall = errors.New(
67
                "ciphertext is too small for chacha20poly1305",
68
        )
69

70
        // ErrNoCommitToRemoteOutput is returned when trying to retrieve the
71
        // commit to-remote output from the blob, though none exists.
72
        ErrNoCommitToRemoteOutput = errors.New(
73
                "cannot obtain commit to-remote p2wkh output script from blob",
74
        )
75

76
        // ErrSweepAddressToLong is returned when trying to encode or decode a
77
        // sweep address with length greater than the maximum length of 42
78
        // bytes, which supports p2wkh and p2sh addresses.
79
        ErrSweepAddressToLong = fmt.Errorf(
80
                "sweep address must be less than or equal to %d bytes long",
81
                MaxSweepAddrSize,
82
        )
83
)
84

85
// Size returns the size of the encoded-and-encrypted blob in bytes.
86
//
87
//        nonce:                24 bytes
88
//        enciphered plaintext:  n bytes
89
//        MAC:                  16 bytes
90
func Size(kit JusticeKit) int {
3✔
91
        return NonceSize + kit.PlainTextSize() + CiphertextExpansion
3✔
92
}
3✔
93

94
// schnorrPubKey is a 32-byte serialized x-only public key.
95
type schnorrPubKey [32]byte
96

97
// toBlobSchnorrPubKey serializes the given public key into a schnorrPubKey that
98
// can be set as a field on a JusticeKit.
99
func toBlobSchnorrPubKey(pubKey *btcec.PublicKey) schnorrPubKey {
3✔
100
        var blobPubKey schnorrPubKey
3✔
101
        copy(blobPubKey[:], schnorr.SerializePubKey(pubKey))
3✔
102
        return blobPubKey
3✔
103
}
3✔
104

105
// pubKey is a 33-byte, serialized compressed public key.
106
type pubKey [33]byte
107

108
// toBlobPubKey serializes the given public key into a pubKey that can be set
109
// as a field on a JusticeKit.
110
func toBlobPubKey(pk *btcec.PublicKey) pubKey {
3✔
111
        var blobPubKey pubKey
3✔
112
        copy(blobPubKey[:], pk.SerializeCompressed())
3✔
113
        return blobPubKey
3✔
114
}
3✔
115

116
// justiceKitPacketV0 is lé Blob of Justice. The JusticeKit contains information
117
// required to construct a justice transaction, that sweeps a remote party's
118
// revoked commitment transaction. It supports encryption and decryption using
119
// chacha20poly1305, allowing the client to encrypt the contents of the blob,
120
// and for a watchtower to later decrypt if action must be taken.
121
type justiceKitPacketV0 struct {
122
        // sweepAddress is the witness program of the output where the client's
123
        // fund will be deposited. This value is included in the blobs, as
124
        // opposed to the session info, such that the sweep addresses can't be
125
        // correlated across sessions and/or towers.
126
        //
127
        // NOTE: This is chosen to be the length of a maximally sized witness
128
        // program.
129
        sweepAddress []byte
130

131
        // revocationPubKey is the compressed pubkey that guards the revocation
132
        // clause of the remote party's to-local output.
133
        revocationPubKey pubKey
134

135
        // localDelayPubKey is the compressed pubkey in the to-local script of
136
        // the remote party, which guards the path where the remote party
137
        // claims their commitment output.
138
        localDelayPubKey pubKey
139

140
        // csvDelay is the relative timelock in the remote party's to-local
141
        // output, which the remote party must wait out before sweeping their
142
        // commitment output.
143
        csvDelay uint32
144

145
        // commitToLocalSig is a signature under RevocationPubKey using
146
        // SIGHASH_ALL.
147
        commitToLocalSig lnwire.Sig
148

149
        // commitToRemotePubKey is the public key in the to-remote output of the
150
        // revoked commitment transaction.
151
        //
152
        // NOTE: This value is only used if it contains a valid compressed
153
        // public key.
154
        commitToRemotePubKey pubKey
155

156
        // commitToRemoteSig is a signature under CommitToRemotePubKey using
157
        // SIGHASH_ALL.
158
        //
159
        // NOTE: This value is only used if CommitToRemotePubKey contains a
160
        // valid compressed public key.
161
        commitToRemoteSig lnwire.Sig
162
}
163

164
// Encrypt encodes the blob of justice using encoding version, and then
165
// creates a ciphertext using chacha20poly1305 under the chosen (nonce, key)
166
// pair.
167
//
168
// NOTE: It is the caller's responsibility to ensure that this method is only
169
// called once for a given (nonce, key) pair.
170
func Encrypt(kit JusticeKit, key BreachKey) ([]byte, error) {
3✔
171
        // Encode the plaintext using the provided version, to obtain the
3✔
172
        // plaintext bytes.
3✔
173
        var ptxtBuf bytes.Buffer
3✔
174
        err := kit.encode(&ptxtBuf)
3✔
175
        if err != nil {
3✔
UNCOV
176
                return nil, err
×
UNCOV
177
        }
×
178

179
        // Create a new chacha20poly1305 cipher, using a 32-byte key.
180
        cipher, err := chacha20poly1305.NewX(key[:])
3✔
181
        if err != nil {
3✔
182
                return nil, err
×
183
        }
×
184

185
        // Allocate the ciphertext, which will contain the nonce, encrypted
186
        // plaintext and MAC.
187
        plaintext := ptxtBuf.Bytes()
3✔
188
        ciphertext := make([]byte, Size(kit))
3✔
189

3✔
190
        // Generate a random  24-byte nonce in the ciphertext's prefix.
3✔
191
        nonce := ciphertext[:NonceSize]
3✔
192
        if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
3✔
193
                return nil, err
×
194
        }
×
195

196
        // Finally, encrypt the plaintext using the given nonce, storing the
197
        // result in the ciphertext buffer.
198
        cipher.Seal(ciphertext[NonceSize:NonceSize], nonce, plaintext, nil)
3✔
199

3✔
200
        return ciphertext, nil
3✔
201
}
202

203
// Decrypt unenciphers a blob of justice by decrypting the ciphertext using
204
// chacha20poly1305 with the chosen (nonce, key) pair. The internal plaintext is
205
// then deserialized using the given encoding version.
206
func Decrypt(key BreachKey, ciphertext []byte,
207
        blobType Type) (JusticeKit, error) {
3✔
208

3✔
209
        // Fail if the blob's overall length is less than required for the nonce
3✔
210
        // and expansion factor.
3✔
211
        if len(ciphertext) < NonceSize+CiphertextExpansion {
3✔
212
                return nil, ErrCiphertextTooSmall
×
213
        }
×
214

215
        // Create a new chacha20poly1305 cipher, using a 32-byte key.
216
        cipher, err := chacha20poly1305.NewX(key[:])
3✔
217
        if err != nil {
3✔
218
                return nil, err
×
219
        }
×
220

221
        // Allocate the final buffer that will contain the blob's plaintext
222
        // bytes, which is computed by subtracting the ciphertext expansion
223
        // factor from the blob's length.
224
        plaintext := make([]byte, len(ciphertext)-CiphertextExpansion)
3✔
225

3✔
226
        // Decrypt the ciphertext, placing the resulting plaintext in our
3✔
227
        // plaintext buffer.
3✔
228
        nonce := ciphertext[:NonceSize]
3✔
229
        _, err = cipher.Open(plaintext[:0], nonce, ciphertext[NonceSize:], nil)
3✔
230
        if err != nil {
3✔
231
                return nil, err
×
232
        }
×
233

234
        commitment, err := blobType.CommitmentType(nil)
3✔
235
        if err != nil {
3✔
UNCOV
236
                return nil, err
×
UNCOV
237
        }
×
238

239
        kit, err := commitment.EmptyJusticeKit()
3✔
240
        if err != nil {
3✔
241
                return nil, err
×
242
        }
×
243

244
        // If decryption succeeded, we will then decode the plaintext bytes
245
        // using the specified blob version.
246
        err = kit.decode(bytes.NewReader(plaintext))
3✔
247
        if err != nil {
3✔
248
                return nil, err
×
249
        }
×
250

251
        return kit, nil
3✔
252
}
253

254
// encode encodes the JusticeKit using the version 0 encoding scheme to the
255
// provided io.Writer. The encoding supports sweeping of the commit to-local
256
// output, and  optionally the  commit to-remote output. The encoding produces a
257
// constant-size plaintext size of 274 bytes.
258
//
259
// blob version 0 plaintext encoding:
260
//
261
//        sweep address length:            1 byte
262
//        padded sweep address:           42 bytes
263
//        revocation pubkey:              33 bytes
264
//        local delay pubkey:             33 bytes
265
//        csv delay:                       4 bytes
266
//        commit to-local revocation sig: 64 bytes
267
//        commit to-remote pubkey:        33 bytes, maybe blank
268
//        commit to-remote sig:           64 bytes, maybe blank
269
func (b *justiceKitPacketV0) encode(w io.Writer) error {
3✔
270
        // Assert the sweep address length is sane.
3✔
271
        if len(b.sweepAddress) > MaxSweepAddrSize {
3✔
UNCOV
272
                return ErrSweepAddressToLong
×
UNCOV
273
        }
×
274

275
        // Write the actual length of the sweep address as a single byte.
276
        err := binary.Write(w, byteOrder, uint8(len(b.sweepAddress)))
3✔
277
        if err != nil {
3✔
278
                return err
×
279
        }
×
280

281
        // Pad the sweep address to our maximum length of 42 bytes.
282
        var sweepAddressBuf [MaxSweepAddrSize]byte
3✔
283
        copy(sweepAddressBuf[:], b.sweepAddress)
3✔
284

3✔
285
        // Write padded 42-byte sweep address.
3✔
286
        _, err = w.Write(sweepAddressBuf[:])
3✔
287
        if err != nil {
3✔
288
                return err
×
289
        }
×
290

291
        // Write 33-byte revocation public key.
292
        _, err = w.Write(b.revocationPubKey[:])
3✔
293
        if err != nil {
3✔
294
                return err
×
295
        }
×
296

297
        // Write 33-byte local delay public key.
298
        _, err = w.Write(b.localDelayPubKey[:])
3✔
299
        if err != nil {
3✔
300
                return err
×
301
        }
×
302

303
        // Write 4-byte CSV delay.
304
        err = binary.Write(w, byteOrder, b.csvDelay)
3✔
305
        if err != nil {
3✔
306
                return err
×
307
        }
×
308

309
        // Write 64-byte revocation signature for commit to-local output.
310
        _, err = w.Write(b.commitToLocalSig.RawBytes())
3✔
311
        if err != nil {
3✔
312
                return err
×
313
        }
×
314

315
        // Write 33-byte commit to-remote public key, which may be blank.
316
        _, err = w.Write(b.commitToRemotePubKey[:])
3✔
317
        if err != nil {
3✔
318
                return err
×
319
        }
×
320

321
        // Write 64-byte commit to-remote signature, which may be blank.
322
        _, err = w.Write(b.commitToRemoteSig.RawBytes())
3✔
323

3✔
324
        return err
3✔
325
}
326

327
// decode reconstructs a JusticeKit from the io.Reader, using version 0
328
// encoding scheme. This will parse a constant size input stream of 274 bytes to
329
// recover information for the commit to-local output, and possibly the commit
330
// to-remote output.
331
//
332
// blob version 0 plaintext encoding:
333
//
334
//        sweep address length:            1 byte
335
//        padded sweep address:           42 bytes
336
//        revocation pubkey:              33 bytes
337
//        local delay pubkey:             33 bytes
338
//        csv delay:                       4 bytes
339
//        commit to-local revocation sig: 64 bytes
340
//        commit to-remote pubkey:        33 bytes, maybe blank
341
//        commit to-remote sig:           64 bytes, maybe blank
342
func (b *justiceKitPacketV0) decode(r io.Reader) error {
3✔
343
        // Read the sweep address length as a single byte.
3✔
344
        var sweepAddrLen uint8
3✔
345
        err := binary.Read(r, byteOrder, &sweepAddrLen)
3✔
346
        if err != nil {
3✔
347
                return err
×
348
        }
×
349

350
        // Assert the sweep address length is sane.
351
        if sweepAddrLen > MaxSweepAddrSize {
3✔
352
                return ErrSweepAddressToLong
×
353
        }
×
354

355
        // Read padded 42-byte sweep address.
356
        var sweepAddressBuf [MaxSweepAddrSize]byte
3✔
357
        _, err = io.ReadFull(r, sweepAddressBuf[:])
3✔
358
        if err != nil {
3✔
359
                return err
×
360
        }
×
361

362
        // Parse sweep address from padded buffer.
363
        b.sweepAddress = make([]byte, sweepAddrLen)
3✔
364
        copy(b.sweepAddress, sweepAddressBuf[:])
3✔
365

3✔
366
        // Read 33-byte revocation public key.
3✔
367
        _, err = io.ReadFull(r, b.revocationPubKey[:])
3✔
368
        if err != nil {
3✔
369
                return err
×
370
        }
×
371

372
        // Read 33-byte local delay public key.
373
        _, err = io.ReadFull(r, b.localDelayPubKey[:])
3✔
374
        if err != nil {
3✔
375
                return err
×
376
        }
×
377

378
        // Read 4-byte CSV delay.
379
        err = binary.Read(r, byteOrder, &b.csvDelay)
3✔
380
        if err != nil {
3✔
381
                return err
×
382
        }
×
383

384
        // Read 64-byte revocation signature for commit to-local output.
385
        var localSig [64]byte
3✔
386
        _, err = io.ReadFull(r, localSig[:])
3✔
387
        if err != nil {
3✔
388
                return err
×
389
        }
×
390

391
        b.commitToLocalSig, err = lnwire.NewSigFromWireECDSA(localSig[:])
3✔
392
        if err != nil {
3✔
393
                return err
×
394
        }
×
395

396
        var (
3✔
397
                commitToRemotePubkey pubKey
3✔
398
                commitToRemoteSig    [64]byte
3✔
399
        )
3✔
400

3✔
401
        // Read 33-byte commit to-remote public key, which may be discarded.
3✔
402
        _, err = io.ReadFull(r, commitToRemotePubkey[:])
3✔
403
        if err != nil {
3✔
404
                return err
×
405
        }
×
406

407
        // Read 64-byte commit to-remote signature, which may be discarded.
408
        _, err = io.ReadFull(r, commitToRemoteSig[:])
3✔
409
        if err != nil {
3✔
410
                return err
×
411
        }
×
412

413
        // Only populate the commit to-remote fields in the decoded blob if a
414
        // valid compressed public key was read from the reader.
415
        if btcec.IsCompressedPubKey(commitToRemotePubkey[:]) {
6✔
416
                b.commitToRemotePubKey = commitToRemotePubkey
3✔
417
                b.commitToRemoteSig, err = lnwire.NewSigFromWireECDSA(
3✔
418
                        commitToRemoteSig[:],
3✔
419
                )
3✔
420
                if err != nil {
3✔
421
                        return err
×
422
                }
×
423
        }
424

425
        return nil
3✔
426
}
427

428
// justiceKitPacketV1 is the Blob of Justice for taproot channels.
429
type justiceKitPacketV1 struct {
430
        // sweepAddress is the witness program of the output where the client's
431
        // fund will be deposited. This value is included in the blobs, as
432
        // opposed to the session info, such that the sweep addresses can't be
433
        // correlated across sessions and/or towers.
434
        //
435
        // NOTE: This is chosen to be the length of a maximally sized witness
436
        // program.
437
        sweepAddress []byte
438

439
        // revocationPubKey is the x-only pubkey that guards the revocation
440
        // clause of the remote party's to-local output.
441
        revocationPubKey schnorrPubKey
442

443
        // localDelayPubKey is the x-only pubkey in the to-local script of
444
        // the remote party, which guards the path where the remote party
445
        // claims their commitment output.
446
        localDelayPubKey schnorrPubKey
447

448
        // delayScriptHash is the hash of the to_local delay script that is used
449
        // in the TapTree.
450
        delayScriptHash [chainhash.HashSize]byte
451

452
        // commitToLocalSig is a signature under revocationPubKey using
453
        // SIGHASH_DEFAULT.
454
        commitToLocalSig lnwire.Sig
455

456
        // commitToRemotePubKey is the public key in the to-remote output of the
457
        // revoked commitment transaction. This uses a 33-byte compressed pubkey
458
        // encoding unlike the other public keys because it will not always be
459
        // present and so this gives us an easy way to check if it is present or
460
        // not.
461
        //
462
        // NOTE: This value is only used if it contains a valid compressed
463
        // public key.
464
        commitToRemotePubKey pubKey
465

466
        // commitToRemoteSig is a signature under commitToRemotePubKey using
467
        // SIGHASH_DEFAULT.
468
        //
469
        // NOTE: This value is only used if commitToRemotePubKey contains a
470
        // valid compressed public key.
471
        commitToRemoteSig lnwire.Sig
472
}
473

474
// encode encodes the justiceKitPacketV1 to the provided io.Writer. The encoding
475
// supports sweeping of the commit to-local output, and optionally the commit
476
// to-remote output. The encoding produces a constant-size plaintext size of
477
// 300 bytes.
478
//
479
// blob version 1 plaintext encoding:
480
//
481
//        sweep address length:            1 byte
482
//        padded sweep address:           42 bytes
483
//        revocation pubkey:              32 bytes
484
//        local delay pubkey:             32 bytes
485
//        commit to-local revocation sig: 64 bytes
486
//        hash of to-local delay script:  32 bytes
487
//        commit to-remote pubkey:        33 bytes, maybe blank
488
//        commit to-remote sig:           64 bytes, maybe blank
489
func (t *justiceKitPacketV1) encode(w io.Writer) error {
3✔
490
        // Assert the sweep address length is sane.
3✔
491
        if len(t.sweepAddress) > MaxSweepAddrSize {
3✔
492
                return ErrSweepAddressToLong
×
493
        }
×
494

495
        // Write the actual length of the sweep address as a single byte.
496
        err := binary.Write(w, byteOrder, uint8(len(t.sweepAddress)))
3✔
497
        if err != nil {
3✔
498
                return err
×
499
        }
×
500

501
        // Pad the sweep address to our maximum length of 42 bytes.
502
        var sweepAddressBuf [MaxSweepAddrSize]byte
3✔
503
        copy(sweepAddressBuf[:], t.sweepAddress)
3✔
504

3✔
505
        // Write padded 42-byte sweep address.
3✔
506
        _, err = w.Write(sweepAddressBuf[:])
3✔
507
        if err != nil {
3✔
508
                return err
×
509
        }
×
510

511
        // Write 32-byte revocation public key.
512
        _, err = w.Write(t.revocationPubKey[:])
3✔
513
        if err != nil {
3✔
514
                return err
×
515
        }
×
516

517
        // Write 32-byte local delay public key.
518
        _, err = w.Write(t.localDelayPubKey[:])
3✔
519
        if err != nil {
3✔
520
                return err
×
521
        }
×
522

523
        // Write 64-byte revocation signature for commit to-local output.
524
        _, err = w.Write(t.commitToLocalSig.RawBytes())
3✔
525
        if err != nil {
3✔
526
                return err
×
527
        }
×
528

529
        // Write 32-byte hash of the to-local delay script.
530
        _, err = w.Write(t.delayScriptHash[:])
3✔
531
        if err != nil {
3✔
532
                return err
×
533
        }
×
534

535
        // Write 33-byte commit to-remote public key, which may be blank.
536
        _, err = w.Write(t.commitToRemotePubKey[:])
3✔
537
        if err != nil {
3✔
538
                return err
×
539
        }
×
540

541
        // Write 64-byte commit to-remote signature, which may be blank.
542
        _, err = w.Write(t.commitToRemoteSig.RawBytes())
3✔
543

3✔
544
        return err
3✔
545
}
546

547
// decode reconstructs a justiceKitPacketV1 from the io.Reader, using version 1
548
// encoding scheme. This will parse a constant size input stream of 300 bytes to
549
// recover information for the commit to-local output, and possibly the commit
550
// to-remote output.
551
//
552
// blob version 1 plaintext encoding:
553
//
554
//        sweep address length:            1 byte
555
//        padded sweep address:           42 bytes
556
//        revocation pubkey:              32 bytes
557
//        local delay pubkey:             32 bytes
558
//        commit to-local revocation sig: 64 bytes
559
//        hash of to-local delay script:  32 bytes
560
//        commit to-remote pubkey:        33 bytes, maybe blank
561
//        commit to-remote sig:           64 bytes, maybe blank
562
func (t *justiceKitPacketV1) decode(r io.Reader) error {
3✔
563
        // Read the sweep address length as a single byte.
3✔
564
        var sweepAddrLen uint8
3✔
565
        err := binary.Read(r, byteOrder, &sweepAddrLen)
3✔
566
        if err != nil {
3✔
567
                return err
×
568
        }
×
569
        // Assert the sweep address length is sane.
570
        if sweepAddrLen > MaxSweepAddrSize {
3✔
571
                return ErrSweepAddressToLong
×
572
        }
×
573
        // Read padded 42-byte sweep address.
574
        var sweepAddressBuf [MaxSweepAddrSize]byte
3✔
575
        _, err = io.ReadFull(r, sweepAddressBuf[:])
3✔
576
        if err != nil {
3✔
577
                return err
×
578
        }
×
579

580
        // Parse sweep address from padded buffer.
581
        t.sweepAddress = make([]byte, sweepAddrLen)
3✔
582
        copy(t.sweepAddress, sweepAddressBuf[:])
3✔
583

3✔
584
        // Read 32-byte revocation public key.
3✔
585
        _, err = io.ReadFull(r, t.revocationPubKey[:])
3✔
586
        if err != nil {
3✔
587
                return err
×
588
        }
×
589

590
        // Read 32-byte local delay public key.
591
        _, err = io.ReadFull(r, t.localDelayPubKey[:])
3✔
592
        if err != nil {
3✔
593
                return err
×
594
        }
×
595

596
        // Read 64-byte revocation signature for commit to-local output.
597
        var localSig [64]byte
3✔
598
        _, err = io.ReadFull(r, localSig[:])
3✔
599
        if err != nil {
3✔
600
                return err
×
601
        }
×
602

603
        // Read 32-byte to-local delay script hash.
604
        _, err = io.ReadFull(r, t.delayScriptHash[:])
3✔
605
        if err != nil {
3✔
606
                return err
×
607
        }
×
608

609
        t.commitToLocalSig, err = lnwire.NewSigFromSchnorrRawSignature(
3✔
610
                localSig[:],
3✔
611
        )
3✔
612
        if err != nil {
3✔
613
                return err
×
614
        }
×
615
        var (
3✔
616
                commitToRemotePubkey pubKey
3✔
617
                commitToRemoteSig    [64]byte
3✔
618
        )
3✔
619
        // Read 33-byte commit to-remote public key, which may be discarded.
3✔
620
        _, err = io.ReadFull(r, commitToRemotePubkey[:])
3✔
621
        if err != nil {
3✔
622
                return err
×
623
        }
×
624
        // Read 64-byte commit to-remote signature, which may be discarded.
625
        _, err = io.ReadFull(r, commitToRemoteSig[:])
3✔
626
        if err != nil {
3✔
627
                return err
×
628
        }
×
629

630
        // Only populate the commit to-remote fields in the decoded blob if a
631
        // valid compressed public key was read from the reader.
632
        if !btcec.IsCompressedPubKey(commitToRemotePubkey[:]) {
3✔
UNCOV
633
                return nil
×
UNCOV
634
        }
×
635

636
        t.commitToRemotePubKey = commitToRemotePubkey
3✔
637
        t.commitToRemoteSig, err = lnwire.NewSigFromSchnorrRawSignature(
3✔
638
                commitToRemoteSig[:],
3✔
639
        )
3✔
640
        if err != nil {
3✔
641
                return err
×
642
        }
×
643

644
        return nil
3✔
645
}
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