• 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

0.0
/channeldb/migration/lnwire21/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
// MaxSliceLength is the maximum allowed length for any opaque byte slices in
21
// the wire protocol.
22
const MaxSliceLength = 65535
23

24
// PkScript is simple type definition which represents a raw serialized public
25
// key script.
26
type PkScript []byte
27

28
// addressType specifies the network protocol and version that should be used
29
// when connecting to a node at a particular address.
30
type addressType uint8
31

32
const (
33
        // noAddr denotes a blank address. An address of this type indicates
34
        // that a node doesn't have any advertised addresses.
35
        noAddr addressType = 0
36

37
        // tcp4Addr denotes an IPv4 TCP address.
38
        tcp4Addr addressType = 1
39

40
        // tcp6Addr denotes an IPv6 TCP address.
41
        tcp6Addr addressType = 2
42

43
        // v2OnionAddr denotes a version 2 Tor onion service address.
44
        v2OnionAddr addressType = 3
45

46
        // v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
47
        v3OnionAddr addressType = 4
48
)
49

50
// AddrLen returns the number of bytes that it takes to encode the target
51
// address.
52
func (a addressType) AddrLen() uint16 {
×
53
        switch a {
×
54
        case noAddr:
×
55
                return 0
×
56
        case tcp4Addr:
×
57
                return 6
×
58
        case tcp6Addr:
×
59
                return 18
×
60
        case v2OnionAddr:
×
61
                return 12
×
62
        case v3OnionAddr:
×
63
                return 37
×
64
        default:
×
65
                return 0
×
66
        }
67
}
68

