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

lightningnetwork / lnd / 13211764208

08 Feb 2025 03:08AM UTC coverage: 49.288% (-9.5%) from 58.815%
13211764208

Pull #9489

github

calvinrzachman
itest: verify switchrpc server enforces send then track

We prevent the rpc server from allowing onion dispatches for
attempt IDs which have already been tracked by rpc clients.

This helps protect the client from leaking a duplicate onion
attempt. NOTE: This is not the only method for solving this
issue! The issue could be addressed via careful client side
programming which accounts for the uncertainty and async
nature of dispatching onions to a remote process via RPC.
This would require some lnd ChannelRouter changes for how
we intend to use these RPCs though.
Pull Request #9489: multi: add BuildOnion, SendOnion, and TrackOnion RPCs

474 of 990 new or added lines in 11 files covered. (47.88%)

27321 existing lines in 435 files now uncovered.

101192 of 205306 relevant lines covered (49.29%)

1.54 hits per line

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

46.48
/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 e == nil {
3✔
343
                        return fmt.Errorf("cannot write nil TCPAddr")
×
344
                }
×
345

346
                if e.IP.To4() != nil {
6✔
347
                        var descriptor [1]byte
3✔
348
                        descriptor[0] = uint8(tcp4Addr)
3✔
349
                        if _, err := w.Write(descriptor[:]); err != nil {
3✔
350
                                return err
×
351
                        }
×
352

353
                        var ip [4]byte
3✔
354
                        copy(ip[:], e.IP.To4())
3✔
355
                        if _, err := w.Write(ip[:]); err != nil {
3✔
356
                                return err
×
357
                        }
×
358
                } else {
3✔
359
                        var descriptor [1]byte
3✔
360
                        descriptor[0] = uint8(tcp6Addr)
3✔
361
                        if _, err := w.Write(descriptor[:]); err != nil {
3✔
362
                                return err
×
363
                        }
×
364
                        var ip [16]byte
3✔
365
                        copy(ip[:], e.IP.To16())
3✔
366
                        if _, err := w.Write(ip[:]); err != nil {
3✔
367
                                return err
×
368
                        }
×
369
                }
370
                var port [2]byte
3✔
371
                binary.BigEndian.PutUint16(port[:], uint16(e.Port))
3✔
372
                if _, err := w.Write(port[:]); err != nil {
3✔
373
                        return err
×
374
                }
×
375

376
        case *tor.OnionAddr:
3✔
377
                if e == nil {
3✔
378
                        return errors.New("cannot write nil onion address")
×
379
                }
×
380

381
                var suffixIndex int
3✔
382
                switch len(e.OnionService) {
3✔
383
                case tor.V2Len:
3✔
384
                        descriptor := []byte{byte(v2OnionAddr)}
3✔
385
                        if _, err := w.Write(descriptor); err != nil {
3✔
386
                                return err
×
387
                        }
×
388
                        suffixIndex = tor.V2Len - tor.OnionSuffixLen
3✔
389
                case tor.V3Len:
3✔
390
                        descriptor := []byte{byte(v3OnionAddr)}
3✔
391
                        if _, err := w.Write(descriptor); err != nil {
3✔
392
                                return err
×
393
                        }
×
394
                        suffixIndex = tor.V3Len - tor.OnionSuffixLen
3✔
395
                default:
×
396
                        return errors.New("unknown onion service length")
×
397
                }
398

399
                host, err := tor.Base32Encoding.DecodeString(
3✔
400
                        e.OnionService[:suffixIndex],
3✔
401
                )
3✔
402
                if err != nil {
3✔
403
                        return err
×
404
                }
×
405
                if _, err := w.Write(host); err != nil {
3✔
406
                        return err
×
407
                }
×
408

409
                var port [2]byte
3✔
410
                binary.BigEndian.PutUint16(port[:], uint16(e.Port))
3✔
411
                if _, err := w.Write(port[:]); err != nil {
3✔
412
                        return err
×
413
                }
×
414

415
        case []net.Addr:
3✔
416
                // First, we'll encode all the addresses into an intermediate
3✔
417
                // buffer. We need to do this in order to compute the total
