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

lightningnetwork / lnd / 15561477203

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

Pull #9356

github

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

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

28366 existing lines in 455 files now uncovered.

97715 of 167461 relevant lines covered (58.35%)

1.81 hits per line

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

45.0
/lnwire/lnwire.go
1
package lnwire
2

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

12
        "github.com/btcsuite/btcd/btcec/v2"
13
        "github.com/btcsuite/btcd/btcutil"
14
        "github.com/btcsuite/btcd/chaincfg/chainhash"
15
        "github.com/btcsuite/btcd/wire"
16
        "github.com/go-errors/errors"
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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

UNCOV
190
        case PartialSig:
×
UNCOV
191
                if err := e.Encode(w); err != nil {
×
192
                        return err
×
193
                }
×
194

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

202
                if _, err := w.Write(e[:]); err != nil {
×
203
                        return err
×
204
                }
×
205

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

213
                if _, err := w.Write(e[:]); err != nil {
×
214
                        return err
×
215
                }
×
216

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

224
                if _, err := w.Write(e[:]); err != nil {
×
225
                        return err
×
226
                }
×
227

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

235
                if _, err := w.Write(e[:]); err != nil {
×
236
                        return err
×
237
                }
×
238

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

246
                if _, err := w.Write(e[:]); err != nil {
×
247
                        return err
×
248
                }
×
249

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

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

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

268
                if err := wire.WriteVarBytes(w, 0, e); err != nil {
×
269
                        return err
×
270
                }
×
271

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

277
                if err := e.Encode(w); err != nil {
×
278
                        return err
×
279
                }
×
280

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

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

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

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

305
        case FailCode:
×
306
                if err := WriteElement(w, uint16(e)); err != nil {
×
307
                        return err
×
308
                }
×
309

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

316
                var blockHeight [4]byte
3✔
317
                binary.BigEndian.PutUint32(blockHeight[:], e.BlockHeight)
3✔
318

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

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

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

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

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

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

UNCOV
351
        case *OpaqueAddrs:
×
UNCOV
352
                if err := WriteOpaqueAddrs(w, e); err != nil {
×
353
                        return err
×
354
                }
×
355

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

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

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

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

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

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

406
        case ExtraOpaqueData:
×
407
                return e.Encode(w)
×
408

409
        default:
×
410
                return fmt.Errorf("unknown type in WriteElement: %T", e)
×
411
        }
412

413
        return nil
3✔
414
}
415

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

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

442
                if b[0] == 1 {
6✔
443
                        *e = true
3✔
444
                }
3✔
445

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

3✔
673
                *e = wire.OutPoint{
3✔
674
                        Hash:  *hash,
3✔
675
                        Index: uint32(index),
3✔
676
                }
3✔
677

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

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

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

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

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

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

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

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

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

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

741
                        addrBytesRead++
3✔
742

3✔
743
                        var address net.Addr
3✔
744
                        switch aType := addressType(descriptor[0]); aType {
3✔
UNCOV
745
                        case noAddr:
×
UNCOV
746
                                addrBytesRead += aType.AddrLen()
×
UNCOV
747
                                continue
×
748

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

755
                                var port [2]byte
3✔
756
                                if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
3✔
UNCOV
757
                                        return err
×
UNCOV
758
                                }
×
759

760
                                address = &net.TCPAddr{
3✔
761
                                        IP:   net.IP(ip[:]),
3✔
762
                                        Port: int(binary.BigEndian.Uint16(port[:])),
3✔
763
                                }
3✔
764
                                addrBytesRead += aType.AddrLen()
3✔
765

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

772
                                var port [2]byte
3✔
773
                                if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
3✔
UNCOV
774
                                        return err
×
UNCOV
775
                                }
×
776

777
                                address = &net.TCPAddr{
3✔
778
                                        IP:   net.IP(ip[:]),
3✔
779
                                        Port: int(binary.BigEndian.Uint16(port[:])),
3✔
780
                                }
3✔
781
                                addrBytesRead += aType.AddrLen()
3✔
782

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

789
                                var p [2]byte
3✔
790
                                if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
3✔
UNCOV
791
                                        return err
×
UNCOV
792
                                }
×
793

794
                                onionService := tor.Base32Encoding.EncodeToString(h[:])
3✔
795
                                onionService += tor.OnionSuffix
3✔
796
                                port := int(binary.BigEndian.Uint16(p[:]))
3✔
797

3✔
798
                                address = &tor.OnionAddr{
3✔
799
                                        OnionService: onionService,
3✔
800
                                        Port:         port,
3✔
801
                                }
