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

lightningnetwork / lnd / 16466354971

23 Jul 2025 09:05AM UTC coverage: 57.54% (-9.7%) from 67.201%
16466354971

Pull #9455

github

web-flow
Merge f914ae23c into 90e211684
Pull Request #9455: discovery+lnwire: add support for DNS host name in NodeAnnouncement msg

151 of 291 new or added lines in 7 files covered. (51.89%)

28441 existing lines in 456 files now uncovered.

98864 of 171817 relevant lines covered (57.54%)

1.79 hits per line

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

68.63
/lnwire/writer.go
1
package lnwire
2

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

12
        "github.com/btcsuite/btcd/btcec/v2"
13
        "github.com/btcsuite/btcd/btcutil"
14
        "github.com/btcsuite/btcd/wire"
15
        "github.com/lightningnetwork/lnd/tor"
16
)
17

18
var (
19
        // ErrNilFeatureVector is returned when the supplied feature is nil.
20
        ErrNilFeatureVector = errors.New("cannot write nil feature vector")
21

22
        // ErrPkScriptTooLong is returned when the length of the provided
23
        // script exceeds 34.
24
        ErrPkScriptTooLong = errors.New("'PkScript' too long")
25

26
        // ErrNilTCPAddress is returned when the supplied address is nil.
27
        ErrNilTCPAddress = errors.New("cannot write nil TCPAddr")
28

29
        // ErrNilOnionAddress is returned when the supplied address is nil.
30
        ErrNilOnionAddress = errors.New("cannot write nil onion address")
31

32
        // ErrNilOnionAddress is returned when the supplied address is nil.
33
        ErrNilDNSAddress = errors.New("cannot write nil DNS address")
34

35
        // ErrNilNetAddress is returned when a nil value is used in []net.Addr.
36
        ErrNilNetAddress = errors.New("cannot write nil address")
37

38
        // ErrNilOpaqueAddrs is returned when the supplied address is nil.
39
        ErrNilOpaqueAddrs = errors.New("cannot write nil OpaqueAddrs")
40

41
        // ErrNilPublicKey is returned when a nil pubkey is used.
42
        ErrNilPublicKey = errors.New("cannot write nil pubkey")
43

44
        // ErrUnknownServiceLength is returned when the onion service length is
45
        // unknown.
46
        ErrUnknownServiceLength = errors.New("unknown onion service length")
47
)
48

49
// ErrOutpointIndexTooBig is used when the outpoint index exceeds the max value
50
// of uint16.
UNCOV
51
func ErrOutpointIndexTooBig(index uint32) error {
×
UNCOV
52
        return fmt.Errorf(
×
UNCOV
53
                "index for outpoint (%v) is greater than "+
×
UNCOV
54
                        "max index of %v", index, math.MaxUint16,
×
UNCOV
55
        )
×
UNCOV
56
}
×
57

58
// WriteBytes appends the given bytes to the provided buffer.
59
func WriteBytes(buf *bytes.Buffer, b []byte) error {
3✔
60
        _, err := buf.Write(b)
3✔
61
        return err
3✔
62
}
3✔
63

64
// WriteUint8 appends the uint8 to the provided buffer.
65
func WriteUint8(buf *bytes.Buffer, n uint8) error {
3✔
66
        _, err := buf.Write([]byte{n})
3✔
67
        return err
3✔
68
}
3✔
69

70
// WriteUint16 appends the uint16 to the provided buffer. It encodes the
71
// integer using big endian byte order.
72
func WriteUint16(buf *bytes.Buffer, n uint16) error {
3✔
73
        var b [2]byte
3✔
74
        binary.BigEndian.PutUint16(b[:], n)
3✔
75
        _, err := buf.Write(b[:])
3✔
76
        return err
3✔
77
}
3✔
78

79
// WriteUint32 appends the uint32 to the provided buffer. It encodes the
80
// integer using big endian byte order.
81
func WriteUint32(buf *bytes.Buffer, n uint32) error {
3✔
82
        var b [4]byte
3✔
83
        binary.BigEndian.PutUint32(b[:], n)
3✔
84
        _, err := buf.Write(b[:])
3✔
85
        return err
3✔
86
}
3✔
87