3✔
418
                // length of the addresses.
3✔
419
                var addrBuf bytes.Buffer
3✔
420
                for _, address := range e {
6✔
421
                        if err := WriteElement(&addrBuf, address); err != nil {
3✔
422
                                return err
×
423
                        }
×
424
                }
425

426
                // With the addresses fully encoded, we can now write out the
427
                // number of bytes needed to encode them.
428
                addrLen := addrBuf.Len()
3✔
429
                if err := WriteElement(w, uint16(addrLen)); err != nil {
3✔
430
                        return err
×
431
                }
×
432

433
                // Finally, we'll write out the raw addresses themselves, but
434
                // only if we have any bytes to write.
435
                if addrLen > 0 {
6✔
436
                        if _, err := w.Write(addrBuf.Bytes()); err != nil {
3✔
437
                                return err
×
438
                        }
×
439
                }
440

441
        case color.RGBA:
×
442
                if err := WriteElements(w, e.R, e.G, e.B); err != nil {
×
443
                        return err
×
444
                }
×
445

446
        case DeliveryAddress:
×
447
                var length [2]byte
×
448
                binary.BigEndian.PutUint16(length[:], uint16(len(e)))
×
449
                if _, err := w.Write(length[:]); err != nil {
×
450
                        return err
×
451
                }
×
452
                if _, err := w.Write(e[:]); err != nil {
×
453
                        return err
×
454
                }
×
455

456
        case bool:
3✔
457
                var b [1]byte
3✔
458
                if e {
6✔
459
                        b[0] = 1
3✔
460
                }
3✔
461
                if _, err := w.Write(b[:]); err != nil {
3✔
462
                        return err
×
463
                }
×
464

465
        case ExtraOpaqueData:
×
466
                return e.Encode(w)
×
467

468
        default:
×
469
                return fmt.Errorf("unknown type in WriteElement: %T", e)
×
470
        }
471

472
        return nil
3✔
473
}
474

475
// WriteElements is writes each element in the elements slice to the passed
476
// buffer using WriteElement.
477
//
478
// TODO(yy): rm this method once we finish dereferencing it from other
479
// packages.
480
func WriteElements(buf *bytes.Buffer, elements ...interface{}) error {
3✔
481
        for _, element := range elements {
6✔
482
                err := WriteElement(buf, element)
3✔
483
                if err != nil {
3✔
484
                        return err
×
485
                }
×
486
        }
487
        return nil
3✔
488
}
489

490
// ReadElement is a one-stop utility function to deserialize any datastructure
491
// encoded using the serialization format of lnwire.
492
func ReadElement(r io.Reader, element interface{}) error {
3✔
493
        var err error
3✔
494
        switch e := element.(type) {
3✔
495
        case *bool:
3✔
496
                var b [1]byte
3✔
497
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
498
                        return err
×
UNCOV
499
                }
×
500

501
                if b[0] == 1 {
6✔
502
                        *e = true
3✔
503
                }
3✔
504

505
        case *NodeAlias:
3✔
506
                var a [32]byte
3✔
507
                if _, err := io.ReadFull(r, a[:]); err != nil {
3✔
UNCOV
508
                        return err
×
UNCOV
509
                }
×
510

511
                alias, err := NewNodeAlias(string(a[:]))
3✔
512
                if err != nil {
3✔
UNCOV
513
                        return err
×
UNCOV
514
                }
×
515
                *e = alias
3✔
516

517
        case *QueryEncoding:
×
518
                var b [1]uint8
×
519
                if _, err := r.Read(b[:]); err != nil {
×
520
                        return err
×
521
                }
×
522
                *e = QueryEncoding(b[0])
×
523

524
        case *uint8:
3✔
525
                var b [1]uint8
3✔
526
                if _, err := r.Read(b[:]); err != nil {
3✔
UNCOV
527
                        return err
×
UNCOV
528
                }
×
529
                *e = b[0]
3✔
530

531
        case *FundingFlag:
3✔
532
                var b [1]uint8
3✔
533
                if _, err := r.Read(b[:]); err != nil {
3✔
UNCOV
534
                        return err
×
UNCOV
535
                }
×
536
                *e = FundingFlag(b[0])
3✔
537

538
        case *uint16:
3✔
539
                var b [2]byte
3✔
540
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
541
                        return err
×
UNCOV
542
                }