3✔
802
                                addrBytesRead += aType.AddrLen()
3✔
803

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

810
                                var p [2]byte
3✔
811
                                if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
3✔
UNCOV
812
                                        return err
×
UNCOV
813
                                }
×
814

815
                                onionService := tor.Base32Encoding.EncodeToString(h[:])
3✔
816
                                onionService += tor.OnionSuffix
3✔
817
                                port := int(binary.BigEndian.Uint16(p[:]))
3✔
818

3✔
819
                                address = &tor.OnionAddr{
3✔
820
                                        OnionService: onionService,
3✔
821
                                        Port:         port,
3✔
822
                                }
3✔
823
                                addrBytesRead += aType.AddrLen()
3✔
824

UNCOV
825
                        default:
×
UNCOV
826
                                // If we don't understand this address type,
×
UNCOV
827
                                // we just store it along with the remaining
×
UNCOV
828
                                // address bytes as type OpaqueAddrs. We need
×
UNCOV
829
                                // to hold onto the bytes so that we can still
×
UNCOV
830
                                // write them back to the wire when we
×
UNCOV
831
                                // propagate this message.
×
UNCOV
832
                                payloadLen := 1 + addrsLen - addrBytesRead
×
UNCOV
833
                                payload := make([]byte, payloadLen)
×
UNCOV
834

×
UNCOV
835
                                // First write a byte for the address type that
×
UNCOV
836
                                // we already read.
×
UNCOV
837
                                payload[0] = byte(aType)
×
UNCOV
838

×
UNCOV
839
                                // Now append the rest of the address bytes.
×
UNCOV
840
                                _, err := io.ReadFull(addrBuf, payload[1:])
×
UNCOV
841
                                if err != nil {
×
842
                                        return err
×
843
                                }
×
844

UNCOV
845
                                address = &OpaqueAddrs{
×
UNCOV
846
                                        Payload: payload,
×
UNCOV
847
                                }
×
UNCOV
848
                                addrBytesRead = addrsLen
×
849
                        }
850

851
                        addresses = append(addresses, address)
3✔
852
                }
853

854
                *e = addresses
3✔
855

856
        case *color.RGBA:
3✔
857
                err := ReadElements(r,
3✔
858
                        &e.R,
3✔
859
                        &e.G,
3✔
860
                        &e.B,
3✔
861
                )
3✔
862
                if err != nil {
3✔
UNCOV
863
                        return err
×
UNCOV
864
                }
×
865

866
        case *DeliveryAddress:
3✔
867
                var addrLen [2]byte
3✔
868
                if _, err = io.ReadFull(r, addrLen[:]); err != nil {
3✔
UNCOV
869
                        return err
×
UNCOV
870
                }
×
871
                length := binary.BigEndian.Uint16(addrLen[:])
3✔
872

3✔
873
                var addrBytes [deliveryAddressMaxSize]byte
3✔
874

3✔
875
                if length > deliveryAddressMaxSize {
3✔
UNCOV
876
                        return fmt.Errorf(
×
UNCOV
877
                                "cannot read %d bytes into addrBytes", length,
×
UNCOV
878
                        )
×
UNCOV
879
                }
×
880
                if _, err = io.ReadFull(r, addrBytes[:length]); err != nil {
3✔
UNCOV
881
                        return err
×
UNCOV
882
                }
×
883
                *e = addrBytes[:length]
3✔
884

UNCOV
885
        case *PartialSig:
×
UNCOV
886
                var sig PartialSig
×
UNCOV
887
                if err = sig.Decode(r); err != nil {
×
UNCOV
888
                        return err
×
UNCOV
889
                }
×
UNCOV
890
                *e = sig
×
891

892
        case *ExtraOpaqueData:
3✔
893
                return e.Decode(r)
3✔
894

895
        default:
×
896
                return fmt.Errorf("unknown type in ReadElement: %T", e)
×
897
        }
898

899
        return nil
3✔
900
}
901

902
// ReadElements deserializes a variable number of elements into the passed
903
// io.Reader, with each element being deserialized according to the ReadElement
904
// function.
905
func ReadElements(r io.Reader, elements ...interface{}) error {
3✔
906
        for _, element := range elements {
6✔
907
                err := ReadElement(r, element)
3✔
908
                if err != nil {
3✔
UNCOV
909
                        return err
×
UNCOV
910
                }
×
911
        }
912
        return nil
3✔
913
}
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