For now use directly address/id instead of Node to workaround node isNil problem in edge cases

This commit is contained in:
kdeme 2020-03-18 16:24:23 +01:00 committed by zah
parent 55b8e3e23f
commit a9ff761d68
3 changed files with 42 additions and 31 deletions

View File

@ -88,7 +88,7 @@ proc encryptGCM*(key, nonce, pt, authData: openarray[byte]): seq[byte] =
ectx.getTag(result.toOpenArray(pt.len, result.high))
ectx.clear()
proc makeAuthHeader(c: Codec, toNode: Node, nonce: array[gcmNonceSize, byte],
proc makeAuthHeader(c: Codec, toId: NodeID, nonce: array[gcmNonceSize, byte],
handshakeSecrets: var HandshakeSecrets,
challenge: Whoareyou): seq[byte] =
var resp = AuthResponse(version: 5)
@ -102,7 +102,7 @@ proc makeAuthHeader(c: Codec, toNode: Node, nonce: array[gcmNonceSize, byte],
resp.signature = c.signIDNonce(challenge.idNonce, ephPubkey).getRaw
deriveKeys(ln.id, toNode.id, ephKey, toNode.node.pubKey, challenge.idNonce,
deriveKeys(ln.id, toId, ephKey, challenge.pubKey, challenge.idNonce,
handshakeSecrets)
let respRlp = rlp.encode(resp)
@ -125,7 +125,8 @@ proc packetTag(destNode, srcNode: NodeID): PacketTag =
result = srcId xor destidHash.data
proc encodeEncrypted*(c: Codec,
toNode: Node,
toId: NodeID,
toAddr: Address,
packetData: seq[byte],
challenge: Whoareyou):
(seq[byte], array[gcmNonceSize, byte]) =
@ -141,17 +142,17 @@ proc encodeEncrypted*(c: Codec,
# We might not have the node's keys if the handshake hasn't been performed
# yet. That's fine, we will be responded with whoareyou.
discard c.db.loadKeys(toNode.id, toNode.address, readKey, writeKey)
discard c.db.loadKeys(toId, toAddr, readKey, writeKey)
else:
var sec: HandshakeSecrets
headEnc = c.makeAuthHeader(toNode, nonce, sec, challenge)
headEnc = c.makeAuthHeader(toId, nonce, sec, challenge)
writeKey = sec.writeKey
# TODO: is it safe to ignore the error here?
discard c.db.storeKeys(toNode.id, toNode.address, sec.readKey, sec.writeKey)
discard c.db.storeKeys(toId, toAddr, sec.readKey, sec.writeKey)
var body = packetData
let tag = packetTag(toNode.id, c.localNode.id)
let tag = packetTag(toId, c.localNode.id)
var headBuf = newSeqOfCap[byte](tag.len + headEnc.len)
headBuf.add(tag)

View File

@ -35,7 +35,7 @@ type
db: Database
routingTable: RoutingTable
codec*: Codec
awaitedPackets: Table[(Node, RequestId), Future[Option[Packet]]]
awaitedPackets: Table[(NodeId, RequestId), Future[Option[Packet]]]
lookupLoop: Future[void]
revalidateLoop: Future[void]
bootstrapNodes: seq[Node]
@ -141,10 +141,13 @@ proc sendWhoareyou(d: Protocol, address: Address, toNode: NodeId, authTag: AuthT
data.add(rlp.encode(challenge[]))
d.send(address, data)
proc sendNodes(d: Protocol, toNode: Node, reqId: RequestId, nodes: openarray[Node]) =
proc sendNodes(d: Protocol, toNode: Node, packet: NodesPacket, reqId: RequestId) {.nimcall.} =
let (data, _) = d.codec.encodeEncrypted(toNode, encodePacket(packet, reqId), challenge = nil)
d.send(toNode, data)
proc sendNodes(d: Protocol, toId: NodeId, toAddr: Address, reqId: RequestId,
nodes: openarray[Node]) =
proc sendNodes(d: Protocol, toId: NodeId, toAddr: Address,
packet: NodesPacket, reqId: RequestId) {.nimcall.} =
let (data, _) = d.codec.encodeEncrypted(toId, toAddr,
encodePacket(packet, reqId), challenge = nil)
d.send(toAddr, data)
var packet: NodesPacket
packet.total = ceil(nodes.len / maxNodesPerPacket).uint32
@ -152,14 +155,15 @@ proc sendNodes(d: Protocol, toNode: Node, reqId: RequestId, nodes: openarray[Nod
for i in 0 ..< nodes.len:
packet.enrs.add(nodes[i].record)
if packet.enrs.len == 3:
d.sendNodes(toNode, packet, reqId)
d.sendNodes(toId, toAddr, packet, reqId)
packet.enrs.setLen(0)
if packet.enrs.len != 0:
d.sendNodes(toNode, packet, reqId)
d.sendNodes(toId, toAddr, packet, reqId)
proc handlePing(d: Protocol, fromNode: Node, ping: PingPacket, reqId: RequestId) =
let a = fromNode.address
proc handlePing(d: Protocol, fromId: NodeId, fromAddr: Address,
ping: PingPacket, reqId: RequestId) =
let a = fromAddr
var pong: PongPacket
pong.enrSeq = ping.enrSeq
pong.ip = case a.ip.family
@ -167,15 +171,18 @@ proc handlePing(d: Protocol, fromNode: Node, ping: PingPacket, reqId: RequestId)
of IpAddressFamily.IPv6: @(a.ip.address_v6)
pong.port = a.udpPort.uint16
let (data, _) = d.codec.encodeEncrypted(fromNode, encodePacket(pong, reqId), challenge = nil)
d.send(fromNode, data)
let (data, _) = d.codec.encodeEncrypted(fromId, fromAddr,
encodePacket(pong, reqId), challenge = nil)
d.send(fromAddr, data)
proc handleFindNode(d: Protocol, fromNode: Node, fn: FindNodePacket, reqId: RequestId) =
proc handleFindNode(d: Protocol, fromId: NodeId, fromAddr: Address,
fn: FindNodePacket, reqId: RequestId) =
if fn.distance == 0:
d.sendNodes(fromNode, reqId, [d.localNode])
d.sendNodes(fromId, fromAddr, reqId, [d.localNode])
else:
let distance = min(fn.distance, 256)
d.sendNodes(fromNode, reqId, d.routingTable.neighboursAtDistance(distance))
d.sendNodes(fromId, fromAddr, reqId,
d.routingTable.neighboursAtDistance(distance))
proc receive*(d: Protocol, a: Address, msg: Bytes) {.gcsafe,
raises: [
@ -200,8 +207,10 @@ proc receive*(d: Protocol, a: Address, msg: Bytes) {.gcsafe,
var pr: PendingRequest
if d.pendingRequests.take(whoareyou.authTag, pr):
let toNode = pr.node
whoareyou.pubKey = toNode.node.pubkey # TODO: Yeah, rather ugly this.
try:
let (data, _) = d.codec.encodeEncrypted(toNode, pr.packet, challenge = whoareyou)
let (data, _) = d.codec.encodeEncrypted(toNode.id, toNode.address,
pr.packet, challenge = whoareyou)
d.send(toNode, data)
except RandomSourceDepleted as err:
debug "Failed to respond to a who-you-are msg " &
@ -224,16 +233,14 @@ proc receive*(d: Protocol, a: Address, msg: Bytes) {.gcsafe,
debug "Adding new node to routing table", node = $node, localNode = $d.localNode
discard d.routingTable.addNode(node)
doAssert(not node.isNil, "No node in the routing table (internal error?)")
case packet.kind
of ping:
d.handlePing(node, packet.ping, packet.reqId)
d.handlePing(sender, a, packet.ping, packet.reqId)
of findNode:
d.handleFindNode(node, packet.findNode, packet.reqId)
d.handleFindNode(sender, a, packet.findNode, packet.reqId)
else:
var waiter: Future[Option[Packet]]
if d.awaitedPackets.take((node, packet.reqId), waiter):
if d.awaitedPackets.take((sender, packet.reqId), waiter):
waiter.complete(packet.some)
else:
debug "TODO: handle packet: ", packet = packet.kind, origin = $node
@ -252,7 +259,7 @@ proc receive*(d: Protocol, a: Address, msg: Bytes) {.gcsafe,
proc waitPacket(d: Protocol, fromNode: Node, reqId: RequestId): Future[Option[Packet]] =
result = newFuture[Option[Packet]]("waitPacket")
let res = result
let key = (fromNode, reqId)
let key = (fromNode.id, reqId)
sleepAsync(responseTimeout).addCallback() do(data: pointer):
d.awaitedPackets.del(key)
if not res.finished:
@ -277,7 +284,8 @@ proc waitNodes(d: Protocol, fromNode: Node, reqId: RequestId): Future[seq[Node]]
proc findNode(d: Protocol, toNode: Node, distance: uint32): Future[seq[Node]] {.async.} =
let reqId = newRequestId()
let packet = encodePacket(FindNodePacket(distance: distance), reqId)
let (data, nonce) = d.codec.encodeEncrypted(toNode, packet, challenge = nil)
let (data, nonce) = d.codec.encodeEncrypted(toNode.id, toNode.address, packet,
challenge = nil)
d.pendingRequests[nonce] = PendingRequest(node: toNode, packet: packet)
d.send(toNode, data)
result = await d.waitNodes(toNode, reqId)
@ -371,7 +379,8 @@ proc ping(p: Protocol, toNode: Node): RequestId =
reqId = newRequestId()
ping = PingPacket(enrSeq: p.localNode.record.seqNum)
packet = encodePacket(ping, reqId)
(data, nonce) = p.codec.encodeEncrypted(toNode, packet, challenge = nil)
(data, nonce) = p.codec.encodeEncrypted(toNode.id, toNode.address, packet,
challenge = nil)
p.pendingRequests[nonce] = PendingRequest(node: toNode, packet: packet)
p.send(toNode, data)
return reqId

View File

@ -1,6 +1,6 @@
import
hashes, stint,
../enode, enr
eth/[keys, rlp], ../enode, enr
const
authTagSize* = 12
@ -21,6 +21,7 @@ type
authTag*: AuthTag
idNonce*: IdNonce
recordSeq*: uint64
pubKey* {.rlpIgnore.}: PublicKey
Whoareyou* = ref WhoareyouObj