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

lightningnetwork / lnd / 12293715361

12 Dec 2024 09:38AM UTC coverage: 57.483% (+7.9%) from 49.538%
12293715361

Pull #9348

github

ziggie1984
github: update goveralls tool

The goverall tool had a bug regarding the module versioning of
golang packages see also
https://github.com/mattn/goveralls/pull/222 for more background.
Goveralls is wrapped by another library to make it available for
github actions. So the relevant PR which is referenced here in
LND is:
https://github.com/shogo82148/actions-goveralls/pull/521.
Pull Request #9348: github: update goveralls tool

101897 of 177264 relevant lines covered (57.48%)

24982.4 hits per line

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

0.0
/discovery/chan_series.go
1
package discovery
2

3
import (
4
        "time"
5

6
        "github.com/btcsuite/btcd/chaincfg/chainhash"
7
        graphdb "github.com/lightningnetwork/lnd/graph/db"
8
        "github.com/lightningnetwork/lnd/lnwire"
9
        "github.com/lightningnetwork/lnd/netann"
10
        "github.com/lightningnetwork/lnd/routing/route"
11
)
12

13
// ChannelGraphTimeSeries is an interface that provides time and block based
14
// querying into our view of the channel graph. New channels will have
15
// monotonically increasing block heights, and new channel updates will have
16
// increasing timestamps. Once we connect to a peer, we'll use the methods in
17
// this interface to determine if we're already in sync, or need to request
18
// some new information from them.
19
type ChannelGraphTimeSeries interface {
20
        // HighestChanID should return the channel ID of the channel we know of
21
        // that's furthest in the target chain. This channel will have a block
22
        // height that's close to the current tip of the main chain as we
23
        // know it.  We'll use this to start our QueryChannelRange dance with
24
        // the remote node.
25
        HighestChanID(chain chainhash.Hash) (*lnwire.ShortChannelID, error)
26

27
        // UpdatesInHorizon returns all known channel and node updates with an
28
        // update timestamp between the start time and end time. We'll use this
29
        // to catch up a remote node to the set of channel updates that they
30
        // may have missed out on within the target chain.
31
        UpdatesInHorizon(chain chainhash.Hash,
32
                startTime time.Time, endTime time.Time) ([]lnwire.Message, error)
33

34
        // FilterKnownChanIDs takes a target chain, and a set of channel ID's,
35
        // and returns a filtered set of chan ID's. This filtered set of chan
36
        // ID's represents the ID's that we don't know of which were in the
37
        // passed superSet.
38
        FilterKnownChanIDs(chain chainhash.Hash,
39
                superSet []graphdb.ChannelUpdateInfo,
40
                isZombieChan func(time.Time, time.Time) bool) (
41
                []lnwire.ShortChannelID, error)
42

43
        // FilterChannelRange returns the set of channels that we created
44
        // between the start height and the end height. The channel IDs are
45
        // grouped by their common block height. We'll use this to to a remote
46
        // peer's QueryChannelRange message.
47
        FilterChannelRange(chain chainhash.Hash, startHeight, endHeight uint32,
48
                withTimestamps bool) ([]graphdb.BlockChannelRange, error)
49

50
        // FetchChanAnns returns a full set of channel announcements as well as
51
        // their updates that match the set of specified short channel ID's.
52
        // We'll use this to reply to a QueryShortChanIDs message sent by a
53
        // remote peer. The response will contain a unique set of
54
        // ChannelAnnouncements, the latest ChannelUpdate for each of the
55
        // announcements, and a unique set of NodeAnnouncements.
56
        FetchChanAnns(chain chainhash.Hash,
57
                shortChanIDs []lnwire.ShortChannelID) ([]lnwire.Message, error)
58

59
        // FetchChanUpdates returns the latest channel update messages for the
60
        // specified short channel ID. If no channel updates are known for the
61
        // channel, then an empty slice will be returned.
62
        FetchChanUpdates(chain chainhash.Hash,
63
                shortChanID lnwire.ShortChannelID) ([]*lnwire.ChannelUpdate1,
64
                error)
65
}
66

