nimbus-eth1/fluffy/scripts/test_portal_testnet.nim
Kim De Mey 38036966a6
Improve the tests of the local testnet (#953)
* Improve the tests of the local testnet

The local testnet test was rather flaky and would occasionally
fail. It has been made more robust by adding the ENRs directly
to the routing table instead of doing some random lookups.

Additionally, the amount of nodes were increased (=64), ip limits
configuration was added, and the bits-per-hop value was set to 1
in order to make the lookups more likely to hit the network
instead of only the local routing table.

Failure is obviously still possible to happen when sufficient
packets get lost. If this turns out to be the case with the current
amount of nodes, we might have to revise the testing strategy here.

* Disable lookup test for State network

Disable lookup test for State network due to issue with custom
distance function causing the lookup to not always converging
towards the target.
2022-02-02 22:48:33 +01:00

161 lines
5.9 KiB
Nim

# Nimbus
# Copyright (c) 2021 Status Research & Development GmbH
# Licensed and distributed under either of
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import
std/sequtils,
unittest2, testutils, confutils, chronos,
eth/p2p/discoveryv5/random2, eth/keys,
../rpc/portal_rpc_client
type
PortalTestnetConf* = object
nodeCount* {.
defaultValue: 17
desc: "Number of nodes to test"
name: "node-count" .}: int
rpcAddress* {.
desc: "Listening address of the JSON-RPC service for all nodes"
defaultValue: "127.0.0.1"
name: "rpc-address" }: string
baseRpcPort* {.
defaultValue: 7000
desc: "Port of the JSON-RPC service of the bootstrap (first) node"
name: "base-rpc-port" .}: uint16
proc connectToRpcServers(config: PortalTestnetConf):
Future[seq[RpcClient]] {.async.} =
var clients: seq[RpcClient]
for i in 0..<config.nodeCount:
let client = newRpcHttpClient()
await client.connect(
config.rpcAddress, Port(config.baseRpcPort + uint16(i)), false)
clients.add(client)
return clients
# We are kind of abusing the unittest2 here to run json rpc tests against other
# processes. Needs to be compiled with `-d:unittest2DisableParamFiltering` or
# the confutils cli will not work.
procSuite "Portal testnet tests":
let config = PortalTestnetConf.load()
let rng = newRng()
asyncTest "Discv5 - Random node lookup from each node":
let clients = await connectToRpcServers(config)
var nodeInfos: seq[NodeInfo]
for client in clients:
let nodeInfo = await client.discv5_nodeInfo()
nodeInfos.add(nodeInfo)
# Kick off the network by trying to add all records to each node.
# These nodes are also set as seen, so they get passed along on findNode
# requests.
# Note: The amount of Records added here can be less but then the
# probability that all nodes will still be reached needs to be calculated.
# Note 2: One could also ping all nodes but that is much slower and more
# error prone
for client in clients:
try:
discard await client.discv5_addEnrs(nodeInfos.map(
proc(x: NodeInfo): Record = x.nodeENR))
except CatchableError as e:
# Call shouldn't fail, unless there are json rpc server/client issues
echo e.msg
raise e
for client in clients:
let routingTableInfo = await client.discv5_routingTableInfo()
var start: seq[NodeId]
let nodes = foldl(routingTableInfo.buckets, a & b, start)
# A node will have at least the first bucket filled. One could increase
# this based on the probability that x amount of nodes fit in the buckets.
check nodes.len >= (min(config.nodeCount - 1, 16))
# grab a random node its `NodeInfo` and lookup that node from all nodes.
let randomNodeInfo = sample(rng[], nodeInfos)
for client in clients:
var enr: Record
try:
enr = await client.discv5_lookupEnr(randomNodeInfo.nodeId)
except CatchableError as e:
echo e.msg
check enr == randomNodeInfo.nodeENR
asyncTest "Portal State - Random node lookup from each node":
let clients = await connectToRpcServers(config)
var nodeInfos: seq[NodeInfo]
for client in clients:
let nodeInfo = await client.portal_state_nodeInfo()
nodeInfos.add(nodeInfo)
for client in clients:
try:
discard await client.portal_state_addEnrs(nodeInfos.map(
proc(x: NodeInfo): Record = x.nodeENR))
except CatchableError as e:
# Call shouldn't fail, unless there are json rpc server/client issues
echo e.msg
raise e
for client in clients:
let routingTableInfo = await client.portal_state_routingTableInfo()
var start: seq[NodeId]
let nodes = foldl(routingTableInfo.buckets, a & b, start)
check nodes.len >= (min(config.nodeCount - 1, 16))
# grab a random node its `NodeInfo` and lookup that node from all nodes.
let randomNodeInfo = sample(rng[], nodeInfos)
for client in clients:
var enr: Record
try:
enr = await client.portal_state_lookupEnr(randomNodeInfo.nodeId)
except CatchableError as e:
echo e.msg
# TODO: For state network this occasionally fails. It might be because the
# distance function is not used in all locations, or perhaps it just
# doesn't converge to the target always with this distance function. To be
# further investigated.
skip()
# check enr == randomNodeInfo.nodeENR
asyncTest "Portal History - Random node lookup from each node":
let clients = await connectToRpcServers(config)
var nodeInfos: seq[NodeInfo]
for client in clients:
let nodeInfo = await client.portal_history_nodeInfo()
nodeInfos.add(nodeInfo)
for client in clients:
try:
discard await client.portal_history_addEnrs(nodeInfos.map(
proc(x: NodeInfo): Record = x.nodeENR))
except CatchableError as e:
# Call shouldn't fail, unless there are json rpc server/client issues
echo e.msg
raise e
for client in clients:
let routingTableInfo = await client.portal_history_routingTableInfo()
var start: seq[NodeId]
let nodes = foldl(routingTableInfo.buckets, a & b, start)
check nodes.len >= (min(config.nodeCount - 1, 16))
# grab a random node its `NodeInfo` and lookup that node from all nodes.
let randomNodeInfo = sample(rng[], nodeInfos)
for client in clients:
var enr: Record
try:
enr = await client.portal_history_lookupEnr(randomNodeInfo.nodeId)
except CatchableError as e:
echo e.msg
check enr == randomNodeInfo.nodeENR