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

lightningnetwork / lnd / 16466354971

23 Jul 2025 09:05AM UTC coverage: 57.54% (-9.7%) from 67.201%
16466354971

Pull #9455

github

web-flow
Merge f914ae23c into 90e211684
Pull Request #9455: discovery+lnwire: add support for DNS host name in NodeAnnouncement msg

151 of 291 new or added lines in 7 files covered. (51.89%)

28441 existing lines in 456 files now uncovered.

98864 of 171817 relevant lines covered (57.54%)

1.79 hits per line

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

46.95
/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
// PkScript is simple type definition which represents a raw serialized public
32
// key script.
33
type PkScript []byte
34

35
// addressType specifies the network protocol and version that should be used
36
// when connecting to a node at a particular address.
37
type addressType uint8
38

39
const (
40
        // noAddr denotes a blank address. An address of this type indicates
41
        // that a node doesn't have any advertised addresses.
42
        noAddr addressType = 0
43

44
        // tcp4Addr denotes an IPv4 TCP address.
45
        tcp4Addr addressType = 1
46

47
        // tcp6Addr denotes an IPv6 TCP address.
48
        tcp6Addr addressType = 2
49

50
        // v2OnionAddr denotes a version 2 Tor onion service address.
51
        v2OnionAddr addressType = 3
52

53
        // v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
54
        v3OnionAddr addressType = 4
55

56
        // dnsHostnameAddr denotes a DNS hostname address.
57
        dnsHostnameAddr addressType = 5
58
)
59

60
// AddrLen returns the number of bytes that it takes to encode the target
61
// address.
62
func (a addressType) AddrLen() uint16 {
3✔
63
        switch a {
3✔
UNCOV
64
        case noAddr:
×
UNCOV
65
                return 0
×
66
        case tcp4Addr:
3✔
67
                return 6
3✔
68
        case tcp6Addr:
3✔
69
                return 18
3✔
70
        case v2OnionAddr:
3✔
71
                return 12
3✔
72
        case v3OnionAddr:
3✔
73
                return 37
3✔
74
        default:
×
75
                return 0
×
76
        }
77
}
78

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

UNCOV
193
        case PartialSig:
×
UNCOV
194
                if err := e.Encode(w); err != nil {
×
195
                        return err
×
196
                }
×
197

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

205
                if _, err := w.Write(e[:]); err != nil {
×
206
                        return err
×
207
                }
×
208

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

216
                if _, err := w.Write(e[:]); err != nil {
×
217
                        return err
×
218
                }
×
219

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

227
                if _, err := w.Write(e[:]); err != nil {
×
228
                        return err
×
229
                }
×
230

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

238
                if _, err := w.Write(e[:]); err != nil {
×
239
                        return err
×
240
                }
×
241

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

249
                if _, err := w.Write(e[:]); err != nil {
×
250
                        return err
×
251
                }
×
252

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

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

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

271
                if err := wire.WriteVarBytes(w, 0, e); err != nil {
×
272
                        return err
×
273
                }
×
274

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

280
                if err := e.Encode(w); err != nil {
×
281
                        return err
×
282
                }
×
283

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

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

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

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

308
        case FailCode:
×
309
                if err := WriteElement(w, uint16(e)); err != nil {
×
310
                        return err
×
311
                }
×
312

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

319
                var blockHeight [4]byte
3✔
320
                binary.BigEndian.PutUint32(blockHeight[:], e.BlockHeight)
3✔
321

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

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

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

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

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

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

UNCOV
354
        case *OpaqueAddrs:
×
UNCOV
355
                if err := WriteOpaqueAddrs(w, e); err != nil {
×
356
                        return err
×
357
                }
×
358

359
        case []net.Addr:
3✔
360
                // First, we'll encode all the addresses into an intermediate
3✔
361
                // buffer. We need to do this in order to compute the total
3✔
362
                // length of the addresses.
3✔
363
                var addrBuf bytes.Buffer
3✔
364
                for _, address := range e {
6✔
365
                        if err := WriteElement(&addrBuf, address); err != nil {
6✔
366
                                return err
3✔
367
                        }
3✔
368
                }
369

370
                // With the addresses fully encoded, we can now write out the
371
                // number of bytes needed to encode them.
372
                addrLen := addrBuf.Len()
3✔
373
                if err := WriteElement(w, uint16(addrLen)); err != nil {
3✔
374
                        return err
×
375
                }
