From 6cf028ca42077a5f5cb9c1a3135523e373120c53 Mon Sep 17 00:00:00 2001 From: rymnc Date: Wed, 12 Oct 2022 02:47:57 +0000 Subject: [PATCH] deploy: 04154ab90f77a789e1f38b3976cb395b4f74d1f8 --- docs/tutorial/onchain-rln-relay-chat2.md | 22 +++-- examples/v2/chat2.nim | 18 +++- tests/v2/test_waku_rln_relay_onchain.nim | 10 +-- .../vendor/libbacktrace-upstream/libtool | 2 +- .../waku_rln_relay/waku_rln_relay_types.nim | 4 +- .../waku_rln_relay/waku_rln_relay_utils.nim | 82 ++++++++++++------- 6 files changed, 91 insertions(+), 47 deletions(-) diff --git a/docs/tutorial/onchain-rln-relay-chat2.md b/docs/tutorial/onchain-rln-relay-chat2.md index a00e46afa..299b53164 100644 --- a/docs/tutorial/onchain-rln-relay-chat2.md +++ b/docs/tutorial/onchain-rln-relay-chat2.md @@ -40,7 +40,7 @@ You can test it by connecting two chat2 clients (running Waku-RLN-Relay) directl ## Build chat2 First, build chat2 with the RLN flag set to true. -``` +```bash make chat2 RLN=true ``` @@ -48,7 +48,7 @@ make chat2 RLN=true Run the following command to set up your chat2 client. -``` +```bash ./build/chat2 --fleet:test --content-topic:/toy-chat/2/luzhou/proto --rln-relay:true --rln-relay-dynamic:true --rln-relay-eth-contract-address:0x4252105670fe33d2947e8ead304969849e64f2a6 --rln-relay-eth-account-address:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --rln-relay-eth-account-private-key:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --rln-relay-eth-client-address:xxxx --ports-shift=1 ``` @@ -166,10 +166,18 @@ RLN credential is persisted in the `rlnCredentials.txt` file under the specified If this file does not already exist under the supplied path, then a new credential is generated and persisted in the `rlnCredentials.txt` file. Otherwise, the chat client does not generate a new credential and will use, instead, the persisted RLN credential. -``` +```bash ./build/chat2 --fleet:test --content-topic:/toy-chat/2/luzhou/proto --rln-relay:true --rln-relay-dynamic:true --rln-relay-eth-contract-address:0x4252105670fe33d2947e8ead304969849e64f2a6 --rln-relay-eth-account-address:your_eth_account --rln-relay-eth-account-private-key:your_eth_private_key --rln-relay-eth-client-address:your_goerli_node --ports-shift=1 --rln-relay-cred-path:./ ``` +Note: If you are reusing credentials, you can omit the `rln-relay-eth-account-address` and `rln-relay-eth-account-private-key` flags + +Therefore, the command to start chat2 would be - + +```bash +./build/chat2 --fleet:test --content-topic:/toy-chat/2/luzhou/proto --rln-relay:true --rln-relay-dynamic:true --rln-relay-eth-contract-address:0x4252105670fe33d2947e8ead304969849e64f2a6 --rln-relay-eth-client-address:your_goerli_node --ports-shift=1 --rln-relay-cred-path:./ +``` + # Sample test output In this section, a sample test of running two chat clients is provided. Note that the values used for `rln-relay-eth-account-address`, `rln-relay-eth-account-private-key`, and `rln-relay-eth-client-address` in the following code snippets are junk and not valid. @@ -183,9 +191,11 @@ 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/2/luzhou/proto --rln-relay:true --rln-relay-dynamic:true --rln-relay-eth-contract-address:0x4252105670fe33d2947e8ead304969849e64f2a6 --rln-relay-eth-account-address:0x1234567890123456789012345678901234567890 --rln-relay-eth-account-private-key:0x1234567890123456789012345678901234567890123456789012345678901234 --rln-relay-eth-client-address:wss://goerli.infura.io/ws/v3/12345678901234567890123456789012 --ports-shift=1 +``` +``` Choose a nickname >> Alice Welcome, Alice! Connecting to test fleet using DNS discovery... @@ -225,9 +235,11 @@ your rln identity commitment key is: bd093cbf14fb933d53f596c33f98b3df83b7e9f7a19 ``` **Bob** -``` +```bash ./build/chat2 --fleet:test --content-topic:/toy-chat/2/luzhou/proto --rln-relay:true --rln-relay-dynamic:true --rln-relay-eth-contract-address:0x4252105670fe33d2947e8ead304969849e64f2a6 --rln-relay-eth-account-address:0x1234567890123456789012345678901234567890 --rln-relay-eth-account-private-key:0x1234567890123456789012345678901234567890123456789012345678901234 --rln-relay-eth-client-address:wss://goerli.infura.io/ws/v3/12345678901234567890123456789012 --ports-shift=2 +``` +``` Choose a nickname >> Bob Welcome, Bob! Connecting to test fleet using DNS discovery... diff --git a/examples/v2/chat2.nim b/examples/v2/chat2.nim index 5c8828f90..7ff5e6618 100644 --- a/examples/v2/chat2.nim +++ b/examples/v2/chat2.nim @@ -377,6 +377,10 @@ proc processInput(rfd: AsyncFD) {.async.} = wssEnabled = conf.websocketSecureSupport) await node.start() + if conf.rlnRelayEthAccountPrivateKey == "" and conf.rlnRelayCredPath == "": + raise newException(ConfigurationError, + "Either rln-relay-eth-private-key or rln-relay-cred-path MUST be passed") + if conf.relay: await node.mountRelay(conf.topics.split(" ")) @@ -531,7 +535,7 @@ proc processInput(rfd: AsyncFD) {.async.} = showChatPrompt(chat) proc registrationHandler(txHash: string) {.gcsafe, closure.} = echo "You are registered to the rln membership contract, find details of your registration transaction in https://goerli.etherscan.io/tx/0x", txHash - + echo "rln-relay preparation is in progress..." let res = node.mountRlnRelay(conf = conf, spamHandler = some(spamHandler), registrationHandler = some(registrationHandler)) if res.isErr: @@ -555,11 +559,19 @@ proc main() {.async.} = var thread: Thread[AsyncFD] thread.createThread(readInput, wfd) + try: + await processInput(rfd) + # Handle only ConfigurationError for now + # TODO: Throw other errors from the mounting procedure + except ConfigurationError as e: + raise e - await processInput(rfd) when isMainModule: # isMainModule = true when the module is compiled as the main file - waitFor(main()) + try: + waitFor(main()) + except CatchableError as e: + raise e ## Dump of things that can be improved: ## diff --git a/tests/v2/test_waku_rln_relay_onchain.nim b/tests/v2/test_waku_rln_relay_onchain.nim index 5bf443292..0952bcfa6 100644 --- a/tests/v2/test_waku_rln_relay_onchain.nim +++ b/tests/v2/test_waku_rln_relay_onchain.nim @@ -193,7 +193,7 @@ procSuite "Waku-rln-relay": var rlnPeer = WakuRLNRelay(membershipKeyPair: keyPair.get(), membershipIndex: MembershipIndex(0), ethClientAddress: EthClient, - ethAccountAddress: accounts[0], + ethAccountAddress: some(accounts[0]), membershipContractAddress: contractAddress, rlnInstance: rln) @@ -296,7 +296,7 @@ procSuite "Waku-rln-relay": membershipIndex: MembershipIndex(0), ethClientAddress: EthClient, ethAccountPrivateKey: some(ethPrivKey), - ethAccountAddress: ethacc, + ethAccountAddress: some(ethacc), membershipContractAddress: contractAddress) # register the rln-relay peer to the membership contract @@ -431,7 +431,7 @@ procSuite "Waku-rln-relay": # start rln-relay await node.mountRelay(@[RlnRelayPubsubTopic]) discard await node.mountRlnRelayDynamic(ethClientAddr = EthClient, - ethAccAddr = ethacc, + ethAccountAddress = some(ethacc), ethAccountPrivKeyOpt = some(ethPrivKey), memContractAddr = contractAddress, memKeyPair = keyPair1, @@ -484,7 +484,7 @@ procSuite "Waku-rln-relay": # start rln-relay on the first node, leave rln-relay credentials empty await node.mountRelay(@[RlnRelayPubsubTopic]) discard await node.mountRlnRelayDynamic(ethClientAddr = EthClient, - ethAccAddr = ethacc, + ethAccountAddress = some(ethacc), ethAccountPrivKeyOpt = some(ethPrivKey), memContractAddr = contractAddress, memKeyPair = none(MembershipKeyPair), @@ -497,7 +497,7 @@ procSuite "Waku-rln-relay": # start rln-relay on the second node, leave rln-relay credentials empty await node2.mountRelay(@[RlnRelayPubsubTopic]) discard await node2.mountRlnRelayDynamic(ethClientAddr = EthClient, - ethAccAddr = ethacc, + ethAccountAddress = some(ethacc), ethAccountPrivKeyOpt = some(ethPrivKey), memContractAddr = contractAddress, memKeyPair = none(MembershipKeyPair), diff --git a/vendor/nim-libbacktrace/vendor/libbacktrace-upstream/libtool b/vendor/nim-libbacktrace/vendor/libbacktrace-upstream/libtool index 72dd64d11..6341c0e70 100755 --- a/vendor/nim-libbacktrace/vendor/libbacktrace-upstream/libtool +++ b/vendor/nim-libbacktrace/vendor/libbacktrace-upstream/libtool @@ -2,7 +2,7 @@ # libtool - Provide generalized library-building support services. # Generated automatically by config.status (libbacktrace) version-unused -# Libtool was configured on host fv-az165-850: +# Libtool was configured on host fv-az213-574: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, diff --git a/waku/v2/protocol/waku_rln_relay/waku_rln_relay_types.nim b/waku/v2/protocol/waku_rln_relay/waku_rln_relay_types.nim index 59197fa8f..7d66a44a3 100644 --- a/waku/v2/protocol/waku_rln_relay/waku_rln_relay_types.nim +++ b/waku/v2/protocol/waku_rln_relay/waku_rln_relay_types.nim @@ -92,7 +92,7 @@ when defined(rln) or (not defined(rln) and not defined(rlnzerokit)): membershipIndex*: MembershipIndex membershipContractAddress*: Address ethClientAddress*: string - ethAccountAddress*: Address + ethAccountAddress*: Option[Address] # this field is required for signing transactions # TODO may need to erase this ethAccountPrivateKey when is not used # TODO may need to make ethAccountPrivateKey mandatory @@ -116,7 +116,7 @@ when defined(rlnzerokit): membershipIndex*: MembershipIndex membershipContractAddress*: Address ethClientAddress*: string - ethAccountAddress*: Address + ethAccountAddress*: Option[Address] # this field is required for signing transactions # TODO may need to erase this ethAccountPrivateKey when is not used # TODO may need to make ethAccountPrivateKey mandatory diff --git a/waku/v2/protocol/waku_rln_relay/waku_rln_relay_utils.nim b/waku/v2/protocol/waku_rln_relay/waku_rln_relay_utils.nim index 8d371fe58..867309346 100644 --- a/waku/v2/protocol/waku_rln_relay/waku_rln_relay_utils.nim +++ b/waku/v2/protocol/waku_rln_relay/waku_rln_relay_utils.nim @@ -189,7 +189,7 @@ proc toMembershipIndex(v: UInt256): MembershipIndex = let result: MembershipIndex = cast[MembershipIndex](v) return result -proc register*(idComm: IDCommitment, ethAccountAddress: Address, ethAccountPrivKey: keys.PrivateKey, ethClientAddress: string, membershipContractAddress: Address, registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)): Future[Result[MembershipIndex, string]] {.async.} = +proc register*(idComm: IDCommitment, ethAccountAddress: Option[Address], ethAccountPrivKey: keys.PrivateKey, ethClientAddress: string, membershipContractAddress: Address, registrationHandler: Option[RegistrationHandler] = none(RegistrationHandler)): Future[Result[MembershipIndex, string]] {.async.} = # TODO may need to also get eth Account Private Key as PrivateKey ## registers the idComm into the membership contract whose address is in rlnPeer.membershipContractAddress @@ -199,7 +199,8 @@ proc register*(idComm: IDCommitment, ethAccountAddress: Address, ethAccountPrivK except: return err("could not connect to the Ethereum client") - web3.defaultAccount = ethAccountAddress + if ethAccountAddress.isSome(): + web3.defaultAccount = ethAccountAddress.get() # set the account private key web3.privateKey = some(ethAccountPrivKey) # set the gas price twice the suggested price in order for the fast mining @@ -920,7 +921,7 @@ proc subscribeToMemberRegistrations(web3: Web3, contractAddress: Address, handle do (err: CatchableError): error "Error from subscription: ", err=err.msg -proc subscribeToGroupEvents(ethClientUri: string, ethAccountAddress: Address, contractAddress: Address, blockNumber: string = "0x0", handler: RegistrationEventHandler) {.async, gcsafe.} = +proc subscribeToGroupEvents(ethClientUri: string, ethAccountAddress: Option[Address] = none(Address), contractAddress: Address, blockNumber: string = "0x0", handler: RegistrationEventHandler) {.async, gcsafe.} = ## connects to the eth client whose URI is supplied as `ethClientUri` ## subscribes to the `MemberRegistered` event emitted from the `MembershipContract` which is available on the supplied `contractAddress` ## it collects all the events starting from the given `blockNumber` @@ -1052,7 +1053,7 @@ proc mountRlnRelayStatic*(node: WakuNode, proc mountRlnRelayDynamic*(node: WakuNode, ethClientAddr: string = "", - ethAccAddr: web3.Address, + ethAccountAddress: Option[web3.Address] = none(web3.Address), ethAccountPrivKeyOpt: Option[keys.PrivateKey], memContractAddr: web3.Address, memKeyPair: Option[MembershipKeyPair] = none(MembershipKeyPair), @@ -1090,7 +1091,7 @@ proc mountRlnRelayDynamic*(node: WakuNode, keyPair = keyPairOpt.get() # register the rln-relay peer to the membership contract waku_rln_registration_duration_seconds.nanosecondTime: - let regIndexRes = await register(idComm = keyPair.idCommitment, ethAccountAddress = ethAccAddr, ethAccountPrivKey = ethAccountPrivKeyOpt.get(), ethClientAddress = ethClientAddr, membershipContractAddress = memContractAddr, registrationHandler = registrationHandler) + let regIndexRes = await register(idComm = keyPair.idCommitment, ethAccountAddress = ethAccountAddress, ethAccountPrivKey = ethAccountPrivKeyOpt.get(), ethClientAddress = ethClientAddr, membershipContractAddress = memContractAddr, registrationHandler = registrationHandler) # check whether registration is done if regIndexRes.isErr(): debug "membership registration failed", err=regIndexRes.error() @@ -1109,7 +1110,7 @@ proc mountRlnRelayDynamic*(node: WakuNode, membershipIndex: rlnIndex, membershipContractAddress: memContractAddr, ethClientAddress: ethClientAddr, - ethAccountAddress: ethAccAddr, + ethAccountAddress: ethAccountAddress, ethAccountPrivateKey: ethAccountPrivKeyOpt, rlnInstance: rln, pubsubTopic: pubsubTopic, @@ -1186,18 +1187,24 @@ proc mount(node: WakuNode, info "WakuRLNRelay is mounted successfully", pubsubtopic=conf.rlnRelayPubsubTopic, contentTopic=conf.rlnRelayContentTopic return ok(true) else: # mount the rln relay protocol in the on-chain/dynamic mode - echo "setting up waku-rln-relay in on-chain mode... " + debug "setting up waku-rln-relay in on-chain mode... " - debug "on-chain parameters", contractAddress=conf.rlnRelayEthContractAddress + debug "on-chain setup parameters", contractAddress=conf.rlnRelayEthContractAddress # read related inputs to run rln-relay in on-chain mode and do type conversion when needed let - ethAccountAddr = web3.fromHex(web3.Address, conf.rlnRelayEthAccountAddress) ethClientAddr = conf.rlnRelayEthClientAddress ethMemContractAddress = web3.fromHex(web3.Address, conf.rlnRelayEthContractAddress) var ethAccountPrivKeyOpt = none(keys.PrivateKey) + var ethAccountAddressOpt = none(Address) + var credentials = none(RlnMembershipCredentials) + var res: RlnRelayResult[bool] + if conf.rlnRelayEthAccountPrivateKey != "": ethAccountPrivKeyOpt = some(keys.PrivateKey(SkSecretKey.fromHex(conf.rlnRelayEthAccountPrivateKey).value)) - + + if conf.rlnRelayEthAccountAddress != "": + ethAccountAddressOpt = some(web3.fromHex(web3.Address, conf.rlnRelayEthAccountAddress)) + # if the rlnRelayCredPath config option is non-empty, then rln-relay credentials should be persisted # if the path does not contain any credential file, then a new set is generated and pesisted in the same path # if there is a credential file, then no new credentials are generated, instead the content of the file is read and used to mount rln-relay @@ -1207,41 +1214,54 @@ proc mount(node: WakuNode, # check if there is an rln-relay credential file in the supplied path if fileExists(rlnRelayCredPath): # retrieve rln-relay credential - var credentials = readPersistentRlnCredentials(rlnRelayCredPath) - # mount rln-relay with the provided rln-relay credential - let res = waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr, - memKeyPair = some(credentials.membershipKeyPair), memIndex = some(credentials.rlnIndex), ethAccAddr = ethAccountAddr, - ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic, contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler, registrationHandler = registrationHandler) - if res.isErr: - return err("dynamic rln-relay could not be mounted: " & res.error()) + credentials = some(readPersistentRlnCredentials(rlnRelayCredPath)) else: # there is no credential file available in the supplied path # mount the rln-relay protocol leaving rln-relay credentials arguments unassigned # this infroms mountRlnRelayDynamic proc that new credentials should be generated and registered to the membership contract info "no rln credential is provided" - let res = waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr, - ethAccAddr = ethAccountAddr, ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic, - contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler, registrationHandler = registrationHandler) - if res.isErr: - return err("dynamic rln-relay could not be mounted: " & res.error()) - # Persist generated credentials - var rlnMembershipCredentials = - RlnMembershipCredentials(membershipKeyPair: node.wakuRlnRelay.membershipKeyPair, rlnIndex: node.wakuRlnRelay.membershipIndex) + + if credentials.isSome(): + # mount rln-relay in on-chain mode, with credentials that were read or generated + res = waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, + ethClientAddr = ethClientAddr, + ethAccountAddress = ethAccountAddressOpt, + ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, + pubsubTopic = conf.rlnRelayPubsubTopic, + contentTopic = conf.rlnRelayContentTopic, + spamHandler = spamHandler, + registrationHandler = registrationHandler, + memKeyPair = some(credentials.get().membershipKeyPair), + memIndex = some(credentials.get().rlnIndex)) + else: + # mount rln-relay in on-chain mode, with the provided private key + res = waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, + ethClientAddr = ethClientAddr, + ethAccountAddress = ethAccountAddressOpt, + ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, + pubsubTopic = conf.rlnRelayPubsubTopic, + contentTopic = conf.rlnRelayContentTopic, + spamHandler = spamHandler, + registrationHandler = registrationHandler) + # TODO should be replaced with key-store with proper encryption # persist rln credential - writeFile(rlnRelayCredPath, pretty(%rlnMembershipCredentials)) + credentials = some(RlnMembershipCredentials(rlnIndex: node.wakuRlnRelay.membershipIndex, + membershipKeyPair: node.wakuRlnRelay.membershipKeyPair)) + writeFile(rlnRelayCredPath, pretty(%credentials.get())) + else: # do not persist or use a persisted rln-relay credential # a new credential will be generated during the mount process but will not be persisted info "no need to persist or use a persisted rln-relay credential" - let res = waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr, - ethAccAddr = ethAccountAddr, ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic, + res = waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr, + ethAccountAddress = ethAccountAddressOpt, ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic, contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler, registrationHandler = registrationHandler) - if res.isErr: + + if res.isErr(): return err("dynamic rln-relay could not be mounted: " & res.error()) - - return ok(true) + return ok(res.value()) proc mountRlnRelay*(node: WakuNode,