Use chronicles in discovery

This commit is contained in:
Yuriy Glukhov 2018-07-06 13:15:22 +03:00
parent 66ff278f33
commit b4d343805a
3 changed files with 26 additions and 21 deletions

View File

@ -15,6 +15,7 @@ requires "nim > 0.18.0",
"ranges", "ranges",
"stint", "stint",
"byteutils", "byteutils",
"chronicles",
"https://github.com/status-im/nim-asyncdispatch2" "https://github.com/status-im/nim-asyncdispatch2"
proc runTest(name: string, lang = "c") = exec "nim " & lang & " -r tests/" & name proc runTest(name: string, lang = "c") = exec "nim " & lang & " -r tests/" & name

View File

@ -9,7 +9,7 @@
# #
from strutils import nil from strutils import nil
import times, algorithm, logging import times, algorithm, chronicles
import asyncdispatch2, eth_keys, ranges, stint, nimcrypto, rlp import asyncdispatch2, eth_keys, ranges, stint, nimcrypto, rlp
import kademlia, enode import kademlia, enode
@ -133,7 +133,7 @@ proc sendNeighbours*(d: DiscoveryProtocol, node: Node, neighbours: seq[Node]) =
block: block:
let payload = rlp.encode((nodes, expiration())) let payload = rlp.encode((nodes, expiration()))
let msg = pack(cmdNeighbours, payload, d.privkey) let msg = pack(cmdNeighbours, payload, d.privkey)
debug ">>> neighbours to ", node, ": ", nodes debug ">>> neighbours", to = node, neightbours = nodes
d.send(node, msg) d.send(node, msg)
nodes.setLen(0) nodes.setLen(0)
@ -231,11 +231,11 @@ proc receive(d: DiscoveryProtocol, a: Address, msg: Bytes) =
else: else:
echo "Unknown command: ", cmdId echo "Unknown command: ", cmdId
else: else:
debug "Received msg ", cmdId, " from ", a, " already expired" debug "Received msg is expired", cmdId, "from" = a
else: else:
error "Wrong public key from ", a error "Wrong public key ", "from" = a
else: else:
error "Wrong msg mac from ", a error "Wrong msg mac", "from" = a
proc processClient(transp: DatagramTransport, proc processClient(transp: DatagramTransport,
raddr: TransportAddress): Future[void] {.async, gcsafe.} = raddr: TransportAddress): Future[void] {.async, gcsafe.} =
@ -249,7 +249,7 @@ proc processClient(transp: DatagramTransport,
let a = Address(ip: raddr.address, udpPort: raddr.port, tcpPort: raddr.port) let a = Address(ip: raddr.address, udpPort: raddr.port, tcpPort: raddr.port)
proto.receive(a, buf) proto.receive(a, buf)
except: except:
error "receive failed: ", getCurrentExceptionMsg() error "receive failed: " & getCurrentExceptionMsg()
proc open*(d: DiscoveryProtocol) = proc open*(d: DiscoveryProtocol) =
let ta = initTAddress(d.address.ip, d.address.udpPort) let ta = initTAddress(d.address.ip, d.address.udpPort)

View File

@ -8,12 +8,15 @@
# MIT license (LICENSE-MIT) # MIT license (LICENSE-MIT)
# #
import uri, logging, tables, hashes, times, algorithm, sets, sequtils, random import uri, tables, hashes, times, algorithm, sets, sequtils, random
from strutils import parseInt from strutils import parseInt
import asyncdispatch2, eth_keys, stint, nimcrypto, enode import asyncdispatch2, eth_keys, stint, nimcrypto, chronicles, enode
export sets # TODO: This should not be needed, but compilation fails otherwise export sets # TODO: This should not be needed, but compilation fails otherwise
logScope:
topic = "discovery"
type type
KademliaProtocol* [Wire] = ref object KademliaProtocol* [Wire] = ref object
wire: Wire wire: Wire
@ -331,6 +334,7 @@ proc bond(k: KademliaProtocol, n: Node): Future[bool] {.async.} =
# the remote remembers us. # the remote remembers us.
discard await k.waitPing(n) discard await k.waitPing(n)
echo "bonding completed successfully with"
debug "bonding completed successfully with ", n debug "bonding completed successfully with ", n
k.updateRoutingTable(n) k.updateRoutingTable(n)
return true return true
@ -352,7 +356,7 @@ proc lookup*(k: KademliaProtocol, nodeId: NodeId): Future[seq[Node]] {.async.} =
k.wire.sendFindNode(remote, nodeId) k.wire.sendFindNode(remote, nodeId)
var candidates = await k.waitNeighbours(remote) var candidates = await k.waitNeighbours(remote)
if candidates.len == 0: if candidates.len == 0:
debug "got no candidates from ", remote, ", returning" debug "got no candidates, returning ", "from" = remote
result = candidates result = candidates
else: else:
# The following line: # The following line:
@ -361,12 +365,12 @@ proc lookup*(k: KademliaProtocol, nodeId: NodeId): Future[seq[Node]] {.async.} =
# 2. Removes all previously seen nodes from candidates # 2. Removes all previously seen nodes from candidates
# 3. Deduplicates candidates # 3. Deduplicates candidates
candidates.keepItIf(not nodesSeen.containsOrIncl(it)) candidates.keepItIf(not nodesSeen.containsOrIncl(it))
debug "got ", candidates.len, " new candidates" debug "got new candidates", count = candidates.len
let bonded = await all(candidates.mapIt(k.bond(it))) let bonded = await all(candidates.mapIt(k.bond(it)))
for i in 0 ..< bonded.len: for i in 0 ..< bonded.len:
if not bonded[i]: candidates[i] = nil if not bonded[i]: candidates[i] = nil
candidates.keepItIf(not it.isNil) candidates.keepItIf(not it.isNil)
debug "bonded with ", candidates.len, " candidates" debug "bonded with candidates", count = candidates.len
result = candidates result = candidates
proc excludeIfAsked(nodes: seq[Node]): seq[Node] = proc excludeIfAsked(nodes: seq[Node]): seq[Node] =
@ -385,7 +389,7 @@ proc lookup*(k: KademliaProtocol, nodeId: NodeId): Future[seq[Node]] {.async.} =
sortByDistance(closest, nodeId, BUCKET_SIZE) sortByDistance(closest, nodeId, BUCKET_SIZE)
nodesToAsk = excludeIfAsked(closest) nodesToAsk = excludeIfAsked(closest)
info "lookup finished for ", nodeId.toHex, ": ", closest info "lookup finished", forNode = nodeId.toHex, closest
result = closest result = closest
proc lookupRandom*(k: KademliaProtocol): Future[seq[Node]] = proc lookupRandom*(k: KademliaProtocol): Future[seq[Node]] =
@ -401,19 +405,19 @@ proc resolve*(k: KademliaProtocol, id: NodeId): Future[Node] {.async.} =
proc bootstrap*(k: KademliaProtocol, bootstrapNodes: seq[Node]) {.async.} = proc bootstrap*(k: KademliaProtocol, bootstrapNodes: seq[Node]) {.async.} =
let bonded = await all(bootstrapNodes.mapIt(k.bond(it))) let bonded = await all(bootstrapNodes.mapIt(k.bond(it)))
if true notin bonded: if true notin bonded:
info "Failed to bond with bootstrap nodes " info "Failed to bond with bootstrap nodes"
return return
discard await k.lookupRandom() discard await k.lookupRandom()
proc recvPong*(k: KademliaProtocol, n: Node, token: seq[byte]) = proc recvPong*(k: KademliaProtocol, n: Node, token: seq[byte]) =
debug "<<< pong from ", n debug "<<< pong", "from" = n
let pingid = token & @(n.node.pubkey.data) let pingid = token & @(n.node.pubkey.data)
var future: Future[bool] var future: Future[bool]
if k.pongFutures.take(pingid, future): if k.pongFutures.take(pingid, future):
future.complete(true) future.complete(true)
proc recvPing*(k: KademliaProtocol, n: Node, msgHash: any) = proc recvPing*(k: KademliaProtocol, n: Node, msgHash: any) =
debug "<<< ping from ", n debug "<<< ping", "from" = n
k.updateRoutingTable(n) k.updateRoutingTable(n)
k.wire.sendPong(n, msgHash) k.wire.sendPong(n, msgHash)
@ -428,12 +432,12 @@ proc recvNeighbours*(k: KademliaProtocol, remote: Node, neighbours: seq[Node]) =
## done as part of node lookup, so the actual processing is left to the callback from ## done as part of node lookup, so the actual processing is left to the callback from
## neighbours_callbacks, which is added (and removed after it's done or timed out) in ## neighbours_callbacks, which is added (and removed after it's done or timed out) in
## wait_neighbours(). ## wait_neighbours().
debug "<<< neighbours from ", remote, ": ", neighbours debug "<<< neighbours", "from" = remote, neighbours
let cb = k.neighboursCallbacks.getOrDefault(remote) let cb = k.neighboursCallbacks.getOrDefault(remote)
if not cb.isNil: if not cb.isNil:
cb(neighbours) cb(neighbours)
else: else:
debug "unexpected neighbours from ", remote, ", probably came too late" debug "unexpected neighbours, probably came too late", "from" = remote
proc recvFindNode*(k: KademliaProtocol, remote: Node, nodeId: NodeId) = proc recvFindNode*(k: KademliaProtocol, remote: Node, nodeId: NodeId) =
if remote notin k.routing: if remote notin k.routing:
@ -449,10 +453,10 @@ proc recvFindNode*(k: KademliaProtocol, remote: Node, nodeId: NodeId) =
proc randomNodes*(k: KademliaProtocol, count: int): seq[Node] = proc randomNodes*(k: KademliaProtocol, count: int): seq[Node] =
var count = count var count = count
let sz = k.routing.len let availableNodes = k.routing.len
if count > sz: if count > availableNodes:
warn "Cannot get ", count, " nodes as RoutingTable contains only ", sz, " nodes" warn "Cannot get enough nodes", requestedNodes = count, availableNodes
count = sz count = availableNodes
result = newSeqOfCap[Node](count) result = newSeqOfCap[Node](count)
var seen = initSet[Node]() var seen = initSet[Node]()