×
543
                *e = binary.BigEndian.Uint16(b[:])
3✔
544

545
        case *ChanUpdateMsgFlags:
3✔
546
                var b [1]uint8
3✔
547
                if _, err := r.Read(b[:]); err != nil {
3✔
UNCOV
548
                        return err
×
UNCOV
549
                }
×
550
                *e = ChanUpdateMsgFlags(b[0])
3✔
551

552
        case *ChanUpdateChanFlags:
3✔
553
                var b [1]uint8
3✔
554
                if _, err := r.Read(b[:]); err != nil {
3✔
UNCOV
555
                        return err
×
UNCOV
556
                }
×
557
                *e = ChanUpdateChanFlags(b[0])
3✔
558

559
        case *uint32:
3✔
560
                var b [4]byte
3✔
561
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
562
                        return err
×
UNCOV
563
                }
×
564
                *e = binary.BigEndian.Uint32(b[:])
3✔
565

566
        case *uint64:
3✔
567
                var b [8]byte
3✔
568
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
569
                        return err
×
UNCOV
570
                }
×
571
                *e = binary.BigEndian.Uint64(b[:])
3✔
572

573
        case *MilliSatoshi:
3✔
574
                var b [8]byte
3✔
575
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
576
                        return err
×
UNCOV
577
                }
×
578
                *e = MilliSatoshi(int64(binary.BigEndian.Uint64(b[:])))
3✔
579

580
        case *btcutil.Amount:
3✔
581
                var b [8]byte
3✔
582
                if _, err := io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
583
                        return err
×
UNCOV
584
                }
×
585
                *e = btcutil.Amount(int64(binary.BigEndian.Uint64(b[:])))
3✔
586

587
        case **btcec.PublicKey:
3✔
588
                var b [btcec.PubKeyBytesLenCompressed]byte
3✔
589
                if _, err = io.ReadFull(r, b[:]); err != nil {
3✔
UNCOV
590
                        return err
×
UNCOV
591
                }
×
592

593
                pubKey, err := btcec.ParsePubKey(b[:])
3✔
594
                if err != nil {
3✔
UNCOV
595
                        return err
×
UNCOV
596
                }
×
597
                *e = pubKey
3✔
598

UNCOV
599
        case *RawFeatureVector:
×
UNCOV
600
                f := NewRawFeatureVector()
×
UNCOV
601
                err = f.Decode(r)
×
UNCOV
602
                if err != nil {
×
UNCOV
603
                        return err
×
UNCOV
604
                }
×
UNCOV
605
                *e = *f
×
606

607
        case **RawFeatureVector:
3✔
608
                f := NewRawFeatureVector()
3✔
609
                err = f.Decode(r)
3✔
610
                if err != nil {
3✔
UNCOV
611
                        return err
×
UNCOV
612
                }
×
613
                *e = f
3✔
614

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

3✔
622
                var sigs []Sig
3✔
623
                if numSigs > 0 {
6✔
624
                        sigs = make([]Sig, numSigs)
3✔
625
                        for i := 0; i < int(numSigs); i++ {
6✔
626
                                if err := ReadElement(r, &sigs[i]); err != nil {
3✔
UNCOV
627
                                        return err
×
UNCOV
628
                                }
×
629
                        }
630
                }
631
                *e = sigs
3✔
632

633
        case *Sig:
3✔
634
                if _, err := io.ReadFull(r, e.bytes[:]); err != nil {
3✔
UNCOV
635
                        return err
×
UNCOV
636
                }
×
637

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

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

UNCOV
650
        case *WarningData:
×
UNCOV
651
                var l [2]byte
×
UNCOV
652
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
UNCOV
653
                        return err
×
UNCOV
654
                }
×
UNCOV
655
                errorLen := binary.BigEndian.Uint16(l[:])
×
UNCOV
656

×
UNCOV
657
                *e = WarningData(make([]byte, errorLen))
