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

lightningnetwork / lnd / 17832014233

18 Sep 2025 02:30PM UTC coverage: 57.196% (-9.4%) from 66.637%
17832014233

Pull #10133

github

web-flow
Merge 3e12b2767 into b34fc964b
Pull Request #10133: Add `XFindBaseLocalChanAlias` RPC

20 of 34 new or added lines in 4 files covered. (58.82%)

28528 existing lines in 459 files now uncovered.

99371 of 173739 relevant lines covered (57.2%)

1.78 hits per line

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

44.01
/lnwire/lnwire.go
1
package lnwire
2

3
import (
4
        "bytes"
5
        "encoding/binary"
6
        "errors"
7
        "fmt"
8
        "image/color"
9
        "io"
10
        "math"
11
        "net"
12

13
        "github.com/btcsuite/btcd/btcec/v2"
14
        "github.com/btcsuite/btcd/btcutil"
15
        "github.com/btcsuite/btcd/chaincfg/chainhash"
16
        "github.com/btcsuite/btcd/wire"
17
        "github.com/lightningnetwork/lnd/tor"
18
)
19

20
const (
21
        // MaxSliceLength is the maximum allowed length for any opaque byte
22
        // slices in the wire protocol.
23
        MaxSliceLength = 65535
24

25
        // MaxMsgBody is the largest payload any message is allowed to provide.
26
        // This is two less than the MaxSliceLength as each message has a 2
27
        // byte type that precedes the message body.
28
        MaxMsgBody = 65533
29
)
30

31
const (
32
        // tcp4AddrLen is the length of an IPv4 address
33
        // (4 bytes IP + 2 bytes port).
34
        tcp4AddrLen = 6
35

36
        // tcp6AddrLen is the length of an IPv6 address
37
        // (16 bytes IP + 2 bytes port).
38
        tcp6AddrLen = 18
39

40
        // v2OnionAddrLen is the length of a version 2 Tor onion service
41
        // address.
42
        v2OnionAddrLen = 12
43

44
        // v3OnionAddrLen is the length of a version 3 Tor onion service address
45
        // (35 bytes decoded onion + 2 bytes port).
46
        v3OnionAddrLen = 37
47

48
        // dnsAddrOverhead is the fixed overhead for a DNS address: 1 byte for
49
        // the hostname length and 2 bytes for the port.
50
        dnsAddrOverhead = 3
51
)
52

53
// PkScript is simple type definition which represents a raw serialized public
54
// key script.
55
type PkScript []byte
56

57
// addressType specifies the network protocol and version that should be used
58
// when connecting to a node at a particular address.
59
type addressType uint8
60

61
const (
62
        // noAddr denotes a blank address. An address of this type indicates
63
        // that a node doesn't have any advertised addresses.
64
        noAddr addressType = 0
65

66
        // tcp4Addr denotes an IPv4 TCP address.
67
        tcp4Addr addressType = 1
68

69
        // tcp6Addr denotes an IPv6 TCP address.
70
        tcp6Addr addressType = 2
71

72
        // v2OnionAddr denotes a version 2 Tor onion service address.
73
        v2OnionAddr addressType = 3
74

75
        // v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
76
        v3OnionAddr addressType = 4
77

78
        // dnsAddr denotes a DNS address.
79
        dnsAddr addressType = 5
80
)
81