×
376

377
                // Finally, we'll write out the raw addresses themselves, but
378
                // only if we have any bytes to write.
379
                if addrLen > 0 {
6✔
380
                        if _, err := w.Write(addrBuf.Bytes()); err != nil {
3✔
381
                                return err
×
382
                        }
×
383
                }
384

385
        case color.RGBA:
×
386
                if err := WriteElements(w, e.R, e.G, e.B); err != nil {
×
387
                        return err
×
388
                }
×
389

390
        case DeliveryAddress:
×
391
                var length [2]byte
×
392
                binary.BigEndian.PutUint16(length[:], uint16(len(e)))
×
393
                if _, err := w.Write(length[:]); err != nil {
×
394
                        return err
×
395
                }
×
396
                if _, err := w.Write(e[:]); err != nil {
×
397
                        return err
×
398
                }
×
399

400
        case bool:
3✔
401
                var b [1]byte
3✔
402
                if e {
6✔
403
                        b[0] = 1
3✔
404
                }
3✔
405
                if _, err := w.Write(b[:]); err != nil {
3✔
406
                        return err
×
407
                }
×
408

409
        case ExtraOpaqueData:
×
410
                return e.Encode(w)
×
411

412
        default:
3✔
413
                return fmt.Errorf("unknown type in WriteElement: %T", e)
3✔
414
        }
415

416
        return nil
3✔
417
}
418

419
// WriteElements is writes each element in the elements slice to the passed
420
// buffer using WriteElement.
421
//
422
// TODO(yy): rm this method once we finish dereferencing it from other
423
// packages.
424
func WriteElements(buf *bytes.Buffer, elements ...interface{}) error {
3✔
425
        for _, element := range elements {
6✔
426
                err := WriteElement(buf, element)
3✔
427
                if err != nil {
6✔
428
                        return err
3✔
429
                }
3✔
430
        }
431
        return nil
3✔
432
}
433

434
// ReadElement is a one-stop utility function to deserialize any datastructure
435
// encoded using the serialization format of lnwire.
436
func ReadElement(r io.Reader, element interface{}) error {
3✔
437
        var err error
3✔
438
        switch e := element.(type) {
3✔
439
        case *bool:
3✔
440
                var b [1]byte
3✔
441
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
442
                        return err
×
UNCOV
443
                }
×
444

445
                if b[0] == 1 {
6✔
446
                        *e = true
3✔
447
                }
3✔
448

449
        case *NodeAlias:
3✔
450
                var a [32]byte
3✔
451
                if _, err := io.ReadFull(r, a[:]); err != nil {
3✔
UNCOV
452
                        return err
×
UNCOV
453
                }
×
454

455
                alias, err := NewNodeAlias(string(a[:]))
3✔
456
                if err != nil {
3✔
UNCOV
457
                        return err
×
UNCOV
458
                }
×
459
                *e = alias
3✔
460

461
        case *QueryEncoding:
×
462
                var b [1]uint8
×
463
                if _, err := r.Read(b[:]); err != nil {
×
464
                        return err
×
465
                }
×
466
                *e = QueryEncoding(b[0])
×
467

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

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

482
        case *uint16:
3✔
483
                var b [2]byte
3✔
484
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
485
                        return err
×
UNCOV
486
                }
×
487
                *e = binary.BigEndian.Uint16(b[:])
3✔
488

489
        case *ChanUpdateMsgFlags:
3✔
490
                var b [1]uint8
3✔
491
                if _, err := r.Read(b[:]); err != nil {
3✔
UNCOV
492
                        return err
×
UNCOV
493
                }
×
494
                *e = ChanUpdateMsgFlags(b[0])
3✔
495

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

503
        case *uint32:
3✔
504
                var b [4]byte
3✔
505
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
506
                        return err
×
UNCOV
507
                }
×
508
                *e = binary.BigEndian.Uint32(b[:])
3✔
509

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

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

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

531
        case **btcec.PublicKey:
3✔
532
                var b [btcec.PubKeyBytesLenCompressed]byte
3✔
533
                if _, err = io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
534
                        return err
×
UNCOV
535
                }
×
536

537
                pubKey, err := btcec.ParsePubKey(b[:])
3✔
538
                if err != nil {
3✔
UNCOV
539
                        return err
×
UNCOV
540
                }