67
// ChanSeries is an implementation of the ChannelGraphTimeSeries
68
// interface backed by the channeldb ChannelGraph database. We'll provide this
69
// implementation to the AuthenticatedGossiper so it can properly use the
70
// in-protocol channel range queries to quickly and efficiently synchronize our
71
// channel state with all peers.
72
type ChanSeries struct {
73
        graph *graphdb.ChannelGraph
74
}
75

76
// NewChanSeries constructs a new ChanSeries backed by a channeldb.ChannelGraph.
77
// The returned ChanSeries implements the ChannelGraphTimeSeries interface.
78
func NewChanSeries(graph *graphdb.ChannelGraph) *ChanSeries {
×
79
        return &ChanSeries{
×
80
                graph: graph,
×
81
        }
×
82
}
×
83

84
// HighestChanID should return is the channel ID of the channel we know of
85
// that's furthest in the target chain. This channel will have a block height
86
// that's close to the current tip of the main chain as we know it.  We'll use
87
// this to start our QueryChannelRange dance with the remote node.
88
//
89
// NOTE: This is part of the ChannelGraphTimeSeries interface.
90
func (c *ChanSeries) HighestChanID(chain chainhash.Hash) (*lnwire.ShortChannelID, error) {
×
91
        chanID, err := c.graph.HighestChanID()
×
92
        if err != nil {
×
93
                return nil, err
×
94
        }
×
95

96
        shortChanID := lnwire.NewShortChanIDFromInt(chanID)
×
97
        return &shortChanID, nil
×
98
}
99

100
// UpdatesInHorizon returns all known channel and node updates with an update
101
// timestamp between the start time and end time. We'll use this to catch up a
102
// remote node to the set of channel updates that they may have missed out on
103
// within the target chain.
104
//
105
// NOTE: This is part of the ChannelGraphTimeSeries interface.
106
func (c *ChanSeries) UpdatesInHorizon(chain chainhash.Hash,
107
        startTime time.Time, endTime time.Time) ([]lnwire.Message, error) {
×
108

×
109
        var updates []lnwire.Message
×
110

×
111
        // First, we'll query for all the set of channels that have an update
×
112
        // that falls within the specified horizon.
×
113
        chansInHorizon, err := c.graph.ChanUpdatesInHorizon(
×
114
                startTime, endTime,
×
115
        )
×
116
        if err != nil {
×
117
                return nil, err
×
118
        }
×
119
        for _, channel := range chansInHorizon {
×
120
                // If the channel hasn't been fully advertised yet, or is a
×
121
                // private channel, then we'll skip it as we can't construct a
×
122
                // full authentication proof if one is requested.
×
123
                if channel.Info.AuthProof == nil {
×
124
                        continue
×
125
                }
126

127
                chanAnn, edge1, edge2, err := netann.CreateChanAnnouncement(
×
128
                        channel.Info.AuthProof, channel.Info, channel.Policy1,
×
129
                        channel.Policy2,
×
130
                )
×
131
                if err != nil {
×
132
                        return nil, err
×
133
                }
×
134

135
                updates = append(updates, chanAnn)
×
136
                if edge1 != nil {
×
137
                        // We don't want to send channel updates that don't
×
138
                        // conform to the spec (anymore).
×
139
                        err := netann.ValidateChannelUpdateFields(0, edge1)
×
140
                        if err != nil {
×
141
                                log.Errorf("not sending invalid channel "+
×
142
                                        "update %v: %v", edge1, err)
×
143
                        } else {
×
144
                                updates = append(updates, edge1)
×
145
                        }
×
146
                }
147
                if edge2 != nil {
×
148
                        err := netann.ValidateChannelUpdateFields(0, edge2)
×
149
                        if err != nil {
×
150
                                log.Errorf("not sending invalid channel "+
×
151
                                        "update %v: %v", edge2, err)
×
152
                        } else {
×
153
                                updates = append(updates, edge2)
×
154
                        }
×
155
                }
156
        }
157

158
        // Next, we'll send out all the node announcements that have an update
159
        // within the horizon as well. We send these second to ensure that they
160
        // follow any active channels they have.
161
        nodeAnnsInHorizon, err := c.graph.NodeUpdatesInHorizon(
×
162
                startTime, endTime,
×
163
        )
×
164
        if err != nil {
×
165
                return nil, err
×
166
        }
×
167
        for _, nodeAnn := range nodeAnnsInHorizon {
×
168
                nodeAnn := nodeAnn
×
169

×
170
                // Ensure we only forward nodes that are publicly advertised to
×
171
                // prevent leaking information about nodes.
×
172
                isNodePublic, err := c.graph.IsPublicNode(nodeAnn.PubKeyBytes)
×
173
                if err != nil {
×
174
                        log.Errorf("Unable to determine if node %x is "+
×
175
                                "advertised: %v", nodeAnn.PubKeyBytes, err)
×
176
                        continue
×
177
                }
178

179
                if !isNodePublic {
×
180
                        log.Tracef("Skipping forwarding announcement for "+
×
181
                                "node %x due to being unadvertised",
×
182
                                nodeAnn.PubKeyBytes)
×
183
                        continue
×
184
                }
185

186
                nodeUpdate, err := nodeAnn.NodeAnnouncement(true)
×
187
                if err != nil {
×
188
                        return nil, err
×
189
                }
×
190

191
                updates = append(updates, nodeUpdate)
×
192
        }
193

194
        return updates, nil
×
195
}
196