82
// WriteElement is a one-stop shop to write the big endian representation of
83
// any element which is to be serialized for the wire protocol.
84
//
85
// TODO(yy): rm this method once we finish dereferencing it from other
86
// packages.
87
func WriteElement(w *bytes.Buffer, element interface{}) error {
3✔
88
        switch e := element.(type) {
3✔
89
        case NodeAlias:
×
90
                if _, err := w.Write(e[:]); err != nil {
×
91
                        return err
×
92
                }
×
93

94
        case QueryEncoding:
×
95
                var b [1]byte
×
96
                b[0] = uint8(e)
×
97
                if _, err := w.Write(b[:]); err != nil {
×
98
                        return err
×
99
                }
×
100

101
        case uint8:
3✔
102
                var b [1]byte
3✔
103
                b[0] = e
3✔
104
                if _, err := w.Write(b[:]); err != nil {
3✔
105
                        return err
×
106
                }
×
107

108
        case FundingFlag:
×
109
                var b [1]byte
×
110
                b[0] = uint8(e)
×
111
                if _, err := w.Write(b[:]); err != nil {
×
112
                        return err
×
113
                }
×
114

115
        case uint16:
3✔
116
                var b [2]byte
3✔
117
                binary.BigEndian.PutUint16(b[:], e)
3✔
118
                if _, err := w.Write(b[:]); err != nil {
3✔
119
                        return err
×
120
                }
×
121

122
        case ChanUpdateMsgFlags:
×
123
                var b [1]byte
×
124
                b[0] = uint8(e)
×
125
                if _, err := w.Write(b[:]); err != nil {
×
126
                        return err
×
127
                }
×
128

129
        case ChanUpdateChanFlags:
×
130
                var b [1]byte
×
131
                b[0] = uint8(e)
×
132
                if _, err := w.Write(b[:]); err != nil {
×
133
                        return err
×
134
                }
×
135

136
        case MilliSatoshi:
×
137
                var b [8]byte
×
138
                binary.BigEndian.PutUint64(b[:], uint64(e))
×
139
                if _, err := w.Write(b[:]); err != nil {
×
140
                        return err
×
141
                }
×
142

143
        case btcutil.Amount:
3✔
144
                var b [8]byte
3✔
145
                binary.BigEndian.PutUint64(b[:], uint64(e))
3✔
146
                if _, err := w.Write(b[:]); err != nil {
3✔
147
                        return err
×
148
                }
×
149

150
        case uint32:
3✔
151
                var b [4]byte
3✔
152
                binary.BigEndian.PutUint32(b[:], e)
3✔
153
                if _, err := w.Write(b[:]); err != nil {
3✔
154
                        return err
×
155
                }
×
156

157
        case uint64:
3✔
158
                var b [8]byte
3✔
159
                binary.BigEndian.PutUint64(b[:], e)
3✔
160
                if _, err := w.Write(b[:]); err != nil {
3✔
161
                        return err
×
162
                }
×
163

164
        case *btcec.PublicKey:
3✔
165
                if e == nil {
3✔
166
                        return fmt.Errorf("cannot write nil pubkey")
×
167
                }
×
168

169
                var b [33]byte
3✔
170
                serializedPubkey := e.SerializeCompressed()
3✔
171
                copy(b[:], serializedPubkey)
3✔
172
                if _, err := w.Write(b[:]); err != nil {
3✔
173
                        return err
×
174
                }
×
175

176
        case []Sig:
×
177
                var b [2]byte
×
178
                numSigs := uint16(len(e))
×
179
                binary.BigEndian.PutUint16(b[:], numSigs)
×
180
                if _, err := w.Write(b[:]); err != nil {
×
181
                        return err
×
182
                }
×
183

184
                for _, sig := range e {
×
185
                        if err := WriteElement(w, sig); err != nil {
×
186
                                return err
×
187
                        }
×
188
                }
189

190
        case Sig:
×
191
                // Write buffer
×
192
                if _, err := w.Write(e.bytes[:]); err != nil {
×
193
                        return err
×
194
                }
×
195

UNCOV
196
        case PartialSig:
×
UNCOV
197
                if err := e.Encode(w); err != nil {
×
198
                        return err
×
199
                }
×
200

201
        case PingPayload:
×
202
                var l [2]byte
×
203
                binary.BigEndian.PutUint16(l[:], uint16(len(e)))
×
204
                if _, err := w.Write(l[:]); err != nil {
×
205
                        return err
×
206
                }
×
207

208
                if _, err := w.Write(e[:]); err != nil {
×
209
                        return err
×
210
                }
×
211

212
        case PongPayload:
×
213
                var l [2]byte
×
214
                binary.BigEndian.PutUint16(l[:], uint16(len(e)))
×
215
                if _, err := w.Write(l[:]); err != nil {
×
216
                        return err
×
217
                }
×
218

219
                if _, err := w.Write(e[:]); err != nil {
×
220
                        return err
×
221
                }
×
222

223
        case WarningData:
×
224
                var l [2]byte
×
225
                binary.BigEndian.PutUint16(l[:], uint16(len(e)))
×
226
                if _, err := w.Write(l[:]); err != nil {
×
227
                        return err
×
228
                }
×
229

230
                if _, err := w.Write(e[:]); err != nil {
×
231
                        return err
×
232
                }
×
233

234
        case ErrorData:
×
235
                var l [2]byte
×
236
                binary.BigEndian.PutUint16(l[:], uint16(len(e)))
×
237
                if _, err := w.Write(l[:]); err != nil {
×
238
                        return err
×
239
                }
×
240

241
                if _, err := w.Write(e[:]); err != nil {
×
242
                        return err
×
243
                }
×
244

245
        case OpaqueReason:
×
246
                var l [2]byte
×
247
                binary.BigEndian.PutUint16(l[:], uint16(len(e)))
×
248
                if _, err := w.Write(l[:]); err != nil {
×
249
                        return err
×
250
                }
×
251

252
                if _, err := w.Write(e[:]); err != nil {
×
253
                        return err
×
254
                }
×
255

256
        case [33]byte:
×
257
                if _, err := w.Write(e[:]); err != nil {
×
258
                        return err
×
259
                }
×
260

261
        case []byte:
3✔
262
                if _, err := w.Write(e[:]); err != nil {
3✔
263
                        return err
×
264
                }
×
265

266
        case PkScript:
×
267
                // The largest script we'll accept is a p2wsh which is exactly
×
268
                // 34 bytes long.
×
269
                scriptLength := len(e)
×
270
                if scriptLength > 34 {
×
271
                        return fmt.Errorf("'PkScript' too long")
×
272
                }
×
273

274
                if err := wire.WriteVarBytes(w, 0, e); err != nil {
×
275
                        return err
×
276
                }
×
277

278
        case *RawFeatureVector:
×
279
                if e == nil {
×
280
                        return fmt.Errorf("cannot write nil feature vector")
×
281
                }
×
282

283
                if err := e.Encode(w); err != nil {
×
284
                        return err
×
285
                }
×
286

287
        case wire.OutPoint:
3✔
288
                var h [32]byte
3✔
289
                copy(h[:], e.Hash[:])
3✔
290
                if _, err := w.Write(h[:]); err != nil {
3✔
291
                        return err
×
292
                }
×
293

294
                if e.Index > math.MaxUint16 {
3✔
295
                        return fmt.Errorf("index for outpoint (%v) is "+
×
296
                                "greater than max index of %v", e.Index,
×
297
                                math.MaxUint16)
×
298
                }
×
299

300
                var idx [2]byte
3✔
301
                binary.BigEndian.PutUint16(idx[:], uint16(e.Index))
3✔
302
                if _, err := w.Write(idx[:]); err != nil {
3✔
303
                        return err
×
304
                }
×
305

306
        case ChannelID:
×
307
                if _, err := w.Write(e[:]); err != nil {
×
308
                        return err
×
309
                }
×
310

311
        case FailCode:
×
312
                if err := WriteElement(w, uint16(e)); err != nil {
×
313
                        return err
×
314
                }
×
315

316
        case ShortChannelID:
3✔
317
                // Check that field fit in 3 bytes and write the blockHeight
3✔
318
                if e.BlockHeight > ((1 << 24) - 1) {
3✔
319
                        return errors.New("block height should fit in 3 bytes")
×
320
                }
×
321

322
                var blockHeight [4]byte
3✔
323
                binary.BigEndian.PutUint32(blockHeight[:], e.BlockHeight)
3✔
324

3✔
325
                if _, err := w.Write(blockHeight[1:]); err != nil {
3✔
326
                        return err
×
327
                }
×
328

329
                // Check that field fit in 3 bytes and write the txIndex
330
                if e.TxIndex > ((1 << 24) - 1) {
3✔
331
                        return errors.New("tx index should fit in 3 bytes")
×
332
                }
×
333

334
                var txIndex [4]byte
3✔
335
                binary.BigEndian.PutUint32(txIndex[:], e.TxIndex)
3✔
336
                if _, err := w.Write(txIndex[1:]); err != nil {
3✔
337
                        return err
×
338
                }
×
339

340
                // Write the txPosition
341
                var txPosition [2]byte
3✔
342
                binary.BigEndian.PutUint16(txPosition[:], e.TxPosition)
3✔
343
                if _, err := w.Write(txPosition[:]); err != nil {
3✔
344
                        return err
×
345
                }
×
346

347
        case *net.TCPAddr:
3✔
348
                if err := WriteTCPAddr(w, e); err != nil {
3✔
349
                        return err
×
350
                }
×
351

352
        case *tor.OnionAddr:
3✔
353
                if err := WriteOnionAddr(w, e); err != nil {
3✔
354
                        return err
×
355
                }
×
356

UNCOV
357
        case *DNSAddress:
×
UNCOV
358
                if err := WriteDNSAddress(w, e); err != nil {
×
359
                        return err
×
360
                }
×
361

UNCOV
362
        case *OpaqueAddrs:
×
UNCOV
363
                if err := WriteOpaqueAddrs(w, e); err != nil {
×
364
                        return err
×
365
                }
×
366

367
        case []net.Addr:
3✔
368
                // First, we'll encode all the addresses into an intermediate
3✔
369
                // buffer. We need to do this in order to compute the total
3✔
370
                // length of the addresses.
3✔
371
                var addrBuf bytes.Buffer
3✔
372
                for _, address := range e {
6✔
373
                        if err := WriteElement(&addrBuf, address); err != nil {
3✔
374
                                return err
×
375
                        }
×
376
                }
377

378
                // With the addresses fully encoded, we can now write out the
379
                // number of bytes needed to encode them.
380
                addrLen := addrBuf.Len()
3✔
381
                if err := WriteElement(w, uint16(addrLen)); err != nil {
3✔
382
                        return err
×
383
                }
×
384

385
                // Finally, we'll write out the raw addresses themselves, but
386
                // only if we have any bytes to write.
387
                if addrLen > 0 {
6✔
388
                        if _, err := w.Write(addrBuf.Bytes()); err != nil {
3✔
389
                                return err
×
390
                        }
×
391
                }
392

393
        case color.RGBA:
×
394
                if err := WriteElements(w, e.R, e.G, e.B); err != nil {
×
395
                        return err
×
396
                }
×
397

398
        case DeliveryAddress:
×
399
                var length [2]byte
×
400
                binary.BigEndian.PutUint16(length[:], uint16(len(e)))
×
401
                if _, err := w.Write(length[:]); err != nil {
×
402
                        return err
×
403
                }
×
404
                if _, err := w.Write(e[:]); err != nil {
×
405
                        return err
×
406
                }
×
407

408
        case bool:
3✔
409
                var b [1]byte
3✔
410
                if e {
6✔
411
                        b[0] = 1
3✔
412
                }
3✔
413
                if _, err := w.Write(b[:]); err != nil {
3✔
414
                        return err
×
415
                }
×
416

417
        case ExtraOpaqueData:
×
418
                return e.Encode(w)
×
419

420
        default:
×
421
                return fmt.Errorf("unknown type in WriteElement: %T", e)
×
422
        }
423

424
        return nil
3✔
425
}
426