69
// WriteElement is a one-stop shop to write the big endian representation of
70
// any element which is to be serialized for the wire protocol. The passed
71
// io.Writer should be backed by an appropriately sized byte slice, or be able
72
// to dynamically expand to accommodate additional data.
73
//
74
// TODO(roasbeef): this should eventually draw from a buffer pool for
75
// serialization.
UNCOV
76
func WriteElement(w io.Writer, element interface{}) error {
×
UNCOV
77
        switch e := element.(type) {
×
78
        case NodeAlias:
×
79
                if _, err := w.Write(e[:]); err != nil {
×
80
                        return err
×
81
                }
×
82

83
        case ShortChanIDEncoding:
×
84
                var b [1]byte
×
85
                b[0] = uint8(e)
×
86
                if _, err := w.Write(b[:]); err != nil {
×
87
                        return err
×
88
                }
×
89
        case uint8:
×
90
                var b [1]byte
×
91
                b[0] = e
×
92
                if _, err := w.Write(b[:]); err != nil {
×
93
                        return err
×
94
                }
×
95
        case FundingFlag:
×
96
                var b [1]byte
×
97
                b[0] = uint8(e)
×
98
                if _, err := w.Write(b[:]); err != nil {
×
99
                        return err
×
100
                }
×
UNCOV
101
        case uint16:
×
UNCOV
102
                var b [2]byte
×
UNCOV
103
                binary.BigEndian.PutUint16(b[:], e)
×
UNCOV
104
                if _, err := w.Write(b[:]); err != nil {
×
105
                        return err
×
106
                }
×
UNCOV
107
        case ChanUpdateMsgFlags:
×
UNCOV
108
                var b [1]byte
×
UNCOV
109
                b[0] = uint8(e)
×
UNCOV
110
                if _, err := w.Write(b[:]); err != nil {
×
111
                        return err
×
112
                }
×
UNCOV
113
        case ChanUpdateChanFlags:
×
UNCOV
114
                var b [1]byte
×
UNCOV
115
                b[0] = uint8(e)
×
UNCOV
116
                if _, err := w.Write(b[:]); err != nil {
×
117
                        return err
×
118
                }
×
UNCOV
119
        case MilliSatoshi:
×
UNCOV
120
                var b [8]byte
×
UNCOV
121
                binary.BigEndian.PutUint64(b[:], uint64(e))
×
UNCOV
122
                if _, err := w.Write(b[:]); err != nil {
×
123
                        return err
×
124
                }
×
125
        case btcutil.Amount:
×
126
                var b [8]byte
×
127
                binary.BigEndian.PutUint64(b[:], uint64(e))
×
128
                if _, err := w.Write(b[:]); err != nil {
×
129
                        return err
×
130
                }
×
UNCOV
131
        case uint32:
×
UNCOV
132
                var b [4]byte
×
UNCOV
133
                binary.BigEndian.PutUint32(b[:], e)
×
UNCOV
134
                if _, err := w.Write(b[:]); err != nil {
×
135
                        return err
×
136
                }
×
UNCOV
137
        case uint64:
×
UNCOV
138
                var b [8]byte
×
UNCOV
139
                binary.BigEndian.PutUint64(b[:], e)
×
UNCOV
140
                if _, err := w.Write(b[:]); err != nil {
×
141
                        return err
×
142
                }
×
UNCOV
143
        case *btcec.PublicKey:
×
UNCOV
144
                if e == nil {
×
145
                        return fmt.Errorf("cannot write nil pubkey")
×
146
                }
×
147

UNCOV
148
                var b [33]byte
×
UNCOV
149
                serializedPubkey := e.SerializeCompressed()
×
UNCOV
150
                copy(b[:], serializedPubkey)
×
UNCOV
151
                if _, err := w.Write(b[:]); err != nil {
×
152
                        return err
×
153
                }
×
UNCOV
154
        case []Sig:
×
UNCOV
155
                var b [2]byte
×
UNCOV
156
                numSigs := uint16(len(e))
×
UNCOV
157
                binary.BigEndian.PutUint16(b[:], numSigs)
×
UNCOV
158
                if _, err := w.Write(b[:]); err != nil {
×
159
                        return err
×
160
                }
×
161

UNCOV
162
                for _, sig := range e {
×
UNCOV
163
                        if err := WriteElement(w, sig); err != nil {
×
164
                                return err
×
165
                        }
×
166
                }
UNCOV
167
        case Sig:
×
UNCOV
168
                // Write buffer
×
UNCOV
169
                if _, err := w.Write(e[:]); err != nil {
×
170
                        return err
×
171
                }
×
172
        case PingPayload:
×
173
                var l [2]byte
×
174
                binary.BigEndian.PutUint16(l[:], uint16(len(e)))
×
175
                if _, err := w.Write(l[:]); err != nil {
×
176
                        return err
×
177
                }
×
178

179
                if _, err := w.Write(e[:]); err != nil {
×
180
                        return err
×
181
                }
×
182
        case PongPayload:
×
183
                var l [2]byte
×
184
                binary.BigEndian.PutUint16(l[:], uint16(len(e)))
×
185
                if _, err := w.Write(l[:]); err != nil {
×
186
                        return err
×
187
                }
×
188

189
                if _, err := w.Write(e[:]); err != nil {
×
190
                        return err
×
191
                }
×
192
        case ErrorData:
×
193
                var l [2]byte
×
194
                binary.BigEndian.PutUint16(l[:], uint16(len(e)))
×
195
                if _, err := w.Write(l[:]); err != nil {
×
196
                        return err
×
197
                }
×
198

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

UNCOV
209
                if _, err := w.Write(e[:]); err != nil {
×
210
                        return err
×
211
                }
×
212
        case [33]byte:
×
213
                if _, err := w.Write(e[:]); err != nil {
×
214
                        return err
×
215
                }
×
UNCOV
216
        case []byte:
×
UNCOV
217
                if _, err := w.Write(e[:]); err != nil {
×
218
                        return err
×
219
                }
×
220
        case PkScript:
×
221
                // The largest script we'll accept is a p2wsh which is exactly
×
222
                // 34 bytes long.
×
223
                scriptLength := len(e)
×
224
                if scriptLength > 34 {
×
225
                        return fmt.Errorf("'PkScript' too long")
×
226
                }
×
227

228
                if err := wire.WriteVarBytes(w, 0, e); err != nil {
×
229
                        return err
×
230
                }
×
231
        case *RawFeatureVector:
×
232
                if e == nil {
×
233
                        return fmt.Errorf("cannot write nil feature vector")
×
234
                }
×
235

236
                if err := e.Encode(w); err != nil {
×
237
                        return err
×
238
                }
×
239

240
        case wire.OutPoint:
×
241
                var h [32]byte
×
242
                copy(h[:], e.Hash[:])
×
243
                if _, err := w.Write(h[:]); err != nil {
×
244
                        return err
×
245
                }
×
246

247
                if e.Index > math.MaxUint16 {
×
248
                        return fmt.Errorf("index for outpoint (%v) is "+
×
249
                                "greater than max index of %v", e.Index,
×
250
                                math.MaxUint16)
×
251
                }
×
252

253
                var idx [2]byte
×
254
                binary.BigEndian.PutUint16(idx[:], uint16(e.Index))
×
255
                if _, err := w.Write(idx[:]); err != nil {
×
256
                        return err
×
257
                }
×
258

UNCOV
259
        case ChannelID:
×
UNCOV
260
                if _, err := w.Write(e[:]); err != nil {
×
261
                        return err
×
262
                }
×
263
        case FailCode:
×
264
                if err := WriteElement(w, uint16(e)); err != nil {
×
265
                        return err
×
266
                }
×
UNCOV
267
        case ShortChannelID:
×
UNCOV
268
                // Check that field fit in 3 bytes and write the blockHeight
×
UNCOV
269
                if e.BlockHeight > ((1 << 24) - 1) {
×
270
                        return errors.New("block height should fit in 3 bytes")
×
271
                }
×
272

UNCOV
273
                var blockHeight [4]byte
×
UNCOV
274
                binary.BigEndian.PutUint32(blockHeight[:], e.BlockHeight)
×
UNCOV
275

×
UNCOV
276
                if _, err := w.Write(blockHeight[1:]); err != nil {
×
277
                        return err
×
278
                }
×
279

280
                // Check that field fit in 3 bytes and write the txIndex
UNCOV
281
                if e.TxIndex > ((1 << 24) - 1) {
×
282
                        return errors.New("tx index should fit in 3 bytes")
×
283
                }
×
284

UNCOV
285
                var txIndex [4]byte
×
UNCOV
286
                binary.BigEndian.PutUint32(txIndex[:], e.TxIndex)
×
UNCOV
287
                if _, err := w.Write(txIndex[1:]); err != nil {
×
288
                        return err
×
289
                }
×
290

291
                // Write the txPosition
UNCOV
292
                var txPosition [2]byte
×
UNCOV
293
                binary.BigEndian.PutUint16(txPosition[:], e.TxPosition)
×
UNCOV
294
                if _, err := w.Write(txPosition[:]); err != nil {
×
295
                        return err
×
296
                }
×
297

298
        case *net.TCPAddr:
×
299
                if e == nil {
×
300
                        return fmt.Errorf("cannot write nil TCPAddr")
×
301
                }
×
302

303
                if e.IP.To4() != nil {
×
304
                        var descriptor [1]byte
×
305
                        descriptor[0] = uint8(tcp4Addr)
×
306
                        if _, err := w.Write(descriptor[:]); err != nil {
×
307
                                return err
×
308
                        }
×
309

310
                        var ip [4]byte
×
311
                        copy(ip[:], e.IP.To4())
×
312
                        if _, err := w.Write(ip[:]); err != nil {
×
313
                                return err
×
314
                        }
×
315
                } else {
×
316
                        var descriptor [1]byte
×
317
                        descriptor[0] = uint8(tcp6Addr)
×
318
                        if _, err := w.Write(descriptor[:]); err != nil {
×
319
                                return err
×
320
                        }
×
321
                        var ip [16]byte
×
322
                        copy(ip[:], e.IP.To16())
×
323
                        if _, err := w.Write(ip[:]); err != nil {
×
324
                                return err
×
325
                        }
×
326
                }
327
                var port [2]byte
×
328
                binary.BigEndian.PutUint16(port[:], uint16(e.Port))
×
329
                if _, err := w.Write(port[:]); err != nil {
×
330
                        return err
×
331
                }
×
332

333
        case *tor.OnionAddr:
×
334
                if e == nil {
×
335
                        return errors.New("cannot write nil onion address")
×
336
                }
×
337

338
                var suffixIndex int
×
339
                switch len(e.OnionService) {
×
340
                case tor.V2Len:
×
341
                        descriptor := []byte{byte(v2OnionAddr)}
×
342
                        if _, err := w.Write(descriptor); err != nil {
×
343
                                return err
×
344
                        }
×
345
                        suffixIndex = tor.V2Len - tor.OnionSuffixLen
×
346
                case tor.V3Len:
×
347
                        descriptor := []byte{byte(v3OnionAddr)}
×
348
                        if _, err := w.Write(descriptor); err != nil {
×
349
                                return err
×
350
                        }
×
351
                        suffixIndex = tor.V3Len - tor.OnionSuffixLen
×
352
                default:
×
353
                        return errors.New("unknown onion service length")
×
354
                }
355

356
                host, err := tor.Base32Encoding.DecodeString(
×
357
                        e.OnionService[:suffixIndex],
×
358
                )
×
359
                if err != nil {
×
360
                        return err
×
361
                }
×
362
                if _, err := w.Write(host); err != nil {
×
363
                        return err
×
364
                }
×
365

366
                var port [2]byte
×
367
                binary.BigEndian.PutUint16(port[:], uint16(e.Port))
×
368
                if _, err := w.Write(port[:]); err != nil {
×
369
                        return err
×
370
                }
×
371

372
        case []net.Addr:
×
373
                // First, we'll encode all the addresses into an intermediate
×
374
                // buffer. We need to do this in order to compute the total
×
375
                // length of the addresses.
×
376
                var addrBuf bytes.Buffer
×
377
                for _, address := range e {
×
378
                        if err := WriteElement(&addrBuf, address); err != nil {
×
379
                                return err
×
380
                        }
×
381
                }
382

383
                // With the addresses fully encoded, we can now write out the
384
                // number of bytes needed to encode them.
385
                addrLen := addrBuf.Len()
×
386
                if err := WriteElement(w, uint16(addrLen)); err != nil {
×
387
                        return err
×
388
                }
×
389

390
                // Finally, we'll write out the raw addresses themselves, but
391
                // only if we have any bytes to write.
392
                if addrLen > 0 {
×
393
                        if _, err := w.Write(addrBuf.Bytes()); err != nil {
×
394
                                return err
×
395
                        }
×
396
                }
397
        case color.RGBA:
×
398
                if err := WriteElements(w, e.R, e.G, e.B); err != nil {
×
399
                        return err
×
400
                }
×
401

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

412
        case bool:
×
413
                var b [1]byte
×
414
                if e {
×
415
                        b[0] = 1
×
416
                }
×
417
                if _, err := w.Write(b[:]); err != nil {
×
418
                        return err
×
419
                }
×
420
        default:
×
421
                return fmt.Errorf("unknown type in WriteElement: %T", e)
×
422
        }
423

UNCOV
424
        return nil
×
425
}
426