197
// FilterKnownChanIDs takes a target chain, and a set of channel ID's, and
198
// returns a filtered set of chan ID's. This filtered set of chan ID's
199
// represents the ID's that we don't know of which were in the passed superSet.
200
//
201
// NOTE: This is part of the ChannelGraphTimeSeries interface.
202
func (c *ChanSeries) FilterKnownChanIDs(_ chainhash.Hash,
203
        superSet []graphdb.ChannelUpdateInfo,
204
        isZombieChan func(time.Time, time.Time) bool) (
205
        []lnwire.ShortChannelID, error) {
×
206

×
207
        newChanIDs, err := c.graph.FilterKnownChanIDs(superSet, isZombieChan)
×
208
        if err != nil {
×
209
                return nil, err
×
210
        }
×
211

212
        filteredIDs := make([]lnwire.ShortChannelID, 0, len(newChanIDs))
×
213
        for _, chanID := range newChanIDs {
×
214
                filteredIDs = append(
×
215
                        filteredIDs, lnwire.NewShortChanIDFromInt(chanID),
×
216
                )
×
217
        }
×
218

219
        return filteredIDs, nil
×
220
}
221

222
// FilterChannelRange returns the set of channels that we created between the
223
// start height and the end height. The channel IDs are grouped by their common
224
// block height. We'll use this respond to a remote peer's QueryChannelRange
225
// message.
226
//
227
// NOTE: This is part of the ChannelGraphTimeSeries interface.
228
func (c *ChanSeries) FilterChannelRange(_ chainhash.Hash, startHeight,
229
        endHeight uint32, withTimestamps bool) ([]graphdb.BlockChannelRange,
230
        error) {
×
231

×
232
        return c.graph.FilterChannelRange(
×
233
                startHeight, endHeight, withTimestamps,
×
234
        )
×
235
}
×
236