×
541
                *e = pubKey
3✔
542

UNCOV
543
        case *RawFeatureVector:
×
UNCOV
544
                f := NewRawFeatureVector()
×
UNCOV
545
                err = f.Decode(r)
×
UNCOV
546
                if err != nil {
×
UNCOV
547
                        return err
×
UNCOV
548
                }
×
UNCOV
549
                *e = *f
×
550

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

559
        case *[]Sig:
3✔
560
                var l [2]byte
3✔
561
                if _, err := io.ReadFull(r, l[:]); err != nil {
3✔
UNCOV
562
                        return err
×
UNCOV
563
                }
×
564
                numSigs := binary.BigEndian.Uint16(l[:])
3✔
565

3✔
566
                var sigs []Sig
3✔
567
                if numSigs > 0 {
6✔
568
                        sigs = make([]Sig, numSigs)
3✔
569
                        for i := 0; i < int(numSigs); i++ {
6✔
570
                                if err := ReadElement(r, &sigs[i]); err != nil {
3✔
UNCOV
571
                                        return err
×
UNCOV
572
                                }
×
573
                        }
574
                }
575
                *e = sigs
3✔
576

577
        case *Sig:
3✔
578
                if _, err := io.ReadFull(r, e.bytes[:]); err != nil {
3✔
UNCOV
579
                        return err
×
UNCOV
580
                }
×
581

582
        case *OpaqueReason:
3✔
583
                var l [2]byte
3✔
584
                if _, err := io.ReadFull(r, l[:]); err != nil {
3✔
UNCOV
585
                        return err
×
UNCOV
586
                }
×
587
                reasonLen := binary.BigEndian.Uint16(l[:])
3✔
588

3✔
589
                *e = OpaqueReason(make([]byte, reasonLen))
3✔
590
                if _, err := io.ReadFull(r, *e); err != nil {
3✔
UNCOV
591
                        return err
×
UNCOV
592
                }
×
593

UNCOV
594
        case *WarningData:
×
UNCOV
595
                var l [2]byte
×
UNCOV
596
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
UNCOV
597
                        return err
×
UNCOV
598
                }
×
UNCOV
599
                errorLen := binary.BigEndian.Uint16(l[:])
×
UNCOV
600

×
UNCOV
601
                *e = WarningData(make([]byte, errorLen))
×
UNCOV
602
                if _, err := io.ReadFull(r, *e); err != nil {
×
UNCOV
603
                        return err
×
UNCOV
604
                }
×
605

606
        case *ErrorData:
3✔
607
                var l [2]byte
3✔
608
                if _, err := io.ReadFull(r, l[:]); err != nil {
3✔
UNCOV
609
                        return err
×
UNCOV
610
                }
×
611
                errorLen := binary.BigEndian.Uint16(l[:])
3✔
612

3✔
613
                *e = ErrorData(make([]byte, errorLen))
3✔
614
                if _, err := io.ReadFull(r, *e); err != nil {
3✔
UNCOV
615
                        return err
×
UNCOV
616
                }
×
617

UNCOV
618
        case *PingPayload:
×
UNCOV
619
                var l [2]byte
×
UNCOV
620
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
UNCOV
621
                        return err
×
UNCOV
622
                }
×
UNCOV
623
                pingLen := binary.BigEndian.Uint16(l[:])
×
UNCOV
624

×
UNCOV
625
                *e = PingPayload(make([]byte, pingLen))
×
UNCOV
626
                if _, err := io.ReadFull(r, *e); err != nil {
×
UNCOV
627
                        return err
×
UNCOV
628
                }
×
629

UNCOV
630
        case *PongPayload:
×
UNCOV
631
                var l [2]byte
×
UNCOV
632
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
UNCOV
633
                        return err
×
UNCOV
634
                }
×
UNCOV
635
                pongLen := binary.BigEndian.Uint16(l[:])
×
UNCOV
636

×
UNCOV
637
                *e = PongPayload(make([]byte, pongLen))
×
UNCOV
638
                if _, err := io.ReadFull(r, *e); err != nil {
×
UNCOV
639
                        return err
×
UNCOV
640
                }
×
641

642
        case *[33]byte:
3✔
643
                if _, err := io.ReadFull(r, e[:]); err != nil {
3✔
UNCOV
644
                        return err
×
UNCOV
645
                }
×
646

647
        case []byte:
