Compare commits

...

69 Commits

Author SHA1 Message Date
cedoor
5fe6e4cd5f chore: v4.0.0-beta.16 2024-07-01 16:29:18 +01:00
Giacomo
e63209914d Add missing implicit method from contract to interface (#814)
refactor(contracts): add missing implicit method from interface
2024-07-01 16:28:15 +01:00
cedoor
504c0f7f9c chore: v4.0.0-beta.15 2024-06-28 11:02:25 +01:00
Cedoor
a1628f635a chore: deploy contracts and replace mumbai with amoy (#809)
* chore: remove unused env variable

* chore: deploy contracts and replace mumbai with amoy

* docs(subgraph): update README.md

* style(subgraph): format code with prettier

* docs(contracts): update deploy command name
2024-06-28 10:59:08 +01:00
cedoor
bb1975a949 chore: v4.0.0-beta.14 2024-06-24 12:41:04 +01:00
Cedoor
b9a163e613 docs: update pull_request_template.md (#807)
Update pull_request_template.md
2024-06-24 12:40:18 +01:00
Cedoor
7ec35c22f8 chore(proof): update @zk-kit/artifacts dep version (#806) 2024-06-24 12:39:31 +01:00
cedoor
f19daf7896 chore: v4.0.0-beta.13 2024-06-18 12:09:38 +01:00
Cedoor
3572f4493d fix(identity)!: update type of private key (#803)
* fix(identity)!: update type of private key

The new types support buffers and text, so that there is less ambiguity on strings.

* refactor(identity): use base64 as encoding for exported priv keys

re #799

* Update packages/identity/src/index.ts

Co-authored-by: Andrew Twyman <artwyman@users.noreply.github.com>

* test(identity): add more tests

re #799

---------

Co-authored-by: Andrew Twyman <artwyman@users.noreply.github.com>
2024-06-18 12:08:20 +01:00
dropbigfish
2830d3d0dc chore: fix wrong link in README.md (#802)
Signed-off-by: dropbigfish <fillfish@foxmail.com>
2024-06-13 11:20:10 +01:00
Giacomo
62b6b170a6 Announce Trusted Setup V4 ceremony (#794)
* chore(website): add trusted setup ceremony on the website

* docs(docs): add trusted setup ceremony instructions on documentation

* chore(docs): add candidate plan for prod ceremony

re n

* fix(docs): rename file to avoid mismatching hyphens

* style(website): follow style guide for hover

* fix(website): wrong link to ceremony

* fix(docs): switch emoji
2024-06-11 10:46:27 +02:00
Vivian Plasencia
5d513f92fb chore: v4.0.0-beta.12 2024-05-31 15:17:01 +02:00
sripwoud
0c942220b6 chore(proof): bump @zk-kit/artifacts to 1.4.1 (#798)
chore(proof): bump `@zk-kit/artifacts`

includes a retry mechanism to fetch artifacts
2024-05-31 14:43:17 +02:00
Vivian Plasencia
9237e147b8 chore: add runs-on to docs workflow (#797) 2024-05-31 13:16:45 +02:00
Vivian Plasencia
1dbc310333 chore: update verification keys (#795)
These are the new keys after the staging ceremony.
2024-05-31 13:02:34 +02:00
sripwoud
4870175577 docs: add link to API Reference (typedoc) (#790)
* chore: shorten `docs` scripts

`githubPages` is true by default
https://rb.gy/hzopfn

* docs: update README.md

* chore: trigger docs workflow only on changes in relevant files

* refactor: provide `cname` typedoc option via config file

* chore: remove heyauthn from exclude typedoc list
2024-05-30 17:29:56 +02:00
Vivian Plasencia
55e887c111 chore: update video url and thumbnail (#793) 2024-05-22 15:20:12 +02:00
Vivian Plasencia
f934c02214 chore: v4.0.0-beta.11 2024-05-21 09:48:11 +02:00
Vivian Plasencia
43fba00845 chore: update zk kit dependencies (#791)
* chore: update @zk-kit/baby-jubjub and @zk-kit/eddsa-poseidon dependencies

re #786

* chore(group): use the new @zk-kit/lean-imt library

re #786

* chore: update @zk-kit/utils version

re #786

* chore(contracts): use the new @zk-kit/lean-imt.sol library in contracts

re #786
2024-05-21 09:43:55 +02:00
sripwoud
7b3621a701 refactor: add @zk-kit/artifacts (#788)
* refactor: add `@zk-kit/artifacts`

* chore: update `jest.config.ts`

* test: increase timeouts

* chore: bump `@zk-kit/utils`

* fix: bump `@zk-kit/artifacts`
2024-05-20 12:16:01 -05:00
Vivian Plasencia
f3f3688476 test(circuits): add test using the identity library (#785)
There is a new test using the Semaphore Identity package to test compatibility between the Identity
library and the circuit.

re #484
2024-05-17 10:01:44 +01:00
Vivian Plasencia
0fa785bc58 chore: v4.0.0-beta.10 2024-05-16 12:47:57 +02:00
Vivian Plasencia
51ebe9db4d feat: support more tree depths (#779)
* feat: support more tree depth

Now Semaphore v4 will support tree depth from 2 to 32.

re #778

* test(proof): update tests to support circuit changes and tree depth 2 - 32

re #778

* fix(contracts): update verifier VK_POINTS

re #778

* test(proof): make tests more atomic

* chore: support tree depth 1

re #778
2024-05-16 12:41:46 +02:00
Vivian Plasencia
c88175bb2d chore: update zk-kit dependencies (#781)
* chore: update @zk-kit/imt and @zk-kit/imt.sol dependencies

re #776

* chore(identity): update dependency @zk-kit/eddsa-poseidon

re #776

* chore: update dependency @zk-kit/utils

re #776

* chore: add fixed version of zk-kit packages

re #776

* chore(identity): update dependency @zk-kit/baby-jubjub

re #776

* chore: update @zk-kit/baby-jubjub package version

re #776

* chore(identity): update @zk-kit/eddsa-poseidon package version

re #776

* chore: update yarn.lock file
2024-05-15 16:52:12 +01:00
Cedoor
ea175fa90c chore: add code owners (#784)
Through Github rulesets and the definition of code owners, it is possible to automate the review
process without additional workflows. It also makes responsibilities within the project clearer. The
current CODEOWNERS file is very simple but more complex rules can be introduced in the future.

re #783
2024-05-15 14:41:35 +01:00
Cedoor
f9e41fb306 chore(circuits): update binary-merkle-root dependency (#780)
re #776
2024-05-13 17:15:18 +01:00
Cedoor
47bfebd4ed docs(docs): add v4 audit report (#777) 2024-05-12 11:17:14 +01:00
Vivian Plasencia
9e5b2285fc test: add missing tests in the js libraries (#774)
* test: add missing tests

Now all lines of js libraries are 100% covered.

re #484

* test(proof): update message type

re #484

* test(proof): update constant

re #484

* test(proof): update number constant

re #484
2024-05-09 12:53:20 +01:00
aguzmant103
de15989638 chore(website): update event list (#775) 2024-05-08 23:15:49 +02:00
sripwoud
2e56ab6b07 chore: optimize pull-requests workflow (#765)
* chore: optimize pull-requests workflow

* fix: quote glob pattern

* fix: append `$` to variables in workflow

* chore: include `yaml` files in lintstaged format check

* feat: detect to_format or to_lint changed files

* feat: run test workflow steps conditionally

* Update .github/workflows/pull-requests.yml

Co-authored-by: Daehyun Paik <paik@a30a.dev>

* Update .github/workflows/pull-requests.yml

Co-authored-by: Daehyun Paik <paik@a30a.dev>

* fix: build utils before contracts

* fix: build identity pkg before running contracts tests

* fix: need to quote `true`

* fix: build group pkg before running contracts tests

* fix: build `{group,identity,proof}` before running circuits tests

* fix: build `proof` pkg before running contracts tests

* fix: build utils before testing circuits

* fix: build `utils` before `subgraph` pkg

---------

Co-authored-by: Daehyun Paik <paik@a30a.dev>
2024-05-08 11:10:00 +01:00
hw
3329922077 test(contracts): update contract tests to be more atomic and use loadFixture (#706) (#770)
test(contracts): update contract test

update contract test to be more atomic and use loadFixture

re #706
2024-05-08 10:55:47 +01:00
Giacomo
6b6bc6a98e Improve documentation for @semaphore/cli package (#771)
docs(cli): improve code comments and readme of the @semaphore/cli package
2024-05-07 14:31:04 +01:00
Giacomo
b9fa75cba3 Improve documentation for @semaphore/data package (#768)
* docs(data): improve code comments and readme of the @semaphore/data package

* docs(data): update package.json description and small nit on README
2024-05-07 14:30:43 +01:00
Giacomo
1b34ad312d Improve documentation for @semaphore/hardhat package (#772)
* docs(hardhat): improve code comments and readme for @semaphore/hardhat package

* docs(hardhat): update package.json description
2024-05-07 14:27:32 +01:00
Vivek
74df3c204d Update articles.json (#769) 2024-05-07 10:47:15 +02:00
Nick Addison
08af4a315f Added missing await in proofs example (#767)
Added missing await in proofs example
2024-05-07 10:46:58 +02:00
cedoor
ddfe4ffd56 chore: v4.0.0-beta.9 2024-05-02 16:29:22 +01:00
Cedoor
87f63451e3 fix(group): add check for zero values in group constructor (#764) 2024-05-02 16:28:21 +01:00
Vivian Plasencia
f8deb64285 chore: update config (#763)
* chore: update lint-staged config

* chore: use czg instead of cz + cz-git

re #738

* chore: use cat instead of vim editor to write commits

re #738

* chore: use secrets.GITHUB_TOKEN instead of secrets.GH_TOKEN

re #738

* style: add a space at the end of the pre-commit file
2024-05-01 10:45:27 +02:00
Vivian Plasencia
82bc47fb24 test(proof): increase timeout for tests generating proofs (#762)
re #761
2024-04-30 15:39:38 +02:00
Seva Zhidkov
5ced7db5f8 docs: fix 404 broken link to circuit file (#760)
docs: fix broken link to circuit file 

broken since [this commit](d9d5de1569 (diff-27cc20ba62610ee534566b1969efe92677c1c6af8940cdc20b57fcb0b4e0c6b3))
2024-04-30 14:33:03 +02:00
Vivian Plasencia
5c224f214c fix: update format code command (#759) 2024-04-29 18:07:36 +02:00
sripwoud
0b9ba376db chore(docs): format mdx files (#754)
* chore(docs): format `mdx` files with `remark`

`prettier` doesn't not have proper support for MDX v3.
Docusaurus recommends using `remark` instead.
https://docusaurus.io/docs/markdown-features/react

re #503

* chore(docs): add remark lint plugins

* chore: bump yarn.lock

* chore: add `quiet` option to remark
2024-04-29 17:13:35 +02:00
cedoor
a9410fa6d1 chore: v4.0.0-beta.8 2024-04-26 18:09:23 +02:00
Cedoor
79bd8d6305 fix: update snarkjs dependency version (#755)
re #713, #675
2024-04-26 17:59:14 +02:00
Vivian Plasencia
c5448fe1f0 Move heyauthn package (#753)
chore: remove heyauthn package

The heyauthn package was moved to the semaphore-protocol extensions repo.

re #752
2024-04-25 15:57:23 +02:00
sripwoud
cf1cffdf65 refactor!: use maybeGetSemaphoreSnarkArtifacts from `@zk-kit/utils (#747)
* chore(proof): bump `@zk-kit/utils` dep

* refactor(proof): use `maybeGetSemaphoreSnarkArtifacts` from `@zk-kit/utils`

Delete logic related to fetching snark artifacts (wasm and zkey files) that was moved to
`@zk-kit/utils`

* revert(proof): add back `requireObject(snarkArtifacts)` check

* chore(proof): update rollup.browser.config.ts

* docs(proof): update README

* chore(proof): remove unused import in rollup.browser.config.ts

* Update packages/proof/package.json

Co-authored-by: Cedoor <me@cedoor.dev>

* docs(proof): add links to other repos in proof README

* chore: bump `yarn.lock`

* docs(proof): add punctuation

---------

Co-authored-by: Cedoor <me@cedoor.dev>
2024-04-24 16:43:19 +02:00
Cedoor
41a85e0e45 Merge pull request #748 from semaphore-protocol/gitignore
chore: update `.gitignore`
2024-04-24 15:08:17 +02:00
Cedoor
6502c17f7b Merge pull request #750 from semaphore-protocol/fix/docs
docs: fix `typedoc` compilation warnings
2024-04-24 15:07:24 +02:00
Cedoor
1849055e88 Merge pull request #751 from semaphore-protocol/fix/install-circom-deps
ci: fix circom deps installation steps
2024-04-24 15:01:04 +02:00
sripwoud
e536debb16 ci: add comment 2024-04-24 14:36:13 +02:00
sripwoud
4ba367bee4 chore: format 2024-04-24 13:56:48 +02:00
sripwoud
ce6d622202 ci: remove microsoft.prod sources file 2024-04-24 13:54:20 +02:00
sripwoud
3b08b67175 ci: debug pull-requests workflow 2024-04-24 13:52:02 +02:00
sripwoud
68181aa1fb docs: fix warnings about function signatures 2024-04-24 13:29:58 +02:00
sripwoud
6225b9b7c0 docs: fix typedoc entryPoints 2024-04-24 13:29:25 +02:00
sripwoud
940db25a87 chore: update .gitignore
Don't version control `asdf` and `direnv` configuration files
2024-04-24 13:09:22 +02:00
Cedoor
9dc768376c Merge pull request #743 from semaphore-protocol/fix/baby-jubjub
Add check to make sure Baby Jubjub secret scalar is < l
2024-04-19 11:04:57 +02:00
cedoor
ba8132561a chore: update lockfile 2024-04-17 10:46:45 +02:00
Cedoor
5aaa9e4f69 Merge pull request #742 from semaphore-protocol/docs/update-code
Update Solidity code to create groups in documentation website
2024-04-16 09:21:17 +01:00
cedoor
f19b632e1e docs(docs): update solidity code to create groups 2024-04-15 16:55:32 +01:00
cedoor
b40f9f13e9 test(circuits): add new test for l = r - 1 2024-04-12 18:45:34 +01:00
cedoor
e884186488 refactor(circuits): remove greater-than check and update less-than bits 2024-04-12 16:22:49 +01:00
Cedoor
a4a6837f5a Merge pull request #737 from Stumble/yumin/fix-alias
fix: incorrect alias check brought from snarkjs. (possible security vulnerability)
2024-04-12 12:12:23 +01:00
Cedoor
2aee16e082 Merge pull request #741 from 0xbok/sol-op
perf(contracts): turn on solidity optimizer
2024-04-09 10:58:49 +01:00
0xbok
7c99c74fac perf(contracts): turn on solidity optimizer
Turn on solidity optimizer

re #740
2024-04-09 02:12:08 +04:00
Yumin Xia
8e246c48bf fix: incorrect alias check brought from snarkjs. 2024-04-05 12:21:59 -07:00
cedoor
75eac56e9f chore: update lockfile 2024-03-29 17:51:34 +00:00
cedoor
d9d5de1569 fix(circuits): check whether the secret scalar is within the r field 2024-03-29 17:49:40 +00:00
134 changed files with 6074 additions and 4954 deletions

View File

@@ -1,5 +1,4 @@
DEFAULT_NETWORK=hardhat
TREE_DEPTH=10
REPORT_GAS=false
BACKEND_PRIVATE_KEY=
COINMARKETCAP_API_KEY=

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @semaphore-protocol/core-devs

View File

@@ -32,9 +32,7 @@
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have run `yarn prettier` and `yarn lint` without getting any errors
- [ ] I have run `yarn format` and `yarn lint` without getting any errors
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

View File

@@ -1,14 +0,0 @@
name: auto-assign
on:
pull_request:
types: [opened]
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: wow-actions/auto-assign@v3
with:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
reviewers: org/core-devs

View File

@@ -2,8 +2,16 @@ name: docs
on:
push:
branches:
- main
branches: [main]
paths:
[
"apps/docs/**",
"packages/data/**",
"packages/group/**",
"packages/identity/**",
"packages/proof/**",
"packages/utils/**"
]
jobs:
gh-pages:

View File

@@ -33,8 +33,8 @@ jobs:
- name: Build subgraph
run: yarn build:subgraph
- name: Run Prettier
run: yarn prettier
- name: Format
run: yarn format
- name: Run Eslint
run: yarn lint
@@ -82,8 +82,11 @@ jobs:
cache: yarn
# https://github.com/iden3/circuits/blob/8fffb6609ecad0b7bcda19bb908bdb544bdb3cf7/.github/workflows/main.yml#L18-L22
# https://stackoverflow.com/a/78377916
- name: Setup Circom deps
run: sudo apt-get update && sudo apt-get install -y wget nlohmann-json3-dev libgmp-dev nasm g++ build-essential
run: |
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update && sudo apt-get install -y wget nlohmann-json3-dev libgmp-dev nasm g++ build-essential
- name: Setup Circom
run: wget https://github.com/iden3/circom/releases/latest/download/circom-linux-amd64 && sudo mv ./circom-linux-amd64 /usr/bin/circom && sudo chmod +x /usr/bin/circom

View File

@@ -22,20 +22,57 @@ jobs:
- name: Install dependencies
run: yarn
- name: Build libraries
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
with:
files_yaml: |
circuits:
- packages/circuits/**/*.{circom,json,ts}
contracts:
- packages/contracts/**/*.{js,json,ts,sol}
docs:
- apps/docs/**/*
libraries:
- packages/**/*.{js,json,ts}
- '!packages/{circuits,contracts}/**/*'
subgraph:
- apps/subgraph/**/*
to_format:
- '**/*.{cjs,js,json,jsx,md,mdx,sol,ts,tsx,yaml,yml}'
to_lint:
- '**/*.{cjs,js,jsx,ts,tsx}'
- if: steps.changed-files.outputs.contracts_any_changed == 'true'
name: Compile and lint contracts
run: |
yarn workspace @semaphore-protocol/utils build
yarn compile:contracts
yarn workspace semaphore-contracts lint
- if: steps.changed-files.outputs.docs_any_changed == 'true'
name: Build and format docs
run: |
yarn workspace semaphore-docs build
yarn workspace semaphore-docs format
- if: steps.changed-files.outputs.libraries_any_changed == 'true'
name: Build libraries
run: yarn build:libraries
- name: Compile contracts
run: yarn compile:contracts
- if: steps.changed-files.outputs.subgraph_any_changed == 'true'
name: Build subgraph
run: |
yarn workspace @semaphore-protocol/utils build
yarn build:subgraph
- name: Build subgraph
run: yarn build:subgraph
- if: steps.changed-files.outputs.to_format_any_changed == 'true'
name: Format
run: yarn run prettier --check ${{ steps.changed-files.outputs.to_format_all_changed_files }}
- name: Run Prettier
run: yarn prettier
- name: Run Eslint
run: yarn lint
- if: steps.changed-files.outputs.to_lint_any_changed == 'true'
name: Run Eslint
run: yarn run eslint ${{ steps.changed-files.outputs.to_lint_all_changed_files }} --ext .cjs,.js,.jsx,.ts,.tsx
test:
runs-on: ubuntu-latest
@@ -49,21 +86,55 @@ jobs:
node-version: 20
cache: yarn
# https://github.com/iden3/circuits/blob/8fffb6609ecad0b7bcda19bb908bdb544bdb3cf7/.github/workflows/main.yml#L18-L22
- name: Setup Circom deps
run: sudo apt-get update && sudo apt-get install -y wget nlohmann-json3-dev libgmp-dev nasm g++ build-essential
- name: Setup Circom
run: wget https://github.com/iden3/circom/releases/latest/download/circom-linux-amd64 && sudo mv ./circom-linux-amd64 /usr/bin/circom && sudo chmod +x /usr/bin/circom
- name: Install dependencies
run: yarn
- name: Build libraries
run: yarn build:libraries
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
with:
files_yaml: |
circuits:
- packages/circuits/**/*.{circom,json,ts}
contracts:
- packages/contracts/**/*.{js,json,ts,sol}
libraries:
- packages/**/*.{js,json,ts}
- '!packages/{circuits,contracts}/**/*'
subgraph:
- apps/subgraph/**/*
- name: Build subgraph
run: yarn build:subgraph
# https://github.com/iden3/circuits/blob/8fffb6609ecad0b7bcda19bb908bdb544bdb3cf7/.github/workflows/main.yml#L18-L22
# https://stackoverflow.com/a/78377916
- if: steps.changed-files.outputs.circuits_any_changed == 'true'
name: Setup Circom and Test circuits
run: |
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
sudo apt-get update && sudo apt-get install -y wget nlohmann-json3-dev libgmp-dev nasm g++ build-essential
wget https://github.com/iden3/circom/releases/latest/download/circom-linux-amd64 && sudo mv ./circom-linux-amd64 /usr/bin/circom && sudo chmod +x /usr/bin/circom
yarn workspace @semaphore-protocol/group build
yarn workspace @semaphore-protocol/identity build
yarn workspace @semaphore-protocol/proof build
yarn workspace @semaphore-protocol/utils build
yarn test:circuits
- name: Test contracts, libraries, circuits and subgraph
run: yarn test
- if: steps.changed-files.outputs.contracts_any_changed == 'true'
name: Build and Test contracts
run: |
yarn workspace @semaphore-protocol/group build
yarn workspace @semaphore-protocol/identity build
yarn workspace @semaphore-protocol/proof build
yarn workspace @semaphore-protocol/utils build
yarn compile:contracts
yarn test:contracts
- if: steps.changed-files.outputs.libraries_any_changed == 'true'
name: Build and Test libraries
run: yarn build:libraries && yarn test:libraries
- if: steps.changed-files.outputs.subgraph_any_changed == 'true'
name: Build and Test Subgraph
run: |
yarn workspace @semaphore-protocol/utils build
yarn build:subgraph
yarn test:subgraph

6
.gitignore vendored
View File

@@ -86,5 +86,11 @@ typechain-types
!.yarn/sdks
!.yarn/versions
# asdf
.tool-versions
# direnv
.envrc
# Other
snark-artifacts

4
.husky/pre-commit Normal file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged

View File

@@ -2,5 +2,5 @@
. "$(dirname -- "$0")/_/husky.sh"
if [ "$NO_HOOK" != "1" ]; then
exec < /dev/tty && yarn cz --hook || true
exec < /dev/tty && npx czg --hook || true
fi

View File

@@ -1,3 +1,4 @@
{
"**/*.{js,ts}": ["prettier --write", "eslint --fix"]
"**/*.{js,ts,jsx,tsx,md,json,sol,yaml,yml}": "prettier --write",
"**/*.{js,ts,jsx,tsx}": "eslint"
}

View File

@@ -1,9 +1,9 @@
<p align="center">
<h1 align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://github.com/semaphore-protocol/.github/blob/main/assets/semaphore-logo-light.svg">
<source media="(prefers-color-scheme: light)" srcset="https://github.com/semaphore-protocol/.github/blob/main/assets/semaphore-logo-dark.svg">
<img width="250" alt="Semaphore icon" src="https://github.com/semaphore-protocol/.github/blob/main/assets/semaphore-logo-dark.svg">
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/semaphore-protocol/.github/main/assets/semaphore-logo-light.svg">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/semaphore-protocol/.github/main/assets/semaphore-logo-dark.svg">
<img width="250" alt="Semaphore icon" src="https://raw.githubusercontent.com/semaphore-protocol/.github/main/assets/semaphore-logo-dark.svg">
</picture>
</h1>
</p>
@@ -56,6 +56,10 @@
<a href="https://semaphore.pse.dev/discord">
🗣️ Chat &amp; Support
</a>
<span>&nbsp;&nbsp;|&nbsp;&nbsp;</span>
<a href="https://js.semaphore.pse.dev">
💻 API Reference
</a>
</h4>
</div>
@@ -257,28 +261,6 @@ The core of the Semaphore protocol is in the [circuit logic](/packages/circuits/
</a>
</td>
</tr>
<tr>
<td>
<a href="/packages/heyauthn">
@semaphore-protocol/heyauthn
</a>
<a href="https://js.semaphore.pse.dev/modules/_semaphore_protocol_heyauthn">
(docs)
</a>
</td>
<td>
<!-- NPM version -->
<a href="https://npmjs.org/package/@semaphore-protocol/heyauthn">
<img src="https://img.shields.io/npm/v/@semaphore-protocol/heyauthn.svg?style=flat-square" alt="NPM version" />
</a>
</td>
<td>
<!-- Downloads -->
<a href="https://npmjs.org/package/@semaphore-protocol/heyauthn">
<img src="https://img.shields.io/npm/dm/@semaphore-protocol/heyauthn.svg?style=flat-square" alt="Downloads" />
</a>
</td>
</tr>
<tbody>
</table>
@@ -317,13 +299,13 @@ yarn lint
Run [Prettier](https://prettier.io/) to check formatting rules:
```bash
yarn prettier
yarn format
```
Or to automatically format the code:
```bash
yarn prettier:write
yarn format:write
```
### Conventional commits

View File

@@ -67,7 +67,7 @@ const config: Config = {
announcementBar: {
id: "semaphore-v4-beta",
content:
'<b>Semaphore V4-beta is out 🎉 <a href="/getting-started">Try it out</a> and let us know for any feedback on <a href="https://semaphore.pse.dev/discord" target="_blank">Discord</a> or <a href="https://github.com/orgs/semaphore-protocol/discussions" target="_blank">Github</a>!</b>',
'<b>Semaphore V4-beta is out 🎉 <a href="/getting-started">Try it out</a> and contribute to the <a href="/trusted-setup">Trusted Setup ceremony</a>. Let us know for any feedback on <a href="https://semaphore.pse.dev/discord" target="_blank">Discord</a> or <a href="https://github.com/orgs/semaphore-protocol/discussions" target="_blank">Github</a>!</b>',
backgroundColor: "#dde6fc",
textColor: "#000000"
},

View File

@@ -18,34 +18,31 @@ Hay dos formas para hacer esto, usando [`SemaphoreSubgraph`](https://github.com/
## Instalar librería
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @semaphore-protocol/data@^3
```
</TabItem>
```bash
npm install @semaphore-protocol/data@^3
```
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/data@^3
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/data@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/data@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/data@^3
```
</TabItem>
</Tabs>
## Obtener datos usando SemaphoreSubgraph
@@ -113,6 +110,7 @@ const semaphoreSubgraph = new SemaphoreSubgraph("sepolia")
const { members } = await semaphoreSubgraph.getGroup(groupId, { members: true })
const group = new Group(groupId, 20, members)
```
:::
## Obtener datos usando SemaphoreEthers
@@ -178,4 +176,5 @@ const semaphoreEthers = new SemaphoreEthers("sepolia")
const members = await semaphoreEthers.getGroupMembers(groupId)
const group = new Group(groupId, 20, members)
```
:::

View File

@@ -11,70 +11,67 @@ import TabItem from "@theme/TabItem"
Un [grupo Semaphore](/V3/glossary/#grupo-semaphore) contiene los [identity commitments](/V3/glossary/#compromiso-de-identidad-identity-commitment) (compromisos de identidad) de miembros del grupo.
Estos son algunos ejemplos de uso de los grupos:
- Encuesta con preguntas a la que se unen las personas que acudieron a un evento para calificarlo,
- votación a la que se unen los miembros para votar por una propuesta,
- Denunciantes que están verificados como empleados de una organización.
- Encuesta con preguntas a la que se unen las personas que acudieron a un evento para calificarlo,
- votación a la que se unen los miembros para votar por una propuesta,
- Denunciantes que están verificados como empleados de una organización.
Un grupo Semaphore es un [árbol de Merkle incremental](/V3/glossary/#árbol-de-merkle-merkle-tree), y los miembros del grupo (por ejemplo, [identity commitments](/V3/glossary/#compromiso-de-identidad-identity-commitment)) son las hojas del árbol.
Los grupos Semaphore determinan los siguientes tres parámetro:
- **Group id**: un identificador único para el grupo;
- **Tree depth**: el número máximo de miembros que puede contener un grupo (`max size = 2 ^ tree depth`);
- **Members** la lista de miembros para inicializar el grupo.
- **Group id**: un identificador único para el grupo;
- **Tree depth**: el número máximo de miembros que puede contener un grupo (`max size = 2 ^ tree depth`);
- **Members** la lista de miembros para inicializar el grupo.
Aprenda cómo trabajar con grupos.
- [**Grupos off-chain**](#grupos-off-chain-externos-a-la-cadena)
- [**Grupos on-chain**](#grupos-on-chain)
- [**Grupos off-chain**](#grupos-off-chain-externos-a-la-cadena)
- [**Grupos on-chain**](#grupos-on-chain)
## Grupos off-chain (externos a la cadena)
- [Crear un grupo](#crear-un-grupo)
- [Añadir miembros](#añadir-miembros)
- [Remover o actualizar miembros](#remover-o-actualizar-miembros)
- [Crear un grupo](#crear-un-grupo)
- [Añadir miembros](#añadir-miembros)
- [Remover o actualizar miembros](#remover-o-actualizar-miembros)
### Crear un grupo
Utilice la clase `Group` de la librería [`@semaphore-protocol/group`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/group) para crear un grupo off-chain con los siguientes parámetros:
- `Group id`: un identificar único para el grupo;
- `Tree depth`: (_default `20`_) el número máximo de usuarios que puede contener un grupo, el valor por defecto es 20 (`max size = 2 ^ tree depth`).
- `Members`: (_default `[]`_) la lista de miembros para inicializar el grupo.
- `Group id`: un identificar único para el grupo;
- `Tree depth`: (*default `20`*) el número máximo de usuarios que puede contener un grupo, el valor por defecto es 20 (`max size = 2 ^ tree depth`).
- `Members`: (*default `[]`*) la lista de miembros para inicializar el grupo.
#### Instalar librería:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @semaphore-protocol/group@^3
```
</TabItem>
```bash
npm install @semaphore-protocol/group@^3
```
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/group@^3
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/group@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/group@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/group@^3
```
</TabItem>
</Tabs>
Para crear un grupo con el número de usuarios que aparece por defecto (20) _`treeDepth`_, llame la función para construir un `Group` sin el segundo parámetro. Por ejemplo:
Para crear un grupo con el número de usuarios que aparece por defecto (20) *`treeDepth`*, llame la función para construir un `Group` sin el segundo parámetro. Por ejemplo:
```ts
import { Group } from "@semaphore-protocol/group"
@@ -82,7 +79,7 @@ import { Group } from "@semaphore-protocol/group"
const group = new Group(1)
```
El siguiente código de ejemplo pasa por _`treeDepth`_ para crear un grupo para `2 ^ 30 = 1073741824` miembros:
El siguiente código de ejemplo pasa por *`treeDepth`* para crear un grupo para `2 ^ 30 = 1073741824` miembros:
```ts
import { Group } from "@semaphore-protocol/group"

View File

@@ -11,48 +11,47 @@ import TabItem from "@theme/TabItem"
Para unirse a un [grupo Semaphore](/V3/glossary#grupo-semaphore), un usuario primero deberá crear una [identidad Semaphore](/V3/glossary#identidad-semaphore).
Una identidad Semaphore contiene dos valores generados junto con la identidad:
- Identity trapdoor (Identidad trampilla)
- Identity nullifier (Anulador de identidad)
- Identity trapdoor (Identidad trampilla)
- Identity nullifier (Anulador de identidad)
Para utilizar y verificar su identidad, la persona dueña de la identidad (usuario) debe conocer los valores trapdoor y nullifier.
Para prevenir fraudes, la persona dueña debe conservar de forma secreta ambos valores.
## Crear identidades
En su código, utilice la librería [`@semaphore-protocol/identity`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/identity) para crear una identidad Semaphore _de forma determinística_ (del hash de un mensaje) o _de forma aleatoria_.
En su código, utilice la librería [`@semaphore-protocol/identity`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/identity) para crear una identidad Semaphore *de forma determinística* (del hash de un mensaje) o *de forma aleatoria*.
- [**Crear identidades aleatorias**](#crear-identidades-aleatorias)
- [**Crear identidades determinísticas**](#crear-identidades-determinísticas)
- [**Crear identidades aleatorias**](#crear-identidades-aleatorias)
- [**Crear identidades determinísticas**](#crear-identidades-determinísticas)
### Instalar librería:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @semaphore-protocol/identity@^3
```
</TabItem>
```bash
npm install @semaphore-protocol/identity@^3
```
</TabItem>
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/identity@^3
```
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/identity@^3
```
</TabItem>
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/identity@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/identity@^3
```
</TabItem>
</Tabs>
### Crear identidades aleatorias
@@ -67,8 +66,8 @@ const { trapdoor, nullifier, commitment } = new Identity()
La nueva identidad contiene dos valores aleatorios secretos: `trapdoor` y `nullifier`, y un valor público: `commitment`.
El hash Poseidon del identity nullifier y trapdoor se conoce como _identity secret_ (el secreto de identidad),
y su hash es el _identity commitment_ (compromiso de identidad).
El hash Poseidon del identity nullifier y trapdoor se conoce como *identity secret* (el secreto de identidad),
y su hash es el *identity commitment* (compromiso de identidad).
Un identity commitment (compromiso de identidad), de forma similar a las direcciones Ethereum, es un valor público que se utiliza en los grupos Semaphore para representar la
identidad de un miembro del grupo. Los valores secretos son similares a las llaves privadas
@@ -77,7 +76,7 @@ Ethereum y se utilizan para generar pruebas de conocimiento cero (ZKP) Semaphore
### Crear identidades determinísticas
Si transmite un mensaje como un parámetro, Semaphore genera `trapdoor` y `nullifier`
del hash _SHA256_ del mensaje.
del hash *SHA256* del mensaje.
El mensaje puede ser una contraseña o un mensaje que el usuario firma de forma criptográfica con una llave privada.
Al utilizar identidades determinísticas siempre deberá mantener secreto el mensaje.

View File

@@ -10,56 +10,54 @@ import TabItem from "@theme/TabItem"
Una vez que un usuario liga su [identidad Semaphore](/V3/glossary#identidad-semaphore) a un [grupo Semaphore](/V3/glossary#grupo-semaphore), el usuario puede emitir una señal anónima con una prueba de conocimiento cero (ZKP) que demuestre lo siguiente:
- el usuario es un miembro del grupo,
- el mismo usuario creo tanto la señal como la prueba.
- el usuario es un miembro del grupo,
- el mismo usuario creo tanto la señal como la prueba.
Las y los desarrolladores pueden utilizar Semaphore para realizar las siguientes acciones:
- [**Generar una prueba externa a la cadena (off-chain)**](#generar-una-prueba-off-chain)
- [**Verificar una prueba externa a la cadena (off-chain)**](#verificar-una-prueba-off-chain)
- [**Verificar una prueba interna a la cadena (on-chain)**](#verificar-una-prueba-on-chain)
- [**Generar una prueba externa a la cadena (off-chain)**](#generar-una-prueba-off-chain)
- [**Verificar una prueba externa a la cadena (off-chain)**](#verificar-una-prueba-off-chain)
- [**Verificar una prueba interna a la cadena (on-chain)**](#verificar-una-prueba-on-chain)
## Generar una prueba off-chain
Utilice la librería [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/proof) para generar una prueba off-chain.
Para generar una prueba, transforme los siguientes parámetros con la función `generateProof`:
- `identity`: la identidad Semaphore del usuario emitiendo la señal y generando la prueba;
- `group`: el grupo al cual pertenece el usuario;
- `externalNullifier`: el valor que impide la emisión de dos señales por el mismo usuario;
- `signal`: la señal que el usuario quiere enviar de forma anónima;
- `snarkArtifacts`: la `zkey` y `wasm` de los [archivos confiables de configuración](/V3/glossary/#archivos-confiables-de-configuración-trusted-setup-files).
- `identity`: la identidad Semaphore del usuario emitiendo la señal y generando la prueba;
- `group`: el grupo al cual pertenece el usuario;
- `externalNullifier`: el valor que impide la emisión de dos señales por el mismo usuario;
- `signal`: la señal que el usuario quiere enviar de forma anónima;
- `snarkArtifacts`: la `zkey` y `wasm` de los [archivos confiables de configuración](/V3/glossary/#archivos-confiables-de-configuración-trusted-setup-files).
#### Instalar librería:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @semaphore-protocol/proof@^3
```
</TabItem>
```bash
npm install @semaphore-protocol/proof@^3
```
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/proof@^3
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/proof@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/proof@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/proof@^3
```
</TabItem>
</Tabs>
En el caso de uso de un sistema de votación, una vez que todos los votantes hayan ligado sus [identidades](/V3/guides/identities#crear-identidades) al [grupo](/V3/guides/groups) de la votación,
@@ -86,6 +84,7 @@ Si estás generando la prueba en el lado del cliente, puedes evitar agregar los
```ts
const fullProof = await generateProof(identity, group, externalNullifier, signal)
```
:::
## Verificar una prueba off-chain
@@ -93,8 +92,8 @@ const fullProof = await generateProof(identity, group, externalNullifier, signal
Utilice la librería [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/proof) para verificar una prueba Semaphore off-chain.
Para verificar una prueba, transforme los siguientes parámetros con la función `verifyProof`:
- `fullProof`: la prueba Semaphore;
- `treeDepth`: la profundidad del árbol de Merkle.
- `fullProof`: la prueba Semaphore;
- `treeDepth`: la profundidad del árbol de Merkle.
La siguiente muestra de código demuestra cómo verificar la prueba generada previamente:
@@ -116,12 +115,12 @@ Vea nuestros [contratos desplegados](/V3/deployed-contracts) para encontrar las
Para verificar las pruebas Semaphore en su contrato, importe `ISemaphore.sol`, transfórmelo a la dirección `Semaphore.sol` y llame el método `verifyProof` con los siguientes parámetros:
- `groupId`: el identificador del grupo;
- `merkleTreeRoot`: la raíz del árbol de Merkle;
- `signal`: la señal que el usuario quiere enviar de forma anónima ;
- `nullifierHash`: un nullifier hash (hash anulador);
- `externalNullifier`: el valor que impide la emisión de dos señales por el mismo usuario;
- `proof`: una prueba Semaphore que es compatible con Solidity.
- `groupId`: el identificador del grupo;
- `merkleTreeRoot`: la raíz del árbol de Merkle;
- `signal`: la señal que el usuario quiere enviar de forma anónima ;
- `nullifierHash`: un nullifier hash (hash anulador);
- `externalNullifier`: el valor que impide la emisión de dos señales por el mismo usuario;
- `proof`: una prueba Semaphore que es compatible con Solidity.
:::info
Puede importar `ISemaphore.sol` y otros contratos Semaphore del módulo NPM [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/contracts).

View File

@@ -31,37 +31,34 @@ El CLI [`semaphore`](https://github.com/semaphore-protocol/semaphore/tree/main/p
Para comenzar a trabajar en su proyecto, instale las siguientes dependencias:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
cd my-app
npm i
```
</TabItem>
```bash
cd my-app
npm i
```
<TabItem value="yarn">
```bash
cd my-app
yarn
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
cd my-app
yarn
```
</TabItem>
<TabItem value="pnpm">
```bash
cd my-app
pnpm install
```
</TabItem>
<TabItem value="pnpm">
```bash
cd my-app
pnpm install
```
</TabItem>
</Tabs>
## Output
@@ -116,34 +113,31 @@ cd apps/contracts
Y compile sus contratos al correr:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm run compile
```
</TabItem>
```bash
npm run compile
```
<TabItem value="yarn">
```bash
yarn compile
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn compile
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm compile
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm compile
```
</TabItem>
</Tabs>
### Pruebe los contratos
@@ -151,100 +145,91 @@ pnpm compile
Pruebe sus contratos al correr:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm test
```
</TabItem>
```bash
npm test
```
<TabItem value="yarn">
```bash
yarn test
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn test
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm test
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm test
```
</TabItem>
</Tabs>
Genere un reporte de la prueba de cobertura:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm run test:coverage
```
</TabItem>
```bash
npm run test:coverage
```
<TabItem value="yarn">
```bash
yarn test:coverage
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn test:coverage
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm test:coverage
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm test:coverage
```
</TabItem>
</Tabs>
O un reporte de la prueba de gas:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm run test:report-gas
```
</TabItem>
```bash
npm run test:report-gas
```
<TabItem value="yarn">
```bash
yarn test:report-gas
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn test:report-gas
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm test:report-gas
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm test:report-gas
```
</TabItem>
</Tabs>
### Desplegar contratos
@@ -255,82 +240,76 @@ En la carpeta raíz del proyecto:
1. Agregue sus variables de entorno en el archivo `.env`.
:::note
Deberá por lo menos configurar un URL válido en Ethereum (ejemplo: Infura) y una llave privada con algunos ethers.
:::
:::note
Deberá por lo menos configurar un URL válido en Ethereum (ejemplo: Infura) y una llave privada con algunos ethers.
:::
2. Vaya a la carpeta `apps/contracts` y desplegue su contrato.
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm run deploy -- --semaphore <semaphore-address> --group <group-id> --network goerli
```
</TabItem>
```bash
npm run deploy -- --semaphore <semaphore-address> --group <group-id> --network goerli
```
<TabItem value="yarn">
```bash
yarn deploy --semaphore <semaphore-address> --group <group-id> --network goerli
```
</TabItem>
</TabItem>
<TabItem value="yarn">
<TabItem value="pnpm">
```bash
pnpm deploy --semaphore <semaphore-address> --group <group-id> --network goerli
```
</TabItem>
</Tabs>
```bash
yarn deploy --semaphore <semaphore-address> --group <group-id> --network goerli
```
:::note
Revise las direcciones de los contratos de Semaphore [aquí](/V3/deployed-contracts).
:::
</TabItem>
<TabItem value="pnpm">
```bash
pnpm deploy --semaphore <semaphore-address> --group <group-id> --network goerli
```
</TabItem>
</Tabs>
:::note
Revise las direcciones de los contratos de Semaphore [aquí](/V3/deployed-contracts).
:::
:::caution
El group id (id del grupo) es un número.
:::
:::caution
El group id (id del grupo) es un número.
:::
### Inicie la app
Inicie la aplicación:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm run dev
```
</TabItem>
```bash
npm run dev
```
<TabItem value="yarn">
```bash
yarn dev
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn dev
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm dev
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm dev
```
</TabItem>
</Tabs>

View File

@@ -70,65 +70,59 @@ Para resolver eso:
1- Instale `@esbuild-plugins/node-globals-polyfill` y `@esbuild-plugins/node-modules-polyfill`
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @esbuild-plugins/node-globals-polyfill
```
</TabItem>
```bash
npm install @esbuild-plugins/node-globals-polyfill
```
<TabItem value="yarn">
```bash
yarn add @esbuild-plugins/node-globals-polyfill
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @esbuild-plugins/node-globals-polyfill
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @esbuild-plugins/node-globals-polyfill
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @esbuild-plugins/node-globals-polyfill
```
</TabItem>
</Tabs>
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @esbuild-plugins/node-modules-polyfill
```
</TabItem>
```bash
npm install @esbuild-plugins/node-modules-polyfill
```
<TabItem value="yarn">
```bash
yarn add @esbuild-plugins/node-modules-polyfill
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @esbuild-plugins/node-modules-polyfill
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @esbuild-plugins/node-modules-polyfill
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @esbuild-plugins/node-modules-polyfill
```
</TabItem>
</Tabs>
2- Modifique `vite.config.ts` para añadirlos:
@@ -236,4 +230,4 @@ Para comprobarlo, puede utilizar la [Semaphore CLI](https://github.com/semaphore
### Transacción revertida al usar el mismo external nullifier
Cuando genera una prueba usando el mismo external nullifier que usó para verificar una prueba antes, la transacción se revertirá porque ese external nullifier ya se usó. Si desea enviar y verificar varias pruebas de la misma identidad, debe usar un external nullifier diferente cada vez que genere una prueba.
Cuando genera una prueba usando el mismo external nullifier que usó para verificar una prueba antes, la transacción se revertirá porque ese external nullifier ya se usó. Si desea enviar y verificar varias pruebas de la misma identidad, debe usar un external nullifier diferente cada vez que genere una prueba.

View File

@@ -11,13 +11,15 @@
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids"
"write-heading-ids": "docusaurus write-heading-ids",
"format": "remark ./**/*.mdx --frail --quiet",
"format:write": "remark ./**/*.mdx --output"
},
"dependencies": {
"@docusaurus/core": "3.1.1",
"@docusaurus/preset-classic": "3.1.1",
"@mdx-js/react": "^3.0.0",
"@semaphore-protocol/utils": "4.0.0-beta.7",
"@semaphore-protocol/utils": "4.0.0-beta.16",
"@svgr/webpack": "^5.5.0",
"clsx": "^1.2.1",
"docusaurus-plugin-sass": "^0.2.5",
@@ -32,6 +34,11 @@
"@docusaurus/module-type-aliases": "3.1.1",
"@docusaurus/tsconfig": "3.1.1",
"@types/react": "^18.2.29",
"remark-cli": "^12.0.0",
"remark-frontmatter": "^5.0.0",
"remark-mdx": "^3.0.1",
"remark-preset-lint-consistent": "^6.0.0",
"remark-preset-lint-recommended": "^7.0.0",
"typescript": "~5.2.2"
},
"browserslist": {
@@ -48,5 +55,22 @@
},
"engines": {
"node": ">=18.0"
},
"remarkConfig": {
"settings": {
"bullet": "-"
},
"plugins": [
"remark-mdx",
"remark-preset-lint-consistent",
"remark-preset-lint-recommended",
[
"remark-frontmatter",
{
"type": "yaml",
"marker": "-"
}
]
]
}
}

View File

@@ -18,34 +18,31 @@ There are two ways to do this, using [`SemaphoreSubgraph`](https://github.com/se
## Install library
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @semaphore-protocol/data@^3
```
</TabItem>
```bash
npm install @semaphore-protocol/data@^3
```
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/data@^3
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/data@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/data@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/data@^3
```
</TabItem>
</Tabs>
## Fetch data using SemaphoreSubgraph
@@ -113,6 +110,7 @@ const semaphoreSubgraph = new SemaphoreSubgraph("sepolia")
const { members } = await semaphoreSubgraph.getGroup(groupId, { members: true })
const group = new Group(groupId, 20, members)
```
:::
## Fetch data using SemaphoreEthers
@@ -178,4 +176,5 @@ const semaphoreEthers = new SemaphoreEthers("sepolia")
const members = await semaphoreEthers.getGroupMembers(groupId)
const group = new Group(groupId, 20, members)
```
:::

View File

@@ -11,70 +11,67 @@ import TabItem from "@theme/TabItem"
A [Semaphore group](/V3/glossary/#semaphore-group) contains [identity commitments](/V3/glossary/#identity-commitment) of group members.
Example uses of groups include the following:
- poll question that attendees join to rate an event,
- ballot that members join to vote on a proposal,
- whistleblowers who are verified employees of an organization.
- poll question that attendees join to rate an event,
- ballot that members join to vote on a proposal,
- whistleblowers who are verified employees of an organization.
A Semaphore group is an [incremental Merkle tree](/V3/glossary/#merkle-tree), and group members (i.e., [identity commitments](/V3/glossary/#identity-commitment)) are tree leaves.
Semaphore groups set the following three parameters:
- **Group id**: a unique identifier for the group;
- **Tree depth**: the maximum number of members a group can contain (`max size = 2 ^ tree depth`);
- **Members**: the list of members to initialize the group.
- **Group id**: a unique identifier for the group;
- **Tree depth**: the maximum number of members a group can contain (`max size = 2 ^ tree depth`);
- **Members**: the list of members to initialize the group.
Learn how to work with groups.
- [**Off-chain groups**](#off-chain-groups)
- [**On-chain groups**](#on-chain-groups)
- [**Off-chain groups**](#off-chain-groups)
- [**On-chain groups**](#on-chain-groups)
## Off-chain groups
- [Create a group](#create-a-group)
- [Add members](#add-members)
- [Remove or update members](#remove-or-update-members)
- [Create a group](#create-a-group)
- [Add members](#add-members)
- [Remove or update members](#remove-or-update-members)
### Create a group
Use the [`@semaphore-protocol/group`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/group) library `Group` class to create an off-chain group with the following parameters:
- `Group id`: a unique identifier for the group;
- `Tree depth`: (_default `20`_) the maximum number of members a group can contain (`max size = 2 ^ tree depth`).
- `Members`: (_default `[]`_) the list of members to initialize the group.
- `Group id`: a unique identifier for the group;
- `Tree depth`: (*default `20`*) the maximum number of members a group can contain (`max size = 2 ^ tree depth`).
- `Members`: (*default `[]`*) the list of members to initialize the group.
#### Install library:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @semaphore-protocol/group@^3
```
</TabItem>
```bash
npm install @semaphore-protocol/group@^3
```
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/group@^3
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/group@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/group@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/group@^3
```
</TabItem>
</Tabs>
To create a group with default _`treeDepth`_, call the `Group` constructor without the second parameter. For example:
To create a group with default *`treeDepth`*, call the `Group` constructor without the second parameter. For example:
```ts
import { Group } from "@semaphore-protocol/group"
@@ -82,7 +79,7 @@ import { Group } from "@semaphore-protocol/group"
const group = new Group(1)
```
The following example code passes _`treeDepth`_ to create a group for `2 ^ 30 = 1073741824` members:
The following example code passes *`treeDepth`* to create a group for `2 ^ 30 = 1073741824` members:
```ts
import { Group } from "@semaphore-protocol/group"

View File

@@ -11,50 +11,47 @@ import TabItem from "@theme/TabItem"
In order to join a [Semaphore group](/V3/glossary#semaphore-group), a user must first create a [Semaphore identity](/V3/glossary#semaphore-identity).
A Semaphore identity contains two values generated with the identity:
- Identity trapdoor
- identity nullifier
- Identity trapdoor
- identity nullifier
To use and verify the identity, the identity owner (user) must know the trapdoor and nullifier values.
To prevent fraud, the owner should keep both values secret.
## Create identities
In your code, use the [`@semaphore-protocol/identity`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/identity) library to create a Semaphore identity _deterministically_ (from the hash of a message) or _randomly_.
In your code, use the [`@semaphore-protocol/identity`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/identity) library to create a Semaphore identity *deterministically* (from the hash of a message) or *randomly*.
- [**Create random identities**](#create-random-identities)
- [**Create deterministic identities**](#create-deterministic-identities)
- [**Create random identities**](#create-random-identities)
- [**Create deterministic identities**](#create-deterministic-identities)
### Install library:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @semaphore-protocol/identity@^3
```
</TabItem>
```bash
npm install @semaphore-protocol/identity@^3
```
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/identity@^3
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/identity@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/identity@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/identity@^3
```
</TabItem>
</Tabs>
### Create random identities
@@ -69,8 +66,8 @@ const { trapdoor, nullifier, commitment } = new Identity()
The new identity contains two random secret values: `trapdoor` and `nullifier`, and one public value: `commitment`.
The Poseidon hash of the identity nullifier and trapdoor is called the _identity secret_,
and its hash is the _identity commitment_.
The Poseidon hash of the identity nullifier and trapdoor is called the *identity secret*,
and its hash is the *identity commitment*.
An identity commitment, similarly to Ethereum addresses, is a public value used
in Semaphore groups to represent the identity of a group member. The secret values are similar to
@@ -79,7 +76,7 @@ Ethereum private keys and are used to generate Semaphore zero-knowledge proofs a
### Create deterministic identities
If you pass a message as a parameter, Semaphore generates `trapdoor` and `nullifier`
from the _SHA256_ hash of the message.
from the *SHA256* hash of the message.
The message might be a password or a message that the user cryptographically signs with a private key.
When using deterministic identities, you should always keep the message secret.

View File

@@ -10,57 +10,54 @@ import TabItem from "@theme/TabItem"
Once a user joins their [Semaphore identity](/V3/glossary#semaphore-identity) to a [Semaphore group](/V3/glossary#semaphore-group), the user can signal anonymously with a zero-knowledge proof that proves the following:
- the user is a member of the group,
- the same user created the signal and the proof.
- the user is a member of the group,
- the same user created the signal and the proof.
Developers can use Semaphore for the following:
- [**Generate a proof off-chain**](#generate-a-proof-off-chain)
- [**Verify a proof off-chain**](#verify-a-proof-off-chain)
- [**Verify a proof on-chain**](#verify-a-proof-on-chain)
- [**Generate a proof off-chain**](#generate-a-proof-off-chain)
- [**Verify a proof off-chain**](#verify-a-proof-off-chain)
- [**Verify a proof on-chain**](#verify-a-proof-on-chain)
## Generate a proof off-chain
Use the [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/proof) library to generate an off-chain proof.
To generate a proof, pass the following parameters to the `generateProof` function:
- `identity`: the Semaphore identity of the user broadcasting the signal and generating the proof;
- `group`: the group to which the user belongs;
- `externalNullifier`: the value that prevents double-signaling;
- `signal`: the signal the user wants to send anonymously;
- `snarkArtifacts`: the `zkey` and `wasm` [trusted setup files](/V3/glossary/#trusted-setup-files).
- `identity`: the Semaphore identity of the user broadcasting the signal and generating the proof;
- `group`: the group to which the user belongs;
- `externalNullifier`: the value that prevents double-signaling;
- `signal`: the signal the user wants to send anonymously;
- `snarkArtifacts`: the `zkey` and `wasm` [trusted setup files](/V3/glossary/#trusted-setup-files).
#### Install library:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @semaphore-protocol/proof@^3
```
</TabItem>
```bash
npm install @semaphore-protocol/proof@^3
```
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/proof@^3
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/proof@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/proof@^3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/proof@^3
```
</TabItem>
</Tabs>
In the voting system use case, once all the voters have joined their [identities](/V3/guides/identities#create-identities) to the ballot [group](/V3/guides/groups),
@@ -87,6 +84,7 @@ If you are generating the proof on the client side, you can avoid adding the sna
```ts
const fullProof = await generateProof(identity, group, externalNullifier, signal)
```
:::
## Verify a proof off-chain
@@ -94,8 +92,8 @@ const fullProof = await generateProof(identity, group, externalNullifier, signal
Use the [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/proof) library to verify a Semaphore proof off-chain.
To verify a proof, pass the following to the `verifyProof` function:
- `fullProof`: the Semaphore proof;
- `treeDepth`: the Merkle tree depth.
- `fullProof`: the Semaphore proof;
- `treeDepth`: the Merkle tree depth.
The following code sample shows how to verify the previously generated proof:
@@ -117,12 +115,12 @@ See our [deployed contracts](/V3/deployed-contracts) to find the addresses for y
To verify Semaphore proofs in your contract, import `ISemaphore.sol`, pass it the `Semaphore.sol` address and call the `verifyProof` method with following parameters:
- `groupId`: the identifier of the group;
- `merkleTreeRoot`: the root of the Merkle tree;
- `signal`: the signal the user wants to send anonymously;
- `nullifierHash`: a nullifier hash;
- `externalNullifier`: the value that prevents double-signaling;
- `proof`: a Solidity-compatible Semaphore proof.
- `groupId`: the identifier of the group;
- `merkleTreeRoot`: the root of the Merkle tree;
- `signal`: the signal the user wants to send anonymously;
- `nullifierHash`: a nullifier hash;
- `externalNullifier`: the value that prevents double-signaling;
- `proof`: a Solidity-compatible Semaphore proof.
:::info
You can import `ISemaphore.sol` and other Semaphore contracts from the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/contracts) NPM module.

View File

@@ -31,37 +31,34 @@ The [`semaphore CLI`](https://github.com/semaphore-protocol/semaphore/tree/v3.15
To start working on your project, install the dependencies:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
cd my-app
npm i
```
</TabItem>
```bash
cd my-app
npm i
```
<TabItem value="yarn">
```bash
cd my-app
yarn
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
cd my-app
yarn
```
</TabItem>
<TabItem value="pnpm">
```bash
cd my-app
pnpm install
```
</TabItem>
<TabItem value="pnpm">
```bash
cd my-app
pnpm install
```
</TabItem>
</Tabs>
## Output
@@ -116,34 +113,31 @@ cd apps/contracts
And compile your contracts:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm run compile
```
</TabItem>
```bash
npm run compile
```
<TabItem value="yarn">
```bash
yarn compile
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn compile
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm compile
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm compile
```
</TabItem>
</Tabs>
### Test contracts
@@ -151,100 +145,91 @@ pnpm compile
Test your contracts:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm test
```
</TabItem>
```bash
npm test
```
<TabItem value="yarn">
```bash
yarn test
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn test
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm test
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm test
```
</TabItem>
</Tabs>
Generate a test coverage report:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm run test:coverage
```
</TabItem>
```bash
npm run test:coverage
```
<TabItem value="yarn">
```bash
yarn test:coverage
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn test:coverage
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm test:coverage
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm test:coverage
```
</TabItem>
</Tabs>
Or a test gas report:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm run test:report-gas
```
</TabItem>
```bash
npm run test:report-gas
```
<TabItem value="yarn">
```bash
yarn test:report-gas
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn test:report-gas
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm test:report-gas
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm test:report-gas
```
</TabItem>
</Tabs>
### Deploy contracts
@@ -255,82 +240,76 @@ In the project root folder:
1. Add your environment variables in the `.env` file.
:::note
You should at least set a valid Infura API Key (you could use Alchemy as well) and a private key with some ethers.
:::
:::note
You should at least set a valid Infura API Key (you could use Alchemy as well) and a private key with some ethers.
:::
2. Go to the `apps/contracts` folder and deploy your contract.
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm run deploy -- --semaphore <semaphore-address> --group <group-id> --network arbitrum-goerli
```
</TabItem>
```bash
npm run deploy -- --semaphore <semaphore-address> --group <group-id> --network arbitrum-goerli
```
<TabItem value="yarn">
```bash
yarn deploy --semaphore <semaphore-address> --group <group-id> --network arbitrum-goerli
```
</TabItem>
</TabItem>
<TabItem value="yarn">
<TabItem value="pnpm">
```bash
pnpm deploy --semaphore <semaphore-address> --group <group-id> --network arbitrum-goerli
```
</TabItem>
</Tabs>
```bash
yarn deploy --semaphore <semaphore-address> --group <group-id> --network arbitrum-goerli
```
:::note
Check the Semaphore contract addresses [here](/V3/deployed-contracts).
:::
</TabItem>
<TabItem value="pnpm">
```bash
pnpm deploy --semaphore <semaphore-address> --group <group-id> --network arbitrum-goerli
```
</TabItem>
</Tabs>
:::note
Check the Semaphore contract addresses [here](/V3/deployed-contracts).
:::
:::caution
The group id is a number.
:::
:::caution
The group id is a number.
:::
### Start app
Start the application:
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm run dev
```
</TabItem>
```bash
npm run dev
```
<TabItem value="yarn">
```bash
yarn dev
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn dev
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm dev
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm dev
```
</TabItem>
</Tabs>

View File

@@ -70,65 +70,59 @@ To solve that:
1- Install `@esbuild-plugins/node-globals-polyfill` and `@esbuild-plugins/node-modules-polyfill`
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @esbuild-plugins/node-globals-polyfill
```
</TabItem>
```bash
npm install @esbuild-plugins/node-globals-polyfill
```
<TabItem value="yarn">
```bash
yarn add @esbuild-plugins/node-globals-polyfill
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @esbuild-plugins/node-globals-polyfill
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @esbuild-plugins/node-globals-polyfill
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @esbuild-plugins/node-globals-polyfill
```
</TabItem>
</Tabs>
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @esbuild-plugins/node-modules-polyfill
```
</TabItem>
```bash
npm install @esbuild-plugins/node-modules-polyfill
```
<TabItem value="yarn">
```bash
yarn add @esbuild-plugins/node-modules-polyfill
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @esbuild-plugins/node-modules-polyfill
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @esbuild-plugins/node-modules-polyfill
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @esbuild-plugins/node-modules-polyfill
```
</TabItem>
</Tabs>
2- Modify the `vite.config.ts` to add them:

View File

@@ -1,5 +1,5 @@
---
sidebar_position: 11
sidebar_position: 12
---
# Credits

View File

@@ -1,5 +1,5 @@
---
sidebar_position: 10
sidebar_position: 11
---
# FAQ

View File

@@ -111,23 +111,23 @@ In the project root folder:
1. Add your environment variables in the `.env` file.
:::note
You should at least set a valid Infura API Key (you could use Alchemy as well) and a private key with some ethers.
:::
:::note
You should at least set a valid Infura API Key (you could use Alchemy as well) and a private key with some ethers.
:::
2. Go to the `apps/contracts` folder and deploy your contract.
```bash
yarn deploy --semaphore <semaphore-address> --group <group-id> --network sepolia
```
```bash
yarn deploy --semaphore <semaphore-address> --group <group-id> --network sepolia
```
:::note
Check the Semaphore contract addresses [here](/deployed-contracts).
:::
:::note
Check the Semaphore contract addresses [here](/deployed-contracts).
:::
:::caution
The group id is a number.
:::
:::caution
The group id is a number.
:::
### Start app

View File

@@ -1,5 +1,5 @@
---
sidebar_position: 7
sidebar_position: 8
---
# Glossary

View File

@@ -11,9 +11,9 @@ import TabItem from "@theme/TabItem"
A [Semaphore group](/glossary/#group) contains [identity commitments](/glossary/#identity-commitment) of group members.
Example uses of groups include the following:
- poll question that attendees join to rate an event,
- ballot that members join to vote on a proposal,
- whistleblowers who are verified employees of an organization.
- poll question that attendees join to rate an event,
- ballot that members join to vote on a proposal,
- whistleblowers who are verified employees of an organization.
:::info
Semaphore V4 uses the [ZK-Kit](https://github.com/privacy-scaling-explorations/zk-kit) LeanIMT (i.e., Lean Incremental
@@ -28,34 +28,31 @@ Use the [`@semaphore-protocol/group`](https://github.com/semaphore-protocol/sema
### Install package
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @semaphore-protocol/group
```
</TabItem>
```bash
npm install @semaphore-protocol/group
```
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/group
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/group
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/group
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/group
```
</TabItem>
</Tabs>
:::info
@@ -142,39 +139,36 @@ Use the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/
### Install package
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @semaphore-protocol/contracts
```
</TabItem>
```bash
npm install @semaphore-protocol/contracts
```
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/contracts
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/contracts
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/contracts
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/contracts
```
</TabItem>
</Tabs>
### Create a group
To create a group initialize your contract with the `Semaphore.sol` address and a group ID.
To create a group initialize your contract with the `Semaphore.sol` address.
The `createGroup` function can be used to create a Semaphore group. For example:
```solidity
@@ -187,16 +181,15 @@ contract YourContract {
uint256 public groupId;
constructor(ISemaphore _semaphore, uint256 _groupId) {
constructor(ISemaphore _semaphore) {
semaphore = _semaphore;
groupId = _groupId;
semaphore.createGroup(groupId, address(this));
groupId = semaphore.createGroup();
}
}
```
`Semaphore.sol` also includes a mechanism to verify Semaphore proofs created with old Merkle tree roots, the duration of which can optionally be defined by the admin in the `createGroup` function as the third parameter. The default value duration is 1 hour and it should be fine for most use-cases. For more context see the issue [#98](https://github.com/semaphore-protocol/semaphore/issues/98).
`Semaphore.sol` also includes a mechanism to verify Semaphore proofs created with old Merkle tree roots, the duration of which can optionally be defined by the admin in the `createGroup` function. The default value duration is 1 hour and it should be fine for most use-cases. For more context see the issue [#98](https://github.com/semaphore-protocol/semaphore/issues/98).
### Add members
@@ -241,4 +234,3 @@ function removeMember(uint256 identityCommitment, uint256[] calldata merkleProof
:::info
If you want to see an example of a working contract, have a look at the [`contracts-hardhat`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-contracts-hardhat) CLI template. You can also create a project with that template by running `semaphore create my-app --template contracts-hardhat`.
:::

View File

@@ -11,9 +11,9 @@ import TabItem from "@theme/TabItem"
In order to join a [Semaphore group](/glossary#group), a user must first create a [Semaphore identity](/glossary#identity).
A Semaphore identity contains three values generated with the identity:
- Private key
- Public key
- Commitment
- Private key
- Public key
- Commitment
To use and verify the identity, the identity owner (user) must know its private key.
To prevent fraud, the owner should keep their private key secret.
@@ -23,34 +23,31 @@ To prevent fraud, the owner should keep their private key secret.
In your code, use the [`@semaphore-protocol/identity`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/identity) package to manage Semaphore identites.
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @semaphore-protocol/identity
```
</TabItem>
```bash
npm install @semaphore-protocol/identity
```
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/identity
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/identity
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/identity
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/identity
```
</TabItem>
</Tabs>
:::info
@@ -88,7 +85,7 @@ You may choose to delegate such functionality to existing wallets such as Metama
1. In Metamask, a user signs a message with the private key of their Ethereum account.
2. In your application, the user creates a deterministic identity with the signed message that acts as your Semaphore private key.
3. The user can now recreate their Semaphore identity whenever they want by signing the same message with their Ethereum account in Metamask.
:::
:::
## Sign and verify messages

View File

@@ -10,8 +10,8 @@ import TabItem from "@theme/TabItem"
Once a user joins a [Semaphore group](/glossary#group) with their [Semaphore identity](/glossary#identity), the user can send their anonymous [message](/glossary#message) with a zero-knowledge proof that proves the following:
- the user is a member of the group,
- the same user created the message and the proof.
- the user is a member of the group,
- the same user created the message and the proof.
A unique [nullifier](/glossary#nullifier) is also generated for each proof that can be used to check whether that proof has already been validated.
@@ -20,34 +20,31 @@ A unique [nullifier](/glossary#nullifier) is also generated for each proof that
In your code, use the [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/proof) package to generate and verify a proof.
<Tabs
defaultValue="npm"
groupId="package-managers"
values={[
defaultValue="npm"
groupId="package-managers"
values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}>
<TabItem value="npm">
]}
>
<TabItem value="npm">
```bash
npm install @semaphore-protocol/proof
```
</TabItem>
```bash
npm install @semaphore-protocol/proof
```
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/proof
```
</TabItem>
</TabItem>
<TabItem value="yarn">
```bash
yarn add @semaphore-protocol/proof
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/proof
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm add @semaphore-protocol/proof
```
</TabItem>
</Tabs>
:::info
@@ -73,7 +70,7 @@ import { Group } from "@semaphore-protocol/group"
const semaphoreSubgraph = new SemaphoreSubgraph("sepolia")
const { members } = semaphoreSubgraph.getGroup("42", { members: true })
const { members } = await semaphoreSubgraph.getGroup("42", { members: true })
const group = new Group(members)
```

View File

@@ -1,5 +1,5 @@
---
sidebar_position: 8
sidebar_position: 9
---
import Articles from '@site/src/components/Articles';

View File

@@ -1,5 +1,5 @@
---
sidebar_position: 6
sidebar_position: 7
---
import RemoteCode from '@site/src/components/RemoteCode';
@@ -7,7 +7,7 @@ import RemoteCode from '@site/src/components/RemoteCode';
# Subgraph
[The Graph](https://thegraph.com/) is a protocol for indexing networks like Ethereum and IPFS.
Site owners publish _subgraphs_ that expose site data for anyone to query.
Site owners publish *subgraphs* that expose site data for anyone to query.
Semaphore's subgraph allows you to retrieve data from the [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) smart contract.
:::tip
@@ -16,5 +16,4 @@ The Graph protocol uses the [GraphQL](https://graphql.org/) query language. For
## Schema
<RemoteCode url="https://raw.githubusercontent.com/semaphore-protocol/semaphore/main/apps/subgraph/schema.graphql"
title="apps/subgraph/schema.graphql" language="graphql" />
<RemoteCode url="https://raw.githubusercontent.com/semaphore-protocol/semaphore/main/apps/subgraph/schema.graphql" title="apps/subgraph/schema.graphql" language="graphql" />

View File

@@ -4,7 +4,7 @@ sidebar_position: 2
# Circuits
The [Semaphore circuit](https://github.com/semaphore-protocol/semaphore/tree/main/packages/circuits/semaphore.circom) is the heart of the protocol and consists of three parts:
The [Semaphore circuit](https://github.com/semaphore-protocol/semaphore/blob/main/packages/circuits/src/semaphore.circom) is the heart of the protocol and consists of three parts:
- [Proof of membership](#proof-of-membership)
- [Nullifier](#nullifier)

View File

@@ -1,5 +1,5 @@
---
sidebar_position: 9
sidebar_position: 10
---
import Tabs from "@theme/Tabs"

View File

@@ -0,0 +1,50 @@
---
sidebar_position: 6
---
# Trusted Setup
gm, everyone 😎 we are excited to announce the upcoming Multi-Party Computation (MPC) Phase 2 Trusted Setup ceremony for the Semaphore V4 circuit - this is crucial for establishing a robust security foundation for the cryptographic protocol 🎉
The ceremony will take place from **June 10** to **July 10**. If all goes to plan, finalization should take place on **July 15** with the announcement of the final beacon on **July 12**.
## Securing Semaphore V4
To contribute to this ceremony, you will just need your browser!
1. Visit [ceremony.pse.dev](https://ceremony.pse.dev/projects/Semaphore%20V4%20Ceremony).
2. Login and associate your **Github** account.
3. Hit the `contribute` button and wait for your turn.
nb. you will find your contribution certificate on your GitHub gists - and, if all goes wrong or you feel lost, there are instructions on site or post a message on Semaphore / PSE discord.
## What You Need to Know About the Ceremony
### Your Role
Many zero-knowledge proof systems, including those based on the Groth16 scheme, require this layer of randomness, often referred to as "toxic waste” which must remain unknown to anyone to maintain the integrity of the zero-knowledge proof system. Trusted setups rely on a 1 of N honest participant assumption. As long as just one participant actually discards their “toxic waste”, the proof system will be secure. You can be that one participant by providing your unique entropy with your contribution, making the ceremony unpredictable and unbiased, safeguarding the entire process against potential vulnerabilities.
### Why It Matters
Trusted setups are crucial as they generate a set of parameters necessary to initiate SNARK-based systems. Through a series of computations performed by various participants. This sequence involves downloading previous contributions, adding generated randomness, and uploading the results of your contribution. These contributions are then integrated into the final artifacts crucial for proof generation/verification.
### Semaphore Circuit
The [Semaphore circuit](https://github.com/semaphore-protocol/semaphore/blob/main/packages/circuits/src/semaphore.circom) centered around the creation of the _Semaphore identity_ and _identity commitment_, includes verification processes, and facilitates the generation of the _nullifier_. We are going to support `MAX_DEPTH` from 1 to 32 - therefore you will have to contribute to 32 variants of the same circuit. Since the constraints will range from 2k to less than 10k with very small artifacts size (≤ 8mb x contribution), the waiting and contribution time shouldnt be much!
### Transparency and Fairness
We are committed to transparency on ceremony setup, execution, finalization, and later verification. Our primary goal is to **engage as many contributors as possible** to ensure the circuit is **secure** and **production-ready**. To this end, the ceremony is designed to _maximize contributor inclusion_, monitor & troubleshoot whenever is needed, _lower the entry barriers_, _making contributiong as effortless as possible_. A key step towards achieving these goals is running the ceremony w/ [p0tion](https://github.com/privacy-scaling-explorations/p0tion): an in-house developed, open-source, battle-tested tool that is fully equipped to meet our needs.
### Ceremony Settings
To protect the ceremony from sybils, in order to contribute you must have a GitHub account such that you have: 1 public repository, at least 1 follower, following at least 5 other accounts and, your account is at least 1 month old. While to protect from fake contributors or people hanging due to connection/machine resources, we are going to set a 10 minutes time-window on contributions (+ 1 hour verification) - after this amount of time, you will be kicked out and will have to wait **1 day** before you can contribute again.
## Troubleshooting
- If you have been idle longer than expected, it may be that the current contributor has been blocked for some reason. Do not worry, the maximum wait in this case is one hour, after which you will be able to continue contributing.
### Learn more about Trusted Setups
- [How Do Trusted Setups Work? - Vitalik](https://vitalik.eth.limo/general/2022/03/14/trustedsetup.html)
- [p0tion FAQs](https://p0tion.super.site/faqs#block-cebca23ebb514c2ea096ad44d4833356)

View File

@@ -40,11 +40,12 @@ and [JavaScript libraries](https://github.com/semaphore-protocol/semaphore/tree/
### Audits
| Version | Auditors | Report | Scope |
| ------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------ |
| v2.0.0 | [PSE](https://pse.dev/) | [Semaphore_2.0.0_Audit.pdf](https://github.com/semaphore-protocol/semaphore/files/9850441/Semaphore_2.0.0_Audit.pdf) | `circuits`, `contracts` |
| v2.5.0 | [PSE](https://pse.dev/) | [Semaphore_2.5.0_Audit.pdf](https://github.com/semaphore-protocol/semaphore/files/9845008/Semaphore_2.5.0_Audit.pdf) | `contracts`, `libraries` |
| v3.0.0 | [Veridise](https://veridise.com/) | [Semaphore_3.0.0_Audit.pdf](https://github.com/semaphore-protocol/semaphore/files/10513776/Semaphore_3.0.0_Audit.pdf) | `circuits`, `contracts` |
| Version | Auditors | Report | Scope |
| ------- | --------------------------------- | -------------------------------------------------------------------------------- | ------------------------------------ |
| v2.0.0 | [PSE](https://pse.dev/) | [Semaphore_2.0.0_Audit.pdf](https://semaphore.pse.dev/Semaphore_2.0.0_Audit.pdf) | `circuits`, `contracts` |
| v2.5.0 | [PSE](https://pse.dev/) | [Semaphore_2.5.0_Audit.pdf](https://semaphore.pse.dev/Semaphore_2.5.0_Audit.pdf) | `contracts`, `libraries` |
| v3.0.0 | [Veridise](https://veridise.com/) | [Semaphore_3.0.0_Audit.pdf](https://semaphore.pse.dev/Semaphore_3.0.0_Audit.pdf) | `circuits`, `contracts` |
| v4.0.0 | [PSE](https://pse.dev/) | [Semaphore_4.0.0_Audit.pdf](https://semaphore.pse.dev/Semaphore_4.0.0_Audit.pdf) | `circuits`, `contracts`, `libraries` |
:::caution
Semaphore V4 is in early testing and might have bugs. Please, don't use it in production.

View File

@@ -42,14 +42,15 @@
## Networks
| Semaphore version | Sepolia | Mumbai | Optimism Sepolia | Arbitrum Sepolia | Arbitrum One |
| ----------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| v2.0 | N/A | N/A | N/A | N/A | [semaphore-protocol/arbitrum](https://thegraph.com/hosted-service/subgraph/semaphore-protocol/arbitrum) |
| v2.5 | N/A | N/A | N/A | N/A | N/A |
| v2.6 | N/A | N/A | N/A | N/A | [semaphore-protocol/arbitrum-86337c](https://thegraph.com/hosted-service/subgraph/semaphore-protocol/arbitrum-86337c) |
| v3.0 - v3.1 | N/A | N/A | N/A | N/A | [semaphore-protocol/arbitrum-72dca3](https://thegraph.com/hosted-service/subgraph/semaphore-protocol/arbitrum-72dca3) |
| >= v3.2 | [semaphore-sepolia](https://api.studio.thegraph.com/query/14377/semaphore-sepolia/v3.6.1) | [semaphore-mumbai](https://api.studio.thegraph.com/query/14377/semaphore-mumbai/v3.6.1) | N/A | N/A | [semaphore-arbitrum](https://api.studio.thegraph.com/query/14377/semaphore-arbitrum/v3.6.1) |
| >= v4.0.0-beta | [semaphore-sepolia](https://api.studio.thegraph.com/query/14377/semaphore-sepolia/v4.0.0-beta) | [semaphore-matic-mumbai](https://api.studio.thegraph.com/query/14377/semaphore-matic-mumbai/v4.0.0-beta) | [semaphore-optimism-sepolia](https://api.studio.thegraph.com/query/14377/semaphore-optimism-sepolia/v4.0.0-beta) | [semaphore-arbitrum-sepolia](https://api.studio.thegraph.com/query/14377/semaphore-arbitrum-sepolia/v4.0.0-beta) | N/A |
| Semaphore version | Sepolia | Polygon Mumbai | Optimism Sepolia | Arbitrum Sepolia | Arbitrum One | Polygon Amoy |
| ----------------- | ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| v2.0 | N/A | N/A | N/A | N/A | [semaphore-protocol/arbitrum](https://thegraph.com/hosted-service/subgraph/semaphore-protocol/arbitrum) | N/A |
| v2.5 | N/A | N/A | N/A | N/A | N/A | N/A |
| v2.6 | N/A | N/A | N/A | N/A | [semaphore-protocol/arbitrum-86337c](https://thegraph.com/hosted-service/subgraph/semaphore-protocol/arbitrum-86337c) | N/A |
| v3.0 - v3.1 | N/A | N/A | N/A | N/A | [semaphore-protocol/arbitrum-72dca3](https://thegraph.com/hosted-service/subgraph/semaphore-protocol/arbitrum-72dca3) | N/A |
| >= v3.2 | [semaphore-sepolia](https://api.studio.thegraph.com/query/14377/semaphore-sepolia/v3.6.1) | [semaphore-mumbai](https://api.studio.thegraph.com/query/14377/semaphore-mumbai/v3.6.1) | N/A | N/A | [semaphore-arbitrum](https://api.studio.thegraph.com/query/14377/semaphore-arbitrum/v3.6.1) | N/A |
| v4.0.0-beta | [semaphore-sepolia](https://api.studio.thegraph.com/query/14377/semaphore-sepolia/v4.0.0-beta) | [semaphore-matic-mumbai](https://api.studio.thegraph.com/query/14377/semaphore-matic-mumbai/v4.0.0-beta) | [semaphore-optimism-sepolia](https://api.studio.thegraph.com/query/14377/semaphore-optimism-sepolia/v4.0.0-beta) | [semaphore-arbitrum-sepolia](https://api.studio.thegraph.com/query/14377/semaphore-arbitrum-sepolia/v4.0.0-beta) | N/A | N/A |
| >= v4.0.0-beta.15 | [semaphore-sepolia](https://api.studio.thegraph.com/query/14377/semaphore-sepolia/v4.0.0-beta.15) | N/A | [semaphore-optimism-sepolia](https://api.studio.thegraph.com/query/14377/semaphore-optimism-sepolia/v4.0.0-beta.15) | [semaphore-arbitrum-sepolia](https://api.studio.thegraph.com/query/14377/semaphore-arbitrum-sepolia/v4.0.0-beta.15) | N/A | [semaphore-matic-amoy](https://api.studio.thegraph.com/query/14377/semaphore-matic-amoy/v4.0.0-beta.15) |
## 🛠 Install
@@ -134,5 +135,5 @@ yarn deploy-local
Once the subgraph is published it will start indexing. You can query the subgraph using the following GraphQL endpoint:
```
http://127.0.0.1:8000/subgraphs/name/sempahore/graphql
http://127.0.0.1:8000/subgraphs/name/semaphore/graphql
```

View File

@@ -7,8 +7,8 @@
"scripts": {
"codegen": "node scripts/generate-subgraph.js ${0} && graph codegen",
"build": "graph build",
"auth": "graph auth --studio",
"deploy": "graph deploy --node https://api.studio.thegraph.com/deploy/ ${0}",
"auth": "graph auth --studio ${0}",
"deploy": "graph deploy --studio ${0}",
"start-ipfs": "node scripts/start-ipfs.js",
"create-local": "graph create --node http://localhost:8020/ semaphore",
"remove-local": "graph remove --node http://localhost:8020/ semaphore",
@@ -16,8 +16,8 @@
"test": "graph test Semaphore -v 0.5.0"
},
"dependencies": {
"@graphprotocol/graph-cli": "0.67.0",
"@graphprotocol/graph-ts": "0.32.0",
"@graphprotocol/graph-cli": "0.77.0",
"@graphprotocol/graph-ts": "0.35.1",
"@semaphore-protocol/utils": "workspace:packages/utils"
},
"devDependencies": {

View File

@@ -6,6 +6,9 @@ const network = process.argv.at(2)
const template = readFileSync("./subgraph.template.yaml", "utf-8")
const subgraph = Mustache.render(template, { network, ...getDeployedContract(network) })
const subgraph = Mustache.render(template, {
network: network === "matic-amoy" ? "polygon-amoy" : network,
...getDeployedContract(network)
})
writeFileSync("./subgraph.yaml", subgraph)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,9 +1,10 @@
import { Box, Container } from "@chakra-ui/react"
import { Box, Container, Link } from "@chakra-ui/react"
import type { Metadata } from "next"
import Script from "next/script"
import Footer from "../components/Footer"
import Navbar from "../components/Navbar"
import Providers from "./providers"
import Banner from "@/components/Banner"
export const metadata: Metadata = {
title: "Semaphore",
@@ -30,9 +31,24 @@ export default function RootLayout({ children }: { children: React.ReactNode })
<html lang="en" suppressHydrationWarning>
<body suppressHydrationWarning>
<Providers>
<Banner>
Semaphore V4
<Link
_hover={{
textDecoration: "underline",
textDecorationColor: "primary.600"
}}
href="https://ceremony.pse.dev/projects/Semaphore%20V4%20Ceremony"
ml="1"
isExternal
>
<b>Trusted Setup</b>
</Link>{" "}
ceremony is open for contributions until <b>July 10</b>.
</Banner>
<Navbar />
<Container maxW="1440px" px={{ base: "5", md: "10" }}>
<Box h="96px" />
<Box h="146px" /> {/* Adjusted to account for TopBanner and Navbar */}
{children}
<Footer />
</Container>

View File

@@ -0,0 +1,28 @@
import { Box, Text } from "@chakra-ui/react"
interface BannerProps {
children: React.ReactNode
}
export default function Banner({ children }: BannerProps) {
return (
<Box
bg="darkBlueBg"
py="3"
textAlign="center"
borderBottom="1px solid"
color="text"
fontSize="sm"
position="fixed"
top="0"
left="0"
right="0"
zIndex="2"
display="flex"
justifyContent="center"
alignItems="center"
>
<Text>{children}</Text>
</Box>
)
}

View File

@@ -30,7 +30,7 @@ export default function Navbar() {
const { isOpen, onOpen, onClose } = useDisclosure()
return (
<HStack zIndex="1" py="7" top="0" left="0" right="0" position="fixed" bgColor="darkBlueBg">
<HStack zIndex="1" py="7" top="42px" left="0" right="0" position="fixed" bgColor="darkBlueBg">
<Container maxW="1440px" px={{ base: "5", md: "10" }}>
<HStack justify="space-between">
<Link as={NextLink} href="/">

View File

@@ -33,5 +33,12 @@
"date": "2023-10-30",
"authors": ["Laszlo Fazekas"],
"url": "https://hackernoon.com/brief-introduction-of-semaphore-a-zero-knowledge-group-membership-protocol"
},
{
"title": "Semaphore v3 overview + simplification",
"minRead": 7,
"date": "2024-01-01",
"authors": ["Vivek Bhupatiraju"],
"url": "https://vivs.wiki/Semaphore"
}
]

View File

@@ -1,14 +1,20 @@
[
{
"name": "ETHGlobal - Circuit Breaker",
"date": "Feb 2-21, 2024",
"description": "Semaphore team will deliver the online workshop \"Semaphore: The power of anonymity\" about building ZK applications. It will also mention improvements on Semaphore v4 and ZK-KIT.",
"link": "https://ethglobal.com/events/circuitbreaker"
"name": "Trusted Setup ceremony",
"date": "June 10 - July 10, 2024",
"description": "The Semaphore team will perform the Phase 2 MPC Trusted Setup ceremony to secure V4 circuit variants from 1 to 32 tree depths.",
"link": "https://docs.semaphore.pse.dev/trusted-setup"
},
{
"name": "ETHDam",
"date": "Apr 12-14, 2024",
"name": "ETHRome",
"date": "Oct 4-6, 2024",
"description": "Semaphore team will deliver an in-person talk and sponsor prizes for the hackathon.",
"link": "https://www.ethdam.com/"
"link": "https://www.ethrome.org/"
},
{
"name": "Devcon",
"date": "Nov 12-15, 2024",
"description": "Semaphore team will deliver an in-person talk and run workshops.",
"link": "https://devcon.org/en/"
}
]

View File

@@ -116,7 +116,7 @@
"eventName": "ETHGlobal Circuit Breaker",
"date": "2024-02-02",
"speakers": ["Vivian Plasencia"],
"url": "https://youtu.be/tx1Xglf07yE",
"thumbnail": "https://img.youtube.com/vi/tx1Xglf07yE/0.jpg"
"url": "https://youtu.be/ux5Xy_lpiYk",
"thumbnail": "https://img.youtube.com/vi/ux5Xy_lpiYk/0.jpg"
}
]

View File

@@ -18,17 +18,17 @@
"test:contracts": "yarn workspace semaphore-contracts test:coverage",
"test:circuits": "yarn workspace @semaphore-protocol/circuits test",
"lint": "eslint . --ext .js,.ts,.tsx && yarn workspace semaphore-contracts lint",
"prettier": "prettier -c .",
"prettier:write": "prettier -w .",
"docs": "typedoc --cname js.semaphore.pse.dev --githubPages true",
"format": "prettier -c . && yarn workspace semaphore-docs format",
"format:write": "prettier -w . && yarn workspace semaphore-docs format:write",
"docs": "typedoc",
"version:bump": "yarn workspaces foreach -A --no-private version -d ${0} && yarn version apply --all && yarn remove:stable-version-field && NO_HOOK=1 git commit -am \"chore: v${0}\" && git tag v${0}",
"version:publish": "yarn build:libraries && yarn clean:cli-templates && yarn workspaces foreach -A --no-private npm publish --tolerate-republish --access public",
"version:release": "changelogithub",
"clean": "ts-node scripts/clean-apps.ts && ts-node scripts/clean-packages.ts && yarn clean:cli-templates && rimraf node_modules",
"clean:cli-templates": "ts-node scripts/clean-cli-templates.ts",
"remove:stable-version-field": "ts-node scripts/remove-stable-version-field.ts && yarn prettier:write",
"remove:stable-version-field": "ts-node scripts/remove-stable-version-field.ts && yarn format:write",
"precommit": "lint-staged",
"postinstall": "husky install"
"postinstall": "husky && git config --local core.editor cat"
},
"keywords": [
"ethereum",
@@ -58,8 +58,7 @@
"@typescript-eslint/eslint-plugin": "^7.0.2",
"@typescript-eslint/parser": "^7.0.2",
"changelogithub": "0.12.7",
"commitizen": "^4.3.0",
"cz-git": "^1.9.0",
"czg": "^1.9.1",
"dotenv": "^16.0.2",
"eslint": "^8.56.0",
"eslint-config-airbnb": "^19.0.4",
@@ -76,18 +75,13 @@
"lint-staged": "^15.2.2",
"prettier": "^3.2.5",
"rimraf": "^5.0.5",
"snarkjs": "^0.7.2",
"snarkjs": "0.7.4",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"tslib": "^2.6.2",
"typedoc": "^0.25.8",
"typescript": "^5.3.3"
},
"config": {
"commitizen": {
"path": "./node_modules/cz-git"
}
},
"resolutions": {
"changelogithub@0.12.7": "patch:changelogithub@npm:0.12.7#.yarn/patches/changelogithub-npm-0.12.7-72f348805d.patch"
}

View File

@@ -4,12 +4,12 @@
"version": "2.1.5",
"circuits": "./circuits.json",
"dirPtau": "./ptau",
"dirCircuits": "./",
"dirCircuits": "./src",
"dirInputs": "./inputs",
"dirBuild": "./build",
"optimization": 2,
"inspect": true,
"include": ["../../node_modules/circomlib/circuits", "../../node_modules/@zk-kit/circuits/circom"],
"include": ["../../node_modules/circomlib/circuits", "../../node_modules/@zk-kit/binary-merkle-root.circom/src"],
"groth16numContributions": 1,
"groth16askForEntropy": false,
"logLevel": "INFO",

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/circuits",
"version": "4.0.0-beta.7",
"version": "4.0.0-beta.16",
"description": "Semaphore Circom circuits to generate zero-knowledge proofs.",
"license": "MIT",
"files": [
@@ -24,13 +24,13 @@
"access": "public"
},
"dependencies": {
"@zk-kit/circuits": "0.2.4",
"@zk-kit/binary-merkle-root.circom": "1.0.0",
"circomlib": "2.0.5"
},
"devDependencies": {
"@semaphore-protocol/core": "workspace:^",
"@types/mocha": "^10.0.6",
"@zk-kit/eddsa-poseidon": "0.6.0",
"@zk-kit/imt": "^2.0.0-beta.2",
"@zk-kit/baby-jubjub": "1.0.1",
"circomkit": "^0.0.19",
"mocha": "^10.2.0",
"poseidon-lite": "^0.2.0"

View File

@@ -3,6 +3,7 @@ pragma circom 2.1.5;
include "babyjub.circom";
include "poseidon.circom";
include "binary-merkle-root.circom";
include "comparators.circom";
// The Semaphore circuit can be divided into 3 main parts.
// The first part involves the generation of the Semaphore identity,
@@ -34,6 +35,13 @@ template Semaphore(MAX_DEPTH) {
// The output signals are all public.
signal output merkleRoot, nullifier;
// The secret scalar must be in the prime subgroup order 'l'.
var l = 2736030358979909402780800718157159386076813972158567259200215660948447373041;
component isLessThan = LessThan(251);
isLessThan.in <== [secret, l];
isLessThan.out === 1;
// Identity generation.
// The circuit derives the EdDSA public key from a secret using
// Baby Jubjub (https://eips.ethereum.org/EIPS/eip-2494),

View File

@@ -1,3 +1,4 @@
import type { Group } from "@semaphore-protocol/core"
import { Circomkit } from "circomkit"
import { readFileSync } from "fs"
import path from "path"
@@ -5,8 +6,27 @@ import path from "path"
const configFilePath = path.join(__dirname, "../circomkit.json")
const config = JSON.parse(readFileSync(configFilePath, "utf-8"))
// eslint-disable-next-line import/prefer-default-export
export const circomkit = new Circomkit({
...config,
verbose: false
})
export function generateMerkleProof(group: Group, _index: number, maxDepth: number) {
const { siblings: merkleProofSiblings, index } = group.generateMerkleProof(_index)
// The index must be converted to a list of indices, 1 for each tree level.
// The circuit tree depth is 20, so the number of siblings must be 20, even if
// the tree depth is actually 3. The missing siblings can be set to 0, as they
// won't be used to calculate the root in the circuit.
const merkleProofIndices: number[] = []
for (let i = 0; i < maxDepth; i += 1) {
merkleProofIndices.push((index >> i) & 1)
if (merkleProofSiblings[i] === undefined) {
merkleProofSiblings[i] = BigInt(0)
}
}
return { merkleProofSiblings, merkleProofIndices }
}

View File

@@ -1,8 +1,14 @@
import { derivePublicKey, deriveSecretScalar } from "@zk-kit/eddsa-poseidon"
import { LeanIMT } from "@zk-kit/imt"
import { Group, Identity } from "@semaphore-protocol/core"
import { Base8, mulPointEscalar } from "@zk-kit/baby-jubjub"
import { WitnessTester } from "circomkit"
import { poseidon2 } from "poseidon-lite"
import { circomkit } from "./common"
import { circomkit, generateMerkleProof } from "./common"
// Prime number of 251 bits.
const l = 2736030358979909402780800718157159386076813972158567259200215660948447373041n
// Prime finite field.
const r = 21888242871839275222246405745257275088548364400416034343698204186575808495617n
describe("semaphore", () => {
let circuit: WitnessTester<
@@ -15,49 +21,6 @@ describe("semaphore", () => {
const scope = 32
const message = 43
const secret = 1
const publicKey = derivePublicKey(secret)
const leaf = poseidon2(publicKey)
const tree = new LeanIMT((a, b) => poseidon2([a, b]))
tree.insert(leaf)
for (let i = 1; i < 4; i += 1) {
tree.insert(BigInt(i))
}
const { siblings: merkleProofSiblings, index } = tree.generateProof(0)
// The index must be converted to a list of indices, 1 for each tree level.
// The circuit tree depth is 20, so the number of siblings must be 20, even if
// the tree depth is actually 3. The missing siblings can be set to 0, as they
// won't be used to calculate the root in the circuit.
const merkleProofIndices: number[] = []
for (let i = 0; i < MAX_DEPTH; i += 1) {
merkleProofIndices.push((index >> i) & 1)
if (merkleProofSiblings[i] === undefined) {
merkleProofSiblings[i] = BigInt(0)
}
}
const INPUT = {
secret: deriveSecretScalar(secret) as `${number}`,
merkleProofLength: tree.depth,
merkleProofIndices,
merkleProofSiblings,
scope,
message
}
const OUTPUT = {
nullifier: poseidon2([scope, deriveSecretScalar(secret)]),
merkleRoot: tree.root
}
before(async () => {
circuit = await circomkit.WitnessTester("semaphore", {
file: "semaphore",
@@ -67,6 +30,92 @@ describe("semaphore", () => {
})
it("Should calculate the root and the nullifier correctly", async () => {
const secret = l - 1n
const commitment = poseidon2(mulPointEscalar(Base8, secret))
const group = new Group([commitment, 2n, 3n])
const { merkleProofSiblings, merkleProofIndices } = generateMerkleProof(group, 0, MAX_DEPTH)
const INPUT = {
secret,
merkleProofLength: group.depth,
merkleProofIndices,
merkleProofSiblings,
scope,
message
}
const OUTPUT = {
nullifier: poseidon2([scope, secret]),
merkleRoot: group.root
}
await circuit.expectPass(INPUT, OUTPUT)
})
it("Should not calculate the root and the nullifier correctly if secret > l", async () => {
const secret = l
const commitment = poseidon2(mulPointEscalar(Base8, secret))
const group = new Group([commitment, 2n, 3n])
const { merkleProofSiblings, merkleProofIndices } = generateMerkleProof(group, 0, MAX_DEPTH)
const INPUT = {
secret,
merkleProofLength: group.depth,
merkleProofIndices,
merkleProofSiblings,
scope,
message
}
await circuit.expectFail(INPUT)
})
it("Should not calculate the root and the nullifier correctly if secret = r - 1", async () => {
const secret = r - 1n
const commitment = poseidon2(mulPointEscalar(Base8, secret))
const group = new Group([commitment, 2n, 3n])
const { merkleProofSiblings, merkleProofIndices } = generateMerkleProof(group, 0, MAX_DEPTH)
const INPUT = {
secret,
merkleProofLength: group.depth,
merkleProofIndices,
merkleProofSiblings,
scope,
message
}
await circuit.expectFail(INPUT)
})
it("Should calculate the root and the nullifier correctly using the Semaphore Identity library", async () => {
const { commitment, secretScalar: secret } = new Identity()
const group = new Group([commitment, 2n, 3n])
const { merkleProofSiblings, merkleProofIndices } = generateMerkleProof(group, 0, MAX_DEPTH)
const INPUT = {
secret,
merkleProofLength: group.depth,
merkleProofIndices,
merkleProofSiblings,
scope,
message
}
const OUTPUT = {
nullifier: poseidon2([scope, secret]),
merkleRoot: group.root
}
await circuit.expectPass(INPUT, OUTPUT)
})
})

View File

@@ -0,0 +1,8 @@
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"esModuleInterop": true
},
"include": ["tests/**/*"]
}

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/cli-template-contracts-hardhat",
"version": "4.0.0-beta.7",
"version": "4.0.0-beta.16",
"description": "Semaphore Hardhat template.",
"license": "Unlicense",
"files": [
@@ -41,9 +41,9 @@
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
"@nomicfoundation/hardhat-verify": "^2.0.0",
"@semaphore-protocol/core": "4.0.0-beta.7",
"@semaphore-protocol/hardhat": "4.0.0-beta.7",
"@semaphore-protocol/utils": "4.0.0-beta.7",
"@semaphore-protocol/core": "4.0.0-beta.16",
"@semaphore-protocol/hardhat": "4.0.0-beta.16",
"@semaphore-protocol/utils": "4.0.0-beta.16",
"@typechain/ethers-v6": "^0.5.0",
"@typechain/hardhat": "^9.0.0",
"@types/chai": "^4.2.0",
@@ -71,7 +71,7 @@
"typescript": "^5.3.3"
},
"dependencies": {
"@semaphore-protocol/contracts": "4.0.0-beta.7"
"@semaphore-protocol/contracts": "4.0.0-beta.16"
},
"packageManager": "yarn@4.1.0"
}

View File

@@ -20,9 +20,9 @@
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
"@nomicfoundation/hardhat-verify": "^2.0.0",
"@semaphore-protocol/core": "4.0.0-beta.7",
"@semaphore-protocol/hardhat": "4.0.0-beta.7",
"@semaphore-protocol/utils": "4.0.0-beta.7",
"@semaphore-protocol/core": "4.0.0-beta.16",
"@semaphore-protocol/hardhat": "4.0.0-beta.16",
"@semaphore-protocol/utils": "4.0.0-beta.16",
"@typechain/ethers-v6": "^0.5.0",
"@typechain/hardhat": "^9.0.0",
"@types/chai": "^4.2.0",
@@ -50,7 +50,7 @@
"typescript": "^5.3.3"
},
"dependencies": {
"@semaphore-protocol/contracts": "4.0.0-beta.7"
"@semaphore-protocol/contracts": "4.0.0-beta.16"
},
"packageManager": "yarn@4.1.0"
}

View File

@@ -9,9 +9,9 @@
"lint": "next lint"
},
"dependencies": {
"@semaphore-protocol/core": "4.0.0-beta.7",
"@semaphore-protocol/data": "4.0.0-beta.7",
"@semaphore-protocol/utils": "4.0.0-beta.7",
"@semaphore-protocol/core": "4.0.0-beta.16",
"@semaphore-protocol/data": "4.0.0-beta.16",
"@semaphore-protocol/utils": "4.0.0-beta.16",
"ethers": "^6.11.1",
"next": "14.1.0",
"next-pwa": "^5.6.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/cli-template-monorepo-ethers",
"version": "4.0.0-beta.7",
"version": "4.0.0-beta.16",
"description": "Semaphore Hardhat + Next.js + SemaphoreEthers template.",
"license": "Unlicense",
"files": [

View File

@@ -20,9 +20,9 @@
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
"@nomicfoundation/hardhat-verify": "^2.0.0",
"@semaphore-protocol/core": "4.0.0-beta.7",
"@semaphore-protocol/hardhat": "4.0.0-beta.7",
"@semaphore-protocol/utils": "4.0.0-beta.7",
"@semaphore-protocol/core": "4.0.0-beta.16",
"@semaphore-protocol/hardhat": "4.0.0-beta.16",
"@semaphore-protocol/utils": "4.0.0-beta.16",
"@typechain/ethers-v6": "^0.5.0",
"@typechain/hardhat": "^9.0.0",
"@types/chai": "^4.2.0",
@@ -50,7 +50,7 @@
"typescript": "^5.3.3"
},
"dependencies": {
"@semaphore-protocol/contracts": "4.0.0-beta.7"
"@semaphore-protocol/contracts": "4.0.0-beta.16"
},
"packageManager": "yarn@4.1.0"
}

View File

@@ -9,9 +9,9 @@
"lint": "next lint"
},
"dependencies": {
"@semaphore-protocol/core": "4.0.0-beta.7",
"@semaphore-protocol/data": "4.0.0-beta.7",
"@semaphore-protocol/utils": "4.0.0-beta.7",
"@semaphore-protocol/core": "4.0.0-beta.16",
"@semaphore-protocol/data": "4.0.0-beta.16",
"@semaphore-protocol/utils": "4.0.0-beta.16",
"ethers": "^6.11.1",
"next": "14.1.0",
"next-pwa": "^5.6.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/cli-template-monorepo-subgraph",
"version": "4.0.0-beta.7",
"version": "4.0.0-beta.16",
"description": "Semaphore Hardhat + Next.js + SemaphoreSubgraph template.",
"license": "Unlicense",
"files": [

View File

@@ -46,23 +46,25 @@
</h4>
</div>
| Setting up a project, although not particularly complex, can be a lengthy process for some people. The Semaphore CLI reduces the set-up time from a few minutes to a few seconds. In addition, it can also be used to obtain on-chain group data. |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Semaphore CLI simplifies the process of setting up Semaphore projects and retrieving on-chain group data, reducing setup time from minutes to seconds. |
| ------------------------------------------------------------------------------------------------------------------------------------------------------ |
## 🛠 Install
Install the `@semaphore-protocol/cli` package globally:
To install Semaphore CLI globally:
```bash
npm i -g @semaphore-protocol/cli
```
or run specific commands with `npx`:
Alternatively, you can use `npx` to run commands without installing the package globally:
```bash
npx @semaphore-protocol/cli create my-app
```
This command sets up a new project in the `my-app` directory using the `monorepo-ethers` template.
## 📜 Usage
```
@@ -82,3 +84,15 @@ Commands:
get-proofs [options] [group-id] Get the proofs of a group from a supported network (e.g. sepolia or arbitrum).
help [command] Display help for a specific command.
```
## 🌐 Supported Networks
Semaphore CLI supports multiple Ethereum networks. Use the `get-groups` command to interact with groups on networks like Sepolia or Arbitrum.
## 📦 Supported Templates
When creating a new project, you can choose from several templates designed to integrate seamlessly with Semaphore's privacy protocols:
- **monorepo-ethers**: Hardhat + Next.js + SemaphoreEthers
- **monorepo-subgraph**: Hardhat + Next.js + SemaphoreSubgraph
- **contracts-hardhat**: Hardhat only, focused on smart contract development.

View File

@@ -1,7 +1,7 @@
{
"name": "@semaphore-protocol/cli",
"type": "module",
"version": "4.0.0-beta.7",
"version": "4.0.0-beta.16",
"description": "A command line tool to set up your Semaphore project and get group data.",
"license": "MIT",
"bin": {
@@ -41,8 +41,8 @@
"rollup-plugin-cleanup": "^3.2.1"
},
"dependencies": {
"@semaphore-protocol/data": "4.0.0-beta.7",
"@semaphore-protocol/utils": "4.0.0-beta.7",
"@semaphore-protocol/data": "4.0.0-beta.16",
"@semaphore-protocol/utils": "4.0.0-beta.16",
"axios": "^1.6.7",
"boxen": "^7.1.1",
"chalk": "^5.3.0",

View File

@@ -7,10 +7,10 @@ import { lt as semverLt } from "semver"
const cliRegistryURL = "https://registry.npmjs.org/-/package/@semaphore-protocol/cli/dist-tags"
/**
* Checks the registry directly via the API, if that fails, tries the slower `npm view [package] version` command.
* This is important for users in environments where direct access to npm is blocked by a firewall, and packages are
* provided exclusively via a private registry.
* @param currentVersion The current version of the CLI.
* Checks for the latest version of the CLI tool against the registry. It first attempts to fetch the version directly
* via an API call. If this fails, possibly due to network restrictions, it falls back to using the `npm view` command.
* This method ensures that users behind a firewall or using a private registry can still check for updates.
* @param currentVersion The current version of the CLI being used.
*/
export default async function checkLatestVersion(currentVersion: string) {
let latestVersion: string

View File

@@ -1,12 +1,16 @@
import { SemaphoreSubgraph, SemaphoreEthers } from "@semaphore-protocol/data"
import { SupportedNetwork } from "@semaphore-protocol/utils"
import logSymbols from "log-symbols"
import Spinner from "./spinner.js"
/**
* Gets all group ids on the specified network
* @param network The specified network
* Retrieves all group IDs from the Semaphore protocol on a specified network. This function first attempts to
* fetch the group IDs using the SemaphoreSubgraph interface. If that fails, it tries the SemaphoreEthers interface
* as a fallback. This dual-method approach ensures higher reliability in fetching data across different network conditions.
* @param network The blockchain network from which to fetch the group IDs.
* @returns A promise that resolves to an array of group IDs or null if an error occurs.
*/
export default async function getGroupIds(network): Promise<string[]> {
export default async function getGroupIds(network: SupportedNetwork): Promise<string[]> {
let groupIds: string[]
const spinner = new Spinner("Fetching groups")

View File

@@ -14,9 +14,11 @@ import getGroupIds from "./getGroupIds.js"
import { getGroupId, getProjectName, getSupportedNetwork, getSupportedTemplate } from "./inquirerPrompts.js"
import Spinner from "./spinner.js"
// Define the path to the package.json file to extract metadata for the CLI.
const packagePath = `${dirname(fileURLToPath(import.meta.url))}/..`
const { description, version } = JSON.parse(readFileSync(`${packagePath}/package.json`, "utf8"))
// List of supported templates for project creation.
const supportedTemplates = [
{
value: "monorepo-ethers",
@@ -32,6 +34,7 @@ const supportedTemplates = [
}
]
// Setup the CLI program with basic information and help text.
program
.name("semaphore")
.description(description)
@@ -46,6 +49,7 @@ program
}
})
// Define the 'create' command to scaffold new Semaphore projects.
program
.command("create")
.description("Create a Semaphore project with a supported template.")
@@ -78,15 +82,19 @@ program
await checkLatestVersion(version)
// Extract the template package into the project directory.
await pacote.extract(
`@semaphore-protocol/cli-template-${template}@${version}`,
`${currentDirectory}/${projectDirectory}`
)
// Decompress the template files after extraction.
await decompress(`${currentDirectory}/${projectDirectory}/files.tgz`, `${currentDirectory}/${projectDirectory}`)
// Clean up the compressed file after extraction.
unlinkSync(`${currentDirectory}/${projectDirectory}/files.tgz`)
// Copy the example environment file to the actual environment file.
copyFileSync(
`${currentDirectory}/${projectDirectory}/.env.example`,
`${currentDirectory}/${projectDirectory}/.env`
@@ -99,6 +107,7 @@ program
console.info(` ${chalk.cyan("cd")} ${projectDirectory}`)
console.info(` ${chalk.cyan("yarn install")}\n`)
// Read the package.json to list available npm scripts.
const { scripts } = JSON.parse(readFileSync(`${currentDirectory}/${projectDirectory}/package.json`, "utf8"))
if (scripts) {

View File

@@ -1,5 +1,9 @@
import inquirer from "inquirer"
/**
* Prompts the user to input the name of their project. Provides a default name of "my-app".
* @returns A promise that resolves to the user's input for the project name.
*/
export async function getProjectName() {
const { projectName } = await inquirer.prompt({
name: "projectName",
@@ -10,6 +14,12 @@ export async function getProjectName() {
return projectName
}
/**
* Prompts the user to select a template from a list of supported templates. Each template is presented
* with its value and name for better clarity.
* @param supportedTemplates An array of objects, each containing a 'value' and 'name' property for the template.
* @returns A promise that resolves to the selected template's value.
*/
export async function getSupportedTemplate(supportedTemplates: { value: string; name: string }[]) {
const { selectedTemplate } = await inquirer.prompt({
name: "selectedTemplate",
@@ -24,6 +34,11 @@ export async function getSupportedTemplate(supportedTemplates: { value: string;
return selectedTemplate
}
/**
* Prompts the user to select a network from a list of supported networks.
* @param supportedNetworks An array of strings representing the supported networks.
* @returns A promise that resolves to the selected network.
*/
export async function getSupportedNetwork(supportedNetworks: string[]) {
const { selectedNetwork } = await inquirer.prompt({
name: "selectedNetwork",
@@ -35,6 +50,11 @@ export async function getSupportedNetwork(supportedNetworks: string[]) {
return selectedNetwork
}
/**
* Prompts the user to select a group ID from a list of existing group IDs.
* @param groupIds An array of strings representing the group IDs.
* @returns A promise that resolves to the selected group ID.
*/
export async function getGroupId(groupIds: string[]) {
const { selectedGroupId } = await inquirer.prompt({
name: "selectedGroupId",

View File

@@ -1,5 +1,10 @@
import ora, { Ora } from "ora"
/**
* A utility class for managing a CLI spinner. This class encapsulates the functionality of the `ora` spinner,
* providing methods to start and stop the spinner. It is used to give visual feedback to the user during operations
* that have a noticeable delay, such as network requests.
*/
export default class Spinner {
private ora: Ora

View File

@@ -95,13 +95,13 @@ yarn test:report-gas
Deploy the `Semaphore.sol` contract without any parameter:
```bash
yarn deploy:semaphore
yarn deploy
```
or deploy it by providing the addresses of the contracts/libraries on which it depends:
```bash
yarn deploy:semaphore --semaphoreVerifier <address>
yarn deploy --semaphoreVerifier <address>
```
> **Note**
@@ -110,11 +110,11 @@ yarn deploy:semaphore --semaphoreVerifier <address>
If you want to deploy your contract in a specific network you can set up the `DEFAULT_NETWORK` variable in your `.env` file with the name of one of our supported networks (hardhat, localhost, sepolia, arbitrum). Or you can specify it as an option:
```bash
yarn deploy:semaphore --network sepolia
yarn deploy:semaphore --network mumbai
yarn deploy:semaphore --network optimism-sepolia
yarn deploy:semaphore --network arbitrum-sepolia
yarn deploy:semaphore --network arbitrum
yarn deploy --network sepolia
yarn deploy --network mumbai
yarn deploy --network optimism-sepolia
yarn deploy --network arbitrum-sepolia
yarn deploy --network arbitrum
```
If you want to deploy contracts on Sepolia or Arbitrum, remember to provide a valid private key and an Infura API in your `.env` file.

View File

@@ -19,6 +19,7 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
mapping(uint256 => Group) public groups;
/// @dev Counter to assign an incremental id to the groups.
/// This counter is used to keep track of the number of groups created.
uint256 public groupCounter;
/// @dev Initializes the Semaphore verifier used to verify the user's ZK proofs.

View File

@@ -5,4 +5,4 @@ pragma solidity 0.8.23;
uint8 constant MIN_DEPTH = 1;
/// @dev Maximum supported tree depth.
uint8 constant MAX_DEPTH = 12;
uint8 constant MAX_DEPTH = 32;

View File

@@ -2,7 +2,7 @@
pragma solidity 0.8.23;
import {ISemaphoreGroups} from "../interfaces/ISemaphoreGroups.sol";
import {InternalLeanIMT, LeanIMTData} from "@zk-kit/imt.sol/internal/InternalLeanIMT.sol";
import {InternalLeanIMT, LeanIMTData} from "@zk-kit/lean-imt.sol/InternalLeanIMT.sol";
/// @title Semaphore groups contract.
/// @dev This contract allows you to create groups, add, remove and update members.

View File

@@ -23,204 +23,521 @@ contract SemaphoreVerifier {
uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
// TODO: Add more variables when Semaphore supports tree depth > 12.
// Right now Semaphore supports tree depth 1-12. It will support up to 32.
// Verification Key points.
// These values are taken from the verification key json file generated with snarkjs.
// It allows to use the same verifier to verify proofs for all the tree depths supported by Semaphore.
uint256[14][MAX_DEPTH] VK_POINTS = [
[
563562783592406106461234396505774794044312891062077216951605541624542949349,
16293410697967515504861065986355060225819302510590370360517024529684437085892,
718666295291146285397081607986058864287612968465033527894198098928522749430,
10971164449179097832515056670594147898894418081309026322805549037082528587660,
16397970494781113622140409380710514277504568512202481522431528914560031562762,
15987991045804318696151558137607070651882190737142560406194591976742796145195,
19175554796060272870947844726785784415291967441071791144616572094703752022787,
14708716857471570462880683190724447733812118518043273649838616424043548023127,
5109703116431086866657790821388182053265093586387384935734011036204399393630,
1612476077210311180626421664389270104678910550524363357381847966959374674423,
16028984344157742576452936855797086856968817024956118691418341585143424903639,
6905323418829609143361434077039383502192920586565275784934386988372483556465,
5037234187699234788733084505200789125332575456459095878140727750253994537245,
5152780378461098676484401284161685966625077837157208907964141131514955942959
6798275159111696631765684932966934480819839778360905827982023140392612472251,
10049769308514589345710525790497478045162192181874654650612439582831356277192,
13909893679970909921284721325099295595079958875696358686115736114533495869795,
9632931161306518428495887250948808623666181422608519935229236995717535313753,
11373228439083951786763438874368468668602473169346848394664028118071804690004,
2392728274936215006016716287711141290248196217507457308817981648956555973842,
21165236263460891597139480651611604342552675916374159149811150532317922022637,
2205889866435138776852640052657720558691248366998420655585799331913362910317,
5142950424486523257531761394520431861723450305642839631787321698382624066484,
15189409525440736600177098582380596261100810741418368942552492853472187151232,
15166768161845773257369241904008805578918273462394677953758522994830670545180,
11585842449811129847758954303386730558495513604993443241740010514431580852767,
18309269743519286170259635930367379586611051469932392196263349325096833776404,
5169422438906150387687192335052847822734742081564185146089879581734761329500
],
[
6925326031648378844726759441690273332175949886518827719224741736678266471462,
8087990171976409378525016197066789089596692733769545253942804888352233244331,
10115242383701466910539784663900956956505212347433548599529944880163612117847,
15618724583521291135890928658458637081479213437530496494788106479523123480134,
19573269191775350978579562905764743103417752180580176229566975904395505694207,
2381522187377974692257359562587606852360557473353020907100590706767276986457,
3570865353993345507636525265023758855364727230473021611280650482974485897542,
3026650225811133060402545160946181194870257210933662802529138266788423022235,
10948020004642082805202152014062303498984706484599503419636897666877701726029,
16425328653566008388486740080892552688012772956429074139489785673820307770702,
20638502839000044414864636985783149953889799151008745227055624454042471377832,
977321369609271151576827768083353705509746900519279122286818202637470656742,
18662986393280647182646025762677321210586855801774577114215804961111542726195,
9182414327249389553719378979750943052880001176853490206379257023646169811116
9002589149121965406377790703690701514742110610103894317373190676851261250182,
19341779283870938325962302230892649885502492339014465701160403382913313018716,
15384387008815567134216543585911373077215244920196736604974944142355824894376,
15853924395610285571497184614672056220255220256147800551140212909213761909913,
9858819933413872566321287453112479619079314892623028633956302548255682218967,
8978980794620905465584214544974627507731009260328687273037813961789203643024,
10076358326823042048333094257819800797834453359160913022846795563251044706095,
19803968301016597767781555029004899114416563609613744105056144083718519453457,
5163620256392555974431339018883081297271688900512864797552560460039668157036,
14255936460639291949681319740874191007595598327244735898045668418052144766452,
14537605621065916653836904827349546258169731169287489407049733321313440129043,
13697104552179432948127977631695913762483329167428550338828664939969524379194,
10518837188707767707511411972157042015637825295037224566646839468274503919246,
20859740531774787409224706405964614133972994888613078458739440328759279998775
],
[
7699900854308622607636895140107457213471038801393300399043779958706267744510,
7699563868952902688273782470023919811229667532027732585467624469008534197561,
8605006500231713390564760089884965869867818332514275728271802101761117177706,
15390497513810955087868026868634948499789494261604405008298272598684585331879,
1172653041469601107707030355715854571110526375194334139771259673595104816259,
139822645729727942447876327389754883087551266970976361358585992124005959663,
807568760006422352594797418374693945705914727214443753238278163089338607471,
19362805143026565781098954744725161233661862485826387437200176803022106919133,
9457043262004277983171082100772969689099515860060732671699192102623198243288,
19229090298682361289811638032020124933114889462217199961448135904896325661193,
18883326163102164343877677909116984239805709949130729675634413304023108763212,
2795333364660917174391473381893559091159208514832297547909172862364581446206,
18012979848063967305324818138773222084850070233834350625943804711450349870116,
11425098272720529401115253745902976848228234025625773037823969253767737500443
4892475367240699533498124978912576905968020673574559095879617409161257740280,
20083606144842666939684160820556467581044745205228415333288523629251382490832,
19196917991372254097659601920372094664470329157515388592183392963173987434415,
8880701712891502068342106183752508169009511975869428067925759962432179990770,
8295798606560676055262757451569098075661634806877203374010954805416034560369,
17823033916327857017646050340986899797748134226556967395794361949180557598708,
7863282428525672743372793899382505053760053469668593484933349016990801573594,
18331488006684435728676028523354067877257617459721620528326034910754871664656,
3208791308718324440134969236351379590643354353649811828887575168234009128404,
10257765481441384707633559757593912517257134336953024015057545492286789467798,
211202131360446365222702196868578991195656024430005775334667458570635430182,
20847900408506094777967626429608261593000174750467914924458433091857566381170,
12874163201492094577931796006056258188942453406826318262453514614280169978298,
6030254908603478785612749007917517401778254879153565233016575793713168729906
],
[
9243647856126339588200227750973237380809101852206502177952556679680468734813,
2561989864654045354260435368824127763249975523256535586391379695256700207392,
1308059969166897152269078839315249187046718124106168932020710683189419160756,
18264861452415533737686303596832882667852638121244187636443702248458018416929,
5735580005765404165535708760854311053102182143614810924129912232734875728422,
12547270286864340931439010083179993915942911007015778927394042746771813715897,
17861179987982979247789643870162154315308943006677455616368767345181299723498,
12520843301982976970226379882714814545061255956743392202788539428471921045815,
709419095293140562723620898844593712074413125125086760533949250121053456086,
20254885558410038279405227446341995510955697359900050994091569463713580982280,
8876829807505794597615690202974184696287415186921508358861381955321520402876,
9692396410060123455009190221005078571838194435772371581970098240972280778466,
11541729643712807778212647011796800767186857085220105751644556558522744760878,
7117533920695574619512162711113223946930183977424569115798612426749467545080
14709385606134004409926090352432771201334818755294681438762198567603122984956,
15595111262392352699569329550863719272136417639201948573321210451845475261310,
14227147558489134328158035447732190048870965571562543433839005727350235629494,
6894292519900463438264764292659242116361936210107228897203114956615108320465,
5698226291009392212509456603087660757167892215070748391710298686451794945150,
6157973895099184288402315817801807399850034827661856468278605062696847353498,
15141526076642728649535042926649597908183234939224775055067110611584500129001,
4384760212321739848884344304193577499977798066111221580475869690599633722806,
4172483707996304656828832165635673373391709578552982633845732115764569616109,
18703118242791177268087540217341214701751955061868356627779317654228486952499,
19450300041750343627209216069867232901980973906626832440586455706765725761024,
16059746288175455494980620176090534670137960271693908437020084988051972211964,
20545976615820429183066000767405817531114365884543728191728740956241774393365,
441682222632036954103668474012025602234972690129065917741930205184363335774
],
[
12554869896570109663558999106053541183136083706372178136870048170147558661370,
21307904757295729894500052152251151076177124351059746872940558537429181679313,
13447792161027167738515744919555311619301071111923271126707713963292614473975,
11194665041440536766843756304212299788817698936187605770131686430625103172681,
7022760843802757109079393624924627417630030139055381384837279305453559861026,
14368180091281110030022253036601349874026580767275461373222397498585380849175,
20362090815079102760789516334841889611927869342884580401494938701237909313479,
11683916255585393494577805363227207275174890005674166623110857790951330330248,
21680925564107543632769644144771629045807478787600735681275069556336841549441,
1554686039880869088226596836931999292372497423378849142389700108361111176287,
9553151402225656007352139561853210183786116738154807824913092141416366824324,
21774504332021003611111291017295441063483107704370481606906960187337904118400,
3472743162059388238264946309663113383560193397376658519781344886918012396958,
21850707327192737842691835772722844106916466129654852946865863108319178245521
5475541246268319974306511838266954642349839591742677843373092350878881816036,
14320850367979727803456370253215537369678224171279198206044992705279862306132,
14026863062721131266417143383735927929515468275568001741023143022462108466668,
9695519010485916829174245942670015592311240112874015080337013283624414875322,
5694780594861626040122686431862072023944220266576706715410778734338641503716,
8712472904136893949123536631603982882802768648960668490262215595304129180625,
1995786476093573828491499692373505173525336583145392096683467783999902548268,
4926925836258627177637371690839427994092983220113811290959738100072290144384,
3791559722445528845247206264702403543222196830021730221796818130566106209767,
18417761581887733852915376127193234657558128442956795523445623750943914605716,
6559711611059474660788123194641390228396298237139470196512451543415077405796,
10546964127996233691569839986330212916129646278460480030759233831657936468012,
19639002331873293572459373894235941550278985499149213248754356208213460657162,
16617740711303077578250556582154106231075844388484693766277639059298286987625
],
[
6841243505372324564043525805425666596605335849634400049689614462868641599622,
11706947284665470438085734275890584651957983546291282232304205898476084974953,
8134420958061302592465696766566203845441024351721660066575866529624350946525,
2674642993002069213220912300725195098434544703961492590713058622848310061455,
14007544454490183581525584522132854274412440955138184221862170710084681738226,
9427297140302346741340407818949601657384670126565058224960470754064287232598,
9424279417196769259939653963004219272435595656090601392111859177294419276463,
5159704841441138198509282351301933053602549958584575945916187562678590534936,
5934282708091541939003757621608766449985810436411564642900129758520734711260,
6572936900512215029112509161886160866328777917297795430264727434969553346474,
17332317297867087005634642159909283377570778576256008720318658354552654813365,
20469716791176463599463762213563135543375669917658488173798369718370224346075,
11895216520141526042182770992519307655836464153974170586288146149131884093776,
2345310584279491449819095573562431881564998414485162753036518957549727207513
10286912080628596477467183526391676938111746098793720613051271594210995874277,
12402838088924052923512617712407943454558325804407246215860795418264423785092,
8969827906164370148568535190125332589838680819876134752608330672491611718778,
18192144771812728760821091791509406004413270888917521896519497516182602851052,
10137887164821194167739010222610234245229180897989876335252633099720202939025,
13556557929447859629157159796541922173969485671491640178139584889369979056605,
18001826336416230108554083436980932740049468855770464827475781769090259294957,
10997751199060512644156045915284269336171252742084691214654620601348632057908,
79913969765597476108932900497715672182891152853885723893501837676479334643,
5339064100797178384601587097901074769415731437415874905101259438574150065725,
11790468783349396195257730524002236946005794800506042451697489501177528985869,
2058745275642252757008568790584694831559296102476273845301514491747777902,
8569838436054970055409792695113682207394942064434307728493565465575383738014,
13183322615830117090366962414504200812495447396240587506161350006490578304105
],
[
16222168105567777760688113388791710300819703656136395550799888633073848798053,
14347453588631116202352669855016330076170847581618919999243717038742915487177,
1551977748690015855031859376084014992267998166583511614295554470740621685494,
5558376366205739247464101507558623934779699722049069497418188353860561540238,
15084362489402846752495176069529022447007294106313236924068931072406922960482,
17446301099629553693162731281967866078816607293341610477850995414321505446665,
15416633712259927998995598381829216728913683600537032862643171407716059372732,
6910124994917236999728700744617337824847623550680442113266553962793201270115,
3240338086312503075747637551773566329150860621223080774242357236897458479365,
9706162939164863315053907226494918827393300584078535638283184502242772542378,
3821371825593696440611637099905775310839636477646533943959149234595561019388,
12220054708690507765048929995921680127285008492320123722886943219569231705313,
16484014909498227505527128570845947338361237083477117662394990633734193572570,
15639273550026538537711009501005182488432976272250651065072907504931158455474
21294477411884184721419887719040509211791603543588769195913632677965664561521,
11068844518467094308182673400072406174415035287465774858372276008144890272347,
3145975317148809397211222308484405528017506805621720865271122352919092734185,
4898298183000166428070984533097167988044449442228324686951622815588789280020,
3610567344582501189941093515503625764015617358100951789070992465620388014770,
10092557495034796324189431780067983533486688638792444215776822879681822814418,
1266136239205073111432095590744834423814511894190159459963868637184138842722,
11374864676654295041142699893206238903356920702572230940823052344171478284171,
7496182320409371534981231046400216671163346135425875811178408606577271153492,
1462528704706444827904493040179558039394825924259061934534583958249261959624,
16141406653410498360525438265360373701532563198050057601030953589813051750690,
14018180053857919258735952789533727227462568550710713906158448711665296451356,
511374127838749625770334668647416912569313578777284750605965725458096929607,
17635169227434142694714979150654436187903738366738972509867831826867283825221
],
[
8039261311473792027408130340265108867783988336829815266149766357424909552805,
13742810756711208866393269789950822956196651488331544225304557369739035583007,
5732605965679620193714116075516176231919315490749768120227762344555213912038,
1426283383724925735279168010737048062664480092231550167387716017170422478271,
7289543915982634578897897440956973302403422297539950338836810160596047457980,
15177295033774438197517772642364420015492974487860823338193520175227862903717,
5412509155867259433944542755241941469706034032614068890113478300647952353475,
16755045912589178729548422106539306191579601567866216267685082373250783779841,
844425885324371282218176954530597075058496766373014736097970493596574863875,
12323478340077628423886836431146436403221716179764806398442271274194718652143,
19468406721151512215981453048984639951787280312568894384216547824763527840472,
6512636337641737270183934024333064400224464644359645491020358650071524340464,
8198878215192784492258585011520207242810327647198332623948351347768018051267,
8014960150646978739731831763393714179490854831922196242908407049327430863238
17019299296527992906342471627956454165356014861255173051509531752951474839628,
18275029135856620478842184125347270385705018956856636472544734692104668441197,
18712955702371136698460276131619504667967074451844136203135440318125770689683,
4726292743397434547486156972449202870187918808626632743805765024906772393932,
10971489037448711908698715978943908500318707562175731815741960924655210840831,
6006427343343794957952233726619963086279381477900155964075102505701412817059,
15106747726469907788692287944434907296109850836405367650663267344226048690859,
20492702082677255463093066854699770210633096845859381878102473765397334244292,
20017671604137050517701389289600332952924272776091967565221423262198791114477,
19092277823744726322414075820335182617528620489612060910384627313255069537857,
521420364975417235554366424369539937652264103736140177007376087084617840969,
3996914661098703435279657116324643068485300222550651293916442007463647760470,
4679024209278631191232555253447082923762821738851347894762954616029136450469,
8497347026541846312098745702841179850966624542794907236048342704145659678775
],
[
12816421563768297608770270654146762017343826741755988834647936785087288245221,
4869230832458710492613139050501069397194236257402947715710705773326736170245,
18301439700961740613282752163964601039402055729651579152511810295028351855917,
11073344652802336528382437239976464979745376329678013840706100925574578891663,
9107882721143487446664847981273782313316003453386555221878701631432129058401,
9441695541513726822451572070540177043748046411169636568582927338148104680158,
8987068930426301924419900826390508311526176863992306858982473479912439758010,
1725109031239210601724581840155988791039497876559382612372874257775877974323,
18516110346729610211387987894593386281257834088357741109524145966500785499183,
114078214476076549461901405178268623018026929846201249476869510133510589766,
15915940069177053049090451855582611051242699463952201407239272373068542013292,
9373936080407194259749015269175580128112032582312467763484971165406599176646,
4922802633190996456945600288106639549790810185209505074744770090776471062338,
8883001810279320778962047313612748029483858862205749774979015238684570049088
7070022814268269475674001477040669982274081663112043242616687573179272469763,
4203949560354147821783061259439508268015232617968894950825877033100175693770,
15428836885992191488864297196572470385256339610669991675966605773279258629810,
12940391355331109441147053871885221765801476632578768077585085250842908979972,
6504013699913689711099075581237522738280971836923813934562267069952131008789,
9335304366750096675257996749136859439347731736177301019673263812644758419624,
18674691980838913091347677991332234920479452203295602521958600357998616141596,
4741568400157063102689633599777211724821079787176561142252991434247861983373,
6081240166901015395566231760209678592881994305266889564610929100038948121840,
6726099338457783260423971895907643672217936148382337363967495541886267184664,
1518231630037540558074208692256894068220282655237665440528391362801123567400,
6814959623000862963349418000763326032812413890585599160227546882616685479781,
17691964860627566514162469663546469998385191762053312278765810284413361692706,
8886638770454932775046812264172460584356331780532116653693013498914944507850
],
[
10621957863293158040009666146187340406300006617270113507997717497098731431645,
11544253490899949675932185200523769178642714850738952025947643180461452257027,
19367886286197174023585178612664391272570357530876044259219178006444442279835,
49583159539136224825737189586941489049516773623689603831917260806184061698,
14718035764669896417897962215694711502145567157050183561348015124983050763912,
16468329864686708461615593125586840110548434159129257976547738477143616225069,
19316680422470456517825967239402234468963225932355881906076897312088976727808,
3793008941035953637072065313624049788550692955904011087840457148221740889857,
8994123619474927749524041243795236789619386871069943230512200348341409025802,
2898455184193535874162795400065700362364113037155462125222703939894764399559,
7006987736985681119096469806956612323700302986805047546691419062106874738669,
6578526693577992862738197741211972861837397562647850241473856881198749597774,
18253609658317686864081972526657430282945609846265497350129963610508303097865,
20602454323920106770928127673050173555696255204782817307960073152139829286712
9215863273591023879373751614289228209440638027086548351177699133093136218918,
15029143251469020678417745262015955011761489030158757959406941301509954637253,
17639902090432855761607212999107125862255080434477939330403550134367931862250,
17630923485910370531147811073172401806424795286222769017995022586794787691894,
6051337981942268387146348592741777699916830790184591013400952407193740242722,
14813309083853385461981331205467429689964041093530055551198131882311452944165,
13243916879266487104491184915617833718034439141755271499342847081003561471291,
20559308417239116672012110806712907520758637467837138402161111223933628840592,
19581439469161095403630005805154174170687505024117879919441181595776240034092,
17149923765379212333833055145767060687040557826663126725983709990821216291941,
8848229792169763857187638630433883807573443546037902935946980878173551942434,
9076584903972238461379608530218901607367189390010139393438137978954314962294,
2838594782505936821949168913265923356032509180068328675364337511551145041706,
12082207822506113008552336146445599677710895859529470992436917935385155760011
],
[
6919690594446594824660388293695365136302375315018989420609208580270256193473,
20152340858374022568747410447956756883573367358669429548835673215400335225747,
11674218038035204128186342498577020603218612593894174060137243207689886423596,
16509772385894559653132866836382733797078280267167499296517180188027714772070,
18387700354891683161007139598833533459740755646851082725263944626765753998128,
8496770255291121655312305725645117658510206297162207504909146686627154245846,
3295351580633631545204707236418977224205703294426182202748223245617942752953,
11318533876720817956139762907441156918032396007060817178042936071438547629319,
9798692489110933308397734193670030418121117030189402149994776248649813971130,
7253879530870754821836349446054636336833607432103959373798000294248292966203,
21808645514001764351825515375665639285586999794992628373968527911077248645185,
2859748802987042398453158245958377568437550705999358391809538153774651114865,
4373537692781319117201803895634857716202697229097770645380222493663057011429,
21723556418902236605356947828522543021755681613733490227407492902239152334538
11286999809932675831231635172884104916598198610643895494221292893580015272745,
13783008611244158112820345862046566925592820181422685465611038024392658912218,
7399859568003719929092067255297667044787076639314018778324389410794797203822,
18220331907668058189189266984811818382536030325980319490052254711990106619408,
7221075042299165070640763584725863160347647659704278782330562384672809305162,
13601198331885563117630840819920283945716376381432043240564878006092148603574,
17966363662480886855360210401838893312981368660270687414500495451106355682632,
9255647376958236127578779968319205385670535134228597865566167852255941456992,
8203959912436866237932353632392355578980349384400645301966843912631449233592,
20011411139499301504584228175724552542130947288854633651397978547089429982167,
1820524505387064465309460998360793499775868154592043137422833944836520606454,
1959603910351136409471920269505238383870634384371099582856753558856496902512,
4198694051360120490653446337443734423586650228488283685090646499268901675490,
21526524841382152147992421724785801038770676270240714297859552516739773492697
],
[
3246325158773052647788911340476235648870186305670446321333841273770228016262,
21672319732433045166991956534762990382763080837755725716637027617201056105221,
1097625536358560225015844871776096852794298581720514105921271391131873344240,
5332470123606111842725808071294486759248878958039162159296029608796276205941,
4147129560663007063799754603731275683761368247704376766576071776957227165800,
7032402220603422034618210155106646820962552774510253688945919060625670415308,
5241022678363371404039324538224070321660623527603509392150146296843642044363,
5281273397025328620822441453790518717375265972202147684745427714882287252791,
8109626675067152219533782552336308649905522111608563670382254454484448073029,
4696661232179595878220108186097206302552300846640109174608389689072223809776,
13974026846148052806722306435446895222317781098029808723550029071117080027133,
14451415757463182353662034231421738047130904367363697865823311429455557043904,
9490728148230530026163178051838213576627639298618884515939110001242292217290,
227687333556127166330064214209948378192130717415165040791158610964406937909
16377454805970471136556451041642561492050129029468552950239023629414014853926,
17038353963915800405951415178090940216214909064699790293151814567548494237780,
3632028168433409518690370660019979191925992823806956511592031439491580827093,
15490021089663831333876456182365939475639854244939093159179164741657017023319,
11332498437023113295175458390938230450212523402749978995184951126111215368275,
7016084735586326731105326496042171157633237979413962565940384222454876829020,
5013383022618445727921740844767853050438275291216971327851792785650669011741,
528618354489883480125467549183593651465882051681270315858578353218107644734,
6932115924239435517832880685428272633342271017032662880345701095160428372300,
5520601709801507363146277496110244143378961419982733100311341395981490633588,
434079293392651414251114604226309649137438107252197032381696615267775897288,
18623332313653972273799518879682220458729835518812577091590130632605360081933,
16981203870828204556408891045732712151034600645789784935821356391746701607849,
10839961472824284602079430847341654099878245597092020402049973455392611362164
],
[
19318612173039398554610402032189036230760569630971013176034600348734573687128,
10869362019203773549991994466432246818750552482449272815024995819170579818159,
17376037803297137953593713472693431735691900221654570494069764772063916969267,
3245151284162480382840661459866398914990218375518126822356780454697379196592,
10532694937633872732615221785339191399998813277853598590284977223084586265406,
18569891906743239236657790847950300608514739578359676359176841830736581922673,
5204330292569275288250153279775499240677764904182920564782936399035494759139,
14869136923170104943599081137392440247136712268832152014557322866069417673392,
16609139756845639786750046885223171804867949172280450359139781662901766868597,
7367747621397764356413880321758620580129087430671669202576071458908338963767,
18157171842959734937470210968648189999811759058976098804831380331978049484161,
14612065821098816890897211924691530301447930045836897440401478111363414764157,
3678851330338811698871212394774190592148694554830208940152772420325429207592,
1261073646471879421850354957670569129175034189935008550219832398890385831603
],
[
13337456010890669571312110722110978626654402271645533931088450675631972389174,
21739762430966591611544841693197130387727042679304816904320680605415377362025,
21111955068677333960505079108312560231811849538594697119908234179626105686302,
9392230200497743555544102618287208999941692619434060081126831244370851959140,
18128060449612109642142496525936963279825759724692188014181733764391545826501,
6412545369924963430376339636555328095118045874871394681127600419621347748574,
9178419128141821432265215706509797566711681420667049266964463482093364121974,
12757958736224258162889762688354106158996770313065275427510212926355720788806,
21697843782274732041256438596018216848529426578597975296740068185709056950695,
9641329027897013830146943496858364657344657408442613002988204006109548012670,
10157462635214395067310714425532743819094195406756516970796212542533337329791,
6756552332702121619038049584093175387814338143922613739401669728656840170909,
9276003791014657516094759987195269349958840151064358512535335441437526577719,
17177335596130235736675313878734353760926293469390853206840228086544227127243
],
[
10611805799193697089972647133835358446175696630019306104758388585312795475026,
9765887841111014027207536734081294072212942995633675647422724718381533100171,
19734635784073407875945934329600179316595807453795254623432046479616133177247,
12111202900875841332274674234864138665123655274511234144349518743965832241535,
4691701433964504850819405353426875432448611177084640879664399563684106977201,
6997026109056305304958456212770850719737661180940807196442278723629505898836,
21862540916562048400075167198394269266629631981308358022452061330955535980535,
20203136947717696850833432049217389834551585785220431602620838951128875924332,
6166688558584392552732686802822787347815166465668907688252438119180905848686,
1515830657197384709067854833370847128665474205967014377229527531272518040510,
9783110166666159719262248155776421656845594701278593694743917659000214566949,
14498343612651837182986000137068086166435021811504906980633109697812438152688,
7451534988011232583608528483663880320228268776552285912767998924492654022315,
14389118774297616531519885127100101489071211382178872997387065906551438715617
],
[
21819764752388384320943920865020023504588699757854723759009625630599418384159,
9338876125692749169921649753345966897920335121369780024613311788669200836231,
16193105938174292468402166430441544247332830012383311834096877330373326202912,
18733835313573560168713238640348200008758608939774980957241614757051426557329,
17586200399272141670685001491641162521294196727236050999778548238215046166017,
281329337697491075931159352771449215426528517554332825727307529327678211850,
13587768455979634277266588196077051473493752291227370910424884771755142551393,
12132714832736811067697324782216133875324337588127071061942622831539088199516,
5424242637034241045316293106740200282134858230716641545833281265555664814058,
4099977807866045222441365441679488428090978308192769063472099506097446172444,
20991094374514370732056452708323057419772785522538068181419368097559064487764,
17494034245166301533444525935585362973100718889755879021217726039762737332309,
21513377844056886482755561165035200163740875639723610667981589251852648290497,
9065101624205101464784359744884631484276281653365096468139033730232168384170
],
[
9675068040487058613030479303481110062861018853323992035192122053375288989240,
3919601513420678474289276072949118564098120747866534224625771548831677958372,
14608360470284772612816373122857162753416790881336559383898199290740342112532,
14825744772260021909192492207967364627484904101011554011523154032558083852565,
20984349344022619370458450579312578055808523135369866643465670885076660164806,
418264638272070574199167297855020670696708537402223370097894154915338824856,
21427513166561351336822904548010728579322568176247623689193394481261310743729,
17218242846472515735641714187716984107651753683015981795233490838798663005098,
21103921212558832170255972733170723908475938955264614598038505509464559335152,
10402439116707708662126524824676626448483957064152280120730850351913612702748,
17902409153345924357919108278878752639341210912451068626743802458423268435162,
17156991212231172773517848502387153524430619870630373199856683436943875771004,
10646416238055467241386416360395574804199761155307993872061057698215892822922,
9567771666871218298332873263950533751702773388778384953522740303362056866931
],
[
12968340607736823528148475270009593191211106142050392359906510451365260428580,
2721486373801018323157167210616746825623246218390071226081564411423434451187,
9200592412239337272867558509657794777460340114124665277681133167901890516146,
21479491441666028821536714814783435198368229014209693309182760114418462843253,
271501919920560807144690888833558109667061334163559001274202634455325808979,
14794481401072540343622539363544947515055760970979041148841701973173121160867,
16241413887148836912852878034655069636111245133456457252704664072852738020971,
4616891037946851677520624578755099324972320662835976914889099357030429177473,
3608927726708508538381205233592212299638621918906539441231152707366248326730,
20453218571243012416227036764366636460616051978680116597236464784651135817662,
21663166035926867176571290287267617498655213253914511123571589436615865760399,
6820544505512911561421102139415733480016159315919965296282806777526762552747,
1241495087165602740391581058509323079765010896996258108944819093246488858318,
8124857698166498408579282540958166224847900470279217858870563626568969324640
],
[
7468504662830152377628803783383953933430030795298938442558418401235422516300,
4793686881935694857536946556150865385816389634693618604434563516314064685468,
1544206620168318762839348132398850094597148992890365849594573375964142863145,
5369558539480434036232750403701436967132622763576337857204435045501308015944,
12006824962639473646619675695320713559632292589665720351249509600690404062910,
13276706600670868735848192943347104623934461144298261448190397129714774342173,
18264760419082021650494509547780257751527429714087988777838583561869870161497,
16206621246021864196868319303736926716510401444517967423381020552156354105325,
1711726122386296242553570383485323505029934793448519517467561601648909492476,
424608816752490157168394436055547341686841853472229245627510525503910492101,
15415617655332841541287596609058338190575210759281068404604554729079985521497,
18478290351885872204755929772605378173281926792205081562405194750294909414375,
1332104917854036528393448566746555920300729960761914526841432630705030394652,
4875500610885916981959937005615629475085341806101091219174051361012752723259
],
[
11778504031072617076835666396737479480765353231040635692430530998929741888857,
21484720459303605302798978604237614472976046584193439253348361650969825748292,
8499136457565785031004321689745329944377719203840897611578892135704152228750,
2793941551558768339218839007321603095797268500190811372910811097625523777732,
1105636691459466684354861615642532458695547504319491829198944901848354002466,
12426506081436950451531584361567271522327297423292681691257507245865800741808,
21744454903360799020170340278186587365704908765309976031542813238813825084489,
11372248299010487313898881702904101518095247949018830132141430386679279269802,
21355163712164844869530150285034119671090568151924216195709912115114996041497,
5914269246724008463378274526282819036767424774567321843447592335886063108576,
11757178117438262829005662514573037965023628709384135799022098340275235227691,
12324099857879926506512664547633107100872133202763933183968148074461422444945,
19030167447913285073203707487614824348154933215474799593455300093917690498309,
10756138991756861027792433599825283466492898786698456971350016301834120358130
],
[
11875738647114616324350947684061726919561909502972863503130998242120718452173,
13694249165008464179020280306785446096967664405044044843321440965214796746818,
19812433478661078453961877947302599509407379278239949313742808880496429684167,
8478769662157599345424310347901565107922506021173025438525323643981274129672,
5818698629865247565077962768609742022241069606093835632689725123770908238374,
10032230959981143208283946841992758493223859540652919348005062379046462012203,
11522228664628777947230879504212386210128576797203829606594158165912469543023,
13272285677937114294437486001063514791939240537126238704993220742500063989359,
8471655692275117723910962427858752915984310638982095612617085072826817856111,
4389133967757502017802977428616053155133503096651056259096018766643340643444,
14833683426056097377459837308704611274315245609945506612281500340707955071545,
21735047966739217600224642583481593664121921255631091231639049365846545339271,
7278464060898751306868720821317869528105334779561787036194323452374165351865,
6039871164511288641970658426390882746101314533737081850970345002118723705339
],
[
19806735015669785931995353978269817545182909058206355431360188275802638341659,
5812040741672176204747103844640668295298927415072914668459838256763201016256,
11525530340338830716502860942689345100262306689117330289237484894552808300709,
17521885357464563233202648521875905290166433650141773052058705408597538338911,
3562081668776383619644089086241623016377051210290983257053604147762967187048,
4553365292908760204444921066083280974740968313355524357160308575327815731986,
9612674806513362915023578944934656419542782185316845654919222232866782079973,
2856039308549766546769489569358317466998141815061340660074603482372423614916,
17144423089194150938664044057037571466137059216126551322826296560818480520188,
7777587218396926909905079292812226413674978129026320051535300425275288555883,
13348600530906896077492067999286804922009589548263122827764204432718850414877,
3504452333162729816257605356258771813994176063517472700088677353335099652978,
9271993074172346116417190887626439840621996383820554885726881799780298924983,
19415901227000992567609415633317148788461729474913900357094507534384428975572
],
[
19436706355139059383094509938806698706706766923839248625914995027794208831821,
10792411997925964958381215817029067479896035855504468308483392531229534219232,
8072583953344188119277829536748521153437596767795457833432747233169365522749,
935862788360489051830486282214078237146011038653740178111222389815697167391,
7693170882539863875701602528545342311434468852163389086171388853464572270633,
3908303967241020812745991584454294385640133430208468916543029049706292930305,
14200361022064175872846252914915938901018673724842857113422899538373627654493,
1887985090111673428008310095306101841985601166058324952496388205310462613383,
11573157656525163647952907768764423420183350046483835223957092582860133547451,
9173604865670358445639146193904526160076171763657483567287015999631297551260,
8178722693917751358075016256308930447648179998714325218415150487090497217243,
16479808796736995387921450370830080669813035631409450618705788666753274143975,
20533543720941262967922843401527010251494136604304116450329194230919992456714,
21738708027542248258448002258354036928076950567990414271901435012481250510866
],
[
21007636601223260258896743126015285106374704680873221102534543271676455685798,
13369983427310673379273386726118528512090053533610011895772924489087434499560,
7437655172123655742476741904638757853205242308502126726581419961030710769332,
781816009964815727693649369421765727079762601401895827065766198634750193888,
705729203963801077445366659807159942042515811344776106038944684242779323077,
8198640129213076396347058165827729949570109420499123900233622693161948493955,
17567949859381263201697894705370978555666635560577878390586549308344241574720,
16953629262080155066207979848352607491010984453917718285923448228568338552102,
16571340903058171078202337397668804978258511905425857983395617262853832093164,
8200869898550007995855767338315600003217265793696813934354774140864404387075,
19245130308508431368191001431651810775716975255435369252757393063712397235401,
19295429264588775090334360243373041256684104838925789132682844828445374541241,
8244640034562580123950327146088236084020067479873470678893810764954021793820,
6071779329882466654134795663117452253106971568263743258793999061311754781283
],
[
7297858819137361266048049960276576061221795813016982777983276508233065012908,
18289767809318109953604511379563953654879368440278122006476245297734205780313,
11861017471431365163414128324204576291654501179050818386156071891372931715517,
4400537004106671968009111731711678778861503186165383927771233149107549932374,
12211353780794522017482442205152184029453185156252615419956272689806996867522,
11858951133579915446931127734829983281450719684822534749146423795831786572024,
18699083494838544659449334875917956720534604312394484877250282743052866694,
749778821409550859537528691118971534871459292764959826137658158363222566834,
2909597392070263345393422292436111503720531353687130181723707126400751447693,
12217177777420376281128847110380606163261839348068116179245513037333903388087,
6920254660239140919505113388774145966103232605095540610909080767264160069300,
9696367212878183305057911542364374139977595200010754215085255727487778572962,
14968323162826489282828176469636555044919206060463682988985750923782404039777,
11757071201913114247059598621424329188966752420483410843397919162379753756933
],
[
2149278938146333837762157047865197539626726297462234579786480672038208839960,
2992162472650247075753290379196863994101122291268065125561265479303189972094,
28038421244332437252451488699272760491836813993308427474241344447797755331,
551667036500907650888508201663204030618105224866044580467647054394918324251,
13128279467779141267539556181844646897000953259054467200148815485804849945589,
19182542610668848202527767345596590904881280203255613775118909904478382941801,
12622787765544530515623619382100437898246101834816376149292007743211956407286,
12570391550772615838335361042568121892906867634448929202232001812492234390257,
5735316164124731332271878247418185434228086026647700113833855177940542823181,
9649474108395394754402030685603045386825744478341882098839846461266003368756,
16190069071551003451113144390700917484497316557096684922619605534369669949534,
10681321343942329435795471710031949263678373347092770298132700842902513672840,
13863872929961730606993556753801300020729351590807975827100825368353540990573,
11931534405924761866343686993715271905704590108489876499851774273982957911423
],
[
8817602722261405319698829040610455364903580494786394492896940141358443005801,
11119926988115729035668011565310535780603655775231850120289918739692745155137,
654240854620562345252945066604315306494281026224973615193213783227252715475,
1680290803075724940691569649460494417420550431404206498993917267359934429167,
454088003829163771011170852736324196796734198039551149147118112028488218145,
19539522144446103612355666512646927077463791742130426065863787086655625062176,
9677517649080056520842169551325292586844311652869297540972831144430102239541,
12171721941568335982623293519100425613310698565606469058956892831634461540059,
15037699242073552386046516617138931456404909452736126928849871092088157606104,
2403475304123870051310189713205959145472986292698418380091083485671020127630,
127899593359332180821632671011918317356219506177015610133494845926153175595,
18684733307620435559282273679266280240730732702398400109727422417551972403102,
17130978638728591547347686801647449269492555647218567636544356715497286682290,
14514080855160049012448903996874963632870196574887173768510902774625324658544
],
[
14337554339543299757023541671562153395916531829217482775164867679838962247573,
4417305792230285111357011064673221162480286486496089003939989926259051525871,
18318343953566300700872145919583310314872293221527574189507609074563561808951,
18102181553730085952093068611215465293662342195186852247233989189686218494670,
5855924544364003112712450030145237149424995112678688873039358008205969147611,
15570549396870292677660853760591267003520405786863190676970087082855555878636,
14821240964410715386910463283745689087244285662861027299124772223732179089302,
15446473065604291444037235422131957717379131935322344411928007251149202158658,
586582749011680966506460208877749670972200690716863059163322868400282852300,
6765443750336920009167305874738739551390685770965140484130502003990191861016,
11516588183751421185156362409787679404091107770536300994982153030408504091807,
9422281521245157165519221572217222566067379888854607677340273485846988818889,
11972785834549950434085949313031360662160524117252689786653411157712853588295,
1251548247225430075659521219630231228104532865302157324337575228144557232422
],
[
6800687607590437742793451968857688924532461129043710692695682669594760138183,
1902628209424530126704615228962823322693910527728191597878269502368972448245,
17205169168497932228842841751695431463810324846010162985835301764799251782423,
10034931611814725856775298104026042876081758307779816060207300321750191893265,
6083168185688688297667869638715177381772180226443830560342282797830104869062,
926194281246578915103720926341497520082595828680525575284123365838007044551,
9409122852531801098754556536729028548924539102103420345160677794564194221020,
20542245913396046089533736519215869670909083018889617904362139603473474391693,
16873198639240289433836743385124757917190871707428690095953534423420502659893,
6588241760722454601615602907791715854928448488066342428651422663075975107816,
19842357292988471204463611705572234531158701273234975255676630503476698710155,
14693625717448698302951456188963654748379774732579848481403435079923870603157,
20241432824683494982737262054148903653340519392174437358036298330854555784611,
5945081237575571782036580504962786649821981413555607621373828735238630355652
],
[
17652382972559786603081358712023734457988123179346418318061767410638467351353,
8609310002954675750899296865505156197275068986904937546335682968407062557353,
20953981342395933310821155979182741101782516022917194002901756056810161577653,
14010114671133332884183212883039266364632832900771268544464943567097360538030,
20768578042859563979294333002563065924476840206018011719077318477769915880402,
2001786654254515377677955109354751436919751171611935922531378122392365944293,
2298051095199584549599791615579815921675635758326996304424561508720678758962,
15610877986863106190281569495837881819071964316157027243989237288310023404773,
21503958051574416294837474683907975773972588915544597427974161349505807601206,
16176536100016079147853297185775543699660096471098091832015791823791903209774,
3606739889472294515277184850587920470749374877850756839089044653095424769194,
14664144387169595605857061033949425545099119522415523292224065111113602111904,
19699387660834749955063410769084991520255142011324093146157127237115274380578,
4331670811250121546993058308579590495468093227852181043972677680581964769228
],
[
11589273064298032074960397339280273111253628710081452605587787277989878262684,
155887139811629598842391409587306581332057016161277301334614704354501745866,
21415746312736962630685763964130668169157204911852029590085104536633069699336,
16121151623164478719433805875174860779395398667644700642305374194327245787952,
10631178625335401501457304969878852001559776191683447428857609753454937038299,
11675745006421997275450756626998030285194831397590498324078767720340123952646,
1759441622054752159360583922123536313476013806215300533220440946452846159126,
3059329356920789196856680267147718801714171797250645043538678427768342056591,
1809413652255811383678263677090386586529134039718623375196604927184100692799,
7533217575609552382385270158875791232330359159976337796303987871112517604844,
7704646641054955393597890923317433079643657350033170553840404545002600772539,
19522826015127415513569513500635678903639248861485847260009074714535026926155,
9396801995941988552875859512580723873116085524385365053682345361229348266222,
8122885501816310710455960482459104382732335722838233409931476783790044860185
],
[
14621784478774900045485232005516896073016099759402781623216618339142142444432,
1432416214818308586539371032122259241440290306461685527056371471791146740623,
10859741497221216461724796630804714121202257706435373999834867538278407694230,
11269289100589657711755210305168004136417079020640258348687053385360804643179,
16304360708182088008313907877667665892976553429106710412375369419780233976442,
10460941404478613816427928998514834125407907547113907613807191273719986187223,
20051043271541513424021087402997604909963063035826832503174487686321968961776,
13432165841378395910455231038520827433713426813680931204822379789609795102053,
18762866968227660024720719389346562423430884054824643430326826128394380607310,
17713599719831815773421839749444223685540274101601039260510841144941870261910,
1883157762896148563929088253054113240995256206097667755269496270918239318411,
10985354533025938485092599481185428202087973711120611094551172933738810516920,
670487064764400248463858966885752477833093767820377805346079091001272760417,
8502840196732756246718058003393498205431869135787193347957619883686320532648
]
];
@@ -241,7 +558,7 @@ contract SemaphoreVerifier {
assembly {
function checkField(v) {
if iszero(lt(v, q)) {
if iszero(lt(v, r)) {
mstore(0, 0)
return(0, 0x20)
}

View File

@@ -55,6 +55,10 @@ interface ISemaphore {
uint256[8] points
);
/// @dev Returns the current value of the group counter.
/// @return The current group counter value.
function groupCounter() external view returns (uint256);
/// @dev See {SemaphoreGroups-_createGroup}.
function createGroup() external returns (uint256);

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/contracts",
"version": "4.0.0-beta.7",
"version": "4.0.0-beta.16",
"description": "Semaphore contracts to manage groups and broadcast anonymous signals.",
"license": "MIT",
"files": [
@@ -30,6 +30,6 @@
"access": "public"
},
"dependencies": {
"@zk-kit/imt.sol": "2.0.0-beta.8"
"@zk-kit/lean-imt.sol": "2.0.0"
}
}

View File

@@ -14,7 +14,15 @@ import "./tasks/deploy"
dotenvConfig({ path: resolve(__dirname, "../../.env") })
const hardhatConfig: HardhatUserConfig = {
solidity: "0.8.23",
solidity: {
version: "0.8.23",
settings: {
optimizer: {
enabled: true,
runs: 200
}
}
},
networks: {
hardhat: {
chainId: 1337,

View File

@@ -18,7 +18,7 @@
"@nomicfoundation/hardhat-ethers": "^3.0.0",
"@nomicfoundation/hardhat-network-helpers": "^1.0.0",
"@nomicfoundation/hardhat-toolbox": "^4.0.0",
"@nomicfoundation/hardhat-verify": "^2.0.5",
"@nomicfoundation/hardhat-verify": "^2.0.8",
"@semaphore-protocol/core": "workspace:packages/core",
"@semaphore-protocol/utils": "workspace:packages/utils",
"@typechain/ethers-v6": "^0.5.0",
@@ -39,6 +39,6 @@
"typescript": "^5.3.3"
},
"dependencies": {
"@zk-kit/imt.sol": "2.0.0-beta.8"
"@zk-kit/lean-imt.sol": "2.0.0"
}
}

View File

@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/no-shadow */
/* eslint-disable jest/valid-expect */
import { Group, Identity, SemaphoreProof, generateProof } from "@semaphore-protocol/core"
import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers"
import { expect } from "chai"
import { Signer, ZeroAddress } from "ethers"
import { run } from "hardhat"
@@ -8,29 +9,30 @@ import { run } from "hardhat"
import { Semaphore } from "../typechain-types"
describe("Semaphore", () => {
let semaphoreContract: Semaphore
let accounts: Signer[]
let accountAddresses: string[]
const merkleTreeDepth = 12
const groupId = 0
const members = Array.from({ length: 3 }, (_, i) => new Identity(i.toString())).map(({ commitment }) => commitment)
before(async () => {
async function deploySemaphoreFixture() {
const { semaphore } = await run("deploy", {
logs: false
})
semaphoreContract = semaphore
const semaphoreContract: Semaphore = semaphore
accounts = await run("accounts", { logs: false })
accountAddresses = await Promise.all(accounts.map((signer: Signer) => signer.getAddress()))
})
const accounts = await run("accounts", { logs: false })
const accountAddresses = await Promise.all(accounts.map((signer: Signer) => signer.getAddress()))
const groupId = 0
return {
semaphoreContract,
accounts,
accountAddresses,
groupId
}
}
describe("# createGroup", () => {
it("Should create a group", async () => {
const groupId = 0
const { semaphoreContract, accounts, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const transaction = semaphoreContract.connect(accounts[1])["createGroup(address)"](accountAddresses[1])
await expect(transaction).to.emit(semaphoreContract, "GroupCreated").withArgs(groupId)
@@ -40,11 +42,16 @@ describe("Semaphore", () => {
})
it("Should create a group with a custom Merkle tree root expiration", async () => {
const groupId = 1
const { semaphoreContract, accounts, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const transaction = await semaphoreContract.connect(accounts[1])["createGroup(address,uint256)"](
accountAddresses[0],
5 // 5 seconds.
)
const members = Array.from({ length: 3 }, (_, i) => new Identity(i.toString())).map(
({ commitment }) => commitment
)
await semaphoreContract.addMember(groupId, members[0])
await semaphoreContract.addMember(groupId, members[1])
await semaphoreContract.addMember(groupId, members[2])
@@ -56,7 +63,7 @@ describe("Semaphore", () => {
})
it("Should create a group without any parameters", async () => {
const groupId = 2
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const transaction = await semaphoreContract["createGroup()"]()
@@ -69,6 +76,10 @@ describe("Semaphore", () => {
describe("# updateGroupMerkleTreeDuration", () => {
it("Should not update a group Merkle tree duration if the caller is not the group admin", async () => {
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
await semaphoreContract["createGroup(address)"](accountAddresses[1])
const transaction = semaphoreContract.updateGroupMerkleTreeDuration(groupId, 300)
await expect(transaction).to.be.revertedWithCustomError(
@@ -78,7 +89,11 @@ describe("Semaphore", () => {
})
it("Should update the group Merkle tree duration", async () => {
const transaction = semaphoreContract.connect(accounts[1]).updateGroupMerkleTreeDuration(groupId, 300)
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
await semaphoreContract["createGroup(address)"](accountAddresses[0])
const transaction = semaphoreContract.updateGroupMerkleTreeDuration(groupId, 300)
await expect(transaction)
.to.emit(semaphoreContract, "GroupMerkleTreeDurationUpdated")
@@ -88,6 +103,10 @@ describe("Semaphore", () => {
describe("# updateGroupAdmin", () => {
it("Should not update an admin if the caller is not the admin", async () => {
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
await semaphoreContract["createGroup(address)"](accountAddresses[1])
const transaction = semaphoreContract.updateGroupAdmin(groupId, accountAddresses[0])
await expect(transaction).to.be.revertedWithCustomError(
@@ -97,14 +116,23 @@ describe("Semaphore", () => {
})
it("Should update the admin", async () => {
const transaction = semaphoreContract.connect(accounts[1]).updateGroupAdmin(groupId, accountAddresses[0])
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
await semaphoreContract["createGroup(address)"](accountAddresses[0])
const transaction = semaphoreContract.updateGroupAdmin(groupId, accountAddresses[1])
await expect(transaction)
.to.emit(semaphoreContract, "GroupAdminPending")
.withArgs(groupId, accountAddresses[1], accountAddresses[0])
.withArgs(groupId, accountAddresses[0], accountAddresses[1])
})
it("Should not accept accept the new admin if the caller is not the new admin", async () => {
const { semaphoreContract, accounts, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
await semaphoreContract["createGroup(address)"](accountAddresses[0])
await semaphoreContract.updateGroupAdmin(groupId, accountAddresses[1])
const transaction = semaphoreContract.connect(accounts[2]).acceptGroupAdmin(groupId)
await expect(transaction).to.be.revertedWithCustomError(
@@ -114,18 +142,27 @@ describe("Semaphore", () => {
})
it("Should accept the new admin", async () => {
const transaction = semaphoreContract.acceptGroupAdmin(groupId)
const { semaphoreContract, accounts, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
await semaphoreContract["createGroup(address)"](accountAddresses[0])
await semaphoreContract.updateGroupAdmin(groupId, accountAddresses[1])
const transaction = semaphoreContract.connect(accounts[1]).acceptGroupAdmin(groupId)
await expect(transaction)
.to.emit(semaphoreContract, "GroupAdminUpdated")
.withArgs(groupId, accountAddresses[1], accountAddresses[0])
.withArgs(groupId, accountAddresses[0], accountAddresses[1])
})
})
describe("# addMember", () => {
it("Should not add a member if the caller is not the group admin", async () => {
const { semaphoreContract, accounts, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const member = 2n
await semaphoreContract["createGroup(address)"](accountAddresses[0])
const transaction = semaphoreContract.connect(accounts[1]).addMember(groupId, member)
await expect(transaction).to.be.revertedWithCustomError(
@@ -135,10 +172,17 @@ describe("Semaphore", () => {
})
it("Should add a new member in an existing group", async () => {
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const group = new Group()
const members = Array.from({ length: 3 }, (_, i) => new Identity(i.toString())).map(
({ commitment }) => commitment
)
group.addMember(members[0])
await semaphoreContract["createGroup(address)"](accountAddresses[0])
const transaction = semaphoreContract.addMember(groupId, members[0])
await expect(transaction)
@@ -149,8 +193,12 @@ describe("Semaphore", () => {
describe("# addMembers", () => {
it("Should not add members if the caller is not the group admin", async () => {
const { semaphoreContract, accounts, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const members = [1n, 2n, 3n]
await semaphoreContract["createGroup(address)"](accountAddresses[0])
const transaction = semaphoreContract.connect(accounts[1]).addMembers(groupId, members)
await expect(transaction).to.be.revertedWithCustomError(
@@ -160,7 +208,8 @@ describe("Semaphore", () => {
})
it("Should add new members to an existing group", async () => {
const groupId = 3
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const members = [1n, 2n, 3n]
const group = new Group()
@@ -178,8 +227,12 @@ describe("Semaphore", () => {
describe("# updateMember", () => {
it("Should not update a member if the caller is not the group admin", async () => {
const { semaphoreContract, accounts, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const member = 2n
await semaphoreContract["createGroup(address)"](accountAddresses[0])
const transaction = semaphoreContract.connect(accounts[1]).updateMember(groupId, member, 1, [0, 1])
await expect(transaction).to.be.revertedWithCustomError(
@@ -189,7 +242,8 @@ describe("Semaphore", () => {
})
it("Should update a member from an existing group", async () => {
const groupId = 4
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const members = [1n, 2n, 3n]
const group = new Group()
@@ -210,8 +264,12 @@ describe("Semaphore", () => {
describe("# removeMember", () => {
it("Should not remove a member if the caller is not the group admin", async () => {
const { semaphoreContract, accounts, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const member = 2n
await semaphoreContract["createGroup(address)"](accountAddresses[0])
const transaction = semaphoreContract.connect(accounts[1]).removeMember(groupId, member, [0, 1])
await expect(transaction).to.be.revertedWithCustomError(
@@ -221,7 +279,8 @@ describe("Semaphore", () => {
})
it("Should remove a member from an existing group", async () => {
const groupId = 5
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const members = [1n, 2n, 3n]
const group = new Group()
@@ -242,12 +301,18 @@ describe("Semaphore", () => {
describe("# getGroupAdmin", () => {
it("Should return a 0 address if the group does not exist", async () => {
const { semaphoreContract } = await loadFixture(deploySemaphoreFixture)
const address = await semaphoreContract.getGroupAdmin(999)
expect(address).to.equal(ZeroAddress)
})
it("Should return the address of the group admin", async () => {
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
await semaphoreContract["createGroup(address)"](accountAddresses[0])
const address = await semaphoreContract.getGroupAdmin(groupId)
expect(address).to.equal(accountAddresses[0])
@@ -255,31 +320,45 @@ describe("Semaphore", () => {
})
describe("# verifyProof", () => {
const groupId = 6
const message = 2
const identity = new Identity("0")
async function deployVerifyProofFixture() {
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const group = new Group()
const members = Array.from({ length: 3 }, (_, i) => new Identity(i.toString())).map(
({ commitment }) => commitment
)
group.addMembers(members)
let proof: SemaphoreProof
before(async () => {
await semaphoreContract["createGroup(address)"](accountAddresses[0])
await semaphoreContract.addMembers(groupId, members)
proof = await generateProof(identity, group, message, group.root, merkleTreeDepth)
})
const identity = new Identity("0")
const group = new Group()
group.addMembers(members)
const merkleTreeDepth = 12
const message = 2
const proof: SemaphoreProof = await generateProof(identity, group, message, group.root, merkleTreeDepth)
return {
semaphoreContract,
accountAddresses,
groupId,
members,
proof
}
}
it("Should not verify a proof if the group does not exist", async () => {
const { semaphoreContract, proof } = await loadFixture(deployVerifyProofFixture)
const transaction = semaphoreContract.verifyProof(11, proof)
await expect(transaction).to.be.revertedWithCustomError(semaphoreContract, "Semaphore__GroupDoesNotExist")
})
it("Should not verify a proof if the Merkle tree root is not part of the group", async () => {
const { semaphoreContract, groupId, proof } = await loadFixture(deployVerifyProofFixture)
const transaction = semaphoreContract.verifyProof(groupId, { ...proof, merkleTreeRoot: 1 })
await expect(transaction).to.be.revertedWithCustomError(
@@ -289,20 +368,31 @@ describe("Semaphore", () => {
})
it("Should verify a proof for an onchain group", async () => {
const { semaphoreContract, groupId, proof } = await loadFixture(deployVerifyProofFixture)
const validProof = await semaphoreContract.verifyProof(groupId, proof)
expect(validProof).to.equal(true)
})
it("Should not verify a proof if the Merkle tree root is expired", async () => {
const groupId = 1
const { semaphoreContract, accountAddresses, members } = await loadFixture(deployVerifyProofFixture)
// create new group with 0s Merkle tree root expiration
const groupId = 1
await semaphoreContract["createGroup(address,uint256)"](accountAddresses[0], 0)
await semaphoreContract.addMember(groupId, members[0])
await semaphoreContract.addMember(groupId, members[1])
await semaphoreContract.addMember(groupId, members[2])
const message = 2
const merkleTreeDepth = 12
const identity = new Identity("0")
const group = new Group()
group.addMembers([members[0], members[1]])
const proof = await generateProof(identity, group, message, group.root, merkleTreeDepth)
const transaction = semaphoreContract.verifyProof(groupId, proof)
await expect(transaction).to.be.revertedWithCustomError(
@@ -312,8 +402,16 @@ describe("Semaphore", () => {
})
it("Should not verify a proof if the Merkle depth is not supported", async () => {
const scope = "random-scope"
const { semaphoreContract, groupId, members } = await loadFixture(deployVerifyProofFixture)
const message = 2
const merkleTreeDepth = 12
const identity = new Identity("0")
const group = new Group()
group.addMembers(members)
const scope = "random-scope"
const proof = await generateProof(identity, group, message, scope, merkleTreeDepth)
proof.merkleTreeDepth = 33
@@ -327,9 +425,11 @@ describe("Semaphore", () => {
})
it("Should not verify a proof if the group has no members", async () => {
const groupId = 7
const { semaphoreContract, accountAddresses, proof } = await loadFixture(deployVerifyProofFixture)
await semaphoreContract["createGroup(address)"](accountAddresses[0])
const groupId = 1
const transaction = semaphoreContract.verifyProof(groupId, proof)
await expect(transaction).to.be.revertedWithCustomError(semaphoreContract, "Semaphore__GroupHasNoMembers")
@@ -337,58 +437,64 @@ describe("Semaphore", () => {
})
describe("# validateProof", () => {
const message = 2
const identity = new Identity("0")
const groupOneMemberId = 7
async function deployValidateProofFixture() {
const { semaphoreContract, accountAddresses } = await loadFixture(deploySemaphoreFixture)
const group = new Group()
const groupOneMember = new Group()
group.addMembers(members)
groupOneMember.addMember(members[0])
let proof: SemaphoreProof
let proofOneMember: SemaphoreProof
before(async () => {
await semaphoreContract["createGroup(address)"](accountAddresses[0])
await semaphoreContract.addMembers(groupId, [members[1], members[2]])
await semaphoreContract.addMember(groupOneMemberId, members[0])
proof = await generateProof(identity, group, message, group.root, merkleTreeDepth)
proofOneMember = await generateProof(
identity,
groupOneMember,
message,
groupOneMember.root,
merkleTreeDepth
const members = Array.from({ length: 3 }, (_, i) => new Identity(i.toString())).map(
({ commitment }) => commitment
)
})
const merkleTreeDepth = 12
const message = 2
// groupId = 0
await semaphoreContract["createGroup(address)"](accountAddresses[0])
await semaphoreContract.addMembers(0, [members[1], members[2]])
// groupId = 1
const groupId = 1
await semaphoreContract["createGroup(address)"](accountAddresses[0])
await semaphoreContract.addMember(groupId, members[0])
await semaphoreContract.addMember(groupId, members[1])
const identity = new Identity("0")
const group = new Group()
group.addMember(members[0])
const proof = await generateProof(identity, group, message, group.root, merkleTreeDepth)
return { semaphoreContract, groupId, proof }
}
it("Should throw an exception if the proof is not valid", async () => {
const { semaphoreContract, groupId, proof } = await loadFixture(deployValidateProofFixture)
const transaction = semaphoreContract.validateProof(groupId, { ...proof, scope: 0 })
await expect(transaction).to.be.revertedWithCustomError(semaphoreContract, "Semaphore__InvalidProof")
})
it("Should validate a proof for an onchain group with one member correctly", async () => {
const transaction = semaphoreContract.validateProof(groupOneMemberId, proofOneMember)
const { semaphoreContract, groupId, proof } = await loadFixture(deployValidateProofFixture)
const transaction = semaphoreContract.validateProof(groupId, proof)
await expect(transaction)
.to.emit(semaphoreContract, "ProofValidated")
.withArgs(
groupOneMemberId,
proofOneMember.merkleTreeDepth,
proofOneMember.merkleTreeRoot,
proofOneMember.nullifier,
proofOneMember.message,
proofOneMember.merkleTreeRoot,
proofOneMember.points
groupId,
proof.merkleTreeDepth,
proof.merkleTreeRoot,
proof.nullifier,
proof.message,
proof.merkleTreeRoot,
proof.points
)
})
it("Should validate a proof for an onchain group with more than one member correctly", async () => {
const { semaphoreContract, groupId, proof } = await loadFixture(deployValidateProofFixture)
const transaction = semaphoreContract.validateProof(groupId, proof)
await expect(transaction)
@@ -405,6 +511,10 @@ describe("Semaphore", () => {
})
it("Should not validate the same proof for an onchain group twice", async () => {
const { semaphoreContract, groupId, proof } = await loadFixture(deployValidateProofFixture)
await semaphoreContract.validateProof(groupId, proof)
const transaction = semaphoreContract.validateProof(groupId, proof)
await expect(transaction).to.be.revertedWithCustomError(
@@ -417,30 +527,62 @@ describe("Semaphore", () => {
describe("SemaphoreGroups", () => {
describe("# hasMember", () => {
it("Should return true because the member is part of the group", async () => {
const groupId = 1
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const members = Array.from({ length: 3 }, (_, i) => new Identity(i.toString())).map(
({ commitment }) => commitment
)
await semaphoreContract["createGroup(address)"](accountAddresses[0])
await semaphoreContract.addMember(groupId, members[0])
const isMember = await semaphoreContract.hasMember(groupId, members[0])
await expect(isMember).to.be.true
})
it("Should return false because the member is not part of the group", async () => {
const groupId = 1
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
await semaphoreContract["createGroup(address)"](accountAddresses[0])
const identity = new Identity()
const isMember = await semaphoreContract.hasMember(groupId, identity.commitment)
await expect(isMember).to.be.false
})
})
describe("# indexOf", () => {
it("Should return the index of a member", async () => {
const groupId = 1
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const members = Array.from({ length: 3 }, (_, i) => new Identity(i.toString())).map(
({ commitment }) => commitment
)
await semaphoreContract["createGroup(address)"](accountAddresses[0])
await semaphoreContract.addMember(groupId, members[0])
const index = await semaphoreContract.indexOf(groupId, members[0])
await expect(index).to.equal(0)
})
})
describe("# getMerkleTreeDepth", () => {
it("Should return the merkle tree depth", async () => {
const groupId = 1
const { semaphoreContract, accountAddresses, groupId } = await loadFixture(deploySemaphoreFixture)
const members = Array.from({ length: 3 }, (_, i) => new Identity(i.toString())).map(
({ commitment }) => commitment
)
await semaphoreContract["createGroup(address)"](accountAddresses[0])
await semaphoreContract.addMember(groupId, members[0])
await semaphoreContract.addMember(groupId, members[1])
await semaphoreContract.addMember(groupId, members[2])
const depth = await semaphoreContract.getMerkleTreeDepth(groupId)
await expect(depth).to.equal(2)

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/core",
"version": "4.0.0-beta.7",
"version": "4.0.0-beta.16",
"description": "Core library for the essential Semaphore features.",
"type": "module",
"license": "MIT",
@@ -42,8 +42,8 @@
"access": "public"
},
"dependencies": {
"@semaphore-protocol/group": "4.0.0-beta.7",
"@semaphore-protocol/identity": "4.0.0-beta.7",
"@semaphore-protocol/proof": "4.0.0-beta.7"
"@semaphore-protocol/group": "4.0.0-beta.16",
"@semaphore-protocol/identity": "4.0.0-beta.16",
"@semaphore-protocol/proof": "4.0.0-beta.16"
}
}

View File

@@ -2,7 +2,7 @@
<h1 align="center">
Semaphore data
</h1>
<p align="center">A library to query Semaphore contracts.</p>
<p align="center">A library for querying Semaphore smart contract.</p>
</p>
<p align="center">
@@ -49,8 +49,8 @@
</h4>
</div>
| This library allows you to query the [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) contract data (i.e. groups) using the [Semaphore subgraph](https://github.com/semaphore-protocol/subgraph) or Ethers. It can be used on Node.js and browsers. |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| This library provides tools for querying and interacting with the [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) smart contract. It supports both the Semaphore subgraph and direct Ethereum network connections via Ethers. Designed for use in both Node.js and browser environments, it facilitates the management of group data and verification processes within the Semaphore protocol. |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
## 🛠 Install
@@ -70,15 +70,11 @@ yarn add @semaphore-protocol/data
## 📜 Usage
For more information on the functions provided by `@semaphore-protocol/data`, please refer to the [TypeDoc documentation](https://js.semaphore.pse.dev/modules/_semaphore_protocol_data).
For detailed information on the functions provided by `@semaphore-protocol/data`, please refer to the [TypeDoc documentation](https://js.semaphore.pse.dev/modules/_semaphore_protocol_data).
\# **getSupportedNetworks**(): _string[]_
### Creating and Managing Subgraphs
```typescript
const supportedNetworks = getSupportedNetworks()
```
\# **new SemaphoreSubgraph**(networkOrSubgraphURL: SupportedNetwork | ValueOf\<SupportedNetwork> | string = "sepolia"): _SemaphoreSubgraph_
**Initialize a Semaphore Subgraph instance**
```typescript
import { SemaphoreSubgraph } from "@semaphore-protocol/data"
@@ -86,62 +82,53 @@ import { SemaphoreSubgraph } from "@semaphore-protocol/data"
const semaphoreSubgraph = new SemaphoreSubgraph()
// or:
const semaphoreSubgraph = new SemaphoreSubgraph("arbitrum")
const semaphoreSubgraphOnArbitrum = new SemaphoreSubgraph("arbitrum")
// or:
const semaphoreSubgraph = new SemaphoreSubgraph(
const customSubgraph = new SemaphoreSubgraph(
"https://api.studio.thegraph.com/query/14377/<your-subgraph>/<your-version>"
)
```
\# **getGroupIds**(): _Promise\<string[]>_
With your SemaphoreSubgraph, you can:
**Query Group IDs**
```typescript
const groupIds = await semaphoreSubgraph.getGroupIds()
```
\# **getGroups**(options?: _GroupOptions_): _Promise\<GroupResponse[]>_
```typescript
const groups = await semaphoreSubgraph.getGroups()
// or
const groups = await semaphoreSubgraph.getGroups({ members: true, verifiedProofs: true })
```
\# **getGroup**(groupId: _string_, options?: _GroupOptions_): _Promise\<GroupResponse>_
**Query Group Details**
```typescript
const group = await semaphoreSubgraph.getGroup("42")
// or
const { members, verifiedProofs } = semaphoreSubgraph.getGroup("42", { members: true, verifiedProofs: true })
const { members, verifiedProofs } = await semaphoreSubgraph.getGroup("42", { members: true, verifiedProofs: true })
```
\# **getGroupMembers**(groupId: _string_): _Promise\<string[]>_
**Query Group Members**
```typescript
const members = await semaphoreSubgraph.getGroupMembers("42")
```
\# **getGroupVerifiedProofs**(groupId: _string_): _Promise\<any[]>_
**Query Verified Proofs**
```typescript
const verifiedProofs = await semaphoreSubgraph.getGroupVerifiedProofs("42")
```
\# **isGroupMember**(groupId: _string_, member: _string_): _Promise\<boolean>_
**Check Group Membership**
```typescript
await semaphoreSubgraph.isGroupMember(
const isMember = await semaphoreSubgraph.isGroupMember(
"42",
"16948514235341957898454876473214737047419402240398321289450170535251226167324"
)
```
\# **new Ethers**(networkOrEthereumURL: Network | string = "sepolia", options: EthersOptions = {}): _SemaphoreEthers_
### Using Ethers for Direct Blockchain Interaction
**Initialize a Semaphore Ethers instance**
```typescript
import { SemaphoreEthers } from "@semaphore-protocol/data"
@@ -149,51 +136,53 @@ import { SemaphoreEthers } from "@semaphore-protocol/data"
const semaphoreEthers = new SemaphoreEthers()
// or:
const semaphoreEthers = new SemaphoreEthers("homestead", {
const semaphoreEthersOnHomestead = new SemaphoreEthers("homestead", {
address: "semaphore-address",
startBlock: 0
})
// or:
const semaphoreEthers = new SemaphoreEthers("http://localhost:8545", {
const localEthersInstance = new SemaphoreEthers("http://localhost:8545", {
address: "semaphore-address"
})
```
\# **getGroupIds**(): _Promise\<string[]>_
With your SemaphoreEthers instance, you can:
**Fetch Group IDs**
```typescript
const groupIds = await semaphoreEthers.getGroupIds()
```
\# **getGroup**(groupId: _string_): _Promise\<GroupResponse>_
**Fetch Group Details**
```typescript
const group = await semaphoreEthers.getGroup("42")
```
\# **getGroupAdmin**(groupId: _string_): _Promise\<string>_
**Fetch Group Admin**
```typescript
const admin = await semaphoreEthers.getGroupAdmin("42")
```
\# **getGroupMembers**(groupId: _string_): _Promise\<string[]>_
**Fetch Group Members**
```typescript
const members = await semaphoreEthers.getGroupMembers("42")
```
\# **getGroupVerifiedProofs**(groupId: _string_): _Promise\<any[]>_
**Fetch Verified Proofs**
```typescript
const verifiedProofs = await semaphoreEthers.getGroupVerifiedProofs("42")
```
\# **isGroupMember**(groupId: _string_, member: _string_): _Promise\<boolean>_
**Check Group Membership**
```typescript
await semaphoreEthers.isGroupMember(
const isMember = await semaphoreEthers.isGroupMember(
"42",
"16948514235341957898454876473214737047419402240398321289450170535251226167324"
)

View File

@@ -1,7 +1,7 @@
{
"name": "@semaphore-protocol/data",
"version": "4.0.0-beta.7",
"description": "A library to query Semaphore contracts.",
"version": "4.0.0-beta.16",
"description": "A library for querying Semaphore smart contract.",
"type": "module",
"license": "MIT",
"main": "dist/index.js",
@@ -37,7 +37,7 @@
"rollup-plugin-cleanup": "^3.2.1"
},
"dependencies": {
"@semaphore-protocol/utils": "4.0.0-beta.7",
"@semaphore-protocol/utils": "4.0.0-beta.16",
"axios": "1.6.6",
"ethers": "6.11.0"
}

View File

@@ -1,8 +1,11 @@
/**
* Check if the parameter type is correct.
* @param value Parameter value.
* @param name Parameter name.
* @param type Expected parameter type.
* Validates the type of a given parameter against an expected type.
* Throws a {@link TypeError} if the validation fails.
* This function is useful for ensuring that function arguments conform to expected types at runtime.
* @param value The value of the parameter to check.
* @param name The name of the parameter, used in the error message for easier debugging.
* @param type The expected JavaScript type as a string (e.g., 'string', 'number', 'object').
* @throws {TypeError} Throws an error if the type of `value` does not match the `type`.
*/
export default function checkParameter(value: any, name: string, type: string) {
if (typeof value !== type) {

View File

@@ -21,15 +21,23 @@ import getEvents from "./getEvents"
import SemaphoreABI from "./semaphoreABI.json"
import { EthersNetwork, EthersOptions, GroupResponse } from "./types"
/**
* The SemaphoreEthers class provides a high-level interface to interact with the Semaphore smart contract
* using the {@link https://docs.ethers.org/v5/ | ethers.js} library. It encapsulates all necessary functionalities to connect to Ethereum networks,
* manage contract instances, and perform operations such as retrieving group information or checking group memberships.
* This class simplifies the interaction with the Ethereum blockchain by abstracting the details of network connections
* and contract interactions.
*/
export default class SemaphoreEthers {
private _network: EthersNetwork | string
private _options: EthersOptions
private _contract: Contract
/**
* Initializes the Ethers object with an Ethereum network or custom URL.
* @param networkOrEthereumURL Ethereum network or custom URL.
* @param options Ethers options.
* Constructs a new SemaphoreEthers instance, initializing it with a network or a custom Ethereum node URL,
* and optional configuration settings for the ethers provider and contract.
* @param networkOrEthereumURL The Ethereum network name or a custom JSON-RPC URL to connect to.
* @param options Configuration options for the ethers provider and the Semaphore contract.
*/
constructor(networkOrEthereumURL: EthersNetwork | string = defaultNetwork, options: EthersOptions = {}) {
checkParameter(networkOrEthereumURL, "networkOrSubgraphURL", "string")
@@ -92,32 +100,32 @@ export default class SemaphoreEthers {
}
/**
* Returns the Ethereum network or custom URL.
* @returns Ethereum network or custom URL.
* Retrieves the Ethereum network or custom URL currently used by this instance.
* @returns The network or URL as a string.
*/
get network(): EthersNetwork | string {
return this._network
}
/**
* Returns the Ethers options.
* @returns Ethers options.
* Retrieves the options used for configuring the ethers provider and the Semaphore contract.
* @returns The configuration options.
*/
get options(): EthersOptions {
return this._options
}
/**
* Returns the contract object.
* @returns Contract object.
* Retrieves the ethers Contract instance used to interact with the Semaphore contract.
* @returns The Contract instance.
*/
get contract(): Contract {
return this._contract
}
/**
* Returns the list of group ids.
* @returns List of group ids.
* Fetches the list of group IDs from the Semaphore contract by querying the "GroupCreated" events.
* @returns A promise that resolves to an array of group IDs as strings.
*/
async getGroupIds(): Promise<string[]> {
const groups = await getEvents(this._contract, "GroupCreated", [], this._options.startBlock)
@@ -126,9 +134,10 @@ export default class SemaphoreEthers {
}
/**
* Returns a specific group.
* @param groupId Group id.
* @returns Specific group.
* Retrieves detailed information about a specific group by its ID. This method queries the Semaphore contract
* to get the group's admin, Merkle tree root, depth, and size.
* @param groupId The unique identifier of the group.
* @returns A promise that resolves to a GroupResponse object.
*/
async getGroup(groupId: string): Promise<GroupResponse> {
checkParameter(groupId, "groupId", "string")
@@ -157,9 +166,10 @@ export default class SemaphoreEthers {
}
/**
* Returns a list of group members.
* @param groupId Group id.
* @returns Group members.
* Fetches a list of members from a specific group. This method queries the Semaphore contract for events
* related to member additions and updates, and constructs the list of current group members.
* @param groupId The unique identifier of the group.
* @returns A promise that resolves to an array of member identity commitments as strings.
*/
async getGroupMembers(groupId: string): Promise<string[]> {
checkParameter(groupId, "groupId", "string")
@@ -241,9 +251,10 @@ export default class SemaphoreEthers {
}
/**
* Returns a list of group validated proofs.
* @param groupId Group id.
* @returns Group validated proofs.
* Retrieves a list of validated proofs for a specific group. This method queries the Semaphore contract
* for "ProofValidated" events and returns details about each proof.
* @param groupId The unique identifier of the group.
* @returns A promise that resolves to an array of validated proofs.
*/
async getGroupValidatedProofs(groupId: string): Promise<any> {
checkParameter(groupId, "groupId", "string")
@@ -272,10 +283,11 @@ export default class SemaphoreEthers {
}
/**
* Returns true if a member is part of group, and false otherwise.
* @param groupId Group id
* @param member Group member.
* @returns True if the member is part of the group, false otherwise.
* Checks whether a specific member is part of a group. This method queries the Semaphore contract
* to determine if the provided identity commitment is a member of the specified group.
* @param groupId The unique identifier of the group.
* @param member The identity commitment of the member to check.
* @returns A promise that resolves to true if the member is part of the group, otherwise false.
*/
async isGroupMember(groupId: string, member: string): Promise<boolean> {
checkParameter(groupId, "groupId", "string")

View File

@@ -2,12 +2,12 @@
import { Contract, EventLog } from "ethers/contract"
/**
* Returns the list of events of a contract with possible filters.
* @param contract Contract instance.
* @param eventName Name of the event.
* @param filterArgs Filter arguments.
* @param startBlock Block from which to start fetching.
* @returns List of contract events.
* Fetches a list of blockchain events from a smart contract based on specified filters and starting block.
* @param contract An instance of an ethers Contract connected to the blockchain.
* @param eventName The name of the event to filter.
* @param filterArgs Optional arguments to further filter the events.
* @param startBlock The block number from which to start fetching events (defaults to 0).
* @returns A promise that resolves to an array of event logs, each including event arguments and the block number.
*/
export default async function getEvents(
contract: Contract,

View File

@@ -3,6 +3,7 @@ import { isSupportedNetwork } from "@semaphore-protocol/utils/networks"
/**
* Returns the subgraph URL related to the network passed as a parameter.
* This function retrieves the URL of the Semaphore subgraph based on the provided network.
* @param supportedNetwork Semaphore supported network.
* @returns Subgraph URL.
*/
@@ -11,5 +12,5 @@ export default function getURL(supportedNetwork: SupportedNetwork): string {
throw new TypeError(`Network '${supportedNetwork}' is not supported`)
}
return `https://api.studio.thegraph.com/query/14377/semaphore-${supportedNetwork}/v4.0.0-beta`
return `https://api.studio.thegraph.com/query/14377/semaphore-${supportedNetwork}/v4.0.0-beta.15`
}

View File

@@ -1,10 +1,10 @@
import axios, { AxiosRequestConfig, AxiosResponse } from "axios"
/**
* Returns the response data of an HTTP request.
* @param url HTTP URL.
* @param config Axios request configuration.
* @returns Request data.
* Sends an HTTP request to a specified URL and returns the parsed response data.
* @param url The URL to which the HTTP request is sent.
* @param config Optional Axios request configuration to customize headers, method, timeout, etc.
* @returns A promise that resolves to the data extracted from the response, typically in JSON format.
*/
/* istanbul ignore next */
export default async function request(url: string, config?: AxiosRequestConfig): Promise<any> {

View File

@@ -6,12 +6,22 @@ import request from "./request"
import { GroupOptions, GroupResponse } from "./types"
import { jsDateToGraphqlDate } from "./utils"
/**
* The SemaphoreSubgraph class provides an interface to interact with the Semaphore smart contract
* via subgraph queries. It enables operations such as retrieving lists of group members and validated proofs,
* as well as checking membership within groups.
* Each group in Semaphore is represented as a {@link https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html | LeanIMT}
* (Lean Incremental Merkle Tree). This class supports interaction through either a
* {@link SupportedNetwork} or a direct URL to the subgraph. The subgraphs themselves are hosted on
* {@link https://thegraph.com/ | The Graph} protocol, facilitating efficient and decentralized query processing.
*/
export default class SemaphoreSubgraph {
private _url: string
/**
* Initializes the subgraph object with one of the supported networks or a custom URL.
* @param networkOrSubgraphURL Supported Semaphore network or custom Subgraph URL.
* Initializes the SemaphoreSubgraph instance with a supported network or a custom subgraph URL.
* This allows to interact with the Semaphore smart contract through the specified endpoint.
* @param networkOrSubgraphURL Either a supported network identifier or a direct URL to the subgraph.
*/
constructor(networkOrSubgraphURL: SupportedNetwork | string = defaultNetwork) {
checkParameter(networkOrSubgraphURL, "networkOrSubgraphURL", "string")
@@ -25,16 +35,18 @@ export default class SemaphoreSubgraph {
}
/**
* Returns the subgraph URL.
* @returns Subgraph URL.
* Retrieves the URL of the subgraph currently being used by the instance.
* This URL points to the specific subgraph where Semaphore data is stored.
* @returns The URL of the subgraph.
*/
get url(): string {
return this._url
}
/**
* Returns the list of group ids.
* @returns List of group ids.
* Fetches a list of all group IDs from the subgraph. This method queries the subgraph to retrieve
* identifiers for all groups managed by the Semaphore smart contract.
* @returns A promise that resolves to an array of group IDs.
*/
async getGroupIds(): Promise<string[]> {
const config: AxiosRequestConfig = {
@@ -54,9 +66,11 @@ export default class SemaphoreSubgraph {
}
/**
* Returns the list of groups.
* @param options Options to select the group parameters.
* @returns List of groups.
* Retrieves detailed information about groups from the subgraph based on the provided options.
* This method can filter groups by various parameters and include additional details like members
* and validated proofs if specified in the options.
* @param options Configuration options to filter groups and specify which additional details to fetch.
* @returns A promise that resolves to an array of group details.
*/
async getGroups(options: GroupOptions = {}): Promise<GroupResponse[]> {
checkParameter(options, "options", "object")
@@ -143,10 +157,11 @@ export default class SemaphoreSubgraph {
}
/**
* Returns a specific group.
* @param groupId Group id.
* @param options Options to select the group parameters.
* @returns Specific group.
* Fetches detailed information about a specific group by its ID. This method can also retrieve
* members and validated proofs for the group if requested via options.
* @param groupId The unique identifier of the group.
* @param options Configuration options to specify which details to fetch about the group.
* @returns A promise that resolves to the details of the specified group.
*/
async getGroup(groupId: string, options: Omit<GroupOptions, "filters"> = {}): Promise<GroupResponse> {
checkParameter(groupId, "groupId", "string")
@@ -204,9 +219,9 @@ export default class SemaphoreSubgraph {
}
/**
* Returns a list of group members.
* @param groupId Group id.
* @returns Group members.
* Retrieves a list of members from a specific group.
* @param groupId The unique identifier of the group.
* @returns A promise that resolves to an array of group members' identity commitments.
*/
async getGroupMembers(groupId: string): Promise<string[]> {
const group = await this.getGroup(groupId, { members: true }) // parameters are checked inside getGroup
@@ -214,9 +229,9 @@ export default class SemaphoreSubgraph {
}
/**
* Returns a list of validated proofs.
* @param groupId Group id.
* @returns Validated proofs.
* Fetches a list of validated proofs for a specific group.
* @param groupId The unique identifier of the group.
* @returns A promise that resolves to an array of validated proofs.
*/
async getGroupValidatedProofs(groupId: string): Promise<any[]> {
const group = await this.getGroup(groupId, { validatedProofs: true }) // parameters are checked inside getGroup
@@ -225,10 +240,11 @@ export default class SemaphoreSubgraph {
}
/**
* Returns true if a member is part of group, and false otherwise.
* @param groupId Group id
* @param member Group member.
* @returns True if the member is part of the group, false otherwise.
* Determines whether a specific member is part of a group. This method queries the subgraph to check
* if the provided member's identity commitment exists within the specified group.
* @param groupId The unique identifier of the group.
* @param member The identity commitment of the member to check.
* @returns A promise that resolves to true if the member is part of the group, otherwise false.
*/
async isGroupMember(groupId: string, member: string): Promise<boolean> {
checkParameter(groupId, "groupId", "string")

View File

@@ -2,7 +2,7 @@ export type EthersNetwork =
| "mainnet"
| "sepolia"
| "matic"
| "matic-mumbai"
| "matic-amoy"
| "arbitrum"
| "arbitrum-sepolia"
| "optimism"

View File

@@ -1,3 +1,8 @@
/**
* Converts a JavaScript Date object into a Unix timestamp.
* @param date The Date object to convert.
* @returns The Unix timestamp equivalent of the provided Date object.
*/
// eslint-disable-next-line import/prefer-default-export
export function jsDateToGraphqlDate(date: Date): number {
return Math.round(date.getTime() / 1000)

View File

@@ -18,7 +18,8 @@ jest.mock("ethers/contract", () => ({
getMerkleTreeRoot: () => "222",
getMerkleTreeDepth: () => BigInt(3),
getMerkleTreeSize: () => BigInt(8),
getGroupAdmin: () => "0xA9C2B639a28cDa8b59C4377e980F75A93dD8605F"
getGroupAdmin: () => "0xA9C2B639a28cDa8b59C4377e980F75A93dD8605F",
hasMember: () => true
}) as any
)
}))
@@ -235,4 +236,25 @@ describe("SemaphoreEthers", () => {
await expect(fun).rejects.toThrow("Group '666' not found")
})
})
describe("isGroupMember", () => {
it("Should return true because the member is part of the group", async () => {
const semaphore = new SemaphoreEthers()
const isMember = await semaphore.isGroupMember("42", "1")
expect(isMember).toBeTruthy()
})
it("Should return false because the member is not part of the group", async () => {
ContractMocked.mockReturnValueOnce({
hasMember: () => false
} as any)
const semaphore = new SemaphoreEthers()
const isMember = await semaphore.isGroupMember("48", "2")
expect(isMember).toBeFalsy()
})
})
})

View File

@@ -1,6 +1,6 @@
{
"name": "@semaphore-protocol/group",
"version": "4.0.0-beta.7",
"version": "4.0.0-beta.16",
"description": "A library to create and manage Semaphore groups.",
"type": "module",
"license": "MIT",
@@ -39,7 +39,7 @@
"rollup-plugin-cleanup": "^3.2.1"
},
"dependencies": {
"@zk-kit/imt": "2.0.0-beta.2",
"@zk-kit/utils": "1.0.0-beta"
"@zk-kit/lean-imt": "2.0.1",
"@zk-kit/utils": "1.0.0"
}
}

View File

@@ -1,4 +1,4 @@
import { LeanIMT, LeanIMTMerkleProof } from "@zk-kit/imt"
import { LeanIMT, LeanIMTMerkleProof } from "@zk-kit/lean-imt"
import type { BigNumber } from "@zk-kit/utils"
import { poseidon2 } from "poseidon-lite/poseidon2"
@@ -23,6 +23,12 @@ export class Group {
* @param members A list of identity commitments.
*/
constructor(members: BigNumber[] = []) {
for (const member of members) {
if (member === 0n || member === "0") {
throw new Error("Failed to add member: value cannot be 0")
}
}
this.leanIMT = new LeanIMT((a, b) => poseidon2([a, b]), members.map(BigInt))
}
@@ -144,10 +150,10 @@ export class Group {
* @param nodes The stringified JSON of the group.
* @returns The {@link Group} instance.
*/
static import(exportedGroup: string): Group {
static import(nodes: string): Group {
const group = new Group()
group.leanIMT.import(exportedGroup)
group.leanIMT.import(nodes)
return group
}

View File

@@ -23,6 +23,12 @@ describe("Group", () => {
expect(group.depth).toBe(2)
expect(group.size).toBe(3)
})
it("Should not create a group with a list of members if any value is 0", () => {
const fun = () => new Group([1n, 0n])
expect(fun).toThrow("Failed to add member: value cannot be 0")
})
})
describe("# addMember", () => {

View File

@@ -2,7 +2,7 @@
<h1 align="center">
Semaphore Hardhat plugin
</h1>
<p align="center">A Semaphore Hardhat plugin to deploy Semaphore contracts.</p>
<p align="center">A Hardhat plugin to deploy Semaphore contracts.</p>
</p>
<p align="center">
@@ -46,14 +46,14 @@
</h4>
</div>
| This Hardhat plugin provides two simple tasks that can be used to deploy Semaphore contracts without any additional configuration. |
| ---------------------------------------------------------------------------------------------------------------------------------- |
| The Semaphore Hardhat plugin simplifies the deployment of Semaphore contracts, reducing setup time and complexity. |
| ------------------------------------------------------------------------------------------------------------------ |
## 🛠 Install
### npm or yarn
Install the `@semaphore-protocol/hardhat` package with npm:
To install the Semaphore Hardhat plugin, use npm or yarn:
```bash
npm i @semaphore-protocol/hardhat
@@ -67,7 +67,7 @@ yarn add @semaphore-protocol/hardhat
## 📜 Usage
Import the plugin in your `hardhat.config.ts` file:
To use the plugin, import it in your Hardhat configuration file (`hardhat.config.ts`):
```typescript
import "@semaphore-protocol/hardhat"
@@ -110,3 +110,13 @@ task("deploy", "Deploy a Greeter contract")
return greeter
})
```
### Deploying Contracts
Use the provided tasks to deploy your Semaphore contracts:
```bash
npx hardhat deploy
```
This command will deploy a Semaphore contract using the addresses provided or deploy necessary dependencies like Semaphore Verifier and Poseidon library.

View File

@@ -1,7 +1,7 @@
{
"name": "@semaphore-protocol/hardhat",
"version": "4.0.0-beta.7",
"description": "A Semaphore Hardhat plugin to deploy verifiers and Semaphore contract.",
"version": "4.0.0-beta.16",
"description": "A Hardhat plugin to deploy Semaphore contracts.",
"type": "module",
"license": "MIT",
"main": "dist/index.js",
@@ -41,7 +41,7 @@
},
"dependencies": {
"@nomicfoundation/hardhat-ethers": "^3.0.0",
"@semaphore-protocol/contracts": "4.0.0-beta.7",
"@semaphore-protocol/contracts": "4.0.0-beta.16",
"ethers": "^6.4.0",
"hardhat-dependency-compiler": "^1.1.3"
}

Some files were not shown because too many files have changed in this diff Show More