88
// WriteUint64 appends the uint64 to the provided buffer. It encodes the
89
// integer using big endian byte order.
90
func WriteUint64(buf *bytes.Buffer, n uint64) error {
3✔
91
        var b [8]byte
3✔
92
        binary.BigEndian.PutUint64(b[:], n)
3✔
93
        _, err := buf.Write(b[:])
3✔
94
        return err
3✔
95
}
3✔
96

97
// WriteSatoshi appends the Satoshi value to the provided buffer.
98
func WriteSatoshi(buf *bytes.Buffer, amount btcutil.Amount) error {
3✔
99
        return WriteUint64(buf, uint64(amount))
3✔
100
}
3✔
101

102
// WriteMilliSatoshi appends the MilliSatoshi value to the provided buffer.
103
func WriteMilliSatoshi(buf *bytes.Buffer, amount MilliSatoshi) error {
3✔
104
        return WriteUint64(buf, uint64(amount))
3✔
105
}
3✔
106

107
// WritePublicKey appends the compressed public key to the provided buffer.
108
func WritePublicKey(buf *bytes.Buffer, pub *btcec.PublicKey) error {
3✔
109
        if pub == nil {
3✔
UNCOV
110
                return ErrNilPublicKey
×
UNCOV
111
        }
×
112

113
        serializedPubkey := pub.SerializeCompressed()
3✔
114
        return WriteBytes(buf, serializedPubkey)
3✔
115
}
116

117
// WriteChannelID appends the ChannelID to the provided buffer.
118
func WriteChannelID(buf *bytes.Buffer, channelID ChannelID) error {
3✔
119
        return WriteBytes(buf, channelID[:])
3✔
120
}
3✔
121

122
// WriteNodeAlias appends the alias to the provided buffer.
123
func WriteNodeAlias(buf *bytes.Buffer, alias NodeAlias) error {
3✔
124
        return WriteBytes(buf, alias[:])
3✔
125
}
3✔
126

127
// WriteShortChannelID appends the ShortChannelID to the provided buffer. It
128
// encodes the BlockHeight and TxIndex each using 3 bytes with big endian byte
129
// order, and encodes txPosition using 2 bytes with big endian byte order.
130
func WriteShortChannelID(buf *bytes.Buffer, shortChanID ShortChannelID) error {
3✔
131
        // Check that field fit in 3 bytes and write the blockHeight
3✔
132
        if shortChanID.BlockHeight > ((1 << 24) - 1) {
3✔
133
                return errors.New("block height should fit in 3 bytes")
×
134
        }
×
135

136
        var blockHeight [4]byte
3✔
137
        binary.BigEndian.PutUint32(blockHeight[:], shortChanID.BlockHeight)
3✔
138

3✔
139
        if _, err := buf.Write(blockHeight[1:]); err != nil {
3✔
140
                return err
×
141
        }
×
142

143
        // Check that field fit in 3 bytes and write the txIndex
144
        if shortChanID.TxIndex > ((1 << 24) - 1) {
3✔
145
                return errors.New("tx index should fit in 3 bytes")
×
146
        }
×
147

148
        var txIndex [4]byte
3✔
149
        binary.BigEndian.PutUint32(txIndex[:], shortChanID.TxIndex)
3✔
150
        if _, err := buf.Write(txIndex[1:]); err != nil {
3✔
151
                return err
×
152
        }
×
153

154
        // Write the TxPosition
155
        return WriteUint16(buf, shortChanID.TxPosition)
3✔
156
}
157

158
// WriteSig appends the signature to the provided buffer.
159
func WriteSig(buf *bytes.Buffer, sig Sig) error {
3✔
160
        return WriteBytes(buf, sig.bytes[:])
3✔
161
}
3✔
162

163
// WriteSigs appends the slice of signatures to the provided buffer with its
164
// length.
165
func WriteSigs(buf *bytes.Buffer, sigs []Sig) error {
3✔
166
        // Write the length of the sigs.
3✔
167
        if err := WriteUint16(buf, uint16(len(sigs))); err != nil {
3✔
168
                return err
×
169
        }
×
170

171
        for _, sig := range sigs {
6✔
172
                if err := WriteSig(buf, sig); err != nil {
3✔
173
                        return err
×
174
                }
×
175
        }
176
        return nil
3✔
177
}
178

