mirror of https://github.com/status-im/go-waku.git
fix(rln): remove idcommitment and idkey
This commit is contained in:
parent
a231a043b6
commit
3b4dcf3195
|
@ -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
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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())
|
||||||
|
|
10
waku_rln.go
10
waku_rln.go
|
@ -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",
|
||||||
|
|
Loading…
Reference in New Issue