fix(rln): remove idcommitment and idkey

This commit is contained in:
Richard Ramos 2022-10-20 17:49:45 -04:00 committed by RichΛrd
parent a231a043b6
commit 3b4dcf3195
9 changed files with 50 additions and 93 deletions

View File

@ -1,9 +1,9 @@
# Spam-protected chat2 application with on-chain group management # Spam-protected chat2 application with on-chain group management
This document is a tutorial on how to run the chat2 application in the spam-protected mode using the Waku-RLN-Relay protocol and with dynamic/on-chain group management. This document is a tutorial on how to run the chat2 application in the spam-protected mode using the Waku-RLN-Relay protocol and with dynamic/on-chain group management.
In the on-chain/dynamic group management, the state of the group members i.e., their identity commitment keys is moderated via a membership smart contract deployed on the Goerli network which is one of the Ethereum testnets. In the on-chain/dynamic group management, the state of the group members i.e., their identity commitment keys is moderated via a membership smart contract deployed on the Goerli network which is one of the Ethereum testnets.
Members can be dynamically added to the group and the group size can grow up to 2^20 members. Members can be dynamically added to the group and the group size can grow up to 2^20 members.
This differs from the prior test scenarios in which the RLN group was static and the set of members' keys was hardcoded and fixed. This differs from the prior test scenarios in which the RLN group was static and the set of members' keys was hardcoded and fixed.
## Prerequisites ## Prerequisites
@ -12,15 +12,17 @@ In case you are not familiar with either of these two steps, you may follow the
Note that the required `0.001` ethers correspond to the registration fee, Note that the required `0.001` ethers correspond to the registration fee,
however, you still need to have more funds in your account to cover the cost of the transaction gas fee. however, you still need to have more funds in your account to cover the cost of the transaction gas fee.
## Overview ## Overview
Figure 1 provides an overview of the interaction of the chat2 clients with the test fleets and the membership contract. Figure 1 provides an overview of the interaction of the chat2 clients with the test fleets and the membership contract.
At a high level, when a chat2 client is run with Waku-RLN-Relay mounted in on-chain mode, it creates RLN credential (i.e., an identity key and an identity commitment key) and At a high level, when a chat2 client is run with Waku-RLN-Relay mounted in on-chain mode, it creates an RLN credential (i.e., an identity key and an identity commitment key) and
sends a transaction to the membership contract to register the corresponding membership identity commitment key. sends a transaction to the membership contract to register the corresponding membership identity commitment key.
This transaction will also transfer `0.001` Ethers to the contract as membership fee. This transaction will also transfer `0.001` Ethers to the contract as a membership fee.
This amount plus the transaction fee will be deducted from the supplied Goerli account. 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. 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. 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. 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. Under the hood, the chat2 client constantly listens to the membership contract and keeps itself updated with the latest state of the group.
@ -29,7 +31,7 @@ The test fleets will act as routers and are also set to run Waku-RLN-Relay over
Spam messages published on the said combination of topics will be caught by the test fleet nodes and will not be routed. Spam messages published on the said combination of topics will be caught by the test fleet nodes and will not be routed.
Note that spam protection does not rely on the presence of the test fleets. Note that spam protection does not rely on the presence of the test fleets.
In fact, all the chat2 clients are also capable of catching and dropping spam messages if they receive any. In fact, all the chat2 clients are also capable of catching and dropping spam messages if they receive any.
You can test it by connecting two chat2 clients (running Waku-RLN-Relay) directly to each others and see they can spot each others' spam activities. You can test it by connecting two chat2 clients (running Waku-RLN-Relay) directly to each other and see if they can spot each other's spam activities.
![](./imgs/rln-relay-chat2-overview.png) ![](./imgs/rln-relay-chat2-overview.png)
Figure 1. Figure 1.
@ -45,7 +47,6 @@ You can test it by connecting two chat2 clients (running Waku-RLN-Relay) directl
git clone https://github.com/status-im/go-waku git clone https://github.com/status-im/go-waku
cd go-waku cd go-waku
``` ```
## Build chat2 ## Build chat2
``` ```
make chat2 make chat2
@ -63,18 +64,19 @@ In this command
- the `--fleet=test` indicates that the chat2 app gets connected to the test fleets. - the `--fleet=test` indicates that the chat2 app gets connected to the test fleets.
- the `toy-chat/2/luzhou/proto` passed to the `--content-topic` option indicates the content topic on which the chat2 application is going to run. - the `toy-chat/2/luzhou/proto` passed to the `--content-topic` option indicates the content topic on which the chat2 application is going to run.
- the `--rln-relay` flag is set to `true` to enable the Waku-RLN-Relay protocol for spam protection. - the `--rln-relay` flag is set to `true` to enable the Waku-RLN-Relay protocol for spam protection.
- the `--rln-relay-dynamic` flag is set to `true` to enable the on-chain mode of Waku-RLN-Relay protocol with dynamic group management. - the `--rln-relay-dynamic` flag is set to `true` to enable the on-chain mode of Waku-RLN-Relay protocol with dynamic group management.
- the `--rln-relay-eth-contract-address` option gets the address of the membership contract. - the `--rln-relay-eth-contract-address` option gets the address of the membership contract.
The current address of the contract is `0x4252105670fe33d2947e8ead304969849e64f2a6`. The current address of the contract is `0x4252105670fe33d2947e8ead304969849e64f2a6`.
You may check the state of the contract on the [Goerli testnet](https://goerli.etherscan.io/address/0x4252105670fe33d2947e8ead304969849e64f2a6). You may check the state of the contract on the [Goerli testnet](https://goerli.etherscan.io/address/0x4252105670fe33d2947e8ead304969849e64f2a6).
- the `--rln-relay-eth-account-private-key` option is for your account private key on the Goerli testnet. - the `--rln-relay-eth-account-private-key` option is for your account private key on the Goerli testnet.
It is made up of 64 hex characters (not sensitive to the `0x` prefix). It is made up of 64 hex characters (not sensitive to the `0x` prefix).
- the `--rln-relay-eth-client-address` should be assigned with the address of a websocket endpoint of the hosted node on the Goerli testnet. - the `--rln-relay-eth-client-address` is the WebSocket address of the hosted node on the Goerli testnet.
You need to replace the `xxxx` with the actual node's websocket endpoint. You need to replace the `xxxx` with the actual node's address.
For the last two config options i.e., `--rln-relay-eth-account-private-key`, and `--rln-relay-eth-client-address`, if you do not know how to obtain those, you may use the following tutorial on the [prerequisites of running on-chain spam-protected chat2](https://github.com/status-im/nwaku/blob/master/docs/tutorial/pre-requisites-of-running-on-chain-spam-protected-chat2.md). For the last three config options i.e., `rln-relay-eth-account-address`, `rln-relay-eth-account-private-key`, and `rln-relay-eth-client-address`, if you do not know how to obtain those, you may use the following tutorial on the [prerequisites of running on-chain spam-protected chat2](./pre-requisites-of-running-on-chain-spam-protected-chat2.md).
> You may set up more than one chat client, using the `--rln-relay-cred-path` flag, specifying in each client a different path to store the credentials. You may set up more than one chat client,
using the `--rln-relay-cred-path` flag, specifying in each client a different path to store the credentials, and using a different `--tcp-port`.
Once you run the command, you will see the following message: Once you run the command, you will see the following message:
``` ```
@ -140,6 +142,7 @@ Thus, if you send two messages less than `10` seconds apart, they are likely to
After sending a chat message, you may experience some delay before the next chat prompt appears. After sending a chat message, you may experience some delay before the next chat prompt appears.
The reason is that under the hood a zero-knowledge proof is being generated and attached to your message. The reason is that under the hood a zero-knowledge proof is being generated and attached to your message.
Try to spam the network by violating the message rate limit i.e., Try to spam the network by violating the message rate limit i.e.,
sending more than one message per epoch. sending more than one message per epoch.
Your messages will be routed via test fleets that are running in spam-protected mode over the same content topic i.e., `/toy-chat/2/luzhou/proto` as your chat client. Your messages will be routed via test fleets that are running in spam-protected mode over the same content topic i.e., `/toy-chat/2/luzhou/proto` as your chat client.
@ -153,20 +156,23 @@ Once you are done with the test, make sure you close all the chat2 clients by ty
Bye! Bye!
``` ```
## 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. You may pass the `--rln-relay-cred-path` config option to specify a path for 1) persisting RLN credentials and 2) retrieving persisted RLN credentials.
For instance, if the previously generated credential are 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.
INFO: RLN config: Otherwise, the chat client does not generate a new credential and will use, instead, the persisted RLN credential.
- Your membership index is: 63
- 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 --rln-relay-eth-contract-address=0x4252105670fe33d2947e8ead304969849e64f2a6 --rln-relay-eth-account-private-key=your_eth_private_key --rln-relay-eth-client-address=your_goerli_node --rln-relay-membership-index=63 --rln-relay-id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --rln-relay-id-commitment:6c6598126ba10d1b70100893b76d7f8d7343eeb8f5ecfd48371b421c5aa6f012
```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-private-key=your_eth_private_key --rln-relay-eth-client-address==your_goerli_node --rln-relay-cred-path:./
```
Note: If you are reusing credentials, you can omit the `--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 --rln-relay-cred-path=./
``` ```
# Sample test output # Sample test output

View File

@ -114,13 +114,10 @@ func execute(options Options) {
} }
if options.RLNRelay.Enable && options.RLNRelay.Dynamic { if options.RLNRelay.Enable && options.RLNRelay.Dynamic {
if options.RLNRelay.IDKey == "" && options.RLNRelay.IDCommitment == "" { err := writeRLNMembershipCredentialsToFile(options.RLNRelay.CredentialsPath, wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex(), wakuNode.RLNRelay().MembershipContractAddress())
// Write membership credentials file only if the idkey and commitment are not specified if err != nil {
err := writeRLNMembershipCredentialsToFile(options.RLNRelay.CredentialsPath, wakuNode.RLNRelay().MembershipKeyPair(), wakuNode.RLNRelay().MembershipIndex(), wakuNode.RLNRelay().MembershipContractAddress()) fmt.Println(err.Error())
if err != nil { return
fmt.Println(err.Error())
return
}
} }
} }

View File

@ -202,16 +202,6 @@ func getFlags() []cli.Flag {
Usage: "Enable waku-rln-relay with on-chain dynamic group management", Usage: "Enable waku-rln-relay with on-chain dynamic group management",
Destination: &options.RLNRelay.Dynamic, Destination: &options.RLNRelay.Dynamic,
}, },
&cli.StringFlag{
Name: "rln-relay-id-key",
Usage: "Rln relay identity secret key as a Hex string",
Destination: &options.RLNRelay.IDKey,
},
&cli.StringFlag{
Name: "rln-relay-id-commitment-key",
Usage: "Rln relay identity commitment key as a Hex string",
Destination: &options.RLNRelay.IDCommitment,
},
&cli.PathFlag{ &cli.PathFlag{
Name: "rln-relay-cred-path", Name: "rln-relay-cred-path",
Usage: "The path for persisting rln-relay credential", Usage: "The path for persisting rln-relay credential",

View File

@ -34,8 +34,6 @@ type RLNRelayOptions struct {
PubsubTopic string PubsubTopic string
ContentTopic string ContentTopic string
Dynamic bool Dynamic bool
IDKey string
IDCommitment string
ETHPrivateKey *ecdsa.PrivateKey ETHPrivateKey *ecdsa.PrivateKey
ETHClientAddress string ETHClientAddress string
MembershipContractAddress common.Address MembershipContractAddress common.Address

View File

@ -70,11 +70,6 @@ func loadMembershipCredentialsFromFile(rlnCredentialsPath string) (node.Membersh
} }
func getMembershipCredentials(options RLNRelayOptions) (credentials node.MembershipCredentials, err error) { func getMembershipCredentials(options RLNRelayOptions) (credentials node.MembershipCredentials, err error) {
valuesWereInput := false
if options.IDKey != "" || options.IDCommitment != "" {
valuesWereInput = true
}
path := options.CredentialsPath path := options.CredentialsPath
if path == "" { if path == "" {
@ -83,31 +78,21 @@ func getMembershipCredentials(options RLNRelayOptions) (credentials node.Members
}, nil }, nil
} }
var osErr error path = filepath.Join(path, RLN_CREDENTIALS_FILENAME)
if !valuesWereInput { _, osErr := os.Stat(path)
path = filepath.Join(path, RLN_CREDENTIALS_FILENAME) if osErr == nil {
if _, osErr = os.Stat(path); osErr == nil { if credentials, err := loadMembershipCredentialsFromFile(path); err != nil {
if credentials, err := loadMembershipCredentialsFromFile(path); err != nil { return node.MembershipCredentials{}, fmt.Errorf("could not read membership credentials file: %w", err)
return node.MembershipCredentials{}, fmt.Errorf("could not read membership credentials file: %w", err) } else {
} else { if (bytes.Equal(credentials.Contract.Bytes(), common.Address{}.Bytes())) {
if (bytes.Equal(credentials.Contract.Bytes(), common.Address{}.Bytes())) { credentials.Contract = options.MembershipContractAddress
credentials.Contract = options.MembershipContractAddress
}
return credentials, nil
} }
return credentials, nil
} }
} }
var keypair *rln.MembershipKeyPair if os.IsNotExist(osErr) {
if valuesWereInput || os.IsNotExist(osErr) {
if options.IDKey != "" && options.IDCommitment != "" {
keypair = new(rln.MembershipKeyPair)
copy((keypair.IDKey)[:], common.FromHex(options.IDKey))
copy((keypair.IDCommitment)[:], common.FromHex(options.IDCommitment))
}
return node.MembershipCredentials{ return node.MembershipCredentials{
Keypair: keypair,
Index: uint(options.MembershipIndex), Index: uint(options.MembershipIndex),
Contract: options.MembershipContractAddress, Contract: options.MembershipContractAddress,
}, nil }, nil

View File

@ -49,8 +49,6 @@ type RLNRelayOptions struct {
PubsubTopic string PubsubTopic string
ContentTopic string ContentTopic string
Dynamic bool Dynamic bool
IDKey string
IDCommitment string
ETHPrivateKey *ecdsa.PrivateKey ETHPrivateKey *ecdsa.PrivateKey
ETHClientAddress string ETHClientAddress string
MembershipContractAddress common.Address MembershipContractAddress common.Address

View File

@ -103,16 +103,9 @@ func getMembershipCredentials(logger *zap.Logger, options Options) (fromFile boo
} }
} }
var keypair *rln.MembershipKeyPair
if os.IsNotExist(err) { if os.IsNotExist(err) {
if options.RLNRelay.IDKey != "" && options.RLNRelay.IDCommitment != "" {
keypair = new(rln.MembershipKeyPair)
copy((keypair.IDKey)[:], common.FromHex(options.RLNRelay.IDKey))
copy((keypair.IDCommitment)[:], common.FromHex(options.RLNRelay.IDCommitment))
}
return false, node.MembershipCredentials{ return false, node.MembershipCredentials{
Keypair: keypair, Keypair: nil,
Index: uint(options.RLNRelay.MembershipIndex), Index: uint(options.RLNRelay.MembershipIndex),
Contract: options.RLNRelay.MembershipContractAddress, Contract: options.RLNRelay.MembershipContractAddress,
}, nil }, nil

View File

@ -114,7 +114,7 @@ func (s *WakuRLNRelayDynamicSuite) TestDynamicGroupManagement() {
RLN: rlnInstance, RLN: rlnInstance,
log: utils.Logger(), log: utils.Logger(),
nullifierLog: make(map[r.Epoch][]r.ProofMetadata), nullifierLog: make(map[r.Epoch][]r.ProofMetadata),
membershipKeyPair: *keyPair, membershipKeyPair: keyPair,
} }
// generate another membership key pair // generate another membership key pair
@ -190,7 +190,7 @@ func (s *WakuRLNRelayDynamicSuite) TestRegistrationProcedure() {
RLN: rlnInstance, RLN: rlnInstance,
log: utils.Logger(), log: utils.Logger(),
nullifierLog: make(map[r.Epoch][]r.ProofMetadata), nullifierLog: make(map[r.Epoch][]r.ProofMetadata),
membershipKeyPair: *keyPair, membershipKeyPair: keyPair,
} }
_, err = rlnPeer.Register(context.TODO()) _, err = rlnPeer.Register(context.TODO())

View File

@ -39,16 +39,6 @@ func rlnFlags() []cli.Flag {
Usage: "Enable waku-rln-relay with on-chain dynamic group management", Usage: "Enable waku-rln-relay with on-chain dynamic group management",
Destination: &options.RLNRelay.Dynamic, Destination: &options.RLNRelay.Dynamic,
}, },
&cli.StringFlag{
Name: "rln-relay-id-key",
Usage: "Rln relay identity secret key as a Hex string",
Destination: &options.RLNRelay.IDKey,
},
&cli.StringFlag{
Name: "rln-relay-id-commitment-key",
Usage: "Rln relay identity commitment key as a Hex string",
Destination: &options.RLNRelay.IDCommitment,
},
&cli.PathFlag{ &cli.PathFlag{
Name: "rln-relay-cred-path", Name: "rln-relay-cred-path",
Usage: "RLN relay membership credentials file", Usage: "RLN relay membership credentials file",