3✔
648
                if _, err := io.ReadFull(r, e); err != nil {
3✔
UNCOV
649
                        return err
×
UNCOV
650
                }
×
651

652
        case *PkScript:
×
653
                pkScript, err := wire.ReadVarBytes(r, 0, 34, "pkscript")
×
654
                if err != nil {
×
655
                        return err
×
656
                }
×
657
                *e = pkScript
×
658

659
        case *wire.OutPoint:
3✔
660
                var h [32]byte
3✔
661
                if _, err = io.ReadFull(r, h[:]); err != nil {
3✔
UNCOV
662
                        return err
×
UNCOV
663
                }
×
664
                hash, err := chainhash.NewHash(h[:])
3✔
665
                if err != nil {
3✔
666
                        return err
×
667
                }
×
668

669
                var idxBytes [2]byte
3✔
670
                _, err = io.ReadFull(r, idxBytes[:])
3✔
671
                if err != nil {
3✔
UNCOV
672
                        return err
×
UNCOV
673
                }
×
674
                index := binary.BigEndian.Uint16(idxBytes[:])
3✔
675

3✔
676
                *e = wire.OutPoint{
3✔
677
                        Hash:  *hash,
3✔
678
                        Index: uint32(index),
3✔
679
                }
3✔
680

681
        case *FailCode:
3✔
682
                if err := ReadElement(r, (*uint16)(e)); err != nil {
3✔
UNCOV
683
                        return err
×
UNCOV
684
                }
×
685

686
        case *ChannelID:
3✔
687
                if _, err := io.ReadFull(r, e[:]); err != nil {
3✔
UNCOV
688
                        return err
×
UNCOV
689
                }
×
690

691
        case *ShortChannelID:
3✔
692
                var blockHeight [4]byte
3✔
693
                if _, err = io.ReadFull(r, blockHeight[1:]); err != nil {
3✔
UNCOV
694
                        return err
×
UNCOV
695
                }
×
696

697
                var txIndex [4]byte
3✔
698
                if _, err = io.ReadFull(r, txIndex[1:]); err != nil {
3✔
UNCOV
699
                        return err
×
UNCOV
700
                }
×
701

702
                var txPosition [2]byte
3✔
703
                if _, err = io.ReadFull(r, txPosition[:]); err != nil {
3✔
UNCOV
704
                        return err
×
UNCOV
705
                }
×
706

707
                *e = ShortChannelID{
3✔
708
                        BlockHeight: binary.BigEndian.Uint32(blockHeight[:]),
3✔
709
                        TxIndex:     binary.BigEndian.Uint32(txIndex[:]),
3✔
710
                        TxPosition:  binary.BigEndian.Uint16(txPosition[:]),
3✔
711
                }
3✔
712

713
        case *[]net.Addr:
3✔
714
                // First, we'll read the number of total bytes that have been
3✔
715
                // used to encode the set of addresses.
3✔
716
                var numAddrsBytes [2]byte
3✔
717
                if _, err = io.ReadFull(r, numAddrsBytes[:]); err != nil {
3✔
UNCOV
718
                        return err
×
UNCOV
719
                }
×
720
                addrsLen := binary.BigEndian.Uint16(numAddrsBytes[:])
3✔
721

3✔
722
                // With the number of addresses, read, we'll now pull in the
3✔
723
                // buffer of the encoded addresses into memory.
3✔
724
                addrs := make([]byte, addrsLen)
3✔
725
                if _, err := io.ReadFull(r, addrs[:]); err != nil {
3✔
UNCOV
726
                        return err
×
UNCOV
727
                }
×
728
                addrBuf := bytes.NewReader(addrs)
3✔
729

3✔
730
                // Finally, we'll parse the remaining address payload in
3✔
731
                // series, using the first byte to denote how to decode the
3✔
732
                // address itself.
3✔
733
                var (
3✔
734
                        addresses       []net.Addr
3✔
735
                        addrBytesRead   uint16
3✔
736
                        dnsAddrIncluded bool
3✔
737
                )
3✔
738

