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

lightningnetwork / lnd / 19027031130

03 Nov 2025 07:27AM UTC coverage: 56.922% (-9.7%) from 66.639%
19027031130

Pull #9334

github

web-flow
Merge b9be11a16 into f938e40af
Pull Request #9334: Use all valid routes during blinded path construction

9 of 11 new or added lines in 3 files covered. (81.82%)

29175 existing lines in 461 files now uncovered.

99696 of 175144 relevant lines covered (56.92%)

1.77 hits per line

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

0.0
/lnwire/dns_addr.go
1
package lnwire
2

3
import (
4
        "bytes"
5
        "errors"
6
        "fmt"
7
        "io"
8
        "net"
9
        "strconv"
10

11
        "github.com/lightningnetwork/lnd/tlv"
12
)
13

14
var (
15
        // ErrEmptyDNSHostname is returned when a DNS hostname is empty.
16
        ErrEmptyDNSHostname = errors.New("hostname cannot be empty")
17

18
        // ErrZeroPort is returned when a DNS port is zero.
19
        ErrZeroPort = errors.New("port cannot be zero")
20

21
        // ErrHostnameTooLong is returned when a DNS hostname exceeds 255 bytes.
22
        ErrHostnameTooLong = errors.New("DNS hostname length exceeds limit " +
23
                "of 255 bytes")
24

25
        // ErrInvalidHostnameCharacter is returned when a DNS hostname contains
26
        // an invalid character.
27
        ErrInvalidHostnameCharacter = errors.New("hostname contains invalid " +
28
                "character")
29
)
30

31
// DNSAddress is used to represent a DNS address of a node.
32
type DNSAddress struct {
33
        // Hostname is the DNS hostname of the address. This MUST only contain
34
        // ASCII characters as per Bolt #7. The maximum length that this may
35
        // be is 255 bytes.
36
        Hostname string
37

38
        // Port is the port number of the address.
39
        Port uint16
40
}
41

42
// A compile-time check to ensure that DNSAddress implements the net.Addr
43
// interface.
44
var _ net.Addr = (*DNSAddress)(nil)
45

46
// Network returns the network that this address uses, which is "tcp".
47
func (d *DNSAddress) Network() string {
×
48
        return "tcp"
×
49
}
×
50

51
// String returns the address in the form "hostname:port".
UNCOV
52
func (d *DNSAddress) String() string {
×
UNCOV
53
        return net.JoinHostPort(d.Hostname, strconv.Itoa(int(d.Port)))
×
UNCOV
54
}
×
55

56
// ValidateDNSAddr validates that the DNS hostname is not empty and contains
57
// only ASCII characters and of max length 255 characters and port is non zero
58
// according to BOLT #7.
UNCOV
59
func ValidateDNSAddr(hostname string, port uint16) error {
×
UNCOV
60
        if hostname == "" {
×
UNCOV
61
                return ErrEmptyDNSHostname
×
UNCOV
62
        }
×
63

64
        // Per BOLT 7, ports must not be zero for type 5 address (DNS address).
UNCOV
65
        if port == 0 {
×
UNCOV
66
                return ErrZeroPort
×
UNCOV
67
        }
×
68

UNCOV
69
        if len(hostname) > 255 {
×
UNCOV
70
                return fmt.Errorf("%w: DNS hostname length %d",
×
UNCOV
71
                        ErrHostnameTooLong, len(hostname))
×
UNCOV
72
        }
×
73

74
        // Check if hostname contains only ASCII characters.
UNCOV
75
        for i, r := range hostname {
×
UNCOV
76
                // Check for valid hostname characters, excluding ASCII control
×
UNCOV
77
                // characters (0-31), spaces, underscores, delete character
×
UNCOV
78
                // (127), and the special characters (like /, \, @, #, $, etc.).
×
UNCOV
79
                if !((r >= 'a' && r <= 'z') ||
×
UNCOV
80
                        (r >= 'A' && r <= 'Z') ||
×
UNCOV
81
                        (r >= '0' && r <= '9') ||
×
UNCOV
82
                        r == '-' ||
×
UNCOV
83
                        r == '.') {
×
UNCOV
84

×
UNCOV
85
                        return fmt.Errorf("%w: hostname '%s' contains invalid "+
×
UNCOV
86
                                "character '%c' at position %d",
×
UNCOV
87
                                ErrInvalidHostnameCharacter, hostname, r, i)
×
UNCOV
88
                }
×
89
        }
90

UNCOV
91
        return nil
×
92
}
93

94
// Record returns a TLV record that can be used to encode/decode the DNSAddress.
95
//
96
// NOTE: this is part of the tlv.RecordProducer interface.
UNCOV
97
func (d *DNSAddress) Record() tlv.Record {
×
UNCOV
98
        sizeFunc := func() uint64 {
×
UNCOV
99
                // Hostname length + 2 bytes for port.
×
UNCOV
100
                return uint64(len(d.Hostname) + 2)
×
UNCOV
101
        }
×
102

UNCOV
103
        return tlv.MakeDynamicRecord(
×
UNCOV
104
                0, d, sizeFunc, dnsAddressEncoder, dnsAddressDecoder,
×
UNCOV
105
        )
×
106
}
107

108
// dnsAddressEncoder is a TLV encoder for DNSAddress.
UNCOV
109
func dnsAddressEncoder(w io.Writer, val any, _ *[8]byte) error {
×
UNCOV
110
        if v, ok := val.(*DNSAddress); ok {
×
UNCOV
111
                var buf bytes.Buffer
×
UNCOV
112

×
UNCOV
113
                // Write the hostname as raw bytes (no length prefix for TLV).
×
UNCOV
114
                if _, err := buf.WriteString(v.Hostname); err != nil {
×
115
                        return err
×
116
                }
×
117

118
                // Write the port as 2 bytes.
UNCOV
119
                err := WriteUint16(&buf, v.Port)
×
UNCOV
120
                if err != nil {
×
121
                        return err
×
122
                }
×
123

UNCOV
124
                _, err = w.Write(buf.Bytes())
×
UNCOV
125

×
UNCOV
126
                return err
×
127
        }
128

129
        return tlv.NewTypeForEncodingErr(val, "DNSAddress")
×
130
}
131

132
// dnsAddressDecoder is a TLV decoder for DNSAddress.
133
func dnsAddressDecoder(r io.Reader, val any, _ *[8]byte,
UNCOV
134
        l uint64) error {
×
UNCOV
135

×
UNCOV
136
        if v, ok := val.(*DNSAddress); ok {
×
UNCOV
137
                if l < 2 {
×
UNCOV
138
                        return fmt.Errorf("DNS address must be at least 2 " +
×
UNCOV
139
                                "bytes")
×
UNCOV
140
                }
×
141

142
                // Read hostname (all bytes except last 2).
UNCOV
143
                hostnameLen := l - 2
×
UNCOV
144
                hostnameBytes := make([]byte, hostnameLen)
×
UNCOV
145
                if _, err := io.ReadFull(r, hostnameBytes); err != nil {
×
146
                        return err
×
147
                }
×
UNCOV
148
                v.Hostname = string(hostnameBytes)
×
UNCOV
149

×
UNCOV
150
                // Read port (last 2 bytes).
×
UNCOV
151
                if err := ReadElement(r, &v.Port); err != nil {
×
152
                        return err
×
153
                }
×
154

UNCOV
155
                return ValidateDNSAddr(v.Hostname, v.Port)
×
156
        }
157

158
        return tlv.NewTypeForDecodingErr(val, "DNSAddress", l, 0)
×
159
}
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