discv4: fix ping pong time removal algorithm

This commit is contained in:
jangko 2022-09-07 21:12:32 +07:00
parent 58d7e98c5c
commit 5885f638e4
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
1 changed files with 36 additions and 12 deletions

View File

@ -64,6 +64,8 @@ const
ID_SIZE = 256 ID_SIZE = 256
BOND_EXPIRATION = initDuration(hours = 12) BOND_EXPIRATION = initDuration(hours = 12)
proc len(r: RoutingTable): int
proc toNodeId*(pk: PublicKey): NodeId = proc toNodeId*(pk: PublicKey): NodeId =
readUintBE[256](keccak256.digest(pk.toRaw()).data) readUintBE[256](keccak256.digest(pk.toRaw()).data)
@ -125,25 +127,47 @@ proc cmp(x, y: (TimeKey, int64)): int =
proc removeTooOldPingPongTime(k: KademliaProtocol) = proc removeTooOldPingPongTime(k: KademliaProtocol) =
const const
MaxEntries = 128 MinEntries = 128
MaxRC = 5 MaxRC = MinEntries div 8
if k.pingPongTime.len < MaxEntries: # instead of using fixed limit, we use dynamic limit
# with minimum entries = 128.
# remove 25% of too old entries if we need more space.
# the reason maxEntries is twice routing table because we
# store ping and pong time.
let
maxEntries = max(k.routing.len * 2, MinEntries)
maxRemove = maxEntries div 4
if k.pingPongTime.len < maxEntries:
return return
# it is safe to remove this table sort?
# because we already using ordered table to store time from
# older value to newer value
when false:
k.pingPongTime.sort(cmp, order = SortOrder.Descending) k.pingPongTime.sort(cmp, order = SortOrder.Descending)
var var
num = 0 rci = 0
rc: array[MaxRC, TimeKey] numRemoved = 0
rc: array[MaxRC, TimeKey] # 784 bytes(MinEntries/8*sizeof(TimeKey))
# using fixed size temp on stack possibly
# requires multiple iteration to remove
# old entries
while numRemoved < maxRemove:
for v in keys(k.pingPongTime): for v in keys(k.pingPongTime):
if num < MaxRC: rc[rci] = v
rc[num] = v inc rci
inc num inc numRemoved
if rci >= MaxRC or numRemoved >= maxRemove: break
for i in 0..<num: for i in 0..<rci:
k.pingPongTime.del(rc[i]) k.pingPongTime.del(rc[i])
rci = 0
proc updateLastPingReceived(k: KademliaProtocol, n: Node, t: Time) = proc updateLastPingReceived(k: KademliaProtocol, n: Node, t: Time) =
k.removeTooOldPingPongTime() k.removeTooOldPingPongTime()
k.pingPongTime[n.timeKeyPing] = t.toUnix k.pingPongTime[n.timeKeyPing] = t.toUnix