3✔
739
                for addrBytesRead < addrsLen {
6✔
740
                        var descriptor [1]byte
3✔
741
                        if _, err = io.ReadFull(addrBuf, descriptor[:]); err != nil {
3✔
742
                                return err
×
743
                        }
×
744

745
                        addrBytesRead++
3✔
746

3✔
747
                        var address net.Addr
3✔
748
                        switch aType := addressType(descriptor[0]); aType {
3✔
UNCOV
749
                        case noAddr:
×
UNCOV
750
                                addrBytesRead += aType.AddrLen()
×
UNCOV
751
                                continue
×
752

753
                        case tcp4Addr:
3✔
754
                                var ip [4]byte
3✔
755
                                if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
3✔
UNCOV
756
                                        return err
×
UNCOV
757
                                }
×
758

759
                                var port [2]byte
3✔
760
                                if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
3✔
UNCOV
761
                                        return err
×
UNCOV
762
                                }
×
763

764
                                address = &net.TCPAddr{
3✔
765
                                        IP:   net.IP(ip[:]),
3✔
766
                                        Port: int(binary.BigEndian.Uint16(port[:])),
3✔
767
                                }
3✔
768
                                addrBytesRead += aType.AddrLen()
3✔
769

770
                        case tcp6Addr:
3✔
771
                                var ip [16]byte
3✔
772
                                if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
3✔
UNCOV
773
                                        return err
×
UNCOV
774
                                }
×
775

776
                                var port [2]byte
3✔
777
                                if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
3✔
UNCOV
778
                                        return err
×
UNCOV
779
                                }
×
780

781
                                address = &net.TCPAddr{
3✔
782
                                        IP:   net.IP(ip[:]),
3✔
783
                                        Port: int(binary.BigEndian.Uint16(port[:])),
3✔
784
                                }
3✔
785
                                addrBytesRead += aType.AddrLen()
3✔
786

787
                        case v2OnionAddr:
3✔
788
                                var h [tor.V2DecodedLen]byte
3✔
789
                                if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
3✔
UNCOV
790
                                        return err
×
UNCOV
791
                                }
×
792

793
                                var p [2]byte
3✔
794
                                if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
3✔
UNCOV
795
                                        return err
×
UNCOV
796
                                }
×
797

798
                                onionService := tor.Base32Encoding.EncodeToString(h[:])
3✔
799
                                onionService += tor.OnionSuffix
3✔
800
                                port := int(binary.BigEndian.Uint16(p[:]))
3✔
801

3✔
802
                                address = &tor.OnionAddr{
3✔
803
                                        OnionService: onionService,
3✔
804
                                        Port:         port,
3✔
805
                                }
3✔
806
                                addrBytesRead += aType.AddrLen()
3✔
807

808
                        case v3OnionAddr:
3✔
809
                                var h [tor.V3DecodedLen]byte
3✔
810
                                if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
3✔
UNCOV
811
                                        return err
×
UNCOV
812
                                }
×
813

814
                                var p [2]byte
3✔
815
                                if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
3✔
UNCOV
816
                                        return err
×
UNCOV
817
                                }
×
818

819
                                onionService := tor.Base32Encoding.EncodeToString(h[:])
3✔
820
                                onionService += tor.OnionSuffix
3✔
821
                                port := int(binary.BigEndian.Uint16(p[:]))
3✔
822

3✔
823
                                address = &tor.OnionAddr{
3✔
824
                                        OnionService: onionService,
3✔
825
                                        Port:         port,
3✔
826
                                }
3✔
827
                                addrBytesRead += aType.AddrLen()
3✔
828

829
                        case dnsHostnameAddr:
3✔
830
                                if dnsAddrIncluded {
3✔
NEW
831
                                        return errors.New("cannot advertise " +
×
NEW
832
                                                "multiple DNS addresses. See " +
×
NEW
833
                                                "Bolt 07")
×
NEW
834
                                }
×
835
                                dnsAddrIncluded = true
3✔
836

3✔
837
                                // Read hostname length byte.
3✔
838
                                var hostnameLen byte
3✔
839
                                err := binary.Read(
3✔
840
                                        addrBuf, binary.BigEndian, &hostnameLen,
3✔
841
                                )
3✔
842
                                if err != nil {
3✔
NEW
843
                                        return err
×
NEW
844
                                }
×
845

846
                                // Read hostname of variable size.
847
                                hostname := make([]byte, hostnameLen)
3✔
848
                                _, err = io.ReadFull(addrBuf, hostname)
3✔
849
                                if err != nil {
3✔
NEW
850
                                        return err
×
NEW
851
                                }
×
852

853
                                // Read port.
854
                                const portLen = 2
