@@ -191,6 +191,12 @@ func (tab *Table) Lookup(targetID NodeID) []*Node {
191
191
result := tab .closest (target , bucketSize )
192
192
tab .mutex .Unlock ()
193
193
194
+ // If the result set is empty, all nodes were dropped, refresh
195
+ if len (result .entries ) == 0 {
196
+ tab .refresh ()
197
+ return nil
198
+ }
199
+
194
200
for {
195
201
// ask the alpha closest nodes that we haven't asked yet
196
202
for i := 0 ; i < len (result .entries ) && pendingQueries < alpha ; i ++ {
@@ -207,7 +213,7 @@ func (tab *Table) Lookup(targetID NodeID) []*Node {
207
213
tab .db .updateFindFails (n .ID , fails )
208
214
glog .V (logger .Detail ).Infof ("Bumping failures for %x: %d" , n .ID [:8 ], fails )
209
215
210
- if fails > maxFindnodeFailures {
216
+ if fails >= maxFindnodeFailures {
211
217
glog .V (logger .Detail ).Infof ("Evacuating node %x: %d findnode failures" , n .ID [:8 ], fails )
212
218
tab .del (n )
213
219
}
@@ -232,19 +238,41 @@ func (tab *Table) Lookup(targetID NodeID) []*Node {
232
238
return result .entries
233
239
}
234
240
235
- // refresh performs a lookup for a random target to keep buckets full.
241
+ // refresh performs a lookup for a random target to keep buckets full, or seeds
242
+ // the table if it is empty (initial bootstrap or discarded faulty peers).
236
243
func (tab * Table ) refresh () {
237
- // The Kademlia paper specifies that the bucket refresh should
238
- // perform a refresh in the least recently used bucket. We cannot
239
- // adhere to this because the findnode target is a 512bit value
240
- // (not hash-sized) and it is not easily possible to generate a
241
- // sha3 preimage that falls into a chosen bucket.
242
- //
243
- // We perform a lookup with a random target instead.
244
- var target NodeID
245
- rand .Read (target [:])
246
- result := tab .Lookup (target )
247
- if len (result ) == 0 {
244
+ seed := true
245
+
246
+ // If the discovery table is empty, seed with previously known nodes
247
+ tab .mutex .Lock ()
248
+ for _ , bucket := range tab .buckets {
249
+ if len (bucket .entries ) > 0 {
250
+ seed = false
251
+ break
252
+ }
253
+ }
254
+ tab .mutex .Unlock ()
255
+
256
+ // If the table is not empty, try to refresh using the live entries
257
+ if ! seed {
258
+ // The Kademlia paper specifies that the bucket refresh should
259
+ // perform a refresh in the least recently used bucket. We cannot
260
+ // adhere to this because the findnode target is a 512bit value
261
+ // (not hash-sized) and it is not easily possible to generate a
262
+ // sha3 preimage that falls into a chosen bucket.
263
+ //
264
+ // We perform a lookup with a random target instead.
265
+ var target NodeID
266
+ rand .Read (target [:])
267
+
268
+ result := tab .Lookup (target )
269
+ if len (result ) == 0 {
270
+ // Lookup failed, seed after all
271
+ seed = true
272
+ }
273
+ }
274
+
275
+ if seed {
248
276
// Pick a batch of previously know seeds to lookup with
249
277
seeds := tab .db .querySeeds (10 )
250
278
for _ , seed := range seeds {
0 commit comments