237
// FetchChanAnns returns a full set of channel announcements as well as their
238
// updates that match the set of specified short channel ID's.  We'll use this
239
// to reply to a QueryShortChanIDs message sent by a remote peer. The response
240
// will contain a unique set of ChannelAnnouncements, the latest ChannelUpdate
241
// for each of the announcements, and a unique set of NodeAnnouncements.
242
//
243
// NOTE: This is part of the ChannelGraphTimeSeries interface.
244
func (c *ChanSeries) FetchChanAnns(chain chainhash.Hash,
245
        shortChanIDs []lnwire.ShortChannelID) ([]lnwire.Message, error) {
×
246

×
247
        chanIDs := make([]uint64, 0, len(shortChanIDs))
×
248
        for _, chanID := range shortChanIDs {
×
249
                chanIDs = append(chanIDs, chanID.ToUint64())
×
250
        }
×
251

252
        channels, err := c.graph.FetchChanInfos(chanIDs)
×
253
        if err != nil {
×
254
                return nil, err
×
255
        }
×
256

257
        // We'll use this map to ensure we don't send the same node
258
        // announcement more than one time as one node may have many channel
259
        // anns we'll need to send.
260
        nodePubsSent := make(map[route.Vertex]struct{})
×
261

×
262
        chanAnns := make([]lnwire.Message, 0, len(channels)*3)
×
263
        for _, channel := range channels {
×
264
                // If the channel doesn't have an authentication proof, then we
×
265
                // won't send it over as it may not yet be finalized, or be a
×
266
                // non-advertised channel.
×
267
                if channel.Info.AuthProof == nil {
×
268
                        continue
×
269
                }
270

271
                chanAnn, edge1, edge2, err := netann.CreateChanAnnouncement(
×
272
                        channel.Info.AuthProof, channel.Info, channel.Policy1,
×
273
                        channel.Policy2,
×
274
                )
×
275
                if err != nil {
×
276
                        return nil, err
×
277
                }
×
278

279
                chanAnns = append(chanAnns, chanAnn)
×
280
                if edge1 != nil {
×
281
                        chanAnns = append(chanAnns, edge1)
×
282

×
283
                        // If this edge has a validated node announcement, that
×
284
                        // we haven't yet sent, then we'll send that as well.
×
285
                        nodePub := channel.Node2.PubKeyBytes
×
286
                        hasNodeAnn := channel.Node2.HaveNodeAnnouncement
×
287
                        if _, ok := nodePubsSent[nodePub]; !ok && hasNodeAnn {
×
288
                                nodeAnn, err := channel.Node2.NodeAnnouncement(
×
289
                                        true,
×
290
                                )
×
291
                                if err != nil {
×
292
                                        return nil, err
×
293
                                }
×
294

295
                                chanAnns = append(chanAnns, nodeAnn)
×
296
                                nodePubsSent[nodePub] = struct{}{}
×
297
                        }
298
                }
299
                if edge2 != nil {
×
300
                        chanAnns = append(chanAnns, edge2)
×
301

×
302
                        // If this edge has a validated node announcement, that
×
303
                        // we haven't yet sent, then we'll send that as well.
×
304
                        nodePub := channel.Node1.PubKeyBytes
×
305
                        hasNodeAnn := channel.Node1.HaveNodeAnnouncement
×
306
                        if _, ok := nodePubsSent[nodePub]; !ok && hasNodeAnn {
×
307
                                nodeAnn, err := channel.Node1.NodeAnnouncement(
×
308
                                        true,
×
309
                                )
×
310
                                if err != nil {
×
311
                                        return nil, err
×
312
                                }
×
313

314
                                chanAnns = append(chanAnns, nodeAnn)
×
315
                                nodePubsSent[nodePub] = struct{}{}
×
316
                        }
317
                }
318
        }
319

320
        return chanAnns, nil
×
321
}
322

323
// FetchChanUpdates returns the latest channel update messages for the
324
// specified short channel ID. If no channel updates are known for the channel,
325
// then an empty slice will be returned.
326
//
327
// NOTE: This is part of the ChannelGraphTimeSeries interface.
328
func (c *ChanSeries) FetchChanUpdates(chain chainhash.Hash,
329
        shortChanID lnwire.ShortChannelID) ([]*lnwire.ChannelUpdate1, error) {
×
330

×
331
        chanInfo, e1, e2, err := c.graph.FetchChannelEdgesByID(
×
332
                shortChanID.ToUint64(),
×
333
        )
×
334
        if err != nil {
×
335
                return nil, err
×
336
        }
×
337

338
        chanUpdates := make([]*lnwire.ChannelUpdate1, 0, 2)
×
339
        if e1 != nil {
×
340
                chanUpdate, err := netann.ChannelUpdateFromEdge(chanInfo, e1)
×
341
                if err != nil {
×
342
                        return nil, err
×
343
                }
×
344

345
                chanUpdates = append(chanUpdates, chanUpdate)
×
346
        }
347
        if e2 != nil {
×
348
                chanUpdate, err := netann.ChannelUpdateFromEdge(chanInfo, e2)
×
349
                if err != nil {
×
350
                        return nil, err
×
351
                }
×
352

353
                chanUpdates = append(chanUpdates, chanUpdate)
×
354
        }
355

356
        return chanUpdates, nil
×
357
}
358

359
// A compile-time assertion to ensure that ChanSeries meets the
360
// ChannelGraphTimeSeries interface.
361
var _ ChannelGraphTimeSeries = (*ChanSeries)(nil)
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