×
UNCOV
658
                if _, err := io.ReadFull(r, *e); err != nil {
×
UNCOV
659
                        return err
×
UNCOV
660
                }
×
661

662
        case *ErrorData:
3✔
663
                var l [2]byte
3✔
664
                if _, err := io.ReadFull(r, l[:]); err != nil {
3✔
UNCOV
665
                        return err
×
UNCOV
666
                }
×
667
                errorLen := binary.BigEndian.Uint16(l[:])
3✔
668

3✔
669
                *e = ErrorData(make([]byte, errorLen))
3✔
670
                if _, err := io.ReadFull(r, *e); err != nil {
3✔
UNCOV
671
                        return err
×
UNCOV
672
                }
×
673

UNCOV
674
        case *PingPayload:
×
UNCOV
675
                var l [2]byte
×
UNCOV
676
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
UNCOV
677
                        return err
×
UNCOV
678
                }
×
UNCOV
679
                pingLen := binary.BigEndian.Uint16(l[:])
×
UNCOV
680

×
UNCOV
681
                *e = PingPayload(make([]byte, pingLen))
×
UNCOV
682
                if _, err := io.ReadFull(r, *e); err != nil {
×
UNCOV
683
                        return err
×
UNCOV
684
                }
×
685

UNCOV
686
        case *PongPayload:
×
UNCOV
687
                var l [2]byte
×
UNCOV
688
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
UNCOV
689
                        return err
×
UNCOV
690
                }
×
UNCOV
691
                pongLen := binary.BigEndian.Uint16(l[:])
×
UNCOV
692

×
UNCOV
693
                *e = PongPayload(make([]byte, pongLen))
×
UNCOV
694
                if _, err := io.ReadFull(r, *e); err != nil {
×
UNCOV
695
                        return err
×
UNCOV
696
                }
×
697

698
        case *[33]byte:
3✔
699
                if _, err := io.ReadFull(r, e[:]); err != nil {
3✔
UNCOV
700
                        return err
×
UNCOV
701
                }
×
702

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

708
        case *PkScript:
×
709
                pkScript, err := wire.ReadVarBytes(r, 0, 34, "pkscript")
×
710
                if err != nil {
×
711
                        return err
×
712
                }
×
713
                *e = pkScript
×
714

715
        case *wire.OutPoint:
3✔
716
                var h [32]byte
3✔
717
                if _, err = io.ReadFull(r, h[:]); err != nil {
3✔
UNCOV
718
                        return err
×
UNCOV
719
                }
×
720
                hash, err := chainhash.NewHash(h[:])
3✔
721
                if err != nil {
3✔
722
                        return err
×
723
                }
×
724

725
                var idxBytes [2]byte
3✔
726
                _, err = io.ReadFull(r, idxBytes[:])
3✔
727
                if err != nil {
3✔
UNCOV
728
                        return err
×
UNCOV
729
                }
×
730
                index := binary.BigEndian.Uint16(idxBytes[:])
3✔
731

3✔
732
                *e = wire.OutPoint{
3✔
733
                        Hash:  *hash,
3✔
734
                        Index: uint32(index),
3✔
735
                }
3✔
736

737
        case *FailCode:
3✔
738
                if err := ReadElement(r, (*uint16)(e)); err != nil {
3✔
UNCOV
739
                        return err
×
UNCOV
740
                }
×
741

742
        case *ChannelID:
3✔
743
                if _, err := io.ReadFull(r, e[:]); err != nil {
3✔
UNCOV
744
                        return err
×
UNCOV
745
                }
×
746

747
        case *ShortChannelID:
3✔
748
                var blockHeight [4]byte
3✔
749
                if _, err = io.ReadFull(r, blockHeight[1:]); err != nil {
3✔
UNCOV
750
                        return err
×
UNCOV
751
                }
×
752

753
                var txIndex [4]byte
3✔
754
                if _, err = io.ReadFull(r, txIndex[1:]); err != nil {
3✔
UNCOV
755
                        return err
×
UNCOV
756
                }
×
757

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

