mirror of https://github.com/status-im/nim-eth.git
Add resolve proc + test
This commit is contained in:
parent
d3c9ccea67
commit
59ba3704d6
|
@ -61,7 +61,7 @@ proc addNode*(d: Protocol, enr: EnrUri) =
|
|||
doAssert(res)
|
||||
d.addNode newNode(r)
|
||||
|
||||
proc getNode*(d: Protocol, id: NodeId): Node =
|
||||
proc getNode*(d: Protocol, id: NodeId): Option[Node] =
|
||||
d.routingTable.getNode(id)
|
||||
|
||||
proc randomNodes*(d: Protocol, count: int): seq[Node] =
|
||||
|
@ -213,9 +213,7 @@ proc receive*(d: Protocol, a: Address, msg: openArray[byte]) {.gcsafe,
|
|||
var packet: Packet
|
||||
let decoded = d.codec.decodeEncrypted(sender, a, msg, authTag, node, packet)
|
||||
if decoded == DecodeStatus.Success:
|
||||
if node.isNil:
|
||||
node = d.routingTable.getNode(sender)
|
||||
else:
|
||||
if not node.isNil:
|
||||
# Not filling table with nodes without correct IP in the ENR
|
||||
if a.ip == node.address.ip:
|
||||
debug "Adding new node to routing table", node = $node,
|
||||
|
@ -232,7 +230,7 @@ proc receive*(d: Protocol, a: Address, msg: openArray[byte]) {.gcsafe,
|
|||
if d.awaitedPackets.take((sender, packet.reqId), waiter):
|
||||
waiter.complete(packet.some)
|
||||
else:
|
||||
debug "TODO: handle packet: ", packet = packet.kind, origin = $node
|
||||
debug "TODO: handle packet: ", packet = packet.kind, origin = a
|
||||
elif decoded == DecodeStatus.DecryptError:
|
||||
debug "Could not decrypt packet, respond with whoareyou",
|
||||
localNode = $d.localNode, address = a
|
||||
|
@ -418,6 +416,31 @@ proc lookupRandom*(d: Protocol): Future[seq[Node]]
|
|||
raise newException(RandomSourceDepleted, "Could not randomize bytes")
|
||||
d.lookup(id)
|
||||
|
||||
proc resolve*(d: Protocol, id: NodeId): Future[Option[Node]] {.async.} =
|
||||
## Resolve a `Node` based on provided `NodeId`.
|
||||
##
|
||||
## This will first look in the own DHT. If the node is known, it will try to
|
||||
## contact if for newer information. If node is not known or it does not
|
||||
## reply, a lookup is done to see if it can find a (newer) record of the node
|
||||
## on the network.
|
||||
|
||||
let node = d.getNode(id)
|
||||
if node.isSome():
|
||||
let request = await d.findNode(node.get(), 0)
|
||||
|
||||
if request.len > 0:
|
||||
return some(request[0])
|
||||
|
||||
let discovered = await d.lookup(id)
|
||||
for n in discovered:
|
||||
if n.id == id:
|
||||
# TODO: Not getting any new seqNum here as in a lookup nodes in table with
|
||||
# new seqNum don't get replaced.
|
||||
if node.isSome() and node.get().record.seqNum >= n.record.seqNum:
|
||||
return node
|
||||
else:
|
||||
return some(n)
|
||||
|
||||
proc revalidateNode*(d: Protocol, n: Node)
|
||||
{.async, raises:[Defect, Exception].} = # TODO: Exception
|
||||
trace "Ping to revalidate node", node = $n
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import
|
||||
std/[algorithm, times, sequtils, bitops, random, sets], stint, chronicles,
|
||||
std/[algorithm, times, sequtils, bitops, random, sets, options],
|
||||
stint, chronicles,
|
||||
types, node
|
||||
|
||||
type
|
||||
|
@ -174,11 +175,11 @@ proc addNode*(r: var RoutingTable, n: Node): Node =
|
|||
# Nothing added, ping evictionCandidate
|
||||
return evictionCandidate
|
||||
|
||||
proc getNode*(r: RoutingTable, id: NodeId): Node =
|
||||
proc getNode*(r: RoutingTable, id: NodeId): Option[Node] =
|
||||
let b = r.bucketForNode(id)
|
||||
for n in b.nodes:
|
||||
if n.id == id:
|
||||
return n
|
||||
return some(n)
|
||||
|
||||
proc contains*(r: RoutingTable, n: Node): bool = n in r.bucketForNode(n.id)
|
||||
|
||||
|
|
|
@ -60,7 +60,9 @@ suite "Discovery v5 Tests":
|
|||
for i in 0..<1000:
|
||||
node.addNode(generateNode())
|
||||
|
||||
check node.getNode(targetNode.id) == targetNode
|
||||
let n = node.getNode(targetNode.id)
|
||||
require n.isSome()
|
||||
check n.get() == targetNode
|
||||
|
||||
await node.closeWait()
|
||||
|
||||
|
@ -82,8 +84,10 @@ suite "Discovery v5 Tests":
|
|||
await node1.revalidateNode(bootnode.localNode)
|
||||
await node1.revalidateNode(node2.localNode)
|
||||
|
||||
check node1.getNode(bootnode.localNode.id) == bootnode.localNode
|
||||
check node1.getNode(node2.localNode.id) == nil
|
||||
let n = node1.getNode(bootnode.localNode.id)
|
||||
require n.isSome()
|
||||
check n.get() == bootnode.localNode
|
||||
check node1.getNode(node2.localNode.id).isNone()
|
||||
|
||||
await node1.closeWait()
|
||||
|
||||
|
@ -310,3 +314,66 @@ suite "Discovery v5 Tests":
|
|||
|
||||
for node in nodes:
|
||||
await node.closeWait()
|
||||
|
||||
asyncTest "Resolve target":
|
||||
let
|
||||
mainNode = initDiscoveryNode(PrivateKey.random()[], localAddress(20301))
|
||||
lookupNode = initDiscoveryNode(PrivateKey.random()[], localAddress(20302))
|
||||
targetKey = PrivateKey.random()[]
|
||||
targetAddress = localAddress(20303)
|
||||
targetNode = initDiscoveryNode(targetKey, targetAddress)
|
||||
targetId = targetNode.localNode.id
|
||||
|
||||
var targetSeqNum = targetNode.localNode.record.seqNum
|
||||
|
||||
# Populate DHT with target through a ping. Next, close target and see
|
||||
# if resolve works (only local lookup)
|
||||
block:
|
||||
let pong = await targetNode.ping(mainNode.localNode)
|
||||
require pong.isSome()
|
||||
await targetNode.closeWait()
|
||||
let n = await mainNode.resolve(targetId)
|
||||
require n.isSome()
|
||||
check:
|
||||
n.get().id == targetId
|
||||
n.get().record.seqNum == targetSeqNum
|
||||
|
||||
# Bring target back online, update seqNum in ENR, check if we get the
|
||||
# updated ENR.
|
||||
block:
|
||||
# TODO: need to add some logic to update ENRs properly
|
||||
targetSeqNum.inc()
|
||||
let r = enr.Record.init(targetSeqNum, targetKey,
|
||||
some(targetAddress.ip), targetAddress.tcpPort, targetAddress.udpPort)
|
||||
targetNode.localNode.record = r
|
||||
targetNode.open()
|
||||
let n = await mainNode.resolve(targetId)
|
||||
require n.isSome()
|
||||
check:
|
||||
n.get().id == targetId
|
||||
n.get().record.seqNum == targetSeqNum
|
||||
|
||||
# Update seqNum in ENR again, ping lookupNode to be added in DHT,
|
||||
# close targetNode, resolve should lookup, check if we get updated ENR.
|
||||
block:
|
||||
targetSeqNum.inc()
|
||||
let r = enr.Record.init(3, targetKey, some(targetAddress.ip),
|
||||
targetAddress.tcpPort, targetAddress.udpPort)
|
||||
targetNode.localNode.record = r
|
||||
let pong = await targetNode.ping(lookupNode.localNode)
|
||||
require pong.isSome()
|
||||
|
||||
await targetNode.closeWait()
|
||||
# TODO: This step should eventually not be needed and ENRs with new seqNum
|
||||
# should just get updated in the lookup.
|
||||
await mainNode.revalidateNode(targetNode.localNode)
|
||||
|
||||
mainNode.addNode(lookupNode.localNode.record)
|
||||
let n = await mainNode.resolve(targetId)
|
||||
require n.isSome()
|
||||
check:
|
||||
n.get().id == targetId
|
||||
n.get().record.seqNum == targetSeqNum
|
||||
|
||||
await mainNode.closeWait()
|
||||
await lookupNode.closeWait()
|
||||
|
|
Loading…
Reference in New Issue