427
// WriteElements is writes each element in the elements slice to the passed
428
// buffer using WriteElement.
429
//
430
// TODO(yy): rm this method once we finish dereferencing it from other
431
// packages.
432
func WriteElements(buf *bytes.Buffer, elements ...interface{}) error {
3✔
433
        for _, element := range elements {
6✔
434
                err := WriteElement(buf, element)
3✔
435
                if err != nil {
3✔
436
                        return err
×
437
                }
×
438
        }
439
        return nil
3✔
440
}
441

442
// ReadElement is a one-stop utility function to deserialize any datastructure
443
// encoded using the serialization format of lnwire.
444
func ReadElement(r io.Reader, element interface{}) error {
3✔
445
        var err error
3✔
446
        switch e := element.(type) {
3✔
447
        case *bool:
3✔
448
                var b [1]byte
3✔
449
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
450
                        return err
×
UNCOV
451
                }
×
452

453
                if b[0] == 1 {
6✔
454
                        *e = true
3✔
455
                }
3✔
456

457
        case *NodeAlias:
3✔
458
                var a [32]byte
3✔
459
                if _, err := io.ReadFull(r, a[:]); err != nil {
3✔
UNCOV
460
                        return err
×
UNCOV
461
                }
×
462

463
                alias, err := NewNodeAlias(string(a[:]))
3✔
464
                if err != nil {
3✔
UNCOV
465
                        return err
×
UNCOV
466
                }
×
467
                *e = alias
3✔
468

469
        case *QueryEncoding:
×
470
                var b [1]uint8
×
471
                if _, err := r.Read(b[:]); err != nil {
×
472
                        return err
×
473
                }
×
474
                *e = QueryEncoding(b[0])
×
475

476
        case *uint8:
3✔
477
                var b [1]uint8
3✔
478
                if _, err := r.Read(b[:]); err != nil {
3✔
UNCOV
479
                        return err
×
UNCOV
480
                }
×
481
                *e = b[0]
3✔
482

483
        case *FundingFlag:
3✔
484
                var b [1]uint8
3✔
485
                if _, err := r.Read(b[:]); err != nil {
3✔
UNCOV
486
                        return err
×
UNCOV
487
                }
×
488
                *e = FundingFlag(b[0])
3✔
489

490
        case *uint16:
3✔
491
                var b [2]byte
3✔
492
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
493
                        return err
×
UNCOV
494
                }