427
// WriteElements is writes each element in the elements slice to the passed
428
// io.Writer using WriteElement.
UNCOV
429
func WriteElements(w io.Writer, elements ...interface{}) error {
×
UNCOV
430
        for _, element := range elements {
×
UNCOV
431
                err := WriteElement(w, element)
×
UNCOV
432
                if err != nil {
×
433
                        return err
×
434
                }
×
435
        }
UNCOV
436
        return nil
×
437
}
438

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

450
                if b[0] == 1 {
×
451
                        *e = true
×
452
                }
×
453

454
        case *NodeAlias:
×
455
                var a [32]byte
×
456
                if _, err := io.ReadFull(r, a[:]); err != nil {
×
457
                        return err
×
458
                }
×
459

460
                alias, err := NewNodeAlias(string(a[:]))
×
461
                if err != nil {
×
462
                        return err
×
463
                }
×
464

465
                *e = alias
×
466
        case *ShortChanIDEncoding:
×
467
                var b [1]uint8
×
468
                if _, err := r.Read(b[:]); err != nil {
×
469
                        return err
×
470
                }
×
471
                *e = ShortChanIDEncoding(b[0])
×
472
        case *uint8:
×
473
                var b [1]uint8
×
474
                if _, err := r.Read(b[:]); err != nil {
×
475
                        return err
×
476
                }
