2022-02-15 13:00:39 +00:00
|
|
|
#
|
|
|
|
# Ethereum P2P
|
|
|
|
# (c) Copyright 2018
|
|
|
|
# Status Research & Development GmbH
|
|
|
|
#
|
|
|
|
# See the file "LICENSE", included in this
|
|
|
|
# distribution, for details about the copyright.
|
|
|
|
#
|
|
|
|
|
|
|
|
{.used.}
|
|
|
|
|
|
|
|
import
|
2022-03-07 04:13:03 +00:00
|
|
|
std/options,
|
2022-02-15 13:00:39 +00:00
|
|
|
std/sequtils,
|
2022-02-24 11:56:11 +00:00
|
|
|
chronos, stew/byteutils, nimcrypto, asynctest,
|
2022-02-15 13:00:39 +00:00
|
|
|
eth/keys,
|
2022-02-24 11:56:11 +00:00
|
|
|
libp2pdht/dht,
|
2022-02-15 14:02:25 +00:00
|
|
|
chronicles,
|
2022-02-24 11:56:11 +00:00
|
|
|
libp2pdht/discv5/protocol as discv5_protocol,
|
2022-02-16 09:59:36 +00:00
|
|
|
test_helper,
|
2022-03-07 04:13:03 +00:00
|
|
|
libp2p/crypto/crypto,
|
|
|
|
libp2p/crypto/secp,
|
2022-02-16 09:17:00 +00:00
|
|
|
libp2p/routing_record,
|
2022-03-09 04:18:04 +00:00
|
|
|
libp2p/multiaddress,
|
2022-02-16 09:17:00 +00:00
|
|
|
libp2p/multihash,
|
2022-03-07 04:13:03 +00:00
|
|
|
libp2p/multicodec,
|
|
|
|
libp2p/signed_envelope
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-03-10 06:02:24 +00:00
|
|
|
proc bootstrapNodes(
|
|
|
|
nodecount: int,
|
2022-03-16 20:32:21 +00:00
|
|
|
bootnodes: seq[SignedPeerRecord],
|
2022-03-16 21:14:01 +00:00
|
|
|
rng = keys.newRng(),
|
|
|
|
delay: int = 0
|
2022-03-16 20:32:21 +00:00
|
|
|
) : Future[seq[(discv5_protocol.Protocol, keys.PrivateKey)]] {.async.} =
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-03-16 21:14:01 +00:00
|
|
|
debug "---- STARTING BOOSTRAPS ---"
|
2022-03-10 06:02:24 +00:00
|
|
|
for i in 0..<nodecount:
|
|
|
|
let privKey = keys.PrivateKey.random(rng[])
|
|
|
|
let node = initDiscoveryNode(rng, privKey, localAddress(20302 + i), bootnodes)
|
|
|
|
node.start()
|
|
|
|
result.add((node, privKey))
|
2022-03-16 21:14:01 +00:00
|
|
|
if delay > 0:
|
|
|
|
await sleepAsync(chronos.milliseconds(delay))
|
|
|
|
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-03-10 06:02:24 +00:00
|
|
|
#await allFutures(result.mapIt(it.bootstrap())) # this waits for bootstrap based on bootENode, which includes bonding with all its ping pongs
|
|
|
|
|
|
|
|
proc bootstrapNetwork(
|
|
|
|
nodecount: int,
|
|
|
|
rng = keys.newRng()
|
2022-03-16 20:32:21 +00:00
|
|
|
) : Future[seq[(discv5_protocol.Protocol, keys.PrivateKey)]] {.async.} =
|
2022-02-15 13:00:39 +00:00
|
|
|
|
|
|
|
let
|
2022-02-15 14:02:25 +00:00
|
|
|
bootNodeKey = keys.PrivateKey.fromHex(
|
2022-02-15 13:00:39 +00:00
|
|
|
"a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")[]
|
|
|
|
bootNodeAddr = localAddress(20301)
|
2022-03-10 06:02:24 +00:00
|
|
|
bootNode = initDiscoveryNode(rng, bootNodeKey, bootNodeAddr, @[]) # just a shortcut for new and open
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-15 14:02:25 +00:00
|
|
|
#waitFor bootNode.bootstrap() # immediate, since no bootnodes are defined above
|
2022-02-24 11:56:11 +00:00
|
|
|
|
2022-03-16 20:32:21 +00:00
|
|
|
var res = await bootstrapNodes(nodecount - 1,
|
2022-03-10 06:02:24 +00:00
|
|
|
@[bootnode.localNode.record],
|
|
|
|
rng)
|
|
|
|
res.insert((bootNode, bootNodeKey), 0)
|
|
|
|
return res
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-03-07 04:13:03 +00:00
|
|
|
# TODO: Remove this once we have removed all traces of nim-eth/keys
|
|
|
|
func pkToPk(pk: keys.PrivateKey) : Option[crypto.PrivateKey] =
|
|
|
|
let res = some(crypto.PrivateKey.init((secp.SkPrivateKey)(pk)))
|
|
|
|
return res
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
|
|
|
|
# suite "Providers Tests":
|
2022-02-15 13:00:39 +00:00
|
|
|
suite "Providers Tests: node alone":
|
2022-02-24 11:56:11 +00:00
|
|
|
var
|
|
|
|
rng: ref HmacDrbgContext
|
2022-03-10 06:02:24 +00:00
|
|
|
nodes: seq[(discv5_protocol.Protocol, keys.PrivateKey)]
|
2022-02-24 11:56:11 +00:00
|
|
|
targetId: NodeId
|
2022-03-10 06:02:24 +00:00
|
|
|
node0: discv5_protocol.Protocol
|
2022-03-07 04:13:03 +00:00
|
|
|
privKey_keys0: keys.PrivateKey
|
|
|
|
privKey0: crypto.PrivateKey
|
|
|
|
signedPeerRec0: SignedPeerRecord
|
|
|
|
peerRec0: PeerRecord
|
2022-02-24 11:56:11 +00:00
|
|
|
|
2022-02-25 01:27:43 +00:00
|
|
|
setupAll:
|
2022-02-24 11:56:11 +00:00
|
|
|
rng = keys.newRng()
|
2022-03-16 20:32:21 +00:00
|
|
|
nodes = await bootstrapNetwork(nodecount=1)
|
2022-02-24 11:56:11 +00:00
|
|
|
targetId = toNodeId(keys.PrivateKey.random(rng[]).toPublicKey)
|
2022-03-07 04:13:03 +00:00
|
|
|
(node0, privKey_keys0) = nodes[0]
|
|
|
|
privKey0 = privKey_keys0.pkToPk.get
|
|
|
|
signedPeerRec0 = privKey0.toSignedPeerRecord
|
|
|
|
peerRec0 = signedPeerRec0.data
|
2022-02-24 11:56:11 +00:00
|
|
|
|
2022-02-25 01:27:43 +00:00
|
|
|
teardownAll:
|
2022-03-07 04:13:03 +00:00
|
|
|
for (n, _) in nodes:
|
2022-03-10 06:02:24 +00:00
|
|
|
await n.closeWait()
|
2022-02-24 11:56:11 +00:00
|
|
|
await sleepAsync(chronos.seconds(3))
|
|
|
|
|
|
|
|
|
|
|
|
test "Node in isolation should store":
|
|
|
|
debug "---- ADDING PROVIDERS ---", nodes = nodes.len
|
2022-03-07 04:13:03 +00:00
|
|
|
let addedTo = await node0.addProvider(targetId, signedPeerRec0)
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "Provider added to: ", addedTo
|
|
|
|
|
|
|
|
debug "---- STARTING CHECKS ---"
|
|
|
|
check (addedTo.len == 1)
|
2022-03-10 06:02:24 +00:00
|
|
|
check (addedTo[0].id == node0.localNode.id)
|
2022-03-07 04:13:03 +00:00
|
|
|
check (node0.getProvidersLocal(targetId)[0].data.peerId == peerRec0.peerId)
|
2022-02-24 11:56:11 +00:00
|
|
|
|
|
|
|
test "Node in isolation should retrieve":
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- STARTING PROVIDERS LOOKUP ---"
|
2022-03-10 06:02:24 +00:00
|
|
|
let providersRes = await node0.getProviders(targetId)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- STARTING CHECKS ---"
|
2022-03-10 06:02:24 +00:00
|
|
|
check providersRes.isOk
|
|
|
|
let providers = providersRes.get
|
|
|
|
debug "Providers:", providers
|
2022-03-07 04:13:03 +00:00
|
|
|
check (providers.len > 0 and providers[0].data.peerId == peerRec0.peerId)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
test "Should not retrieve bogus":
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
let bogusId = toNodeId(keys.PrivateKey.random(rng[]).toPublicKey)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- STARTING PROVIDERS LOOKUP ---"
|
2022-03-10 06:02:24 +00:00
|
|
|
let providersRes = await node0.getProviders(bogusId)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- STARTING CHECKS ---"
|
2022-03-10 06:02:24 +00:00
|
|
|
check providersRes.isOk
|
|
|
|
let providers = providersRes.get
|
|
|
|
debug "Providers:", providers
|
2022-02-24 11:56:11 +00:00
|
|
|
check (providers.len == 0)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
suite "Providers Tests: two nodes":
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
var
|
|
|
|
rng: ref HmacDrbgContext
|
2022-03-10 06:02:24 +00:00
|
|
|
nodes: seq[(discv5_protocol.Protocol, keys.PrivateKey)]
|
2022-02-24 11:56:11 +00:00
|
|
|
targetId: NodeId
|
2022-03-10 06:02:24 +00:00
|
|
|
node0: discv5_protocol.Protocol
|
2022-03-07 04:13:03 +00:00
|
|
|
privKey_keys0: keys.PrivateKey
|
|
|
|
privKey0: crypto.PrivateKey
|
|
|
|
signedPeerRec0: SignedPeerRecord
|
|
|
|
peerRec0: PeerRecord
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-25 01:27:43 +00:00
|
|
|
setupAll:
|
2022-02-24 11:56:11 +00:00
|
|
|
rng = keys.newRng()
|
2022-03-16 20:32:21 +00:00
|
|
|
nodes = await bootstrapNetwork(nodecount=3)
|
2022-02-24 11:56:11 +00:00
|
|
|
targetId = toNodeId(keys.PrivateKey.random(rng[]).toPublicKey)
|
2022-03-07 04:13:03 +00:00
|
|
|
(node0, privKey_keys0) = nodes[0]
|
|
|
|
privKey0 = privKey_keys0.pkToPk.get
|
|
|
|
signedPeerRec0 = privKey0.toSignedPeerRecord
|
|
|
|
peerRec0 = signedPeerRec0.data
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-25 01:27:43 +00:00
|
|
|
teardownAll:
|
2022-03-07 04:13:03 +00:00
|
|
|
for (n, _) in nodes:
|
2022-03-10 06:02:24 +00:00
|
|
|
await n.closeWait()
|
2022-02-15 13:00:39 +00:00
|
|
|
await sleepAsync(chronos.seconds(3))
|
|
|
|
|
2022-03-07 04:13:03 +00:00
|
|
|
test "2 nodes, store and retrieve from same":
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- ADDING PROVIDERS ---"
|
2022-03-07 04:13:03 +00:00
|
|
|
let addedTo = await node0.addProvider(targetId, signedPeerRec0)
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "Provider added to: ", addedTo
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- STARTING PROVIDERS LOOKUP ---"
|
2022-03-10 06:02:24 +00:00
|
|
|
let providersRes = await node0.getProviders(targetId)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- STARTING CHECKS ---"
|
2022-03-10 06:02:24 +00:00
|
|
|
check providersRes.isOk
|
|
|
|
let providers = providersRes.get
|
|
|
|
debug "Providers:", providers
|
2022-03-07 04:13:03 +00:00
|
|
|
check (providers.len == 1 and providers[0].data.peerId == peerRec0.peerId)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-03-07 04:13:03 +00:00
|
|
|
test "2 nodes, retrieve from other":
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- STARTING PROVIDERS LOOKUP ---"
|
2022-03-07 04:13:03 +00:00
|
|
|
let (node1, _) = nodes[1]
|
2022-03-10 06:02:24 +00:00
|
|
|
let providersRes = await node1.getProviders(targetId)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- STARTING CHECKS ---"
|
2022-03-10 06:02:24 +00:00
|
|
|
let providers = providersRes.get
|
|
|
|
debug "Providers:", providers
|
2022-03-07 04:13:03 +00:00
|
|
|
check (providers.len == 1 and providers[0].data.peerId == peerRec0.peerId)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
suite "Providers Tests: 20 nodes":
|
|
|
|
|
|
|
|
var
|
|
|
|
rng: ref HmacDrbgContext
|
2022-03-10 06:02:24 +00:00
|
|
|
nodes: seq[(discv5_protocol.Protocol, keys.PrivateKey)]
|
2022-02-24 11:56:11 +00:00
|
|
|
targetId: NodeId
|
2022-03-10 06:02:24 +00:00
|
|
|
node0: discv5_protocol.Protocol
|
2022-03-07 04:13:03 +00:00
|
|
|
privKey_keys0: keys.PrivateKey
|
|
|
|
privKey0: crypto.PrivateKey
|
|
|
|
signedPeerRec0: SignedPeerRecord
|
|
|
|
peerRec0: PeerRecord
|
2022-02-24 11:56:11 +00:00
|
|
|
|
2022-02-25 01:27:43 +00:00
|
|
|
setupAll:
|
2022-02-24 11:56:11 +00:00
|
|
|
rng = keys.newRng()
|
2022-03-16 20:32:21 +00:00
|
|
|
nodes = await bootstrapNetwork(nodecount=20)
|
2022-02-24 11:56:11 +00:00
|
|
|
targetId = toNodeId(keys.PrivateKey.random(rng[]).toPublicKey)
|
2022-03-07 04:13:03 +00:00
|
|
|
(node0, privKey_keys0) = nodes[0]
|
|
|
|
privKey0 = privKey_keys0.pkToPk.get
|
|
|
|
signedPeerRec0 = privKey0.toSignedPeerRecord
|
|
|
|
peerRec0 = signedPeerRec0.data
|
2022-02-24 11:56:11 +00:00
|
|
|
|
2022-02-16 10:28:07 +00:00
|
|
|
await sleepAsync(chronos.seconds(15))
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-25 01:27:43 +00:00
|
|
|
teardownAll:
|
2022-03-07 04:13:03 +00:00
|
|
|
for (n, _) in nodes: # if last test is enabled, we need nodes[1..^1] here
|
2022-03-10 06:02:24 +00:00
|
|
|
await n.closeWait()
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-03-07 04:13:03 +00:00
|
|
|
test "20 nodes, store and retrieve from same":
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- ADDING PROVIDERS ---"
|
2022-03-07 04:13:03 +00:00
|
|
|
let addedTo = await node0.addProvider(targetId, signedPeerRec0)
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "Provider added to: ", addedTo
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- STARTING PROVIDERS LOOKUP ---"
|
2022-03-10 06:02:24 +00:00
|
|
|
let providersRes = await node0.getProviders(targetId)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- STARTING CHECKS ---"
|
2022-03-10 06:02:24 +00:00
|
|
|
let providers = providersRes.get
|
|
|
|
debug "Providers:", providers
|
2022-03-07 04:13:03 +00:00
|
|
|
check (providers.len == 1 and providers[0].data.peerId == peerRec0.peerId)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-03-07 04:13:03 +00:00
|
|
|
test "20 nodes, retrieve from other":
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- STARTING PROVIDERS LOOKUP ---"
|
2022-03-07 04:13:03 +00:00
|
|
|
let (node19, _) = nodes[^2]
|
2022-03-10 06:02:24 +00:00
|
|
|
let providersRes = await node19.getProviders(targetId)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-02-24 11:56:11 +00:00
|
|
|
debug "---- STARTING CHECKS ---"
|
2022-03-10 06:02:24 +00:00
|
|
|
let providers = providersRes.get
|
|
|
|
debug "Providers:", providers
|
2022-03-07 04:13:03 +00:00
|
|
|
check (providers.len == 1 and providers[0].data.peerId == peerRec0.peerId)
|
2022-02-15 13:00:39 +00:00
|
|
|
|
2022-03-06 23:28:56 +00:00
|
|
|
# test "20 nodes, retieve after bootnode dies":
|
|
|
|
# # TODO: currently this is not working even with a 2 minute timeout
|
|
|
|
# debug "---- KILLING BOOTSTRAP NODE ---"
|
2022-03-10 06:02:24 +00:00
|
|
|
# await nodes[0].closeWait()
|
2022-02-24 11:56:11 +00:00
|
|
|
|
2022-03-06 23:28:56 +00:00
|
|
|
# debug "---- STARTING PROVIDERS LOOKUP ---"
|
|
|
|
# let providers = await nodes[^2].getProviders(targetId)
|
|
|
|
# debug "Providers:", providers
|
2022-02-24 11:56:11 +00:00
|
|
|
|
2022-03-06 23:28:56 +00:00
|
|
|
# debug "---- STARTING CHECKS ---"
|
|
|
|
# check (providers.len == 1 and providers[0].peerId == nodes[0].toPeerRecord.peerId)
|