mirror of https://github.com/status-im/nim-eth.git
Use addresses instead of stubs as db keys
This commit is contained in:
parent
988d743c9a
commit
9772fbe470
|
@ -1,4 +1,5 @@
|
|||
import types
|
||||
import std/net
|
||||
import types, ../enode
|
||||
import eth/trie/db
|
||||
|
||||
type
|
||||
|
@ -11,18 +12,28 @@ type
|
|||
proc init*(T: type DiscoveryDB, backend: TrieDatabaseRef): DiscoveryDB =
|
||||
T(backend: backend)
|
||||
|
||||
proc makeKey(id: NodeId, address: int): array[1 + sizeof(id) + sizeof(address), byte] =
|
||||
const keySize = 1 + # unique triedb prefix (kNodeToKeys)
|
||||
sizeof(NodeId) +
|
||||
16 + # max size of ip address (ipv6)
|
||||
2 # Sizeof port
|
||||
|
||||
proc makeKey(id: NodeId, address: Address): array[keySize, byte] =
|
||||
result[0] = byte(kNodeToKeys)
|
||||
copyMem(addr result[1], unsafeAddr id, sizeof(id))
|
||||
copyMem(addr result[sizeof(id) + 1], unsafeAddr address, sizeof(address))
|
||||
case address.ip.family
|
||||
of IpAddressFamily.IpV4:
|
||||
copyMem(addr result[sizeof(id) + 1], unsafeAddr address.ip.address_v4, sizeof(address.ip.address_v4))
|
||||
of IpAddressFamily.IpV6:
|
||||
copyMem(addr result[sizeof(id) + 1], unsafeAddr address.ip.address_v6, sizeof(address.ip.address_v6))
|
||||
copyMem(addr result[sizeof(id) + 1 + sizeof(address.ip.address_v6)], unsafeAddr address.udpPort, sizeof(address.udpPort))
|
||||
|
||||
method storeKeys*(db: DiscoveryDB, id: NodeId, address: int, r, w: array[16, byte]) =
|
||||
method storeKeys*(db: DiscoveryDB, id: NodeId, address: Address, r, w: array[16, byte]) =
|
||||
var value: array[sizeof(r) + sizeof(w), byte]
|
||||
value[0 .. 15] = r
|
||||
value[16 .. ^1] = w
|
||||
db.backend.put(makeKey(id, address), value)
|
||||
|
||||
method loadKeys*(db: DiscoveryDB, id: NodeId, address: int, r, w: var array[16, byte]): bool =
|
||||
method loadKeys*(db: DiscoveryDB, id: NodeId, address: Address, r, w: var array[16, byte]): bool =
|
||||
let res = db.backend.get(makeKey(id, address))
|
||||
if res.len == sizeof(r) + sizeof(w):
|
||||
copyMem(addr r[0], unsafeAddr res[0], sizeof(r))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import tables
|
||||
import types, node, enr, hkdf, eth/[rlp, keys], nimcrypto, stint
|
||||
import types, node, enr, hkdf, ../enode, eth/[rlp, keys], nimcrypto, stint
|
||||
|
||||
const
|
||||
idNoncePrefix = "discovery-id-nonce"
|
||||
|
@ -114,7 +114,7 @@ proc packetTag(destNode, srcNode: NodeID): array[32, byte] =
|
|||
let destidHash = sha256.digest(destId)
|
||||
result = srcId xor destidHash.data
|
||||
|
||||
proc encodeEncrypted*(c: Codec, toNode: Node, toAddr: int, packetData: seq[byte], challenge: Whoareyou): (seq[byte], array[gcmNonceSize, byte]) =
|
||||
proc encodeEncrypted*(c: Codec, toNode: Node, packetData: seq[byte], challenge: Whoareyou): (seq[byte], array[gcmNonceSize, byte]) =
|
||||
var nonce: array[gcmNonceSize, byte]
|
||||
randomBytes(nonce)
|
||||
var headEnc: seq[byte]
|
||||
|
@ -127,14 +127,14 @@ proc encodeEncrypted*(c: Codec, toNode: Node, toAddr: int, packetData: seq[byte]
|
|||
|
||||
# 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, toAddr, readKey, writeKey)
|
||||
discard c.db.loadKeys(toNode.id, toNode.address, readKey, writeKey)
|
||||
else:
|
||||
var sec: HandshakeSecrets
|
||||
headEnc = c.makeAuthHeader(toNode, nonce, sec, challenge)
|
||||
|
||||
writeKey = sec.writeKey
|
||||
|
||||
c.db.storeKeys(toNode.id, toAddr, sec.readKey, sec.writeKey)
|
||||
c.db.storeKeys(toNode.id, toNode.address, sec.readKey, sec.writeKey)
|
||||
|
||||
var body = packetData
|
||||
let tag = packetTag(toNode.id, c.localNode.id)
|
||||
|
@ -201,7 +201,7 @@ proc decodeAuthResp(c: Codec, fromId: NodeId, head: AuthHeader, challenge: Whoar
|
|||
newNode = newNode(authResp.record)
|
||||
return true
|
||||
|
||||
proc decodeEncrypted*(c: var Codec, fromId: NodeID, fromAddr: int, input: seq[byte], authTag: var array[12, byte], newNode: var Node, packet: var Packet): bool =
|
||||
proc decodeEncrypted*(c: var Codec, fromId: NodeID, fromAddr: Address, input: seq[byte], authTag: var array[12, byte], newNode: var Node, packet: var Packet): bool =
|
||||
let input = input.toRange
|
||||
var r = rlpFromBytes(input[32 .. ^1])
|
||||
let authEndPos = r.currentElemEnd
|
||||
|
|
|
@ -45,6 +45,8 @@ proc newNode*(r: Record): Node =
|
|||
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)
|
||||
|
||||
proc address*(n: Node): Address {.inline.} = n.node.address
|
||||
|
||||
proc `$`*(n: Node): string =
|
||||
if n == nil:
|
||||
"Node[local]"
|
||||
|
|
|
@ -92,7 +92,7 @@ proc sendWhoareyou(d: Protocol, address: Address, toNode: NodeId, authTag: array
|
|||
|
||||
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, 12345, encodePacket(packet, reqId), challenge = nil)
|
||||
let (data, _) = d.codec.encodeEncrypted(toNode, encodePacket(packet, reqId), challenge = nil)
|
||||
d.send(toNode, data)
|
||||
|
||||
const maxNodesPerPacket = 3
|
||||
|
@ -109,7 +109,8 @@ proc sendNodes(d: Protocol, toNode: Node, reqId: RequestId, nodes: openarray[Nod
|
|||
if packet.enrs.len != 0:
|
||||
d.sendNodes(toNode, packet, reqId)
|
||||
|
||||
proc handlePing(d: Protocol, fromNode: Node, a: Address, ping: PingPacket, reqId: RequestId) =
|
||||
proc handlePing(d: Protocol, fromNode: Node, ping: PingPacket, reqId: RequestId) =
|
||||
let a = fromNode.address
|
||||
var pong: PongPacket
|
||||
pong.enrSeq = ping.enrSeq
|
||||
pong.ip = case a.ip.family
|
||||
|
@ -117,10 +118,10 @@ proc handlePing(d: Protocol, fromNode: Node, a: Address, ping: PingPacket, reqId
|
|||
of IpAddressFamily.IPv6: @(a.ip.address_v6)
|
||||
pong.port = a.udpPort.uint16
|
||||
|
||||
let (data, _) = d.codec.encodeEncrypted(fromNode, 12345, encodePacket(pong, reqId), challenge = nil)
|
||||
let (data, _) = d.codec.encodeEncrypted(fromNode, encodePacket(pong, reqId), challenge = nil)
|
||||
d.send(fromNode, data)
|
||||
|
||||
proc handleFindNode(d: Protocol, fromNode: Node, a: Address, fn: FindNodePacket, reqId: RequestId) =
|
||||
proc handleFindNode(d: Protocol, fromNode: Node, fn: FindNodePacket, reqId: RequestId) =
|
||||
if fn.distance == 0:
|
||||
d.sendNodes(fromNode, reqId, [d.localNode])
|
||||
else:
|
||||
|
@ -142,7 +143,7 @@ proc receive*(d: Protocol, a: Address, msg: Bytes) {.gcsafe.} =
|
|||
if d.pendingRequests.take(whoareyou.authTag, pr):
|
||||
let toNode = pr.node
|
||||
|
||||
let (data, _) = d.codec.encodeEncrypted(toNode, 12345, pr.packet, challenge = whoareyou)
|
||||
let (data, _) = d.codec.encodeEncrypted(toNode, pr.packet, challenge = whoareyou)
|
||||
d.send(toNode, data)
|
||||
|
||||
else:
|
||||
|
@ -155,7 +156,7 @@ proc receive*(d: Protocol, a: Address, msg: Bytes) {.gcsafe.} =
|
|||
var node: Node
|
||||
var packet: Packet
|
||||
|
||||
if d.codec.decodeEncrypted(sender, 12345, msg, authTag, node, packet):
|
||||
if d.codec.decodeEncrypted(sender, a, msg, authTag, node, packet):
|
||||
if node.isNil:
|
||||
node = d.routingTable.getNode(sender)
|
||||
else:
|
||||
|
@ -166,9 +167,9 @@ proc receive*(d: Protocol, a: Address, msg: Bytes) {.gcsafe.} =
|
|||
|
||||
case packet.kind
|
||||
of ping:
|
||||
d.handlePing(node, a, packet.ping, packet.reqId)
|
||||
d.handlePing(node, packet.ping, packet.reqId)
|
||||
of findNode:
|
||||
d.handleFindNode(node, a, packet.findNode, packet.reqId)
|
||||
d.handleFindNode(node, packet.findNode, packet.reqId)
|
||||
else:
|
||||
var waiter: Future[Option[Packet]]
|
||||
if d.awaitedPackets.take((node, packet.reqId), waiter):
|
||||
|
@ -212,7 +213,7 @@ 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, 12345, packet, challenge = nil)
|
||||
let (data, nonce) = d.codec.encodeEncrypted(toNode, packet, challenge = nil)
|
||||
d.pendingRequests[nonce] = PendingRequest(node: toNode, packet: packet)
|
||||
d.send(toNode, data)
|
||||
result = await d.waitNodes(toNode, reqId)
|
||||
|
@ -323,7 +324,7 @@ when isMainModule:
|
|||
result.add(d)
|
||||
|
||||
proc addNode(d: openarray[Protocol], enr: string) =
|
||||
for dd in d: dd.addNode(enr)
|
||||
for dd in d: dd.addNode(EnrUri(enr))
|
||||
|
||||
proc test() {.async.} =
|
||||
block:
|
||||
|
|
|
@ -68,8 +68,8 @@ template packetKind*(T: typedesc[SomePacket]): PacketKind =
|
|||
elif T is FindNodePacket: findNode
|
||||
elif T is NodesPacket: nodes
|
||||
|
||||
method storeKeys*(db: Database, id: NodeId, address: int, r, w: array[16, byte]) {.base.} = discard
|
||||
method loadKeys*(db: Database, id: NodeId, address: int, r, w: var array[16, byte]): bool {.base.} = discard
|
||||
method storeKeys*(db: Database, id: NodeId, address: Address, r, w: array[16, byte]) {.base.} = discard
|
||||
method loadKeys*(db: Database, id: NodeId, address: Address, r, w: var array[16, byte]): bool {.base.} = discard
|
||||
|
||||
proc toBytes*(id: NodeId): array[32, byte] {.inline.} =
|
||||
id.toByteArrayBE()
|
||||
|
|
Loading…
Reference in New Issue