×
477
                *e = b[0]
×
478
        case *FundingFlag:
×
479
                var b [1]uint8
×
480
                if _, err := r.Read(b[:]); err != nil {
×
481
                        return err
×
482
                }
×
483
                *e = FundingFlag(b[0])
×
UNCOV
484
        case *uint16:
×
UNCOV
485
                var b [2]byte
×
UNCOV
486
                if _, err := io.ReadFull(r, b[:]); err != nil {
×
487
                        return err
×
488
                }
×
UNCOV
489
                *e = binary.BigEndian.Uint16(b[:])
×
UNCOV
490
        case *ChanUpdateMsgFlags:
×
UNCOV
491
                var b [1]uint8
×
UNCOV
492
                if _, err := r.Read(b[:]); err != nil {
×
493
                        return err
×
494
                }
×
UNCOV
495
                *e = ChanUpdateMsgFlags(b[0])
×
UNCOV
496
        case *ChanUpdateChanFlags:
×
UNCOV
497
                var b [1]uint8
×
UNCOV
498
                if _, err := r.Read(b[:]); err != nil {
×
499
                        return err
×
500
                }
×
UNCOV
501
                *e = ChanUpdateChanFlags(b[0])
×
UNCOV
502
        case *uint32:
×
UNCOV
503
                var b [4]byte
