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

lightningnetwork / lnd / 18016273007

25 Sep 2025 05:55PM UTC coverage: 54.653% (-12.0%) from 66.622%
18016273007

Pull #10248

github

web-flow
Merge 128443298 into b09b20c69
Pull Request #10248: Enforce TLV when creating a Route

25 of 30 new or added lines in 4 files covered. (83.33%)

23906 existing lines in 281 files now uncovered.

109536 of 200421 relevant lines covered (54.65%)

21816.97 hits per line

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

31.33
/netann/node_announcement.go
1
package netann
2

3
import (
4
        "bytes"
5
        "errors"
6
        "fmt"
7
        "image/color"
8
        "net"
9
        "time"
10

11
        "github.com/btcsuite/btcd/btcec/v2"
12
        "github.com/btcsuite/btcd/chaincfg/chainhash"
13
        "github.com/lightningnetwork/lnd/keychain"
14
        "github.com/lightningnetwork/lnd/lnwallet"
15
        "github.com/lightningnetwork/lnd/lnwire"
16
)
17

18
// NodeAnnModifier is a closure that makes in-place modifications to an
19
// lnwire.NodeAnnouncement.
20
type NodeAnnModifier func(*lnwire.NodeAnnouncement)
21

22
// NodeAnnSetAlias is a functional option that sets the alias of the
23
// given node announcement.
UNCOV
24
func NodeAnnSetAlias(alias lnwire.NodeAlias) func(*lnwire.NodeAnnouncement) {
×
UNCOV
25
        return func(nodeAnn *lnwire.NodeAnnouncement) {
×
UNCOV
26
                nodeAnn.Alias = alias
×
UNCOV
27
        }
×
28
}
29

30
// NodeAnnSetAddrs is a functional option that allows updating the addresses of
31
// the given node announcement.
UNCOV
32
func NodeAnnSetAddrs(addrs []net.Addr) func(*lnwire.NodeAnnouncement) {
×
UNCOV
33
        return func(nodeAnn *lnwire.NodeAnnouncement) {
×
UNCOV
34
                nodeAnn.Addresses = addrs
×
UNCOV
35
        }
×
36
}
37

38
// NodeAnnSetColor is a functional option that sets the color of the
39
// given node announcement.
UNCOV
40
func NodeAnnSetColor(newColor color.RGBA) func(*lnwire.NodeAnnouncement) {
×
UNCOV
41
        return func(nodeAnn *lnwire.NodeAnnouncement) {
×
UNCOV
42
                nodeAnn.RGBColor = newColor
×
UNCOV
43
        }
×
44
}
45

46
// NodeAnnSetFeatures is a functional option that allows updating the features of
47
// the given node announcement.
UNCOV
48
func NodeAnnSetFeatures(features *lnwire.RawFeatureVector) func(*lnwire.NodeAnnouncement) {
×
UNCOV
49
        return func(nodeAnn *lnwire.NodeAnnouncement) {
×
UNCOV
50
                nodeAnn.Features = features
×
UNCOV
51
        }
×
52
}
53

54
// NodeAnnSetTimestamp is a functional option that sets the timestamp of the
55
// announcement to the current time, or increments it if the timestamp is
56
// already in the future.
UNCOV
57
func NodeAnnSetTimestamp(nodeAnn *lnwire.NodeAnnouncement) {
×
UNCOV
58
        newTimestamp := uint32(time.Now().Unix())
×
UNCOV
59
        if newTimestamp <= nodeAnn.Timestamp {
×
UNCOV
60
                // Increment the prior value to  ensure the timestamp
×
UNCOV
61
                // monotonically increases, otherwise the announcement won't
×
UNCOV
62
                // propagate.
×
UNCOV
63
                newTimestamp = nodeAnn.Timestamp + 1
×
UNCOV
64
        }
×
UNCOV
65
        nodeAnn.Timestamp = newTimestamp
×
66
}
67

