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

lightningnetwork / lnd / 17448539139

03 Sep 2025 11:19PM UTC coverage: 66.664% (+9.3%) from 57.321%
17448539139

Pull #10183

github

web-flow
Merge a58e329b2 into ea6cc8154
Pull Request #10183: brontide: eliminate all allocations from WriteMessage+Flush

47 of 55 new or added lines in 3 files covered. (85.45%)

2794 existing lines in 19 files now uncovered.

136134 of 204209 relevant lines covered (66.66%)

21430.41 hits per line

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

69.28
/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,818✔
88
        switch e := element.(type) {
3,818✔
89
        case NodeAlias:
×
90
                if _, err := w.Write(e[:]); err != nil {
×
91
                        return err
×
92
                }
×
93

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

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

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

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

UNCOV
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

UNCOV
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

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

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

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

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

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

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

176
        case []Sig:
×
UNCOV
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
×
UNCOV
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
×
UNCOV
194
                }
×
195

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

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

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

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

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

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

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

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

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

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

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

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

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

266
        case PkScript:
×
UNCOV
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 {
×
UNCOV
271
                        return fmt.Errorf("'PkScript' too long")
×
272
                }
×
273

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

367
        case []net.Addr:
110✔
368
                // First, we'll encode all the addresses into an intermediate
110✔
369
                // buffer. We need to do this in order to compute the total
110✔
370
                // length of the addresses.
110✔
371
                var addrBuf bytes.Buffer
110✔
372
                for _, address := range e {
293✔
373
                        if err := WriteElement(&addrBuf, address); err != nil {
183✔
UNCOV
374
                                return err
×
UNCOV
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()
110✔
381
                if err := WriteElement(w, uint16(addrLen)); err != nil {
110✔
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 {
149✔
388
                        if _, err := w.Write(addrBuf.Bytes()); err != nil {
39✔
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
×
UNCOV
396
                }
×
397

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

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

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

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

424
        return nil
3,818✔
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 {
376✔
433
        for _, element := range elements {
3,796✔
434
                err := WriteElement(buf, element)
3,420✔
435
                if err != nil {
3,420✔
UNCOV
436
                        return err
×
UNCOV
437
                }
×
438
        }
439
        return nil
376✔
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 {
100,702✔
445
        var err error
100,702✔
446
        switch e := element.(type) {
100,702✔
447
        case *bool:
284✔
448
                var b [1]byte
284✔
449
                if _, err := io.ReadFull(r, b[:]); err != nil {
285✔
450
                        return err
1✔
451
                }
1✔
452

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

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

463
                alias, err := NewNodeAlias(string(a[:]))
387✔
464
                if err != nil {
397✔
465
                        return err
10✔
466
                }
10✔
467
                *e = alias
377✔
468

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2,298✔
574
                var sigs []Sig
2,298✔
575
                if numSigs > 0 {
3,094✔
576
                        sigs = make([]Sig, numSigs)
796✔
577
                        for i := 0; i < int(numSigs); i++ {
8,291✔
578
                                if err := ReadElement(r, &sigs[i]); err != nil {
7,504✔
579
                                        return err
9✔
580
                                }
9✔
581
                        }
582
                }
583
                *e = sigs
2,289✔
584

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

705
                var txIndex [4]byte
10,878✔
706
                if _, err = io.ReadFull(r, txIndex[1:]); err != nil {
11,068✔
707
                        return err
190✔
708
                }
190✔
709

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

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

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

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

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

521✔
746
                for addrBytesRead < addrsLen {
8,531✔
747
                        var descriptor [1]byte
8,010✔
748
                        if _, err = io.ReadFull(addrBuf, descriptor[:]); err != nil {
8,010✔
UNCOV
749
                                return err
×
UNCOV
750
                        }
×
751

752
                        addrBytesRead++
8,010✔
753

8,010✔
754
                        var address net.Addr
8,010✔
755
                        switch aType := addressType(descriptor[0]); aType {
8,010✔
756
                        case noAddr:
1,046✔
757
                                continue
1,046✔
758

759
                        case tcp4Addr:
2,725✔
760
                                var ip [4]byte
2,725✔
761
                                if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
2,727✔
762
                                        return err
2✔
763
                                }
2✔
764

765
                                var port [2]byte
2,723✔
766
                                if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
2,724✔
767
                                        return err
1✔
768
                                }
1✔
769

770
                                address = &net.TCPAddr{
2,722✔
771
                                        IP:   net.IP(ip[:]),
2,722✔
772
                                        Port: int(binary.BigEndian.Uint16(port[:])),
2,722✔
773
                                }
2,722✔
774
                                addrBytesRead += tcp4AddrLen
2,722✔
775

776
                        case tcp6Addr:
2,404✔
777
                                var ip [16]byte
2,404✔
778
                                if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
2,408✔
779
                                        return err
4✔
780
                                }
4✔
781

782
                                var port [2]byte
2,400✔
783
                                if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
2,401✔
784
                                        return err
1✔
785
                                }
1✔
786

787
                                address = &net.TCPAddr{
2,399✔
788
                                        IP:   net.IP(ip[:]),
2,399✔
789
                                        Port: int(binary.BigEndian.Uint16(port[:])),
2,399✔
790
                                }
2,399✔
791
                                addrBytesRead += tcp6AddrLen
2,399✔
792

793
                        case v2OnionAddr:
1,163✔
794
                                var h [tor.V2DecodedLen]byte
1,163✔
795
                                if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
1,166✔
796
                                        return err
3✔
797
                                }
3✔
798

799
                                var p [2]byte
1,160✔
800
                                if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
1,161✔
801
                                        return err
1✔
802
                                }
1✔
803

804
                                onionService := tor.Base32Encoding.EncodeToString(h[:])
1,159✔
805
                                onionService += tor.OnionSuffix
1,159✔
806
                                port := int(binary.BigEndian.Uint16(p[:]))
1,159✔
807

1,159✔
808
                                address = &tor.OnionAddr{
1,159✔
809
                                        OnionService: onionService,
1,159✔
810
                                        Port:         port,
1,159✔
811
                                }
1,159✔
812
                                addrBytesRead += v2OnionAddrLen
1,159✔
813

814
                        case v3OnionAddr:
396✔
815
                                var h [tor.V3DecodedLen]byte
396✔
816
                                if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
399✔
817
                                        return err
3✔
818
                                }
3✔
819

820
                                var p [2]byte
393✔
821
                                if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
394✔
822
                                        return err
1✔
823
                                }
1✔
824

825
                                onionService := tor.Base32Encoding.EncodeToString(h[:])
392✔
826
                                onionService += tor.OnionSuffix
392✔
827
                                port := int(binary.BigEndian.Uint16(p[:]))
392✔
828

392✔
829
                                address = &tor.OnionAddr{
392✔
830
                                        OnionService: onionService,
392✔
831
                                        Port:         port,
392✔
832
                                }
392✔
833
                                addrBytesRead += v3OnionAddrLen
392✔
834

835
                        case dnsAddr:
25✔
836
                                var hostnameLen [1]byte
25✔
837
                                _, err := io.ReadFull(addrBuf, hostnameLen[:])
25✔
838
                                if err != nil {
25✔
839
                                        return err
×
840
                                }
×
841

842
                                hostname := make([]byte, hostnameLen[0])
25✔
843
                                _, err = io.ReadFull(addrBuf, hostname)
25✔
844
                                if err != nil {
26✔
845
                                        return err
1✔
846
                                }
1✔
847

848
                                var port [2]byte
24✔
849
                                _, err = io.ReadFull(addrBuf, port[:])
24✔
850
                                if err != nil {
24✔
UNCOV
851
                                        return err
×
UNCOV
852
                                }
×
853

854
                                address = &DNSAddress{
24✔
855
                                        Hostname: string(hostname),
24✔
856
                                        Port: binary.BigEndian.Uint16(
24✔
857
                                                port[:],
24✔
858
                                        ),
24✔
859
                                }
24✔
860
                                addrBytesRead += dnsAddrOverhead +
24✔
861
                                        uint16(len(hostname))
24✔
862

863
                        default:
260✔
864
                                // If we don't understand this address type,
260✔
865
                                // we just store it along with the remaining
260✔
866
                                // address bytes as type OpaqueAddrs. We need
260✔
867
                                // to hold onto the bytes so that we can still
260✔
868
                                // write them back to the wire when we
260✔
869
                                // propagate this message.
260✔
870
                                payloadLen := 1 + addrsLen - addrBytesRead
260✔
871
                                payload := make([]byte, payloadLen)
260✔
872

260✔
873
                                // First write a byte for the address type that
260✔
874
                                // we already read.
260✔
875
                                payload[0] = byte(aType)
260✔
876

260✔
877
                                // Now append the rest of the address bytes.
260✔
878
                                _, err := io.ReadFull(addrBuf, payload[1:])
260✔
879
                                if err != nil {
260✔
UNCOV
880
                                        return err
×
881
                                }
×
882

883
                                address = &OpaqueAddrs{
260✔
884
                                        Payload: payload,
260✔
885
                                }
260✔
886
                                addrBytesRead = addrsLen
260✔
887
                        }
