mirror of https://github.com/status-im/nim-eth.git
Make the custom distances call somewhat more accessible (#404)
And make the naming more consistent
This commit is contained in:
parent
32ef1b7f4f
commit
5125a438db
|
@ -67,7 +67,8 @@ proc verifyNodesRecords(enrs: openarray[Record], fromNode: Node, nodesLimit: int
|
||||||
continue
|
continue
|
||||||
# Check if returned node has one of the requested distances.
|
# Check if returned node has one of the requested distances.
|
||||||
if distances.isSome():
|
if distances.isSome():
|
||||||
if (not distances.get().contains(logDist(n.id, fromNode.id))):
|
# TODO: This is incorrect for custom distances
|
||||||
|
if (not distances.get().contains(logDistance(n.id, fromNode.id))):
|
||||||
debug "Incorrect distance",
|
debug "Incorrect distance",
|
||||||
record = n.record.toURI, sender = fromNode.record.toURI
|
record = n.record.toURI, sender = fromNode.record.toURI
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -586,7 +586,7 @@ proc talkreq*(d: Protocol, toNode: Node, protocol, request: seq[byte]):
|
||||||
return err("Talk response message not received in time")
|
return err("Talk response message not received in time")
|
||||||
|
|
||||||
proc lookupDistances*(target, dest: NodeId): seq[uint16] =
|
proc lookupDistances*(target, dest: NodeId): seq[uint16] =
|
||||||
let td = logDist(target, dest)
|
let td = logDistance(target, dest)
|
||||||
let tdAsInt = int(td)
|
let tdAsInt = int(td)
|
||||||
result.add(td)
|
result.add(td)
|
||||||
var i = 1
|
var i = 1
|
||||||
|
@ -658,7 +658,7 @@ proc lookup*(d: Protocol, target: NodeId): Future[seq[Node]] {.async.} =
|
||||||
# If it wasn't seen before, insert node while remaining sorted
|
# If it wasn't seen before, insert node while remaining sorted
|
||||||
closestNodes.insert(n, closestNodes.lowerBound(n,
|
closestNodes.insert(n, closestNodes.lowerBound(n,
|
||||||
proc(x: Node, n: Node): int =
|
proc(x: Node, n: Node): int =
|
||||||
cmp(distanceTo(x.id, target), distanceTo(n.id, target))
|
cmp(distance(x.id, target), distance(n.id, target))
|
||||||
))
|
))
|
||||||
|
|
||||||
if closestNodes.len > BUCKET_SIZE:
|
if closestNodes.len > BUCKET_SIZE:
|
||||||
|
|
|
@ -93,20 +93,11 @@ type
|
||||||
NoAddress
|
NoAddress
|
||||||
|
|
||||||
# xor distance functions
|
# xor distance functions
|
||||||
#
|
func distance*(a, b: NodeId): Uint256 =
|
||||||
func distanceTo*(a, b: NodeId): Uint256 =
|
|
||||||
## Calculate the distance to a NodeId.
|
## Calculate the distance to a NodeId.
|
||||||
a xor b
|
a xor b
|
||||||
|
|
||||||
func idAtDistance*(id: NodeId, dist: uint16): NodeId =
|
func logDistance*(a, b: NodeId): uint16 =
|
||||||
## Calculate the "lowest" `NodeId` for given logarithmic distance.
|
|
||||||
## A logarithmic distance obviously covers a whole range of distances and thus
|
|
||||||
## potential `NodeId`s.
|
|
||||||
# xor the NodeId with 2^(d - 1) or one could say, calculate back the leading
|
|
||||||
# zeroes and xor those` with the id.
|
|
||||||
id xor (1.stuint(256) shl (dist.int - 1))
|
|
||||||
|
|
||||||
func logDist*(a, b: NodeId): uint16 =
|
|
||||||
## Calculate the logarithmic distance between two `NodeId`s.
|
## Calculate the logarithmic distance between two `NodeId`s.
|
||||||
##
|
##
|
||||||
## According the specification, this is the log base 2 of the distance. But it
|
## According the specification, this is the log base 2 of the distance. But it
|
||||||
|
@ -124,7 +115,14 @@ func logDist*(a, b: NodeId): uint16 =
|
||||||
lz += bitops.countLeadingZeroBits(x)
|
lz += bitops.countLeadingZeroBits(x)
|
||||||
break
|
break
|
||||||
return uint16(a.len * 8 - lz)
|
return uint16(a.len * 8 - lz)
|
||||||
#
|
|
||||||
|
func idAtDistance*(id: NodeId, dist: uint16): NodeId =
|
||||||
|
## Calculate the "lowest" `NodeId` for given logarithmic distance.
|
||||||
|
## A logarithmic distance obviously covers a whole range of distances and thus
|
||||||
|
## potential `NodeId`s.
|
||||||
|
# xor the NodeId with 2^(d - 1) or one could say, calculate back the leading
|
||||||
|
# zeroes and xor those` with the id.
|
||||||
|
id xor (1.stuint(256) shl (dist.int - 1))
|
||||||
|
|
||||||
const
|
const
|
||||||
BUCKET_SIZE* = 16 ## Maximum amount of nodes per bucket
|
BUCKET_SIZE* = 16 ## Maximum amount of nodes per bucket
|
||||||
|
@ -136,8 +134,17 @@ const
|
||||||
DefaultTableIpLimit* = 10'u
|
DefaultTableIpLimit* = 10'u
|
||||||
DefaultTableIpLimits* = TableIpLimits(tableIpLimit: DefaultTableIpLimit,
|
DefaultTableIpLimits* = TableIpLimits(tableIpLimit: DefaultTableIpLimit,
|
||||||
bucketIpLimit: DefaultBucketIpLimit)
|
bucketIpLimit: DefaultBucketIpLimit)
|
||||||
XorDistanceCalculator* = DistanceCalculator(calculateDistance: distanceTo,
|
XorDistanceCalculator* = DistanceCalculator(calculateDistance: distance,
|
||||||
calculateLogDistance: logDist, calculateIdAtDistance: idAtDistance)
|
calculateLogDistance: logDistance, calculateIdAtDistance: idAtDistance)
|
||||||
|
|
||||||
|
func distance*(r: RoutingTable, a, b: NodeId): Uint256 =
|
||||||
|
r.distanceCalculator.calculateDistance(a, b)
|
||||||
|
|
||||||
|
func logDistance*(r: RoutingTable, a, b: NodeId): uint16 =
|
||||||
|
r.distanceCalculator.calculateLogDistance(a, b)
|
||||||
|
|
||||||
|
func idAtDistance*(r: RoutingTable, id: NodeId, dist: uint16): NodeId =
|
||||||
|
r.distanceCalculator.calculateIdAtDistance(id, dist)
|
||||||
|
|
||||||
proc new(T: type KBucket, istart, iend: NodeId, bucketIpLimit: uint): T =
|
proc new(T: type KBucket, istart, iend: NodeId, bucketIpLimit: uint): T =
|
||||||
KBucket(
|
KBucket(
|
||||||
|
@ -420,10 +427,10 @@ proc contains*(r: RoutingTable, n: Node): bool = n in r.bucketForNode(n.id)
|
||||||
# Check if the routing table contains node `n`.
|
# Check if the routing table contains node `n`.
|
||||||
|
|
||||||
proc bucketsByDistanceTo(r: RoutingTable, id: NodeId): seq[KBucket] =
|
proc bucketsByDistanceTo(r: RoutingTable, id: NodeId): seq[KBucket] =
|
||||||
sortedByIt(r.buckets, r.distanceCalculator.calculateDistance(it.midpoint, id))
|
sortedByIt(r.buckets, r.distance(it.midpoint, id))
|
||||||
|
|
||||||
proc nodesByDistanceTo(r: RoutingTable, k: KBucket, id: NodeId): seq[Node] =
|
proc nodesByDistanceTo(r: RoutingTable, k: KBucket, id: NodeId): seq[Node] =
|
||||||
sortedByIt(k.nodes, r.distanceCalculator.calculateDistance(it.id, id))
|
sortedByIt(k.nodes, r.distance(it.id, id))
|
||||||
|
|
||||||
proc neighbours*(r: RoutingTable, id: NodeId, k: int = BUCKET_SIZE,
|
proc neighbours*(r: RoutingTable, id: NodeId, k: int = BUCKET_SIZE,
|
||||||
seenOnly = false): seq[Node] =
|
seenOnly = false): seq[Node] =
|
||||||
|
@ -442,17 +449,17 @@ proc neighbours*(r: RoutingTable, id: NodeId, k: int = BUCKET_SIZE,
|
||||||
|
|
||||||
# TODO: is this sort still needed? Can we get nodes closer from the "next"
|
# TODO: is this sort still needed? Can we get nodes closer from the "next"
|
||||||
# bucket?
|
# bucket?
|
||||||
result = sortedByIt(result, r.distanceCalculator.calculateDistance(it.id, id))
|
result = sortedByIt(result, r.distance(it.id, id))
|
||||||
if result.len > k:
|
if result.len > k:
|
||||||
result.setLen(k)
|
result.setLen(k)
|
||||||
|
|
||||||
proc neighboursAtDistance*(r: RoutingTable, distance: uint16,
|
proc neighboursAtDistance*(r: RoutingTable, distance: uint16,
|
||||||
k: int = BUCKET_SIZE, seenOnly = false): seq[Node] =
|
k: int = BUCKET_SIZE, seenOnly = false): seq[Node] =
|
||||||
## Return up to k neighbours at given logarithmic distance.
|
## Return up to k neighbours at given logarithmic distance.
|
||||||
result = r.neighbours(r.distanceCalculator.calculateIdAtDistance(r.thisNode.id, distance), k, seenOnly)
|
result = r.neighbours(r.idAtDistance(r.thisNode.id, distance), k, seenOnly)
|
||||||
# This is a bit silly, first getting closest nodes then to only keep the ones
|
# This is a bit silly, first getting closest nodes then to only keep the ones
|
||||||
# that are exactly the requested distance.
|
# that are exactly the requested distance.
|
||||||
keepIf(result, proc(n: Node): bool = r.distanceCalculator.calculateLogDistance(n.id, r.thisNode.id) == distance)
|
keepIf(result, proc(n: Node): bool = r.logDistance(n.id, r.thisNode.id) == distance)
|
||||||
|
|
||||||
proc neighboursAtDistances*(r: RoutingTable, distances: seq[uint16],
|
proc neighboursAtDistances*(r: RoutingTable, distances: seq[uint16],
|
||||||
k: int = BUCKET_SIZE, seenOnly = false): seq[Node] =
|
k: int = BUCKET_SIZE, seenOnly = false): seq[Node] =
|
||||||
|
@ -461,12 +468,12 @@ proc neighboursAtDistances*(r: RoutingTable, distances: seq[uint16],
|
||||||
# first one prioritize. It might end up not including all the node distances
|
# first one prioritize. It might end up not including all the node distances
|
||||||
# requested. Need to rework the logic here and not use the neighbours call.
|
# requested. Need to rework the logic here and not use the neighbours call.
|
||||||
if distances.len > 0:
|
if distances.len > 0:
|
||||||
result = r.neighbours(r.distanceCalculator.calculateIdAtDistance(r.thisNode.id, distances[0]), k,
|
result = r.neighbours(r.idAtDistance(r.thisNode.id, distances[0]), k,
|
||||||
seenOnly)
|
seenOnly)
|
||||||
# This is a bit silly, first getting closest nodes then to only keep the ones
|
# This is a bit silly, first getting closest nodes then to only keep the ones
|
||||||
# that are exactly the requested distances.
|
# that are exactly the requested distances.
|
||||||
keepIf(result, proc(n: Node): bool =
|
keepIf(result, proc(n: Node): bool =
|
||||||
distances.contains(r.distanceCalculator.calculateLogDistance(n.id, r.thisNode.id)))
|
distances.contains(r.logDistance(n.id, r.thisNode.id)))
|
||||||
|
|
||||||
proc len*(r: RoutingTable): int =
|
proc len*(r: RoutingTable): int =
|
||||||
for b in r.buckets: result += b.len
|
for b in r.buckets: result += b.len
|
||||||
|
|
|
@ -54,7 +54,7 @@ proc nodeAndPrivKeyAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32,
|
||||||
while true:
|
while true:
|
||||||
let pk = PrivateKey.random(rng)
|
let pk = PrivateKey.random(rng)
|
||||||
let node = generateNode(pk, ip = ip)
|
let node = generateNode(pk, ip = ip)
|
||||||
if logDist(n.id, node.id) == d:
|
if logDistance(n.id, node.id) == d:
|
||||||
return (node, pk)
|
return (node, pk)
|
||||||
|
|
||||||
proc nodeAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32,
|
proc nodeAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32,
|
||||||
|
|
|
@ -62,6 +62,7 @@ procSuite "Discovery v5 Tests":
|
||||||
const
|
const
|
||||||
targetId = "0x0000"
|
targetId = "0x0000"
|
||||||
testValues = [
|
testValues = [
|
||||||
|
("0x0000", 0'u16),
|
||||||
("0x0001", 1'u16),
|
("0x0001", 1'u16),
|
||||||
("0x0002", 2'u16),
|
("0x0002", 2'u16),
|
||||||
("0x0003", 2'u16),
|
("0x0003", 2'u16),
|
||||||
|
@ -78,7 +79,7 @@ procSuite "Discovery v5 Tests":
|
||||||
]
|
]
|
||||||
|
|
||||||
for (id, d) in testValues:
|
for (id, d) in testValues:
|
||||||
check logDist(parse(targetId, UInt256, 16), parse(id, UInt256, 16)) == d
|
check logDistance(parse(targetId, UInt256, 16), parse(id, UInt256, 16)) == d
|
||||||
|
|
||||||
test "Distance check with keys":
|
test "Distance check with keys":
|
||||||
const
|
const
|
||||||
|
@ -96,7 +97,7 @@ procSuite "Discovery v5 Tests":
|
||||||
|
|
||||||
for (key, d) in testValues:
|
for (key, d) in testValues:
|
||||||
let id = toNodeId(PrivateKey.fromHex(key)[].toPublicKey())
|
let id = toNodeId(PrivateKey.fromHex(key)[].toPublicKey())
|
||||||
check logDist(targetId, id) == d
|
check logDistance(targetId, id) == d
|
||||||
|
|
||||||
test "Distance to id check":
|
test "Distance to id check":
|
||||||
const
|
const
|
||||||
|
@ -211,7 +212,7 @@ procSuite "Discovery v5 Tests":
|
||||||
let
|
let
|
||||||
neighbours = mainNode.neighbours(mainNode.localNode.id)
|
neighbours = mainNode.neighbours(mainNode.localNode.id)
|
||||||
closest = neighbours[0]
|
closest = neighbours[0]
|
||||||
closestDistance = logDist(closest.id, mainNode.localNode.id)
|
closestDistance = logDistance(closest.id, mainNode.localNode.id)
|
||||||
|
|
||||||
debug "Closest neighbour", closestDistance, id=closest.id.toHex()
|
debug "Closest neighbour", closestDistance, id=closest.id.toHex()
|
||||||
|
|
||||||
|
@ -471,7 +472,7 @@ procSuite "Discovery v5 Tests":
|
||||||
some(port), some(port))[]
|
some(port), some(port))[]
|
||||||
fromNode = newNode(fromNoderecord)[]
|
fromNode = newNode(fromNoderecord)[]
|
||||||
pk = PrivateKey.random(rng[])
|
pk = PrivateKey.random(rng[])
|
||||||
targetDistance = @[logDist(fromNode.id, pk.toPublicKey().toNodeId())]
|
targetDistance = @[logDistance(fromNode.id, pk.toPublicKey().toNodeId())]
|
||||||
limit = 16
|
limit = 16
|
||||||
|
|
||||||
block: # Duplicates
|
block: # Duplicates
|
||||||
|
|
Loading…
Reference in New Issue