68
// SignNodeAnnouncement signs the lnwire.NodeAnnouncement provided, which
69
// should be the most recent, valid update, otherwise the timestamp may not
70
// monotonically increase from the prior.
71
func SignNodeAnnouncement(signer lnwallet.MessageSigner,
UNCOV
72
        keyLoc keychain.KeyLocator, nodeAnn *lnwire.NodeAnnouncement) error {
×
UNCOV
73

×
UNCOV
74
        // Create the DER-encoded ECDSA signature over the message digest.
×
UNCOV
75
        sig, err := SignAnnouncement(signer, keyLoc, nodeAnn)
×
UNCOV
76
        if err != nil {
×
77
                return err
×
78
        }
×
79

80
        // Parse the DER-encoded signature into a fixed-size 64-byte array.
UNCOV
81
        nodeAnn.Signature, err = lnwire.NewSigFromSignature(sig)
×
UNCOV
82
        return err
×
83
}
84

85
// ValidateNodeAnn validates the fields and signature of a node announcement.
86
func ValidateNodeAnn(a *lnwire.NodeAnnouncement) error {
17✔
87
        err := ValidateNodeAnnFields(a)
17✔
88
        if err != nil {
17✔
89
                return fmt.Errorf("invalid node announcement fields: %w", err)
×
90
        }
×
91

92
        return ValidateNodeAnnSignature(a)
17✔
93
}
94

95
// ValidateNodeAnnFields validates the fields of a node announcement.
96
func ValidateNodeAnnFields(a *lnwire.NodeAnnouncement) error {
31✔
97
        // Check that it only has at most one DNS address.
31✔
98
        hasDNSAddr := false
31✔
99
        for _, addr := range a.Addresses {
61✔
100
                dnsAddr, ok := addr.(*lnwire.DNSAddress)
30✔
101
                if !ok {
60✔
102
                        continue
30✔
103
                }
104
                if hasDNSAddr {
×
105
                        return errors.New("node announcement contains " +
×
106
                                "multiple DNS addresses. Only one is allowed")
×
107
                }
×
108

109
                hasDNSAddr = true
×
110

×
111
                err := lnwire.ValidateDNSAddr(dnsAddr.Hostname, dnsAddr.Port)
×
112
                if err != nil {
×
113
                        return err
×
114
                }
×
115
        }
116

117
        return nil
31✔
118
}
119

120
// ValidateNodeAnnSignature validates the node announcement by ensuring that the
121
// attached signature is needed a signature of the node announcement under the
122
// specified node public key.
123
func ValidateNodeAnnSignature(a *lnwire.NodeAnnouncement) error {
17✔
124
        // Reconstruct the data of announcement which should be covered by the
17✔
125
        // signature so we can verify the signature shortly below
17✔
126
        data, err := a.DataToSign()
17✔
127
        if err != nil {
18✔
128
                return err
1✔
129
        }
1✔
130

131
        nodeSig, err := a.Signature.ToSignature()
16✔
132
        if err != nil {
16✔
133
                return err
×
134
        }
×
135
        nodeKey, err := btcec.ParsePubKey(a.NodeID[:])
16✔
136
        if err != nil {
16✔
137
                return err
×
138
        }
×
139

140
        // Finally ensure that the passed signature is valid, if not we'll
141
        // return an error so this node announcement can be rejected.
142
        dataHash := chainhash.DoubleHashB(data)
16✔
143
        if !nodeSig.Verify(dataHash, nodeKey) {
16✔
144
                var msgBuf bytes.Buffer
×
145
                if _, err := lnwire.WriteMessage(&msgBuf, a, 0); err != nil {
×
146
                        return err
×
147
                }
×
148

149
                return fmt.Errorf("signature on NodeAnnouncement(%x) is "+
×
150
                        "invalid: %x", nodeKey.SerializeCompressed(),
×
151
                        msgBuf.Bytes())
×
152
        }
153

154
        return nil
16✔
155
}
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