888

889
                        addresses = append(addresses, address)
6,947✔
890
                }
891

892
                *e = addresses
504✔
893

894
        case *color.RGBA:
391✔
895
                err := ReadElements(r,
391✔
896
                        &e.R,
391✔
897
                        &e.G,
391✔
898
                        &e.B,
391✔
899
                )
391✔
900
                if err != nil {
393✔
901
                        return err
2✔
902
                }
2✔
903

904
        case *DeliveryAddress:
697✔
905
                var addrLen [2]byte
697✔
906
                if _, err = io.ReadFull(r, addrLen[:]); err != nil {
706✔
907
                        return err
9✔
908
                }
9✔
909
                length := binary.BigEndian.Uint16(addrLen[:])
688✔
910

688✔
911
                var addrBytes [deliveryAddressMaxSize]byte
688✔
912

688✔
913
                if length > deliveryAddressMaxSize {
793✔
914
                        return fmt.Errorf(
105✔
915
                                "cannot read %d bytes into addrBytes", length,
105✔
916
                        )
105✔
917
                }
105✔
918
                if _, err = io.ReadFull(r, addrBytes[:length]); err != nil {
584✔
919
                        return err
1✔
920
                }
1✔
921
                *e = addrBytes[:length]
582✔
922

923
        case *PartialSig:
123✔
924
                var sig PartialSig
123✔
925
                if err = sig.Decode(r); err != nil {
124✔
926
                        return err
1✔
927
                }
1✔
928
                *e = sig
122✔
929

930
        case *ExtraOpaqueData:
12,334✔
931
                return e.Decode(r)
12,334✔
932

UNCOV
933
        default:
×
UNCOV
934
                return fmt.Errorf("unknown type in ReadElement: %T", e)
×
935
        }
936

937
        return nil
86,361✔
938
}
939

940
// ReadElements deserializes a variable number of elements into the passed
941
// io.Reader, with each element being deserialized according to the ReadElement
942
// function.
943
func ReadElements(r io.Reader, elements ...interface{}) error {
36,316✔
944
        for _, element := range elements {
127,136✔
945
                err := ReadElement(r, element)
90,820✔
946
                if err != nil {
92,781✔
947
                        return err
1,961✔
948
                }
1,961✔
949
        }
950
        return nil
34,355✔
951
}
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