×
495
                *e = binary.BigEndian.Uint16(b[:])
3✔
496

497
        case *ChanUpdateMsgFlags:
3✔
498
                var b [1]uint8
3✔
499
                if _, err := r.Read(b[:]); err != nil {
3✔
UNCOV
500
                        return err
×
UNCOV
501
                }
×
502
                *e = ChanUpdateMsgFlags(b[0])
3✔
503

504
        case *ChanUpdateChanFlags:
3✔
505
                var b [1]uint8
3✔
506
                if _, err := r.Read(b[:]); err != nil {
3✔
UNCOV
507
                        return err
×
UNCOV
508
                }
×
509
                *e = ChanUpdateChanFlags(b[0])
3✔
510

511
        case *uint32:
3✔
512
                var b [4]byte
3✔
513
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
514
                        return err
×
UNCOV
515
                }
×
516
                *e = binary.BigEndian.Uint32(b[:])
3✔
517

518
        case *uint64:
3✔
519
                var b [8]byte
3✔
520
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
521
                        return err
×
UNCOV
522
                }
×
523
                *e = binary.BigEndian.Uint64(b[:])
3✔
524

525
        case *MilliSatoshi:
3✔
526
                var b [8]byte
3✔
527
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
528
                        return err
×
UNCOV
529
                }
