mirror of https://github.com/status-im/nim-eth.git
discv5: Pass bootstrap nodes and add deletion of nodes
This commit is contained in:
parent
2b7a25175b
commit
267a06dbe6
|
@ -241,6 +241,9 @@ proc decodeAuthResp(c: Codec, fromId: NodeId, head: AuthHeader,
|
|||
# 2. Should verify ENR and check for correct id in case an ENR is included
|
||||
# 3. Should verify id nonce signature
|
||||
|
||||
# More TODO:
|
||||
# This will also not work if ENR does not contain an IP address or if the
|
||||
# IP address is out of date and doesn't match current UDP end point
|
||||
newNode = newNode(authResp.record)
|
||||
return true
|
||||
|
||||
|
|
|
@ -44,6 +44,10 @@ proc newNode*(r: Record): Node =
|
|||
result = newNode(initENode(pk, a))
|
||||
result.record = r
|
||||
|
||||
proc newNodes*(records: openarray[Record]): seq[Node] =
|
||||
for record in records:
|
||||
result.add(newNode(record))
|
||||
|
||||
proc hash*(n: Node): hashes.Hash = hash(n.node.pubkey.data)
|
||||
proc `==`*(a, b: Node): bool = (a.isNil and b.isNil) or (not a.isNil and not b.isNil and a.node.pubkey == b.node.pubkey)
|
||||
|
||||
|
|
|
@ -38,11 +38,32 @@ type
|
|||
awaitedPackets: Table[(Node, RequestId), Future[Option[Packet]]]
|
||||
lookupLoop: Future[void]
|
||||
revalidateLoop: Future[void]
|
||||
bootstrapNodes: seq[Node]
|
||||
|
||||
PendingRequest = object
|
||||
node: Node
|
||||
packet: seq[byte]
|
||||
|
||||
proc addNode*(d: Protocol, node: Node) =
|
||||
discard d.routingTable.addNode(node)
|
||||
|
||||
template addNode*(d: Protocol, enode: ENode) =
|
||||
addNode d, newNode(enode)
|
||||
|
||||
template addNode*(d: Protocol, r: Record) =
|
||||
addNode d, newNode(r)
|
||||
|
||||
proc addNode*(d: Protocol, enr: EnrUri) =
|
||||
var r: Record
|
||||
let res = r.fromUri(enr)
|
||||
doAssert(res)
|
||||
d.addNode newNode(r)
|
||||
|
||||
proc randomNodes*(k: Protocol, count: int): seq[Node] =
|
||||
k.routingTable.randomNodes(count)
|
||||
|
||||
proc nodesDiscovered*(k: Protocol): int {.inline.} = k.routingTable.len
|
||||
|
||||
proc whoareyouMagic(toNode: NodeId): array[magicSize, byte] =
|
||||
const prefix = "WHOAREYOU"
|
||||
var data: array[prefix.len + sizeof(toNode), byte]
|
||||
|
@ -51,7 +72,8 @@ proc whoareyouMagic(toNode: NodeId): array[magicSize, byte] =
|
|||
sha256.digest(data).data
|
||||
|
||||
proc newProtocol*(privKey: PrivateKey, db: Database,
|
||||
ip: IpAddress, tcpPort, udpPort: Port): Protocol =
|
||||
ip: IpAddress, tcpPort, udpPort: Port,
|
||||
bootstrapRecords: openarray[Record] = []): Protocol =
|
||||
let
|
||||
a = Address(ip: ip, tcpPort: tcpPort, udpPort: udpPort)
|
||||
enode = initENode(privKey.getPublicKey(), a)
|
||||
|
@ -64,7 +86,8 @@ proc newProtocol*(privKey: PrivateKey, db: Database,
|
|||
localNode: node,
|
||||
whoareyouMagic: whoareyouMagic(node.id),
|
||||
idHash: sha256.digest(node.id.toByteArrayBE).data,
|
||||
codec: Codec(localNode: node, privKey: privKey, db: db))
|
||||
codec: Codec(localNode: node, privKey: privKey, db: db),
|
||||
bootstrapNodes: newNodes(bootstrapRecords))
|
||||
|
||||
result.routingTable.init(node)
|
||||
|
||||
|
@ -355,6 +378,7 @@ proc ping(p: Protocol, toNode: Node): RequestId =
|
|||
|
||||
proc revalidateNode(p: Protocol, n: Node)
|
||||
{.async, raises:[Defect, Exception].} = # TODO: Exception
|
||||
trace "Ping to revalidate node", node = $n
|
||||
let reqId = p.ping(n)
|
||||
|
||||
let resp = await p.waitPacket(n, reqId)
|
||||
|
@ -367,8 +391,15 @@ proc revalidateNode(p: Protocol, n: Node)
|
|||
p.routingTable.setJustSeen(n)
|
||||
trace "Revalidated node", node = $n
|
||||
else:
|
||||
if false: # TODO: if not bootnode:
|
||||
# For now we never remove bootstrap nodes. It might make sense to actually
|
||||
# do so and to retry them only in case we drop to a really low amount of
|
||||
# peers in the DHT
|
||||
if n notin p.bootstrapNodes:
|
||||
trace "Revalidation of node failed, removing node", node = $n
|
||||
p.routingTable.removeNode(n)
|
||||
# TODO: Do we delete the shared secrets here?
|
||||
# And if so, the current way they are stored, we might not have the key
|
||||
# (specifically if the ENR does not have the correct address)
|
||||
|
||||
proc revalidateLoop(p: Protocol) {.async.} =
|
||||
try:
|
||||
|
@ -389,8 +420,12 @@ proc lookupLoop(d: Protocol) {.async.} =
|
|||
## TODO: Same story as for `revalidateLoop`
|
||||
try:
|
||||
while true:
|
||||
let nodes = await d.lookupRandom()
|
||||
trace "Discovered nodes", nodes = $nodes
|
||||
# lookup self (neighbour nodes)
|
||||
var nodes = await d.lookup(d.localNode.id)
|
||||
trace "Discovered nodes in self lookup", nodes = $nodes
|
||||
|
||||
nodes = await d.lookupRandom()
|
||||
trace "Discovered nodes in random lookup", nodes = $nodes
|
||||
await sleepAsync(lookupInterval)
|
||||
except CancelledError:
|
||||
trace "lookupLoop canceled"
|
||||
|
@ -401,6 +436,10 @@ proc open*(d: Protocol) =
|
|||
# TODO allow binding to specific IP / IPv6 / etc
|
||||
let ta = initTAddress(IPv4_any(), d.localNode.node.address.udpPort)
|
||||
d.transp = newDatagramTransport(processClient, udata = d, local = ta)
|
||||
|
||||
for node in d.bootstrapNodes:
|
||||
d.addNode(node)
|
||||
|
||||
# Might want to move these to a separate proc if this turns out to be needed.
|
||||
d.lookupLoop = lookupLoop(d)
|
||||
d.revalidateLoop = revalidateLoop(d)
|
||||
|
@ -425,26 +464,6 @@ proc closeWait*(d: Protocol) {.async.} =
|
|||
d.lookupLoop.cancelAndWait()])
|
||||
await d.transp.closeWait()
|
||||
|
||||
proc addNode*(d: Protocol, node: Node) =
|
||||
discard d.routingTable.addNode(node)
|
||||
|
||||
template addNode*(d: Protocol, enode: ENode) =
|
||||
addNode d, newNode(enode)
|
||||
|
||||
template addNode*(d: Protocol, r: Record) =
|
||||
addNode d, newNode(r)
|
||||
|
||||
proc addNode*(d: Protocol, enr: EnrUri) =
|
||||
var r: Record
|
||||
let res = r.fromUri(enr)
|
||||
doAssert(res)
|
||||
d.addNode newNode(r)
|
||||
|
||||
proc randomNodes*(k: Protocol, count: int): seq[Node] =
|
||||
k.routingTable.randomNodes(count)
|
||||
|
||||
proc nodesDiscovered*(k: Protocol): int {.inline.} = k.routingTable.len
|
||||
|
||||
when isMainModule:
|
||||
import discovery_db
|
||||
import eth/trie/db
|
||||
|
|
|
@ -6,14 +6,13 @@ import
|
|||
./p2p_test_helper
|
||||
|
||||
proc initDiscoveryNode*(privKey: PrivateKey, address: Address,
|
||||
bootnodes: seq[Record]): discv5_protocol.Protocol =
|
||||
bootstrapRecords: seq[Record]):
|
||||
discv5_protocol.Protocol =
|
||||
var db = DiscoveryDB.init(newMemoryDB())
|
||||
result = newProtocol(privKey, db,
|
||||
parseIpAddress("127.0.0.1"),
|
||||
address.tcpPort, address.udpPort)
|
||||
|
||||
for node in bootnodes:
|
||||
result.addNode(node)
|
||||
address.tcpPort, address.udpPort,
|
||||
bootstrapRecords)
|
||||
|
||||
result.open()
|
||||
|
||||
|
|
Loading…
Reference in New Issue