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

lightningnetwork / lnd / 13157733617

05 Feb 2025 12:49PM UTC coverage: 57.712% (-1.1%) from 58.82%
13157733617

Pull #9447

github

yyforyongyu
sweep: rename methods for clarity

We now rename "third party" to "unknown" as the inputs can be spent via
an older sweeping tx, a third party (anchor), or a remote party (pin).
In fee bumper we don't have the info to distinguish the above cases, and
leave them to be further handled by the sweeper as it has more context.
Pull Request #9447: sweep: start tracking input spending status in the fee bumper

83 of 87 new or added lines in 2 files covered. (95.4%)

19472 existing lines in 252 files now uncovered.

103634 of 179570 relevant lines covered (57.71%)

24840.31 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.
UNCOV
78
func NewChanSeries(graph *graphdb.ChannelGraph) *ChanSeries {
×
UNCOV
79
        return &ChanSeries{
×
UNCOV
80
                graph: graph,
×
UNCOV
81
        }
×
UNCOV
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.
UNCOV
90
func (c *ChanSeries) HighestChanID(chain chainhash.Hash) (*lnwire.ShortChannelID, error) {
×
UNCOV
91
        chanID, err := c.graph.HighestChanID()
×
UNCOV
92
        if err != nil {
×
93
                return nil, err
×
94
        }
×
95

UNCOV
96
        shortChanID := lnwire.NewShortChanIDFromInt(chanID)
×
UNCOV
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,
UNCOV
107
        startTime time.Time, endTime time.Time) ([]lnwire.Message, error) {
×
UNCOV
108

×
UNCOV
109
        var updates []lnwire.Message
×
UNCOV
110

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

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

UNCOV
135
                updates = append(updates, chanAnn)
×
UNCOV
136
                if edge1 != nil {
×
UNCOV
137
                        // We don't want to send channel updates that don't
×
UNCOV
138
                        // conform to the spec (anymore).
×
UNCOV
139
                        err := netann.ValidateChannelUpdateFields(0, edge1)
×
UNCOV
140
                        if err != nil {
×
141
                                log.Errorf("not sending invalid channel "+
×
142
                                        "update %v: %v", edge1, err)
×
UNCOV
143
                        } else {
×
UNCOV
144
                                updates = append(updates, edge1)
×
UNCOV
145
                        }
×
146
                }
UNCOV
147
                if edge2 != nil {
×
UNCOV
148
                        err := netann.ValidateChannelUpdateFields(0, edge2)
×
UNCOV
149
                        if err != nil {
×
150
                                log.Errorf("not sending invalid channel "+
×
151
                                        "update %v: %v", edge2, err)
×
UNCOV
152
                        } else {
×
UNCOV
153
                                updates = append(updates, edge2)
×
UNCOV
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.
UNCOV
161
        nodeAnnsInHorizon, err := c.graph.NodeUpdatesInHorizon(
×
UNCOV
162
                startTime, endTime,
×
UNCOV
163
        )
×
UNCOV
164
        if err != nil {
×
165
                return nil, err
×
166
        }
×
UNCOV
167
        for _, nodeAnn := range nodeAnnsInHorizon {
×
UNCOV
168
                nodeAnn := nodeAnn
×
UNCOV
169

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

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

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

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

UNCOV
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) (
UNCOV
205
        []lnwire.ShortChannelID, error) {
×
UNCOV
206

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

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

UNCOV
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,
UNCOV
230
        error) {
×
UNCOV
231

×
UNCOV
232
        return c.graph.FilterChannelRange(
×
UNCOV
233
                startHeight, endHeight, withTimestamps,
×
UNCOV
234
        )
×
UNCOV
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,
UNCOV
245
        shortChanIDs []lnwire.ShortChannelID) ([]lnwire.Message, error) {
×
UNCOV
246

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

UNCOV
252
        channels, err := c.graph.FetchChanInfos(chanIDs)
×
UNCOV
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.
UNCOV
260
        nodePubsSent := make(map[route.Vertex]struct{})
×
UNCOV
261

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

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

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

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

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

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

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

UNCOV
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,
UNCOV
329
        shortChanID lnwire.ShortChannelID) ([]*lnwire.ChannelUpdate1, error) {
×
UNCOV
330

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

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

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

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

UNCOV
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