chore: move docs to semaphore-protocol org

Former-commit-id: d88e4e9146
This commit is contained in:
cedoor
2022-05-07 11:01:21 +02:00
parent 6ef014fa7c
commit 9875778ad9
42 changed files with 1 additions and 12496 deletions

View File

@@ -1,25 +0,0 @@
name: docs
on:
push:
branches:
- main
jobs:
publish_docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 16.x
- run: cd docs && yarn --frozen-lockfile && yarn build
- uses: crazy-max/ghaction-github-pages@v2.5.0
with:
build_dir: docs/build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,6 +1,6 @@
<p align="center">
<h1 align="center">
<img width="40" src="https://github.com/appliedzkp/semaphore/blob/main/docs/static/img/semaphore-icon.svg">
<img width="40" src="https://github.com/semaphore-protocol/docs/blob/main/static/img/semaphore-icon.svg">
Semaphore
</h1>
<p align="center">A privacy gadget for creating anonymous proof of membership on Ethereum.</p>
@@ -10,9 +10,6 @@
<a href="https://github.com/appliedzkp/semaphore/blob/main/LICENSE">
<img alt="Github license" src="https://img.shields.io/github/license/appliedzkp/semaphore.svg?style=flat-square">
</a>
<a href="https://github.com/appliedzkp/semaphore/actions?query=workflow%3Adocs">
<img alt="GitHub Workflow docs" src="https://img.shields.io/github/workflow/status/appliedzkp/semaphore/docs?label=docs&style=flat-square&logo=github">
</a>
<a href="https://github.com/appliedzkp/semaphore/actions?query=workflow%3Atest">
<img alt="GitHub Workflow test" src="https://img.shields.io/github/workflow/status/appliedzkp/semaphore/test?label=test&style=flat-square&logo=github">
</a>

2
docs/.gitignore vendored
View File

@@ -1,2 +0,0 @@
# Production
build

View File