×
530
                *e = MilliSatoshi(int64(binary.BigEndian.Uint64(b[:])))
3✔
531

532
        case *btcutil.Amount:
3✔
533
                var b [8]byte
3✔
534
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
535
                        return err
×
UNCOV
536
                }
×
537
                *e = btcutil.Amount(int64(binary.BigEndian.Uint64(b[:])))
3✔
538

539
        case **btcec.PublicKey:
3✔
540
                var b [btcec.PubKeyBytesLenCompressed]byte
3✔
541
                if _, err = io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
542
                        return err
×
UNCOV
543
                }
×
544

545
                pubKey, err := btcec.ParsePubKey(b[:])
3✔
546
                if err != nil {
3✔
UNCOV
547
                        return err
×
UNCOV
548
                }
×
549
                *e = pubKey
3✔
550

UNCOV
551
        case *RawFeatureVector:
×
UNCOV
552
                f := NewRawFeatureVector()
×
UNCOV
553
                err = f.Decode(r)
×
UNCOV
554
                if err != nil {
×
UNCOV
555
                        return err
×
UNCOV
556
                }
×
UNCOV
557
                *e = *f
×
558

559
        case **RawFeatureVector:
3✔
560
                f := NewRawFeatureVector()
3✔
561
                err = f.Decode(r)
3✔
562
                if err != nil {
3✔
UNCOV
563
                        return err
×
UNCOV
564
                }
×
565
                *e = f
3✔
566

567
        case *[]Sig:
3✔
568
                var l [2]byte
3✔
569
                if _, err := io.ReadFull(r, l[:]); err != nil {
3✔
UNCOV
570
                        return err
×
UNCOV
571
                }
×
572
                numSigs := binary.BigEndian.Uint16(l[:])
3✔
573

3✔
574
                var sigs []Sig
3✔
575
                if numSigs > 0 {
6✔
576
                        sigs = make([]Sig, numSigs)
3✔
577
                        for i := 0; i < int(numSigs); i++ {
6✔
578
                                if err := ReadElement(r, &sigs[i]); err != nil {
3✔
UNCOV
579
                                        return err
×
UNCOV
580
                                }
×
581
                        }
582
                }
583
                *e = sigs
3✔
584

585
        case *Sig:
3✔
586
                if _, err := io.ReadFull(r, e.bytes[:]); err != nil {
3✔
UNCOV
587
                        return err
×
UNCOV
588
                }
×
589

590
        case *OpaqueReason:
3✔
591
                var l [2]byte
3✔
592
                if _, err := io.ReadFull(r, l[:]); err != nil {
3✔
UNCOV
593
                        return err
×
UNCOV
594
                }
×
595
                reasonLen := binary.BigEndian.Uint16(l[:])
3✔
596

3✔
597
                *e = OpaqueReason(make([]byte, reasonLen))
3✔
598
                if _, err := io.ReadFull(r, *e); err != nil {
3✔
UNCOV
599
                        return err
×
UNCOV
600
                }
×
601

UNCOV
602
        case *WarningData:
×
UNCOV
603
                var l [2]byte
×
UNCOV
604
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
UNCOV
605
                        return err
×
UNCOV
606
                }
×
UNCOV
607
                errorLen := binary.BigEndian.Uint16(l[:])
×
UNCOV
608

×
UNCOV
609
                *e = WarningData(make([]byte, errorLen))
×
UNCOV
610
                if _, err := io.ReadFull(r, *e); err != nil {
×
UNCOV
611
                        return err
×
UNCOV
612
                }
×
613

614
        case *ErrorData:
3✔
615
                var l [2]byte
3✔
616
                if _, err := io.ReadFull(r, l[:]); err != nil {
3✔
UNCOV
617
                        return err
×
UNCOV
618
                }
×
619
                errorLen := binary.BigEndian.Uint16(l[:])
3✔
620

3✔
621
                *e = ErrorData(make([]byte, errorLen))
3✔
622
                if _, err := io.ReadFull(r, *e); err != nil {
3✔
UNCOV
623
                        return err
×
UNCOV
624
                }
×
625

UNCOV
626
        case *PingPayload:
×
UNCOV
627
                var l [2]byte
×
UNCOV
628
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
UNCOV
629
                        return err
×
UNCOV
630
                }
×
UNCOV
631
                pingLen := binary.BigEndian.Uint16(l[:])
×
UNCOV
632

×
UNCOV
633
                *e = PingPayload(make([]byte, pingLen))
