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

lightningnetwork / lnd / 17949158775

23 Sep 2025 02:18PM UTC coverage: 66.713% (+0.07%) from 66.647%
17949158775

Pull #10232

github

web-flow
Merge fc770ddb4 into 82f77e542
Pull Request #10232: lnwire: add missing Gossip 1.75 fields and message

491 of 568 new or added lines in 19 files covered. (86.44%)

64 existing lines in 19 files now uncovered.

136915 of 205230 relevant lines covered (66.71%)

21387.93 hits per line

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

70.24
/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.NodeAnnouncement1.
20
type NodeAnnModifier func(*lnwire.NodeAnnouncement1)
21

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

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

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

46
// NodeAnnSetFeatures is a functional option that allows updating the features of
47
// the given node announcement.
48
func NodeAnnSetFeatures(
49
        features *lnwire.RawFeatureVector) func(*lnwire.NodeAnnouncement1) {
3✔
50

3✔
51
        return func(nodeAnn *lnwire.NodeAnnouncement1) {
6✔
52
                nodeAnn.Features = features
3✔
53
        }
3✔
54
}
55

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

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

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

82
        // Parse the DER-encoded signature into a fixed-size 64-byte array.
83
        nodeAnn.Signature, err = lnwire.NewSigFromSignature(sig)
3✔
84
        return err
3✔
85
}
86

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

94
        return ValidateNodeAnnSignature(a)
20✔
95
}
96

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

111
                hasDNSAddr = true
×
112

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

119
        return nil
34✔
120
}
121

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

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

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

NEW
151
                return fmt.Errorf("signature on NodeAnnouncement1(%x) is "+
×
152
                        "invalid: %x", nodeKey.SerializeCompressed(),
×
153
                        msgBuf.Bytes())
×
154
        }
155

156
        return nil
19✔
157
}
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