763
                *e = ShortChannelID{
3✔
764
                        BlockHeight: binary.BigEndian.Uint32(blockHeight[:]),
3✔
765
                        TxIndex:     binary.BigEndian.Uint32(txIndex[:]),
3✔
766
                        TxPosition:  binary.BigEndian.Uint16(txPosition[:]),
3✔
767
                }
3✔
768

769
        case *[]net.Addr:
3✔
770
                // First, we'll read the number of total bytes that have been
3✔
771
                // used to encode the set of addresses.
3✔
772
                var numAddrsBytes [2]byte
3✔
773
                if _, err = io.ReadFull(r, numAddrsBytes[:]); err != nil {
3✔
UNCOV
774
                        return err
×
UNCOV
775
                }
×
776
                addrsLen := binary.BigEndian.Uint16(numAddrsBytes[:])
3✔
777

3✔
778
                // With the number of addresses, read, we'll now pull in the
3✔
779
                // buffer of the encoded addresses into memory.
3✔
780
                addrs := make([]byte, addrsLen)
3✔
781
                if _, err := io.ReadFull(r, addrs[:]); err != nil {
3✔
UNCOV
782
                        return err
×
UNCOV
783
                }
×
784
                addrBuf := bytes.NewReader(addrs)
3✔
785

3✔
786
                // Finally, we'll parse the remaining address payload in
3✔
787
                // series, using the first byte to denote how to decode the
3✔
788
                // address itself.
3✔
789
                var (
3✔
790
                        addresses     []net.Addr
3✔
791
                        addrBytesRead uint16
3✔
792
                )
3✔
793

3✔
794
                for addrBytesRead < addrsLen {
6✔
795
                        var descriptor [1]byte
3✔
796
                        if _, err = io.ReadFull(addrBuf, descriptor[:]); err != nil {
3✔
797
                                return err
×
798
                        }
×
799

800
                        addrBytesRead++
3✔
801

3✔
802
                        var address net.Addr
3✔
803
                        switch aType := addressType(descriptor[0]); aType {
3✔
UNCOV
804
                        case noAddr:
×
UNCOV
805
                                addrBytesRead += aType.AddrLen()
×
UNCOV
806
                                continue
×
807

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

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

819
                                address = &net.TCPAddr{
3✔
820
                                        IP:   net.IP(ip[:]),
3✔
821
                                        Port: int(binary.BigEndian.Uint16(port[:])),
3✔
822
                                }
3✔
823
                                addrBytesRead += aType.AddrLen()
3✔
824

825
                        case tcp6Addr:
3✔
826
                                var ip [16]byte
3✔
827
                                if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
3✔
UNCOV
828
                                        return err
×
UNCOV
829
                                }
×
830

831
                                var port [2]byte
3✔
832
                                if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
3✔
UNCOV
833
                                        return err
×
UNCOV
834
                                }
×
835

836
                                address = &net.TCPAddr{
3✔
837
                                        IP:   net.IP(ip[:]),
3✔
838
                                        Port: int(binary.BigEndian.Uint16(port[:])),
3✔
839
                                }
3✔
840
                                addrBytesRead += aType.AddrLen()
3✔
841

842
                        case v2OnionAddr:
3✔
843
                                var h [tor.V2DecodedLen]byte
3✔
844
                                if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
3✔
UNCOV
845
                                        return err
×
UNCOV
846
                                }
×
847

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

853
                                onionService := tor.Base32Encoding.EncodeToString(h[:])
3✔
854
                                onionService += tor.OnionSuffix
3✔
855
                                port := int(binary.BigEndian.Uint16(p[:]))
3✔
856

3✔
857
                                address = &tor.OnionAddr{
3✔
858
                                        OnionService: onionService,
3✔
859
                                        Port:         port,
3✔
860
                                }
3✔
861
                                addrBytesRead += aType.AddrLen()
3✔
862

863
                        case v3OnionAddr:
3✔
864
                                var h [tor.V3DecodedLen]byte
3✔
865
                                if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
3✔
UNCOV
866
                                        return err
×
UNCOV
867
                                }
×
868

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

874
                                onionService := tor.Base32Encoding.EncodeToString(h[:])