×
UNCOV
634
                if _, err := io.ReadFull(r, *e); err != nil {
×
UNCOV
635
                        return err
×
UNCOV
636
                }
×
637

UNCOV
638
        case *PongPayload:
×
UNCOV
639
                var l [2]byte
×
UNCOV
640
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
UNCOV
641
                        return err
×
UNCOV
642
                }
×
UNCOV
643
                pongLen := binary.BigEndian.Uint16(l[:])
×
UNCOV
644

×
UNCOV
645
                *e = PongPayload(make([]byte, pongLen))
×
UNCOV
646
                if _, err := io.ReadFull(r, *e); err != nil {
×
UNCOV
647
                        return err
×
UNCOV
648
                }
×
649

650
        case *[33]byte:
3✔
651
                if _, err := io.ReadFull(r, e[:]); err != nil {
3✔
UNCOV
652
                        return err
×
UNCOV
653
                }
×
654

655
        case []byte:
3✔
656
                if _, err := io.ReadFull(r, e); err != nil {
3✔
UNCOV
657
                        return err
×
UNCOV
658
                }
×
659

660
        case *PkScript:
×
661
                pkScript, err := wire.ReadVarBytes(r, 0, 34, "pkscript")
×
662
                if err != nil {
×
663
                        return err
×
664
                }
×
665
                *e = pkScript
×
666

667
        case *wire.OutPoint:
3✔
668
                var h [32]byte
3✔
669
                if _, err = io.ReadFull(r, h[:]); err != nil {
3✔
UNCOV
670
                        return err
×
UNCOV
671
                }
×
672
                hash, err := chainhash.NewHash(h[:])
3✔
673
                if err != nil {
3✔
674
                        return err
×
675
                }
×
676

677
                var idxBytes [2]byte
3✔
678
                _, err = io.ReadFull(r, idxBytes[:])
3✔
679
                if err != nil {
3✔
UNCOV
680
                        return err
×
UNCOV
681
                }
×
682
                index := binary.BigEndian.Uint16(idxBytes[:])
3✔
683

3✔
684
                *e = wire.OutPoint{
3✔
685
                        Hash:  *hash,
3✔
686
                        Index: uint32(index),
3✔
687
                }
3✔
688

689
        case *FailCode:
3✔
690
                if err := ReadElement(r, (*uint16)(e)); err != nil {
3✔
UNCOV
691
                        return err
×
UNCOV
692
                }
×
693

694
        case *ChannelID:
3✔
695
                if _, err := io.ReadFull(r, e[:]); err != nil {
3✔
UNCOV
696
                        return err
×
UNCOV
697
                }
×
698

699
        case *ShortChannelID:
3✔
700
                var blockHeight [4]byte
3✔
701
                if _, err = io.ReadFull(r, blockHeight[1:]); err != nil {
3✔
UNCOV
702
                        return err
×
UNCOV
703
                }
×
704

705
                var txIndex [4]byte
3✔
706
                if _, err = io.ReadFull(r, txIndex[1:]); err != nil {
3✔
UNCOV
707
                        return err
×
UNCOV
708
                }
×
709

710
                var txPosition [2]byte
3✔
711
                if _, err = io.ReadFull(r, txPosition[:]); err != nil {
3✔
UNCOV
712
                        return err
×
UNCOV
713
                }
×
714

715
                *e = ShortChannelID{
3✔
716
                        BlockHeight: binary.BigEndian.Uint32(blockHeight[:]),
3✔
717
                        TxIndex:     binary.BigEndian.Uint32(txIndex[:]),
3✔
718
                        TxPosition:  binary.BigEndian.Uint16(txPosition[:]),
3✔
719
                }
3✔
720

721
        case *[]net.Addr:
3✔
722
                // First, we'll read the number of total bytes that have been
3✔
723
                // used to encode the set of addresses.
3✔
724
                var numAddrsBytes [2]byte
3✔
725
                if _, err = io.ReadFull(r, numAddrsBytes[:]); err != nil {
3✔
UNCOV
726
                        return err
×
UNCOV
727
                }
×
728
                addrsLen := binary.BigEndian.Uint16(numAddrsBytes[:])
3✔
729

3✔
730
                // With the number of addresses, read, we'll now pull in the
3✔
731
                // buffer of the encoded addresses into memory.
3✔
732
                addrs := make([]byte, addrsLen)
3✔
733
                if _, err := io.ReadFull(r, addrs[:]); err != nil {
3✔
UNCOV
734
                        return err
×
UNCOV
735
                }
×
736
                addrBuf := bytes.NewReader(addrs)
3✔
737

3✔
738
                // Finally, we'll parse the remaining address payload in
3✔
739
                // series, using the first byte to denote how to decode the
3✔
740
                // address itself.