×
UNCOV
504
                if _, err := io.ReadFull(r, b[:]); err != nil {
×
505
                        return err
×
506
                }
×
UNCOV
507
                *e = binary.BigEndian.Uint32(b[:])
×
UNCOV
508
        case *uint64:
×
UNCOV
509
                var b [8]byte
×
UNCOV
510
                if _, err := io.ReadFull(r, b[:]); err != nil {
×
511
                        return err
×
512
                }
×
UNCOV
513
                *e = binary.BigEndian.Uint64(b[:])
×
UNCOV
514
        case *MilliSatoshi:
×
UNCOV
515
                var b [8]byte
×
UNCOV
516
                if _, err := io.ReadFull(r, b[:]); err != nil {
×
517
                        return err
×
518
                }
×
UNCOV
519
                *e = MilliSatoshi(int64(binary.BigEndian.Uint64(b[:])))
×
520
        case *btcutil.Amount:
×
521
                var b [8]byte
×
522
                if _, err := io.ReadFull(r, b[:]); err != nil {
×
523
                        return err
×
524
                }
×
525
                *e = btcutil.Amount(int64(binary.BigEndian.Uint64(b[:])))
×
UNCOV
526
        case **btcec.PublicKey:
×
UNCOV
527
                var b [btcec.PubKeyBytesLenCompressed]byte
×
UNCOV
528
                if _, err = io.ReadFull(r, b[:]); err != nil {
×
529
                        return err
×
530
                }
×
531

UNCOV
532
                pubKey, err := btcec.ParsePubKey(b[:])
×
UNCOV
533
                if err != nil {
×
534
                        return err
×
535
                }
×
UNCOV
536
                *e = pubKey
×
537
        case **RawFeatureVector:
×
538
                f := NewRawFeatureVector()
×
539
                err = f.Decode(r)
×
540
                if err != nil {
×
541
                        return err
×
542
                }
×
543

544
                *e = f
×
545

UNCOV
546
        case *[]Sig:
×
UNCOV
547
                var l [2]byte
×
UNCOV
548
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
549
                        return err
×
550
                }
×
UNCOV
551
                numSigs := binary.BigEndian.Uint16(l[:])
×
UNCOV
552

×
UNCOV
553
                var sigs []Sig
×
UNCOV
554
                if numSigs > 0 {
×
UNCOV
555
                        sigs = make([]Sig, numSigs)
×
UNCOV
556
                        for i := 0; i < int(numSigs); i++ {
×
UNCOV
557
                                if err := ReadElement(r, &sigs[i]); err != nil {
×
558
                                        return err
×
559
                                }
×
560
                        }
561
                }
562

UNCOV
563
                *e = sigs
×
564

UNCOV
565
        case *Sig:
×
UNCOV
566
                if _, err := io.ReadFull(r, e[:]); err != nil {
×
567
                        return err
×
568
                }
×
UNCOV
569
        case *OpaqueReason:
×
UNCOV
570
                var l [2]byte
×
UNCOV
571
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
572
                        return err
×
573
                }
×
UNCOV
574
                reasonLen := binary.BigEndian.Uint16(l[:])
×
UNCOV
575

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

×
587
                *e = ErrorData(make([]byte, errorLen))
×
588
                if _, err := io.ReadFull(r, *e); err != nil {
×
589
                        return err
×
590
                }
×
591
        case *PingPayload:
×
592
                var l [2]byte
×
593
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
594
                        return err
×
595
                }
×
596
                pingLen := binary.BigEndian.Uint16(l[:])
×
597

×
598
                *e = PingPayload(make([]byte, pingLen))
×
599
                if _, err := io.ReadFull(r, *e); err != nil {
×
600
                        return err
×
601
                }
×
602
        case *PongPayload:
×
603
                var l [2]byte
×
604
                if _, err := io.ReadFull(r, l[:]); err != nil {
×
605
                        return err
×
606
                }
×
607
                pongLen := binary.BigEndian.Uint16(l[:])
×
608

×
609
                *e = PongPayload(make([]byte, pongLen))
×
610
                if _, err := io.ReadFull(r, *e); err != nil {
×
611
                        return err
×
612
                }
