diff --git a/apps/chat2/chat2.nim b/apps/chat2/chat2.nim index 7fb4551d2..98e5842db 100644 --- a/apps/chat2/chat2.nim +++ b/apps/chat2/chat2.nim @@ -519,7 +519,7 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} = rlnRelayDynamic: conf.rlnRelayDynamic, rlnRelayCredIndex: conf.rlnRelayCredIndex, rlnRelayEthContractAddress: conf.rlnRelayEthContractAddress, - rlnRelayEthClientAddress: conf.rlnRelayEthClientAddress, + rlnRelayEthClientAddress: string(conf.rlnRelayethClientAddress), rlnRelayCredPath: conf.rlnRelayCredPath, rlnRelayCredPassword: conf.rlnRelayCredPassword, rlnRelayUserMessageLimit: conf.rlnRelayUserMessageLimit, @@ -529,7 +529,7 @@ proc processInput(rfd: AsyncFD, rng: ref HmacDrbgContext) {.async.} = rlnRelayDynamic: conf.rlnRelayDynamic, rlnRelayCredIndex: conf.rlnRelayCredIndex, rlnRelayEthContractAddress: conf.rlnRelayEthContractAddress, - rlnRelayEthClientAddress: conf.rlnRelayEthClientAddress, + rlnRelayEthClientAddress: string(conf.rlnRelayethClientAddress), rlnRelayCredPath: conf.rlnRelayCredPath, rlnRelayCredPassword: conf.rlnRelayCredPassword, ) diff --git a/apps/chat2/config_chat2.nim b/apps/chat2/config_chat2.nim index 9aa736ebb..a23683e93 100644 --- a/apps/chat2/config_chat2.nim +++ b/apps/chat2/config_chat2.nim @@ -1,11 +1,12 @@ import - std/strutils, - confutils, confutils/defs, confutils/std/net, chronicles, chronos, + confutils, confutils/defs, confutils/std/net, + eth/keys, libp2p/crypto/crypto, libp2p/crypto/secp, nimcrypto/utils, - eth/keys + std/strutils, + regex import ../../../waku/waku_core @@ -14,7 +15,7 @@ type none prod test - + EthRpcUrl = distinct string Chat2Conf* = object ## General node config @@ -252,9 +253,9 @@ type name: "rln-relay-id-commitment-key" }: string rlnRelayEthClientAddress* {. - desc: "WebSocket address of an Ethereum testnet client e.g., http://localhost:8540/", + desc: "HTTP address of an Ethereum testnet client e.g., http://localhost:8540/", defaultValue: "http://localhost:8540/" - name: "rln-relay-eth-client-address" }: string + name: "rln-relay-eth-client-address" }: EthRpcUrl rlnRelayEthContractAddress* {. desc: "Address of membership contract on an Ethereum testnet", @@ -307,6 +308,28 @@ proc parseCmdArg*(T: type Option[uint], p: string): T = except CatchableError: raise newException(ValueError, "Invalid unsigned integer") +proc completeCmdArg*(T: type EthRpcUrl, val: string): seq[string] = + return @[] + +proc parseCmdArg*(T: type EthRpcUrl, s: string): T = + ## allowed patterns: + ## http://url:port + ## https://url:port + ## http://url:port/path + ## https://url:port/path + ## http://url/with/path + ## http://url:port/path?query + ## https://url:port/path?query + ## disallowed patterns: + ## any valid/invalid ws or wss url + var httpPattern = re2"^(https?:\/\/)(?:w{1,3}\.)?[^\s.]+(?:\.[a-z]+)*(?::\d+)?(?![^<]*(?:<\/\w+>|\/?>))" + var wsPattern = re2"^(wss?:\/\/)(?:w{1,3}\.)?[^\s.]+(?:\.[a-z]+)*(?::\d+)?(?![^<]*(?:<\/\w+>|\/?>))" + if regex.match(s, wsPattern): + raise newException(ValueError, "Websocket RPC URL is not supported, Please use an HTTP URL") + if not regex.match(s, httpPattern): + raise newException(ValueError, "Invalid HTTP RPC URL") + return EthRpcUrl(s) + func defaultListenAddress*(conf: Chat2Conf): IpAddress = # TODO: How should we select between IPv4 and IPv6 # Maybe there should be a config option for this. diff --git a/apps/networkmonitor/networkmonitor.nim b/apps/networkmonitor/networkmonitor.nim index 1a49d3981..7907b2150 100644 --- a/apps/networkmonitor/networkmonitor.nim +++ b/apps/networkmonitor/networkmonitor.nim @@ -542,7 +542,7 @@ when isMainModule: rlnRelayDynamic: conf.rlnRelayDynamic, rlnRelayCredIndex: some(uint(0)), rlnRelayEthContractAddress: conf.rlnRelayEthContractAddress, - rlnRelayEthClientAddress: conf.rlnRelayEthClientAddress, + rlnRelayEthClientAddress: string(conf.rlnRelayethClientAddress), rlnRelayCredPath: "", rlnRelayCredPassword: "", rlnRelayTreePath: conf.rlnRelayTreePath, diff --git a/apps/networkmonitor/networkmonitor_config.nim b/apps/networkmonitor/networkmonitor_config.nim index 911b3c242..cb0641821 100644 --- a/apps/networkmonitor/networkmonitor_config.nim +++ b/apps/networkmonitor/networkmonitor_config.nim @@ -1,11 +1,14 @@ import - std/strutils, chronicles, chronicles/topics_registry, - chronos, confutils, + chronos, + std/strutils, stew/results, - stew/shims/net + stew/shims/net, + regex + +type EthRpcUrl = distinct string type NetworkMonitorConf* = object @@ -63,9 +66,9 @@ type name: "rln-relay-tree-path" }: string rlnRelayEthClientAddress* {. - desc: "WebSocket address of an Ethereum testnet client e.g., http://localhost:8540/", + desc: "HTTP address of an Ethereum testnet client e.g., http://localhost:8540/", defaultValue: "http://localhost:8540/", - name: "rln-relay-eth-client-address" }: string + name: "rln-relay-eth-client-address" }: EthRpcUrl rlnRelayEthContractAddress* {. desc: "Address of membership contract on an Ethereum testnet", @@ -116,6 +119,29 @@ proc parseCmdArg*(T: type chronos.Duration, p: string): T = proc completeCmdArg*(T: type chronos.Duration, val: string): seq[string] = return @[] +proc completeCmdArg*(T: type EthRpcUrl, val: string): seq[string] = + return @[] + +proc parseCmdArg*(T: type EthRpcUrl, s: string): T = + ## allowed patterns: + ## http://url:port + ## https://url:port + ## http://url:port/path + ## https://url:port/path + ## http://url/with/path + ## http://url:port/path?query + ## https://url:port/path?query + ## disallowed patterns: + ## any valid/invalid ws or wss url + var httpPattern = re2"^(https?:\/\/)(?:w{1,3}\.)?[^\s.]+(?:\.[a-z]+)*(?::\d+)?(?![^<]*(?:<\/\w+>|\/?>))" + var wsPattern = re2"^(wss?:\/\/)(?:w{1,3}\.)?[^\s.]+(?:\.[a-z]+)*(?::\d+)?(?![^<]*(?:<\/\w+>|\/?>))" + if regex.match(s, wsPattern): + echo "here" + raise newException(ValueError, "Websocket RPC URL is not supported, Please use an HTTP URL") + if not regex.match(s, httpPattern): + raise newException(ValueError, "Invalid HTTP RPC URL") + return EthRpcUrl(s) + proc loadConfig*(T: type NetworkMonitorConf): Result[T, string] = try: let conf = NetworkMonitorConf.load(version=git_version) diff --git a/apps/wakunode2/app.nim b/apps/wakunode2/app.nim index 2fbe197a5..291ea1d1d 100644 --- a/apps/wakunode2/app.nim +++ b/apps/wakunode2/app.nim @@ -472,7 +472,7 @@ proc setupProtocols(node: WakuNode, rlnRelayDynamic: conf.rlnRelayDynamic, rlnRelayCredIndex: conf.rlnRelayCredIndex, rlnRelayEthContractAddress: conf.rlnRelayEthContractAddress, - rlnRelayEthClientAddress: conf.rlnRelayEthClientAddress, + rlnRelayEthClientAddress: string(conf.rlnRelayethClientAddress), rlnRelayCredPath: conf.rlnRelayCredPath, rlnRelayCredPassword: conf.rlnRelayCredPassword, rlnRelayTreePath: conf.rlnRelayTreePath, @@ -484,7 +484,7 @@ proc setupProtocols(node: WakuNode, rlnRelayDynamic: conf.rlnRelayDynamic, rlnRelayCredIndex: conf.rlnRelayCredIndex, rlnRelayEthContractAddress: conf.rlnRelayEthContractAddress, - rlnRelayEthClientAddress: conf.rlnRelayEthClientAddress, + rlnRelayEthClientAddress: string(conf.rlnRelayethClientAddress), rlnRelayCredPath: conf.rlnRelayCredPath, rlnRelayCredPassword: conf.rlnRelayCredPassword, rlnRelayTreePath: conf.rlnRelayTreePath, diff --git a/apps/wakunode2/external_config.nim b/apps/wakunode2/external_config.nim index 907f42e6d..82ed60bc8 100644 --- a/apps/wakunode2/external_config.nim +++ b/apps/wakunode2/external_config.nim @@ -36,6 +36,8 @@ type ProtectedTopic* = object type ShardIdx = distinct uint16 +type EthRpcUrl = distinct string + type StartUpCommand* = enum noCommand # default, runs waku generateRlnKeystore # generates a new RLN keystore @@ -63,9 +65,9 @@ type name: "rln-relay-cred-path" }: string rlnRelayEthClientAddress* {. - desc: "WebSocket address of an Ethereum testnet client e.g., http://localhost:8540/", + desc: "HTTP address of an Ethereum testnet client e.g., http://localhost:8540/", defaultValue: "http://localhost:8540/", - name: "rln-relay-eth-client-address" }: string + name: "rln-relay-eth-client-address" }: EthRpcUrl rlnRelayEthContractAddress* {. desc: "Address of membership contract on an Ethereum testnet", @@ -603,6 +605,28 @@ proc parseCmdArg*(T: type Option[uint], p: string): T = except CatchableError: raise newException(ValueError, "Invalid unsigned integer") +proc completeCmdArg*(T: type EthRpcUrl, val: string): seq[string] = + return @[] + +proc parseCmdArg*(T: type EthRpcUrl, s: string): T = + ## allowed patterns: + ## http://url:port + ## https://url:port + ## http://url:port/path + ## https://url:port/path + ## http://url/with/path + ## http://url:port/path?query + ## https://url:port/path?query + ## disallowed patterns: + ## any valid/invalid ws or wss url + var httpPattern = re2"^(https?:\/\/)(?:w{1,3}\.)?[^\s.]+(?:\.[a-z]+)*(?::\d+)?(?![^<]*(?:<\/\w+>|\/?>))" + var wsPattern = re2"^(wss?:\/\/)(?:w{1,3}\.)?[^\s.]+(?:\.[a-z]+)*(?::\d+)?(?![^<]*(?:<\/\w+>|\/?>))" + if regex.match(s, wsPattern): + raise newException(ValueError, "Websocket RPC URL is not supported, Please use an HTTP URL") + if not regex.match(s, httpPattern): + raise newException(ValueError, "Invalid HTTP RPC URL") + return EthRpcUrl(s) + ## Load proc readValue*(r: var TomlReader, value: var crypto.PrivateKey) {.raises: [SerializationError].} = @@ -641,6 +665,18 @@ proc readValue*(r: var EnvvarReader, value: var ShardIdx) {.raises: [Serializati except CatchableError: raise newException(SerializationError, getCurrentExceptionMsg()) +proc readValue*(r: var TomlReader, value: var EthRpcUrl) {.raises: [SerializationError].} = + try: + value = parseCmdArg(EthRpcUrl, r.readValue(string)) + except CatchableError: + raise newException(SerializationError, getCurrentExceptionMsg()) + +proc readValue*(r: var EnvvarReader, value: var EthRpcUrl) {.raises: [SerializationError].} = + try: + value = parseCmdArg(EthRpcUrl, r.readValue(string)) + except CatchableError: + raise newException(SerializationError, getCurrentExceptionMsg()) + {.push warning[ProveInit]: off.} proc load*(T: type WakuNodeConf, version=""): ConfResult[T] = diff --git a/docs/operators/how-to/run-with-rln.md b/docs/operators/how-to/run-with-rln.md index ed6d27873..f56af0146 100644 --- a/docs/operators/how-to/run-with-rln.md +++ b/docs/operators/how-to/run-with-rln.md @@ -33,7 +33,7 @@ make wakunode2 Follow [Step 10](../droplet-quickstart.md#10-run-nwaku) of the [droplet quickstart](../droplet-quickstart.md) guide, while replacing the run command with - ```bash -export SEPOLIA_WS_NODE_ADDRESS= +export SEPOLIA_HTTP_NODE_ADDRESS= export RLN_RELAY_CONTRACT_ADDRESS="0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4" # Replace this with any compatible implementation $WAKUNODE_DIR/wakunode2 \ --store:true \ @@ -44,7 +44,7 @@ $WAKUNODE_DIR/wakunode2 \ --rln-relay:true \ --rln-relay-dynamic:true \ --rln-relay-eth-contract-address:"$RLN_RELAY_CONTRACT_ADDRESS" \ ---rln-relay-eth-client-address:"$SEPOLIA_WS_NODE_ADDRESS" +--rln-relay-eth-client-address:"$SEPOLIA_HTTP_NODE_ADDRESS" ``` OR @@ -53,7 +53,7 @@ If you are running the nwaku node within docker, follow [Step 2](../docker-quick ```bash export WAKU_FLEET= -export SEPOLIA_WS_NODE_ADDRESS= +export SEPOLIA_HTTP_NODE_ADDRESS= export RLN_RELAY_CONTRACT_ADDRESS="0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4" # Replace this with any compatible implementation docker run -i -t -p 60000:60000 -p 9000:9000/udp wakuorg/nwaku:v0.20.0 \ --dns-discovery:true \ @@ -63,7 +63,7 @@ docker run -i -t -p 60000:60000 -p 9000:9000/udp wakuorg/nwaku:v0.20.0 \ --rln-relay:true \ --rln-relay-dynamic:true \ --rln-relay-eth-contract-address:"$RLN_RELAY_CONTRACT_ADDRESS" \ - --rln-relay-eth-client-address:"$SEPOLIA_WS_NODE_ADDRESS" + --rln-relay-eth-client-address:"$SEPOLIA_HTTP_NODE_ADDRESS" ``` > Note: You can choose to keep connections to other nodes alive by adding the `--keep-alive` flag. @@ -74,7 +74,7 @@ runtime arguments - 1. `--rln-relay`: Allows waku-rln-relay to be mounted into the setup of the nwaku node 2. `--rln-relay-dynamic`: Enables waku-rln-relay to connect to an ethereum node to fetch the membership group 3. `--rln-relay-eth-contract-address`: The contract address of an RLN membership group -4. `--rln-relay-eth-client-address`: The websocket url to a Sepolia ethereum node +4. `--rln-relay-eth-client-address`: The HTTP url to a Sepolia ethereum node You should now have nwaku running, with RLN enabled! diff --git a/docs/tutorial/onchain-rln-relay-chat2.md b/docs/tutorial/onchain-rln-relay-chat2.md index 0d2e8741d..227afcfe9 100644 --- a/docs/tutorial/onchain-rln-relay-chat2.md +++ b/docs/tutorial/onchain-rln-relay-chat2.md @@ -166,7 +166,7 @@ You can check this fact by looking at `Bob`'s console, where `message3` is missi **Alice** ```bash -./build/chat2 --fleet:test --content-topic:/toy-chat/3/mingde/proto --rln-relay:true --rln-relay-dynamic:true --rln-relay-eth-contract-address:0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4 --rln-relay-cred-path:rlnKeystore.json --rln-relay-cred-password:password --rln-relay-eth-client-address:wss://sepolia.infura.io/ws/v3/12345678901234567890123456789012 --ports-shift=1 +./build/chat2 --fleet:test --content-topic:/toy-chat/3/mingde/proto --rln-relay:true --rln-relay-dynamic:true --rln-relay-eth-contract-address:0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4 --rln-relay-cred-path:rlnKeystore.json --rln-relay-cred-password:password --rln-relay-eth-client-address:https://sepolia.infura.io/v3/12345678901234567890123456789012 --ports-shift=1 ``` ``` @@ -209,7 +209,7 @@ your rln identity commitment key is: bd093cbf14fb933d53f596c33f98b3df83b7e9f7a19 **Bob** ```bash -./build/chat2 --fleet:test --content-topic:/toy-chat/3/mingde/proto --rln-relay:true --rln-relay-dynamic:true --rln-relay-eth-contract-address:0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4 --rln-relay-cred-path:rlnKeystore.json --rln-relay-cred-index:1 --rln-relay-cred-password:password --rln-relay-eth-client-address:wss://sepolia.infura.io/ws/v3/12345678901234567890123456789012 --ports-shift=2 +./build/chat2 --fleet:test --content-topic:/toy-chat/3/mingde/proto --rln-relay:true --rln-relay-dynamic:true --rln-relay-eth-contract-address:0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4 --rln-relay-cred-path:rlnKeystore.json --rln-relay-cred-index:1 --rln-relay-cred-password:password --rln-relay-eth-client-address:https://sepolia.infura.io/v3/12345678901234567890123456789012 --ports-shift=2 ``` ``` diff --git a/tools/rln_keystore_generator/rln_keystore_generator.nim b/tools/rln_keystore_generator/rln_keystore_generator.nim index 5742eedc2..14cde6af1 100644 --- a/tools/rln_keystore_generator/rln_keystore_generator.nim +++ b/tools/rln_keystore_generator/rln_keystore_generator.nim @@ -49,7 +49,7 @@ proc doRlnKeystoreGenerator*(conf: WakuNodeConf) = quit(0) # 4. initialize OnchainGroupManager - let groupManager = OnchainGroupManager(ethClientUrl: conf.rlnRelayEthClientAddress, + let groupManager = OnchainGroupManager(ethClientUrl: string(conf.rlnRelayethClientAddress), ethContractAddress: conf.rlnRelayEthContractAddress, rlnInstance: rlnInstance, keystorePath: none(string), diff --git a/waku/waku_rln_relay/rln_relay.nim b/waku/waku_rln_relay/rln_relay.nim index 98765120b..b1f885993 100644 --- a/waku/waku_rln_relay/rln_relay.nim +++ b/waku/waku_rln_relay/rln_relay.nim @@ -398,7 +398,7 @@ proc mount(conf: WakuRlnConfig, let rlnRelayCredPath = useValueOrNone(conf.rlnRelayCredPath) rlnRelayCredPassword = useValueOrNone(conf.rlnRelayCredPassword) - groupManager = OnchainGroupManager(ethClientUrl: conf.rlnRelayEthClientAddress, + groupManager = OnchainGroupManager(ethClientUrl: string(conf.rlnRelayethClientAddress), ethContractAddress: $conf.rlnRelayEthContractAddress, rlnInstance: rlnInstance, registrationHandler: registrationHandler,