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

lightningnetwork / lnd / 15561477203

10 Jun 2025 01:54PM UTC coverage: 58.351% (-10.1%) from 68.487%
15561477203

Pull #9356

github

web-flow
Merge 6440b25db into c6d6d4c0b
Pull Request #9356: lnrpc: add incoming/outgoing channel ids filter to forwarding history request

33 of 36 new or added lines in 2 files covered. (91.67%)

28366 existing lines in 455 files now uncovered.

97715 of 167461 relevant lines covered (58.35%)

1.81 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