@@ -1,93 +0,0 @@
<p align="center">
<h1 align="center">
Semaphore docs
</h1>
<p align="center">Semaphore documentation website.</p>
</p>
<p align="center">
<a href="https://prettier.io/" target="_blank">
<img alt="Code style prettier" src="https://img.shields.io/badge/code%20style-prettier-f8bc45?style=flat-square&logo=prettier">
</a>
<img alt="Repository top language" src="https://img.shields.io/github/languages/top/akinovak/semaphore-spec?style=flat-square">
</p>
---
This directory contains the Semaphore documentation published at [semaphore.appliedzkp.org/docs](https://semaphore.appliedzkp.org/docs).
## Build and run Semaphore docs
Semaphore documentation uses Markdown syntax.
[semaphore.appliedzkp.org/docs](https://semaphore.appliedzkp.org/docs) uses the [Docusaurus](https://docusaurus.io/) site generator and JavaScript tooling to build and deploy styles, scripts, and HTML.
- [Install and run for development](#install-and-run-for-development)
- [Use deployment commands](#use-deployment-commands)
## Install and run for development
Install dependencies, build the documentation, and run the site on your local machine.
### Install Node.js and a package manager
If you haven't already, download and install [Node.js](https://nodejs.org/en/).
You can use `npm` (included with Node.js) or `yarn` to install Docusaurus and other Node.js packages.
To install `yarn`, run the following in your terminal:
```sh
$ npm i --global yarn
```
### 🛠 Get the code
Clone the Semaphore repository and then change to the `docs` directory:
```sh
$ git clone https://github.com/appliedzkp/semaphore.git && cd semaphore/docs
```
### Install dependencies
To install dependencies, run `yarn`:
```sh
$ yarn
```
### Start the site
To generate the HTML and start the site, run `yarn start`:
```sh
$ yarn start
```
Visit the Semaphore docs site in your browser at [http://localhost:3000](http://localhost:3000).
## 📜 Use deployment commands
### Develop
```
$ yarn start
```
Th `start` command starts a local development server (default port is `:3000`) and launches the site in your browser.
As you edit, the server reloads most changes and automatically refreshes the site in your browser.
### Build
```
$ yarn build
```
The `build` command generates static content into the `build` directory that can be served by any static content hosting service.
### Deploy
```
$ GIT_USER=<Your GitHub username> USE_SSH=true yarn deploy
```
If you use GitHub pages for hosting, this command lets you build the website and push to the `gh-pages` branch.

View File

@@ -1,3 +0,0 @@
module.exports = {
presets: [require.resolve("@docusaurus/core/lib/babel/preset")]
}

View File

@@ -1,126 +0,0 @@
module.exports = {
title: "Semaphore",
tagline: "Documentation and Guides",
url: "https://semaphore.appliedzkp.org/",
baseUrl: "/",
favicon: "/img/favicon.ico",
onBrokenLinks: "throw",
onBrokenMarkdownLinks: "warn",
organizationName: "appliedzkp",
projectName: "semaphore",
trailingSlash: false,
presets: [
[
"@docusaurus/preset-classic",
{
docs: {
path: "docs",
routeBasePath: "docs/",
sidebarPath: require.resolve("./sidebars.js"),
editUrl: "https://github.com/appliedzkp/semaphore/edit/main/",
includeCurrentVersion: false
},
theme: {
customCss: require.resolve("./src/css/custom.css"),
customCss2: require.resolve("./src/css/colors.css")
}
}
]
],
themeConfig: {
prism: {
additionalLanguages: ["solidity"]
},
navbar: {
title: "Semaphore",
logo: {
alt: "Semaphore Icon",
src: "img/semaphore-icon.svg"
},
items: [
{
type: "docsVersionDropdown",
position: "left",
dropdownActiveClassDisabled: true,
docsPluginId: "default",
className: "persistent"
},
{
label: "Whitepaper",
to: "https://semaphore.appliedzkp.org/whitepaper-v1.pdf",
position: "right",
className: "V1_active"
},
{
label: "GitHub",
href: "https://github.com/appliedzkp/semaphore",
position: "right",
className: "persistent"
}
]
},
footer: {
links: [
{
title: "PSE Team",
items: [
{
label: "Github",
href: "https://github.com/appliedzkp"
},
{
label: "Medium",
href: "https://medium.com/privacy-scaling-explorations"
},
{
label: "Twitter",
href: "https://twitter.com/PrivacyScaling"
}
]
},
{
title: "Community",
items: [
{
label: "Github",
href: "https://github.com/appliedzkp/semaphore"
},
{
label: "Telegram",
href: "https://t.me/joinchat/B-PQx1U3GtAh--Z4Fwo56A"
}
]
},
{
title: "More",
items: [
{
label: "ZK-kit",
href: "https://github.com/appliedzkp/zk-kit"
},
{
label: "Interep",
href: "https://github.com/interep-project"
}
]
}
]
},
colorMode: {
defaultMode: "dark",
// Should we use the prefers-color-scheme media-query,
// using user system preferences, instead of the hardcoded defaultMode
respectPrefersColorScheme: true,
// Dark/light switch icon options
switchConfig: {
// Icon for the switch while in dark mode
darkIcon: "\u{263D}",
// Unicode icons such as '\u2600' will work
// Unicode with 5 chars require brackets: '\u{1F602}'
lightIcon: "\u{263C}"
}
}
}
}

View File

@@ -1,51 +0,0 @@
{
"name": "@semaphore/docs",
"description": "Semaphore documentation website.",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "docusaurus start",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "2.0.0-beta.15",
"@docusaurus/preset-classic": "2.0.0-beta.15",
"@emotion/react": "^11.7.1",
"@emotion/styled": "^11.6.0",
"@mdx-js/react": "^1.6.22",
"@svgr/webpack": "^5.5.0",
"clsx": "^1.1.1",
"file-loader": "^6.2.0",
"prism-react-renderer": "^1.2.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"url-loader": "^4.1.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "2.0.0-beta.15",
"@tsconfig/docusaurus": "^1.0.4",
"@types/react": "^17.0.14",
"@types/react-helmet": "^6.1.2",
"@types/react-router-dom": "^5.1.8",
"typescript": "^4.3.5"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

View File

@@ -1,26 +0,0 @@
/**
* Creating a sidebar enables you to:
- create an ordered group of docs
- render a sidebar for each doc of that group
- provide next/previous navigation
The sidebars can be generated from the filesystem, or explicitly defined here.
Create as many sidebars as you want.
*/
module.exports = {
// By default, Docusaurus generates a sidebar from the docs folder structure
tutorialSidebar: [{ type: "autogenerated", dirName: "." }]
// But you can create a sidebar manually
/*
tutorialSidebar: [
{
type: 'category',
label: 'Tutorial',
items: ['hello'],
},
],
*/
}

View File

@@ -1,279 +0,0 @@
:root {
--ifm-dark-value: 10%;
--ifm-darker-value: 15%;
--ifm-darkest-value: 30%;
--ifm-light-value: 15%;
--ifm-lighter-value: 30%;
--ifm-lightest-value: 50%;
--ifm-color-primary: #3578e5;
--ifm-color-primary-dark: rgb(48, 108, 206);
--ifm-color-primary-darker: rgb(45, 102, 195);
--ifm-color-primary-darkest: rgb(37, 84, 160);
--ifm-color-primary-light: rgb(83, 140, 233);
--ifm-color-primary-lighter: rgb(114, 161, 237);
--ifm-color-primary-lightest: rgb(154, 188, 242);
--ifm-color-secondary: #ebedf0;
--ifm-color-secondary-dark: rgb(212, 213, 216);
--ifm-color-secondary-darker: rgb(200, 201, 204);
--ifm-color-secondary-darkest: rgb(164, 166, 168);
--ifm-color-secondary-light: rgb(238, 240, 242);
--ifm-color-secondary-lighter: rgb(241, 242, 245);
--ifm-color-secondary-lightest: rgb(245, 246, 248);
--ifm-color-success: #00a400;
--ifm-color-success-dark: rgb(0, 148, 0);
--ifm-color-success-darker: rgb(0, 139, 0);
--ifm-color-success-darkest: rgb(0, 115, 0);
--ifm-color-success-light: rgb(38, 178, 38);
--ifm-color-success-lighter: rgb(77, 191, 77);
--ifm-color-success-lightest: rgb(128, 210, 128);
--ifm-color-info: #54c7ec;
--ifm-color-info-dark: rgb(76, 179, 212);
--ifm-color-info-darker: rgb(71, 169, 201);
--ifm-color-info-darkest: rgb(59, 139, 165);
--ifm-color-info-light: rgb(110, 207, 239);
--ifm-color-info-lighter: rgb(135, 216, 242);
--ifm-color-info-lightest: rgb(170, 227, 246);
--ifm-color-warning: #ffba00;
--ifm-color-warning-dark: rgb(230, 167, 0);
--ifm-color-warning-darker: rgb(217, 158, 0);
--ifm-color-warning-darkest: rgb(179, 130, 0);
--ifm-color-warning-light: rgb(255, 196, 38);
--ifm-color-warning-lighter: rgb(255, 207, 77);
--ifm-color-warning-lightest: rgb(255, 221, 128);
--ifm-color-danger: #fa383e;
--ifm-color-danger-dark: rgb(225, 50, 56);
--ifm-color-danger-darker: rgb(213, 48, 53);
--ifm-color-danger-darkest: rgb(175, 39, 43);
--ifm-color-danger-light: rgb(251, 86, 91);
--ifm-color-danger-lighter: rgb(251, 116, 120);
--ifm-color-danger-lightest: rgb(253, 156, 159);
--ifm-color-white: #fff;
--ifm-color-black: #000;
--ifm-color-gray-0: var(--ifm-color-white);
--ifm-color-gray-100: #f5f6f7;
--ifm-color-gray-200: #ebedf0;
--ifm-color-gray-300: #dadde1;
--ifm-color-gray-400: #ccd0d5;
--ifm-color-gray-500: #bec3c9;
--ifm-color-gray-600: #8d949e;
--ifm-color-gray-700: #606770;
--ifm-color-gray-800: #444950;
--ifm-color-gray-900: #1c1e21;
--ifm-color-gray-1000: var(--ifm-color-black);
--ifm-color-emphasis-0: var(--ifm-color-gray-0);
--ifm-color-emphasis-100: var(--ifm-color-gray-100);
--ifm-color-emphasis-200: var(--ifm-color-gray-200);
--ifm-color-emphasis-300: var(--ifm-color-gray-300);
--ifm-color-emphasis-400: var(--ifm-color-gray-400);
--ifm-color-emphasis-500: var(--ifm-color-gray-500);
--ifm-color-emphasis-600: var(--ifm-color-gray-600);
--ifm-color-emphasis-700: var(--ifm-color-gray-700);
--ifm-color-emphasis-800: var(--ifm-color-gray-800);
--ifm-color-emphasis-900: var(--ifm-color-gray-900);
--ifm-color-emphasis-1000: var(--ifm-color-gray-1000);
--ifm-color-content: var(--ifm-color-emphasis-900);
--ifm-color-content-inverse: var(--ifm-color-emphasis-0);
--ifm-color-content-secondary: #606770;
--ifm-background-color: transparent;
--ifm-background-surface-color: var(--ifm-color-content-inverse);
--ifm-global-border-width: 1px;
--ifm-global-radius: 0.4rem;
--ifm-hover-overlay: rgba(0, 0, 0, 0.05);
--ifm-font-color-base: var(--ifm-color-content);
--ifm-font-color-base-inverse: var(--ifm-color-content-inverse);
--ifm-font-color-secondary: var(--ifm-color-content-secondary);
--ifm-font-family-base: system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif,
BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
--ifm-font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--ifm-font-size-base: 100%;
--ifm-font-weight-light: 300;
--ifm-font-weight-normal: 400;
--ifm-font-weight-semibold: 500;
--ifm-font-weight-bold: 700;
--ifm-font-weight-base: var(--ifm-font-weight-normal);
--ifm-line-height-base: 1.65;
--ifm-global-spacing: 1rem;
--ifm-spacing-vertical: var(--ifm-global-spacing);
--ifm-spacing-horizontal: var(--ifm-global-spacing);
--ifm-transition-fast: 200ms;
--ifm-transition-slow: 400ms;
--ifm-transition-timing-default: cubic-bezier(0.08, 0.52, 0.52, 1);
--ifm-global-shadow-lw: 0 1px 2px 0 rgba(0, 0, 0, 0.1);
--ifm-global-shadow-md: 0 5px 40px rgba(0, 0, 0, 0.2);
--ifm-global-shadow-tl: 0 12px 28px 0 rgba(0, 0, 0, 0.2), 0 2px 4px 0 rgba(0, 0, 0, 0.1);
--ifm-z-index-dropdown: 100;
--ifm-z-index-fixed: 200;
--ifm-z-index-overlay: 400;
--ifm-container-width: 1140px;
--ifm-container-width-xl: 1320px;
--ifm-code-background: var(--ifm-color-emphasis-200);
--ifm-code-border-radius: var(--ifm-global-radius);
--ifm-code-color: var(--ifm-color-emphasis-900);
--ifm-code-font-size: 90%;
--ifm-code-padding-horizontal: 0.4rem;
--ifm-code-padding-vertical: 0.2rem;
--ifm-pre-background: var(--ifm-color-emphasis-100);
--ifm-pre-border-radius: var(--ifm-code-border-radius);
--ifm-pre-color: inherit;
--ifm-pre-line-height: 1.45;
--ifm-pre-padding: 1rem;
--ifm-heading-color: inherit;
--ifm-heading-margin-top: 0;
--ifm-heading-margin-bottom: var(--ifm-spacing-vertical);
--ifm-heading-font-family: inherit;
--ifm-heading-font-weight: var(--ifm-font-weight-bold);
--ifm-heading-line-height: 1.25;
--ifm-h1-font-size: 1.5rem;
--ifm-h2-font-size: 1.25rem;
--ifm-h3-font-size: 1rem;
--ifm-h4-font-size: 0.875rem;
--ifm-h5-font-size: 0.875rem;
--ifm-h6-font-size: 0.85rem;
--ifm-image-alignment-padding: 1.25rem;
--ifm-leading-desktop: 1.25;
--ifm-leading: calc(var(--ifm-leading-desktop) * 1rem);
--ifm-list-left-padding: 2rem;
--ifm-list-margin: 1rem;
--ifm-list-item-margin: 0.25rem;
--ifm-list-paragraph-margin: 1rem;
--ifm-table-cell-padding: 0.75rem;
--ifm-table-background: transparent;
--ifm-table-stripe-background: var(--ifm-color-emphasis-100);
--ifm-table-border-width: 1px;
--ifm-table-border-color: var(--ifm-color-emphasis-200);
--ifm-table-head-background: inherit;
--ifm-table-head-color: inherit;
--ifm-table-head-font-weight: var(--ifm-font-weight-bold);
--ifm-table-cell-color: inherit;
--ifm-link-color: var(--ifm-color-primary);
--ifm-link-decoration: none;
--ifm-link-hover-color: var(--ifm-link-color);
--ifm-link-hover-decoration: underline;
--ifm-paragraph-margin-bottom: var(--ifm-leading);
--ifm-blockquote-color: #6a737d;
--ifm-blockquote-font-size: var(--ifm-font-size-base);
--ifm-blockquote-padding-horizontal: 1rem;
--ifm-blockquote-padding-vertical: 1rem;
--ifm-hr-border-color: var(--ifm-color-emphasis-500);
--ifm-hr-border-width: 1px;
--ifm-hr-margin-vertical: 1.5rem;
--ifm-alert-background-color: inherit;
--ifm-alert-border-color: inherit;
--ifm-alert-border-radius: var(--ifm-global-radius);
--ifm-alert-border-width: var(--ifm-global-border-width);
--ifm-alert-color: var(--ifm-font-color-base-inverse);
--ifm-alert-padding-horizontal: var(--ifm-spacing-horizontal);
--ifm-alert-padding-vertical: var(--ifm-spacing-vertical);
--ifm-avatar-intro-margin: 1rem;
--ifm-avatar-intro-alignment: inherit;
--ifm-avatar-photo-size-sm: 2rem;
--ifm-avatar-photo-size-md: 3rem;
--ifm-avatar-photo-size-lg: 4rem;
--ifm-avatar-photo-size-xl: 6rem;
--ifm-badge-background-color: inherit;
--ifm-badge-border-color: inherit;
--ifm-badge-border-radius: var(--ifm-global-radius);
--ifm-badge-border-width: var(--ifm-global-border-width);
--ifm-badge-color: var(--ifm-color-white);
--ifm-badge-padding-horizontal: calc(var(--ifm-spacing-horizontal) * 0.5);
--ifm-badge-padding-vertical: calc(var(--ifm-spacing-vertical) * 0.25);
--ifm-breadcrumb-border-radius: 1.5rem;
--ifm-breadcrumb-spacing: 0.0625rem;
--ifm-breadcrumb-color-active: var(--ifm-color-primary);
--ifm-breadcrumb-item-background-active: var(--ifm-hover-overlay);
--ifm-breadcrumb-padding-horizontal: 1rem;
--ifm-breadcrumb-padding-vertical: 0.5rem;
--ifm-breadcrumb-size-multiplier: 1;
--ifm-breadcrumb-separator: url(
data:image/svg + xml;utf8,
<svgxmlns="http://www.w3.org/2000/svg"x="0px"y="0px"viewBox="0 0 256 256"><g><g><polygonpoints="79.093,0 48.907,30.187 146.72,128 48.907,225.813 79.093,256 207.093,128"/></g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g><g></g></svg>
);
--ifm-breadcrumb-separator-filter: none;
--ifm-breadcrumb-separator-size: 0.5rem;
--ifm-breadcrumb-separator-size-multiplier: 1.25;
--ifm-button-background-color: inherit;
--ifm-button-border-color: var(--ifm-button-background-color);
--ifm-button-border-width: var(--ifm-global-border-width);
--ifm-button-color: var(--ifm-font-color-base-inverse);
--ifm-button-font-weight: var(--ifm-font-weight-bold);
--ifm-button-padding-horizontal: 1.5rem;
--ifm-button-padding-vertical: 0.375rem;
--ifm-button-size-multiplier: 1;
--ifm-button-transition-duration: var(--ifm-transition-fast);
--ifm-button-border-radius: calc(var(--ifm-global-radius) * var(--ifm-button-size-multiplier));
--ifm-button-group-margin: 2px;
--ifm-card-background-color: var(--ifm-background-surface-color);
--ifm-card-border-radius: calc(var(--ifm-global-radius) * 2);
--ifm-card-horizontal-spacing: var(--ifm-global-spacing);
--ifm-card-vertical-spacing: var(--ifm-global-spacing);
--ifm-toc-border-color: var(--ifm-color-emphasis-300);
--ifm-toc-link-color: var(--ifm-color-content-secondary);
--ifm-toc-padding-vertical: 0.5rem;
--ifm-toc-padding-horizontal: 0.5rem;
--ifm-dropdown-background-color: var(--ifm-background-surface-color);
--ifm-dropdown-font-weight: var(--ifm-font-weight-semibold);
--ifm-dropdown-link-color: var(--ifm-font-color-base);
--ifm-dropdown-hover-background-color: var(--ifm-hover-overlay);
--ifm-footer-background-color: var(--ifm-color-emphasis-100);
--ifm-footer-color: inherit;
--ifm-footer-link-color: var(--ifm-color-emphasis-700);
--ifm-footer-link-hover-color: var(--ifm-color-primary);
--ifm-footer-link-horizontal-spacing: 0.5rem;
--ifm-footer-padding-horizontal: calc(var(--ifm-spacing-horizontal) * 2);
--ifm-footer-padding-vertical: calc(var(--ifm-spacing-vertical) * 2);
--ifm-footer-title-color: inherit;
--ifm-hero-background-color: var(--ifm-background-surface-color);
--ifm-hero-text-color: var(--ifm-color-emphasis-800);
--ifm-menu-color: var(--ifm-color-emphasis-700);
--ifm-menu-color-active: var(--ifm-color-primary);
--ifm-menu-color-background-active: var(--ifm-hover-overlay);
--ifm-menu-color-background-hover: var(--ifm-hover-overlay);
--ifm-menu-link-padding-horizontal: 1rem;
--ifm-menu-link-padding-vertical: 0.375rem;
--ifm-menu-link-sublist-icon: url(
data:image/svg + xml;utf8,
<svgxmlns="http://www.w3.org/2000/svg"width="16px"height="16px"viewBox="0 0 24 24"><pathfill="rgba(0,0,0,0.5)"d="M7.41 15.41L12 10.83l4.59 4.58L18 14l-6-6-6 6z"></path></svg>
);
--ifm-menu-link-sublist-icon-filter: none;
--ifm-navbar-background-color: var(--ifm-background-surface-color);
--ifm-navbar-height: 3.75rem;
--ifm-navbar-item-padding-horizontal: 1rem;
--ifm-navbar-item-padding-vertical: 0.25rem;
--ifm-navbar-link-color: var(--ifm-font-color-base);
--ifm-navbar-link-hover-color: var(--ifm-color-primary);
--ifm-navbar-link-active-color: var(--ifm-link-color);
--ifm-navbar-padding-horizontal: var(--ifm-spacing-horizontal);
--ifm-navbar-padding-vertical: calc(var(--ifm-spacing-vertical) * 0.5);
--ifm-navbar-shadow: var(--ifm-global-shadow-lw);
--ifm-navbar-search-input-background-color: var(--ifm-color-emphasis-200);
--ifm-navbar-search-input-color: var(--ifm-color-emphasis-800);
--ifm-navbar-search-input-placeholder-color: var(--ifm-color-emphasis-500);
--ifm-navbar-search-input-icon: url(
data:image/svg + xml;utf8,
<svgfill="currentColor"xmlns="http://www.w3.org/2000/svg"viewBox="0 0 16 16"height="16px"width="16px"><pathd="M6.02945,10.20327a4.17382,4.17382,0,1,1,4.17382-4.17382A4.15609,4.15609,0,0,1,6.02945,10.20327Zm9.69195,4.2199L10.8989,9.59979A5.88021,5.88021,0,0,0,12.058,6.02856,6.00467,6.00467,0,1,0,9.59979,10.8989l4.82338,4.82338a.89729.89729,0,0,0,1.29912,0,.89749.89749,0,0,0-.00087-1.29909Z"/></svg>
);
--ifm-navbar-sidebar-width: 80vw;
--ifm-pagination-border-radius: calc(var(--ifm-global-radius) * var(--ifm-pagination-size-multiplier));
--ifm-pagination-color-active: var(--ifm-color-primary);
--ifm-pagination-font-size: 1rem;
--ifm-pagination-item-active-background: var(--ifm-hover-overlay);
--ifm-pagination-page-spacing: 0.0625rem;
--ifm-pagination-padding-horizontal: calc(var(--ifm-spacing-horizontal) * 1);
--ifm-pagination-padding-vertical: calc(var(--ifm-spacing-vertical) * 0.25);
--ifm-pagination-size-multiplier: 1;
--ifm-pagination-nav-border-radius: var(--ifm-global-radius);
--ifm-pagination-nav-color-hover: var(--ifm-color-primary);
--ifm-pills-color-active: var(--ifm-color-primary);
--ifm-pills-color-background-active: var(--ifm-hover-overlay);
--ifm-pills-spacing: 0.0625rem;
--ifm-tabs-color: var(--ifm-font-color-secondary);
--ifm-tabs-color-active: var(--ifm-color-primary);
--ifm-tabs-padding-horizontal: 1rem;
--ifm-tabs-padding-vertical: 1rem;
--ifm-tabs-spacing: 0.0625rem;
--ifm-scrollbar-size: 7px;
--ifm-scrollbar-track-background-color: #f1f1f1;
--ifm-scrollbar-thumb-background-color: #888;
--ifm-scrollbar-thumb-hover-background-color: #555;
}

View File

@@ -1,388 +0,0 @@
/**
* Any CSS included here will be global. The classic template
* bundles Infima by default. Infima is a CSS framework designed to
* work well for content-centric websites.
*/
/* You can override the default Infima variables here. */
@import url("https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,500;1,400&family=Inter:wght@400;500;600&display=swap");
:root {
--ifm-color-primary: #3578e5;
--ifm-color-primary-dark: #1d68e1;
--ifm-color-primary-darker: #1b62d4;
--ifm-color-primary-darkest: #1751af;
--ifm-color-primary-light: #4e89e8;
--ifm-color-primary-lighter: #5a91ea;
--ifm-color-primary-lightest: #80aaef;
--collapse-button-bg-color-dark: #2e333a;
--ifm-code-font-size: 95%;
--ifm-h1-font-size: 1.75rem;
--ifm-h2-font-size: 1.5rem;
--ifm-h3-font-size: 1.25rem;
--ifm-h4-font-size: 1rem;
--ifm-h5-font-size: 0.875rem;
--ifm-h6-font-size: 0.85rem;
/* --ifm-table-border-color: var(--ifm-color-emphasis-100); */
/* --ifm-toc-border-color: none; */
--ifm-toc-border-width: 1px;
/* --ifm-menu-color: var(--ifm-color-emphasis-900); */
--ifm-menu-color-background-active: transparent;
--ifm-menu-color-background-hover: transparent;
--ifm-global-shadow-lw: 0 1px 10px 0 rgba(0, 0, 0, 0.1);
--ifm-global-shadow-md: 0 5px 40px rgba(0, 0, 0, 0.1);
--ifm-global-shadow-tl: 0 12px 28px 0 rgba(0, 0, 0, 0.2), 0 2px 4px 0 rgba(0, 0, 0, 0.1);
--ifm-global-spacing: 1.5rem;
/* --ifm-navbar-background-color: rgba(255, 0.2); */
}
html[data-theme="dark"] {
--ifm-color-primary: white;
--ifm-color-primary-dark: #5a91ea;
--ifm-navbar-background-color: #191b1f;
--ifm-global-shadow-md: 0 5px 4px rgba(255, 255, 255, 0.448);
}
html[data-theme="light"] {
--ifm-color-primary: black;
}
.html {
font-family: "Inter", system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif,
BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
font-size: 16px;
font-variant: none;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
font-feature-settings: "ss01" on, "ss02" on, "cv01" on, "cv03" on;
font-weight: 400;
}
.markdown a {
color: #3578e5;
}
p {
line-height: 1.5rem;
font-weight: 400;
}
hr {
border-bottom-width: 0px;
border-top-width: 1px;
border-color: var(--ifm-color-emphasis-200);
}
h1,
h2,
h3,
h4,
h5 {
/* font-family: "Archivo", sans-serif; */
font-weight: 500;
}
h1 {
font-size: 32px;
}
h2 {
font-size: 24px !important;
}
h3 {
font-size: 20px !important;
}
h4 {
font-size: 20px !important;
}
h4 {
font-size: 16px !important;
}
.menu__link--sublist:after {
background: var(--ifm-menu-link-sublist-icon) 50% / 1.5rem 1.5rem;
/* color: var( --ifm-color-primary); */
}
.navbar {
align-items: center;
}
html[data-theme="dark"] .navbar {
/* background-color: none; */
border-bottom: var(--ifm-toc-border-color) 1px solid;
}
html[data-theme="light"] .navbar {
/* background-color: none; */
border-bottom: var(--ifm-toc-border-color) 1px solid;
}
.container {
padding: 0px;
/* margin: 4rem auto 0px; */
max-width: 90% !important;
}
.container.padding-top--md {
padding-top: 2rem !important;
}
.react-toggle-track {
background-color: var(--ifm-color-emphasis-100) !important;
}
.react-toggle-thumb {
background-color: var(--ifm-color-emphasis-200) !important;
}
.react-toggle-thumb:hover {
box-shadow: none !important;
}
.navbar__title {
/* font-family: "Archivo", sans-serif; */
color: var(--ifm-color-primary);
font-weight: 500;
}
.navbar__link {
/* font-family: "Archivo", sans-serif; */
color: var(--ifm-color-primary);
font-weight: 400;
}
.navbar__logo {
height: 20px;
width: 20px;
}
.menu__link {
font-size: 16px;
font-weight: 400;
}
html[data-theme="dark"] .navbar__logo {
filter: invert(100%) sepia(0%) saturate(7500%) hue-rotate(337deg) brightness(112%) contrast(104%);
}
.docusaurus-highlight-code-line {
background-color: rgb(72, 77, 91);
display: block;
margin: 0 calc(-1 * var(--ifm-pre-padding));
padding: 0 var(--ifm-pre-padding);
color: var(--ifm-color-secondary-darker);
}
.badge {
margin-bottom: 16px;
}
.badge--secondary {
--ifm-badge-background-color: var(--ifm-color-emphasis-0);
--ifm-badge-border-color: var(--ifm-badge-background-color);
color: var(--ifm-color-base);
}
html[data-theme="light"] .DocSearch {
/* --docsearch-primary-color: var(--ifm-color-primary); */
/* --docsearch-text-color: var(--ifm-font-color-base); */
--docsearch-muted-color: var(--ifm-color-emphasis-900);
--docsearch-container-background: rgba(94, 100, 112, 0.7);
/* Modal */
--docsearch-modal-background: var(--ifm-color-secondary-lighter);
/* Search box */
--docsearch-searchbox-background: var(--ifm-color-secondary);
--docsearch-searchbox-focus-background: var(--ifm-color-white);
/* Hit */
--docsearch-hit-color: var(--ifm-font-color-base);
--docsearch-hit-active-color: var(--ifm-color-emphasis-700);
--docsearch-hit-background: var(--ifm-color-white);
--docsearch-searchbox-background: rgba(0, 0, 0, 0.05);
--docsearch-highlight-color: var(--ifm-color-emphasis-100);
/* Footer */
--docsearch-footer-background: var(--ifm-color-white);
--docsearch-searchbox-shadow: none;
}
html[data-theme="dark"] .DocSearch {
/* --docsearch-text-color: var(--ifm-font-color-100); */
--docsearch-muted-color: var(--ifm-color-secondary-darkest);
--docsearch-container-background: rgba(47, 55, 69, 0.7);
/* Modal */
--docsearch-modal-background: var(--ifm-background-color);
/* Search box */
--docsearch-searchbox-background: var(--ifm-background-color);
--docsearch-searchbox-focus-background: var(--ifm-color-black);
/* Hit */
--docsearch-hit-color: var(--ifm-font-color-base);
--docsearch-hit-active-color: var(--ifm-color-emphasis-700);
--docsearch-hit-background: var(--ifm-color-emphasis-100);
--docsearch-searchbox-background: rgba(0, 0, 0, 0.2);
/* Footer */
--docsearch-footer-background: var(--ifm-background-surface-color);
--docsearch-key-gradient: linear-gradient(
-26.5deg,
var(--ifm-color-emphasis-200) 0%,
var(--ifm-color-emphasis-100) 100%
);
--docsearch-searchbox-shadow: inset 0 0 0 2px var(--ifm-color-emphasis-200);
}
html[data-theme="light"] .DocSearch-Hit {
background-color: transparent;
}
html[data-theme="light"] .DocSearch-Hit :focus {
background-color: var(--ifm-color-emphasis-100);
}
html[data-theme="light"] .DocSearch-Hit :hover {
background-color: var(--ifm-color-emphasis-100);
}
html[data-theme="light"] .DocSearch-Hit {
background-color: transparent;
}
html[data-theme="dark"] .DocSearch-Hit {
background-color: transparent;
}
html[data-theme="dark"] .DocSearch-Hit :focus {
background-color: var(--ifm-color-emphasis-100);
}
html[data-theme="dark"] .DocSearch-Hit :hover {
background-color: var(--ifm-color-emphasis-100);
}
html[data-theme="dark"] .DocSearch-Hit a :hover {
background-color: transparent;
}
html[data-theme="dark"] .DocSearch-Hit a {
background-color: var(--ifm-color-emphasis-0);
}
.react-toggle-thumb :hover {
border: none;
outline: none;
box-shadow: none;
}
.react-toggle-thumb :focus {
border: none;
outline: none;
box-shadow: none;
}
.react-toggle-thumb :active {
border: none;
outline: none;
box-shadow: none;
}
.menu {
/* background-color: var(--ifm-color-emphasis-0); */
padding: 1.5rem 1rem !important;
}
.dropdown__menu {
box-shadow: 0 5px 40px rgba(0, 0, 0, 0.1);
}
.menu__link:hover {
text-decoration: underline;
}
.menu__link--active {
font-weight: 600;
}
.table-of-contents {
opacity: 0.4;
}
.table-of-contents:hover {
opacity: 1;
}
.table-of-contents__link:hover {
text-decoration: underline;
}
.navbar__inner {
flex-wrap: unset;
}
.navbar__item {
display: none;
}
.navbar__item.dropdown {
display: inline-block;
}
.navbar__item.persistent {
display: inline-block;
}
.navbar__item.V2_active.V2 {
display: inline-block;
}
.navbar__item.V1_active.V1 {
display: inline-block;
}
.menu__link.V2_active,
.V1_active {
display: none;
}
.menu__list-item--collapsed .menu__link {
display: flex;
}
.menu__link.persistent {
display: flex;
}
.menu__link.V2_active.V2 {
display: flex;
}
.menu__link.V1_active.V1 {
display: flex;
}
@media (max-width: 960px) {
.menu {
/* background-color: var(--ifm-color-emphasis-0); */
padding: initial !important;
}
.container {
max-width: 100% !important;
padding: 1rem;
}
.container.padding-top--md {
padding-top: initial;
}
.navbar__item {
display: none !important;
}
.footer {
display: none;
}
}

View File

@@ -1,239 +0,0 @@
import Link from "@docusaurus/Link"
import styled from "@emotion/styled"
import Layout from "@theme/Layout"
import React from "react"
export const semaphoreComponents = [
{
title: "semaphore-circuits",
href: "https://github.com/appliedzkp/semaphore/tree/main/circuits"
},
{
title: "semaphore-contracts",
href: "https://github.com/appliedzkp/semaphore/tree/main/contracts"
},
{
title: "@zk-kit/identity",
href: "https://github.com/appliedzkp/zk-kit/tree/main/packages/identity"
},
{
title: "@zk-kit/protocols",
href: "https://github.com/appliedzkp/zk-kit/tree/main/packages/protocols"
}
]
export const pseProjects = [
{
title: "ZK-kit",
text: "A monorepo of reusable JS libraries for zero-knowledge technologies.",
to: "https://github.com/appliedzkp/zk-kit"
},
{
title: "Interep",
text: "A system that allows DApps or services to verify users' reputation without exposing their identities.",
to: "https://github.com/interep-project"
}
]
const Container = styled.div`
display: flex;
flex-direction: column;
margin: 0 auto;
margin-bottom: 4rem;
`
const Row = styled.div`
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-gap: 16px;
justify-content: center;
margin: 0 auto;
padding: 1rem 0;
max-width: 960px;
@media (max-width: 960px) {
grid-template-columns: 1fr;
padding: 1rem;
max-width: 100%;
margin: 0 1rem;
}
@media (max-width: 640px) {
grid-template-columns: 1fr;
}
`
const TwoRow = styled(Row)`
grid-template-columns: 1fr 1fr;
grid-gap: 48px;
@media (max-width: 960px) {
grid-template-columns: 1fr;
}
@media (max-width: 640px) {
grid-template-columns: 1fr;
}
`
const ButtonGroup = styled.div`
display: flex;
`
const Button = styled.div`
padding: 0.6rem 1rem;
margin: 0 0.3rem;
cursor: pointer;
border-radius: 10px;
border: 1px solid var(--ifm-color-emphasis-200);
&:hover {
border: 1px solid var(--ifm-color-emphasis-400);
}
`
const Card = styled.div`
display: flex;
max-height: 250px;
min-width: 350px;
padding: 1.1rem;
flex-direction: column;
justify-content: center;
cursor: pointer;
border: 1px solid transparent;
border-bottom: 1px solid var(--ifm-color-emphasis-200);
/* flex: 1 1 0px; */
&:hover {
border-bottom: 1px solid var(--ifm-color-emphasis-400);
}
@media (max-width: 960px) {
width: 100%;
}
`
const LinkRow = styled.div`
width: 100%;
align-items: center;
justify-content: space-between;
display: flex;
flex-direction: row;
a h3 {
color: black !important;
}
`
const DocsHeader = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
overflow: hidden;
width: 100%;
position: relative;
`
const StyledGithubIcon = styled.div`
svg {
fill: var(--ifm-font-color-base);
}
`
export default function Home() {
return (
<Layout title={`Semaphore Docs`} description="Technical Documentation For The Semaphore Protocol.">
<Container>
<DocsHeader>
<div
style={{
padding: "4rem 0 ",
textAlign: "center",
display: "flex",
flexDirection: "column",
alignItems: "center"
}}
>
<h1 style={{ margin: "20px", fontSize: "36px" }}> Semaphore</h1>
<p
style={{
maxWidth: "700px",
fontSize: "20px"
}}
>
A privacy gadget for creating anonymous proof of membership on Ethereum.
</p>
<ButtonGroup>
<Link style={{ textDecoration: "none" }} href="/docs/introduction">
<Button>Introduction</Button>
</Link>
<Link style={{ textDecoration: "none" }} href="/docs/quick-setup">
<Button>Quick setup</Button>
</Link>
<Link style={{ textDecoration: "none" }} href="/docs/credits">
<Button>Credits</Button>
</Link>
</ButtonGroup>
</div>
</DocsHeader>
<hr />
<TwoRow
style={{
gap: "56px",
marginTop: "4rem"
}}
>
<div>
<h2>Developer Links</h2>
<p>Learn more about the code of the various Semaphore components.</p>
{semaphoreComponents.map((action) => (
<Link style={{ textDecoration: "none" }} href={action.href}>
<Card key={action.title} style={{ marginBottom: "1rem" }}>
<LinkRow>
<StyledGithubIcon style={{ display: "flex", alignItems: "center" }}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120.78 117.79" style={{ width: "24px" }}>
<defs></defs>
<title>Github</title>
<g id="Layer_2" data-name="Layer 2">
<g id="Layer_1-2" data-name="Layer 1">
<path d="M60.39,0A60.39,60.39,0,0,0,41.3,117.69c3,.56,4.12-1.31,4.12-2.91,0-1.44-.05-6.19-.08-11.24C28.54,107.19,25,96.42,25,96.42c-2.75-7-6.71-8.84-6.71-8.84-5.48-3.75.41-3.67.41-3.67,6.07.43,9.26,6.22,9.26,6.22,5.39,9.23,14.13,6.57,17.57,5,.55-3.9,2.11-6.56,3.84-8.07C36,85.55,21.85,80.37,21.85,57.23A23.35,23.35,0,0,1,28.08,41c-.63-1.52-2.7-7.66.58-16,0,0,5.07-1.62,16.61,6.19a57.36,57.36,0,0,1,30.25,0C87,23.42,92.11,25,92.11,25c3.28,8.32,1.22,14.46.59,16a23.34,23.34,0,0,1,6.21,16.21c0,23.2-14.12,28.3-27.57,29.8,2.16,1.87,4.09,5.55,4.09,11.18,0,8.08-.06,14.59-.06,16.57,0,1.61,1.08,3.49,4.14,2.9A60.39,60.39,0,0,0,60.39,0Z" />
<path d="M22.87,86.7c-.13.3-.6.39-1,.19s-.69-.61-.55-.91.61-.39,1-.19.69.61.54.91Z" />
<path d="M25.32,89.43c-.29.27-.85.14-1.24-.28a.92.92,0,0,1-.17-1.25c.3-.27.84-.14,1.24.28s.47,1,.17,1.25Z" />
<path d="M27.7,92.91c-.37.26-1,0-1.35-.52s-.37-1.18,0-1.44,1,0,1.35.51.37,1.19,0,1.45Z" />
<path d="M31,96.27A1.13,1.13,0,0,1,29.41,96c-.53-.49-.68-1.18-.34-1.54s1-.27,1.56.23.68,1.18.33,1.54Z" />
<path d="M35.46,98.22c-.15.47-.82.69-1.51.49s-1.13-.76-1-1.24.82-.7,1.51-.49,1.13.76,1,1.24Z" />
<path d="M40.4,98.58c0,.5-.56.91-1.28.92s-1.3-.38-1.31-.88.56-.91,1.29-.92,1.3.39,1.3.88Z" />
<path d="M45,97.8c.09.49-.41,1-1.12,1.12s-1.35-.17-1.44-.66.42-1,1.12-1.12,1.35.17,1.44.66Z" />
</g>
</g>
</svg>
<h3 style={{ marginBottom: "0rem", marginLeft: "16px" }}>{action.title}</h3>
</StyledGithubIcon>
</LinkRow>
</Card>
</Link>
))}
</div>
<div>
<h2>Privacy and Scaling Explorations</h2>
<p>Discover other interesting projects of our team.</p>
<div>
{pseProjects.map((action) => (
<Link style={{ textDecoration: "none" }} key={action.title} to={action.to}>
<Card key={action.title} style={{ marginBottom: "1rem" }}>
<LinkRow>
<div style={{ display: "flex", alignItems: "center" }}>
<h3 style={{ marginBottom: "0rem" }}>{action.title}</h3>
</div>
</LinkRow>
<p style={{ marginBottom: "0rem" }}>{action.text}</p>
</Card>
</Link>
))}
</div>
</div>
</TwoRow>
</Container>
</Layout>
)
}

View File

@@ -1,15 +0,0 @@
import React from "react"
import OriginalNavBarItem from "@theme-original/NavbarItem"
import { useLocation } from "@docusaurus/router"
export default function NavbarItem(props) {
const { pathname } = useLocation()
let [, , version] = pathname.split("/")
return (
<>
<OriginalNavBarItem {...props} className={props.className + " " + version} />
</>
)
}

View File

1
docs/static/CNAME vendored
View File

@@ -1 +0,0 @@
semaphore.appliedzkp.org

View File

@@ -1,3 +0,0 @@
<svg width="307" height="297" viewBox="0 0 307 297" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M79.6904 63.6726L191.365 0.301019C191.901 -0.00282284 192.535 -0.0804208 193.128 0.0854393L304.479 31.2364C306.468 31.7928 306.784 34.4801 304.978 35.482L160.442 115.672C159.321 116.294 158.921 117.709 159.549 118.826L223.992 233.345C224.619 234.459 224.223 235.87 223.108 236.494L115.628 296.705C115.096 297.004 114.467 297.079 113.878 296.915L1.69033 265.623C-0.304074 265.066 -0.616403 262.37 1.19806 261.372L142.351 183.779C143.479 183.159 143.883 181.736 143.248 180.616L78.8201 66.8205C78.1918 65.7108 78.5813 64.3019 79.6904 63.6726ZM104.391 68.5965L180.084 25.8849C182.163 24.7122 184.438 27.076 183.188 29.1083L140.865 97.8769C140.143 99.0502 138.561 99.3349 137.475 98.487L104.105 72.43C102.806 71.4157 102.956 69.4065 104.391 68.5965ZM121.115 275.355L197.913 232.02C199.702 231.01 199.382 228.342 197.406 227.784L137.532 210.86C136.302 210.512 135.024 211.229 134.679 212.459L117.755 272.717C117.198 274.702 119.32 276.367 121.115 275.355Z" fill="black"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

View File

@@ -1,7 +0,0 @@
{
// This file is not used in compilation. It is here just for a nice editor experience.
"extends": "@tsconfig/docusaurus/tsconfig.json",
"compilerOptions": {
"baseUrl": "."
}
}

View File

@@ -1,17 +0,0 @@
---
sidebar_position: 8
---
# Security audit
The [Ethereum Foundation](https://ethereum.org/) and [POA
Network](https://www.poa.network/) commissioned [ABDK
Consulting](https://www.abdk.consulting) to audit the source code of Semaphore
as well as relevant circuits in
[circomlib](https://github.com/iden3/circomlib), which contains components
which the Semaphore zk-SNARK uses.
The summary of the audit results can be found
[here](https://github.com/appliedzkp/semaphore/tree/master/audit). After three
rounds of fixes, all security and performance issues were fixed, and the few
remaining issues are minor and do not affect security.

View File

@@ -1,105 +0,0 @@
---
sidebar_position: 5
---
# Contract API
## Constructor
**Contract ABI**:
`constructor(uint8 _treeLevels, uint232 _firstExternalNullifier)`
- `_treeLevels`: The depth of the identity tree.
- `_firstExternalNullifier`: The first identity nullifier to add.
The depth of the identity tree determines how many identity commitments may be
added to this contract: `2 ^ _treeLevels`. Once the tree is full, further
insertions will fail with the revert reason `IncrementalMerkleTree: tree is full`.
The first external nullifier will be added as an external nullifier to the
contract, and this external nullifier will be active once the deployment
completes.
## Add, deactivate, or reactivate external nullifiiers
**Contract ABI**:
`addExternalNullifier(uint232 _externalNullifier)`
Adds an external nullifier to the contract. Only the owner can do this.
This external nullifier is active once it is added.
- `_externalNullifier`: The new external nullifier to set.
`deactivateExternalNullifier(uint232 _externalNullifier)`
- `_externalNullifier`: The existing external nullifier to deactivate.
Deactivate an external nullifier. The external nullifier must already be active
for this function to work. Only the owner can do this.
`reactivateExternalNullifier(uint232 _externalNullifier)`
Reactivate an external nullifier. The external nullifier must already be
inactive for this function to work. Only the owner can do this.
- `_externalNullifier`: The deactivated external nullifier to reactivate.
## Insert identities
**Contract ABI**:
`function insertIdentity(uint256 _identityCommitment)`
- `_identity_commitment`: The user's identity commitment, which is the hash of
their public key and their identity nullifier (a random 31-byte value). It
should be the output of a Pedersen hash. It is the responsibility of the
caller to verify this.
**Off-chain `libsemaphore` helper functions**:
Use `genIdentity()` to generate an `Identity` object, and
`genIdentityCommitment(identity: Identity)` to generate the
`_identityCommitment` value to pass to the contract.
To convert `identity` to a string and back, so that you can store it in a
database or somewhere safe, use `serialiseIdentity()` and
`unSerialiseIdentity()`.
See the [Usage section on inserting
identities](./usage#insert-identities) for more information.
## Broadcast signals
**Contract ABI**:
```
broadcastSignal(
bytes memory _signal,
uint256[8] memory _proof,
uint256 _root,
uint256 _nullifiersHash,
uint232 _externalNullifier
)
```
- `_signal`: the signal to broadcast.
- `_proof`: a zk-SNARK proof (see below).
- `_root`: The root of the identity tree, where the user's identity commitment
is the last-inserted leaf.
- `_nullifiersHash`: A uniquely derived hash of the external nullifier, user's
identity nullifier, and the Merkle path index to their identity commitment.
It ensures that a user cannot broadcast a signal with the same external
nullifier more than once.
- `_externalNullifier`: The external nullifier at which the signal is
broadcast.
**Off-chain `libsemaphore` helper functions**:
Use `libsemaphore`'s `genWitness()`, `genProof()`, `genPublicSignals()` and
finally `genBroadcastSignalParams()` to generate the parameters to the
contract's `broadcastSignal()` function.
See the [Usage section on broadcasting
signals](./usage#broadcast-signals) for more information.

View File

@@ -1,33 +0,0 @@
---
sidebar_position: 9
---
# Credits
- Barry WhiteHat
- Chih Cheng Liang
- Kobi Gurkan
- Koh Wei Jie
- Harry Roberts
Many thanks to:
- ABDK Consulting
- Jordi Baylina / iden3
- POA Network
- PepperSec
- Ethereum Foundation
# Resources
[To Mixers and Beyond: presenting Semaphore, a privacy gadget built on Ethereum](https://medium.com/coinmonks/to-mixers-and-beyond-presenting-semaphore-a-privacy-gadget-built-on-ethereum-4c8b00857c9b) - Koh Wei Jie
[Privacy in Ethereum](https://www.youtube.com/watch?v=maDHYyj30kg) - Barry WhiteHat at the Taipei Ethereum Meetup
[Snarks for mixing, signaling and scaling by](https://www.youtube.com/watch?v=lv6iK9qezBY) - Barry WhiteHat at Devcon 4
[Privacy in Ethereum](https://www.youtube.com/watch?v=zBUo7G95wYE) - Barry WhiteHat at Devcon 5
[A trustless Ethereum mixer using zero-knowledge signalling](https://www.youtube.com/watch?v=GzVT16lFOHU) - Koh Wei Jie and Barry WhiteHat at Devcon 5
[Hands-on Applications of Zero-Knowledge Signalling](https://www.youtube.com/watch?v=7wd2aAN2jXI) - Koh Wei Jie at Devcon 5

View File

@@ -1,137 +0,0 @@
---
sidebar_position: 2
---
# How it works
## Inserting identities
An identity is comprised of the following information:
1. An [EdDSA](https://en.wikipedia.org/wiki/EdDSA) private key. Note that it is
_not_ an Ethereum private key.
2. An identity nullifier, whih is a random 32-byte value.
3. An identity trapdoor, whih is a random 32-byte value.
An identity commitment is the Pedersen hash of:
1. The public key associated with the identity's private key.
2. The identity nullifier.
3. The identity trapdoor.
To register an identity, the user must insert their identity commitment into
Semaphore's identity tree. They can do this by calling the Semaphore contract's
`insertIdentity(uint256 _identityCommitment)` function. See the [API
reference](./contract-api) for more information.
## Broadcasting signals
To broadcast a signal, the user must invoke this Semaphore contract function:
```
broadcastSignal(
bytes memory _signal,
uint256[8] memory _proof,
uint256 _root,
uint256 _nullifiersHash,
uint232 _externalNullifier
)
```
- `_signal`: the signal to broadcast.
- `_proof`: a zk-SNARK proof (see below).
- `_root`: The root of the identity tree, where the user's identity commitment
is the last-inserted leaf.
- `_nullifiersHash`: A uniquely derived hash of the external nullifier, user's
identity nullifier, and the Merkle path index to their identity commitment.
It ensures that a user cannot broadcast a signal with the same external
nullifier more than once.
- `_externalNullifier`: The external nullifier at which the signal is
broadcast.
To zk-SNARK proof must satisfy the constraints created by Semaphore's zk-SNARK
circuit as described below:
### The zk-SNARK circuit
The
[semaphore-base.circom](https://github.com/appliedzkp/semaphore/blob/master/circuits/circom/semaphore-base.circom)
circuit helps to prove the following:
### That the identity commitment exists in the Merkle tree
**Private inputs:**
- `identity_pk`: the user's EdDSA public key
- `identity_nullifier`: a random 32-byte value which the user should save
- `identity_trapdoor`: a random 32-byte value which the user should save
- `identity_path_elements`: the values along the Merkle path to the
user's identity commitment
- `identity_path_index[n_levels]`: the direction (left/right) per tree level
corresponding to the Merkle path to the user's identity commitment
**Public inputs:**
- `root`: The Merkle root of the identity tree
**Procedure:**
The circuit hashes the public key, identity nullifier, and identity trapdoor to
generate an **identity commitment**. It then verifies the Merkle proof against
the Merkle root and the identity commitment.
### That the signal was only broadcasted once
**Private inputs:**
- `identity_nullifier`: as above
- `identity_path_index`: as above
**Public inputs:**
- `external_nullifier`: the 29-byte external nullifier - see above
- `nullifiers_hash`: the hash of the identity nullifier, external nullifier,
and Merkle path index (`identity_path_index`)
**Procedure:**
The circuit hashes the given identity nullifier, external nullifier, and Merkle
path index, and checks that it matches the given nullifiers hash. Additionally,
the smart contract ensures that it has not previously seen this nullifiers
hash. This way, double-signalling is impossible.
### That the signal was truly broadcasted by the user who generated the proof
**Private inputs:**
- `identity_pk`: as above
- `auth_sig_r`: the `r` value of the signature of the signal
- `auth_sig_s`: the `s` value of the signature of the signal
**Public inputs:**
- `signal_hash`: the hash of the signal
- `external_nullifier`: the 29-byte external nullifier - see above
**Procedure:**
The circuit hashes the signal hash and the external nullifier, and verifies
this output against the given public key and signature. This ensures the
authenticity of the signal and prevents front-running attacks.
## Cryptographic primitives
Semaphore uses MiMC for the Merkle tree, Pedersen commmitments for the identity
commitments, Blake2 for the nullifiers hash, and EdDSA for the signature.
MiMC is a relatively new hash function. We use the recommended MiMC
construction from [Albrecht et al](https://eprint.iacr.org/2016/492.pdf), and
there is a prize to break MiMC at [http://mimchash.org](http://mimchash.org)
which has not been claimed yet.
We have also implemented a version of Semaphore which uses the Poseidon hash
function for the Merkle tree and EdDSA signature verification. This may have
better security than MiMC, allows identity insertions to save about 20% gas,
and roughly halves the proving time. Note, however, that the Poseidon-related
circuits and EVM bytecode generator have not been audited, so use it with
caution. To use it, checkout the `feat/poseidon` branch of this repository.

View File

@@ -1,245 +0,0 @@
---
sidebar_position: 6
---
# libsemaphore
[`libsemaphore`](https://www.npmjs.com/package/libsemaphore) is a helper
library for Semaphore written in Typescript. Any dApp written in Javascript or
Typescript should use it as it provides useful abstractions over common tasks
and objects, such as identities and proof generation.
Note that only v1.0.14 and above works with the Semaphore code in this
repository. v0.0.x is compatible with the pre-audited Semaphore code.
## Available types, interfaces, and functions
### Types
**`SnarkBigInt`**
A big integer type compatible with the `snarkjs` library. Note that it is not
advisable to mix variables of this type with `bigNumber`s or `BigInt`s.
Encapsulates `snarkjs.bigInt`.
**`EddsaPrivateKey`**
An [EdDSA](https://tools.ietf.org/html/rfc8032) private key which should be 32
bytes long. Encapsulates a [`Buffer`](https://nodejs.org/api/buffer.html).
**`EddsaPublicKey`**
An EdDSA public key. Encapsulates an array of `SnarkBigInt`s.
**`SnarkProvingKey`**
A proving key, which when used with a secret _witness_, generates a zk-SNARK
proof about said witness. Encapsulates a `Buffer`.
**`SnarkVerifyingKey`**
A verifying key which when used with public inputs to a zk-SNARK and a
`SnarkProof`, can prove the proof's validity. Encapsulates a `Buffer`.
**`SnarkWitness`**
The secret inputs to a zk-SNARK. Encapsulates an array of `SnarkBigInt`s.
**`SnarkPublicSignals`**
The public inputs to a zk-SNARK. Encapsulates an array of `SnarkBigInt`s.
### Interfaces
**`EddsaKeyPair`**
Encapsulates an `EddsaPublicKey` and an `EddsaPrivateKey`.
```ts
interface EddsaKeyPair {
pubKey: EddsaPublicKey
privKey: EddsaPrivateKey
}
```
**`Identity`**
Encapsulates all information required to generate an identity commitment, and
is crucial to creating `SnarkProof`s to broadcast signals.
```ts
interface Identity {
keypair: EddsaKeyPair
identityNullifier: SnarkBigInt
identityTrapdoor: SnarkBigInt
}
```
**`SnarkProof`**
Note that `broadcastSignal()` accepts a `uint256[8]` array for its `_proof`
parameter. See `genBroadcastSignalParams()`.
```ts
interface SnarkProof {
pi_a: SnarkBigInt[]
pi_b: SnarkBigInt[][]
pi_c: SnarkBigInt[]
}
```
### Functions
**`genPubKey(privKey: EddsaPrivateKey): EddsaPublicKey`**
Generates a public EdDSA key from a supplied private key. To generate a private
key, use `crypto.randomBytes(32)` where `crypto` is the built-in Node or
browser module.
**`genIdentity(): Identity`**
This is a convenience function to generate a fresh and random `Identity`. That
is, the 32-byte private key for the `EddsaKeyPair` is randomly generated, as
are the distinct 31-byte identity nullifier and the 31-byte identity trapdoor
values.
**`serialiseIdentity(identity: Identity): string`**
Converts an `Identity` into a JSON string which looks like this:
```text
["e82cc2b8654705e427df423c6300307a873a2e637028fab3163cf95b18bb172e","a02e517dfb3a4184adaa951d02bfe0fe092d1ee34438721d798db75b8db083","15c6540bf7bddb0616984fccda7e954a0fb5ea4679ac686509dc4bd7ba9c3b"]
```
You can also spell this function as `serializeIdentity`.
To convert this string back into an `Identity`, use `unSerialiseIdentity()`.
**`unSerialiseIdentity(string: serialisedId): Identity`**
Converts the `string` output of `serialiseIdentity()` to an `Identity`.
You can also spell this function as `unSerializeIdentity`.
**`genIdentityCommitment(identity: Identity): SnarkBigInt`**
Generates an identity commitment, which is the hash of the public key, the
identity nullifier, and the identity trapdoor.
**`async genProof(witness: SnarkWitness, provingKey: SnarkProvingKey): SnarkProof`**
Generates a `SnarkProof`, which can be sent to the Semaphore contract's
`broadcastSignal()` function. It can also be verified off-chain using
`verifyProof()` below.
**`genPublicSignals(witness: SnarkWitness, circuit: SnarkCircuit): SnarkPublicSignals`**
Extracts the public signals to be supplied to the contract or `verifyProof()`.
**`verifyProof(verifyingKey: SnarkVerifyingKey, proof: SnarkProof, publicSignals: SnarkPublicSignals): boolean`**
Returns `true` if the given `proof` is valid, given the correct verifying key
and public signals.
Returns `false` otherwise.
**`signMsg(privKey: EddsaPrivateKey, msg: SnarkBigInt): EdDSAMiMcSpongeSignature)`**
Encapsualtes `circomlib.eddsa.signMiMCSponge` to sign a message `msg` using private key `privKey`.
**`verifySignature(msg: SnarkBigInt, signature: EdDSAMiMcSpongeSignature, pubKey: EddsaPublicKey)`: boolean**
Returns `true` if the cryptographic `signature` of the signed `msg` is from the
private key associated with `pubKey`.
Returns `false` otherwise.
**`setupTree(levels: number, prefix: string): MerkleTree`**
Returns a Merkle tree created using
[`semaphore-merkle-tree`](https://www.npmjs.com/package/semaphore-merkle-tree)
with the same number of levels which the Semaphore zk-SNARK circuit expects.
This tree is also configured to use `MimcSpongeHasher`, which is also what the
circuit expects.
`levels` sets the number of levels of the tree. A tree with 20 levels, for
instance, supports up to 1048576 deposits.
**`genCircuit(circuitDefinition: any)`**
Returns a `new snarkjs.Circuit(circuitDefinition)`. The `circuitDefinition`
object should be the `JSON.parse`d result of the `circom` command which
converts a `.circom` file to a `.json` file.
**`async genWitness(...)`**
This function has the following signature:
```ts
const genWitness = async (
signal: string,
circuit: SnarkCircuit,
identity: Identity,
idCommitments: SnarkBigInt[] | BigInt[] | ethers.utils.BigNumber[],
treeDepth: number,
externalNullifier: SnarkBigInt,
)
```
- `signal` is the string you wish to broadcast.
- `circuit` is the output of `genCircuit()`.
- `identity` is the `Identity` whose identity commitment you want to prove is
in the set of registered identities.
- `idCommitments` is an array of registered identity commmitments; i.e. the
leaves of the tree.
- `treeDepth` is the number of levels which the Merkle tree used has
- `externalNullifier` is the current external nullifier
It returns an object as such:
- `witness`: The witness to pass to `genProof()`.
- `signal`: The computed signal for Semaphore. This is the hash of the
recipient's address, relayer's address, and fee.
- `signalHash`: The hash of the computed signal.
- `msg`: The hash of the external nullifier and the signal hash
- `signature`: The signature on the above msg.
- `tree`: The Merkle tree object after it has been updated with the identity commitment
- `identityPath`: The Merkle path to the identity commmitment
- `identityPathIndex`: The leaf index of the identity commitment
- `identityPathElements`: The elements along the above Merkle path
Only `witness` is essential to generate the proof; the other data is only
useful for debugging and additional off-chain checks, such as verifying the
signature and the Merkle tree root.
**`formatForVerifierContract = (proof: SnarkProof, publicSignals: SnarkPublicSignals`**
Converts the data in `proof` and `publicSignals` to strings and rearranges
elements of `proof.pi_b` so that `snarkjs`'s `verifier.sol` will accept it.
To be specific, it returns an object as such:
```ts
{
a: [ proof.pi_a[0].toString(), proof.pi_a[1].toString() ],
b: [
[ proof.pi_b[0][1].toString(), proof.pi_b[0][0].toString() ],
[ proof.pi_b[1][1].toString(), proof.pi_b[1][0].toString() ],
],
c: [ proof.pi_c[0].toString(), proof.pi_c[1].toString() ],
input: publicSignals.map((x) => x.toString()),
}
```
**`stringifyBigInts = (obj: any) => object`**
Encapsulates `snarkjs.stringifyBigInts()`. Makes it easy to convert `SnarkProof`s to JSON.
**`unstringifyBigInts = (obj: any) => object`**
Encapsulates `snarkjs.unstringifyBigInts()`. Makes it easy to convert JSON to `SnarkProof`s.
**`genExternalNullifier = (plaintext: string) => string`**
Each external nullifier must be at most 29 bytes large. This function
keccak-256-hashes a given `plaintext`, takes the last 29 bytes, and pads it
(from the start) with 0s, and returns the resulting hex string.

View File

@@ -1,68 +0,0 @@
---
sidebar_position: 3
---
# Quick start
Semaphore has been tested with Node 11.14.0. It will run with Node 12 LTE but
we highly recommend using Node 11.14.0 if you wish to develop on its source
code, as one of its dependencies, `script`, cannot compile when if you use Node 12.
Use [`nvm`](https://github.com/nvm-sh/nvm) to manage your Node version.
Clone this repository, install dependencies, and build the source code:
```bash
git clone git@github.com:kobigurk/semaphore.git && \
cd semaphore && \
npm i && \
npm run bootstrap && \
npm run build
```
**Note**: we use `lerna` to manage the `circuits`, `config`, and `contracts`
subpackages. Do not run `npm install` within any of these directories. Instead,
just run `npm run bootstrap` in the main directory.
Next, either download the compiled zk-SNARK circuit, proving key, and
verification key (note that these keys are for testing purposes, and not for
production, as there is no certainty that the toxic waste was securely
discarded).
To download the circuit, proving key, and verification key, run:
```bash
# Start from the base directory
./circuits/scripts/download_snarks.sh
```
To generate the above files locally instead, run:
```bash
# Start from the base directory
./circuits/scripts/build_snarks.sh
```
This process should take about 45 minutes.
Build the Solidity contracts (you need `solc` v 0.5.12 installed in your
`$PATH`):
```bash
# Start from the base directory
cd contracts && \
npm run compileSol
```
Run tests while still in the `contracts/` directory:
```bash
# The first command tests the Merkle tree contract and the second
# tests the Semaphore contract
npm run test-semaphore && \
npm run test-mt
```

View File

@@ -1,11 +0,0 @@
---
sidebar_position: 7
---
# Multi-party trusted setup
The Semaphore authors will use the [Perpetual Powers of
Tau](https://github.com/weijiekoh/perpetualpowersoftau/) ceremony and a random
beacon as phase 1 of the trusted setup.
More details about phase 2 will be released soon.

View File

@@ -1,144 +0,0 @@
---
sidebar_position: 4
---
# Usage
The Semaphore contract forms a base layer for other contracts to create
applications that rely on anonymous signaling.
First, you should ensure that the proving key, verification key, and circuit
file, which are static, be easily available to your users. These may be hosted
in a CDN or bundled with your application code.
The Semaphore team has not performed a trusted setup yet, so trustworthy
versions of these files are not available yet.
Untrusted versions of these files, however, may be obtained via the
`circuits/scripts/download_snarks.sh` script.
Next, to have full flexibility over Semaphore's mechanisms, write a Client
contract and set the owner of the Semaphore contract as the address of the
Client contract. You may also write a Client contract which deploys a Semaphore
contract in its constructor, or on the fly.
With the Client contract as the owner of the Semaphore contract, the Client
contract may call owner-only Semaphore functions such as
`addExternalNullifier()`.
## Add, deactivate, or reactivate external nullifiiers
These functions add, deactivate, and reactivate an external nullifier respectively.
As each identity can only signal once to an external nullifier, and as a signal
can only be successfully broadcasted to an active external nullifier, these
functions enable use cases where it is necessary to have multiple external
nullifiers or to activate and/or deactivate them.
Refer to the [high-level explanation of
Semaphore](https://medium.com/coinmonks/to-mixers-and-beyond-presenting-semaphore-a-privacy-gadget-built-on-ethereum-4c8b00857c9b)
for more details.
## Set broadcast permissioning
Note that `Semaphore.broadcastSignal()` is permissioned by default, so if you
wish for anyone to be able to broadcast a signal, the owner of the Semaphore
contract (either a Client contract or externally owned account) must first
invoke `setPermissioning(false)`.
See [SemaphoreClient.sol](https://github.com/appliedzkp/semaphore/blob/master/contracts/sol/SemaphoreClient.sol) for an example.
## Insert identities
To generate an identity commitment, use the `libsemaphore` functions
`genIdentity()` and `genIdentityCommitment()` Typescript (or Javascript)
functions:
```ts
const identity: Identity = genIdentity()
const identityCommitment = genIdentityCommitment(identity)
```
Be sure to store `identity` somewhere safe. The `serialiseIdentity()` function
can help with this:
`const serialisedId: string = serialiseIdentity(identity: Identity)`
It converts an `Identity` into a JSON string which looks like this:
```text
["e82cc2b8654705e427df423c6300307a873a2e637028fab3163cf95b18bb172e","a02e517dfb3a4184adaa951d02bfe0fe092d1ee34438721d798db75b8db083","15c6540bf7bddb0616984fccda7e954a0fb5ea4679ac686509dc4bd7ba9c3b"]
```
To convert this string back into an `Identity`, use `unSerialiseIdentity()`.
`const id: Identity = unSerialiseIdentity(serialisedId)`
## Broadcast signals
First obtain the leaves of the identity tree (in sequence, up to the user's
identity commitment, or more).
```ts
const leaves = <list of leaves>
```
Next, load the circuit from disk (or from a remote source):
```ts
const circuitPath = path.join(__dirname, "/path/to/circuit.json")
const cirDef = JSON.parse(fs.readFileSync(circuitPath).toString())
const circuit = genCircuit(cirDef)
```
Next, use `libsemaphore`'s `genWitness()` helper function as such:
```
const result = await genWitness(
signal,
circuit,
identity,
leaves,
num_levels,
external_nullifier,
)
```
- `signal`: a string which is the signal to broadcast.
- `circuit`: the output of `genCircuit()` (see above).
- `identity`: the user's identity as an `Identity` object.
- `leaves` the list of leaves in the tree (see above).
- `num_levels`: the depth of the Merkle tree.
- `external_nullifier`: the external nullifier at which to broadcast.
Load the proving key from disk (or from a remote source):
```ts
const provingKeyPath = path.join(__dirname, "/path/to/proving_key.bin")
const provingKey: SnarkProvingKey = fs.readFileSync(provingKeyPath)
```
Generate the proof (this takes about 30-45 seconds on a modern laptop):
```ts
const proof = await genProof(result.witness, provingKey)
```
Generate the `broadcastSignal()` parameters:
```ts
const publicSignals = genPublicSignals(result.witness, circuit)
const params = genBroadcastSignalParams(result, proof, publicSignals)
```
Finally, invoke `broadcastSignal()` with the parameters:
```ts
const tx = await semaphoreClientContract.broadcastSignal(
ethers.utils.toUtf8Bytes(signal),
params.proof,
params.root,
params.nullifiersHash,
external_nullifier,
{ gasLimit: 500000 }
)
```

View File

@@ -1,105 +0,0 @@
---
id: introduction
title: What Is Semaphore?
sidebar_position: 1
---
## Overview
[Semaphore](https://github.com/appliedzkp/semaphore) is a zero-knowledge gadget
which allows Ethereum users to prove their membership of a set which they had
previously joined without revealing their original identity. At the same time,
it allows users to signal their endorsement of an arbitrary string. It is
designed to be a simple and generic privacy layer for Ethereum dApps. Use cases
include private voting, whistleblowing, mixers, and anonymous authentication.
Finally, it provides a simple built-in mechanism to prevent double-signalling
or double-spending.
This gadget comprises of smart contracts and
[zero-knowledge](https://z.cash/technology/zksnarks/) components which work in
tandem. The Semaphore smart contract handles state, permissions, and proof
verification on-chain. The zero-knowledge components work off-chain to allow
the user to generate proofs, which allow the smart contract to update its state
if these proofs are valid.
For a formal description of Semaphore and its underlying cryptographic
mechanisms, also see this document
[here](https://github.com/appliedzkp/semaphore/tree/master/spec).
Semaphore is designed for smart contract and dApp developers, not end users.
Developers should abstract its features away in order to provide user-friendly
privacy.
Try a simple demo [here](https://weijiekoh.github.io/semaphore-ui/) or read a
high-level description of Semaphore
[here](https://medium.com/coinmonks/to-mixers-and-beyond-presenting-semaphore-a-privacy-gadget-built-on-ethereum-4c8b00857c9b).
## Basic features
In sum, Semaphore provides the ability to:
1. Register an identity in a smart contract, and then:
2. Broadcast a signal:
- Anonymously prove that their identity is in the set of registered
identities, and at the same time:
- Publicly store an arbitrary string in the contract, if and only if that
string is unique to the user and the contracts current external
nullifier, which is a unique value akin to a topic. This means that
double-signalling the same message under the same external nullifier is
not possible.
### External nullifiers
Think of an external nullifier as a voting booth where each user may only cast
one vote. If they try to cast a second vote a the same booth, that vote is
invalid.
An external nullifier is any 29-byte value. Semaphore always starts with one
external nullifier, which is set upon contract deployment. The owner of the
Semaphore contract may add more external nullifiers, deactivate, or reactivate
existing ones.
The first time a particular user broadcasts a signal to an active external
nullifier `n`, and if the user's proof of membership of the set of registered
users is valid, the transaction will succeed. The second time she does so to
the same `n`, however, her transaction will fail.
Additionally, all signals broadcast transactions to a deactivated external
nullifier will fail.
Each client application must use the above features of Semaphore in a unique
way to achieve its privacy goals. A mixer, for instance, would use one external
nullifier as such:
| Signal | External nullifier |
| ----------------------------------------------------------------------------- | ---------------------------- |
| The hash of the recipient's address, relayer's address, and the relayer's fee | The mixer contract's address |
This allows anonymous withdrawals of funds (via a transaction relayer, who is
rewarded with a fee), and prevents double-spending as there is only one
external nullifier.
An anonymous voting app would be configured differently:
| Signal | External nullifier |
| ----------------------------------- | ------------------------ |
| The hash of the respondent's answer | The hash of the question |
This allows any user to vote with an arbitary response (e.g. yes, no, or maybe)
to any question. The user, however, can only vote once per question.
## About the code
This repository contains the code for Semaphore's contracts written in
Soliidty, and zk-SNARK circuits written in
[circom](https://github.com/iden3/circom). It also contains Typescript code to
execute tests.
The code has been audited by ABDK Consulting. Their suggested security and
efficiency fixes have been applied.
A multi-party computation to produce the zk-SNARK proving and verification keys
for Semaphore will begin in the near future.

View File

@@ -1,19 +0,0 @@
---
sidebar_position: 6
---
# Credits
- Barry WhiteHat
- Chih Cheng Liang
- Kobi Gurkan
- Koh Wei Jie
- Harry Roberts
Many thanks to:
- ABDK Consulting
- Jordi Baylina / iden3
- POA Network
- PepperSec
- Ethereum Foundation

View File

@@ -1,4 +0,0 @@
{
"label": "Guides",
"position": 3
}

View File

@@ -1,11 +0,0 @@
---
sidebar_position: 1
---
# Groups
Describe how to use Semaphore groups:
- Create groups
- Add identities
- Remove identities

View File

@@ -1,7 +0,0 @@
---
sidebar_position: 2
---
# Nullifiers
Describe how to use external nullifiers and how to avoid double signaling.

View File

@@ -1,7 +0,0 @@
---
sidebar_position: 3
---
# Signals
Describe how to verify proofs and signal arbitrary strings.

View File

@@ -1,324 +0,0 @@
---
sidebar_position: 2
---
# Quick setup
Set up a new Hardhat project with Semaphore.
Learn how to create and test an Ethereum smart contract that uses zero-knowledge
proofs to verify membership.
To check out the code used in this guide, visit the
[semaphore-quick-setup](https://github.com/cedoor/semaphore-quick-setup) repository.
1. [Create a Node.js project](#create-a-nodejs-project)
2. [Install Hardhat](#install-hardhat)
3. [Install Semaphore contracts and ZK-kit](#install-semaphore-contracts-and-zk-kit)
4. [Create the Semaphore contract](#create-the-semaphore-contract)
5. [Create Semaphore IDs](#create-semaphore-ids)
6. [Create a Hardhat task that deploys your contract](#create-a-hardhat-task-that-deploys-your-contract)
7. [Deploy your contract to a local network](#deploy-your-contract-to-a-local-network)
## Create a Node.js project
1. Follow the [Node.js _LTS version_](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
instructions to install `node` (Hardhat may not work with Node.js _Current_).
2. Follow the [Yarn](https://yarnpkg.com/getting-started/install) instructions
to download and install the `yarn` package manager.
3. Create a directory for the project and change to the new directory.
```sh
mkdir semaphore-example
cd semaphore-example
```
4. In your terminal, run `yarn init` to initialize the Node.js project.
## Install Hardhat
[Hardhat](https://hardhat.org/) is a development environment you can use to
compile, deploy, test, and debug Ethereum software.
Hardhat includes the Hardhat Network, a local Ethereum network for development.
1. Use `yarn` to install [Hardhat](https://hardhat.org/getting-started/):
```sh
yarn add hardhat --dev
```
2. Use `yarn` to run `hardhat` and create a _basic sample project_:
```sh
yarn hardhat
# At the prompt, select "Create a basic sample project"
# and then enter through the prompts.
```
## Install Semaphore contracts and ZK-kit
`@appliedzkp/semaphore-contracts` provides a _base contract_ that verifies
Semaphore proofs.
`@appliedzkp/@zk-kit` provides JavaScript libraries that help developers
build zero-knowledge applications.
To install these dependencies for your project, do the following:
1. Use `yarn` to install `@appliedzkp/semaphore-contracts`:
```sh
yarn add @appliedzkp/semaphore-contracts
```
For more detail about _Semaphore base contracts_, see [Contracts](https://semaphore.appliedzkp.org/docs/technical-reference/contracts).
To view the source, see [Contracts in the Semaphore repository](https://github.com/appliedzkp/semaphore/tree/main/contracts).
2. Use `yarn` to install `@appliedzkp/@zk-kit`:
```sh
yarn add @zk-kit/identity @zk-kit/protocols --dev
```
For more information about `@appliedzkp/@zk-kit`, see the [ZK-kit repository](https://github.com/appliedzkp/zk-kit).
## Create the Semaphore contract
Create a `Greeters` contract that imports and extends the Semaphore base contract:
1. In `./contracts`, rename `Greeter.sol` to `Greeters.sol`.
2. Replace the contents of `Greeters.sol` with the following:
```solidity title="./semaphore-example/contracts/Greeters.sol"
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@appliedzkp/semaphore-contracts/interfaces/IVerifier.sol";
import "@appliedzkp/semaphore-contracts/base/SemaphoreCore.sol";
/// @title Greeters contract.
/// @dev The following code is just a example to show how Semaphore con be used.
contract Greeters is SemaphoreCore {
// A new greeting is published every time a user's proof is validated.
event NewGreeting(bytes32 greeting);
// Greeters are identified by a Merkle root.
// The offchain Merkle tree contains the greeters' identity commitments.
uint256 public greeters;
// The external verifier used to verify Semaphore proofs.
IVerifier public verifier;
constructor(uint256 _greeters, address _verifier) {
greeters = _greeters;
verifier = IVerifier(_verifier);
}
// Only users who create valid proofs can greet.
// The external nullifier is in this example the root of the Merkle tree.
function greet(
bytes32 _greeting,
uint256 _nullifierHash,
uint256[8] calldata _proof
) external {
_verifyProof(_greeting, greeters, _nullifierHash, greeters, _proof, verifier);
// Prevent double-greeting (nullifierHash = hash(root + identityNullifier)).
// Every user can greet once.
_saveNullifierHash(_nullifierHash);
emit NewGreeting(_greeting);
}
}
```
## Create Semaphore IDs
Semaphore _identity commitments_ (Semaphore IDs) represent user identities and
are the leaves of the Merkle trees in the protocol.
Create a `./static` folder and add a `./static/identityCommitments.json` file that
contains the following array of IDs:
```json title="./static/identityCommitments.json"
[
"9426253249246138013650573474062059446203468399013007463704855436559640562175",
"6200634377081441056179822649025268043304989981899916286941956069781421654881",
"19706772421195815860043593475869058320994241404138740034486179990871964981523"
]
```
:::info
To generate the IDs for this example, we used `@zk-kit/identity`
(with a [message strategy](https://github.com/appliedzkp/zk-kit/tree/main/packages/identity#creating-an-identity-with-a-message-strategy)) to create messages.
Then, in Metamask, we signed the messages with the first 3 Ethereum accounts
of the [Hardhat dev wallet](https://hardhat.org/hardhat-network/reference/#accounts).
:::
## Create a Hardhat task that deploys your contract
Hardhat lets you write [tasks](https://hardhat.org/guides/create-task.html#creating-a-task)
that automate building and deploying smart contracts and dApps.
To create a task that deploys the `Greeters` contract, do the following.
1. Use `yarn` to install `@zk-kit/incremental-merkle-tree` and `circomlibjs@0.0.8`:
```bash
yarn add @zk-kit/incremental-merkle-tree circomlibjs@0.0.8 --dev
```
`@zk-kit/incremental-merkle-tree` and `circomlibjs@0.0.8` let you create
off-chain Merkle trees. For more information, see the
[ZK-kit repository](https://github.com/appliedzkp/zk-kit/tree/main/packages/incremental-merkle-tree)
2. Use `yarn` to install `hardhat-dependency-compiler`:
```bash
yarn add hardhat-dependency-compiler --dev
```
[`hardhat-dependency-compiler`](https://github.com/ItsNickBarry/hardhat-dependency-compiler)
compiles Solidity contracts and dependencies.
3. Create a `tasks` folder and add a `./tasks/deploy.js` file that contains the following:
```javascript title="./tasks/deploy.js"
const { IncrementalMerkleTree } = require("@zk-kit/incremental-merkle-tree")
const { poseidon } = require("circomlibjs")
const identityCommitments = require("../static/identityCommitments.json")
const { task, types } = require("hardhat/config")
task("deploy", "Deploy a Greeters contract")
.addOptionalParam("logs", "Print the logs", true, types.boolean)
.setAction(async ({ logs }, { ethers }) => {
const VerifierContract = await ethers.getContractFactory("Verifier")
const verifier = await VerifierContract.deploy()
await verifier.deployed()
logs && console.log(`Verifier contract has been deployed to: ${verifier.address}`)
const GreetersContract = await ethers.getContractFactory("Greeters")
const tree = new IncrementalMerkleTree(poseidon, 20, BigInt(0), 2)
for (const identityCommitment of identityCommitments) {
tree.insert(identityCommitment)
}
const greeters = await GreetersContract.deploy(tree.root, verifier.address)
await greeters.deployed()
logs && console.log(`Greeters contract has been deployed to: ${greeters.address}`)
return greeters
})
```
4. In your `hardhat.config.js` file, add the following:
```javascript title="./hardhat.config.js"
require("@nomiclabs/hardhat-waffle")
require("hardhat-dependency-compiler")
require("./tasks/deploy") // Your deploy task.
module.exports = {
solidity: "0.8.4",
dependencyCompiler: {
// It allows Hardhat to compile the external Verifier.sol contract.
paths: ["@appliedzkp/semaphore-contracts/base/Verifier.sol"]
}
}
```
## Test your smart contract
[`hardhat-waffle`](https://hardhat.org/plugins/nomiclabs-hardhat-waffle.html)
lets you write tests with the [Waffle](https://getwaffle.io/) test framework
and [Chai assertions](https://www.chaijs.com/).
1. Use `yarn` to install the `hardhat-waffle` plugin and dependencies for smart
contract tests:
```bash
yarn add -D @nomiclabs/hardhat-waffle 'ethereum-waffle@^3.0.0' \
@nomiclabs/hardhat-ethers 'ethers@^5.0.0' chai
```
2. Download the Semaphore [snark build files](https://github.com/appliedzkp/semaphore/tree/main/build/snark)
and copy them to the `./static` folder. Your application and tests must pass these
static files to Semaphore to create zero-knowledge proofs.
3. Replace the contents of `./test/sample-test.js` with the following test:
```javascript title="./test/sample-test.js"
const { Strategy, ZkIdentity } = require("@zk-kit/identity")
const { generateMerkleProof, Semaphore } = require("@zk-kit/protocols")
const identityCommitments = require("../static/identityCommitments.json")
const { expect } = require("chai")
const { run, ethers } = require("hardhat")
describe("Greeters", function () {
let contract
let signers
before(async () => {
contract = await run("deploy", { logs: false })
signers = await ethers.getSigners()
})
describe("# greet", () => {
const wasmFilePath = "./static/semaphore.wasm"
const finalZkeyPath = "./static/semaphore_final.zkey"
it("Should greet", async () => {
const message = await signers[0].signMessage("Sign this message to create your identity!")
const identity = new ZkIdentity(Strategy.MESSAGE, message)
const identityCommitment = identity.genIdentityCommitment()
const greeting = "Hello world"
const bytes32Greeting = ethers.utils.formatBytes32String(greeting)
const merkleProof = generateMerkleProof(20, BigInt(0), identityCommitments, identityCommitment)
const witness = Semaphore.genWitness(
identity.getTrapdoor(),
identity.getNullifier(),
merkleProof,
merkleProof.root,
greeting
)
const fullProof = await Semaphore.genProof(witness, wasmFilePath, finalZkeyPath)
const solidityProof = Semaphore.packToSolidityProof(fullProof.proof)
const nullifierHash = Semaphore.genNullifierHash(merkleProof.root, identity.getNullifier())
const transaction = contract.greet(bytes32Greeting, nullifierHash, solidityProof)
await expect(transaction).to.emit(contract, "NewGreeting").withArgs(bytes32Greeting)
})
})
})
```
4. Run the following `yarn` commands to compile and test your contract:
```bash
yarn hardhat compile
yarn hardhat test
```
## Deploy your contract to a local network
To deploy your contract in a local Hardhat network (and use it in your dApp), run the following `yarn` commands:
```bash
yarn hardhat node
yarn hardhat deploy --network localhost # In another tab.
```
For a more complete demo that provides a starting point for your dApp,
see [semaphore-boilerplate](https://github.com/cedoor/semaphore-boilerplate/).

View File

@@ -1,17 +0,0 @@
---
sidebar_position: 5
---
# Resources
[To Mixers and Beyond: presenting Semaphore, a privacy gadget built on Ethereum](https://medium.com/coinmonks/to-mixers-and-beyond-presenting-semaphore-a-privacy-gadget-built-on-ethereum-4c8b00857c9b) - Koh Wei Jie
[Privacy in Ethereum](https://www.youtube.com/watch?v=maDHYyj30kg) - Barry WhiteHat at the Taipei Ethereum Meetup
[Snarks for mixing, signaling and scaling by](https://www.youtube.com/watch?v=lv6iK9qezBY) - Barry WhiteHat at Devcon 4
[Privacy in Ethereum](https://www.youtube.com/watch?v=zBUo7G95wYE) - Barry WhiteHat at Devcon 5
[A trustless Ethereum mixer using zero-knowledge signalling](https://www.youtube.com/watch?v=GzVT16lFOHU) - Koh Wei Jie and Barry WhiteHat at Devcon 5
[Hands-on Applications of Zero-Knowledge Signalling](https://www.youtube.com/watch?v=7wd2aAN2jXI) - Koh Wei Jie at Devcon 5

View File

@@ -1,4 +0,0 @@
{
"label": "Technical Reference",
"position": 4
}

View File

@@ -1,61 +0,0 @@
---
sidebar_position: 1
---
# Circuits
[Semaphore circuits](https://github.com/appliedzkp/semaphore/tree/main/circuits) are the heart of the protocol and essentially allow you to prove:
1. **Merkle tree**: that the identity commitment exists in the Merkle tree,
2. **Nullifiers**: that the signal was only broadcasted once,
3. **Signal**: that the signal was truly broadcasted by the user who generated the proof.
![Semaphore circuit](https://github.com/appliedzkp/semaphore/raw/main/circuits/scheme.png)
## 1. Merkle tree
**Private inputs:**
- `identityNullifier`: a random 32-byte value which the user should save,
- `identityTrapdoor`: a random 32-byte value which the user should save,
- `treeSiblings[nLevels]`: the values along the Merkle path to the user's identity commitment,
- `treePathIndices[nLevels]`: the direction (0/1) per tree level corresponding to the Merkle path to the user's identity commitment.
**Public outputs:**
- `root`: The Merkle root of the identity tree.
**Procedure:**
The circuit hashes the hash of the identity nullifier and the identity trapdoor to
generate an **identity commitment**. It then verifies the Merkle proof against
the Merkle root and the identity commitment.
## 2. Nullifier
**Private inputs:**
- `identityNullifier`: a random 32-byte value which the user should save.
**Public inputs:**
- `externalNullifier`: the 32-byte external nullifier.
**Public outputs:**
- `nullifierHash`: the hash of the identity nullifier and the external nullifier.
**Procedure:**
The circuit hashes the identity nullifier and the external nullifier. The it checks that it matches the given nullifiers hash. Additionally,
the smart contract ensures that it has not previously seen this nullifiers hash. This way, double-signalling is impossible.
## 3. Signal
**Public inputs:**
- `signalHash`: the hash of the user's signal.
**Procedure:**
The circuit performs a dummy square to prevent tampering.

View File

@@ -1,28 +0,0 @@
---
sidebar_position: 2
---
# Contracts
When using Semaphore contracts keep in mind that there are two types of contracts:
- [**Base contracts**](https://github.com/appliedzkp/semaphore/tree/main/contracts/base): they allow you to use the main protocol features (i.e. verify a proof or manage Merkle trees/groups).
- [**Extension contracts**](https://github.com/appliedzkp/semaphore/tree/main/contracts/extensions): they contain application logic and could be used for specific use-cases (e.g. anonymous voting).
Our current available extension contracts can be a good example of how base contracts can be used.
## Base contracts
There are currently two base contracts:
- [**SemaphoreCore.sol**](https://github.com/appliedzkp/semaphore/blob/main/contracts/base/SemaphoreCore.sol): it contains the functions to verify Semaphore proofs and to save the nullifier hash in order to avoid double signaling;
- [**SemaphoreGroups.sol**](https://github.com/appliedzkp/semaphore/blob/main/contracts/base/SemaphoreGroups.sol): it contains the functions to create groups, add or remove members.
These contracts are closely related to the protocol. They are abstract contracts and every function can be overridden, all expect the core ones. The SemaphoreCore contract is always required and devs should always import it, in order to verify their proofs with Semaphore. Some DApps could use the onchain groups, but maybe others can prefer to use their own trees (e.g. offchain trees).
## Extension contracts
- [**SemaphoreVoting.sol**](https://github.com/appliedzkp/semaphore/blob/main/contracts/extensions/SemaphoreVoting.sol): it contains the essential functions to create polls, add voters and cast votes anonymously;
- [**SemaphoreWhistleblowing.sol**](https://github.com/appliedzkp/semaphore/blob/main/contracts/extensions/SemaphoreWhistleblowing.sol): it contains the essential functions to create entities (e.g. non-profit organizations), add whistleblowers and publish leaks anonymously.
These contracts are just extensions of the protocol. More extensions will be added in the future.

View File

@@ -1,31 +0,0 @@
---
sidebar_position: 3
---
# ZK-kit libraries
When using Semaphore each user will need to create their own identity, which will then be added to a group. [`@zk-kit/identity`](https://github.com/appliedzkp/zk-kit/tree/main/packages/identity) allows users to create and manage their identities, while [`@zk-kit/protocols`](https://github.com/appliedzkp/zk-kit/tree/main/packages/protocols) allows users to create Semaphore proofs to prove their group membership and signal their endorsement of an arbitrary string anonymously.
If you need to see the interface of these libraries go to http://zkkit.appliedzkp.org.
:::info
[ZK-kit](https://github.com/appliedzkp/zk-kit) is a set of reusable JavaScript libraries for zero-knowledge technologies. It also contains other useful libraries, such as the [Solidity](https://github.com/appliedzkp/zk-kit/tree/main/packages/incremental-merkle-tree.sol) and [JavaScript](https://github.com/appliedzkp/zk-kit/tree/main/packages/incremental-merkle-tree) implementations of the incremental Merkle tree.
:::
## @zk-kit/identity
The Semaphore identity consists primarily of two values: `trapdoor` and `nullifier`. The Poseidon hash of these two values is the `secret`, whose hash in turn is the `identity commitment`, which is used as leaf of the Merkle tree later.
This library therefore contains a `ZKIdentity` class that can generate these values with 3 different [strategies](http://zkkit.appliedzkp.org/identity/enums/Strategy.html):
- `Strategy.RANDOM`: this is the default option and it generates the values randomly,
- `Strategy.MESSAGE`: it allows values to be generated deterministically from a message using SHA-256,
- `Strategy.SERIALIZE`: it allows you to retrieve values from a previously serialized identity.
## @zk-kit/protocols
The Semaphore proof contains public and private parameters. This library contains some utility functions to simplify the generation of these parameters. It allows, in particular, to generate a Merkle proof, the nullifier hash, the witness and a Solidity-compatible zero-knowledge proof.
Semaphore protocol functions are located in the `Semaphore` class as static methods.
If you need to use a library to manage offchain Merkle trees you can also use [`@zk-kit/incremental-merkle-tree`](https://github.com/appliedzkp/zk-kit/tree/main/packages/incremental-merkle-tree).

View File

@@ -1,48 +0,0 @@
---
id: introduction
title: What Is Semaphore?
sidebar_position: 1
---
:::caution
Semaphore's V2 documentation is under development.
:::
## Overview
[Semaphore](https://github.com/appliedzkp/semaphore) is a zero-knowledge gadget
which allows Ethereum users to prove their membership of a set which they had
previously joined without revealing their original identity. At the same time,
it allows users to signal their endorsement of an arbitrary string. It is
designed to be a simple and generic privacy layer for Ethereum DApps. Use cases
include private voting, whistleblowing, mixers, and anonymous authentication.
Finally, it provides a simple built-in mechanism to prevent double-signalling
or double-spending.
This gadget comprises of smart contracts and
[zero-knowledge](https://z.cash/technology/zksnarks/) components which work in
tandem. The Semaphore smart contract handles state, permissions, and proof
verification onchain. The zero-knowledge components work offchain to allow
users to generate proofs, which allow the smart contract to update its state
if these proofs are valid.
Semaphore is designed for DApp developers (not for end-users) and it allows them to abstract their
features in order to provide user-friendly privacy.
## Basic features
In sum, Semaphore provides the ability to:
1. generate offchain identities and add them to a Merkle tree (offchain or onchain);
2. anonymously broadcast a signal onchain, if and only if the identity of the owner belongs to a
valid Merkle tree and if the nullifier has not already been used.
## About the code
The core of the protocol is in the [circuit logic](https://github.com/appliedzkp/semaphore/tree/main/circuits/scheme.png). However
Semaphore also provides [Solidity contracts](https://github.com/appliedzkp/semaphore/tree/main/contracts)
and [JavaScript libraries](https://github.com/appliedzkp/zk-kit) (i.e. `@zk-kit/identity` and `@zk-kit/protocols`) to make
the steps for offchain proof creation and onchain verification simpler.
A code audit and a multi-party computation to produce the zk-SNARK proving and verification keys
for Semaphore will begin in the near future.

View File

@@ -1,8 +0,0 @@
{
"version-V1/mySidebar": [
{
"type": "autogenerated",
"dirName": "."
}
]
}

View File

@@ -1,8 +0,0 @@
{
"version-V2/mySidebar": [
{
"type": "autogenerated",
"dirName": "."
}
]
}

View File

@@ -1 +0,0 @@
["V2", "V1"]

File diff suppressed because it is too large Load Diff