diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a25711f..56f5314 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - nim: [1.6.18] + nim: [1.6.18, 2.0.12] os: [ubuntu-latest, macOS-latest, windows-latest] steps: - name: Checkout diff --git a/.gitignore b/.gitignore index 8bda8b1..a189692 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ NimBinaries .update.timestamp *.dSYM .vscode/* +nimbledeps diff --git a/codexdht.nimble b/codexdht.nimble index 0f89769..52f6d59 100644 --- a/codexdht.nimble +++ b/codexdht.nimble @@ -1,6 +1,6 @@ # Package -version = "0.4.0" +version = "0.5.0" author = "Status Research & Development GmbH" description = "DHT based on Eth discv5 implementation" license = "MIT" @@ -8,17 +8,17 @@ skipDirs = @["tests"] # Dependencies requires "secp256k1#2acbbdcc0e63002a013fff49f015708522875832" # >= 0.5.2 & < 0.6.0 -requires "protobuf_serialization" # >= 0.2.0 & < 0.3.0 +requires "protobuf_serialization#5a31137a82c2b6a989c9ed979bb636c7a49f570e" # >= 0.2.0 & < 0.3.0 requires "nimcrypto >= 0.5.4" requires "bearssl == 0.2.5" requires "chronicles >= 0.10.2 & < 0.11.0" requires "chronos >= 4.0.3 & < 4.1.0" requires "libp2p == 1.5.0" -requires "metrics" -requires "stew#head" -requires "stint" -requires "https://github.com/codex-storage/nim-datastore >= 0.1.1 & < 0.2.0" -requires "questionable" +requires "metrics#cacfdc12454a0804c65112b9f4f50d1375208dcd" +requires "stew >= 0.2.0" +requires "stint#3236fa68394f1e3a06e2bc34218aacdd2d675923" +requires "https://github.com/codex-storage/nim-datastore#b5635ef82f50255bc5ff2fe411722d870bcb587c" +requires "questionable >= 0.10.15 & < 0.11.0" task testAll, "Run all test suites": exec "nimble install -d -y" diff --git a/codexdht/private/eth/p2p/discoveryv5/node.nim b/codexdht/private/eth/p2p/discoveryv5/node.nim index 2f3d6c9..442d551 100644 --- a/codexdht/private/eth/p2p/discoveryv5/node.nim +++ b/codexdht/private/eth/p2p/discoveryv5/node.nim @@ -28,7 +28,7 @@ type NodeId* = UInt256 Address* = object - ip*: ValidIpAddress + ip*: IpAddress port*: Port Stats* = object @@ -69,7 +69,7 @@ func newNode*( id: ? pk.toNodeId(), pubkey: pk, record: record, - address: Address(ip: ValidIpAddress.init(ip), port: port).some) + address: Address(ip: ip, port: port).some) ok node @@ -103,7 +103,7 @@ func newNode*(r: SignedPeerRecord): Result[Node, cstring] = record: r, address: none(Address))) -proc update*(n: Node, pk: PrivateKey, ip: Option[ValidIpAddress], +proc update*(n: Node, pk: PrivateKey, ip: Option[IpAddress], tcpPort, udpPort: Option[Port] = none[Port]()): Result[void, cstring] = ? n.record.update(pk, ip, tcpPort, udpPort) @@ -154,7 +154,7 @@ func shortLog*(id: NodeId): string = result.add(sid[i]) chronicles.formatIt(NodeId): shortLog(it) -func hash*(ip: ValidIpAddress): Hash = +func hash*(ip: IpAddress): Hash = case ip.family of IpAddressFamily.IPv6: hash(ip.address_v6) of IpAddressFamily.IPv4: hash(ip.address_v4) diff --git a/codexdht/private/eth/p2p/discoveryv5/protocol.nim b/codexdht/private/eth/p2p/discoveryv5/protocol.nim index 77afee3..807e9a1 100644 --- a/codexdht/private/eth/p2p/discoveryv5/protocol.nim +++ b/codexdht/private/eth/p2p/discoveryv5/protocol.nim @@ -236,18 +236,18 @@ proc getNode*(d: Protocol, id: NodeId): Option[Node] = ## Get the node with id from the routing table. d.routingTable.getNode(id) -proc randomNodes*(d: Protocol, maxAmount: int): seq[Node] = +proc randomNodes*(d: Protocol, maxAmount: int): seq[Node] {.raises: Exception.} = ## Get a `maxAmount` of random nodes from the local routing table. d.routingTable.randomNodes(maxAmount) proc randomNodes*(d: Protocol, maxAmount: int, - pred: proc(x: Node): bool {.gcsafe, noSideEffect.}): seq[Node] = + pred: proc(x: Node): bool {.gcsafe, noSideEffect.}): seq[Node] {.raises: Exception.} = ## Get a `maxAmount` of random nodes from the local routing table with the ## `pred` predicate function applied as filter on the nodes selected. d.routingTable.randomNodes(maxAmount, pred) proc randomNodes*(d: Protocol, maxAmount: int, - enrField: (string, seq[byte])): seq[Node] = + enrField: (string, seq[byte])): seq[Node] {.raises: Exception.} = ## Get a `maxAmount` of random nodes from the local routing table. The ## the nodes selected are filtered by provided `enrField`. d.randomNodes(maxAmount, proc(x: Node): bool = x.record.contains(enrField)) @@ -963,7 +963,7 @@ proc revalidateNode*(d: Protocol, n: Node) {.async.} = # Get IP and port from pong message and add it to the ip votes trace "pong rx", n, myip = res.ip, myport = res.port - let a = Address(ip: ValidIpAddress.init(res.ip), port: Port(res.port)) + let a = Address(ip: res.ip, port: Port(res.port)) d.ipVote.insert(n.id, a) proc revalidateLoop(d: Protocol) {.async.} = @@ -1076,7 +1076,7 @@ func init*( proc newProtocol*( privKey: PrivateKey, - enrIp: Option[ValidIpAddress], + enrIp: Option[IpAddress], enrTcpPort, enrUdpPort: Option[Port], localEnrFields: openArray[(string, seq[byte])] = [], bootstrapRecords: openArray[SignedPeerRecord] = [], diff --git a/codexdht/private/eth/p2p/discoveryv5/routing_table.nim b/codexdht/private/eth/p2p/discoveryv5/routing_table.nim index edc9e65..8239ee4 100644 --- a/codexdht/private/eth/p2p/discoveryv5/routing_table.nim +++ b/codexdht/private/eth/p2p/discoveryv5/routing_table.nim @@ -34,7 +34,7 @@ type IpLimits* = object limit*: uint - ips: Table[ValidIpAddress, uint] + ips: Table[IpAddress, uint] RoutingTable* = object @@ -101,7 +101,7 @@ type ReplacementExisting NoAddress -func inc*(ipLimits: var IpLimits, ip: ValidIpAddress): bool = +func inc*(ipLimits: var IpLimits, ip: IpAddress): bool = let val = ipLimits.ips.getOrDefault(ip, 0) if val < ipLimits.limit: ipLimits.ips[ip] = val + 1 @@ -109,7 +109,7 @@ func inc*(ipLimits: var IpLimits, ip: ValidIpAddress): bool = else: false -func dec*(ipLimits: var IpLimits, ip: ValidIpAddress) = +func dec*(ipLimits: var IpLimits, ip: IpAddress) = let val = ipLimits.ips.getOrDefault(ip, 0) if val == 1: ipLimits.ips.del(ip) @@ -555,7 +555,7 @@ proc nodeToRevalidate*(r: RoutingTable): Node = return b.nodes[^1] proc randomNodes*(r: RoutingTable, maxAmount: int, - pred: proc(x: Node): bool {.gcsafe, noSideEffect.} = nil): seq[Node] = + pred: proc(x: Node): bool {.gcsafe, noSideEffect.} = nil): seq[Node] {.raises: Exception.} = ## Get a `maxAmount` of random nodes from the routing table with the `pred` ## predicate function applied as filter on the nodes selected. var maxAmount = maxAmount diff --git a/codexdht/private/eth/p2p/discoveryv5/spr.nim b/codexdht/private/eth/p2p/discoveryv5/spr.nim index 15c6c2a..351b8a7 100644 --- a/codexdht/private/eth/p2p/discoveryv5/spr.nim +++ b/codexdht/private/eth/p2p/discoveryv5/spr.nim @@ -58,7 +58,7 @@ proc incSeqNo*( proc update*( r: var SignedPeerRecord, pk: crypto.PrivateKey, - ip: Option[ValidIpAddress], + ip: Option[IpAddress], tcpPort, udpPort: Option[Port] = none[Port]()): RecordResult[void] = ## Update a `SignedPeerRecord` with given ip address, tcp port, udp port and optional @@ -97,9 +97,8 @@ proc update*( if udpPort.isNone and tcpPort.isNone: return err "No existing address in SignedPeerRecord with no port provided" - let ipAddr = try: ValidIpAddress.init(ip.get) - except ValueError as e: - return err ("Existing address contains invalid address: " & $e.msg).cstring + let ipAddr = ip.get + if tcpPort.isSome: transProto = IpTransportProtocol.tcpProtocol transProtoPort = tcpPort.get @@ -223,7 +222,7 @@ proc init*( T: type SignedPeerRecord, seqNum: uint64, pk: PrivateKey, - ip: Option[ValidIpAddress], + ip: Option[IpAddress], tcpPort, udpPort: Option[Port]): RecordResult[T] = ## Initialize a `SignedPeerRecord` with given sequence number, private key, optional @@ -238,9 +237,7 @@ proc init*( tcpPort, udpPort var - ipAddr = try: ValidIpAddress.init("127.0.0.1") - except ValueError as e: - return err ("Existing address contains invalid address: " & $e.msg).cstring + ipAddr = static parseIpAddress("127.0.0.1") proto: IpTransportProtocol protoPort: Port diff --git a/codexdht/private/eth/p2p/discoveryv5/transport.nim b/codexdht/private/eth/p2p/discoveryv5/transport.nim index 04fe20c..e1dac60 100644 --- a/codexdht/private/eth/p2p/discoveryv5/transport.nim +++ b/codexdht/private/eth/p2p/discoveryv5/transport.nim @@ -259,7 +259,7 @@ proc processClient[T](transp: DatagramTransport, raddr: TransportAddress): except ValueError as e: error "Not a valid IpAddress", exception = e.name, msg = e.msg return - let a = Address(ip: ValidIpAddress.init(ip), port: raddr.port) + let a = Address(ip: ip, port: raddr.port) t.receive(a, buf) @@ -292,7 +292,7 @@ proc newTransport*[T]( Transport[T]( client: client, - bindAddress: Address(ip: ValidIpAddress.init(bindIp), port: bindPort), + bindAddress: Address(ip: bindIp, port: bindPort), codec: Codec( localNode: localNode, privKey: privKey, diff --git a/config.nims b/config.nims index eacae8d..d816c1a 100644 --- a/config.nims +++ b/config.nims @@ -1,2 +1,9 @@ switch("define", "libp2p_pki_schemes=secp256k1") +# begin Nimble config (version 2) +when withDir(thisDir(), system.fileExists("nimble.paths")): + include "nimble.paths" +# end Nimble config + +when (NimMajor, NimMinor) >= (2, 0): + --mm:refc diff --git a/tests/dht/test_helper.nim b/tests/dht/test_helper.nim index 3d92b96..f841b7e 100644 --- a/tests/dht/test_helper.nim +++ b/tests/dht/test_helper.nim @@ -4,14 +4,10 @@ import libp2p/crypto/[crypto, secp], libp2p/multiaddress, codexdht/discv5/[node, routing_table, spr], - codexdht/discv5/crypto as dhtcrypto, - codexdht/discv5/protocol as discv5_protocol, - stew/shims/net - -export net + codexdht/discv5/protocol as discv5_protocol proc localAddress*(port: int): Address = - Address(ip: ValidIpAddress.init("127.0.0.1"), port: Port(port)) + Address(ip: parseIpAddress("127.0.0.1"), port: Port(port)) proc example*(T: type PrivateKey, rng: ref HmacDrbgContext): PrivateKey = PrivateKey.random(PKScheme.Secp256k1, rng[]).expect("Valid rng for private key") @@ -54,7 +50,7 @@ proc nodeIdInNodes*(id: NodeId, nodes: openArray[Node]): bool = if id == n.id: return true proc generateNode*(privKey: PrivateKey, port: int, - ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): Node = + ip: IpAddress = parseIpAddress("127.0.0.1")): Node = let port = Port(port) @@ -72,7 +68,7 @@ proc generateNRandomNodes*(rng: ref HmacDrbgContext, n: int): seq[Node] = res proc nodeAndPrivKeyAtDistance*(n: Node, rng: var HmacDrbgContext, d: uint32, - ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): (Node, PrivateKey) = + ip: IpAddress = parseIpAddress("127.0.0.1")): (Node, PrivateKey) = while true: let privKey = PrivateKey.random(rng).expect("Valid rng for private key") @@ -81,23 +77,23 @@ proc nodeAndPrivKeyAtDistance*(n: Node, rng: var HmacDrbgContext, d: uint32, return (node, privKey) proc nodeAtDistance*(n: Node, rng: var HmacDrbgContext, d: uint32, - ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): Node = + ip: IpAddress = parseIpAddress("127.0.0.1")): Node = let (node, _) = n.nodeAndPrivKeyAtDistance(rng, d, ip) node proc nodesAtDistance*( n: Node, rng: var HmacDrbgContext, d: uint32, amount: int, - ip: ValidIpAddress = ValidIpAddress.init("127.0.0.1")): seq[Node] = + ip: IpAddress = parseIpAddress("127.0.0.1")): seq[Node] = for i in 0..