feat(Rln-Relay): Consolidates the input paths of rln credential, chat2 reads rln credential from file only (#1080)

* Consolidates the input paths of rln credential, accepts credential file only

* fixes a typo
This commit is contained in:
Sanaz Taheri Boshrooyeh 2022-08-18 10:35:02 -07:00 committed by GitHub
parent 73df74f8c6
commit 8a6b1cfba6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 51 additions and 42 deletions

View File

@ -22,7 +22,7 @@ This transaction will also transfer `0.001` Ethers to the contract as membership
This amount plus the transaction fee will be deducted from the supplied Goerli account.
Once the transaction is mined and the registration is successful, the registered credential will get displayed on the console of your chat2 client.
You may copy the displayed RLN credential and reuse them for the future execution of the chat2 application.
Proper instructions in this regard is provided in the following [section](#how-to-reuse-rln-credential).
Proper instructions in this regard is provided in the following [section](#how-to-persist-and-reuse-rln-credential).
If you choose not to reuse the same credential, then for each execution, a new registration will take place and more funds will get deducted from your Goerli account.
Under the hood, the chat2 client constantly listens to the membership contract and keeps itself updated with the latest state of the group.
@ -150,19 +150,15 @@ Once you are done with the test, make sure you close all the chat2 clients by ty
quitting...
```
## How to reuse RLN credential
## How to persist and reuse RLN credential
You may reuse your old RLN credential using `rln-relay-membership-index`, `rln-relay-id` and `rln-relay-id-commitment` options.
For instance, if the previously generated credential are
```
your membership index is: xx
your rln identity key is: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
your rln identity commitment key is: 6c6598126ba10d1b70100893b76d7f8d7343eeb8f5ecfd48371b421c5aa6f012
```
Then, the execution command will look like this (inspect the last three config options):
```
./build/chat2 --fleet:test --content-topic:/toy-chat/2/luzhou/proto --rln-relay:true --rln-relay-dynamic:true --eth-mem-contract-address:0x4252105670fe33d2947e8ead304969849e64f2a6 --eth-account-address:your_eth_account --eth-account-privatekey:your_eth_private_key --eth-client-address:your_goerli_node --ports-shift=1 --rln-relay-membership-index:63 --rln-relay-id:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --rln-relay-id-commitment:6c6598126ba10d1b70100893b76d7f8d7343eeb8f5ecfd48371b421c5aa6f012
You may pass the `rln-relay-cred-path` config option to specify a path for 1) persisting RLN credential 2) retrieving persisted RLN credential.
RLN credential is persisted in the `rlnCredentials.txt` file under the specified path.
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 new credential, instead uses the persisted RLN credential.
```
./build/chat2 --fleet:test --content-topic:/toy-chat/2/luzhou/proto --rln-relay:true --rln-relay-dynamic:true --eth-mem-contract-address:0x4252105670fe33d2947e8ead304969849e64f2a6 --eth-account-address:your_eth_account --eth-account-privatekey:your_eth_private_key --eth-client-address:your_goerli_node --ports-shift=1 --rln-relay-cred-path:./
```
# Sample test output

View File

@ -233,7 +233,12 @@ type
desc: "Enable spam protection through rln-relay: true|false",
defaultValue: false
name: "rln-relay" }: bool
rlnRelayCredPath* {.
desc: "The path for peristing rln-relay credential",
defaultValue: ""
name: "rln-relay-cred-path" }: string
rlnRelayMemIndex* {.
desc: "(experimental) the index of node in the rln-relay group: a value between 0-99 inclusive",
defaultValue: MembershipIndex(0)

View File

@ -114,6 +114,11 @@ type
defaultValue: false
name: "rln-relay" }: bool
rlnRelayCredPath* {.
desc: "The path for peristing rln-relay credential",
defaultValue: ""
name: "rln-relay-cred-path" }: string
rlnRelayMemIndex* {.
desc: "(experimental) the index of node in the rln-relay group: a value between 0-99 inclusive",
defaultValue: MembershipIndex(0)

View File

@ -148,7 +148,7 @@ type MessageValidationResult* {.pure.} = enum
# RLN membership key and index files path
const
RLN_CREDENTIALS_FILEPATH* = "rlnCredentials.txt"
RLN_CREDENTIALS_FILENAME* = "rlnCredentials.txt"
# inputs of the membership contract constructor
# TODO may be able to make these constants private and put them inside the waku_rln_relay_utils

View File

@ -998,15 +998,6 @@ proc mountRlnRelayDynamic*(node: WakuNode,
keyPair = memKeyPair.get()
rlnIndex = memIndex.get()
var
rlnMembershipCredentials = RlnMembershipCredentials(membershipKeyPair: keyPair, rlnIndex: rlnIndex)
# Since the files are stored as a raw text file, it is highly susceptible to theft.
# The files needs some encryption to resolve this.
# Write RLN credentials
writeFile(RLN_CREDENTIALS_FILEPATH, pretty(%rlnMembershipCredentials))
# create the WakuRLNRelay
var rlnPeer = WakuRLNRelay(membershipKeyPair: keyPair,
membershipIndex: rlnIndex,
@ -1075,7 +1066,7 @@ proc mountRlnRelay*(node: WakuNode, conf: WakuNodeConf|Chat2Conf, spamHandler: O
error "root mismatch: something went wrong not in Merkle tree construction"
debug "the calculated root", root
info "WakuRLNRelay is mounted successfully", pubsubtopic=conf.rlnRelayPubsubTopic, contentTopic=conf.rlnRelayContentTopic
else:
else: # mount the rln relay protocol in the on-chain/dynamic mode
info " setting up waku-rln-relay in on-chain mode... "
# read related inputs to run rln-relay in on-chain mode and do type conversion when needed
@ -1083,30 +1074,42 @@ proc mountRlnRelay*(node: WakuNode, conf: WakuNodeConf|Chat2Conf, spamHandler: O
ethAccountAddr = web3.fromHex(web3.Address, conf.rlnRelayEthAccount)
ethClientAddr = conf.rlnRelayEthClientAddress
ethMemContractAddress = web3.fromHex(web3.Address, conf.rlnRelayEthMemContractAddress)
rlnRelayId = conf.rlnRelayIdKey
rlnRelayIdCommitmentKey = conf.rlnRelayIdCommitmentKey
rlnRelayIndex = conf.rlnRelayMemIndex
var ethAccountPrivKeyOpt = none(keys.PrivateKey)
if conf.rlnRelayEthAccountPrivKey != "":
ethAccountPrivKeyOpt = some(keys.PrivateKey(SkSecretKey.fromHex(conf.rlnRelayEthAccountPrivKey).value))
# check if the peer has provided its rln credentials
if rlnRelayIdCommitmentKey != "" and rlnRelayId != "":
# type conversation from hex strings to MembershipKeyPair
let keyPair = @[(rlnRelayId, rlnRelayIdCommitmentKey)]
let memKeyPair = keyPair.toMembershipKeyPairs()[0]
# mount the rln relay protocol in the on-chain/dynamic mode
waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
memKeyPair = some(memKeyPair), memIndex = some(rlnRelayIndex), ethAccAddr = ethAccountAddr,
ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic, contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler)
elif fileExists(RLN_CREDENTIALS_FILEPATH):
var credentials = readPersistentRlnCredentials(RLN_CREDENTIALS_FILEPATH)
waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
# 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
if conf.rlnRelayCredPath != "":
let rlnRelayCredPath = joinPath(conf.rlnRelayCredPath, RLN_CREDENTIALS_FILENAME)
debug "rln-relay credential path", rlnRelayCredPath=rlnRelayCredPath
# 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
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)
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"
waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
ethAccAddr = ethAccountAddr, ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic,
contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler)
# Persist generated credentials
var rlnMembershipCredentials =
RlnMembershipCredentials(membershipKeyPair: node.wakuRlnRelay.membershipKeyPair, rlnIndex: node.wakuRlnRelay.membershipIndex)
# TODO should be replaced with key-store with proper encryption
# persist rln credential
writeFile(rlnRelayCredPath, pretty(%rlnMembershipCredentials))
else:
# no rln credential is provided
# mount the rln relay protocol in the on-chain/dynamic mode
info "no rln credential is provided"
# 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"
waitFor node.mountRlnRelayDynamic(memContractAddr = ethMemContractAddress, ethClientAddr = ethClientAddr,
ethAccAddr = ethAccountAddr, ethAccountPrivKeyOpt = ethAccountPrivKeyOpt, pubsubTopic = conf.rlnRelayPubsubTopic,
contentTopic = conf.rlnRelayContentTopic, spamHandler = spamHandler)