nim-eth/eth/p2p/discoveryv5/node.nim

60 lines
1.5 KiB
Nim
Raw Normal View History

import
std/[net, hashes], nimcrypto, stint, chronos,
eth/keys, enr
2019-12-16 19:38:45 +00:00
{.push raises: [Defect].}
2019-12-16 19:38:45 +00:00
type
NodeId* = UInt256
Address* = object
ip*: IpAddress
port*: Port
2019-12-16 19:38:45 +00:00
Node* = ref object
id*: NodeId
pubkey*: PublicKey
address*: Option[Address]
2019-12-16 19:38:45 +00:00
record*: Record
proc toNodeId*(pk: PublicKey): NodeId =
readUintBE[256](keccak256.digest(pk.toRaw()).data)
2019-12-16 19:38:45 +00:00
proc newNode*(r: Record): Result[Node, cstring] =
2019-12-16 19:38:45 +00:00
# TODO: Handle IPv6
let pk = r.get(PublicKey)
# This check is redundant as the deserialisation of `Record` will already fail
# at `verifySignature` if there is no public key
if pk.isNone():
return err("Could not recover public key from ENR")
let tr = ? r.toTypedRecord()
if tr.ip.isSome() and tr.udp.isSome():
let
ip = IpAddress(family: IpAddressFamily.IPv4, address_v4: tr.ip.get())
a = Address(ip: ip, port: Port(tr.udp.get()))
ok(Node(id: pk.get().toNodeId(), pubkey: pk.get() , record: r,
address: some(a)))
else:
ok(Node(id: pk.get().toNodeId(), pubkey: pk.get(), record: r,
address: none(Address)))
2019-12-16 19:38:45 +00:00
proc hash*(n: Node): hashes.Hash = hash(n.pubkey.toRaw)
2020-05-01 20:34:26 +00:00
proc `==`*(a, b: Node): bool =
(a.isNil and b.isNil) or
(not a.isNil and not b.isNil and a.pubkey == b.pubkey)
proc `$`*(a: Address): string =
result.add($a.ip)
result.add(":" & $a.port)
2020-05-01 20:34:26 +00:00
proc `$`*(n: Node): string =
2019-12-16 19:38:45 +00:00
if n == nil:
"Node[uninitialized]"
elif n.address.isNone():
"Node[unaddressable]"
2019-12-16 19:38:45 +00:00
else:
"Node[" & $n.address.get().ip & ":" & $n.address.get().port & "]"