179
// WriteFailCode appends the FailCode to the provided buffer.
180
func WriteFailCode(buf *bytes.Buffer, e FailCode) error {
3✔
181
        return WriteUint16(buf, uint16(e))
3✔
182
}
3✔
183

184
// WriteRawFeatureVector encodes the feature using the feature's Encode method
185
// and appends the data to the provided buffer. An error will return if the
186
// passed feature is nil.
187
func WriteRawFeatureVector(buf *bytes.Buffer, feature *RawFeatureVector) error {
3✔
188
        if feature == nil {
3✔
UNCOV
189
                return ErrNilFeatureVector
×
UNCOV
190
        }
×
191

192
        return feature.Encode(buf)
3✔
193
}
194

195
// WriteColorRGBA appends the RGBA color using three bytes.
196
func WriteColorRGBA(buf *bytes.Buffer, e color.RGBA) error {
3✔
197
        // Write R
3✔
198
        if err := WriteUint8(buf, e.R); err != nil {
3✔
199
                return err
×
200
        }
×
201

202
        // Write G
203
        if err := WriteUint8(buf, e.G); err != nil {
3✔
204
                return err
×
205
        }
×
206

207
        // Write B
208
        return WriteUint8(buf, e.B)
3✔
209
}
210

211
// WriteQueryEncoding appends the QueryEncoding to the provided buffer.
212
func WriteQueryEncoding(buf *bytes.Buffer, e QueryEncoding) error {
3✔
213
        return WriteUint8(buf, uint8(e))
3✔
214
}
3✔
215

216
// WriteFundingFlag appends the FundingFlag to the provided buffer.
217
func WriteFundingFlag(buf *bytes.Buffer, flag FundingFlag) error {
3✔
218
        return WriteUint8(buf, uint8(flag))
3✔
219
}
3✔
220

221
// WriteChanUpdateMsgFlags appends the update flag to the provided buffer.
222
func WriteChanUpdateMsgFlags(buf *bytes.Buffer, f ChanUpdateMsgFlags) error {
3✔
223
        return WriteUint8(buf, uint8(f))
3✔
224
}
3✔
225

226
// WriteChanUpdateChanFlags appends the update flag to the provided buffer.
227
func WriteChanUpdateChanFlags(buf *bytes.Buffer, f ChanUpdateChanFlags) error {
3✔
228
        return WriteUint8(buf, uint8(f))
3✔
229
}
3✔
230

231
// WriteDeliveryAddress appends the address to the provided buffer.
232
func WriteDeliveryAddress(buf *bytes.Buffer, addr DeliveryAddress) error {
3✔
233
        return writeDataWithLength(buf, addr)
3✔
234
}
3✔
235

236
// WritePingPayload appends the payload to the provided buffer.
UNCOV
237
func WritePingPayload(buf *bytes.Buffer, payload PingPayload) error {
×
UNCOV
238
        return writeDataWithLength(buf, payload)
×
UNCOV
239
}
×
240

241
// WritePongPayload appends the payload to the provided buffer.
UNCOV
242
func WritePongPayload(buf *bytes.Buffer, payload PongPayload) error {
×
UNCOV
243
        return writeDataWithLength(buf, payload)
×
UNCOV
244
}
×
245

246
// WriteWarningData appends the data to the provided buffer.
UNCOV
247
func WriteWarningData(buf *bytes.Buffer, data WarningData) error {
×
UNCOV
248
        return writeDataWithLength(buf, data)
×
UNCOV
249
}
×
250

251
// WriteErrorData appends the data to the provided buffer.
252
func WriteErrorData(buf *bytes.Buffer, data ErrorData) error {
3✔
253
        return writeDataWithLength(buf, data)
3✔
254
}
3✔
255

256
// WriteOpaqueReason appends the reason to the provided buffer.
257
func WriteOpaqueReason(buf *bytes.Buffer, reason OpaqueReason) error {
3✔
258
        return writeDataWithLength(buf, reason)
3✔
259
}
3✔
260

261
// WriteBool appends the boolean to the provided buffer.
262
func WriteBool(buf *bytes.Buffer, b bool) error {
3✔
263
        if b {
6✔
264
                return WriteBytes(buf, []byte{1})
3✔
265
        }
3✔
266
        return WriteBytes(buf, []byte{0})
3✔
267
}
268