3✔
855
                                var port [portLen]byte
3✔
856
                                _, err = io.ReadFull(addrBuf, port[:])
3✔
857
                                if err != nil {
3✔
NEW
858
                                        return err
×
NEW
859
                                }
×
860

861
                                address, err = NewDNSAddr(
3✔
862
                                        string(hostname),
3✔
863
                                        int(binary.BigEndian.Uint16(port[:])),
3✔
864
                                )
3✔
865
                                if err != nil {
3✔
NEW
866
                                        return err
×
NEW
867
                                }
×
868

869
                                length := 1 + uint16(hostnameLen) + portLen
3✔
870
                                addrBytesRead += length
3✔
871

UNCOV
872
                        default:
×
UNCOV
873
                                // If we don't understand this address type,
×
UNCOV
874
                                // we just store it along with the remaining
×
UNCOV
875
                                // address bytes as type OpaqueAddrs. We need
×
UNCOV
876
                                // to hold onto the bytes so that we can still
×
UNCOV
877
                                // write them back to the wire when we
×
UNCOV
878
                                // propagate this message.
×
UNCOV
879
                                payloadLen := 1 + addrsLen - addrBytesRead
×
UNCOV
880
                                payload := make([]byte, payloadLen)
×
UNCOV
881

×
UNCOV
882
                                // First write a byte for the address type that
×
UNCOV
883
                                // we already read.
×
UNCOV
884
                                payload[0] = byte(aType)
×
UNCOV
885

×
UNCOV
886
                                // Now append the rest of the address bytes.
×
UNCOV
887
                                _, err := io.ReadFull(addrBuf, payload[1:])
×
UNCOV
888
                                if err != nil {
×
889
                                        return err
×
890
                                }
×
891

UNCOV
892
                                address = &OpaqueAddrs{
×
UNCOV
893
                                        Payload: payload,
×
UNCOV
894
                                }
×
UNCOV
895
                                addrBytesRead = addrsLen
×
896
                        }
897

898
                        addresses = append(addresses, address)
3✔
899
                }
900

901
                *e = addresses
3✔
902

903
        case *color.RGBA:
3✔
904
                err := ReadElements(r,
3✔
905
                        &e.R,
3✔
906
                        &e.G,
3✔
907
                        &e.B,
3✔
908
                )
3✔
909
                if err != nil {
3✔
UNCOV
910
                        return err
×
UNCOV
911
                }
×
912

913
        case *DeliveryAddress:
3✔
914
                var addrLen [2]byte
3✔
915
                if _, err = io.ReadFull(r, addrLen[:]); err != nil {
3✔
UNCOV
916
                        return err
×
UNCOV
917
                }
×
918
                length := binary.BigEndian.Uint16(addrLen[:])
3✔
919

3✔
920
                var addrBytes [deliveryAddressMaxSize]byte
3✔
921

3✔
922
                if length > deliveryAddressMaxSize {
3✔
UNCOV
923
                        return fmt.Errorf(
×
UNCOV
924
                                "cannot read %d bytes into addrBytes", length,
×
UNCOV
925
                        )
×
UNCOV
926
                }
×
927
                if _, err = io.ReadFull(r, addrBytes[:length]); err != nil {
3✔
UNCOV
928
                        return err
×
UNCOV
929
                }
×
930
                *e = addrBytes[:length]
3✔
931

UNCOV
932
        case *PartialSig:
×
UNCOV
933
                var sig PartialSig
×
UNCOV
934
                if err = sig.Decode(r); err != nil {
×
UNCOV
935
                        return err
×
UNCOV
936
                }
×
UNCOV
937
                *e = sig
×
938

939
        case *ExtraOpaqueData:
3✔
940
                return e.Decode(r)
3✔
941

942
        default:
×
943
                return fmt.Errorf("unknown type in ReadElement: %T", e)
×
944
        }
945

946
        return nil
3✔
947
}
948

949
// ReadElements deserializes a variable number of elements into the passed
950
// io.Reader, with each element being deserialized according to the ReadElement
951
// function.
952
func ReadElements(r io.Reader, elements ...interface{}) error {
3✔
953
        for _, element := range elements {
6✔
954
                err := ReadElement(r, element)
3✔
955
                if err != nil {
3✔
UNCOV
956
                        return err
×
UNCOV
957
                }
×
958
        }
959
        return nil
3✔
960
}
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