fix(rng): create rng only within isMainModule blocks (#1523)

* fix(rng): create rng only within isMainModule blocks

* fix(rng): wakucanary rng

* fix(rng): address comments
This commit is contained in:
Aaryamann Challani 2023-02-06 17:23:05 +05:30 committed by GitHub
parent 4ea6039323
commit c9bc774895
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 84 additions and 71 deletions

View File

@ -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

View File

@ -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:<IP>."
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://<key>@<fqdn>'",
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:

View File

@ -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:

View File

@ -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:

View File

@ -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()

View File

@ -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()

View File

@ -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)

View File

@ -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:

View File

@ -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

View File

@ -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,