269
// WritePkScript appends the script to the provided buffer. Returns an error if
270
// the provided script exceeds 34 bytes.
UNCOV
271
func WritePkScript(buf *bytes.Buffer, s PkScript) error {
×
UNCOV
272
        // The largest script we'll accept is a p2wsh which is exactly
×
UNCOV
273
        // 34 bytes long.
×
UNCOV
274
        scriptLength := len(s)
×
UNCOV
275
        if scriptLength > 34 {
×
UNCOV
276
                return ErrPkScriptTooLong
×
UNCOV
277
        }
×
278

UNCOV
279
        return wire.WriteVarBytes(buf, 0, s)
×
280
}
281

282
// WriteOutPoint appends the outpoint to the provided buffer.
283
func WriteOutPoint(buf *bytes.Buffer, p wire.OutPoint) error {
3✔
284
        // Before we write anything to the buffer, check the Index is sane.
3✔
285
        if p.Index > math.MaxUint16 {
3✔
UNCOV
286
                return ErrOutpointIndexTooBig(p.Index)
×
UNCOV
287
        }
×
288

289
        var h [32]byte
3✔
290
        copy(h[:], p.Hash[:])
3✔
291
        if _, err := buf.Write(h[:]); err != nil {
3✔
292
                return err
×
293
        }
×
294

295
        // Write the index using two bytes.
296
        return WriteUint16(buf, uint16(p.Index))
3✔
297
}
298

299
// WriteTCPAddr appends the TCP address to the provided buffer, either a IPv4
300
// or a IPv6.
301
func WriteTCPAddr(buf *bytes.Buffer, addr *net.TCPAddr) error {
3✔
302
        if addr == nil {
3✔
UNCOV
303
                return ErrNilTCPAddress
×
UNCOV
304
        }
×
305

306
        // Make a slice of bytes to hold the data of descriptor and ip. At
307
        // most, we need 17 bytes - 1 byte for the descriptor, 16 bytes for
308
        // IPv6.
309
        data := make([]byte, 0, 17)
3✔
310

3✔
311
        if addr.IP.To4() != nil {
6✔
312
                data = append(data, uint8(tcp4Addr))
3✔
313
                data = append(data, addr.IP.To4()...)
3✔
314
        } else {
6✔
315
                data = append(data, uint8(tcp6Addr))
3✔
316
                data = append(data, addr.IP.To16()...)
3✔
317
        }
3✔
318

319
        if _, err := buf.Write(data); err != nil {
3✔
320
                return err
×
321
        }
×
322

323
        return WriteUint16(buf, uint16(addr.Port))
3✔
324
}
325

326
// WriteOnionAddr appends the onion address to the provided buffer.
327
func WriteOnionAddr(buf *bytes.Buffer, addr *tor.OnionAddr) error {
3✔
328
        if addr == nil {
3✔
UNCOV
329
                return ErrNilOnionAddress
×
UNCOV
330
        }
×
331

332
        var (
3✔
333
                suffixIndex int
3✔
334
                descriptor  []byte
3✔
335
        )
3✔
336

3✔
337
        // Decide the suffixIndex and descriptor.
3✔
338
        switch len(addr.OnionService) {
3✔
339
        case tor.V2Len:
3✔
340
                descriptor = []byte{byte(v2OnionAddr)}
3✔
341
                suffixIndex = tor.V2Len - tor.OnionSuffixLen
3✔
342

343
        case tor.V3Len:
3✔
344
                descriptor = []byte{byte(v3OnionAddr)}
3✔
345
                suffixIndex = tor.V3Len - tor.OnionSuffixLen
3✔
346

UNCOV
347
        default:
×
UNCOV
348
                return ErrUnknownServiceLength
×
349
        }
350

351
        // Decode the address.
352
        host, err := tor.Base32Encoding.DecodeString(
3✔
353
                addr.OnionService[:suffixIndex],
3✔
354
        )
3✔
355
        if err != nil {
3✔
UNCOV
356
                return err
×
UNCOV
357
        }
×
358

359
        // Perform the actual write when the above checks passed.
360
        if _, err := buf.Write(descriptor); err != nil {
3✔
361
                return err
×
362
        }
×
363
        if _, err := buf.Write(host); err != nil {
3✔
364
                return err
×
365
        }
×
366

367
        return WriteUint16(buf, uint16(addr.Port))
3✔
368
}
369