3✔
875
                                onionService += tor.OnionSuffix
3✔
876
                                port := int(binary.BigEndian.Uint16(p[:]))
3✔
877

3✔
878
                                address = &tor.OnionAddr{
3✔
879
                                        OnionService: onionService,
3✔
880
                                        Port:         port,
3✔
881
                                }
3✔
882
                                addrBytesRead += aType.AddrLen()
3✔
883

UNCOV
884
                        default:
×
UNCOV
885
                                // If we don't understand this address type,
×
UNCOV
886
                                // we just store it along with the remaining
×
UNCOV
887
                                // address bytes as type OpaqueAddrs. We need
×
UNCOV
888
                                // to hold onto the bytes so that we can still
×
UNCOV
889
                                // write them back to the wire when we
×
UNCOV
890
                                // propagate this message.
×
UNCOV
891
                                payloadLen := 1 + addrsLen - addrBytesRead
×
UNCOV
892
                                payload := make([]byte, payloadLen)
×
UNCOV
893

×
UNCOV
894
                                // First write a byte for the address type that
×
UNCOV
895
                                // we already read.
×
UNCOV
896
                                payload[0] = byte(aType)
×
UNCOV
897

×
UNCOV
898
                                // Now append the rest of the address bytes.
×
UNCOV
899
                                _, err := io.ReadFull(addrBuf, payload[1:])
×
UNCOV
900
                                if err != nil {
×
901
                                        return err
×
902
                                }
×
903

UNCOV
904
                                address = &OpaqueAddrs{
×
UNCOV
905
                                        Payload: payload,
×
UNCOV
906
                                }
×
UNCOV
907
                                addrBytesRead = addrsLen
×
908
                        }
909

910
                        addresses = append(addresses, address)
3✔
911
                }
912

913
                *e = addresses
3✔
914

915
        case *color.RGBA:
3✔
916
                err := ReadElements(r,
3✔
917
                        &e.R,
3✔
918
                        &e.G,
3✔
919
                        &e.B,
3✔
920
                )
3✔
921
                if err != nil {
3✔
UNCOV
922
                        return err
×
UNCOV
923
                }
×
924

925
        case *DeliveryAddress:
3✔
926
                var addrLen [2]byte
3✔
927
                if _, err = io.ReadFull(r, addrLen[:]); err != nil {
3✔
UNCOV
928
                        return err
×
UNCOV
929
                }
×
930
                length := binary.BigEndian.Uint16(addrLen[:])
3✔
931

3✔
932
                var addrBytes [deliveryAddressMaxSize]byte
3✔
933

3✔
934
                if length > deliveryAddressMaxSize {
3✔
UNCOV
935
                        return fmt.Errorf(
×
UNCOV
936
                                "cannot read %d bytes into addrBytes", length,
×
UNCOV
937
                        )
×
UNCOV
938
                }
×
939
                if _, err = io.ReadFull(r, addrBytes[:length]); err != nil {
3✔
UNCOV
940
                        return err
×
UNCOV
941
                }
×
942
                *e = addrBytes[:length]
3✔
943

UNCOV
944
        case *PartialSig:
×
UNCOV
945
                var sig PartialSig
×
UNCOV
946
                if err = sig.Decode(r); err != nil {
×
UNCOV
947
                        return err
×
UNCOV
948
                }
×
UNCOV
949
                *e = sig
×
950

951
        case *ExtraOpaqueData:
3✔
952
                return e.Decode(r)
3✔
953

954
        default:
×
955
                return fmt.Errorf("unknown type in ReadElement: %T", e)
×
956
        }
957

958
        return nil
3✔
959
}
960

961
// ReadElements deserializes a variable number of elements into the passed
962
// io.Reader, with each element being deserialized according to the ReadElement
963
// function.
964
func ReadElements(r io.Reader, elements ...interface{}) error {
3✔
965
        for _, element := range elements {
6✔
966
                err := ReadElement(r, element)
3✔
967
                if err != nil {
3✔
UNCOV
968
                        return err
×
UNCOV
969
                }
×
970
        }
971
        return nil
3✔
972
}
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