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

lightningnetwork / lnd / 13518248739

25 Feb 2025 09:45AM UTC coverage: 58.808% (-0.007%) from 58.815%
13518248739

Pull #9552

github

ellemouton
graph/db: move cache write for UpdateEdgePolicy

To the ChannelGraph.
Pull Request #9552: graph: extract cache from CRUD [5]

78 of 89 new or added lines in 2 files covered. (87.64%)

268 existing lines in 16 files now uncovered.

136336 of 231832 relevant lines covered (58.81%)

19292.34 hits per line

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

89.09
/graph/db/graph.go
1
package graphdb
2

3
import (
4
        "errors"
5
        "time"
6

7
        "github.com/lightningnetwork/lnd/batch"
8
        "github.com/lightningnetwork/lnd/graph/db/models"
9
        "github.com/lightningnetwork/lnd/kvdb"
10
        "github.com/lightningnetwork/lnd/lnwire"
11
        "github.com/lightningnetwork/lnd/routing/route"
12
)
13

14
// Config is a struct that holds all the necessary dependencies for a
15
// ChannelGraph.
16
type Config struct {
17
        // KVDB is the kvdb.Backend that will be used for initializing the
18
        // KVStore CRUD layer.
19
        KVDB kvdb.Backend
20

21
        // KVStoreOpts is a list of functional options that will be used when
22
        // initializing the KVStore.
23
        KVStoreOpts []KVStoreOptionModifier
24
}
25

26
// ChannelGraph is a layer above the graph's CRUD layer.
27
//
28
// NOTE: currently, this is purely a pass-through layer directly to the backing
29
// KVStore. Upcoming commits will move the graph cache out of the KVStore and
30
// into this layer so that the KVStore is only responsible for CRUD operations.
31
type ChannelGraph struct {
32
        graphCache *GraphCache
33

34
        *KVStore
35
}
36

37
// NewChannelGraph creates a new ChannelGraph instance with the given backend.
38
func NewChannelGraph(cfg *Config, options ...ChanGraphOption) (*ChannelGraph,
39
        error) {
177✔
40

177✔
41
        opts := defaultChanGraphOptions()
177✔
42
        for _, o := range options {
282✔
43
                o(opts)
105✔
44
        }
105✔
45

46
        store, err := NewKVStore(cfg.KVDB, cfg.KVStoreOpts...)
177✔
47
        if err != nil {
177✔
48
                return nil, err
×
49
        }
×
50

51
        if !opts.useGraphCache {
213✔
52
                return &ChannelGraph{
36✔
53
                        KVStore: store,
36✔
54
                }, nil
36✔
55
        }
36✔
56

57
        // The graph cache can be turned off (e.g. for mobile users) for a
58
        // speed/memory usage tradeoff.
59
        graphCache := NewGraphCache(opts.preAllocCacheNumNodes)
144✔
60
        startTime := time.Now()
144✔
61
        log.Debugf("Populating in-memory channel graph, this might take a " +
144✔
62
                "while...")
144✔
63

144✔
64
        err = store.ForEachNodeCacheable(func(node route.Vertex,
144✔
65
                features *lnwire.FeatureVector) error {
247✔
66

103✔
67
                graphCache.AddNodeFeatures(node, features)
103✔
68

103✔
69
                return nil
103✔
70
        })
103✔
71
        if err != nil {
144✔
72
                return nil, err
×
73
        }
×
74

75
        err = store.ForEachChannel(func(info *models.ChannelEdgeInfo,
144✔
76
                policy1, policy2 *models.ChannelEdgePolicy) error {
543✔
77

399✔
78
                graphCache.AddChannel(info, policy1, policy2)
399✔
79

399✔
80
                return nil
399✔
81
        })
399✔
82
        if err != nil {
144✔
83
                return nil, err
×
84
        }
×
85

86
        log.Debugf("Finished populating in-memory channel graph (took %v, %s)",
144✔
87
                time.Since(startTime), graphCache.Stats())
144✔
88

144✔
89
        store.setGraphCache(graphCache)
144✔
90

144✔
91
        return &ChannelGraph{
144✔
92
                KVStore:    store,
144✔
93
                graphCache: graphCache,
144✔
94
        }, nil
144✔
95
}
96

