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

lightningnetwork / lnd / 16569502135

28 Jul 2025 12:50PM UTC coverage: 67.251% (+0.02%) from 67.227%
16569502135

Pull #9455

github

web-flow
Merge b3899c4fd into 2e36f9b8b
Pull Request #9455: discovery+lnwire: add support for DNS host name in NodeAnnouncement msg

179 of 208 new or added lines in 6 files covered. (86.06%)

105 existing lines in 23 files now uncovered.

135676 of 201746 relevant lines covered (67.25%)

21711.59 hits per line

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

70.72
/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 {
7,683✔
63
        switch a {
7,683✔
64
        case noAddr:
1,046✔
65
                return 0
1,046✔
66
        case tcp4Addr:
2,701✔
67
                return 6
2,701✔
68
        case tcp6Addr:
2,395✔
69
                return 18
2,395✔
70
        case v2OnionAddr:
1,158✔
71
                return 12
1,158✔
72
        case v3OnionAddr:
392✔
73
                return 37
392✔
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,794✔
85
        switch e := element.(type) {
3,794✔
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:
119✔
99
                var b [1]byte
119✔
100
                b[0] = e
119✔
101
                if _, err := w.Write(b[:]); err != nil {
119✔
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:
484✔
113
                var b [2]byte
484✔
114
                binary.BigEndian.PutUint16(b[:], e)
484✔
115
                if _, err := w.Write(b[:]); err != nil {
484✔
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:
110✔
141
                var b [8]byte
110✔
142
                binary.BigEndian.PutUint64(b[:], uint64(e))
110✔
143
                if _, err := w.Write(b[:]); err != nil {
110✔
144
                        return err
×
145
                }
×
146

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

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

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

166
                var b [33]byte
645✔
167
                serializedPubkey := e.SerializeCompressed()
645✔
168
                copy(b[:], serializedPubkey)
645✔
169
                if _, err := w.Write(b[:]); err != nil {
645✔
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

193
        case PartialSig:
111✔
194
                if err := e.Encode(w); err != nil {
111✔
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:
402✔
259
                if _, err := w.Write(e[:]); err != nil {
402✔
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:
110✔
285
                var h [32]byte
110✔
286
                copy(h[:], e.Hash[:])
110✔
287
                if _, err := w.Write(h[:]); err != nil {
110✔
288
                        return err
×
289
                }
×
290

291
                if e.Index > math.MaxUint16 {
110✔
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
110✔
298
                binary.BigEndian.PutUint16(idx[:], uint16(e.Index))
110✔
299
                if _, err := w.Write(idx[:]); err != nil {
110✔
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:
110✔
314
                // Check that field fit in 3 bytes and write the blockHeight
110✔
315
                if e.BlockHeight > ((1 << 24) - 1) {
110✔
316
                        return errors.New("block height should fit in 3 bytes")
×
317
                }
×
318

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

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

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

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

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

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

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

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

359
        case []net.Addr:
110✔
360
                // First, we'll encode all the addresses into an intermediate
110✔
361
                // buffer. We need to do this in order to compute the total
110✔
362
                // length of the addresses.
110✔
363
                var addrBuf bytes.Buffer
110✔
364
                for _, address := range e {
257✔
365
                        if err := WriteElement(&addrBuf, address); err != nil {
150✔
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()
110✔
373
                if err := WriteElement(w, uint16(addrLen)); err != nil {
110✔
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 {
149✔
380
                        if _, err := w.Write(addrBuf.Bytes()); err != nil {
39✔
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:
110✔
401
                var b [1]byte
110✔
402
                if e {
153✔
403
                        b[0] = 1
43✔
404
                }
43✔
405
                if _, err := w.Write(b[:]); err != nil {
110✔
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,794✔
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 {
384✔
425
        for _, element := range elements {
3,816✔
426
                err := WriteElement(buf, element)
3,432✔
427
                if err != nil {
3,435✔
428
                        return err
3✔
429
                }
3✔
430
        }
431
        return nil
384✔
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 {
100,156✔
437
        var err error
100,156✔
438
        switch e := element.(type) {
100,156✔
439
        case *bool:
284✔
440
                var b [1]byte
284✔
441
                if _, err := io.ReadFull(r, b[:]); err != nil {
285✔
442
                        return err
1✔
443
                }
1✔
444

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

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

455
                alias, err := NewNodeAlias(string(a[:]))
387✔
456
                if err != nil {
397✔
457
                        return err
10✔
458
                }
10✔
459
                *e = alias
377✔
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:
2,690✔
469
                var b [1]uint8
2,690✔
470
                if _, err := r.Read(b[:]); err != nil {
2,694✔
471
                        return err
4✔
472
                }
4✔
473
                *e = b[0]
2,686✔
474

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

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

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

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

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

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

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

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

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

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

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

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

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

2,223✔
566
                var sigs []Sig
2,223✔
567
                if numSigs > 0 {
2,992✔
568
                        sigs = make([]Sig, numSigs)
769✔
569
                        for i := 0; i < int(numSigs); i++ {
8,334✔
570
                                if err := ReadElement(r, &sigs[i]); err != nil {
7,574✔
571
                                        return err
9✔
572
                                }
9✔
573
                        }
574
                }
575
                *e = sigs
2,214✔
576

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

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

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

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

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

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

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

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

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

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

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

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

647
        case []byte:
10,763✔
648
                if _, err := io.ReadFull(r, e); err != nil {
10,814✔
649
                        return err
51✔
650
                }
51✔
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:
324✔
660
                var h [32]byte
324✔
661
                if _, err = io.ReadFull(r, h[:]); err != nil {
325✔
662
                        return err
1✔
663
                }
1✔
664
                hash, err := chainhash.NewHash(h[:])
323✔
665
                if err != nil {
323✔
666
                        return err
×
667
                }
×
668

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

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

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

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

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

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

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

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

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

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

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

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

745
                        addrBytesRead++
7,963✔
746

7,963✔
747
                        var address net.Addr
7,963✔
748
                        switch aType := addressType(descriptor[0]); aType {
7,963✔
749
                        case noAddr:
1,046✔
750
                                addrBytesRead += aType.AddrLen()
1,046✔
751
                                continue
1,046✔
752

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

869
                                if err := dnsAddr.Validate(); err != nil {
5✔
NEW
870
                                        return err
×
NEW
871
                                }
×
872

873
                                address = dnsAddr
5✔
874
                                length := 1 + uint16(hostnameLen) + portLen
5✔
875
                                addrBytesRead += length
5✔
876

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

260✔
887
                                // First write a byte for the address type that
260✔
888
                                // we already read.
260✔
889
                                payload[0] = byte(aType)
260✔
890

260✔
891
                                // Now append the rest of the address bytes.
260✔
892
                                _, err := io.ReadFull(addrBuf, payload[1:])
260✔
893
                                if err != nil {
260✔
894
                                        return err
×
895
                                }
×
896

897
                                address = &OpaqueAddrs{
260✔
898
                                        Payload: payload,
260✔
899
                                }
260✔
900
                                addrBytesRead = addrsLen
260✔
901
                        }
902

903
                        addresses = append(addresses, address)
6,899✔
904
                }
905

906
                *e = addresses
502✔
907

908
        case *color.RGBA:
391✔
909
                err := ReadElements(r,
391✔
910
                        &e.R,
391✔
911
                        &e.G,
391✔
912
                        &e.B,
391✔
913
                )
391✔
914
                if err != nil {
393✔
915
                        return err
2✔
916
                }
2✔
917

918
        case *DeliveryAddress:
697✔
919
                var addrLen [2]byte
697✔
920
                if _, err = io.ReadFull(r, addrLen[:]); err != nil {
706✔
921
                        return err
9✔
922
                }
9✔
923
                length := binary.BigEndian.Uint16(addrLen[:])
688✔
924

688✔
925
                var addrBytes [deliveryAddressMaxSize]byte
688✔
926

688✔
927
                if length > deliveryAddressMaxSize {
793✔
928
                        return fmt.Errorf(
105✔
929
                                "cannot read %d bytes into addrBytes", length,
105✔
930
                        )
105✔
931
                }
105✔
932
                if _, err = io.ReadFull(r, addrBytes[:length]); err != nil {
584✔
933
                        return err
1✔
934
                }
1✔
935
                *e = addrBytes[:length]
582✔
936

937
        case *PartialSig:
123✔
938
                var sig PartialSig
123✔
939
                if err = sig.Decode(r); err != nil {
124✔
940
                        return err
1✔
941
                }
1✔
942
                *e = sig
122✔
943

944
        case *ExtraOpaqueData:
12,138✔
945
                return e.Decode(r)
12,138✔
946

947
        default:
×
948
                return fmt.Errorf("unknown type in ReadElement: %T", e)
×
949
        }
950

951
        return nil
85,998✔
952
}
953

954
// ReadElements deserializes a variable number of elements into the passed
955
// io.Reader, with each element being deserialized according to the ReadElement
956
// function.
957
func ReadElements(r io.Reader, elements ...interface{}) error {
36,333✔
958
        for _, element := range elements {
126,509✔
959
                err := ReadElement(r, element)
90,176✔
960
                if err != nil {
92,149✔
961
                        return err
1,973✔
962
                }
1,973✔
963
        }
964
        return nil
34,360✔
965
}
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