diff --git a/apps/chat2/chat2.nim b/apps/chat2/chat2.nim index 5ceb87fbb..990ced449 100644 --- a/apps/chat2/chat2.nim +++ b/apps/chat2/chat2.nim @@ -370,10 +370,12 @@ proc readInput(wfd: AsyncFD) {.thread, raises: [Defect, CatchableError].} = discard waitFor transp.write(line & "\r\n") {.pop.} # @TODO confutils.nim(775, 17) Error: can raise an unlisted exception: ref IOError -proc processInput(rfd: AsyncFD) {.async.} = +proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} = let transp = fromPipe(rfd) conf = Chat2Conf.load() + nodekey = if conf.nodekey.isSome(): conf.nodekey.get() + else: PrivateKey.random(Secp256k1, rng[]).tryGet() # set log level if conf.logLevel != LogLevel.NONE: @@ -383,7 +385,7 @@ proc processInput(rfd: AsyncFD) {.async.} = (extIp, extTcpPort, extUdpPort) = setupNat(conf.nat, clientId, Port(uint16(conf.tcpPort) + conf.portsShift), Port(uint16(conf.udpPort) + conf.portsShift)) - node = WakuNode.new(conf.nodekey, conf.listenAddress, + node = WakuNode.new(nodekey, conf.listenAddress, Port(uint16(conf.tcpPort) + conf.portsShift), extIp, extTcpPort, wsBindPort = Port(uint16(conf.websocketPort) + conf.portsShift), @@ -593,7 +595,7 @@ proc processInput(rfd: AsyncFD) {.async.} = runForever() -proc main() {.async.} = +proc main(rng: ref HmacDrbgContext) {.async.} = let (rfd, wfd) = createAsyncPipe() if rfd == asyncInvalidPipe or wfd == asyncInvalidPipe: raise newException(ValueError, "Could not initialize pipe!") @@ -601,7 +603,7 @@ proc main() {.async.} = var thread: Thread[AsyncFD] thread.createThread(readInput, wfd) try: - await processInput(rfd) + await processInput(rfd, rng) # Handle only ConfigurationError for now # TODO: Throw other errors from the mounting procedure except ConfigurationError as e: @@ -609,8 +611,9 @@ proc main() {.async.} = when isMainModule: # isMainModule = true when the module is compiled as the main file + let rng = crypto.newRng() try: - waitFor(main()) + waitFor(main(rng)) except CatchableError as e: raise e diff --git a/apps/chat2/config_chat2.nim b/apps/chat2/config_chat2.nim index f326a22bb..808f21464 100644 --- a/apps/chat2/config_chat2.nim +++ b/apps/chat2/config_chat2.nim @@ -14,7 +14,7 @@ type none prod test - + Chat2Conf* = object ## General node config @@ -22,11 +22,10 @@ type desc: "Sets the log level." defaultValue: LogLevel.INFO name: "log-level" }: LogLevel - + nodekey* {. desc: "P2P node private key as 64 char hex string.", - defaultValue: crypto.PrivateKey.random(Secp256k1, crypto.newRng()[]).tryGet() - name: "nodekey" }: crypto.PrivateKey + name: "nodekey" }: Option[crypto.PrivateKey] listenAddress* {. defaultValue: defaultListenAddress(config) @@ -52,35 +51,35 @@ type desc: "Specify method to use for determining public address. " & "Must be one of: any, none, upnp, pmp, extip:." defaultValue: "any" }: string - + ## Persistence config - + dbPath* {. desc: "The database path for peristent storage", defaultValue: "" name: "db-path" }: string - + persistPeers* {. desc: "Enable peer persistence: true|false", defaultValue: false name: "persist-peers" }: bool - + persistMessages* {. desc: "Enable message persistence: true|false", defaultValue: false name: "persist-messages" }: bool ## Relay config - + relay* {. desc: "Enable relay protocol: true|false", defaultValue: true name: "relay" }: bool - + staticnodes* {. desc: "Peer multiaddr to directly connect with. Argument may be repeated." name: "staticnode" }: seq[string] - + keepAlive* {. desc: "Enable keep-alive for idle connections: true|false", defaultValue: false @@ -102,38 +101,38 @@ type desc: "Peer multiaddr to query for storage.", defaultValue: "" name: "storenode" }: string - + ## Filter config filter* {. desc: "Enable filter protocol: true|false", defaultValue: false name: "filter" }: bool - + filternode* {. desc: "Peer multiaddr to request content filtering of messages.", defaultValue: "" name: "filternode" }: string - + ## Swap config swap* {. desc: "Enable swap protocol: true|false", defaultValue: true name: "swap" }: bool - + ## Lightpush config lightpush* {. desc: "Enable lightpush protocol: true|false", defaultValue: false name: "lightpush" }: bool - + lightpushnode* {. desc: "Peer multiaddr to request lightpush of published messages.", defaultValue: "" name: "lightpushnode" }: string - + ## JSON-RPC config rpc* {. @@ -150,17 +149,17 @@ type desc: "Listening port of the JSON-RPC server.", defaultValue: 8545 name: "rpc-port" }: uint16 - + rpcAdmin* {. desc: "Enable access to JSON-RPC Admin API: true|false", defaultValue: false name: "rpc-admin" }: bool - + rpcPrivate* {. desc: "Enable access to JSON-RPC Private API: true|false", defaultValue: false name: "rpc-private" }: bool - + ## Metrics config metricsServer* {. @@ -182,26 +181,26 @@ type desc: "Enable metrics logging: true|false" defaultValue: true name: "metrics-logging" }: bool - + ## DNS discovery config - + dnsDiscovery* {. desc: "Enable discovering nodes via DNS" defaultValue: false name: "dns-discovery" }: bool - + dnsDiscoveryUrl* {. desc: "URL for DNS node list in format 'enrtree://@'", defaultValue: "" name: "dns-discovery-url" }: string - + dnsDiscoveryNameServers* {. desc: "DNS name server IPs to query. Argument may be repeated." defaultValue: @[ValidIpAddress.init("1.1.1.1"), ValidIpAddress.init("1.0.0.1")] name: "dns-discovery-name-server" }: seq[ValidIpAddress] ## Chat2 configuration - + fleet* {. desc: "Select the fleet to connect to. This sets the DNS discovery URL to the selected fleet." defaultValue: Fleet.prod @@ -217,19 +216,19 @@ type desc: "Enable websocket: true|false", defaultValue: false name: "websocket-support"}: bool - + websocketPort* {. desc: "WebSocket listening port." defaultValue: 8000 name: "websocket-port" }: Port - + websocketSecureSupport* {. desc: "WebSocket Secure Support." defaultValue: false name: "websocket-secure-support" }: bool ## rln-relay configuration - + rlnRelay* {. desc: "Enable spam protection through rln-relay: true|false", defaultValue: false @@ -239,7 +238,7 @@ type desc: "The path for peristing rln-relay credential", defaultValue: "" name: "rln-relay-cred-path" }: string - + rlnRelayMembershipIndex* {. desc: "(experimental) the index of node in the rln-relay group: a value between 0-99 inclusive", defaultValue: 0 @@ -254,48 +253,48 @@ type desc: "the pubsub topic for which rln-relay gets enabled", defaultValue: "/waku/2/default-waku/proto" name: "rln-relay-pubsub-topic" }: string - + rlnRelayDynamic* {. desc: "Enable waku-rln-relay with on-chain dynamic group management: true|false", defaultValue: false name: "rln-relay-dynamic" }: bool - + rlnRelayIdKey* {. - desc: "Rln relay identity secret key as a Hex string", + desc: "Rln relay identity secret key as a Hex string", defaultValue: "" name: "rln-relay-id-key" }: string - + rlnRelayIdCommitmentKey* {. - desc: "Rln relay identity commitment key as a Hex string", + desc: "Rln relay identity commitment key as a Hex string", defaultValue: "" name: "rln-relay-id-commitment-key" }: string - + rlnRelayEthAccountAddress* {. desc: "Ethereum account address for an Ethereum testnet", # NOTE: This can be derived from the private key, but kept for future use defaultValue: "" name: "rln-relay-eth-account-address" }: string - + rlnRelayEthAccountPrivateKey* {. desc: "Account private key for an Ethereum testnet", defaultValue: "" name: "rln-relay-eth-account-private-key" }: string - + rlnRelayEthClientAddress* {. desc: "WebSocket address of an Ethereum testnet client e.g., ws://localhost:8540/", defaultValue: "ws://localhost:8540/" name: "rln-relay-eth-client-address" }: string - + rlnRelayEthContractAddress* {. - desc: "Address of membership contract on an Ethereum testnet", + desc: "Address of membership contract on an Ethereum testnet", defaultValue: "" name: "rln-relay-eth-contract-address" }: string rlnRelayCredentialsPassword* {. - desc: "Password for encrypting RLN credentials", + desc: "Password for encrypting RLN credentials", defaultValue: "" name: "rln-relay-cred-password" }: string - + # NOTE: Keys are different in nim-libp2p proc parseCmdArg*(T: type crypto.PrivateKey, p: string): T = try: diff --git a/apps/wakunode2/config.nim b/apps/wakunode2/config.nim index 39defe38c..697e00d14 100644 --- a/apps/wakunode2/config.nim +++ b/apps/wakunode2/config.nim @@ -53,8 +53,7 @@ type nodekey* {. desc: "P2P node private key as 64 char hex string.", - defaultValue: defaultPrivateKey() - name: "nodekey" }: PrivateKey + name: "nodekey" }: Option[PrivateKey] listenAddress* {. defaultValue: defaultListenAddress() @@ -465,9 +464,6 @@ proc parseCmdArg*(T: type crypto.PrivateKey, p: string): T = proc completeCmdArg*(T: type crypto.PrivateKey, val: string): seq[string] = return @[] -proc defaultPrivateKey*(): PrivateKey = - crypto.PrivateKey.random(Secp256k1, crypto.newRng()[]).value - proc parseCmdArg*(T: type ValidIpAddress, p: string): T = try: diff --git a/apps/wakunode2/wakunode2.nim b/apps/wakunode2/wakunode2.nim index 01efe5983..3ad4e7563 100644 --- a/apps/wakunode2/wakunode2.nim +++ b/apps/wakunode2/wakunode2.nim @@ -214,6 +214,7 @@ proc retrieveDynamicBootstrapNodes*(dnsDiscovery: bool, dnsDiscoveryUrl: string, ok(newSeq[RemotePeerInfo]()) # Return an empty seq by default proc initNode(conf: WakuNodeConf, + rng: ref HmacDrbgContext, peerStore: Option[WakuPeerStorage], dynamicBootstrapNodes: openArray[RemotePeerInfo] = @[]): SetupResult[WakuNode] = @@ -231,6 +232,13 @@ proc initNode(conf: WakuNodeConf, dnsResolver = DnsResolver.new(nameServers) let + nodekey = if conf.nodekey.isSome(): + conf.nodekey.get() + else: + let nodekeyRes = crypto.PrivateKey.random(Secp256k1, rng[]) + if nodekeyRes.isErr(): + return err("failed to generate nodekey: " & $nodekeyRes.error) + nodekeyRes.get() ## `udpPort` is only supplied to satisfy underlying APIs but is not ## actually a supported transport for libp2p traffic. udpPort = conf.tcpPort @@ -271,7 +279,7 @@ proc initNode(conf: WakuNodeConf, let pStorage = if peerStore.isNone(): nil else: peerStore.get() try: - node = WakuNode.new(conf.nodekey, + node = WakuNode.new(nodekey, conf.listenAddress, Port(uint16(conf.tcpPort) + conf.portsShift), extIp, extPort, extMultiAddrs, @@ -288,7 +296,8 @@ proc initNode(conf: WakuNodeConf, dns4DomainName, discv5UdpPort, some(conf.agentString), - conf.peerStoreCapacity) + conf.peerStoreCapacity, + rng) except: return err("failed to create waku node instance: " & getCurrentExceptionMsg()) @@ -318,7 +327,7 @@ proc initNode(conf: WakuNodeConf, discv5UdpPort.get(), discv5BootstrapEnrs, conf.discv5EnrAutoUpdate, - keys.PrivateKey(conf.nodekey.skkey), + keys.PrivateKey(nodekey.skkey), wakuFlags, [], # Empty enr fields, for now node.rng, @@ -570,6 +579,7 @@ when isMainModule: ## 6. Setup graceful shutdown hooks const versionString = "version / git commit hash: " & git_version + let rng = crypto.newRng() let confRes = WakuNodeConf.load(version=versionString) if confRes.isErr(): @@ -655,7 +665,7 @@ when isMainModule: var node: WakuNode # This is the node we're going to setup using the conf - let initNodeRes = initNode(conf, peerStore, dynamicBootstrapNodes) + let initNodeRes = initNode(conf, rng, peerStore, dynamicBootstrapNodes) if initNodeRes.isok(): node = initNodeRes.get() else: diff --git a/examples/v2/publisher.nim b/examples/v2/publisher.nim index 3708195e2..177933589 100644 --- a/examples/v2/publisher.nim +++ b/examples/v2/publisher.nim @@ -28,12 +28,12 @@ const bootstrapNodes = @["enr:-Nm4QOdTOKZJKTUUZ4O_W932CXIET-M9NamewDnL78P5u9DOGn const wakuPort = 60000 const discv5Port = 9000 -proc setupAndPublish() {.async.} = +proc setupAndPublish(rng: ref HmacDrbgContext) {.async.} = # use notice to filter all waku messaging setupLogLevel(logging.LogLevel.NOTICE) notice "starting publisher", wakuPort=wakuPort, discv5Port=discv5Port let - nodeKey = crypto.PrivateKey.random(Secp256k1, crypto.newRng()[])[] + nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[] ip = ValidIpAddress.init("0.0.0.0") node = WakuNode.new(nodeKey, ip, Port(wakuPort)) flags = initWakuFlags(lightpush = false, filter = false, store = false, relay = true) @@ -84,5 +84,7 @@ proc setupAndPublish() {.async.} = notice "published message", text = text, timestamp = message.timestamp, psTopic = pubSubTopic, contentTopic = contentTopic await sleepAsync(5000) -asyncSpawn setupAndPublish() -runForever() +when isMainModule: + let rng = crypto.newRng() + asyncSpawn setupAndPublish(rng) + runForever() diff --git a/examples/v2/subscriber.nim b/examples/v2/subscriber.nim index 556c1506c..71b0259b7 100644 --- a/examples/v2/subscriber.nim +++ b/examples/v2/subscriber.nim @@ -24,12 +24,12 @@ const bootstrapNodes = @["enr:-Nm4QOdTOKZJKTUUZ4O_W932CXIET-M9NamewDnL78P5u9DOGn const wakuPort = 50000 const discv5Port = 8000 -proc setupAndSubscribe() {.async.} = +proc setupAndSubscribe(rng: ref HmacDrbgContext) {.async.} = # use notice to filter all waku messaging setupLogLevel(logging.LogLevel.NOTICE) notice "starting subscriber", wakuPort=wakuPort, discv5Port=discv5Port let - nodeKey = crypto.PrivateKey.random(Secp256k1, crypto.newRng()[])[] + nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[] ip = ValidIpAddress.init("0.0.0.0") node = WakuNode.new(nodeKey, ip, Port(wakuPort)) flags = initWakuFlags(lightpush = false, filter = false, store = false, relay = true) @@ -79,6 +79,7 @@ proc setupAndSubscribe() {.async.} = timestamp=message.timestamp node.subscribe(pubSubTopic, handler) -asyncSpawn setupAndSubscribe() - -runForever() +when isMainModule: + let rng = crypto.newRng() + asyncSpawn setupAndSubscribe(rng) + runForever() diff --git a/tests/v2/test_waku_switch.nim b/tests/v2/test_waku_switch.nim index abd0ac801..a6e9466ee 100644 --- a/tests/v2/test_waku_switch.nim +++ b/tests/v2/test_waku_switch.nim @@ -10,6 +10,7 @@ import stew/byteutils import ../../waku/v2/node/wakuswitch, + ../test_helpers, ./testlib/switch proc newCircuitRelayClientSwitch(relayClient: RelayClient): Switch = @@ -28,7 +29,7 @@ procSuite "Waku Switch": ## Given let sourceSwitch = newTestSwitch() - wakuSwitch = newWakuSwitch() + wakuSwitch = newWakuSwitch(rng = rng()) await sourceSwitch.start() await wakuSwitch.start() @@ -46,7 +47,7 @@ procSuite "Waku Switch": asyncTest "Waku Switch acts as circuit relayer": ## Setup let - wakuSwitch = newWakuSwitch() + wakuSwitch = newWakuSwitch(rng = rng()) sourceClient = RelayClient.new() destClient = RelayClient.new() sourceSwitch = newCircuitRelayClientSwitch(sourceClient) diff --git a/tools/wakucanary/wakucanary.nim b/tools/wakucanary/wakucanary.nim index 3de2c2e0a..c53ca688f 100644 --- a/tools/wakucanary/wakucanary.nim +++ b/tools/wakucanary/wakucanary.nim @@ -86,7 +86,7 @@ proc areProtocolsSupported( return false -proc main(): Future[int] {.async.} = +proc main(rng: ref HmacDrbgContext): Future[int] {.async.} = let conf: WakuCanaryConf = WakuCanaryConf.load() # create dns resolver @@ -113,7 +113,6 @@ proc main(): Future[int] {.async.} = let peer: RemotePeerInfo = parseRemotePeerInfo(conf.address) - rng = crypto.newRng() nodeKey = crypto.PrivateKey.random(Secp256k1, rng[])[] node = WakuNode.new( nodeKey, @@ -141,7 +140,8 @@ proc main(): Future[int] {.async.} = return 0 when isMainModule: - let status = waitFor main() + let rng = crypto.newRng() + let status = waitFor main(rng) if status == 0: info "The node is reachable and supports all specified protocols" else: diff --git a/waku/v2/node/waku_node.nim b/waku/v2/node/waku_node.nim index db11918d7..48e16c937 100644 --- a/waku/v2/node/waku_node.nim +++ b/waku/v2/node/waku_node.nim @@ -152,6 +152,8 @@ proc new*(T: type WakuNode, discv5UdpPort = none(Port), agentString = none(string), # defaults to nim-libp2p version peerStoreCapacity = none(int), # defaults to 1.25 maxConnections + # TODO: make this argument required after tests are updated + rng: ref HmacDrbgContext = crypto.newRng() ): T {.raises: [Defect, LPError, IOError, TLSStreamProtocolError].} = ## Creates a Waku Node instance. @@ -198,7 +200,6 @@ proc new*(T: type WakuNode, ## Initialize peer let - rng = crypto.newRng() enrIp = if extIp.isSome(): extIp else: some(bindIp) enrTcpPort = if extPort.isSome(): extPort diff --git a/waku/v2/node/wakuswitch.nim b/waku/v2/node/wakuswitch.nim index 438f5a083..678f74af9 100644 --- a/waku/v2/node/wakuswitch.nim +++ b/waku/v2/node/wakuswitch.nim @@ -63,7 +63,7 @@ proc newWakuSwitch*( SecureProtocol.Noise, ], transportFlags: set[ServerFlags] = {}, - rng = crypto.newRng(), + rng: ref HmacDrbgContext, inTimeout: Duration = 5.minutes, outTimeout: Duration = 5.minutes, maxConnections = MaxConnections,