97
// FilterKnownChanIDs takes a set of channel IDs and return the subset of chan
98
// ID's that we don't know and are not known zombies of the passed set. In other
99
// words, we perform a set difference of our set of chan ID's and the ones
100
// passed in. This method can be used by callers to determine the set of
101
// channels another peer knows of that we don't.
102
func (c *ChannelGraph) FilterKnownChanIDs(chansInfo []ChannelUpdateInfo,
103
        isZombieChan func(time.Time, time.Time) bool) ([]uint64, error) {
135✔
104

135✔
105
        unknown, knownZombies, err := c.KVStore.FilterKnownChanIDs(chansInfo)
135✔
106
        if err != nil {
135✔
NEW
107
                return nil, err
×
NEW
108
        }
×
109

110
        for _, info := range knownZombies {
178✔
111
                // TODO(ziggie): Make sure that for the strict pruning case we
43✔
112
                // compare the pubkeys and whether the right timestamp is not
43✔
113
                // older than the `ChannelPruneExpiry`.
43✔
114
                //
43✔
115
                // NOTE: The timestamp data has no verification attached to it
43✔
116
                // in the `ReplyChannelRange` msg so we are trusting this data
43✔
117
                // at this point. However it is not critical because we are just
43✔
118
                // removing the channel from the db when the timestamps are more
43✔
119
                // recent. During the querying of the gossip msg verification
43✔
120
                // happens as usual. However we should start punishing peers
43✔
121
                // when they don't provide us honest data ?
43✔
122
                isStillZombie := isZombieChan(
43✔
123
                        info.Node1UpdateTimestamp, info.Node2UpdateTimestamp,
43✔
124
                )
43✔
125

43✔
126
                if isStillZombie {
70✔
127
                        continue
27✔
128
                }
129

130
                // If we have marked it as a zombie but the latest update
131
                // timestamps could bring it back from the dead, then we mark it
132
                // alive, and we let it be added to the set of IDs to query our
133
                // peer for.
134
                err := c.KVStore.MarkEdgeLive(
16✔
135
                        info.ShortChannelID.ToUint64(),
16✔
136
                )
16✔
137
                // Since there is a chance that the edge could have been marked
16✔
138
                // as "live" between the FilterKnownChanIDs call and the
16✔
139
                // MarkEdgeLive call, we ignore the error if the edge is already
16✔
140
                // marked as live.
16✔
141
                if err != nil && !errors.Is(err, ErrZombieEdgeNotFound) {
16✔
NEW
142
                        return nil, err
×
NEW
143
                }
×
144
        }
145

146
        return unknown, nil
135✔
147
}
148

149
// MarkEdgeZombie attempts to mark a channel identified by its channel ID as a
150
// zombie. This method is used on an ad-hoc basis, when channels need to be
151
// marked as zombies outside the normal pruning cycle.
152
func (c *ChannelGraph) MarkEdgeZombie(chanID uint64,
153
        pubKey1, pubKey2 [33]byte) error {
121✔
154

121✔
155
        err := c.KVStore.MarkEdgeZombie(chanID, pubKey1, pubKey2)
121✔
156
        if err != nil {
121✔
NEW
157
                return err
×
NEW
158
        }
×
159

160
        if c.graphCache != nil {
242✔
161
                c.graphCache.RemoveChannel(pubKey1, pubKey2, chanID)
121✔
162
        }
121✔
163

164
        return nil
121✔
165
}
166

167
// UpdateEdgePolicy updates the edge routing policy for a single directed edge
168
// within the database for the referenced channel. The `flags` attribute within
169
// the ChannelEdgePolicy determines which of the directed edges are being
170
// updated. If the flag is 1, then the first node's information is being
171
// updated, otherwise it's the second node's information. The node ordering is
172
// determined by the lexicographical ordering of the identity public keys of the
173
// nodes on either side of the channel.
174
func (c *ChannelGraph) UpdateEdgePolicy(edge *models.ChannelEdgePolicy,
175
        op ...batch.SchedulerOption) error {
2,666✔
176

2,666✔
177
        from, to, err := c.KVStore.UpdateEdgePolicy(edge, op...)
2,666✔
178
        if err != nil {
2,669✔
179
                return err
3✔
180
        }
3✔
181

182
        if c.graphCache == nil {
3,052✔
183
                return nil
389✔
184
        }
389✔
185

186
        var isUpdate1 bool
2,277✔
187
        if edge.ChannelFlags&lnwire.ChanUpdateDirection == 0 {
3,419✔
188
                isUpdate1 = true
1,142✔
189
        }
1,142✔
190

191
        c.graphCache.UpdatePolicy(edge, from, to, isUpdate1)
2,277✔
192

2,277✔
193
        return nil
2,277✔
194
}
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