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

lightningnetwork / lnd / 13536249039

26 Feb 2025 03:42AM UTC coverage: 57.462% (-1.4%) from 58.835%
13536249039

Pull #8453

github

Roasbeef
peer: update chooseDeliveryScript to gen script if needed

In this commit, we update `chooseDeliveryScript` to generate a new
script if needed. This allows us to fold in a few other lines that
always followed this function into this expanded function.

The tests have been updated accordingly.
Pull Request #8453: [4/4] - multi: integrate new rbf coop close FSM into the existing peer flow

275 of 1318 new or added lines in 22 files covered. (20.86%)

19521 existing lines in 257 files now uncovered.

103858 of 180741 relevant lines covered (57.46%)

24750.23 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