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

lightningnetwork / lnd / 20342025150

18 Dec 2025 03:26PM UTC coverage: 65.128% (-0.07%) from 65.195%
20342025150

Pull #10414

github

web-flow
Merge ac96d94fa into 91423ee51
Pull Request #10414: [g175] graph/db: merge g175 types-prep side branch

449 of 836 new or added lines in 17 files covered. (53.71%)

133 existing lines in 29 files now uncovered.

138014 of 211911 relevant lines covered (65.13%)

20742.58 hits per line

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

78.95
/graph/db/models/node.go
1
package models
2

3
import (
4
        "fmt"
5
        "image/color"
6
        "net"
7
        "time"
8

9
        "github.com/btcsuite/btcd/btcec/v2"
10
        "github.com/lightningnetwork/lnd/fn/v2"
11
        "github.com/lightningnetwork/lnd/lnwire"
12
        "github.com/lightningnetwork/lnd/routing/route"
13
)
14

15
// Node represents an individual vertex/node within the channel graph.
16
// A node is connected to other nodes by one or more channel edges emanating
17
// from it. As the graph is directed, a node will also have an incoming edge
18
// attached to it for each outgoing edge.
19
type Node struct {
20
        // Version is the gossip version that this node was advertised on.
21
        Version lnwire.GossipVersion
22

23
        // PubKeyBytes is the raw bytes of the public key of the target node.
24
        PubKeyBytes [33]byte
25

26
        // LastUpdate is the last time the vertex information for this node has
27
        // been updated.
28
        LastUpdate time.Time
29

30
        // LastBlockHeight is the block height that timestamps the last update
31
        // we received for this node. This is only used if this is a V2 node
32
        // announcement.
33
        LastBlockHeight uint32
34

35
        // Address is the TCP address this node is reachable over.
36
        Addresses []net.Addr
37

38
        // Color is the selected color for the node.
39
        Color fn.Option[color.RGBA]
40

41
        // Alias is a nick-name for the node. The alias can be used to confirm
42
        // a node's identity or to serve as a short ID for an address book.
43
        Alias fn.Option[string]
44

45
        // AuthSigBytes is the raw signature under the advertised public key
46
        // which serves to authenticate the attributes announced by this node.
47
        AuthSigBytes []byte
48

49
        // Features is the list of protocol features supported by this node.
50
        Features *lnwire.FeatureVector
51

52
        // ExtraOpaqueData is the set of data that was appended to this
53
        // message, some of which we may not actually know how to iterate or
54
        // parse. By holding onto this data, we ensure that we're able to
55
        // properly validate the set of signatures that cover these new fields,
56
        // and ensure we're able to make upgrades to the network in a forwards
57
        // compatible manner. This is only used for V1 node announcements.
58
        ExtraOpaqueData []byte
59

60
        // ExtraSignedFields is a map of extra fields that are covered by the
61
        // node announcement's signature that we have not explicitly parsed.
62
        // This is only used for version 2 node announcements and beyond.
63
        ExtraSignedFields map[uint64][]byte
64
}
65

66
// NodeV1Fields houses the fields that are specific to a version 1 node
67
// announcement.
68
type NodeV1Fields struct {
69
        // Address is the TCP address this node is reachable over.
70
        Addresses []net.Addr
71

72
        // AuthSigBytes is the raw signature under the advertised public key
73
        // which serves to authenticate the attributes announced by this node.
74
        AuthSigBytes []byte
75

76
        // Features is the list of protocol features supported by this node.
77
        Features *lnwire.RawFeatureVector
78

79
        // Color is the selected color for the node.
80
        Color color.RGBA
81

82
        // Alias is a nick-name for the node. The alias can be used to confirm
83
        // a node's identity or to serve as a short ID for an address book.
84
        Alias string
85

86
        // LastUpdate is the last time the vertex information for this node has
87
        // been updated.
88
        LastUpdate time.Time
89

90
        // ExtraOpaqueData is the set of data that was appended to this
91
        // message, some of which we may not actually know how to iterate or
92
        // parse. By holding onto this data, we ensure that we're able to
93
        // properly validate the set of signatures that cover these new fields,
94
        // and ensure we're able to make upgrades to the network in a forwards
95
        // compatible manner.
96
        ExtraOpaqueData []byte
97
}
98

99
// NewV1Node creates a new version 1 node from the passed fields.
100
func NewV1Node(pub route.Vertex, n *NodeV1Fields) *Node {
1,133✔
101
        return &Node{
1,133✔
102
                Version:      lnwire.GossipVersion1,
1,133✔
103
                PubKeyBytes:  pub,
1,133✔
104
                Addresses:    n.Addresses,
1,133✔
105
                AuthSigBytes: n.AuthSigBytes,
1,133✔
106
                Features: lnwire.NewFeatureVector(
1,133✔
107
                        n.Features, lnwire.Features,
1,133✔
108
                ),
1,133✔
109
                Color:           fn.Some(n.Color),
1,133✔
110
                Alias:           fn.Some(n.Alias),
1,133✔
111
                LastUpdate:      n.LastUpdate,
1,133✔
112
                ExtraOpaqueData: n.ExtraOpaqueData,
1,133✔
113
        }
1,133✔
114
}
1,133✔
115

