From bfbad64d8335de50714f69a8bccbd06310120a45 Mon Sep 17 00:00:00 2001 From: kdeme Date: Tue, 26 Jan 2021 14:11:22 +0100 Subject: [PATCH] Add update of ENR on newly discovered address --- eth/p2p/discoveryv5/dcli.nim | 26 ++++--- eth/p2p/discoveryv5/enr.nim | 16 ++--- eth/p2p/discoveryv5/node.nim | 16 +++-- eth/p2p/discoveryv5/protocol.nim | 55 +++++++++++--- .../discoveryv5/fuzz_decode_packet.nim | 10 +-- tests/p2p/discv5_test_helper.nim | 2 +- tests/p2p/test_discoveryv5.nim | 30 ++++---- tests/p2p/test_discoveryv5_encoding.nim | 18 ++--- tests/p2p/test_enr.nim | 72 +++++++++++++++---- tests/p2p/test_routing_table.nim | 10 +-- 10 files changed, 177 insertions(+), 78 deletions(-) diff --git a/eth/p2p/discoveryv5/dcli.nim b/eth/p2p/discoveryv5/dcli.nim index 410a257..fa264fe 100644 --- a/eth/p2p/discoveryv5/dcli.nim +++ b/eth/p2p/discoveryv5/dcli.nim @@ -14,12 +14,12 @@ type DiscoveryConf* = object logLevel* {. defaultValue: LogLevel.DEBUG - desc: "Sets the log level." + desc: "Sets the log level" name: "log-level" .}: LogLevel udpPort* {. defaultValue: 9009 - desc: "UDP listening port." + desc: "UDP listening port" name: "udp-port" .}: uint16 listenAddress* {. @@ -28,32 +28,39 @@ type name: "listen-address" }: ValidIpAddress bootnodes* {. - desc: "ENR URI of node to bootstrap discovery with. Argument may be repeated." + desc: "ENR URI of node to bootstrap discovery with. Argument may be repeated" name: "bootnode" .}: seq[enr.Record] nat* {. desc: "Specify method to use for determining public address. " & - "Must be one of: any, none, upnp, pmp, extip:." + "Must be one of: any, none, upnp, pmp, extip:" defaultValue: "any" .}: string + enrAutoUpdate* {. + defaultValue: false + desc: "Discovery can automatically update its ENR with the IP address " & + "and UDP port as seen by other nodes it communicates with. " & + "This option allows to enable/disable this functionality" + name: "enr-auto-update" .}: bool + nodeKey* {. - desc: "P2P node private key as hex.", + desc: "P2P node private key as hex", defaultValue: PrivateKey.random(keys.newRng()[]) name: "nodekey" .}: PrivateKey metricsEnabled* {. defaultValue: false - desc: "Enable the metrics server." + desc: "Enable the metrics server" name: "metrics" .}: bool metricsAddress* {. defaultValue: defaultAdminListenAddress(config) - desc: "Listening address of the metrics server." + desc: "Listening address of the metrics server" name: "metrics-address" .}: ValidIpAddress metricsPort* {. defaultValue: 8008 - desc: "Listening HTTP port of the metrics server." + desc: "Listening HTTP port of the metrics server" name: "metrics-port" .}: Port case cmd* {. @@ -163,7 +170,8 @@ proc run(config: DiscoveryConf) = let (ip, tcpPort, udpPort) = setupNat(config) d = newProtocol(config.nodeKey, ip, tcpPort, udpPort, - bootstrapRecords = config.bootnodes, bindIp = config.listenAddress) + bootstrapRecords = config.bootnodes, bindIp = config.listenAddress, + enrAutoUpdate = config.enrAutoUpdate) d.open() diff --git a/eth/p2p/discoveryv5/enr.nim b/eth/p2p/discoveryv5/enr.nim index c93dd68..7e28e37 100644 --- a/eth/p2p/discoveryv5/enr.nim +++ b/eth/p2p/discoveryv5/enr.nim @@ -144,7 +144,8 @@ template toFieldPair*(key: string, value: auto): FieldPair = (key, toField(value)) proc addAddress(fields: var seq[FieldPair], ip: Option[ValidIpAddress], - tcpPort, udpPort: Port) = + tcpPort, udpPort: Option[Port]) = + # It makes sense to add ports only when there is an IP provided if ip.isSome(): let ipExt = ip.get() @@ -152,16 +153,15 @@ proc addAddress(fields: var seq[FieldPair], ip: Option[ValidIpAddress], fields.add(if isV6: ("ip6", ipExt.address_v6.toField) else: ("ip", ipExt.address_v4.toField)) - fields.add(((if isV6: "tcp6" else: "tcp"), tcpPort.uint16.toField)) - fields.add(((if isV6: "udp6" else: "udp"), udpPort.uint16.toField)) - else: - fields.add(("tcp", tcpPort.uint16.toField)) - fields.add(("udp", udpPort.uint16.toField)) + if tcpPort.isSome(): + fields.add(((if isV6: "tcp6" else: "tcp"), tcpPort.get().uint16.toField)) + if udpPort.isSome(): + fields.add(((if isV6: "udp6" else: "udp"), udpPort.get().uint16.toField)) proc init*(T: type Record, seqNum: uint64, pk: PrivateKey, ip: Option[ValidIpAddress], - tcpPort, udpPort: Port, + tcpPort, udpPort: Option[Port], extraFields: openarray[FieldPair] = []): EnrResult[T] = ## Initialize a `Record` with given sequence number, private key, optional @@ -281,7 +281,7 @@ proc update*(record: var Record, pk: PrivateKey, proc update*(r: var Record, pk: PrivateKey, ip: Option[ValidIpAddress], - tcpPort, udpPort: Port, + tcpPort, udpPort: Option[Port] = none[Port](), extraFields: openarray[FieldPair] = []): EnrResult[void] = ## Update a `Record` with given ip address, tcp port, udp port and optional diff --git a/eth/p2p/discoveryv5/node.nim b/eth/p2p/discoveryv5/node.nim index a8aa506..c336a34 100644 --- a/eth/p2p/discoveryv5/node.nim +++ b/eth/p2p/discoveryv5/node.nim @@ -48,14 +48,20 @@ func newNode*(r: Record): Result[Node, cstring] = ok(Node(id: pk.get().toNodeId(), pubkey: pk.get(), record: r, address: none(Address))) -proc updateNode*(n: Node, pk: PrivateKey, ip: Option[ValidIpAddress], - tcpPort, udpPort: Port, extraFields: openarray[FieldPair] = []): - Result[void, cstring] = +proc update*(n: Node, pk: PrivateKey, ip: Option[ValidIpAddress], + tcpPort, udpPort: Option[Port] = none[Port](), + extraFields: openarray[FieldPair] = []): Result[void, cstring] = ? n.record.update(pk, ip, tcpPort, udpPort, extraFields) if ip.isSome(): - let a = Address(ip: ip.get(), port: udpPort) - n.address = some(a) + if udpPort.isSome(): + let a = Address(ip: ip.get(), port: udpPort.get()) + n.address = some(a) + elif n.address.isSome(): + let a = Address(ip: ip.get(), port: n.address.get().port) + n.address = some(a) + else: + n.address = none(Address) else: n.address = none(Address) diff --git a/eth/p2p/discoveryv5/protocol.nim b/eth/p2p/discoveryv5/protocol.nim index 825d682..2b9f340 100644 --- a/eth/p2p/discoveryv5/protocol.nim +++ b/eth/p2p/discoveryv5/protocol.nim @@ -1,5 +1,5 @@ # nim-eth - Node Discovery Protocol v5 -# Copyright (c) 2020 Status Research & Development GmbH +# Copyright (c) 2020-2021 Status Research & Development GmbH # Licensed under either of # * Apache License, version 2.0, (LICENSE-APACHEv2) # * MIT license (LICENSE-MIT) @@ -106,6 +106,8 @@ const ## refresh the routing table. revalidateMax = 10000 ## Revalidation of a peer is done between 0 and this ## value in milliseconds + ipMajorityInterval = 5.minutes ## Interval for checking the latest IP:Port + ## majority and updating this when ENR auto update is set. initialLookups = 1 ## Amount of lookups done when populating the routing table handshakeTimeout* = 2.seconds ## timeout for the reply on the ## whoareyou message @@ -124,9 +126,11 @@ type awaitedMessages: Table[(NodeId, RequestId), Future[Option[Message]]] refreshLoop: Future[void] revalidateLoop: Future[void] + ipMajorityLoop: Future[void] lastLookup: chronos.Moment bootstrapRecords*: seq[Record] ipVote: IpVote + enrAutoUpdate: bool rng*: ref BrHmacDrbgContext PendingRequest = object @@ -890,21 +894,46 @@ proc refreshLoop(d: Protocol) {.async, raises: [Exception, Defect].} = trace "Discovered nodes in random target query", nodes = randomQuery.len debug "Total nodes in discv5 routing table", total = d.routingTable.len() - let majority = d.ipVote.majority() - if majority.isSome(): - let address = majority.get() - debug "Majority on voted address", address - await sleepAsync(refreshInterval) except CancelledError: trace "refreshLoop canceled" +proc ipMajorityLoop(d: Protocol) {.async, raises: [Exception, Defect].} = + try: + while true: + let majority = d.ipVote.majority() + if majority.isSome(): + if d.localNode.address != majority: + let address = majority.get() + let previous = d.localNode.address + if d.enrAutoUpdate: + let res = d.localNode.update(d.privateKey, + ip = some(address.ip), udpPort = some(address.port)) + if res.isErr: + warn "Failed updating ENR with newly discovered external address", + majority, previous, error = res.error + else: + info "Updated ENR with newly discovered external address", + majority, previous, uri = toURI(d.localNode.record) + else: + warn "Discovered new external address but ENR auto update is off", + majority, previous + else: + debug "Discovered external address matches current address", majority, + current = d.localNode.address + + await sleepAsync(ipMajorityInterval) + except CancelledError: + trace "ipMajorityLoop canceled" + proc newProtocol*(privKey: PrivateKey, - externalIp: Option[ValidIpAddress], tcpPort, udpPort: Port, + externalIp: Option[ValidIpAddress], + tcpPort, udpPort: Port, localEnrFields: openarray[(string, seq[byte])] = [], bootstrapRecords: openarray[Record] = [], previousRecord = none[enr.Record](), bindIp = IPv4_any(), + enrAutoUpdate = false, tableIpLimits = DefaultTableIpLimits, rng = newRng()): Protocol {.raises: [Defect].} = @@ -920,11 +949,11 @@ proc newProtocol*(privKey: PrivateKey, var record: Record if previousRecord.isSome(): record = previousRecord.get() - record.update(privKey, externalIp, tcpPort, udpPort, + record.update(privKey, externalIp, some(tcpPort), some(udpPort), extraFields).expect("Record within size limits and correct key") else: - record = enr.Record.init(1, privKey, externalIp, tcpPort, udpPort, - extraFields).expect("Record within size limits") + record = enr.Record.init(1, privKey, externalIp, some(tcpPort), + some(udpPort), extraFields).expect("Record within size limits") let node = newNode(record).expect("Properly initialized record") # TODO Consider whether this should be a Defect @@ -938,6 +967,7 @@ proc newProtocol*(privKey: PrivateKey, sessions: Sessions.init(256)), bootstrapRecords: @bootstrapRecords, ipVote: IpVote.init(), + enrAutoUpdate: enrAutoUpdate, rng: rng) result.routingTable.init(node, DefaultBitsPerHop, tableIpLimits, rng) @@ -959,6 +989,7 @@ proc open*(d: Protocol) {.raises: [Exception, Defect].} = proc start*(d: Protocol) {.raises: [Exception, Defect].} = d.refreshLoop = refreshLoop(d) d.revalidateLoop = revalidateLoop(d) + d.ipMajorityLoop = ipMajorityLoop(d) proc close*(d: Protocol) {.raises: [Exception, Defect].} = doAssert(not d.transp.closed) @@ -968,6 +999,8 @@ proc close*(d: Protocol) {.raises: [Exception, Defect].} = d.revalidateLoop.cancel() if not d.refreshLoop.isNil: d.refreshLoop.cancel() + if not d.ipMajorityLoop.isNil: + d.ipMajorityLoop.cancel() d.transp.close() @@ -979,5 +1012,7 @@ proc closeWait*(d: Protocol) {.async, raises: [Exception, Defect].} = await d.revalidateLoop.cancelAndWait() if not d.refreshLoop.isNil: await d.refreshLoop.cancelAndWait() + if not d.ipMajorityLoop.isNil: + await d.ipMajorityLoop.cancelAndWait() await d.transp.closeWait() diff --git a/tests/fuzzing/discoveryv5/fuzz_decode_packet.nim b/tests/fuzzing/discoveryv5/fuzz_decode_packet.nim index 933a6b8..4be0be7 100644 --- a/tests/fuzzing/discoveryv5/fuzz_decode_packet.nim +++ b/tests/fuzzing/discoveryv5/fuzz_decode_packet.nim @@ -1,6 +1,6 @@ import testutils/fuzzing, stew/shims/net, stew/byteutils, - eth/p2p/discoveryv5/[encodingv1, enr, sessions, node] + eth/p2p/discoveryv5/[encoding, enr, sessions, node] init: const @@ -12,13 +12,13 @@ init: privKeyB = PrivateKey.fromHex(nodeBKey)[] # receive -> decode enrRecA = enr.Record.init(1, privKeyA, - some(ValidIpAddress.init("127.0.0.1")), Port(9000), - Port(9000)).expect("Properly intialized private key") + some(ValidIpAddress.init("127.0.0.1")), some(Port(9000)), + some(Port(9000))).expect("Properly intialized private key") nodeA = newNode(enrRecA).expect("Properly initialized record") enrRecB = enr.Record.init(1, privKeyB, - some(ValidIpAddress.init("127.0.0.1")), Port(9000), - Port(9000)).expect("Properly intialized private key") + some(ValidIpAddress.init("127.0.0.1")), some(Port(9000)), + some(Port(9000))).expect("Properly intialized private key") nodeB = newNode(enrRecB).expect("Properly initialized record") var codecB = Codec(localNode: nodeB, privKey: privKeyB, diff --git a/tests/p2p/discv5_test_helper.nim b/tests/p2p/discv5_test_helper.nim index 51ece80..8cdcf93 100644 --- a/tests/p2p/discv5_test_helper.nim +++ b/tests/p2p/discv5_test_helper.nim @@ -38,7 +38,7 @@ proc generateNode*(privKey: PrivateKey, port: int = 20302, localEnrFields: openarray[FieldPair] = []): Node = let port = Port(port) let enr = enr.Record.init(1, privKey, some(ip), - port, port, localEnrFields).expect("Properly intialized private key") + some(port), some(port), localEnrFields).expect("Properly intialized private key") result = newNode(enr).expect("Properly initialized node") proc nodeAndPrivKeyAtDistance*(n: Node, rng: var BrHmacDrbgContext, d: uint32, diff --git a/tests/p2p/test_discoveryv5.nim b/tests/p2p/test_discoveryv5.nim index 782ba81..d28f076 100644 --- a/tests/p2p/test_discoveryv5.nim +++ b/tests/p2p/test_discoveryv5.nim @@ -463,7 +463,7 @@ procSuite "Discovery v5 Tests": port = Port(9000) fromNoderecord = enr.Record.init(1, PrivateKey.random(rng[]), some(ValidIpAddress.init("11.12.13.14")), - port, port)[] + some(port), some(port))[] fromNode = newNode(fromNoderecord)[] pk = PrivateKey.random(rng[]) targetDistance = logDist(fromNode.id, pk.toPublicKey().toNodeId()) @@ -471,7 +471,8 @@ procSuite "Discovery v5 Tests": block: # Duplicates let record = enr.Record.init( - 1, pk, some(ValidIpAddress.init("12.13.14.15")), port, port)[] + 1, pk, some(ValidIpAddress.init("12.13.14.15")), + some(port), some(port))[] # Exact duplicates var records = @[record, record] @@ -480,7 +481,8 @@ procSuite "Discovery v5 Tests": # Node id duplicates let recordSameId = enr.Record.init( - 1, pk, some(ValidIpAddress.init("212.13.14.15")), port, port)[] + 1, pk, some(ValidIpAddress.init("212.13.14.15")), + some(port), some(port))[] records.add(recordSameId) nodes = verifyNodesRecords(records, fromNode, targetDistance) check nodes.len == 1 @@ -488,7 +490,7 @@ procSuite "Discovery v5 Tests": block: # No address let recordNoAddress = enr.Record.init( - 1, pk, none(ValidIpAddress), port, port)[] + 1, pk, none(ValidIpAddress), some(port), some(port))[] records = [recordNoAddress] test = verifyNodesRecords(records, fromNode, targetDistance) check test.len == 0 @@ -497,7 +499,7 @@ procSuite "Discovery v5 Tests": let recordInvalidAddress = enr.Record.init( 1, pk, some(ValidIpAddress.init("10.1.2.3")), - port, port)[] + some(port), some(port))[] records = [recordInvalidAddress] test = verifyNodesRecords(records, fromNode, targetDistance) check test.len == 0 @@ -505,7 +507,8 @@ procSuite "Discovery v5 Tests": block: # Invalid address - loopback let recordInvalidAddress = enr.Record.init( - 1, pk, some(ValidIpAddress.init("127.0.0.1")), port, port)[] + 1, pk, some(ValidIpAddress.init("127.0.0.1")), + some(port), some(port))[] records = [recordInvalidAddress] test = verifyNodesRecords(records, fromNode, targetDistance) check test.len == 0 @@ -513,7 +516,8 @@ procSuite "Discovery v5 Tests": block: # Invalid distance let recordInvalidDistance = enr.Record.init( - 1, pk, some(ValidIpAddress.init("12.13.14.15")), port, port)[] + 1, pk, some(ValidIpAddress.init("12.13.14.15")), + some(port), some(port))[] records = [recordInvalidDistance] test = verifyNodesRecords(records, fromNode, 0'u32) check test.len == 0 @@ -530,8 +534,8 @@ procSuite "Discovery v5 Tests": let privKey = PrivateKey.random(rng[]) enrRec = enr.Record.init(1, privKey, - some(ValidIpAddress.init("127.0.0.1")), Port(9000), - Port(9000)).expect("Properly intialized private key") + some(ValidIpAddress.init("127.0.0.1")), some(Port(9000)), + some(Port(9000))).expect("Properly intialized private key") sendNode = newNode(enrRec).expect("Properly initialized record") var codec = Codec(localNode: sendNode, privKey: privKey, sessions: Sessions.init(5)) @@ -559,8 +563,8 @@ procSuite "Discovery v5 Tests": let privKey = PrivateKey.random(rng[]) enrRec = enr.Record.init(1, privKey, - some(ValidIpAddress.init("127.0.0.1")), Port(9000), - Port(9000)).expect("Properly intialized private key") + some(ValidIpAddress.init("127.0.0.1")), some(Port(9000)), + some(Port(9000))).expect("Properly intialized private key") sendNode = newNode(enrRec).expect("Properly initialized record") var codec = Codec(localNode: sendNode, privKey: privKey, sessions: Sessions.init(5)) for i in 0 ..< 5: @@ -590,8 +594,8 @@ procSuite "Discovery v5 Tests": a = localAddress(20303) privKey = PrivateKey.random(rng[]) enrRec = enr.Record.init(1, privKey, - some(ValidIpAddress.init("127.0.0.1")), Port(9000), - Port(9000)).expect("Properly intialized private key") + some(ValidIpAddress.init("127.0.0.1")), some(Port(9000)), + some(Port(9000))).expect("Properly intialized private key") sendNode = newNode(enrRec).expect("Properly initialized record") var codec = Codec(localNode: sendNode, privKey: privKey, sessions: Sessions.init(5)) diff --git a/tests/p2p/test_discoveryv5_encoding.nim b/tests/p2p/test_discoveryv5_encoding.nim index f6a19d3..f7e4e1e 100644 --- a/tests/p2p/test_discoveryv5_encoding.nim +++ b/tests/p2p/test_discoveryv5_encoding.nim @@ -219,13 +219,13 @@ suite "Discovery v5.1 Packet Encodings Test Vectors": privKeyB = PrivateKey.fromHex(nodeBKey)[] # receive -> decode enrRecA = enr.Record.init(1, privKeyA, - some(ValidIpAddress.init("127.0.0.1")), Port(9000), - Port(9000)).expect("Properly intialized private key") + some(ValidIpAddress.init("127.0.0.1")), some(Port(9000)), + some(Port(9000))).expect("Properly intialized private key") nodeA = newNode(enrRecA).expect("Properly initialized record") enrRecB = enr.Record.init(1, privKeyB, - some(ValidIpAddress.init("127.0.0.1")), Port(9000), - Port(9000)).expect("Properly intialized private key") + some(ValidIpAddress.init("127.0.0.1")), some(Port(9000)), + some(Port(9000))).expect("Properly intialized private key") nodeB = newNode(enrRecB).expect("Properly initialized record") var @@ -432,12 +432,14 @@ suite "Discovery v5.1 Additional Encode/Decode": privKeyA = PrivateKey.random(rng[]) # sender -> encode privKeyB = PrivateKey.random(rng[]) # receiver -> decode - enrRecA = enr.Record.init(1, privKeyA, some(ValidIpAddress.init("127.0.0.1")), Port(9000), - Port(9000)).expect("Properly intialized private key") + enrRecA = enr.Record.init(1, privKeyA, + some(ValidIpAddress.init("127.0.0.1")), some(Port(9000)), + some(Port(9000))).expect("Properly intialized private key") nodeA = newNode(enrRecA).expect("Properly initialized record") - enrRecB = enr.Record.init(1, privKeyB, some(ValidIpAddress.init("127.0.0.1")), Port(9000), - Port(9000)).expect("Properly intialized private key") + enrRecB = enr.Record.init(1, privKeyB, + some(ValidIpAddress.init("127.0.0.1")), some(Port(9000)), + some(Port(9000))).expect("Properly intialized private key") nodeB = newNode(enrRecB).expect("Properly initialized record") var diff --git a/tests/p2p/test_enr.nim b/tests/p2p/test_enr.nim index 2db1b84..faee6ee 100644 --- a/tests/p2p/test_enr.nim +++ b/tests/p2p/test_enr.nim @@ -60,8 +60,9 @@ suite "ENR": let keypair = KeyPair.random(rng[]) ip = ValidIpAddress.init("10.20.30.40") + port = some(Port(9000)) enr = Record.init( - 100, keypair.seckey, some(ip), Port(9000), Port(9000),@[])[] + 100, keypair.seckey, some(ip), port, port,@[])[] typedEnr = get enr.toTypedRecord() check: @@ -80,8 +81,9 @@ suite "ENR": test "ENR without address": let keypair = KeyPair.random(rng[]) + port = some(Port(9000)) enr = Record.init( - 100, keypair.seckey, none(ValidIpAddress), Port(9000), Port(9000))[] + 100, keypair.seckey, none(ValidIpAddress), port, port)[] typedEnr = get enr.toTypedRecord() check: @@ -89,11 +91,8 @@ suite "ENR": typedEnr.secp256k1.get() == keypair.pubkey.toRawCompressed() typedEnr.ip.isNone() - typedEnr.tcp.isSome() - typedEnr.tcp.get() == 9000 - - typedEnr.udp.isSome() - typedEnr.udp.get() == 9000 + typedEnr.tcp.isNone() + typedEnr.udp.isNone() typedEnr.ip6.isNone() typedEnr.tcp6.isNone() @@ -115,7 +114,7 @@ suite "ENR": pk = PrivateKey.fromHex( "5d2908f3f09ea1ff2e327c3f623159639b00af406e9009de5fd4b910fc34049d")[] newField = toFieldPair("test", 123'u) - var r = Record.init(1, pk, none(ValidIpAddress), Port(9000), Port(9000))[] + var r = Record.init(1, pk, none(ValidIpAddress), none(Port), none(Port))[] block: # Insert new k:v pair, update of seqNum should occur. let updated = r.update(pk, [newField]) @@ -182,20 +181,63 @@ suite "ENR": let pk = PrivateKey.fromHex( "5d2908f3f09ea1ff2e327c3f623159639b00af406e9009de5fd4b910fc34049d")[] - var r = Record.init(1, pk, none(ValidIpAddress), Port(9000), Port(9000))[] + var r = Record.init(1, pk, none(ValidIpAddress), + some(Port(9000)), some(Port(9000)))[] block: - let updated = r.update(pk, none(ValidIpAddress), Port(9000), Port(9000)) + let updated = r.update(pk, none(ValidIpAddress), + some(Port(9000)), some(Port(9000))) check updated.isOk() check: - r.get("tcp", uint) == 9000 - r.get("udp", uint) == 9000 + r.tryGet("ip", uint).isNone() + r.tryGet("tcp", uint).isNone() + r.tryGet("udp", uint).isNone() r.seqNum == 1 block: - let updated = r.update(pk, none(ValidIpAddress), Port(9001), Port(9002)) + let updated = r.update(pk, none(ValidIpAddress), + some(Port(9001)), some(Port(9002))) check updated.isOk() check: - r.get("tcp", uint) == 9001 - r.get("udp", uint) == 9002 + r.tryGet("ip", uint).isNone() + r.tryGet("tcp", uint).isNone() + r.tryGet("udp", uint).isNone() + r.seqNum == 1 + + block: + let updated = r.update(pk, some(ValidIpAddress.init("10.20.30.40")), + some(Port(9000)), some(Port(9000))) + check updated.isOk() + + let typedEnr = r.toTypedRecord().get() + + check: + typedEnr.ip.isSome() + typedEnr.ip.get() == [byte 10, 20, 30, 40] + + typedEnr.tcp.isSome() + typedEnr.tcp.get() == 9000 + + typedEnr.udp.isSome() + typedEnr.udp.get() == 9000 + r.seqNum == 2 + + block: + let updated = r.update(pk, some(ValidIpAddress.init("10.20.30.40")), + some(Port(9001)), some(Port(9001))) + check updated.isOk() + + let typedEnr = r.toTypedRecord().get() + + check: + typedEnr.ip.isSome() + typedEnr.ip.get() == [byte 10, 20, 30, 40] + + typedEnr.tcp.isSome() + typedEnr.tcp.get() == 9001 + + typedEnr.udp.isSome() + typedEnr.udp.get() == 9001 + + r.seqNum == 3 diff --git a/tests/p2p/test_routing_table.nim b/tests/p2p/test_routing_table.nim index 222d8d0..78d668a 100644 --- a/tests/p2p/test_routing_table.nim +++ b/tests/p2p/test_routing_table.nim @@ -472,8 +472,9 @@ suite "Routing Table Tests": let updatedNode1 = generateNode(pk) # Need to do an update to get seqNum increased - let updated = updatedNode1.updateNode(pk, - some(ValidIpAddress.init("192.168.0.1")), Port(9000), Port(9000)) + let updated = updatedNode1.update(pk, + some(ValidIpAddress.init("192.168.0.1")), + some(Port(9000)), some(Port(9000))) check updated.isOk() check table.addNode(updatedNode1) == Existing @@ -524,8 +525,9 @@ suite "Routing Table Tests": for i in 0..