×
613
        case *[33]byte:
×
614
                if _, err := io.ReadFull(r, e[:]); err != nil {
×
615
                        return err
×
616
                }
×
UNCOV
617
        case []byte:
×
UNCOV
618
                if _, err := io.ReadFull(r, e); err != nil {
×
619
                        return err
×
620
                }
×
621
        case *PkScript:
×
622
                pkScript, err := wire.ReadVarBytes(r, 0, 34, "pkscript")
×
623
                if err != nil {
×
624
                        return err
×
625
                }
×
626
                *e = pkScript
×
627
        case *wire.OutPoint:
×
628
                var h [32]byte
×
629
                if _, err = io.ReadFull(r, h[:]); err != nil {
×
630
                        return err
×
631
                }
×
632
                hash, err := chainhash.NewHash(h[:])
×
633
                if err != nil {
×
634
                        return err
×
635
                }
×
636

637
                var idxBytes [2]byte
×
638
                _, err = io.ReadFull(r, idxBytes[:])
×
639
                if err != nil {
×
640
                        return err
×
641
                }
×
642
                index := binary.BigEndian.Uint16(idxBytes[:])
×
643

×
644
                *e = wire.OutPoint{
×
645
                        Hash:  *hash,
×
646
                        Index: uint32(index),
×
647
                }
×
648
        case *FailCode:
×
649
                if err := ReadElement(r, (*uint16)(e)); err != nil {
×
650
                        return err
×
651
                }
×
UNCOV
652
        case *ChannelID:
×
UNCOV
653
                if _, err := io.ReadFull(r, e[:]); err != nil {
×
654
                        return err
×
655
                }
×
656

UNCOV
657
        case *ShortChannelID:
×
UNCOV
658
                var blockHeight [4]byte
×
UNCOV
659
                if _, err = io.ReadFull(r, blockHeight[1:]); err != nil {
×
660
                        return err
×
661
                }
×
662

UNCOV
663
                var txIndex [4]byte
×
UNCOV
664
                if _, err = io.ReadFull(r, txIndex[1:]); err != nil {
×
665
                        return err
×
666
                }
×
667

UNCOV
668
                var txPosition [2]byte
×
UNCOV
669
                if _, err = io.ReadFull(r, txPosition[:]); err != nil {
×
670
                        return err
×
671
                }
×
672

UNCOV
673
                *e = ShortChannelID{
×
UNCOV
674
                        BlockHeight: binary.BigEndian.Uint32(blockHeight[:]),
×
UNCOV
675
                        TxIndex:     binary.BigEndian.Uint32(txIndex[:]),
×
UNCOV
676
                        TxPosition:  binary.BigEndian.Uint16(txPosition[:]),
×
UNCOV
677
                }
×
678

679
        case *[]net.Addr:
×
680
                // First, we'll read the number of total bytes that have been
×
681
                // used to encode the set of addresses.
×
682
                var numAddrsBytes [2]byte
×
683
                if _, err = io.ReadFull(r, numAddrsBytes[:]); err != nil {
×
684
                        return err
×
685
                }
×
686
                addrsLen := binary.BigEndian.Uint16(numAddrsBytes[:])
×
687

×
688
                // With the number of addresses, read, we'll now pull in the
×
689
                // buffer of the encoded addresses into memory.
×
690
                addrs := make([]byte, addrsLen)
×
691
                if _, err := io.ReadFull(r, addrs[:]); err != nil {
×
692
                        return err
×
693
                }
×
694
                addrBuf := bytes.NewReader(addrs)
×
695

×
696
                // Finally, we'll parse the remaining address payload in
×
697
                // series, using the first byte to denote how to decode the
×
698
                // address itself.
×
699
                var (
×
700
                        addresses     []net.Addr
×
701
                        addrBytesRead uint16
×
702
                )
×
703

×
704
                for addrBytesRead < addrsLen {
×
705
                        var descriptor [1]byte
×
706
                        if _, err = io.ReadFull(addrBuf, descriptor[:]); err != nil {
×
707
                                return err
×
708
                        }
×
709

710
                        addrBytesRead++
×
711

×
712
                        var address net.Addr
×
713
                        switch aType := addressType(descriptor[0]); aType {
×
714
                        case noAddr:
×
715
                                addrBytesRead += aType.AddrLen()
×
716
                                continue
×
717

718
                        case tcp4Addr:
×
719
                                var ip [4]byte
×
720
                                if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
×
721
                                        return err
×
722
                                }
×
723

724
                                var port [2]byte
×
725
                                if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
×
726
                                        return err
×
727
                                }
