mirror of https://github.com/status-im/nim-eth.git
Clean-up routing table object constructions (#395)
This commit is contained in:
parent
c078f85e48
commit
bea1f1c6a1
|
@ -984,7 +984,7 @@ proc newProtocol*(privKey: PrivateKey,
|
|||
# TODO Consider whether this should be a Defect
|
||||
doAssert rng != nil, "RNG initialization failed"
|
||||
|
||||
result = Protocol(
|
||||
Protocol(
|
||||
privateKey: privKey,
|
||||
localNode: node,
|
||||
bindAddress: Address(ip: ValidIpAddress.init(bindIp), port: bindPort),
|
||||
|
@ -993,10 +993,9 @@ proc newProtocol*(privKey: PrivateKey,
|
|||
bootstrapRecords: @bootstrapRecords,
|
||||
ipVote: IpVote.init(),
|
||||
enrAutoUpdate: enrAutoUpdate,
|
||||
routingTable: RoutingTable.init(node, DefaultBitsPerHop, tableIpLimits, rng),
|
||||
rng: rng)
|
||||
|
||||
result.routingTable.init(node, DefaultBitsPerHop, tableIpLimits, rng)
|
||||
|
||||
proc open*(d: Protocol) {.raises: [Defect, CatchableError].} =
|
||||
info "Starting discovery node", node = d.localNode,
|
||||
bindAddress = d.bindAddress
|
||||
|
|
|
@ -139,13 +139,13 @@ const
|
|||
XorDistanceCalculator* = DistanceCalculator(calculateDistance: distanceTo,
|
||||
calculateLogDistance: logDist, calculateIdAtDistance: idAtDistance)
|
||||
|
||||
proc newKBucket(istart, iend: NodeId, bucketIpLimit: uint): KBucket =
|
||||
result.new()
|
||||
result.istart = istart
|
||||
result.iend = iend
|
||||
result.nodes = @[]
|
||||
result.replacementCache = @[]
|
||||
result.ipLimits.limit = bucketIpLimit
|
||||
proc new(T: type KBucket, istart, iend: NodeId, bucketIpLimit: uint): T =
|
||||
KBucket(
|
||||
istart: istart,
|
||||
iend: iend,
|
||||
nodes: @[],
|
||||
replacementCache: @[],
|
||||
ipLimits: IpLimits(limit: bucketIpLimit))
|
||||
|
||||
proc midpoint(k: KBucket): NodeId =
|
||||
k.istart + (k.iend - k.istart) div 2.u256
|
||||
|
@ -196,12 +196,12 @@ proc remove(k: KBucket, n: Node): bool =
|
|||
proc split(k: KBucket): tuple[lower, upper: KBucket] =
|
||||
## Split the kbucket `k` at the median id.
|
||||
let splitid = k.midpoint
|
||||
result.lower = newKBucket(k.istart, splitid, k.ipLimits.limit)
|
||||
result.upper = newKBucket(splitid + 1.u256, k.iend, k.ipLimits.limit)
|
||||
result.lower = KBucket.new(k.istart, splitid, k.ipLimits.limit)
|
||||
result.upper = KBucket.new(splitid + 1.u256, k.iend, k.ipLimits.limit)
|
||||
for node in k.nodes:
|
||||
let bucket = if node.id <= splitid: result.lower else: result.upper
|
||||
bucket.nodes.add(node)
|
||||
# Ip limits got reset because of the newKBuckets, so there is the need to
|
||||
# Ip limits got reset because of the KBucket.new, so there is the need to
|
||||
# increment again for each added node. It should however never fail as the
|
||||
# previous bucket had the same limits.
|
||||
doAssert(bucket.ipLimits.inc(node.address.get().ip),
|
||||
|
@ -252,16 +252,18 @@ proc computeSharedPrefixBits(nodes: openarray[NodeId]): int =
|
|||
# Reaching this would mean that all node ids are equal.
|
||||
doAssert(false, "Unable to calculate number of shared prefix bits")
|
||||
|
||||
proc init*(r: var RoutingTable, thisNode: Node, bitsPerHop = DefaultBitsPerHop,
|
||||
ipLimits = DefaultTableIpLimits, rng: ref BrHmacDrbgContext, distanceCalculator = XorDistanceCalculator) =
|
||||
proc init*(T: type RoutingTable, thisNode: Node, bitsPerHop = DefaultBitsPerHop,
|
||||
ipLimits = DefaultTableIpLimits, rng: ref BrHmacDrbgContext,
|
||||
distanceCalculator = XorDistanceCalculator): T =
|
||||
## Initialize the routing table for provided `Node` and bitsPerHop value.
|
||||
## `bitsPerHop` is default set to 5 as recommended by original Kademlia paper.
|
||||
r.thisNode = thisNode
|
||||
r.buckets = @[newKBucket(0.u256, high(Uint256), ipLimits.bucketIpLimit)]
|
||||
r.bitsPerHop = bitsPerHop
|
||||
r.ipLimits.limit = ipLimits.tableIpLimit
|
||||
r.distanceCalculator = distanceCalculator
|
||||
r.rng = rng
|
||||
RoutingTable(
|
||||
thisNode: thisNode,
|
||||
buckets: @[KBucket.new(0.u256, high(Uint256), ipLimits.bucketIpLimit)],
|
||||
bitsPerHop: bitsPerHop,
|
||||
ipLimits: IpLimits(limit: ipLimits.tableIpLimit),
|
||||
distanceCalculator: distanceCalculator,
|
||||
rng: rng)
|
||||
|
||||
proc splitBucket(r: var RoutingTable, index: int) =
|
||||
let bucket = r.buckets[index]
|
||||
|
|
|
@ -37,18 +37,14 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Add local node":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
table.init(node, 1, ipLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, ipLimits, rng = rng)
|
||||
|
||||
check table.addNode(node) == LocalNode
|
||||
|
||||
test "Bucket splitting in range branch b=1":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
# bitsPerHop = 1 -> Split only the branch in range of own id
|
||||
table.init(node, 1, ipLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, ipLimits, rng = rng)
|
||||
|
||||
for j in 0..5'u32:
|
||||
for i in 0..<BUCKET_SIZE:
|
||||
|
@ -57,10 +53,8 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Bucket splitting off range branch b=1":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
# bitsPerHop = 1 -> Split only the branch in range of own id
|
||||
table.init(node, 1, ipLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, ipLimits, rng = rng)
|
||||
|
||||
# Add 16 nodes, distance 256
|
||||
for i in 0..<BUCKET_SIZE:
|
||||
|
@ -77,10 +71,8 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Bucket splitting off range branch b=2":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
# bitsPerHop = 2, allow not in range branch to split once (2 buckets).
|
||||
table.init(node, 2, ipLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 2, ipLimits, rng = rng)
|
||||
|
||||
# Add 16 nodes, distance 256 from `node`, but all with 2 bits shared prefix
|
||||
# among themselves.
|
||||
|
@ -107,10 +99,8 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Replacement cache":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
# bitsPerHop = 1 -> Split only the branch in range of own id
|
||||
table.init(node, 1, ipLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, ipLimits, rng = rng)
|
||||
|
||||
# create a full bucket
|
||||
let bucketNodes = node.nodesAtDistance(rng[], 256, BUCKET_SIZE)
|
||||
|
@ -141,10 +131,8 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Empty bucket":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
# bitsPerHop = 1 -> Split only the branch in range of own id
|
||||
table.init(node, 1, ipLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, ipLimits, rng = rng)
|
||||
|
||||
check table.nodeToRevalidate().isNil()
|
||||
|
||||
|
@ -165,10 +153,8 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Empty replacement cache":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
# bitsPerHop = 1 -> Split only the branch in range of own id
|
||||
table.init(node, 1, ipLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, ipLimits, rng = rng)
|
||||
|
||||
# create a full bucket TODO: no need to store bucketNodes
|
||||
let bucketNodes = node.nodesAtDistance(rng[], 256, BUCKET_SIZE)
|
||||
|
@ -181,10 +167,8 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Double add":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
# bitsPerHop = 1 -> Split only the branch in range of own id
|
||||
table.init(node, 1, ipLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, ipLimits, rng = rng)
|
||||
|
||||
let doubleNode = node.nodeAtDistance(rng[], 256)
|
||||
# Try to add the node twice
|
||||
|
@ -211,10 +195,8 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Double replacement add":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
# bitsPerHop = 1 -> Split only the branch in range of own id
|
||||
table.init(node, 1, ipLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, ipLimits, rng = rng)
|
||||
|
||||
# create a full bucket
|
||||
let bucketNodes = node.nodesAtDistance(rng[], 256, BUCKET_SIZE)
|
||||
|
@ -241,10 +223,8 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Just seen":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
# bitsPerHop = 1 -> Split only the branch in range of own id
|
||||
table.init(node, 1, ipLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, ipLimits, rng = rng)
|
||||
|
||||
# create a full bucket
|
||||
let bucketNodes = node.nodesAtDistance(rng[], 256, BUCKET_SIZE)
|
||||
|
@ -261,10 +241,8 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Just seen replacement":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
# bitsPerHop = 1 -> Split only the branch in range of own id
|
||||
table.init(node, 1, ipLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, ipLimits, rng = rng)
|
||||
|
||||
# create a full bucket
|
||||
let bucketNodes = node.nodesAtDistance(rng[], 256, BUCKET_SIZE)
|
||||
|
@ -294,10 +272,8 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Ip limits on bucket":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
# bitsPerHop = 1 -> Split only the branch in range of own id
|
||||
table.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
|
||||
block: # First bucket
|
||||
let sameIpNodes = node.nodesAtDistance(rng[], 256,
|
||||
|
@ -344,10 +320,8 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Ip limits on routing table":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
# bitsPerHop = 1 -> Split only the branch in range of own id
|
||||
table.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
|
||||
let amount = uint32(DefaultTableIpLimits.tableIpLimit div
|
||||
DefaultTableIpLimits.bucketIpLimit)
|
||||
|
@ -384,9 +358,7 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Ip limits on replacement cache":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
table.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
|
||||
let diffIpNodes = node.nodesAtDistanceUniqueIp(rng[], 256,
|
||||
int(BUCKET_SIZE - DefaultTableIpLimits.bucketIpLimit + 1),
|
||||
|
@ -422,9 +394,7 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Ip limits on replacement cache: deletion":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
table.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
|
||||
block: # Fill bucket
|
||||
let sameIpNodes = node.nodesAtDistance(rng[], 256,
|
||||
|
@ -462,9 +432,7 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Ip limits on replacement cache: double add":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
table.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
|
||||
# Fill bucket
|
||||
let diffIpNodes = node.nodesAtDistanceUniqueIp(rng[], 256, BUCKET_SIZE,
|
||||
|
@ -484,9 +452,7 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Ip limits on bucket: double add with new ip":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
table.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
|
||||
let pk = PrivateKey.random(rng[])
|
||||
let sameIpNode1 = generateNode(pk)
|
||||
|
@ -509,9 +475,7 @@ suite "Routing Table Tests":
|
|||
|
||||
test "Ip limits on replacement cache: double add with new ip":
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
table.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
|
||||
# Fill bucket
|
||||
let diffIpNodes = node.nodesAtDistanceUniqueIp(rng[], 256, BUCKET_SIZE,
|
||||
|
@ -535,9 +499,7 @@ suite "Routing Table Tests":
|
|||
test "Ip limits on bucket: even more adds with new ip":
|
||||
# This tests against an issue where the ip of the nodes would not get updated
|
||||
let node = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
|
||||
table.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
var table = RoutingTable.init(node, 1, DefaultTableIpLimits, rng = rng)
|
||||
|
||||
let pk = PrivateKey.random(rng[])
|
||||
let sameIpNode1 = generateNode(pk)
|
||||
|
@ -563,8 +525,8 @@ suite "Routing Table Tests":
|
|||
test "Custom distance calculator: distance":
|
||||
let numNodes = 10
|
||||
let local = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
table.init(local, 1, ipLimits, rng = rng, distanceCalculator = customDistanceCalculator)
|
||||
var table = RoutingTable.init(local, 1, ipLimits, rng = rng,
|
||||
distanceCalculator = customDistanceCalculator)
|
||||
|
||||
let nodes = generateNRandomNodes(rng, numNodes)
|
||||
|
||||
|
@ -583,8 +545,8 @@ suite "Routing Table Tests":
|
|||
test "Custom distance calculator: at log distance":
|
||||
let numNodes = 10
|
||||
let local = generateNode(PrivateKey.random(rng[]))
|
||||
var table: RoutingTable
|
||||
table.init(local, 1, ipLimits, rng = rng, distanceCalculator = customDistanceCalculator)
|
||||
var table = RoutingTable.init(local, 1, ipLimits, rng = rng,
|
||||
distanceCalculator = customDistanceCalculator)
|
||||
|
||||
let nodes = generateNRandomNodes(rng, numNodes)
|
||||
|
||||
|
@ -600,4 +562,3 @@ suite "Routing Table Tests":
|
|||
# there may be more than one node at provided distance
|
||||
check len(neighboursAtLogDist) >= 1
|
||||
check neighboursAtLogDist.contains(n)
|
||||
|
||||
|
|
Loading…
Reference in New Issue