370
// WriteDNSAddr appends the DNS address to the provided buffer.
371
func WriteDNSAddr(buf *bytes.Buffer, addr *DNSAddr) error {
3✔
372
        if addr == nil {
3✔
NEW
373
                return ErrNilDNSAddress
×
NEW
374
        }
×
375

376
        // Hold a slice of bytes to hold the data of descriptor, DNS address
377
        // length, and the DNS address. At most we need 257 bytes – 1 byte for
378
        // the descriptor, 1 byte for DNS length, and 225 bytes max for
379
        // DNS address.
380
        hostnameLen := len(addr.Hostname)
3✔
381
        dataLen := 1 + 1 + hostnameLen
3✔
382
        data := make([]byte, 0, dataLen)
3✔
383

3✔
384
        // Write the DNS address type descriptor.
3✔
385
        data = append(data, byte(dnsHostnameAddr))
3✔
386

3✔
387
        // Write the DNS address length.
3✔
388
        data = append(data, byte(hostnameLen))
3✔
389

3✔
390
        // Write the DNS address.
3✔
391
        data = append(data, []byte(addr.Hostname)...)
3✔
392

3✔
393
        if _, err := buf.Write(data); err != nil {
3✔
NEW
394
                return err
×
NEW
395
        }
×
396

397
        return WriteUint16(buf, uint16(addr.Port))
3✔
398
}
399

400
// WriteOpaqueAddrs appends the payload of the given OpaqueAddrs to buffer.
UNCOV
401
func WriteOpaqueAddrs(buf *bytes.Buffer, addr *OpaqueAddrs) error {
×
UNCOV
402
        if addr == nil {
×
403
                return ErrNilOpaqueAddrs
×
404
        }
×
405

UNCOV
406
        _, err := buf.Write(addr.Payload)
×
UNCOV
407
        return err
×
408
}
409

410
// WriteNetAddrs appends a slice of addresses to the provided buffer with the
411
// length info.
412
func WriteNetAddrs(buf *bytes.Buffer, addresses []net.Addr) error {
3✔
413
        // First, we'll encode all the addresses into an intermediate
3✔
414
        // buffer. We need to do this in order to compute the total
3✔
415
        // length of the addresses.
3✔
416
        buffer := make([]byte, 0, MaxMsgBody)
3✔
417
        addrBuf := bytes.NewBuffer(buffer)
3✔
418
        var dnsAddrIncluded bool
3✔
419
        for _, address := range addresses {
6✔
420
                switch a := address.(type) {
3✔
421
                case *net.TCPAddr:
3✔
422
                        if err := WriteTCPAddr(addrBuf, a); err != nil {
3✔
423
                                return err
×
424
                        }
×
425
                case *tor.OnionAddr:
3✔
426
                        if err := WriteOnionAddr(addrBuf, a); err != nil {
3✔
427
                                return err
×
428
                        }
×
429
                case *DNSAddr:
3✔
430
                        if dnsAddrIncluded {
6✔
431
                                return errors.New("cannot advertise multiple " +
3✔
432
                                        "DNS addresses. See Bolt 07")
3✔
433
                        }
3✔
434
                        if err := WriteDNSAddr(addrBuf, a); err != nil {
3✔
NEW
435
                                return err
×
NEW
436
                        }
×
437
                        dnsAddrIncluded = true
3✔
UNCOV
438
                case *OpaqueAddrs:
×
UNCOV
439
                        if err := WriteOpaqueAddrs(addrBuf, a); err != nil {
×
440
                                return err
×
441
                        }
×
UNCOV
442
                default:
×
UNCOV
443
                        return ErrNilNetAddress
×
444
                }
445
        }
446

447
        // With the addresses fully encoded, we can now write out data.
448
        return writeDataWithLength(buf, addrBuf.Bytes())
3✔
449
}
450

451
// writeDataWithLength writes the data and its length to the buffer.
452
func writeDataWithLength(buf *bytes.Buffer, data []byte) error {
3✔
453
        var l [2]byte
3✔
454
        binary.BigEndian.PutUint16(l[:], uint16(len(data)))
3✔
455
        if _, err := buf.Write(l[:]); err != nil {
3✔
456
                return err
×
457
        }
×
458

459
        _, err := buf.Write(data)
3✔
460
        return err
3✔
461
}
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