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

lightningnetwork / lnd / 16569502135

28 Jul 2025 12:50PM UTC coverage: 67.251% (+0.02%) from 67.227%
16569502135

Pull #9455

github

web-flow
Merge b3899c4fd into 2e36f9b8b
Pull Request #9455: discovery+lnwire: add support for DNS host name in NodeAnnouncement msg

179 of 208 new or added lines in 6 files covered. (86.06%)

105 existing lines in 23 files now uncovered.

135676 of 201746 relevant lines covered (67.25%)

21711.59 hits per line

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

79.31
/graph/db/addr.go
1
package graphdb
2

3
import (
4
        "encoding/binary"
5
        "errors"
6
        "fmt"
7
        "io"
8
        "net"
9

10
        "github.com/lightningnetwork/lnd/lnwire"
11
        "github.com/lightningnetwork/lnd/tor"
12
)
13

14
// addressType specifies the network protocol and version that should be used
15
// when connecting to a node at a particular address.
16
type addressType uint8
17

18
const (
19
        // tcp4Addr denotes an IPv4 TCP address.
20
        tcp4Addr addressType = 0
21

22
        // tcp6Addr denotes an IPv6 TCP address.
23
        tcp6Addr addressType = 1
24

25
        // v2OnionAddr denotes a version 2 Tor onion service address.
26
        v2OnionAddr addressType = 2
27

28
        // v3OnionAddr denotes a version 3 Tor (prop224) onion service address.
29
        v3OnionAddr addressType = 3
30

31
        // opaqueAddrs denotes an address (or a set of addresses) that LND was
32
        // not able to parse since LND is not yet aware of the address type.
33
        opaqueAddrs addressType = 4
34

35
        // dnsAddr denotes a DNS hostname address.
36
        dnsAddr addressType = 5
37
)
38

39
// encodeTCPAddr serializes a TCP address into its compact raw bytes
40
// representation.
41
func encodeTCPAddr(w io.Writer, addr *net.TCPAddr) error {
2,124✔
42
        var (
2,124✔
43
                addrType byte
2,124✔
44
                ip       []byte
2,124✔
45
        )
2,124✔
46

2,124✔
47
        if addr.IP.To4() != nil {
3,858✔
48
                addrType = byte(tcp4Addr)
1,734✔
49
                ip = addr.IP.To4()
1,734✔
50
        } else {
2,127✔
51
                addrType = byte(tcp6Addr)
393✔
52
                ip = addr.IP.To16()
393✔
53
        }
393✔
54

55
        if ip == nil {
2,128✔
56
                return fmt.Errorf("unable to encode IP %v", addr.IP)
4✔
57
        }
4✔
58

59
        if _, err := w.Write([]byte{addrType}); err != nil {
2,120✔
60
                return err
×
61
        }
×
62

63
        if _, err := w.Write(ip); err != nil {
2,120✔
64
                return err
×
65
        }
×
66

67
        var port [2]byte
2,120✔
68
        byteOrder.PutUint16(port[:], uint16(addr.Port))
2,120✔
69
        if _, err := w.Write(port[:]); err != nil {
2,120✔
70
                return err
×
71
        }
×
72

73
        return nil
2,120✔
74
}
75

76
// encodeOnionAddr serializes an onion address into its compact raw bytes
77
// representation.
78
func encodeOnionAddr(w io.Writer, addr *tor.OnionAddr) error {
212✔
79
        var suffixIndex int
212✔
80
        hostLen := len(addr.OnionService)
212✔
81
        switch hostLen {
212✔
82
        case tor.V2Len:
106✔
83
                if _, err := w.Write([]byte{byte(v2OnionAddr)}); err != nil {
106✔
84
                        return err
×
85
                }
×
86
                suffixIndex = tor.V2Len - tor.OnionSuffixLen
106✔
87
        case tor.V3Len:
108✔
88
                if _, err := w.Write([]byte{byte(v3OnionAddr)}); err != nil {
108✔
89
                        return err
×
90
                }
×
91
                suffixIndex = tor.V3Len - tor.OnionSuffixLen
108✔
92
        default:
1✔
93
                return errors.New("unknown onion service length")
1✔
94
        }
95

96
        suffix := addr.OnionService[suffixIndex:]
211✔
97
        if suffix != tor.OnionSuffix {
212✔
98
                return fmt.Errorf("invalid suffix \"%v\"", suffix)
1✔
99
        }
1✔
100

101
        host, err := tor.Base32Encoding.DecodeString(
210✔
102
                addr.OnionService[:suffixIndex],
210✔
103
        )
210✔
104
        if err != nil {
211✔
105
                return err
1✔
106
        }
1✔
107

108
        // Sanity check the decoded length.
109
        switch {
209✔
110
        case hostLen == tor.V2Len && len(host) != tor.V2DecodedLen:
×
111
                return fmt.Errorf("onion service %v decoded to invalid host %x",
×
112
                        addr.OnionService, host)
×
113

114
        case hostLen == tor.V3Len && len(host) != tor.V3DecodedLen:
×
115
                return fmt.Errorf("onion service %v decoded to invalid host %x",
×
116
                        addr.OnionService, host)
×
117
        }
118

119
        if _, err := w.Write(host); err != nil {
209✔
120
                return err
×
121
        }
×
122

123
        var port [2]byte
209✔
124
        byteOrder.PutUint16(port[:], uint16(addr.Port))
209✔
125
        if _, err := w.Write(port[:]); err != nil {
209✔
126
                return err
×
127
        }
×
128

129
        return nil
209✔
130
}
131

