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

lightningnetwork / lnd / 15280233992

27 May 2025 04:07PM UTC coverage: 58.56% (+0.6%) from 57.977%
15280233992

Pull #9455

github

web-flow
Merge 015c776a9 into 93a6ab875
Pull Request #9455: discovery+lnwire: add support for DNS host name in NodeAnnouncement msg

145 of 291 new or added lines in 7 files covered. (49.83%)

120 existing lines in 10 files now uncovered.

97608 of 166681 relevant lines covered (58.56%)

1.82 hits per line

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

56.19
/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 {
3✔
42
        var (
3✔
43
                addrType byte
3✔
44
                ip       []byte
3✔
45
        )
3✔
46

3✔
47
        if addr.IP.To4() != nil {
6✔
48
                addrType = byte(tcp4Addr)
3✔
49
                ip = addr.IP.To4()
3✔
50
        } else {
6✔
51
                addrType = byte(tcp6Addr)
3✔
52
                ip = addr.IP.To16()
3✔
53
        }
3✔
54

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

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

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

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

73
        return nil
3✔
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 {
3✔
79
        var suffixIndex int
3✔
80
        hostLen := len(addr.OnionService)
3✔
81
        switch hostLen {
3✔
82
        case tor.V2Len:
3✔
83
                if _, err := w.Write([]byte{byte(v2OnionAddr)}); err != nil {
3✔
84
                        return err
×
85
                }
×
86
                suffixIndex = tor.V2Len - tor.OnionSuffixLen
3✔
87
        case tor.V3Len:
3✔
88
                if _, err := w.Write([]byte{byte(v3OnionAddr)}); err != nil {
3✔
89
                        return err
×
90
                }
×
91
                suffixIndex = tor.V3Len - tor.OnionSuffixLen
3✔
92
        default:
×
93
                return errors.New("unknown onion service length")
×
94
        }
95

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

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

108
        // Sanity check the decoded length.
109
        switch {
3✔
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 {
3✔
120
                return err
×
121
        }
×
122

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

129
        return nil
3✔
130
}
131

132
// encodeOpaqueAddrs serializes the lnwire.OpaqueAddrs type to a raw set of
133
// bytes that we will persist.
134
func encodeOpaqueAddrs(w io.Writer, addr *lnwire.OpaqueAddrs) error {
×
135
        // Write the type byte.
×
136
        if _, err := w.Write([]byte{byte(opaqueAddrs)}); err != nil {
×
137
                return err
×
138
        }
×
139

140
        // Write the length of the payload.
141
        var l [2]byte
×
142
        binary.BigEndian.PutUint16(l[:], uint16(len(addr.Payload)))
×
143
        if _, err := w.Write(l[:]); err != nil {
×
144
                return err
×
145
        }
×
146

147
        // Write the payload.
148
        _, err := w.Write(addr.Payload)
×
149

×
150
        return err
×
151
}
152

153
// encodeDNSAddr serializes a DNS address into its compact raw bytes
154
// representation. It writes the address type, hostname length, hostname, and
155
// port (in big-endian order) to the writer. The function validates that the
156
// DNS address. Returns an error if any part of the serialization fails.
157
func encodeDNSAddr(w io.Writer, addr *lnwire.DNSAddr) error {
3✔
158
        // Validate DNS address.
3✔
159
        _, err := lnwire.NewDNSAddr(addr.Hostname, addr.Port)
3✔
160
        if err != nil {
3✔
NEW
161
                return err
×
NEW
162
        }
×
163

164
        // Write the address type.
165
        if _, err := w.Write([]byte{byte(dnsAddr)}); err != nil {
3✔
NEW
166
                return err
×
NEW
167
        }
×
168

169
        // Write the length of the hostname.
170
        hostnameLen := byte(len(addr.Hostname))
3✔
171
        if _, err := w.Write([]byte{hostnameLen}); err != nil {
3✔
NEW
172
                return err
×
NEW
173
        }
×
174

175
        // Write the hostname bytes.
176
        if _, err := w.Write([]byte(addr.Hostname)); err != nil {
3✔
NEW
177
                return err
×
NEW
178
        }
×
179

180
        // Write the port in big-endian order.
181
        var port [2]byte
3✔
182
        binary.BigEndian.PutUint16(port[:], uint16(addr.Port))
3✔
183
        if _, err := w.Write(port[:]); err != nil {
3✔
NEW
184
                return err
×
NEW
185
        }
×
186

187
        return nil
3✔
188
}
189

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

199
        var address net.Addr
3✔
200
        switch addressType(addrType[0]) {
3✔
201
        case tcp4Addr:
3✔
202
                var ip [4]byte
3✔
203
                if _, err := r.Read(ip[:]); err != nil {
3✔
204
                        return nil, err
×
205
                }
×
206

207
                var port [2]byte
3✔
208
                if _, err := r.Read(port[:]); err != nil {
3✔
209
                        return nil, err
×
210
                }
×
211

212
                address = &net.TCPAddr{
3✔
213
                        IP:   net.IP(ip[:]),
3✔
214
                        Port: int(binary.BigEndian.Uint16(port[:])),
3✔
215
                }
3✔
216

217
        case tcp6Addr:
3✔
218
                var ip [16]byte
3✔
219
                if _, err := r.Read(ip[:]); err != nil {
3✔
220
                        return nil, err
×
221
                }
×
222

223
                var port [2]byte
3✔
224
                if _, err := r.Read(port[:]); err != nil {
3✔
225
                        return nil, err
×
226
                }
×
227

228
                address = &net.TCPAddr{
3✔
229
                        IP:   net.IP(ip[:]),
3✔
230
                        Port: int(binary.BigEndian.Uint16(port[:])),
3✔
231
                }
3✔
232

233
        case v2OnionAddr:
3✔
234
                var h [tor.V2DecodedLen]byte
3✔
235
                if _, err := r.Read(h[:]); err != nil {
3✔
236
                        return nil, err
×
237
                }
×
238

239
                var p [2]byte
3✔
240
                if _, err := r.Read(p[:]); err != nil {
3✔
241
                        return nil, err
×
242
                }
×
243

244
                onionService := tor.Base32Encoding.EncodeToString(h[:])
3✔
245
                onionService += tor.OnionSuffix
3✔
246
                port := int(binary.BigEndian.Uint16(p[:]))
3✔
247

3✔
248
                address = &tor.OnionAddr{
3✔
249
                        OnionService: onionService,
3✔
250
                        Port:         port,
3✔
251
                }
3✔
252

253
        case v3OnionAddr:
3✔
254
                var h [tor.V3DecodedLen]byte
3✔
255
                if _, err := r.Read(h[:]); err != nil {
3✔
256
                        return nil, err
×
257
                }
×
258

259
                var p [2]byte
3✔
260
                if _, err := r.Read(p[:]); err != nil {
3✔
261
                        return nil, err
×
262
                }
×
263

264
                onionService := tor.Base32Encoding.EncodeToString(h[:])
3✔
265
                onionService += tor.OnionSuffix
3✔
266
                port := int(binary.BigEndian.Uint16(p[:]))
3✔
267

3✔
268
                address = &tor.OnionAddr{
3✔
269
                        OnionService: onionService,
3✔
270
                        Port:         port,
3✔
271
                }
3✔
272

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

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

286
                address = &lnwire.OpaqueAddrs{
×
287
                        Payload: payload,
×
288
                }
×
289

290
        case dnsAddr:
3✔
291
                var hostnameLen byte
3✔
292
                err := binary.Read(r, binary.BigEndian, &hostnameLen)
3✔
293
                if err != nil {
3✔
NEW
294
                        return nil, err
×
NEW
295
                }
×
296

297
                hostname := make([]byte, hostnameLen)
3✔
298
                if _, err := r.Read(hostname); err != nil {
3✔
NEW
299
                        return nil, err
×
NEW
300
                }
×
301

302
                var port [2]byte
3✔
303
                n, err := r.Read(port[:])
3✔
304
                if err != nil {
3✔
NEW
305
                        return nil, err
×
NEW
306
                }
×
307
                if n != 2 {
3✔
NEW
308
                        return nil, fmt.Errorf("expected to read 2 bytes for "+
×
NEW
309
                                "port, but got %d bytes", n)
×
NEW
310
                }
×
311

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

319
                address = dnsAddr
3✔
320

321
        default:
×
322
                return nil, ErrUnknownAddressType
×
323
        }
324

325
        return address, nil
3✔
326
}
327

328
// SerializeAddr serializes an address into its raw bytes representation so that
329
// it can be deserialized without requiring address resolution.
330
func SerializeAddr(w io.Writer, address net.Addr) error {
3✔
331
        switch addr := address.(type) {
3✔
332
        case *net.TCPAddr:
3✔
333
                return encodeTCPAddr(w, addr)
3✔
334
        case *tor.OnionAddr:
3✔
335
                return encodeOnionAddr(w, addr)
3✔
336
        case *lnwire.DNSAddr:
3✔
337
                return encodeDNSAddr(w, addr)
3✔
338
        case *lnwire.OpaqueAddrs:
×
339
                return encodeOpaqueAddrs(w, addr)
×
340
        default:
×
341
                return ErrUnknownAddressType
×
342
        }
343
}
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