diff --git a/.gitmodules b/.gitmodules index 1b005cb05..cdf466973 100644 --- a/.gitmodules +++ b/.gitmodules @@ -110,3 +110,13 @@ path = vendor/rln url = https://github.com/kilic/rln branch = full-node +[submodule "vendor/nim-testutils"] + path = vendor/nim-testutils + url = https://github.com/status-im/nim-testutils.git + ignore = untracked + branch = master +[submodule "vendor/nim-unittest2"] + path = vendor/nim-unittest2 + url = https://github.com/status-im/nim-unittest2.git + ignore = untracked + branch = master diff --git a/examples/v1/example.nim b/examples/v1/example.nim index 9121adab9..2fe4f150c 100644 --- a/examples/v1/example.nim +++ b/examples/v1/example.nim @@ -10,99 +10,103 @@ import const clientId = "Waku example v1" -let - # Load the cli configuration from `config_example.nim`. - config = WakuNodeConf.load() - # Seed the rng. - rng = keys.newRng() +proc run(config: WakuNodeConf, rng: ref BrHmacDrbgContext) = # Set up the address according to NAT information. - (ipExt, tcpPortExt, udpPortExt) = setupNat(config.nat, clientId, + let (ipExt, tcpPortExt, udpPortExt) = setupNat(config.nat, clientId, Port(config.tcpPort + config.portsShift), Port(config.udpPort + config.portsShift)) # TODO: EthereumNode should have a better split of binding address and # external address. Also, can't have different ports as it stands now. - address = if ipExt.isNone(): - Address(ip: parseIpAddress("0.0.0.0"), - tcpPort: Port(config.tcpPort + config.portsShift), - udpPort: Port(config.udpPort + config.portsShift)) - else: - Address(ip: ipExt.get(), - tcpPort: Port(config.tcpPort + config.portsShift), - udpPort: Port(config.udpPort + config.portsShift)) + let address = if ipExt.isNone(): + Address(ip: parseIpAddress("0.0.0.0"), + tcpPort: Port(config.tcpPort + config.portsShift), + udpPort: Port(config.udpPort + config.portsShift)) + else: + Address(ip: ipExt.get(), + tcpPort: Port(config.tcpPort + config.portsShift), + udpPort: Port(config.udpPort + config.portsShift)) -# Create Ethereum Node -var node = newEthereumNode(config.nodekey, # Node identifier - address, # Address reachable for incoming requests - NetworkId(1), # Network Id, only applicable for ETH protocol - nil, # Database, not required for Waku - clientId, # Client id string - addAllCapabilities = false, # Disable default all RLPx capabilities - rng = rng) + # Create Ethereum Node + var node = newEthereumNode(config.nodekey, # Node identifier + address, # Address reachable for incoming requests + NetworkId(1), # Network Id, only applicable for ETH protocol + nil, # Database, not required for Waku + clientId, # Client id string + addAllCapabilities = false, # Disable default all RLPx capabilities + rng = rng) -node.addCapability Waku # Enable only the Waku protocol. + node.addCapability Waku # Enable only the Waku protocol. -# Set up the Waku configuration. -let wakuConfig = WakuConfig(powRequirement: 0.002, - bloom: some(fullBloom()), # Full bloom filter - isLightNode: false, # Full node - maxMsgSize: waku_protocol.defaultMaxMsgSize, - topics: none(seq[waku_protocol.Topic]) # empty topic interest - ) -node.configureWaku(wakuConfig) + # Set up the Waku configuration. + let wakuConfig = WakuConfig(powRequirement: 0.002, + bloom: some(fullBloom()), # Full bloom filter + isLightNode: false, # Full node + maxMsgSize: waku_protocol.defaultMaxMsgSize, + topics: none(seq[waku_protocol.Topic]) # empty topic interest + ) + node.configureWaku(wakuConfig) -# Optionally direct connect to a set of nodes. -if config.staticnodes.len > 0: - connectToNodes(node, config.staticnodes) + # Optionally direct connect to a set of nodes. + if config.staticnodes.len > 0: + connectToNodes(node, config.staticnodes) -# Connect to the network, which will make the node start listening and/or -# connect to bootnodes, and/or start discovery. -# This will block until first connection is made, which in this case can only -# happen if we directly connect to nodes (step above) or if an incoming -# connection occurs, which is why we use a callback to exit on errors instead of -# using `await`. -# TODO: This looks a bit awkward and the API should perhaps be altered here. -let connectedFut = node.connectToNetwork(@[], - true, # Enable listening - false # Disable discovery (only discovery v4 is currently supported) - ) -connectedFut.callback = proc(data: pointer) {.gcsafe.} = - {.gcsafe.}: - if connectedFut.failed: - fatal "connectToNetwork failed", msg = connectedFut.readError.msg - quit(1) + # Connect to the network, which will make the node start listening and/or + # connect to bootnodes, and/or start discovery. + # This will block until first connection is made, which in this case can only + # happen if we directly connect to nodes (step above) or if an incoming + # connection occurs, which is why we use a callback to exit on errors instead of + # using `await`. + # TODO: This looks a bit awkward and the API should perhaps be altered here. + let connectedFut = node.connectToNetwork(@[], + true, # Enable listening + false # Disable discovery (only discovery v4 is currently supported) + ) + connectedFut.callback = proc(data: pointer) {.gcsafe.} = + {.gcsafe.}: + if connectedFut.failed: + fatal "connectToNetwork failed", msg = connectedFut.readError.msg + quit(1) -# Using a hardcoded symmetric key for encryption of the payload for the sake of -# simplicity. -var symKey: SymKey -symKey[31] = 1 -# Asymmetric keypair to sign the payload. -let signKeyPair = KeyPair.random(rng[]) + # Using a hardcoded symmetric key for encryption of the payload for the sake of + # simplicity. + var symKey: SymKey + symKey[31] = 1 + # Asymmetric keypair to sign the payload. + let signKeyPair = KeyPair.random(rng[]) -# Code to be executed on receival of a message on filter. -proc handler(msg: ReceivedMessage) = - if msg.decoded.src.isSome(): - echo "Received message from ", $msg.decoded.src.get(), ": ", - string.fromBytes(msg.decoded.payload) + # Code to be executed on receival of a message on filter. + proc handler(msg: ReceivedMessage) = + if msg.decoded.src.isSome(): + echo "Received message from ", $msg.decoded.src.get(), ": ", + string.fromBytes(msg.decoded.payload) -# Create and subscribe filter with above handler. -let - topic = [byte 0, 0, 0, 0] - filter = initFilter(symKey = some(symKey), topics = @[topic]) -discard node.subscribeFilter(filter, handler) + # Create and subscribe filter with above handler. + let + topic = [byte 0, 0, 0, 0] + filter = initFilter(symKey = some(symKey), topics = @[topic]) + discard node.subscribeFilter(filter, handler) -# Repeat the posting of a message every 5 seconds. -proc repeatMessage(udata: pointer) {.gcsafe.} = - {.gcsafe.}: - # Post a waku message on the network, encrypted with provided symmetric key, - # signed with asymmetric key, on topic and with ttl of 30 seconds. - let posted = node.postMessage( - symKey = some(symKey), src = some(signKeyPair.seckey), - ttl = 30, topic = topic, payload = @[byte 0x48, 0x65, 0x6C, 0x6C, 0x6F]) + # Repeat the posting of a message every 5 seconds. + # https://github.com/nim-lang/Nim/issues/17369 + var repeatMessage: proc(udata: pointer) {.gcsafe, raises: [Defect].} + repeatMessage = proc(udata: pointer) = + {.gcsafe.}: + # Post a waku message on the network, encrypted with provided symmetric key, + # signed with asymmetric key, on topic and with ttl of 30 seconds. + let posted = node.postMessage( + symKey = some(symKey), src = some(signKeyPair.seckey), + ttl = 30, topic = topic, payload = @[byte 0x48, 0x65, 0x6C, 0x6C, 0x6F]) - if posted: echo "Posted message as ", $signKeyPair.pubkey - else: echo "Posting message failed." + if posted: echo "Posted message as ", $signKeyPair.pubkey + else: echo "Posting message failed." + discard setTimer(Moment.fromNow(5.seconds), repeatMessage) discard setTimer(Moment.fromNow(5.seconds), repeatMessage) -discard setTimer(Moment.fromNow(5.seconds), repeatMessage) -runForever() + runForever() + +when isMainModule: + let + rng = keys.newRng() + conf = WakuNodeConf.load() + run(conf, rng) diff --git a/tests/test_helpers.nim b/tests/test_helpers.nim index ad745d19c..9acb2311f 100644 --- a/tests/test_helpers.nim +++ b/tests/test_helpers.nim @@ -1,5 +1,5 @@ import - unittest, chronos, bearssl, + chronos, bearssl, eth/[keys, p2p] import libp2p/crypto/crypto @@ -21,18 +21,6 @@ proc setupTestNode*( for capability in capabilities: result.addCapability capability -template asyncTest*(name, body: untyped) = - test name: - proc scenario {.async.} = body - waitFor scenario() - -template procSuite*(name, body: untyped) = - proc suitePayload = - suite name: - body - - suitePayload() - # Copied from here: https://github.com/status-im/nim-libp2p/blob/d522537b19a532bc4af94fcd146f779c1f23bad0/tests/helpers.nim#L28 type RngWrap = object rng: ref BrHmacDrbgContext diff --git a/tests/v1/test_waku_bridge.nim b/tests/v1/test_waku_bridge.nim index 0defd56db..aab6d7090 100644 --- a/tests/v1/test_waku_bridge.nim +++ b/tests/v1/test_waku_bridge.nim @@ -9,8 +9,8 @@ {.used.} import - std/[sequtils, unittest, tables], - chronos, eth/p2p, eth/p2p/peer_pool, + std/[sequtils, tables], + chronos, testutils/unittests, eth/p2p, eth/p2p/peer_pool, eth/p2p/rlpx_protocols/whisper_protocol as whisper, ../../waku/v1/protocol/waku_protocol as waku, ../../waku/v1/protocol/waku_bridge, diff --git a/tests/v1/test_waku_connect.nim b/tests/v1/test_waku_connect.nim index e045da5cc..06ef897d9 100644 --- a/tests/v1/test_waku_connect.nim +++ b/tests/v1/test_waku_connect.nim @@ -9,8 +9,8 @@ {.used.} import - std/[sequtils, tables, unittest], - chronos, eth/[keys, p2p], eth/p2p/peer_pool, + std/[sequtils, tables], + chronos, testutils/unittests, eth/[keys, p2p], eth/p2p/peer_pool, ../../waku/v1/protocol/waku_protocol, ../test_helpers diff --git a/tests/v1/test_waku_mail.nim b/tests/v1/test_waku_mail.nim index 3df1d23cc..e53c6b850 100644 --- a/tests/v1/test_waku_mail.nim +++ b/tests/v1/test_waku_mail.nim @@ -1,8 +1,8 @@ {.used.} import - std/[unittest, tables, sequtils, times], - chronos, eth/[p2p, async_utils], eth/p2p/peer_pool, + std/[tables, sequtils, times], + chronos, testutils/unittests, eth/[p2p, async_utils], eth/p2p/peer_pool, ../../waku/v1/protocol/[waku_protocol, waku_mail], ../test_helpers diff --git a/tests/v2/test_jsonrpc_waku.nim b/tests/v2/test_jsonrpc_waku.nim index 43e497595..a82ffe483 100644 --- a/tests/v2/test_jsonrpc_waku.nim +++ b/tests/v2/test_jsonrpc_waku.nim @@ -1,8 +1,8 @@ {.used.} import - std/[unittest, options, sets, tables, os, strutils, sequtils], - stew/shims/net as stewNet, + std/[options, sets, tables, os, strutils, sequtils], + testutils/unittests, stew/shims/net as stewNet, json_rpc/[rpcserver, rpcclient], eth/[keys, rlp], eth/common/eth_types, libp2p/[standard_setup, switch, multiaddress], diff --git a/tests/v2/test_peer_manager.nim b/tests/v2/test_peer_manager.nim index ad0516720..6007d5f9c 100644 --- a/tests/v2/test_peer_manager.nim +++ b/tests/v2/test_peer_manager.nim @@ -1,8 +1,8 @@ {.used.} import - std/[unittest, options, sets, tables, sequtils], - stew/shims/net as stewNet, + std/[options, sets, tables, sequtils], + testutils/unittests, stew/shims/net as stewNet, json_rpc/[rpcserver, rpcclient], eth/[keys, rlp], eth/common/eth_types, libp2p/[standard_setup, switch, multiaddress], diff --git a/tests/v2/test_waku_bridge.nim b/tests/v2/test_waku_bridge.nim index 0426e61d0..c0243154d 100644 --- a/tests/v2/test_waku_bridge.nim +++ b/tests/v2/test_waku_bridge.nim @@ -1,7 +1,8 @@ {.used.} import - std/[unittest, strutils], + std/strutils, + testutils/unittests, chronicles, chronos, stew/shims/net as stewNet, stew/byteutils, libp2p/crypto/crypto, libp2p/crypto/secp, diff --git a/tests/v2/test_waku_filter.nim b/tests/v2/test_waku_filter.nim index 96e2fdd89..2cc3fdc4c 100644 --- a/tests/v2/test_waku_filter.nim +++ b/tests/v2/test_waku_filter.nim @@ -1,8 +1,8 @@ {.used.} import - std/[unittest, options, tables, sets], - chronos, chronicles, + std/[options, tables, sets], + testutils/unittests, chronos, chronicles, libp2p/switch, libp2p/protobuf/minprotobuf, libp2p/stream/[bufferstream, connection], diff --git a/tests/v2/test_waku_pagination.nim b/tests/v2/test_waku_pagination.nim index a30eddf68..e2c88ca2f 100644 --- a/tests/v2/test_waku_pagination.nim +++ b/tests/v2/test_waku_pagination.nim @@ -1,7 +1,7 @@ {.used.} import - std/[unittest,algorithm,options], - nimcrypto/sha2, + std/[algorithm, options], + testutils/unittests, nimcrypto/sha2, ../../waku/v2/protocol/waku_store/waku_store, ../test_helpers diff --git a/tests/v2/test_waku_payload.nim b/tests/v2/test_waku_payload.nim index 5674ce10d..d57ddadaf 100644 --- a/tests/v2/test_waku_payload.nim +++ b/tests/v2/test_waku_payload.nim @@ -1,7 +1,7 @@ {.used.} import - std/unittest, + testutils/unittests, ../../waku/v2/protocol/waku_message, ../../waku/v2/node/waku_payload, ../test_helpers diff --git a/tests/v2/test_waku_rln_relay.nim b/tests/v2/test_waku_rln_relay.nim index 6b1c52ec1..b1a8085f5 100644 --- a/tests/v2/test_waku_rln_relay.nim +++ b/tests/v2/test_waku_rln_relay.nim @@ -1,17 +1,14 @@ {.used.} import - chronos, chronicles, options, stint, unittest, - web3, + std/options, + testutils/unittests, chronos, chronicles, stint, web3, stew/byteutils, stew/shims/net as stewNet, libp2p/crypto/crypto, ../../waku/v2/protocol/waku_rln_relay/[rln, waku_rln_relay_utils], ../../waku/v2/node/wakunode2, ../test_helpers, - test_utils - - - + ./test_utils # the address of Ethereum client (ganache-cli for now) # TODO this address in hardcoded in the code, we may need to take it as input from the user diff --git a/tests/v2/test_waku_store.nim b/tests/v2/test_waku_store.nim index 5f112a348..205951ed0 100644 --- a/tests/v2/test_waku_store.nim +++ b/tests/v2/test_waku_store.nim @@ -1,8 +1,8 @@ {.used.} import - std/[unittest, options, tables, sets], - chronos, chronicles, + std/[options, tables, sets], + testutils/unittests, chronos, chronicles, libp2p/switch, libp2p/protobuf/minprotobuf, libp2p/stream/[bufferstream, connection], diff --git a/tests/v2/test_waku_swap.nim b/tests/v2/test_waku_swap.nim index 427f380c2..f2fcfed75 100644 --- a/tests/v2/test_waku_swap.nim +++ b/tests/v2/test_waku_swap.nim @@ -1,7 +1,8 @@ {.used.} import - std/[unittest, options, tables, sets], + std/[options, tables, sets], + testutils/unittests, chronos, chronicles, stew/shims/net as stewNet, stew/byteutils, libp2p/switch, libp2p/protobuf/minprotobuf, diff --git a/tests/v2/test_wakunode.nim b/tests/v2/test_wakunode.nim index 5b89e59dd..1f3f90a26 100644 --- a/tests/v2/test_wakunode.nim +++ b/tests/v2/test_wakunode.nim @@ -1,7 +1,7 @@ {.used.} import - std/unittest, + testutils/unittests, chronicles, chronos, stew/shims/net as stewNet, stew/byteutils, libp2p/crypto/crypto, libp2p/crypto/secp, diff --git a/vendor/nim-chronicles b/vendor/nim-chronicles index b42899070..8b1419b4a 160000 --- a/vendor/nim-chronicles +++ b/vendor/nim-chronicles @@ -1 +1 @@ -Subproject commit b42899070a7daa5cf6f0843faf3d6d41659e9591 +Subproject commit 8b1419b4a37a3a8995a9a0a992b4705427056d98 diff --git a/vendor/nim-chronos b/vendor/nim-chronos index 0b78606e4..c206d2bc1 160000 --- a/vendor/nim-chronos +++ b/vendor/nim-chronos @@ -1 +1 @@ -Subproject commit 0b78606e4142affbdc0e0e94bc1b8c39a8705737 +Subproject commit c206d2bc191712e4e5f89ecd87df7ef014bbb484 diff --git a/vendor/nim-confutils b/vendor/nim-confutils index cfa956619..f091a70a5 160000 --- a/vendor/nim-confutils +++ b/vendor/nim-confutils @@ -1 +1 @@ -Subproject commit cfa95661913b0ff8b1609e3954894f8ab31bbf3e +Subproject commit f091a70a5bf95ec772c8b4d9978e81b8ae89af0c diff --git a/vendor/nim-eth b/vendor/nim-eth index be5e088b2..8c27f291f 160000 --- a/vendor/nim-eth +++ b/vendor/nim-eth @@ -1 +1 @@ -Subproject commit be5e088b21e06a85cac4826454412db8459ed4f1 +Subproject commit 8c27f291f535f261274be9f69de1216981ac93e4 diff --git a/vendor/nim-http-utils b/vendor/nim-http-utils index 422026688..613ad40f0 160000 --- a/vendor/nim-http-utils +++ b/vendor/nim-http-utils @@ -1 +1 @@ -Subproject commit 422026688405940a1304d5cdaf68353d93263035 +Subproject commit 613ad40f00ab3d0ee839f9db9c4d25e5e0248dee diff --git a/vendor/nim-json-serialization b/vendor/nim-json-serialization index 7999d2522..fe8a82ca7 160000 --- a/vendor/nim-json-serialization +++ b/vendor/nim-json-serialization @@ -1 +1 @@ -Subproject commit 7999d2522565d88499b9d7f99c4175a8eb3f2b41 +Subproject commit fe8a82ca76150b60a950d5aa4e5baa382441ada4 diff --git a/vendor/nim-libp2p b/vendor/nim-libp2p index 3bf6acef2..df497660b 160000 --- a/vendor/nim-libp2p +++ b/vendor/nim-libp2p @@ -1 +1 @@ -Subproject commit 3bf6acef2348162448b1b988a2ba06f0f2e10103 +Subproject commit df497660bcf7aa23005f22aa7daced15b5668e3a diff --git a/vendor/nim-serialization b/vendor/nim-serialization index 261de741b..f9a1121b8 160000 --- a/vendor/nim-serialization +++ b/vendor/nim-serialization @@ -1 +1 @@ -Subproject commit 261de741b73601821cb6e749fc9b4092f1cc5377 +Subproject commit f9a1121b8733eb75e624ab59f8d79e707f15f76f diff --git a/vendor/nim-stew b/vendor/nim-stew index 6bcb21184..ee78822e0 160000 --- a/vendor/nim-stew +++ b/vendor/nim-stew @@ -1 +1 @@ -Subproject commit 6bcb21184aeb96ce6c62e187a64d678b74609f1e +Subproject commit ee78822e057ac5f39804ecb6ac1096734be13ef8 diff --git a/vendor/nim-testutils b/vendor/nim-testutils new file mode 160000 index 000000000..6d76fc5e5 --- /dev/null +++ b/vendor/nim-testutils @@ -0,0 +1 @@ +Subproject commit 6d76fc5e51ce6580289e872558a3b858775e310f diff --git a/vendor/nim-unittest2 b/vendor/nim-unittest2 new file mode 160000 index 000000000..e788deab3 --- /dev/null +++ b/vendor/nim-unittest2 @@ -0,0 +1 @@ +Subproject commit e788deab3d59ff8a4fe103aeb5d82d3d82fcac7d diff --git a/waku/v1/node/wakunode1.nim b/waku/v1/node/wakunode1.nim index a98163f3b..3eeaa6b30 100644 --- a/waku/v1/node/wakunode1.nim +++ b/waku/v1/node/wakunode1.nim @@ -83,7 +83,9 @@ proc run(config: WakuNodeConf, rng: ref BrHmacDrbgContext) = if config.logAccounting: - proc logPeerAccounting(udata: pointer) {.closure, gcsafe.} = + # https://github.com/nim-lang/Nim/issues/17369 + var logPeerAccounting: proc(udata: pointer) {.gcsafe, raises: [Defect].} + logPeerAccounting = proc(udata: pointer) = {.gcsafe.}: for peer in node.peerPool.peers: let @@ -105,7 +107,9 @@ proc run(config: WakuNodeConf, rng: ref BrHmacDrbgContext) = metrics.startHttpServer($address, Port(port)) if config.logMetrics: - proc logMetrics(udata: pointer) {.closure, gcsafe.} = + # https://github.com/nim-lang/Nim/issues/17369 + var logMetrics: proc(udata: pointer) {.gcsafe, raises: [Defect].} + logMetrics = proc(udata: pointer) = {.gcsafe.}: let connectedPeers = connected_peers diff --git a/waku/v2/node/wakunode2.nim b/waku/v2/node/wakunode2.nim index 009021eb7..228bf17b2 100644 --- a/waku/v2/node/wakunode2.nim +++ b/waku/v2/node/wakunode2.nim @@ -517,7 +517,9 @@ when isMainModule: metrics.startHttpServer($serverIp, serverPort) proc startMetricsLog() = - proc logMetrics(udata: pointer) {.closure, gcsafe.} = + # https://github.com/nim-lang/Nim/issues/17369 + var logMetrics: proc(udata: pointer) {.gcsafe, raises: [Defect].} + logMetrics = proc(udata: pointer) = {.gcsafe.}: # TODO: libp2p_pubsub_peers is not public, so we need to make this either # public in libp2p or do our own peer counting after all. @@ -525,7 +527,10 @@ when isMainModule: totalMessages = 0.float64 for key in waku_node_messages.metrics.keys(): - totalMessages = totalMessages + waku_node_messages.value(key) + try: + totalMessages = totalMessages + waku_node_messages.value(key) + except KeyError: + discard info "Node metrics", totalMessages discard setTimer(Moment.fromNow(2.seconds), logMetrics)