132
// encodeDNSAddr serializes a DNS address into its compact raw bytes
133
// representation.
134
func encodeDNSAddr(w io.Writer, addr *lnwire.DNSAddr) error {
13✔
135
        // Create DNS address.
13✔
136
        dnsAddress, err := lnwire.NewDNSAddr(addr.Hostname, addr.Port)
13✔
137
        if err != nil {
13✔
NEW
138
                return err
×
NEW
139
        }
×
140

141
        // Validate DNS address.
142
        if err := dnsAddress.Validate(); err != nil {
16✔
143
                return err
3✔
144
        }
3✔
145

146
        // Write the address type.
147
        if _, err := w.Write([]byte{byte(dnsAddr)}); err != nil {
11✔
148
                return err
1✔
149
        }
1✔
150

151
        // Write the length of the hostname.
152
        hostnameLen := byte(len(addr.Hostname))
9✔
153
        if _, err := w.Write([]byte{hostnameLen}); err != nil {
10✔
154
                return err
1✔
155
        }
1✔
156

157
        // Write the hostname bytes.
158
        if _, err := w.Write([]byte(addr.Hostname)); err != nil {
9✔
159
                return err
1✔
160
        }
1✔
161

162
        // Write the port in big-endian order.
163
        var port [2]byte
7✔
164
        binary.BigEndian.PutUint16(port[:], uint16(addr.Port))
7✔
165
        if _, err := w.Write(port[:]); err != nil {
8✔
166
                return err
1✔
167
        }
1✔
168

169
        return nil
6✔
170
}
171

172
// encodeOpaqueAddrs serializes the lnwire.OpaqueAddrs type to a raw set of
173
// bytes that we will persist.
174
func encodeOpaqueAddrs(w io.Writer, addr *lnwire.OpaqueAddrs) error {
2✔
175
        // Write the type byte.
2✔
176
        if _, err := w.Write([]byte{byte(opaqueAddrs)}); err != nil {
2✔
177
                return err
×
178
        }
×
179

180
        // Write the length of the payload.
181
        var l [2]byte
2✔
182
        binary.BigEndian.PutUint16(l[:], uint16(len(addr.Payload)))
2✔
183
        if _, err := w.Write(l[:]); err != nil {
2✔
184
                return err
×
185
        }
×
186

187
        // Write the payload.
188
        _, err := w.Write(addr.Payload)
2✔
189

2✔
190
        return err
2✔
191
}
192

