discv5: allow creation of node without external ip

This commit is contained in:
kdeme 2020-03-30 13:21:32 +02:00
parent 0a33744d1c
commit 65bed1ae94
5 changed files with 43 additions and 30 deletions

View File

@ -101,19 +101,23 @@ macro initRecord*(seqNum: uint64, pk: PrivateKey, pairs: untyped{nkTableConstr})
proc init*(T: type Record, seqNum: uint64, proc init*(T: type Record, seqNum: uint64,
pk: PrivateKey, pk: PrivateKey,
address: Option[enode.Address]): T = ip: Option[IpAddress],
if address.isSome(): tcpPort, udpPort: Port): T =
if ip.isSome():
let let
a = address.get() ipExt = ip.get()
isV6 = a.ip.family == IPv6 isV6 = ipExt.family == IPv6
ipField = if isV6: ("ip6", a.ip.address_v6.toField) ipField = if isV6: ("ip6", ipExt.address_v6.toField)
else: ("ip", a.ip.address_v4.toField) else: ("ip", ipExt.address_v4.toField)
tcpField = ((if isV6: "tcp6" else: "tcp"), a.tcpPort.uint16.toField) tcpField = ((if isV6: "tcp6" else: "tcp"), tcpPort.uint16.toField)
udpField = ((if isV6: "udp6" else: "udp"), a.udpPort.uint16.toField) udpField = ((if isV6: "udp6" else: "udp"), udpPort.uint16.toField)
makeEnrAux(seqNum, pk, [ipField, tcpField, udpField]) makeEnrAux(seqNum, pk, [ipField, tcpField, udpField])
else: else:
makeEnrAux(seqNum, pk, []) let
tcpField = ("tcp", tcpPort.uint16.toField)
udpField = ("udp", udpPort.uint16.toField)
makeEnrAux(seqNum, pk, [tcpField, udpField])
proc getField(r: Record, name: string, field: var Field): bool = proc getField(r: Record, name: string, field: var Field): bool =
# It might be more correct to do binary search, # It might be more correct to do binary search,

View File

@ -39,7 +39,8 @@ proc newNode*(r: Record): Node =
udpPort: Port udpPort) udpPort: Port udpPort)
except KeyError: except KeyError:
# TODO: This will result in a 0.0.0.0 address. Might introduce more bugs. # TODO: This will result in a 0.0.0.0 address. Might introduce more bugs.
# Lets fail when creating a node just form a record without IP? # Maybe we shouldn't allow the creation of Node from Record without IP.
# Will need some refactor though.
discard discard
var pk: PublicKey var pk: PublicKey

View File