116
// NodeV2Fields houses the fields that are specific to a version 2 node
117
// announcement.
118
type NodeV2Fields struct {
119
        // LastBlockHeight is the block height that timestamps the last update
120
        // we received for this node.
121
        LastBlockHeight uint32
122

123
        // Address is the TCP address this node is reachable over.
124
        Addresses []net.Addr
125

126
        // Color is the selected color for the node.
127
        Color fn.Option[color.RGBA]
128

129
        // Alias is a nick-name for the node. The alias can be used to confirm
130
        // a node's identity or to serve as a short ID for an address book.
131
        Alias fn.Option[string]
132

133
        // Signature is the schnorr signature under the advertised public key
134
        // which serves to authenticate the attributes announced by this node.
135
        Signature []byte
136

137
        // Features is the list of protocol features supported by this node.
138
        Features *lnwire.RawFeatureVector
139

140
        // ExtraSignedFields is a map of extra fields that are covered by the
141
        // node announcement's signature that we have not explicitly parsed.
142
        ExtraSignedFields map[uint64][]byte
143
}
144

145
// NewV2Node creates a new version 2 node from the passed fields.
NEW
146
func NewV2Node(pub route.Vertex, n *NodeV2Fields) *Node {
×
NEW
147
        return &Node{
×
NEW
148
                Version:      lnwire.GossipVersion2,
×
NEW
149
                PubKeyBytes:  pub,
×
NEW
150
                Addresses:    n.Addresses,
×
NEW
151
                AuthSigBytes: n.Signature,
×
NEW
152
                Features: lnwire.NewFeatureVector(
×
NEW
153
                        n.Features, lnwire.Features,
×
NEW
154
                ),
×
NEW
155
                LastBlockHeight:   n.LastBlockHeight,
×
NEW
156
                Color:             n.Color,
×
NEW
157
                Alias:             n.Alias,
×
NEW
158
                LastUpdate:        time.Unix(0, 0),
×
NEW
159
                ExtraSignedFields: n.ExtraSignedFields,
×
NEW
160
        }
×
NEW
161
}
×
162

163
// NewV1ShellNode creates a new shell version 1 node.
164
func NewV1ShellNode(pubKey route.Vertex) *Node {
9,573✔
165
        return NewShellNode(lnwire.GossipVersion1, pubKey)
9,573✔
166
}
9,573✔
167

168
// NewShellNode creates a new shell node with the given gossip version and
169
// public key.
170
func NewShellNode(v lnwire.GossipVersion, pubKey route.Vertex) *Node {
9,573✔
171
        return &Node{
9,573✔
172
                Version:     v,
9,573✔
173
                PubKeyBytes: pubKey,
9,573✔
174
                Features:    lnwire.EmptyFeatureVector(),
9,573✔
175
                LastUpdate:  time.Unix(0, 0),
9,573✔
176
        }
9,573✔
177
}
9,573✔
178

179
// HaveAnnouncement returns true if we have received a node announcement for
180
// this node. We determine this by checking if we have a signature for the
181
// announcement.
182
func (n *Node) HaveAnnouncement() bool {
1,190✔
183
        return len(n.AuthSigBytes) > 0
1,190✔
184
}
1,190✔
185

186
// PubKey is the node's long-term identity public key. This key will be used to
187
// authenticated any advertisements/updates sent by the node.
188
func (n *Node) PubKey() (*btcec.PublicKey, error) {
2,897✔
189
        return btcec.ParsePubKey(n.PubKeyBytes[:])
2,897✔
190
}
2,897✔
191

192
// NodeAnnouncement retrieves the latest node announcement of the node.
193
func (n *Node) NodeAnnouncement(signed bool) (*lnwire.NodeAnnouncement1,
194
        error) {
18✔
195

18✔
196
        // Error out if we request the signed announcement, but we don't have
18✔
197
        // a signature for this announcement.
18✔
198
        if !n.HaveAnnouncement() && signed {
21✔
199
                return nil, fmt.Errorf("node does not have node announcement")
3✔
200
        }
3✔
201

202
        alias, err := lnwire.NewNodeAlias(n.Alias.UnwrapOr(""))
18✔
203
        if err != nil {
18✔
204
                return nil, err
×
205
        }
×
206

207
        nodeAnn := &lnwire.NodeAnnouncement1{
18✔
208
                Features:        n.Features.RawFeatureVector,
18✔
209
                NodeID:          n.PubKeyBytes,
18✔
210
                RGBColor:        n.Color.UnwrapOr(color.RGBA{}),
18✔
211
                Alias:           alias,
18✔
212
                Addresses:       n.Addresses,
18✔
213
                Timestamp:       uint32(n.LastUpdate.Unix()),
18✔
214
                ExtraOpaqueData: n.ExtraOpaqueData,
18✔
215
        }
18✔
216

18✔
217
        if !signed {
21✔
218
                return nodeAnn, nil
3✔
219
        }
3✔
220

221
        sig, err := lnwire.NewSigFromECDSARawSignature(n.AuthSigBytes)
18✔
222
        if err != nil {
18✔
223
                return nil, err
×
224
        }
×
225

226
        nodeAnn.Signature = sig
18✔
227

18✔
228
        return nodeAnn, nil
18✔
229
}
230

231
// NodeFromWireAnnouncement creates a Node instance from an
232
// lnwire.NodeAnnouncement1 message.
233
func NodeFromWireAnnouncement(msg *lnwire.NodeAnnouncement1) *Node {
20✔
234
        timestamp := time.Unix(int64(msg.Timestamp), 0)
20✔
235

20✔
236
        return NewV1Node(
20✔
237
                msg.NodeID,
20✔
238
                &NodeV1Fields{
20✔
239
                        LastUpdate:      timestamp,
20✔
240
                        Addresses:       msg.Addresses,
20✔
241
                        Alias:           msg.Alias.String(),
20✔
242
                        AuthSigBytes:    msg.Signature.ToSignatureBytes(),
20✔
243
                        Features:        msg.Features,
20✔
244
                        Color:           msg.RGBColor,
20✔
245
                        ExtraOpaqueData: msg.ExtraOpaqueData,
20✔
246
                },
20✔
247
        )
20✔
248
}
20✔
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

© 2026 Coveralls, Inc