193
// DeserializeAddr reads the serialized raw representation of an address and
194
// deserializes it into the actual address. This allows us to avoid address
195
// resolution within the channeldb package.
196
func DeserializeAddr(r io.Reader) (net.Addr, error) {
11,306✔
197
        var addrType [1]byte
11,306✔
198
        if _, err := r.Read(addrType[:]); err != nil {
11,307✔
199
                return nil, err
1✔
200
        }
1✔
201

202
        var address net.Addr
11,305✔
203
        switch addressType(addrType[0]) {
11,305✔
204
        case tcp4Addr:
4,524✔
205
                var ip [4]byte
4,524✔
206
                if _, err := r.Read(ip[:]); err != nil {
4,524✔
207
                        return nil, err
×
208
                }
×
209

210
                var port [2]byte
4,524✔
211
                if _, err := r.Read(port[:]); err != nil {
4,524✔
212
                        return nil, err
×
213
                }
×
214

215
                address = &net.TCPAddr{
4,524✔
216
                        IP:   net.IP(ip[:]),
4,524✔
217
                        Port: int(binary.BigEndian.Uint16(port[:])),
4,524✔
218
                }
4,524✔
219

220
        case tcp6Addr:
6,562✔
221
                var ip [16]byte
6,562✔
222
                if _, err := r.Read(ip[:]); err != nil {
6,562✔
223
                        return nil, err
×
224
                }
×
225

226
                var port [2]byte
6,562✔
227
                if _, err := r.Read(port[:]); err != nil {
6,562✔
228
                        return nil, err
×
229
                }
×
230

231
                address = &net.TCPAddr{
6,562✔
232
                        IP:   net.IP(ip[:]),
6,562✔
233
                        Port: int(binary.BigEndian.Uint16(port[:])),
6,562✔
234
                }
6,562✔
235

236
        case v2OnionAddr:
107✔
237
                var h [tor.V2DecodedLen]byte
107✔
238
                if _, err := r.Read(h[:]); err != nil {
107✔
239
                        return nil, err
×
240
                }
×
241

242
                var p [2]byte
107✔
243
                if _, err := r.Read(p[:]); err != nil {
107✔
244
                        return nil, err
×
245
                }
×
246

247
                onionService := tor.Base32Encoding.EncodeToString(h[:])
107✔
248
                onionService += tor.OnionSuffix
107✔
249
                port := int(binary.BigEndian.Uint16(p[:]))
107✔
250

107✔
251
                address = &tor.OnionAddr{
107✔
252
                        OnionService: onionService,
107✔
253
                        Port:         port,
107✔
254
                }
107✔
255

256
        case v3OnionAddr:
107✔
257
                var h [tor.V3DecodedLen]byte
107✔
258
                if _, err := r.Read(h[:]); err != nil {
107✔
259
                        return nil, err
×
260
                }
×
261

262
                var p [2]byte
107✔
263
                if _, err := r.Read(p[:]); err != nil {
107✔
264
                        return nil, err
×
265
                }
×
266

267
                onionService := tor.Base32Encoding.EncodeToString(h[:])
107✔
268
                onionService += tor.OnionSuffix
107✔
269
                port := int(binary.BigEndian.Uint16(p[:]))
107✔
270

107✔
271
                address = &tor.OnionAddr{
107✔
272
                        OnionService: onionService,
107✔
273
                        Port:         port,
107✔
274
                }
107✔
275

276
        case opaqueAddrs:
3✔
277
                // Read the length of the payload.
3✔
278
                var l [2]byte
3✔
279
                if _, err := r.Read(l[:]); err != nil {
3✔
280
                        return nil, err
×
281
                }
×
282

283
                // Read the payload.
284
                payload := make([]byte, binary.BigEndian.Uint16(l[:]))
3✔
285
                if _, err := r.Read(payload); err != nil {
3✔
286
                        return nil, err
×
287
                }
×
288

289
                address = &lnwire.OpaqueAddrs{
3✔
290
                        Payload: payload,
3✔
291
                }
3✔
292

293
        case dnsAddr:
13✔
294
                var hostnameLen byte
13✔
295
                err := binary.Read(r, binary.BigEndian, &hostnameLen)
13✔
296
                if err != nil {
14✔
297
                        return nil, err
1✔
298
                }
1✔
299

300
                hostname := make([]byte, hostnameLen)
12✔
301
                if _, err := r.Read(hostname); err != nil {
13✔
302
                        return nil, err
1✔
303
                }
1✔
304

305
                var port [2]byte
11✔
306
                n, err := r.Read(port[:])
11✔
307
                if err != nil {
13✔
308
                        return nil, err
2✔
309
                }
2✔
310
                if n != 2 {
10✔
311
                        return nil, fmt.Errorf("expected to read 2 bytes for "+
1✔
312
                                "port, but got %d bytes", n)
1✔
313
                }
1✔
314

315
                dnsAddr, err := lnwire.NewDNSAddr(
8✔
316
                        string(hostname), int(binary.BigEndian.Uint16(port[:])),
8✔
317
                )
8✔
318
                if err != nil {
8✔
NEW
319
                        return nil, err
×
NEW
320
                }
×
321

322
                if err := dnsAddr.Validate(); err != nil {
9✔
323
                        return nil, err
1✔
324
                }
1✔
325

326
                address = dnsAddr
7✔
327

328
        default:
1✔
329
                return nil, ErrUnknownAddressType
1✔
330
        }
331

332
        return address, nil
11,298✔
333
}
334

335
// SerializeAddr serializes an address into its raw bytes representation so that
336
// it can be deserialized without requiring address resolution.
337
func SerializeAddr(w io.Writer, address net.Addr) error {
2,338✔
338
        switch addr := address.(type) {
2,338✔
339
        case *net.TCPAddr:
2,124✔
340
                return encodeTCPAddr(w, addr)
2,124✔
341
        case *tor.OnionAddr:
212✔
342
                return encodeOnionAddr(w, addr)
212✔
343
        case *lnwire.DNSAddr:
5✔
344
                return encodeDNSAddr(w, addr)
5✔
345
        case *lnwire.OpaqueAddrs:
2✔
346
                return encodeOpaqueAddrs(w, addr)
2✔
347
        default:
1✔
348
                return ErrUnknownAddressType
1✔
349
        }
350
}
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