@ -6,6 +6,8 @@ import
import nimcrypto except toHex import nimcrypto except toHex
export options
logScope: logScope:
topics = "discv5" topics = "discv5"
@ -470,12 +472,13 @@ proc lookupLoop(d: Protocol) {.async.} =
trace "lookupLoop canceled" trace "lookupLoop canceled"
proc newProtocol*(privKey: PrivateKey, db: Database, proc newProtocol*(privKey: PrivateKey, db: Database,
ip: IpAddress, tcpPort, udpPort: Port, externalIp: Option[IpAddress], tcpPort, udpPort: Port,
bootstrapRecords: openarray[Record] = []): Protocol = bootstrapRecords: openarray[Record] = []): Protocol =
let let
a = Address(ip: ip, tcpPort: tcpPort, udpPort: udpPort) a = Address(ip: externalIp.get(IPv4_any()),
tcpPort: tcpPort, udpPort: udpPort)
enode = initENode(privKey.getPublicKey(), a) enode = initENode(privKey.getPublicKey(), a)
enrRec = enr.Record.init(12, privKey, some(a)) enrRec = enr.Record.init(1, privKey, externalIp, tcpPort, udpPort)
node = newNode(enode, enrRec) node = newNode(enode, enrRec)
result = Protocol( result = Protocol(

View File

@ -1,16 +1,16 @@
import import
random, unittest, chronos, sequtils, chronicles, tables, stint, options, unittest, chronos, sequtils, chronicles, tables, stint,
eth/[keys, rlp], eth/p2p/enode, eth/trie/db, eth/[keys, rlp], eth/p2p/enode, eth/trie/db,
eth/p2p/discoveryv5/[discovery_db, enr, node, types, routing_table, encoding], eth/p2p/discoveryv5/[discovery_db, enr, node, types, routing_table, encoding],
eth/p2p/discoveryv5/protocol as discv5_protocol, eth/p2p/discoveryv5/protocol as discv5_protocol,
./p2p_test_helper ./p2p_test_helper
proc initDiscoveryNode*(privKey: PrivateKey, address: Address, proc initDiscoveryNode*(privKey: PrivateKey, address: Address,
bootstrapRecords: seq[Record]): bootstrapRecords: openarray[Record] = []):
discv5_protocol.Protocol = discv5_protocol.Protocol =
var db = DiscoveryDB.init(newMemoryDB()) var db = DiscoveryDB.init(newMemoryDB())
result = newProtocol(privKey, db, result = newProtocol(privKey, db,
parseIpAddress("127.0.0.1"), some(parseIpAddress("127.0.0.1")),
address.tcpPort, address.udpPort, address.tcpPort, address.udpPort,
bootstrapRecords) bootstrapRecords)
@ -33,14 +33,16 @@ proc randomPacket(tag: PacketTag): seq[byte] =
result.add(msg) result.add(msg)
proc generateNode(privKey = newPrivateKey(), port: int): Node = proc generateNode(privKey = newPrivateKey(), port: int): Node =
let enr = enr.Record.init(1, privKey, some(localAddress(port))) let port = Port(port)
let enr = enr.Record.init(1, privKey, some(parseIpAddress("127.0.0.1")),
port, port)
result = newNode(enr) result = newNode(enr)
suite "Discovery v5 Tests": suite "Discovery v5 Tests":
asyncTest "Random nodes": asyncTest "Random nodes":
let let
bootNodeKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617") bootNodeKey = initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a617")
bootNode = initDiscoveryNode(bootNodeKey, localAddress(20301), @[]) bootNode = initDiscoveryNode(bootNodeKey, localAddress(20301))
let nodeKeys = [ let nodeKeys = [
initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618"), initPrivateKey("a2b50376a79b1a8c8a3296485572bdfbf54708bb46d3c25d73d2723aaaf6a618"),
@ -72,7 +74,7 @@ suite "Discovery v5 Tests":
const const
nodeCount = 17 nodeCount = 17
let bootNode = initDiscoveryNode(newPrivateKey(), localAddress(20301), @[]) let bootNode = initDiscoveryNode(newPrivateKey(), localAddress(20301))
bootNode.start() bootNode.start()
var nodes = newSeqOfCap[discv5_protocol.Protocol](nodeCount) var nodes = newSeqOfCap[discv5_protocol.Protocol](nodeCount)
@ -94,7 +96,7 @@ suite "Discovery v5 Tests":
asyncTest "FindNode with test table": asyncTest "FindNode with test table":
let mainNode = initDiscoveryNode(newPrivateKey(), localAddress(20301), @[]) let mainNode = initDiscoveryNode(newPrivateKey(), localAddress(20301))
# Generate 1000 random nodes and add to our main node's routing table # Generate 1000 random nodes and add to our main node's routing table
for i in 0..<1000: for i in 0..<1000:
@ -121,7 +123,7 @@ suite "Discovery v5 Tests":
asyncTest "GetNode": asyncTest "GetNode":
# TODO: This could be tested in just a routing table only context # TODO: This could be tested in just a routing table only context
let let
node = initDiscoveryNode(newPrivateKey(), localAddress(20302), @[]) node = initDiscoveryNode(newPrivateKey(), localAddress(20302))
targetNode = generateNode(port = 20303) targetNode = generateNode(port = 20303)
node.addNode(targetNode) node.addNode(targetNode)
@ -135,7 +137,7 @@ suite "Discovery v5 Tests":
asyncTest "Node deletion": asyncTest "Node deletion":
let let
bootnode = initDiscoveryNode(newPrivateKey(), localAddress(20301), @[]) bootnode = initDiscoveryNode(newPrivateKey(), localAddress(20301))
node1 = initDiscoveryNode(newPrivateKey(), localAddress(20302), node1 = initDiscoveryNode(newPrivateKey(), localAddress(20302),
@[bootnode.localNode.record]) @[bootnode.localNode.record])
node2 = initDiscoveryNode(newPrivateKey(), localAddress(20303), node2 = initDiscoveryNode(newPrivateKey(), localAddress(20303),
@ -158,7 +160,7 @@ suite "Discovery v5 Tests":
asyncTest "Handshake cleanup": asyncTest "Handshake cleanup":
let node = initDiscoveryNode(newPrivateKey(), localAddress(20302), @[]) let node = initDiscoveryNode(newPrivateKey(), localAddress(20302))
var tag: PacketTag var tag: PacketTag
let a = localAddress(20303) let a = localAddress(20303)
@ -177,7 +179,7 @@ suite "Discovery v5 Tests":
await node.closeWait() await node.closeWait()
asyncTest "Handshake different address": asyncTest "Handshake different address":
let node = initDiscoveryNode(newPrivateKey(), localAddress(20302), @[]) let node = initDiscoveryNode(newPrivateKey(), localAddress(20302))
var tag: PacketTag var tag: PacketTag
for i in 0 ..< 5: for i in 0 ..< 5:
@ -189,7 +191,7 @@ suite "Discovery v5 Tests":
await node.closeWait() await node.closeWait()
asyncTest "Handshake duplicates": asyncTest "Handshake duplicates":
let node = initDiscoveryNode(newPrivateKey(), localAddress(20302), @[]) let node = initDiscoveryNode(newPrivateKey(), localAddress(20302))
var tag: PacketTag var tag: PacketTag
let a = localAddress(20303) let a = localAddress(20303)

View File

@ -34,8 +34,7 @@ suite "ENR":
let let
keys = newKeyPair() keys = newKeyPair()
ip = parseIpAddress("10.20.30.40") ip = parseIpAddress("10.20.30.40")
enodeAddress = Address(ip: ip, tcpPort: Port 9000, udpPort: Port 9000) enr = Record.init(100, keys.seckey, some(ip), Port(9000), Port(9000))
enr = Record.init(100, keys.seckey, some(enodeAddress))
typedEnr = get enr.toTypedRecord() typedEnr = get enr.toTypedRecord()
check: check:
@ -54,7 +53,7 @@ suite "ENR":
test "ENR without address": test "ENR without address":
let let
keys = newKeyPair() keys = newKeyPair()
enr = Record.init(100, keys.seckey, none(Address)) enr = Record.init(100, keys.seckey, none(IpAddress), Port(9000), Port(9000))
typedEnr = get enr.toTypedRecord() typedEnr = get enr.toTypedRecord()
check: check:
@ -62,8 +61,12 @@ suite "ENR":
typedEnr.secp256k1.get() == keys.pubkey.getRawCompressed() typedEnr.secp256k1.get() == keys.pubkey.getRawCompressed()
typedEnr.ip.isNone() typedEnr.ip.isNone()
typedEnr.tcp.isNone() typedEnr.tcp.isSome()
typedEnr.udp.isNone() typedEnr.tcp.get() == 9000
typedEnr.udp.isSome()
typedEnr.udp.get() == 9000
typedEnr.ip6.isNone() typedEnr.ip6.isNone()
typedEnr.tcp6.isNone() typedEnr.tcp6.isNone()
typedEnr.udp6.isNone() typedEnr.udp6.isNone()