Export discovery routing table and its buckets nodes (#430)

This commit is contained in:
Kim De Mey 2021-11-22 18:53:52 +01:00 committed by GitHub
parent ce296ff76e
commit e606d8c79e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 13 additions and 13 deletions

View File

@ -122,7 +122,7 @@ type
privateKey: PrivateKey privateKey: PrivateKey
bindAddress: Address ## UDP binding address bindAddress: Address ## UDP binding address
pendingRequests: Table[AESGCMNonce, PendingRequest] pendingRequests: Table[AESGCMNonce, PendingRequest]
routingTable: RoutingTable routingTable*: RoutingTable
codec*: Codec codec*: Codec
awaitedMessages: Table[(NodeId, RequestId), Future[Option[Message]]] awaitedMessages: Table[(NodeId, RequestId), Future[Option[Message]]]
refreshLoop: Future[void] refreshLoop: Future[void]

View File

@ -29,8 +29,8 @@ type
calculateIdAtDistance*: IdAtDistanceProc calculateIdAtDistance*: IdAtDistanceProc
RoutingTable* = object RoutingTable* = object
thisNode: Node localNode*: Node
buckets: seq[KBucket] buckets*: seq[KBucket]
bitsPerHop: int ## This value indicates how many bits (at minimum) you get bitsPerHop: int ## This value indicates how many bits (at minimum) you get
## closer to finding your target per query. Practically, it tells you also ## closer to finding your target per query. Practically, it tells you also
## how often your "not in range" branch will split off. Setting this to 1 ## how often your "not in range" branch will split off. Setting this to 1
@ -47,8 +47,8 @@ type
KBucket = ref object KBucket = ref object
istart, iend: NodeId ## Range of NodeIds this KBucket covers. This is not a istart, iend: NodeId ## Range of NodeIds this KBucket covers. This is not a
## simple logarithmic distance as buckets can be split over a prefix that ## simple logarithmic distance as buckets can be split over a prefix that
## does not cover the `thisNode` id. ## does not cover the `localNode` id.
nodes: seq[Node] ## Node entries of the KBucket. Sorted according to last nodes*: seq[Node] ## Node entries of the KBucket. Sorted according to last
## time seen. First entry (head) is considered the most recently seen node ## time seen. First entry (head) is considered the most recently seen node
## and the last entry (tail) is considered the least recently seen node. ## and the last entry (tail) is considered the least recently seen node.
## Here "seen" means a successful request-response. This can also not have ## Here "seen" means a successful request-response. This can also not have
@ -259,13 +259,13 @@ proc computeSharedPrefixBits(nodes: openarray[NodeId]): int =
# Reaching this would mean that all node ids are equal. # Reaching this would mean that all node ids are equal.
doAssert(false, "Unable to calculate number of shared prefix bits") doAssert(false, "Unable to calculate number of shared prefix bits")
proc init*(T: type RoutingTable, thisNode: Node, bitsPerHop = DefaultBitsPerHop, proc init*(T: type RoutingTable, localNode: Node, bitsPerHop = DefaultBitsPerHop,
ipLimits = DefaultTableIpLimits, rng: ref BrHmacDrbgContext, ipLimits = DefaultTableIpLimits, rng: ref BrHmacDrbgContext,
distanceCalculator = XorDistanceCalculator): T = distanceCalculator = XorDistanceCalculator): T =
## Initialize the routing table for provided `Node` and bitsPerHop value. ## Initialize the routing table for provided `Node` and bitsPerHop value.
## `bitsPerHop` is default set to 5 as recommended by original Kademlia paper. ## `bitsPerHop` is default set to 5 as recommended by original Kademlia paper.
RoutingTable( RoutingTable(
thisNode: thisNode, localNode: localNode,
buckets: @[KBucket.new(0.u256, high(Uint256), ipLimits.bucketIpLimit)], buckets: @[KBucket.new(0.u256, high(Uint256), ipLimits.bucketIpLimit)],
bitsPerHop: bitsPerHop, bitsPerHop: bitsPerHop,
ipLimits: IpLimits(limit: ipLimits.tableIpLimit), ipLimits: IpLimits(limit: ipLimits.tableIpLimit),
@ -336,7 +336,7 @@ proc addNode*(r: var RoutingTable, n: Node): NodeStatus =
if n.address.isNone(): if n.address.isNone():
return NoAddress return NoAddress
if n == r.thisNode: if n == r.localNode:
return LocalNode return LocalNode
let bucket = r.bucketForNode(n.id) let bucket = r.bucketForNode(n.id)
@ -386,7 +386,7 @@ proc addNode*(r: var RoutingTable, n: Node): NodeStatus =
let depth = computeSharedPrefixBits(@[bucket.istart, bucket.iend]) let depth = computeSharedPrefixBits(@[bucket.istart, bucket.iend])
# Split if the bucket has the local node in its range or if the depth is not # Split if the bucket has the local node in its range or if the depth is not
# congruent to 0 mod `bitsPerHop` # congruent to 0 mod `bitsPerHop`
if bucket.inRange(r.thisNode) or if bucket.inRange(r.localNode) or
(depth mod r.bitsPerHop != 0 and depth != ID_SIZE): (depth mod r.bitsPerHop != 0 and depth != ID_SIZE):
r.splitBucket(r.buckets.find(bucket)) r.splitBucket(r.buckets.find(bucket))
return r.addNode(n) # retry adding return r.addNode(n) # retry adding
@ -456,10 +456,10 @@ proc neighbours*(r: RoutingTable, id: NodeId, k: int = BUCKET_SIZE,
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.idAtDistance(r.thisNode.id, distance), k, seenOnly) result = r.neighbours(r.idAtDistance(r.localNode.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.logDistance(n.id, r.thisNode.id) == distance) keepIf(result, proc(n: Node): bool = r.logDistance(n.id, r.localNode.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] =
@ -468,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.idAtDistance(r.thisNode.id, distances[0]), k, result = r.neighbours(r.idAtDistance(r.localNode.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.logDistance(n.id, r.thisNode.id))) distances.contains(r.logDistance(n.id, r.localNode.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