@@ -216,22 +216,101 @@ func NewChannelGraph(db kvdb.Backend, rejectCacheSize, chanCacheSize int,
216
216
startTime := time .Now ()
217
217
log .Debugf ("Populating in-memory channel graph, this might " +
218
218
"take a while..." )
219
+
219
220
err := g .ForEachNodeCacheable (
220
221
func (tx kvdb.RTx , node GraphCacheNode ) error {
221
- return g .graphCache .AddNode (tx , node )
222
+ g .graphCache .AddNodeFeatures (node )
223
+
224
+ return nil
222
225
},
223
226
)
224
227
if err != nil {
225
228
return nil , err
226
229
}
227
230
231
+ err = g .ForEachChannel (func (info * ChannelEdgeInfo ,
232
+ policy1 , policy2 * ChannelEdgePolicy ) error {
233
+
234
+ g .graphCache .AddChannel (info , policy1 , policy2 )
235
+
236
+ return nil
237
+ })
238
+ if err != nil {
239
+ return nil , err
240
+ }
241
+
228
242
log .Debugf ("Finished populating in-memory channel graph (took " +
229
243
"%v, %s)" , time .Since (startTime ), g .graphCache .Stats ())
230
244
}
231
245
232
246
return g , nil
233
247
}
234
248
249
+ // channelMapKey is the key structure used for storing channel edge policies.
250
+ type channelMapKey struct {
251
+ nodeKey route.Vertex
252
+ chanID [8 ]byte
253
+ }
254
+
255
+ // getChannelMap loads all channel edge policies from the database and stores
256
+ // them in a map.
257
+ func (c * ChannelGraph ) getChannelMap (edges kvdb.RBucket ) (
258
+ map [channelMapKey ]* ChannelEdgePolicy , error ) {
259
+
260
+ // Create a map to store all channel edge policies.
261
+ channelMap := make (map [channelMapKey ]* ChannelEdgePolicy )
262
+
263
+ err := kvdb .ForAll (edges , func (k , edgeBytes []byte ) error {
264
+ // Skip embedded buckets.
265
+ if bytes .Equal (k , edgeIndexBucket ) ||
266
+ bytes .Equal (k , edgeUpdateIndexBucket ) ||
267
+ bytes .Equal (k , zombieBucket ) ||
268
+ bytes .Equal (k , disabledEdgePolicyBucket ) ||
269
+ bytes .Equal (k , channelPointBucket ) {
270
+
271
+ return nil
272
+ }
273
+
274
+ // Validate key length.
275
+ if len (k ) != 33 + 8 {
276
+ return fmt .Errorf ("invalid edge key %x encountered" , k )
277
+ }
278
+
279
+ var key channelMapKey
280
+ copy (key .nodeKey [:], k [:33 ])
281
+ copy (key .chanID [:], k [33 :])
282
+
283
+ // No need to deserialize unknown policy.
284
+ if bytes .Equal (edgeBytes , unknownPolicy ) {
285
+ return nil
286
+ }
287
+
288
+ edgeReader := bytes .NewReader (edgeBytes )
289
+ edge , err := deserializeChanEdgePolicyRaw (
290
+ edgeReader ,
291
+ )
292
+
293
+ switch {
294
+ // If the db policy was missing an expected optional field, we
295
+ // return nil as if the policy was unknown.
296
+ case err == ErrEdgePolicyOptionalFieldNotFound :
297
+ return nil
298
+
299
+ case err != nil :
300
+ return err
301
+ }
302
+
303
+ channelMap [key ] = edge
304
+
305
+ return nil
306
+ })
307
+ if err != nil {
308
+ return nil , err
309
+ }
310
+
311
+ return channelMap , nil
312
+ }
313
+
235
314
var graphTopLevelBuckets = [][]byte {
236
315
nodeBucket ,
237
316
edgeBucket ,
@@ -332,50 +411,47 @@ func (c *ChannelGraph) NewPathFindTx() (kvdb.RTx, error) {
332
411
func (c * ChannelGraph ) ForEachChannel (cb func (* ChannelEdgeInfo ,
333
412
* ChannelEdgePolicy , * ChannelEdgePolicy ) error ) error {
334
413
335
- // TODO(roasbeef): ptr map to reduce # of allocs? no duplicates
336
-
337
- return kvdb .View (c .db , func (tx kvdb.RTx ) error {
338
- // First, grab the node bucket. This will be used to populate
339
- // the Node pointers in each edge read from disk.
340
- nodes := tx .ReadBucket (nodeBucket )
341
- if nodes == nil {
342
- return ErrGraphNotFound
343
- }
344
-
345
- // Next, grab the edge bucket which stores the edges, and also
346
- // the index itself so we can group the directed edges together
347
- // logically.
414
+ return c .db .View (func (tx kvdb.RTx ) error {
348
415
edges := tx .ReadBucket (edgeBucket )
349
416
if edges == nil {
350
417
return ErrGraphNoEdgesFound
351
418
}
419
+
420
+ // First, load all edges in memory indexed by node and channel
421
+ // id.
422
+ channelMap , err := c .getChannelMap (edges )
423
+ if err != nil {
424
+ return err
425
+ }
426
+
352
427
edgeIndex := edges .NestedReadBucket (edgeIndexBucket )
353
428
if edgeIndex == nil {
354
429
return ErrGraphNoEdgesFound
355
430
}
356
431
357
- // For each edge pair within the edge index, we fetch each edge
358
- // itself and also the node information in order to fully
359
- // populated the object.
360
- return edgeIndex .ForEach (func (chanID , edgeInfoBytes []byte ) error {
361
- infoReader := bytes .NewReader (edgeInfoBytes )
362
- edgeInfo , err := deserializeChanEdgeInfo (infoReader )
363
- if err != nil {
364
- return err
365
- }
366
- edgeInfo .db = c .db
432
+ // Load edge index, recombine each channel with the policies
433
+ // loaded above and invoke the callback.
434
+ return kvdb .ForAll (edgeIndex , func (k , edgeInfoBytes []byte ) error {
435
+ var chanID [8 ]byte
436
+ copy (chanID [:], k )
367
437
368
- edge1 , edge2 , err := fetchChanEdgePolicies (
369
- edgeIndex , edges , nodes , chanID , c .db ,
370
- )
438
+ edgeInfoReader := bytes .NewReader (edgeInfoBytes )
439
+ info , err := deserializeChanEdgeInfo (edgeInfoReader )
371
440
if err != nil {
372
441
return err
373
442
}
374
443
375
- // With both edges read, execute the call back. IF this
376
- // function returns an error then the transaction will
377
- // be aborted.
378
- return cb (& edgeInfo , edge1 , edge2 )
444
+ policy1 := channelMap [channelMapKey {
445
+ nodeKey : info .NodeKey1Bytes ,
446
+ chanID : chanID ,
447
+ }]
448
+
449
+ policy2 := channelMap [channelMapKey {
450
+ nodeKey : info .NodeKey2Bytes ,
451
+ chanID : chanID ,
452
+ }]
453
+
454
+ return cb (& info , policy1 , policy2 )
379
455
})
380
456
}, func () {})
381
457
}
@@ -628,7 +704,6 @@ func (c *ChannelGraph) ForEachNodeCacheable(cb func(kvdb.RTx,
628
704
return ErrGraphNotFound
629
705
}
630
706
631
- cacheableNode := newGraphCacheNode (route.Vertex {}, nil )
632
707
return nodes .ForEach (func (pubKey , nodeBytes []byte ) error {
633
708
// If this is the source key, then we skip this
634
709
// iteration as the value for this key is a pubKey
@@ -638,8 +713,8 @@ func (c *ChannelGraph) ForEachNodeCacheable(cb func(kvdb.RTx,
638
713
}
639
714
640
715
nodeReader := bytes .NewReader (nodeBytes )
641
- err := deserializeLightningNodeCacheable (
642
- nodeReader , cacheableNode ,
716
+ cacheableNode , err := deserializeLightningNodeCacheable (
717
+ nodeReader ,
643
718
)
644
719
if err != nil {
645
720
return err
@@ -2740,8 +2815,6 @@ func (c *ChannelGraph) FetchLightningNode(nodePub route.Vertex) (
2740
2815
type graphCacheNode struct {
2741
2816
pubKeyBytes route.Vertex
2742
2817
features * lnwire.FeatureVector
2743
-
2744
- nodeScratch [8 ]byte
2745
2818
}
2746
2819
2747
2820
// newGraphCacheNode returns a new cache optimized node.
@@ -4090,51 +4163,60 @@ func fetchLightningNode(nodeBucket kvdb.RBucket,
4090
4163
return deserializeLightningNode (nodeReader )
4091
4164
}
4092
4165
4093
- func deserializeLightningNodeCacheable (r io.Reader , node * graphCacheNode ) error {
4166
+ func deserializeLightningNodeCacheable (r io.Reader ) ( * graphCacheNode , error ) {
4094
4167
// Always populate a feature vector, even if we don't have a node
4095
4168
// announcement and short circuit below.
4096
- node .features = lnwire .EmptyFeatureVector ()
4169
+ node := newGraphCacheNode (
4170
+ route.Vertex {},
4171
+ lnwire .EmptyFeatureVector (),
4172
+ )
4173
+
4174
+ var nodeScratch [8 ]byte
4097
4175
4098
4176
// Skip ahead:
4099
4177
// - LastUpdate (8 bytes)
4100
- if _ , err := r .Read (node . nodeScratch [:]); err != nil {
4101
- return err
4178
+ if _ , err := r .Read (nodeScratch [:]); err != nil {
4179
+ return nil , err
4102
4180
}
4103
4181
4104
4182
if _ , err := io .ReadFull (r , node .pubKeyBytes [:]); err != nil {
4105
- return err
4183
+ return nil , err
4106
4184
}
4107
4185
4108
4186
// Read the node announcement flag.
4109
- if _ , err := r .Read (node . nodeScratch [:2 ]); err != nil {
4110
- return err
4187
+ if _ , err := r .Read (nodeScratch [:2 ]); err != nil {
4188
+ return nil , err
4111
4189
}
4112
- hasNodeAnn := byteOrder .Uint16 (node . nodeScratch [:2 ])
4190
+ hasNodeAnn := byteOrder .Uint16 (nodeScratch [:2 ])
4113
4191
4114
4192
// The rest of the data is optional, and will only be there if we got a
4115
4193
// node announcement for this node.
4116
4194
if hasNodeAnn == 0 {
4117
- return nil
4195
+ return node , nil
4118
4196
}
4119
4197
4120
4198
// We did get a node announcement for this node, so we'll have the rest
4121
4199
// of the data available.
4122
4200
var rgb uint8
4123
4201
if err := binary .Read (r , byteOrder , & rgb ); err != nil {
4124
- return err
4202
+ return nil , err
4125
4203
}
4126
4204
if err := binary .Read (r , byteOrder , & rgb ); err != nil {
4127
- return err
4205
+ return nil , err
4128
4206
}
4129
4207
if err := binary .Read (r , byteOrder , & rgb ); err != nil {
4130
- return err
4208
+ return nil , err
4131
4209
}
4132
4210
4133
4211
if _ , err := wire .ReadVarString (r , 0 ); err != nil {
4134
- return err
4212
+ return nil , err
4213
+ }
4214
+
4215
+ if err := node .features .Decode (r ); err != nil {
4216
+ return nil , err
4135
4217
}
4136
4218
4137
- return node . features . Decode ( r )
4219
+ return node , nil
4138
4220
}
4139
4221
4140
4222
func deserializeLightningNode (r io.Reader ) (LightningNode , error ) {
@@ -4652,6 +4734,27 @@ func serializeChanEdgePolicy(w io.Writer, edge *ChannelEdgePolicy,
4652
4734
func deserializeChanEdgePolicy (r io.Reader ,
4653
4735
nodes kvdb.RBucket ) (* ChannelEdgePolicy , error ) {
4654
4736
4737
+ // Deserialize the policy. Note that in case an optional field is not
4738
+ // found, both an error and a populated policy object are returned.
4739
+ edge , deserializeErr := deserializeChanEdgePolicyRaw (r )
4740
+ if deserializeErr != nil &&
4741
+ deserializeErr != ErrEdgePolicyOptionalFieldNotFound {
4742
+
4743
+ return nil , deserializeErr
4744
+ }
4745
+
4746
+ // Populate full LightningNode struct.
4747
+ pub := edge .Node .PubKeyBytes [:]
4748
+ node , err := fetchLightningNode (nodes , pub )
4749
+ if err != nil {
4750
+ return nil , fmt .Errorf ("unable to fetch node: %x, %v" , pub , err )
4751
+ }
4752
+ edge .Node = & node
4753
+
4754
+ return edge , deserializeErr
4755
+ }
4756
+
4757
+ func deserializeChanEdgePolicyRaw (r io.Reader ) (* ChannelEdgePolicy , error ) {
4655
4758
edge := & ChannelEdgePolicy {}
4656
4759
4657
4760
var err error
@@ -4701,13 +4804,9 @@ func deserializeChanEdgePolicy(r io.Reader,
4701
4804
if _ , err := r .Read (pub [:]); err != nil {
4702
4805
return nil , err
4703
4806
}
4704
-
4705
- node , err := fetchLightningNode (nodes , pub [:])
4706
- if err != nil {
4707
- return nil , fmt .Errorf ("unable to fetch node: %x, %v" ,
4708
- pub [:], err )
4807
+ edge .Node = & LightningNode {
4808
+ PubKeyBytes : pub ,
4709
4809
}
4710
- edge .Node = & node
4711
4810
4712
4811
// We'll try and see if there are any opaque bytes left, if not, then
4713
4812
// we'll ignore the EOF error and return the edge as is.
0 commit comments