Skip to content

Commit 549a114

Browse files
committed
fixes
1 parent 5ce5580 commit 549a114

2 files changed

Lines changed: 61 additions & 4 deletions

File tree

libp2p/protocols/service_discovery/registrar.nim

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -379,8 +379,14 @@ proc updateExistingAd*(
379379
registrar.cacheTimestamps[existing.toAdvertisementKey()] = now
380380
return false
381381
elif ad.data.seqNo > existing.data.seqNo:
382+
let oldKey = existing.toAdvertisementKey()
383+
for _, sads in registrar.cache.mpairs:
384+
for j in 0 ..< sads.len:
385+
if sads[j].toAdvertisementKey() == oldKey:
386+
sads[j] = ad
387+
382388
registrar.ipTree.removeAd(existing)
383-
registrar.cacheTimestamps.del(existing.toAdvertisementKey())
389+
registrar.cacheTimestamps.del(oldKey)
384390
ads[idx] = ad
385391
registrar.cacheTimestamps[ad.toAdvertisementKey()] = now
386392
registrar.ipTree.insertAd(ad)
@@ -398,11 +404,15 @@ proc insertNewAd*(
398404
## Insert a brand-new advertisement into the cache.
399405
## Evicts the globally oldest entry first if the cache is at capacity.
400406
## Returns true (a new insertion always warrants a metrics update).
401-
if disco.registrar.cacheTimestamps.len.uint64 >= disco.discoConfig.advertCacheCap:
407+
let key = ad.toAdvertisementKey()
408+
let isNewKey = key notin disco.registrar.cacheTimestamps
409+
if isNewKey and
410+
disco.registrar.cacheTimestamps.len.uint64 >= disco.discoConfig.advertCacheCap:
402411
evictOldestAd(disco, serviceId, ads)
403412
ads.add(ad)
404-
disco.registrar.cacheTimestamps[ad.toAdvertisementKey()] = now
405-
disco.registrar.ipTree.insertAd(ad)
413+
disco.registrar.cacheTimestamps[key] = now
414+
if isNewKey:
415+
disco.registrar.ipTree.insertAd(ad)
406416
return true
407417

408418
proc acceptAdvertisement*(

tests/libp2p/service_discovery/test_registrar.nim

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,32 @@ suite "Service Discovery Registrar - updateExistingAd":
13361336
check currentAd.toAdvertisementKey() in registrar.cacheTimestamps
13371337
check staleAd.toAdvertisementKey() notin registrar.cacheTimestamps
13381338

1339+
test "higher seqNo replaces stale copies in every other service that cached it":
1340+
let registrar = Registrar.new()
1341+
let serviceId1 = makeServiceId(1)
1342+
let serviceId2 = makeServiceId(2)
1343+
let privateKey = PrivateKey.random(rng()).get()
1344+
let oldAd = makeAdvertisement(privateKey = privateKey, seqNo = 1)
1345+
let newAd = makeAdvertisement(privateKey = privateKey, seqNo = 2)
1346+
1347+
registrar.cache[serviceId1] = @[oldAd]
1348+
registrar.cache[serviceId2] = @[oldAd]
1349+
registrar.cacheTimestamps[oldAd.toAdvertisementKey()] = initMoment(1000)
1350+
registrar.ipTree.insertAd(oldAd)
1351+
1352+
var ads1 = registrar.cache[serviceId1]
1353+
let changed = registrar.updateExistingAd(ads1, 0, newAd, initMoment(2000))
1354+
registrar.cache[serviceId1] = ads1
1355+
1356+
check changed
1357+
check registrar.cache[serviceId1].len == 1
1358+
check registrar.cache[serviceId1][0].data.seqNo == 2
1359+
# serviceId2 was never passed into updateExistingAd directly.
1360+
check registrar.cache[serviceId2].len == 1
1361+
check registrar.cache[serviceId2][0].data.seqNo == 2
1362+
check oldAd.toAdvertisementKey() notin registrar.cacheTimestamps
1363+
check newAd.toAdvertisementKey() in registrar.cacheTimestamps
1364+
13391365
suite "Service Discovery Registrar - insertNewAd":
13401366
test "inserts ad into cache, IP tree, and timestamps, returns true":
13411367
let disco =
@@ -1354,6 +1380,27 @@ suite "Service Discovery Registrar - insertNewAd":
13541380
check disco.registrar.cacheTimestamps[ad.toAdvertisementKey()] == now
13551381
check disco.registrar.ipTree.root.counter > 0
13561382

1383+
test "same ad accepted for three services counts the IP tree only once":
1384+
let disco =
1385+
setupServiceDiscoveryNode(discoConfig = ServiceDiscoveryConfig.new(fReturn = 3))
1386+
let serviceId1 = makeServiceId(1)
1387+
let serviceId2 = makeServiceId(2)
1388+
let serviceId3 = makeServiceId(3)
1389+
let ad = makeAdvertisement(addrs = @[makeMultiAddress("10.0.0.1")])
1390+
let now = initMoment(1000)
1391+
1392+
var ads1: seq[Advertisement] = @[]
1393+
var ads2: seq[Advertisement] = @[]
1394+
var ads3: seq[Advertisement] = @[]
1395+
discard disco.insertNewAd(serviceId1, ads1, ad, now)
1396+
discard disco.insertNewAd(serviceId2, ads2, ad, now)
1397+
discard disco.insertNewAd(serviceId3, ads3, ad, now)
1398+
disco.registrar.cache[serviceId1] = ads1
1399+
disco.registrar.cache[serviceId2] = ads2
1400+
disco.registrar.cache[serviceId3] = ads3
1401+
1402+
check disco.registrar.ipTree.root.counter == 1
1403+
13571404
test "inserts ad without eviction when cache is under capacity":
13581405
let disco = setupServiceDiscoveryNode(
13591406
discoConfig = ServiceDiscoveryConfig.new(fReturn = 3, advertExpiry = 900.secs)

0 commit comments

Comments
 (0)