3✔
741
                var (
3✔
742
                        addresses     []net.Addr
3✔
743
                        addrBytesRead uint16
3✔
744
                )
3✔
745

3✔
746
                for addrBytesRead < addrsLen {
6✔
747
                        bytesRead, address, err := ReadAddress(
3✔
748
                                addrBuf, addrsLen-addrBytesRead,
3✔
749
                        )
3✔
750
                        if err != nil {
3✔
UNCOV
751
                                return fmt.Errorf("unable to read address: %w",
×
UNCOV
752
                                        err)
×
UNCOV
753
                        }
×
754
                        addrBytesRead += bytesRead
3✔
755

3✔
756
                        // If we encounter a noAddr descriptor, then we'll move
3✔
757
                        // on to the next address.
3✔
758
                        if address == nil {
3✔
UNCOV
759
                                continue
×
760
                        }
761

762
                        addresses = append(addresses, address)
3✔
763
                }
764

765
                *e = addresses
3✔
766

767
        case *color.RGBA:
3✔
768
                err := ReadElements(r,
3✔
769
                        &e.R,
3✔
770
                        &e.G,
3✔
771
                        &e.B,
3✔
772
                )
3✔
773
                if err != nil {
3✔
UNCOV
774
                        return err
×
UNCOV
775
                }
×
776

777
        case *DeliveryAddress:
3✔
778
                var addrLen [2]byte
3✔
779
                if _, err = io.ReadFull(r, addrLen[:]); err != nil {
3✔
UNCOV
780
                        return err
×
UNCOV
781
                }
×
782
                length := binary.BigEndian.Uint16(addrLen[:])
3✔
783

3✔
784
                var addrBytes [deliveryAddressMaxSize]byte
3✔
785

3✔
786
                if length > deliveryAddressMaxSize {
3✔
UNCOV
787
                        return fmt.Errorf(
×
UNCOV
788
                                "cannot read %d bytes into addrBytes", length,
×
UNCOV
789
                        )
×
UNCOV
790
                }
×
791
                if _, err = io.ReadFull(r, addrBytes[:length]); err != nil {
3✔
UNCOV
792
                        return err
×
UNCOV
793
                }
×
794
                *e = addrBytes[:length]
3✔
795

UNCOV
796
        case *PartialSig:
×
UNCOV
797
                var sig PartialSig
×
UNCOV
798
                if err = sig.Decode(r); err != nil {
×
UNCOV
799
                        return err
×
UNCOV
800
                }
×
UNCOV
801
                *e = sig
×
802

803
        case *ExtraOpaqueData:
3✔
804
                return e.Decode(r)
3✔
805

806
        default:
×
807
                return fmt.Errorf("unknown type in ReadElement: %T", e)
×
808
        }
809

810
        return nil
3✔
811
}
812

813
// ReadElements deserializes a variable number of elements into the passed
814
// io.Reader, with each element being deserialized according to the ReadElement
815
// function.
816
func ReadElements(r io.Reader, elements ...interface{}) error {
3✔
817
        for _, element := range elements {
6✔
818
                err := ReadElement(r, element)
3✔
819
                if err != nil {
3✔
UNCOV
820
                        return err
×
UNCOV
821
                }
×
822
        }
823
        return nil
3✔
824
}
825

826
// ReadAddress attempts to read a single address descriptor (as defined in
827
// Bolt 7) from the passed io.Reader. The total length of the address section
828
// (in bytes) must be provided so that we can ensure we don't read beyond the
829
// end of the address section. The number of bytes read from the reader and the
830
// parsed net.Addr are returned.
831
//
832
// NOTE: it is possible for the number of bytes read to be 1 even if a nil
833
// address is returned.
834
func ReadAddress(addrBuf io.Reader, addrsLen uint16) (uint16, net.Addr, error) {
3✔
835
        var descriptor [1]byte
3✔
836
        if _, err := io.ReadFull(addrBuf, descriptor[:]); err != nil {
3✔
837
                return 0, nil, err
×
838
        }
×
839

840
        addrBytesRead := uint16(1)
3✔
841

3✔
842
        var address net.Addr
3✔
843
        switch aType := addressType(descriptor[0]); aType {
3✔
UNCOV
844
        case noAddr:
×
UNCOV
845
                return addrBytesRead, nil, nil
×
846

847
        case tcp4Addr:
3✔
848
                var ip [4]byte
3✔
849
                if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
3✔
UNCOV
850
                        return 0, nil, err
×
UNCOV
851
                }
×
852

853
                var port [2]byte
3✔
854
                if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
3✔
UNCOV
855
                        return 0, nil, err
×
UNCOV
856
                }
×
857

