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

57 lines
1.5 KiB
Nim

import
std/[net, endians, hashes], nimcrypto, stint, chronicles,
types, enr, eth/keys, ../enode
type
Node* = ref object
node*: ENode
id*: NodeId
record*: Record
proc toNodeId*(pk: PublicKey): NodeId =
readUintBE[256](keccak256.digest(pk.getRaw()).data)
proc newNode*(pk: PublicKey, address: Address): Node =
result.new()
result.node = initENode(pk, address)
result.id = pk.toNodeId()
proc newNode*(uriString: string): Node =
result.new()
result.node = initENode(uriString)
result.id = result.node.pubkey.toNodeId()
proc newNode*(enode: ENode): Node =
result.new()
result.node = enode
result.id = result.node.pubkey.toNodeId()
proc newNode*(r: Record): Node =
# TODO: Handle IPv6
let
ipBytes = r.get("ip", array[4, byte])
udpPort = r.get("udp", uint16)
var pk: PublicKey
if recoverPublicKey(r.get("secp256k1", seq[byte]), pk) != EthKeysStatus.Success:
warn "Could not recover public key"
return
let a = Address(ip: IpAddress(family: IpAddressFamily.IPv4,
address_v4: ipBytes),
udpPort: Port udpPort)
result = newNode(initENode(pk, a))
result.record = r
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]"
else:
"Node[" & $n.node.address.ip & ":" & $n.node.address.udpPort & "]"