×
728

729
                                address = &net.TCPAddr{
×
730
                                        IP:   net.IP(ip[:]),
×
731
                                        Port: int(binary.BigEndian.Uint16(port[:])),
×
732
                                }
×
733
                                addrBytesRead += aType.AddrLen()
×
734

735
                        case tcp6Addr:
×
736
                                var ip [16]byte
×
737
                                if _, err := io.ReadFull(addrBuf, ip[:]); err != nil {
×
738
                                        return err
×
739
                                }
×
740

741
                                var port [2]byte
×
742
                                if _, err := io.ReadFull(addrBuf, port[:]); err != nil {
×
743
                                        return err
×
744
                                }
×
745

746
                                address = &net.TCPAddr{
×
747
                                        IP:   net.IP(ip[:]),
×
748
                                        Port: int(binary.BigEndian.Uint16(port[:])),
×
749
                                }
×
750
                                addrBytesRead += aType.AddrLen()
×
751

752
                        case v2OnionAddr:
×
753
                                var h [tor.V2DecodedLen]byte
×
754
                                if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
×
755
                                        return err
×
756
                                }
×
757

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

763
                                onionService := tor.Base32Encoding.EncodeToString(h[:])
×
764
                                onionService += tor.OnionSuffix
×
765
                                port := int(binary.BigEndian.Uint16(p[:]))
×
766

×
767
                                address = &tor.OnionAddr{
×
768
                                        OnionService: onionService,
×
769
                                        Port:         port,
×
770
                                }
×
771
                                addrBytesRead += aType.AddrLen()
×
772

773
                        case v3OnionAddr:
×
774
                                var h [tor.V3DecodedLen]byte
×
775
                                if _, err := io.ReadFull(addrBuf, h[:]); err != nil {
×
776
                                        return err
×
777
                                }
×
778

779
                                var p [2]byte
×
780
                                if _, err := io.ReadFull(addrBuf, p[:]); err != nil {
×
781
                                        return err
×
782
                                }
×
783

784
                                onionService := tor.Base32Encoding.EncodeToString(h[:])
×
785
                                onionService += tor.OnionSuffix
×
786
                                port := int(binary.BigEndian.Uint16(p[:]))
×
787

×
788
                                address = &tor.OnionAddr{
×
789
                                        OnionService: onionService,
×
790
                                        Port:         port,
×
791
                                }
×
792
                                addrBytesRead += aType.AddrLen()
×
793

794
                        default:
×
795
                                return &ErrUnknownAddrType{aType}
×
796
                        }
797

798
                        addresses = append(addresses, address)
×
799
                }
800

801
                *e = addresses
×
802
        case *color.RGBA:
×
803
                err := ReadElements(r,
×
804
                        &e.R,
×
805
                        &e.G,
×
806
                        &e.B,
×
807
                )
×
808
                if err != nil {
×
809
                        return err
×
810
                }
×
811
        case *DeliveryAddress:
×
812
                var addrLen [2]byte
×
813
                if _, err = io.ReadFull(r, addrLen[:]); err != nil {
×
814
                        return err
×
815
                }
×
816
                length := binary.BigEndian.Uint16(addrLen[:])
×
817

×
818
                var addrBytes [deliveryAddressMaxSize]byte
×
819
                if length > deliveryAddressMaxSize {
×
820
                        return fmt.Errorf("cannot read %d bytes into addrBytes", length)
×
821
                }
×
822
                if _, err = io.ReadFull(r, addrBytes[:length]); err != nil {
×
823
                        return err
×
824
                }
×
825
                *e = addrBytes[:length]
×
826
        default:
×
827
                return fmt.Errorf("unknown type in ReadElement: %T", e)
×
828
        }
829

UNCOV
830
        return nil
×
831
}
832

833
// ReadElements deserializes a variable number of elements into the passed
834
// io.Reader, with each element being deserialized according to the ReadElement
835
// function.
UNCOV
836
func ReadElements(r io.Reader, elements ...interface{}) error {
×
UNCOV
837
        for _, element := range elements {
×
UNCOV
838
                err := ReadElement(r, element)
×
UNCOV
839
                if err != nil {
×
840
                        return err
×
841
                }
×
842
        }
UNCOV
843
        return nil
×
844
}
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