858
                address = &net.TCPAddr{
3✔
859
                        IP:   net.IP(ip[:]),
3✔
860
                        Port: int(binary.BigEndian.Uint16(port[:])),
3✔
861
                }
3✔
862
                addrBytesRead += tcp4AddrLen
3✔
863

864
        case tcp6Addr:
3✔
865
                var ip [16]byte
3✔
866
                if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
3✔
UNCOV
867
                        return 0, nil, err
×
UNCOV
868
                }
×
869

870
                var port [2]byte
3✔
871
                if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
3✔
UNCOV
872
                        return 0, nil, err
×
UNCOV
873
                }
×
874

875
                address = &net.TCPAddr{
3✔
876
                        IP:   net.IP(ip[:]),
3✔
877
                        Port: int(binary.BigEndian.Uint16(port[:])),
3✔
878
                }
3✔
879
                addrBytesRead += tcp6AddrLen
3✔
880

881
        case v2OnionAddr:
3✔
882
                var h [tor.V2DecodedLen]byte
3✔
883
                if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
3✔
UNCOV
884
                        return 0, nil, err
×
UNCOV
885
                }
×
886

887
                var p [2]byte
3✔
888
                if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
3✔
UNCOV
889
                        return 0, nil, err
×
UNCOV
890
                }
×
891

892
                onionService := tor.Base32Encoding.EncodeToString(h[:])
3✔
893
                onionService += tor.OnionSuffix
3✔
894
                port := int(binary.BigEndian.Uint16(p[:]))
3✔
895

3✔
896
                address = &tor.OnionAddr{
3✔
897
                        OnionService: onionService,
3✔
898
                        Port:         port,
3✔
899
                }
3✔
900
                addrBytesRead += v2OnionAddrLen
3✔
901

902
        case v3OnionAddr:
3✔
903
                var h [tor.V3DecodedLen]byte
3✔
904
                if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
3✔
UNCOV
905
                        return 0, nil, err
×
UNCOV
906
                }
×
907

908
                var p [2]byte
3✔
909
                if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
3✔
UNCOV
910
                        return 0, nil, err
×
UNCOV
911
                }
×
912

913
                onionService := tor.Base32Encoding.EncodeToString(h[:])
3✔
914
                onionService += tor.OnionSuffix
3✔
915
                port := int(binary.BigEndian.Uint16(p[:]))
3✔
916

3✔
917
                address = &tor.OnionAddr{
3✔
918
                        OnionService: onionService,
3✔
919
                        Port:         port,
3✔
920
                }
3✔
921
                addrBytesRead += v3OnionAddrLen
3✔
922

UNCOV
923
        case dnsAddr:
×
UNCOV
924
                var hostnameLen [1]byte
×
UNCOV
925
                if _, err := io.ReadFull(addrBuf, hostnameLen[:]); err != nil {
×
926
                        return 0, nil, err
×
927
                }
×
928

UNCOV
929
                hostname := make([]byte, hostnameLen[0])
×
UNCOV
930
                if _, err := io.ReadFull(addrBuf, hostname); err != nil {
×
UNCOV
931
                        return 0, nil, err
×
UNCOV
932
                }
×
933

UNCOV
934
                var port [2]byte
×
UNCOV
935
                if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
×
936
                        return 0, nil, err
×
937
                }
×
938

UNCOV
939
                address = &DNSAddress{
×
UNCOV
940
                        Hostname: string(hostname),
×
UNCOV
941
                        Port:     binary.BigEndian.Uint16(port[:]),
×
UNCOV
942
                }
×
UNCOV
943
                addrBytesRead += dnsAddrOverhead + uint16(len(hostname))
×
944

UNCOV
945
        default:
×
UNCOV
946
                // If we don't understand this address type, we just store it
×
UNCOV
947
                // along with the remaining address bytes as type OpaqueAddrs.
×
UNCOV
948
                // We need to hold onto the bytes so that we can still write
×
UNCOV
949
                // them back to the wire when we propagate this message.
×
UNCOV
950
                payloadLen := 1 + addrsLen - addrBytesRead
×
UNCOV
951
                payload := make([]byte, payloadLen)
×
UNCOV
952

×
UNCOV
953
                // First write a byte for the address type that we already read.
×
UNCOV
954
                payload[0] = byte(aType)
×
UNCOV
955

×
UNCOV
956
                // Now append the rest of the address bytes.
×
UNCOV
957
                if _, err := io.ReadFull(addrBuf, payload[1:]); err != nil {
×
958
                        return 0, nil, err
×
959
                }
×
960

UNCOV
961
                address = &OpaqueAddrs{
×
UNCOV
962
                        Payload: payload,
×
UNCOV
963
                }
×
UNCOV
964
                addrBytesRead = addrsLen
×
965
        }
966

967
        return addrBytesRead, address, nil
3✔
968
}
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