chore: update smart contracts and documentation

This commit is contained in:
Richard Ramos 2023-08-21 15:10:32 -04:00 committed by richΛrd
parent 0b943caaa8
commit f62ba67a92
16 changed files with 599 additions and 1243 deletions

6
.gitignore vendored
View File

@ -64,6 +64,12 @@ Icon
# Nix
result
# Solidity files
waku/v2/protocol/rln/contracts/*.abi
waku/v2/protocol/rln/contracts/*.sol
waku/v2/protocol/rln/contracts/*.bin
# Thumbnails
._*

3
.gitmodules vendored
View File

@ -0,0 +1,3 @@
[submodule "waku/v2/protocol/rln/contracts/rln-contract"]
path = waku/v2/protocol/rln/contracts/rln-contract
url = git@github.com:vacp2p/rln-contract.git

View File

@ -23,17 +23,12 @@ func getMembershipFee(ctx context.Context, rlnContract *contracts.RLN) (*big.Int
return rlnContract.MEMBERSHIPDEPOSIT(&bind.CallOpts{Context: ctx})
}
func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *contracts.RLN, idComm rln.IDCommitment, chainID *big.Int) (rln.MembershipIndex, error) {
// check if the contract exists by calling a static function
membershipFee, err := getMembershipFee(ctx, rlnContract)
if err != nil {
return 0, err
}
func buildTransactor(ctx context.Context, membershipFee *big.Int, chainID *big.Int) (*bind.TransactOpts, error) {
auth, err := bind.NewKeyedTransactorWithChainID(options.ETHPrivateKey, chainID)
if err != nil {
return 0, err
return nil, err
}
auth.Value = membershipFee
auth.Context = ctx
auth.GasLimit = options.ETHGasLimit
@ -44,7 +39,7 @@ func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *con
nonce := &big.Int{}
auth.Nonce, ok = nonce.SetString(options.ETHNonce, 10)
if !ok {
return 0, errors.New("invalid nonce value")
return nil, errors.New("invalid nonce value")
}
}
@ -52,7 +47,7 @@ func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *con
gasFeeCap := &big.Int{}
auth.GasFeeCap, ok = gasFeeCap.SetString(options.ETHGasFeeCap, 10)
if !ok {
return 0, errors.New("invalid gas fee cap value")
return nil, errors.New("invalid gas fee cap value")
}
}
@ -60,7 +55,7 @@ func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *con
gasTipCap := &big.Int{}
auth.GasTipCap, ok = gasTipCap.SetString(options.ETHGasTipCap, 10)
if !ok {
return 0, errors.New("invalid gas tip cap value")
return nil, errors.New("invalid gas tip cap value")
}
}
@ -68,10 +63,25 @@ func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *con
gasPrice := &big.Int{}
auth.GasPrice, ok = gasPrice.SetString(options.ETHGasPrice, 10)
if !ok {
return 0, errors.New("invalid gas price value")
return nil, errors.New("invalid gas price value")
}
}
return auth, nil
}
func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *contracts.RLN, idComm rln.IDCommitment, chainID *big.Int) (rln.MembershipIndex, error) {
// check if the contract exists by calling a static function
membershipFee, err := getMembershipFee(ctx, rlnContract)
if err != nil {
return 0, err
}
auth, err := buildTransactor(ctx, membershipFee, chainID)
if err != nil {
return 0, err
}
log.Debug("registering an id commitment", zap.Binary("idComm", idComm[:]))
// registers the idComm into the membership contract whose address is in rlnPeer.membershipContractAddress
@ -80,18 +90,18 @@ func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *con
return 0, fmt.Errorf("transaction error: %w", err)
}
url := ""
explorerURL := ""
switch chainID.Int64() {
case 1:
url = "https://etherscan.io"
explorerURL = "https://etherscan.io"
case 5:
url = "https://goerli.etherscan.io"
explorerURL = "https://goerli.etherscan.io"
case 11155111:
url = "https://sepolia.etherscan.io"
explorerURL = "https://sepolia.etherscan.io"
}
if url != "" {
logger.Info(fmt.Sprintf("transaction broadcasted, find details of your registration transaction in %s/tx/%s", url, tx.Hash()))
if explorerURL != "" {
logger.Info(fmt.Sprintf("transaction broadcasted, find details of your registration transaction in %s/tx/%s", explorerURL, tx.Hash()))
} else {
logger.Info("transaction broadcasted.", zap.String("transactionHash", tx.Hash().String()))
}
@ -113,7 +123,7 @@ func register(ctx context.Context, ethClient *ethclient.Client, rlnContract *con
return 0, err
}
var eventIDComm rln.IDCommitment = rln.BigIntToBytes32(evt.Pubkey)
var eventIDComm rln.IDCommitment = rln.BigIntToBytes32(evt.IdCommitment)
log.Debug("information extracted from tx log", zap.Uint64("blockNumber", evt.Raw.BlockNumber), logging.HexString("idCommitment", eventIDComm[:]), zap.Uint64("index", evt.Index.Uint64()))

View File

@ -1,33 +1,28 @@
# 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.
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 Sepolia 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.
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
To complete this tutorial, you will need 1) an account with at least `0.001` ethers on the Goerli testnet and 2) a hosted node on the Goerli testnet.
In case you are not familiar with either of these two steps, you may follow the following tutorial to fulfill the [prerequisites of running on-chain spam-protected chat2](./pre-requisites-of-running-on-chain-spam-protected-chat2.md).
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.
To complete this tutorial, you will need
1. An rln keystore file with credentials to the rln membership smart contract you wish to use. You may obtain this by registering to the smart contract and generating a keystore. It is possible to use go-waku to register into the smart contract:
```
make
./build/waku generate-rln-credentials --eth-account-private-key=<private-key> --eth-contract-address=<0x000...> --eth-client-address=<eth-client-rpc-or-wss-endpoint> --cred-path=rlnKeystore.json
```
## Overview
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 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.
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.
Once the transaction is mined and the registration is successful, the registered credential will get displayed on the console of your chat2 client.
At a high level, when a chat2 client is run with Waku-RLN-Relay mounted in on-chain mode, the passed in 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-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.
In the following test setting, the chat2 clients are to be connected to the Waku test fleets as their first hop.
The test fleets will act as routers and are also set to run Waku-RLN-Relay over the same pubsub topic and content topic as chat2 clients i.e., the default pubsub topic of `/waku/2/default-waku/proto` and the content topic of `/toy-chat/2/luzhou/proto`.
The test fleets will act as routers and are also set to run Waku-RLN-Relay over the same pubsub topic and content topic as chat2 clients i.e., the default pubsub topic of `/waku/2/default-waku/proto` and the content topic of `/toy-chat/3/mingde/proto`.
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.
In fact, all the chat2 clients are also capable of catching and dropping spam messages if they receive any.
@ -48,7 +43,7 @@ git clone https://github.com/waku-org/go-waku
cd go-waku
```
## Build chat2
```
```bash
make chat2
```
@ -56,34 +51,40 @@ make chat2
Run the following command to set up your chat2 client.
```
./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=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --rln-relay-eth-client-address=xxxx
```bash
./build/chat2 --fleet=test \
--content-topic=/toy-chat/3/mingde/proto \
--rln-relay=true \
--rln-relay-dynamic=true \
--rln-relay-eth-contract-address=0x9C09146844C1326c2dBC41c451766C7138F88155 \
--rln-relay-cred-path=xxx/xx/rlnKeystore.json \
--rln-relay-cred-password=xxxx \
--rln-relay-eth-client-address=xxxx
```
In this command
- 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/3/mingde/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-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 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).
- 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).
- the `--rln-relay-eth-client-address` is the WebSocket address of the hosted node on the Goerli testnet.
The current address of the contract is `0x9C09146844C1326c2dBC41c451766C7138F88155`.
You may check the state of the contract on the [Sepolia testnet](https://sepolia.etherscan.io/address/0x9C09146844C1326c2dBC41c451766C7138F88155).
- the `--rln-relay-cred-path` option denotes the path to the keystore file described above
- the `--rln-relay-cred-password` option denotes the password to the keystore
- the `rln-relay-eth-client-address` is the WebSocket address of the hosted node on the Sepolia testnet.
You need to replace the `xxxx` with the actual node's address.
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).
For `--rln-relay-eth-client-address`, if you do not know how to obtain it, 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, and using a different `--tcp-port`.
using the `--rln-relay-cred-path` flag, specifying in each client a different path to store the credentials.
Once you run the command, you will see the following message:
```
Setting up dynamic rln...
```
At this phase, your RLN credential are getting created and a transaction is being sent to the membership smart contract.
It will take some time for the transaction to be finalized. Afterwards, messages related to setting up the connections of your chat app will be shown,
At this phase, RLN is being setup by obtaining the membership information from the smart contract. Afterwards, messages related to setting up the connections of your chat app will be shown,
the content may differ on your screen though:
```
INFO: Welcome, Anonymous!
@ -145,9 +146,13 @@ The reason is that under the hood a zero-knowledge proof is being generated and
Try to spam the network by violating the message rate limit i.e.,
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/3/mingde/proto` as your chat client.
Your spam activity will be detected by them and your message will not reach the rest of the chat clients.
You can check this by running a second chat user and verifying that spam messages are not displayed as they are filtered by the test fleets.
Furthermore, the chat client will prompt you with the following warning message indicating that the message rate is being violated:
```
ERROR: message rate violation!
```
A sample test scenario is illustrated in the [Sample test output section](#sample-test-output).
Once you are done with the test, make sure you close all the chat2 clients by typing the `/exit` command.
@ -156,28 +161,32 @@ Once you are done with the test, make sure you close all the chat2 clients by ty
Bye!
```
## How to persist and reuse RLN credential
## How to reuse RLN credential
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.
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 a new credential and will use, instead, the persisted RLN credential.
You may pass the `--rln-relay-cred-path` config option to specify a path to a file for retrieving persisted RLN credentials.
If the keystore exists in the path provided, it is used, and will default to the 0th element in the credential array.
If the keystore does not exist in the path provided, a new keystore will be created and added to the directory it was supposed to be in.
You may provide an index to the credential you wish to use by passing the `--rln-relay-cred-index` config option.
You may provide an index to the membership you wish to use (within the same membership set) by passing the `--rln-relay-membership-group-index` config option.
```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=./
./build/chat2 --fleet=test \
--content-topic=/toy-chat/3/mingde/proto \
--rln-relay=true \
--rln-relay-dynamic=true \
--rln-relay-eth-contract-address=0x9C09146844C1326c2dBC41c451766C7138F88155 \
--rln-relay-eth-client-address=your_sepolia_node \
--rln-relay-cred-path=./rlnKeystore.json \
--rln-relay-cred-password=your_password \
--rln-relay-membership-index=0 \
--rln-relay-membership-group-index=0
```
# 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-private-key`, and `--rln-relay-eth-client-address` in the following code snippets are junk and not valid.
Note that the value used for `--rln-relay-eth-client-address` in the following code snippets is junk and not valid.
The two chat clients namely `Alice` and `Bob` are connected to the test fleets.
`Alice` sends 4 messages i.e., `message1`, `message2`, `message3`, and `message4`.
@ -187,9 +196,11 @@ The test fleets do not relay `message3` further, hence `Bob` never receives it.
You can check this fact by looking at `Bob`'s console, where `message3` is missing.
**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=0x9C09146844C1326c2dBC41c451766C7138F88155 --rln-relay-cred-path=rlnKeystore.json --rln-relay-cred-password=password --rln-relay-eth-client-address=wss://sepolia.infura.io/ws/v3/12345678901234567890123456789012 --nickname=Alice
```
./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=./path/to/alice/folder --nickname=Alice
```
Seting up dynamic rln
INFO: Welcome, Alice!
INFO: type /help to see available commands
@ -235,9 +246,11 @@ INFO RLN Epoch: 165886593
```
**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=0x9C09146844C1326c2dBC41c451766C7138F88155 --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 --nickname=Bob
```
./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=./path/to/bob/folder --nickname=Bob
```
Seting up dynamic rln
INFO: Welcome, Bob!
INFO: type /help to see available commands

View File

@ -0,0 +1,111 @@
In this tutotial you will learn how to:
1. Create Sepolia Ethereum Account and obtain its private key.
2. Obtain Sepolia Ethers from faucet.
3. Set up a hosted node on Sepolia Testnet using Infura.
If you already have an Ethereum account with sufficient ethers on the Sepolia testnet then you can skip the first two sections.
## Creating Sepolia Ethereum Account and obtaining its private key
1. Download and install Metamask. [https://metamask.io/download/](https://metamask.io/download/)
2. Create a new wallet and save your secret recovery key.
![](https://i.imgur.com/HEOI0kp.jpg)
3. Login to Metamask.
![](https://i.imgur.com/zFduIV8.jpg)
4. You should already see an account created. As you can see on top right, it should be pointing to Ethereum mainnet.
![](https://i.imgur.com/gk3TWUd.jpg)
5. You can use the same account for different networks. For Waku we need to connect to the Sepolia test network.
6. You can switch to a test network by clicking on the drop down menu. Select Sepolia test network for Waku:
![](https://i.imgur.com/kbuup6y.jpg)
7. Click on Show/hide test networks.
8. Enable “Show Test Networks".
![](https://i.imgur.com/02x7iSX.jpg)
![](https://i.imgur.com/UFsoRHR.jpg)
9. Close the settings and now you should see the test networks in the drop down on the top right.
![](https://i.imgur.com/leSYt4z.jpg)
10. Switch to Sepolia Test Network.
11. You can see that the same account can be used with different networks. But note that the ETH balance on different networks are different and are different tokens.
![](https://i.imgur.com/Y7YkuEe.jpg)
12. Now to export your private key for the account, if needed, please click on the three dots beside the account.
![](https://i.imgur.com/9BlBmhT.jpg)
13. Click on Account Details.
14. Click on Export Private Key.
![](https://i.imgur.com/7g6SyuX.jpg)
15. Enter your Metamask password when prompted.
![](https://i.imgur.com/VOojHY5.jpg)
16. You will be shown the private key. Copy it as needed.
Obtain Sepolia Ethers from faucet
---
1. Ethers on Sepolia test networks can be obtained from different faucets.
2. One of the faucets is as follows:
1. [https://sepoliafaucet.com//](https://sepoliafaucet.com/)
(NOTE: We have not tested the security of these faucets so please feel free to do your own research or obtain Sepolia ethers from other faucets if needed.)
3. Please follow the instructions on the webpages of these faucets.
4. A lot of faucets limit the Sepolia ETH to 0.05 ETH/day.
5. To obtain more eth, you can do some POW mining. One of those POW faucet is:
[https://sepolia-faucet.pk910.de/](https://sepolia-faucet.pk910.de/)
6. Enter your Eth account address, accept Captcha and start mining.
![](https://i.imgur.com/IvHNsei.jpg)
7. You can see the estimated Sepolia ETH mined per hour. Each session is restricted to a few hours.
![](https://i.imgur.com/qTWwyNr.jpg)
8. When you exceed the hour limit of the session, then the mining will be stopped.
9. Alternatively, stop the mining when mined enough sepolia ether.
10. Do not forget to claim your sepolia ether.
![](https://i.imgur.com/cGCSexB.jpg)
Setting up a hosted node on Sepolia Testnet using Infura
---
(Note: Infura provides a simple straight-forward way of setting up endpoints for interaction with the Ethereum chain and the Waku RLN smart contract without having to run a dedicated Ethereum node. Setting up infura is not mandatory. Operators concerned with the centralized aspect introduced by infura can setup their own node.)
1. Sign up to infura if you do not have an account already. [https://infura.io/register](https://infura.io/register)
![](https://i.imgur.com/SyLaG6s.jpg)
2. After registering and verifying the account, create a new project using Ethereum and give it a name.
![](https://i.imgur.com/fJbNqwd.jpg)
3. After creating the project, you will be presented with a dashboard like follows. Note that your Project Id and secret will be different.
![](imgs/infura-dashboard-mainnet.png)
4. Select Sepolia network in Endpoints.
![](https://i.imgur.com/RgmH7C1.png)
5. You can find the endpoints for the hosted node using https and wss. The wss endpoint is the relevant one for connecting the waku node to the RLN contract on Sepolia network. Like follows:
![](https://i.imgur.com/xqbOcOH.png)
6. You can change security settings or view usage options as required in the dashboard.
7. Congratulations, you are now ready to use the Infura node.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,22 @@
# RLN Contracts
### Requirements:
- Node.js
- Go
- [solcjs 0.8.15](https://github.com/ethereum/solc-js)
- [abigen](https://github.com/ethereum/go-ethereum/tree/master/cmd/abigen)
### Build
1. Install solcjs with `npm install -g solc@0.8.15`
2. Clone [go-ethereum](https://github.com/ethereum/go-ethereum) and install `abigen`
```
cd $GOPATH/src/github.com/ethereum/go-ethereum
$ go install ./cmd/abigen
```
3. Execute `go generate` to create go bindings for the RLN smart contracts
```
go generate
```
### Notes
Follow https://github.com/vacp2p/rln-contract for updates on solc versions

File diff suppressed because one or more lines are too long

View File

@ -1,96 +0,0 @@
pragma solidity ^0.7.4;
import { IPoseidonHasher } from "./crypto/PoseidonHasher.sol";
contract RLN {
uint256 public immutable MEMBERSHIP_DEPOSIT;
uint256 public immutable DEPTH;
uint256 public immutable SET_SIZE;
uint256 public pubkeyIndex = 0;
mapping(uint256 => uint256) public members;
IPoseidonHasher public poseidonHasher;
event MemberRegistered(uint256 pubkey, uint256 index);
event MemberWithdrawn(uint256 pubkey, uint256 index);
constructor(
uint256 membershipDeposit,
uint256 depth,
address _poseidonHasher
) public {
MEMBERSHIP_DEPOSIT = membershipDeposit;
DEPTH = depth;
SET_SIZE = 1 << depth;
poseidonHasher = IPoseidonHasher(_poseidonHasher);
}
function register(uint256 pubkey) external payable {
require(pubkeyIndex < SET_SIZE, "RLN, register: set is full");
require(msg.value == MEMBERSHIP_DEPOSIT, "RLN, register: membership deposit is not satisfied");
_register(pubkey);
}
function registerBatch(uint256[] calldata pubkeys) external payable {
require(pubkeyIndex + pubkeys.length <= SET_SIZE, "RLN, registerBatch: set is full");
require(msg.value == MEMBERSHIP_DEPOSIT * pubkeys.length, "RLN, registerBatch: membership deposit is not satisfied");
for (uint256 i = 0; i < pubkeys.length; i++) {
_register(pubkeys[i]);
}
}
function _register(uint256 pubkey) internal {
members[pubkeyIndex] = pubkey;
emit MemberRegistered(pubkey, pubkeyIndex);
pubkeyIndex += 1;
}
function withdrawBatch(
uint256[] calldata secrets,
uint256[] calldata pubkeyIndexes,
address payable[] calldata receivers
) external {
uint256 batchSize = secrets.length;
require(batchSize != 0, "RLN, withdrawBatch: batch size zero");
require(batchSize == pubkeyIndexes.length, "RLN, withdrawBatch: batch size mismatch pubkey indexes");
require(batchSize == receivers.length, "RLN, withdrawBatch: batch size mismatch receivers");
for (uint256 i = 0; i < batchSize; i++) {
_withdraw(secrets[i], pubkeyIndexes[i], receivers[i]);
}
}
function withdraw(
uint256 secret,
uint256 _pubkeyIndex,
address payable receiver
) external {
_withdraw(secret, _pubkeyIndex, receiver);
}
function _withdraw(
uint256 secret,
uint256 _pubkeyIndex,
address payable receiver
) internal {
require(_pubkeyIndex < SET_SIZE, "RLN, _withdraw: invalid pubkey index");
require(members[_pubkeyIndex] != 0, "RLN, _withdraw: member doesn't exist");
require(receiver != address(0), "RLN, _withdraw: empty receiver address");
// derive public key
uint256 pubkey = hash([secret, 0]);
require(members[_pubkeyIndex] == pubkey, "RLN, _withdraw: not verified");
// delete member
members[_pubkeyIndex] = 0;
// refund deposit
receiver.transfer(MEMBERSHIP_DEPOSIT);
emit MemberWithdrawn(pubkey, _pubkeyIndex);
}
function hash(uint256[2] memory input) internal view returns (uint256) {
return poseidonHasher.hash(input);
}
}

View File

@ -1,535 +0,0 @@
// https://github.com/kilic/rlnapp/blob/master/packages/contracts/contracts/crypto/PoseidonHasher.sol
pragma solidity 0.7.4;
interface IPoseidonHasher {
function hash(uint256[2] memory input) external pure returns (uint256 result);
function identity() external pure returns (uint256);
}
contract PoseidonHasher is IPoseidonHasher {
uint256 constant Q = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
uint256 constant C0 = 2768970367241139781802170833007148522174069744848643939234067191877771423371;
uint256 constant C1 = 6468574107656347268529237497718336587709069456280471580424455063721832719771;
uint256 constant C2 = 18794671303815708509784162368644133457448839260573151733485130900959816547847;
uint256 constant C3 = 21495479230478098685877232964279351350768322664786520160088149860043275231591;
uint256 constant C4 = 13499990804456294376331975175669076043666672782766959528979369127842395667962;
uint256 constant C5 = 11128727858753328237562379127901473551876426168355298792273038389175814738273;
uint256 constant C6 = 6174623859769212836350518599861056828848352474434521101649917228563284157731;
uint256 constant C7 = 731429061815452030222739129549549044853294286077603862495031070831228988506;
uint256 constant C8 = 18691825946094184197601861261718857711439992232978967087150603050561229972879;
uint256 constant C9 = 6901715409529528992021081413007214967207374659260807285380744444309443019002;
uint256 constant C10 = 7889774703159213060685393199720756541539275646424166159037924832893670779999;
uint256 constant C11 = 19148164181730036907570646123652401621475121269795476659255226436085540432812;
uint256 constant C12 = 356519004282890736138910009474234839367086357569508205089190200287135015343;
uint256 constant C13 = 5070064330380484074844995745007722918545766490350556589468108281662282971512;
uint256 constant C14 = 17531425645708334340342421865584088711059286683026910061769879104052748058500;
uint256 constant C15 = 920858801565935944623869688790191117976818337296182581403952541435643043455;
uint256 constant C16 = 7671542183617251806500810220803333911317855932989746628699368932279406768167;
uint256 constant C17 = 7881690674485945577862776772342991782415236259307258648854817257894786877801;
uint256 constant C18 = 19155896751615806549889067080381563929649717724892491357642801041215501837659;
uint256 constant C19 = 9657176770419678097838646349393281787292209556252142440714968703151552794280;
uint256 constant C20 = 1376534476338443314506167934949939673567644510933411653555577922098640496938;
uint256 constant C21 = 17373401671868429549652772677366856294616993437583002599910365256220696563780;
uint256 constant C22 = 9746128003951157537728271629364357225604237114762257721895149249266834505625;
uint256 constant C23 = 17782316906978487011972931426261039391542241330560756508577882755911543517908;
uint256 constant C24 = 6589224737393540076643416156354549730831080306137040791236143083907274321011;
uint256 constant C25 = 17321856211701727875100310423669922181823762220382619531116210312384063527081;
uint256 constant C26 = 21321909001724533038371153813693276559530291455431564073497502239396933319818;
uint256 constant C27 = 17849794853142289789836828064662594833303692772683927435966421769162340090898;
uint256 constant C28 = 3469446763321625523201767743510820386262850368964003752018684310306935672122;
uint256 constant C29 = 4411200946062535851397814394775457104021582693964231752948256822578636459939;
uint256 constant C30 = 18626579782117576204277882219675177684589838126472487652629778677837675278662;
uint256 constant C31 = 764261930639154699767774045099363658161006905585481283735008957581415860662;
uint256 constant C32 = 6122983345977564957406231576949193286198709429730716375547595362175192593123;
uint256 constant C33 = 2469188694307740124657403582315280809174737971010077914159812443136587941756;
uint256 constant C34 = 5382605971470296415808536561267917764719132018437742878552512928718168489695;
uint256 constant C35 = 6589667679759352998039311059993721585330589021804485020627575514256149305666;
uint256 constant C36 = 20661471625156349582050865201555079410137144327315643708284763422133754381325;
uint256 constant C37 = 18694584274137621868895160209707042629719656780873050479100267791928497600376;
uint256 constant C38 = 13822590562029956399621741895244911145933359734099212387467069390727913142666;
uint256 constant C39 = 694674849457359992382704784272941309716157308424480468618786287819256378917;
uint256 constant C40 = 18763037144982179742008371677750585549220053470184500098542470704194556690623;
uint256 constant C41 = 18486457976264107916834430437402981813449917200007719339429151501964183082936;
uint256 constant C42 = 6556747954001777118869362753998468478855885460502383141235961204400638463294;
uint256 constant C43 = 12385133754714463216711399717325449316164682530612784512290690756146937377664;
uint256 constant C44 = 19895348036861519723386861870711743699604138662509897355377030959682349375552;
uint256 constant C45 = 16830822151531046474312344756361243376821272897299262546129244900502111682734;
uint256 constant C46 = 20875209030695524214960780268667166557156788659940284813793529164900666593068;
uint256 constant C47 = 8777606742656153264634386709062440729894098167014885703560793183003141571957;
uint256 constant C48 = 3404497983786933300887052921900023151252717521554164668384012034556256626067;
uint256 constant C49 = 2555107629226010512992356367848094165962022522393505508367085820070687884355;
uint256 constant C50 = 15113919336730148565553505760820732613676431799289611544548947520407297443700;
uint256 constant C51 = 12109280671570307231007703707720632582709786369013364642897329602318304275337;
uint256 constant C52 = 14968914070423010632399365015358049892440762915276845426568596163422798377730;
uint256 constant C53 = 19061189532957010364709072574663003871548558794774753349573267371990486123152;
uint256 constant C54 = 8682801373989521576522508447484143687434748406228624907362693631377691698421;
uint256 constant C55 = 10836672514863795455996193088790111107823297731722043988991810099345596059914;
uint256 constant C56 = 15783196349960742821266383686606772431598902255698169764526487081837237805029;
uint256 constant C57 = 2908608383546665417899486637528022511748691900266764564499649456344035921401;
uint256 constant C58 = 11329727236614532496067886659074662970462346457991275919233250048151273297377;
uint256 constant C59 = 5116653167814666817290578004214535117470888177090558374943095066718387153691;
uint256 constant C60 = 13540152826778549413479417002435847356268346234631393477044136590757331815911;
uint256 constant C61 = 7947441526608065582264952807420254797193034288774248212171921641395121801332;
uint256 constant C62 = 1547483282147791156522335107475157206253201614573941966672490820147450725004;
uint256 constant M0 = 10115680371401748607263639966297231210785101245789087039760048681884121897698;
uint256 constant M1 = 7682529184580308813007726368887641784100790067958820768670102409394963579396;
uint256 constant M2 = 3036380094837744536618704667164758501777151816139077990926623931426168668495;
uint256 constant M3 = 462021688665431536448264191536285854244979957674130050775621906384644169421;
uint256 constant M4 = 62665112908715427992420108025470785827183241813778563254523765114425841603;
uint256 constant M5 = 534236519266104271325123542701236478972353175554309786393016883839422407419;
uint256 constant M6 = 5922526147398848214826466482573128257954044394758836008121691281747299315999;
uint256 constant M7 = 10778490508693548114587990025762035374898560218037495485187480124708600063292;
uint256 constant M8 = 13853145901042782779715203529626320031162484246107565810821674712070680357632;
function hash(uint256[2] memory input) external pure override returns (uint256 result) {
return _hash(input);
}
function _hash(uint256[2] memory input) internal pure returns (uint256 result) {
assembly {
let q := Q
let pos := mload(0x40)
mstore(pos, M0)
mstore(add(pos, 32), M1)
mstore(add(pos, 64), M2)
mstore(add(pos, 96), M3)
mstore(add(pos, 128), M4)
// mstore(add(pos, 160), M5)
// mstore(add(pos, 192), M6)
// mstore(add(pos, 224), M7)
// mstore(add(pos, 256), M8)
// use stack intensively
let m5 := M5
let m6 := M6
let m7 := M7
let m8 := M8
let s0 := add(mload(input), C0)
let s1 := add(mload(add(input, 32)), C0)
let s2 := C0
let t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := mulmod(s1, s1, q)
s1 := mulmod(mulmod(t, t, q), s1, q)
t := mulmod(s2, s2, q)
s2 := mulmod(mulmod(t, t, q), s2, q)
t := C1
let z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
let z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := mulmod(z1, z1, q)
z1 := mulmod(mulmod(t, t, q), z1, q)
t := mulmod(s2, s2, q)
s2 := mulmod(mulmod(t, t, q), s2, q)
t := C2
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := mulmod(s1, s1, q)
s1 := mulmod(mulmod(t, t, q), s1, q)
t := mulmod(s2, s2, q)
s2 := mulmod(mulmod(t, t, q), s2, q)
t := C3
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := mulmod(z1, z1, q)
z1 := mulmod(mulmod(t, t, q), z1, q)
t := mulmod(s2, s2, q)
s2 := mulmod(mulmod(t, t, q), s2, q)
t := C4
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C5
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C6
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C7
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C8
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C9
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C10
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C11
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C12
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C13
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C14
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C15
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C16
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C17
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C18
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C19
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C20
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C21
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C22
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C23
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C24
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C25
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C26
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C27
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C28
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C29
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C30
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C31
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C32
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C33
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C34
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C35
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C36
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C37
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C38
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C39
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C40
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C41
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C42
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C43
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C44
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C45
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C46
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C47
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C48
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C49
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C50
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C51
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C52
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C53
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C54
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C55
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C56
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C57
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := C58
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := C59
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := mulmod(z1, z1, q)
z1 := mulmod(mulmod(t, t, q), z1, q)
t := mulmod(s2, s2, q)
s2 := mulmod(mulmod(t, t, q), s2, q)
t := C60
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := mulmod(s1, s1, q)
s1 := mulmod(mulmod(t, t, q), s1, q)
t := mulmod(s2, s2, q)
s2 := mulmod(mulmod(t, t, q), s2, q)
t := C61
z0 := add(add(add(mulmod(s0, mload(pos), q), mulmod(s1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
z1 := add(add(add(mulmod(s0, mload(add(pos, 96)), q), mulmod(s1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(s0, m6, q), mulmod(s1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(z0, z0, q)
z0 := mulmod(mulmod(t, t, q), z0, q)
t := mulmod(z1, z1, q)
z1 := mulmod(mulmod(t, t, q), z1, q)
t := mulmod(s2, s2, q)
s2 := mulmod(mulmod(t, t, q), s2, q)
t := C62
s0 := add(add(add(mulmod(z0, mload(pos), q), mulmod(z1, mload(add(pos, 32)), q)), mulmod(s2, mload(add(pos, 64)), q)), t)
s1 := add(add(add(mulmod(z0, mload(add(pos, 96)), q), mulmod(z1, mload(add(pos, 128)), q)), mulmod(s2, m5, q)), t)
s2 := add(add(add(mulmod(z0, m6, q), mulmod(z1, m7, q)), mulmod(s2, m8, q)), t)
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := mulmod(s1, s1, q)
s1 := mulmod(mulmod(t, t, q), s1, q)
t := mulmod(s2, s2, q)
s2 := mulmod(mulmod(t, t, q), s2, q)
result := s0
}
}
function identity() external pure override returns (uint256) {
return _identity();
}
function _identity() internal pure returns (uint256) {
return 0x2ff267fd23782a5625e6d804f0a7fa700b8dc6084e2e7a5aff7cd4b1c506d30b;
}
}

View File

@ -1,3 +1,5 @@
package contracts
//go:generate abigen -sol ./RLN.sol -pkg contracts -out ./RLN.go
//go:generate solcjs --abi --bin ./rln-contract/contracts/Rln.sol -o ./
//go:generate abigen --abi ./rln-contract_contracts_Rln_sol_RLN.abi --pkg contracts --type RLN --out ./RLN.go --bin ./rln-contract_contracts_Rln_sol_RLN.bin
//go:generate abigen --abi ./rln-contract_contracts_PoseidonHasher_sol_PoseidonHasher.abi --pkg contracts --type PoseidonHasher --out ./PoseidonHasher.go --bin ./rln-contract_contracts_PoseidonHasher_sol_PoseidonHasher.bin

@ -0,0 +1 @@
Subproject commit f99eb2aa0d62bb27631f6ffb4c6161ceb334d2a3

View File

@ -235,7 +235,7 @@ func (gm *DynamicGroupManager) InsertMembers(toInsert *om.OrderedMap) error {
if oldestIndexInBlock == nil {
oldestIndexInBlock = evt.Index
}
idCommitments = append(idCommitments, rln.BigIntToBytes32(evt.Pubkey))
idCommitments = append(idCommitments, rln.BigIntToBytes32(evt.IdCommitment))
}
if len(idCommitments) == 0 {

View File

@ -14,14 +14,14 @@ import (
"github.com/waku-org/go-zerokit-rln/rln"
)
func eventBuilder(blockNumber uint64, removed bool, pubkey int64, index int64) *contracts.RLNMemberRegistered {
func eventBuilder(blockNumber uint64, removed bool, idCommitment int64, index int64) *contracts.RLNMemberRegistered {
return &contracts.RLNMemberRegistered{
Raw: types.Log{
BlockNumber: blockNumber,
Removed: removed,
},
Index: big.NewInt(index),
Pubkey: big.NewInt(pubkey),
Index: big.NewInt(index),
IdCommitment: big.NewInt(idCommitment),
}
}

View File

@ -219,7 +219,7 @@ func GetMembershipCredentials(logger *zap.Logger, credentialsPath string, passwo
return result, nil
}
// Adds a membership credential to the keystore matching the application, appIdentifier and version filters.
// AddMembershipCredentials inserts a membership credential to the keystore matching the application, appIdentifier and version filters.
func AddMembershipCredentials(path string, newIdentityCredential *rln.IdentityCredential, newMembershipGroup MembershipGroup, password string, appInfo AppInfo, separator string) (membershipGroupIndex uint, err error) {
k, err := LoadAppKeystore(path, appInfo, DefaultSeparator)
if err != nil {

View File

@ -83,8 +83,6 @@ func (s *WakuRLNRelayDynamicSuite) SetupTest() {
auth, err := bind.NewKeyedTransactorWithChainID(s.u1PrivKey, chainID)
s.Require().NoError(err)
// TODO: update rln contract
poseidonHasherAddr, _, _, err := contracts.DeployPoseidonHasher(auth, backend)
s.Require().NoError(err)