mirror of https://github.com/status-im/nim-eth.git
For now use directly address/id instead of Node to workaround node isNil problem in edge cases
This commit is contained in:
parent
55b8e3e23f
commit
a9ff761d68
|
@ -88,7 +88,7 @@ proc encryptGCM*(key, nonce, pt, authData: openarray[byte]): seq[byte] =
|
||||||
ectx.getTag(result.toOpenArray(pt.len, result.high))
|
ectx.getTag(result.toOpenArray(pt.len, result.high))
|
||||||
ectx.clear()
|
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,
|
handshakeSecrets: var HandshakeSecrets,
|
||||||
challenge: Whoareyou): seq[byte] =
|
challenge: Whoareyou): seq[byte] =
|
||||||
var resp = AuthResponse(version: 5)
|
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
|
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)
|
handshakeSecrets)
|
||||||
|
|
||||||
let respRlp = rlp.encode(resp)
|
let respRlp = rlp.encode(resp)
|
||||||
|
@ -125,7 +125,8 @@ proc packetTag(destNode, srcNode: NodeID): PacketTag =
|
||||||
result = srcId xor destidHash.data
|
result = srcId xor destidHash.data
|
||||||
|
|
||||||
proc encodeEncrypted*(c: Codec,
|
proc encodeEncrypted*(c: Codec,
|
||||||
toNode: Node,
|
toId: NodeID,
|
||||||
|
toAddr: Address,
|
||||||
packetData: seq[byte],
|
packetData: seq[byte],
|
||||||
challenge: Whoareyou):
|
challenge: Whoareyou):
|
||||||
(seq[byte], array[gcmNonceSize, byte]) =
|
(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
|
# 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.
|
# 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:
|
else:
|
||||||
var sec: HandshakeSecrets
|
var sec: HandshakeSecrets
|
||||||
headEnc = c.makeAuthHeader(toNode, nonce, sec, challenge)
|
headEnc = c.makeAuthHeader(toId, nonce, sec, challenge)
|
||||||
|
|
||||||
writeKey = sec.writeKey
|
writeKey = sec.writeKey
|
||||||
# TODO: is it safe to ignore the error here?
|
# 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
|
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)
|
var headBuf = newSeqOfCap[byte](tag.len + headEnc.len)
|
||||||
headBuf.add(tag)
|
headBuf.add(tag)
|
||||||
|
|
|
@ -35,7 +35,7 @@ type
|
||||||
db: Database
|
db: Database
|
||||||
routingTable: RoutingTable
|
routingTable: RoutingTable
|
||||||
codec*: Codec
|
codec*: Codec
|
||||||
awaitedPackets: Table[(Node, RequestId), Future[Option[Packet]]]
|
awaitedPackets: Table[(NodeId, RequestId), Future[Option[Packet]]]
|
||||||
lookupLoop: Future[void]
|
lookupLoop: Future[void]
|
||||||
revalidateLoop: Future[void]
|
revalidateLoop: Future[void]
|
||||||
bootstrapNodes: seq[Node]
|
bootstrapNodes: seq[Node]
|
||||||
|
@ -141,10 +141,13 @@ proc sendWhoareyou(d: Protocol, address: Address, toNode: NodeId, authTag: AuthT
|
||||||
data.add(rlp.encode(challenge[]))
|
data.add(rlp.encode(challenge[]))
|
||||||
d.send(address, data)
|
d.send(address, data)
|
||||||
|
|
||||||
proc sendNodes(d: Protocol, toNode: Node, reqId: RequestId, nodes: openarray[Node]) =
|
proc sendNodes(d: Protocol, toId: NodeId, toAddr: Address, reqId: RequestId,
|
||||||
proc sendNodes(d: Protocol, toNode: Node, packet: NodesPacket, reqId: RequestId) {.nimcall.} =
|
nodes: openarray[Node]) =
|
||||||
let (data, _) = d.codec.encodeEncrypted(toNode, encodePacket(packet, reqId), challenge = nil)
|
proc sendNodes(d: Protocol, toId: NodeId, toAddr: Address,
|
||||||
d.send(toNode, data)
|
packet: NodesPacket, reqId: RequestId) {.nimcall.} =
|
||||||
|
let (data, _) = d.codec.encodeEncrypted(toId, toAddr,
|
||||||
|
encodePacket(packet, reqId), challenge = nil)
|
||||||
|
d.send(toAddr, data)
|
||||||
|
|
||||||
var packet: NodesPacket
|
var packet: NodesPacket
|
||||||
packet.total = ceil(nodes.len / maxNodesPerPacket).uint32
|
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:
|
for i in 0 ..< nodes.len:
|
||||||
packet.enrs.add(nodes[i].record)
|
packet.enrs.add(nodes[i].record)
|
||||||
if packet.enrs.len == 3:
|
if packet.enrs.len == 3:
|
||||||
d.sendNodes(toNode, packet, reqId)
|
d.sendNodes(toId, toAddr, packet, reqId)
|
||||||
packet.enrs.setLen(0)
|
packet.enrs.setLen(0)
|
||||||
|
|
||||||
if packet.enrs.len != 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) =
|
proc handlePing(d: Protocol, fromId: NodeId, fromAddr: Address,
|
||||||
let a = fromNode.address
|
ping: PingPacket, reqId: RequestId) =
|
||||||
|
let a = fromAddr
|
||||||
var pong: PongPacket
|
var pong: PongPacket
|
||||||
pong.enrSeq = ping.enrSeq
|
pong.enrSeq = ping.enrSeq
|
||||||
pong.ip = case a.ip.family
|
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)
|
of IpAddressFamily.IPv6: @(a.ip.address_v6)
|
||||||
pong.port = a.udpPort.uint16
|
pong.port = a.udpPort.uint16
|
||||||
|
|
||||||
let (data, _) = d.codec.encodeEncrypted(fromNode, encodePacket(pong, reqId), challenge = nil)
|
let (data, _) = d.codec.encodeEncrypted(fromId, fromAddr,
|
||||||
d.send(fromNode, data)
|
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:
|
if fn.distance == 0:
|
||||||
d.sendNodes(fromNode, reqId, [d.localNode])
|
d.sendNodes(fromId, fromAddr, reqId, [d.localNode])
|
||||||
else:
|
else:
|
||||||
let distance = min(fn.distance, 256)
|
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,
|
proc receive*(d: Protocol, a: Address, msg: Bytes) {.gcsafe,
|
||||||
raises: [
|
raises: [
|
||||||
|
@ -200,8 +207,10 @@ proc receive*(d: Protocol, a: Address, msg: Bytes) {.gcsafe,
|
||||||
var pr: PendingRequest
|
var pr: PendingRequest
|
||||||
if d.pendingRequests.take(whoareyou.authTag, pr):
|
if d.pendingRequests.take(whoareyou.authTag, pr):
|
||||||
let toNode = pr.node
|
let toNode = pr.node
|
||||||
|
whoareyou.pubKey = toNode.node.pubkey # TODO: Yeah, rather ugly this.
|
||||||
try:
|
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)
|
d.send(toNode, data)
|
||||||
except RandomSourceDepleted as err:
|
except RandomSourceDepleted as err:
|
||||||
debug "Failed to respond to a who-you-are msg " &
|
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
|
debug "Adding new node to routing table", node = $node, localNode = $d.localNode
|
||||||
discard d.routingTable.addNode(node)
|
discard d.routingTable.addNode(node)
|
||||||
|
|
||||||
doAssert(not node.isNil, "No node in the routing table (internal error?)")
|
|
||||||
|
|
||||||
case packet.kind
|
case packet.kind
|
||||||
of ping:
|
of ping:
|
||||||
d.handlePing(node, packet.ping, packet.reqId)
|
d.handlePing(sender, a, packet.ping, packet.reqId)
|
||||||
of findNode:
|
of findNode:
|
||||||
d.handleFindNode(node, packet.findNode, packet.reqId)
|
d.handleFindNode(sender, a, packet.findNode, packet.reqId)
|
||||||
else:
|
else:
|
||||||
var waiter: Future[Option[Packet]]
|
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)
|
waiter.complete(packet.some)
|
||||||
else:
|
else:
|
||||||
debug "TODO: handle packet: ", packet = packet.kind, origin = $node
|
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]] =
|
proc waitPacket(d: Protocol, fromNode: Node, reqId: RequestId): Future[Option[Packet]] =
|
||||||
result = newFuture[Option[Packet]]("waitPacket")
|
result = newFuture[Option[Packet]]("waitPacket")
|
||||||
let res = result
|
let res = result
|
||||||
let key = (fromNode, reqId)
|
let key = (fromNode.id, reqId)
|
||||||
sleepAsync(responseTimeout).addCallback() do(data: pointer):
|
sleepAsync(responseTimeout).addCallback() do(data: pointer):
|
||||||
d.awaitedPackets.del(key)
|
d.awaitedPackets.del(key)
|
||||||
if not res.finished:
|
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.} =
|
proc findNode(d: Protocol, toNode: Node, distance: uint32): Future[seq[Node]] {.async.} =
|
||||||
let reqId = newRequestId()
|
let reqId = newRequestId()
|
||||||
let packet = encodePacket(FindNodePacket(distance: distance), reqId)
|
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.pendingRequests[nonce] = PendingRequest(node: toNode, packet: packet)
|
||||||
d.send(toNode, data)
|
d.send(toNode, data)
|
||||||
result = await d.waitNodes(toNode, reqId)
|
result = await d.waitNodes(toNode, reqId)
|
||||||
|
@ -371,7 +379,8 @@ proc ping(p: Protocol, toNode: Node): RequestId =
|
||||||
reqId = newRequestId()
|
reqId = newRequestId()
|
||||||
ping = PingPacket(enrSeq: p.localNode.record.seqNum)
|
ping = PingPacket(enrSeq: p.localNode.record.seqNum)
|
||||||
packet = encodePacket(ping, reqId)
|
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.pendingRequests[nonce] = PendingRequest(node: toNode, packet: packet)
|
||||||
p.send(toNode, data)
|
p.send(toNode, data)
|
||||||
return reqId
|
return reqId
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import
|
import
|
||||||
hashes, stint,
|
hashes, stint,
|
||||||
../enode, enr
|
eth/[keys, rlp], ../enode, enr
|
||||||
|
|
||||||
const
|
const
|
||||||
authTagSize* = 12
|
authTagSize* = 12
|
||||||
|
@ -21,6 +21,7 @@ type
|
||||||
authTag*: AuthTag
|
authTag*: AuthTag
|
||||||
idNonce*: IdNonce
|
idNonce*: IdNonce
|
||||||
recordSeq*: uint64
|
recordSeq*: uint64
|
||||||
|
pubKey* {.rlpIgnore.}: PublicKey
|
||||||
|
|
||||||
Whoareyou* = ref WhoareyouObj
|
Whoareyou* = ref WhoareyouObj
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue