# Table of Contents - [Semaphore](#semaphore) - [Search the documentation | Semaphore](#search-the-documentation-semaphore) - [Semaphore](#semaphore) - [Security audit | Semaphore](#security-audit-semaphore) - [Contract API | Semaphore](#contract-api-semaphore) - [Credits | Semaphore](#credits-semaphore) - [How it works | Semaphore](#how-it-works-semaphore) - [libsemaphore | Semaphore](#libsemaphore-semaphore) - [Multi-party trusted setup | Semaphore](#multi-party-trusted-setup-semaphore) - [Usage | Semaphore](#usage-semaphore) - [Quick start | Semaphore](#quick-start-semaphore) - [Quick setup | Semaphore](#quick-setup-semaphore) - [Credits | Semaphore](#credits-semaphore) - [Quick setup | Semaphore](#quick-setup-semaphore) - [What Is Semaphore? | Semaphore](#what-is-semaphore-semaphore) - [Deployed contracts | Semaphore](#deployed-contracts-semaphore) - [Glossary | Semaphore](#glossary-semaphore) - [Resources | Semaphore](#resources-semaphore) - [Identities | Semaphore](#identities-semaphore) - [Subgraph | Semaphore](#subgraph-semaphore) - [Groups | Semaphore](#groups-semaphore) - [Circuits | Semaphore](#circuits-semaphore) - [Proofs | Semaphore](#proofs-semaphore) - [Credits | Semaphore](#credits-semaphore) - [What Is Semaphore? | Semaphore](#what-is-semaphore-semaphore) - [Contracts | Semaphore](#contracts-semaphore) - [Glossary | Semaphore](#glossary-semaphore) - [Private voting use case | Semaphore](#private-voting-use-case-semaphore) - [Deployed contracts | Semaphore](#deployed-contracts-semaphore) - [Credits | Semaphore](#credits-semaphore) - [Subgraph | Semaphore](#subgraph-semaphore) - [Fetching data | Semaphore](#fetching-data-semaphore) - [Benchmarks | Semaphore](#benchmarks-semaphore) - [Resources | Semaphore](#resources-semaphore) - [Glossary | Semaphore](#glossary-semaphore) - [Troubleshooting | Semaphore](#troubleshooting-semaphore) - [Circuits | Semaphore](#circuits-semaphore) - [Contracts | Semaphore](#contracts-semaphore) - [Deployed contracts | Semaphore](#deployed-contracts-semaphore) - [Resources | Semaphore](#resources-semaphore) - [FAQ | Semaphore](#faq-semaphore) - [Groups | Semaphore](#groups-semaphore) - [Subgraph | Semaphore](#subgraph-semaphore) - [Identities | Semaphore](#identities-semaphore) - [Getting started | Semaphore](#getting-started-semaphore) - [Proofs | Semaphore](#proofs-semaphore) - [Troubleshooting | Semaphore](#troubleshooting-semaphore) - [Contracts | Semaphore](#contracts-semaphore) - [FAQ | Semaphore](#faq-semaphore) - [Proofs | Semaphore](#proofs-semaphore) - [Circuits | Semaphore](#circuits-semaphore) - [Identities | Semaphore](#identities-semaphore) - [Groups | Semaphore](#groups-semaphore) - [Code editors and LLM setup | Semaphore](#code-editors-and-llm-setup-semaphore) - [What Is Semaphore? | Semaphore](#what-is-semaphore-semaphore) - [Búsqueda en la documentación | Semaphore](#b-squeda-en-la-documentaci-n-semaphore) - [What Is Semaphore? | Semaphore](#what-is-semaphore-semaphore) - [Security audit | Semaphore](#security-audit-semaphore) - [Contract API | Semaphore](#contract-api-semaphore) - [How it works | Semaphore](#how-it-works-semaphore) - [Quick start | Semaphore](#quick-start-semaphore) - [libsemaphore | Semaphore](#libsemaphore-semaphore) - [Multi-party trusted setup | Semaphore](#multi-party-trusted-setup-semaphore) - [Usage | Semaphore](#usage-semaphore) - [Credits | Semaphore](#credits-semaphore) - [Proofs | Semaphore](#proofs-semaphore) - [Circuits | Semaphore](#circuits-semaphore) - [Subgraph | Semaphore](#subgraph-semaphore) - [Unknown](#unknown) - [What Is Semaphore? | Semaphore](#what-is-semaphore-semaphore) - [Contracts | Semaphore](#contracts-semaphore) - [Identities | Semaphore](#identities-semaphore) - [¿Qué es Semaphore? | Semaphore](#-qu-es-semaphore-semaphore) - [Resources | Semaphore](#resources-semaphore) - [Glossary | Semaphore](#glossary-semaphore) - [Identities | Semaphore](#identities-semaphore) - [Troubleshooting | Semaphore](#troubleshooting-semaphore) - [Proofs | Semaphore](#proofs-semaphore) - [Circuits | Semaphore](#circuits-semaphore) - [Subgraph | Semaphore](#subgraph-semaphore) - [Deployed contracts | Semaphore](#deployed-contracts-semaphore) - [Contracts | Semaphore](#contracts-semaphore) - [Créditos | Semaphore](#cr-ditos-semaphore) - [Glosario | Semaphore](#glosario-semaphore) - [Groups | Semaphore](#groups-semaphore) - [Private voting use case | Semaphore](#private-voting-use-case-semaphore) - [Contratos desplegados | Semaphore](#contratos-desplegados-semaphore) - [Credits | Semaphore](#credits-semaphore) - [Quick setup | Semaphore](#quick-setup-semaphore) - [Configuración rápida | Semaphore](#configuraci-n-r-pida-semaphore) - [FAQ | Semaphore](#faq-semaphore) - [Credits | Semaphore](#credits-semaphore) - [Subgrafo | Semaphore](#subgrafo-semaphore) - [Circuitos | Semaphore](#circuitos-semaphore) - [Obteniendo datos | Semaphore](#obteniendo-datos-semaphore) - [Grupos | Semaphore](#grupos-semaphore) - [Recursos | Semaphore](#recursos-semaphore) - [Contratos | Semaphore](#contratos-semaphore) - [Identidades | Semaphore](#identidades-semaphore) - [Resources | Semaphore](#resources-semaphore) - [Benchmarks | Semaphore](#benchmarks-semaphore) - [Deployed contracts | Semaphore](#deployed-contracts-semaphore) - [Pruebas | Semaphore](#pruebas-semaphore) - [Glossary | Semaphore](#glossary-semaphore) - [FAQ | Semaphore](#faq-semaphore) - [Groups | Semaphore](#groups-semaphore) - [Getting started | Semaphore](#getting-started-semaphore) - [Solución de problemas | Semaphore](#soluci-n-de-problemas-semaphore) - [Code editors and LLM setup | Semaphore](#code-editors-and-llm-setup-semaphore) --- # Semaphore [Skip to main content](https://docs.semaphore.pse.dev/#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page Overview[​](https://docs.semaphore.pse.dev/#overview "Direct link to heading") ------------------------------------------------------------------------------- [Semaphore](https://github.com/semaphore-protocol/semaphore/tree/main) is a [zero-knowledge](https://z.cash/technology/zksnarks) protocol that allows you to cast a message (for example, a vote or endorsement) as a provable group member without revealing your identity. Additionally, it provides a simple mechanism to prevent double-signaling. Use cases include private voting, whistleblowing, anonymous DAOs and mixers. For in-depth technical details about Semaphore, refer to the [Semaphore V4 Specification](https://github.com/zkspecs/zkspecs/blob/main/specs/3/README.md) . Features[​](https://docs.semaphore.pse.dev/#features "Direct link to heading") ------------------------------------------------------------------------------- With Semaphore, you can allow your users to do the following: 1. [Create a Semaphore identity](https://docs.semaphore.pse.dev/guides/identities) . 2. [Add their Semaphore identity to a group (i.e. _Merkle tree_)](https://docs.semaphore.pse.dev/guides/groups) . 3. [Send a verifiable, anonymous message (e.g a vote or endorsement)](https://docs.semaphore.pse.dev/guides/proofs) . When a user broadcasts a message, Semaphore zero-knowledge proofs can ensure that the user has joined the group and hasn't already cast a message with their nullifier. Semaphore uses on-chain Solidity contracts and off-chain JavaScript libraries that work in tandem. * Off chain, JavaScript libraries can be used to create identities, manage groups and generate proofs. * On chain, Solidity contracts can be used to manage groups and verify proofs. Developer benefits[​](https://docs.semaphore.pse.dev/#developer-benefits "Direct link to heading") --------------------------------------------------------------------------------------------------- Semaphore is designed to be a simple and generic _privacy layer_ for decentralized applications (dApps) on Ethereum. It encourages modular application design, allowing dApp developers to choose and customize the on-chain and off-chain components they need. About the code[​](https://docs.semaphore.pse.dev/#about-the-code "Direct link to heading") ------------------------------------------------------------------------------------------- The core of the protocol is the [circuit logic](https://github.com/semaphore-protocol/semaphore/tree/main/packages/circuits/src/semaphore.circom) . In addition to circuits, Semaphore provides [Solidity contracts](https://github.com/semaphore-protocol/semaphore/tree/main/packages/contracts) and [JavaScript libraries](https://github.com/semaphore-protocol/semaphore/tree/main#-packages) that allow developers to generate zero-knowledge proofs and verify them with minimal effort. Trusted Setup Ceremony[​](https://docs.semaphore.pse.dev/#trusted-setup-ceremony "Direct link to heading") ----------------------------------------------------------------------------------------------------------- The [secure parameters](https://snark-artifacts.pse.dev/) for generating valid proofs with Semaphore circuits were generated in a [Trusted Setup Ceremony](https://ceremony.pse.dev/projects/Semaphore%20V4%20Ceremony) that was completed with over 400 participants on [13 July 2024](https://etherscan.io/block/20300394) . ### Audits[​](https://docs.semaphore.pse.dev/#audits "Direct link to heading") | 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` | * [Overview](https://docs.semaphore.pse.dev/#overview) * [Features](https://docs.semaphore.pse.dev/#features) * [Developer benefits](https://docs.semaphore.pse.dev/#developer-benefits) * [About the code](https://docs.semaphore.pse.dev/#about-the-code) * [Trusted Setup Ceremony](https://docs.semaphore.pse.dev/#trusted-setup-ceremony) * [Audits](https://docs.semaphore.pse.dev/#audits) --- # Search the documentation | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/search#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Search the documentation ======================== [](https://www.algolia.com/) --- # Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V1#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V1**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V1 On this page Overview[​](https://docs.semaphore.pse.dev/V1#overview "Direct link to heading") --------------------------------------------------------------------------------- [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[​](https://docs.semaphore.pse.dev/V1#basic-features "Direct link to heading") --------------------------------------------------------------------------------------------- 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 contract’s 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[​](https://docs.semaphore.pse.dev/V1#external-nullifiers "Direct link to heading") 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 at 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 arbitrary response (e.g. yes, no, or maybe) to any question. The user, however, can only vote once per question. About the code[​](https://docs.semaphore.pse.dev/V1#about-the-code "Direct link to heading") --------------------------------------------------------------------------------------------- This repository contains the code for Semaphore's contracts written in Solidity, 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. * [Overview](https://docs.semaphore.pse.dev/V1#overview) * [Basic features](https://docs.semaphore.pse.dev/V1#basic-features) * [External nullifiers](https://docs.semaphore.pse.dev/V1#external-nullifiers) * [About the code](https://docs.semaphore.pse.dev/V1#about-the-code) --- # Security audit | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V1/audit#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V1**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V1 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/semaphore-protocol/semaphore/blob/main/apps/docs/versioned_docs/version-V1/audit.md) . After three rounds of fixes, all security and performance issues were fixed, and the few remaining issues are minor and do not affect security. --- # Contract API | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V1/contract-api#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V1**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V1 On this page Constructor[​](https://docs.semaphore.pse.dev/V1/contract-api#constructor "Direct link to heading") ---------------------------------------------------------------------------------------------------- **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 nullifiers[​](https://docs.semaphore.pse.dev/V1/contract-api#add-deactivate-or-reactivate-external-nullifiers "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- **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[​](https://docs.semaphore.pse.dev/V1/contract-api#insert-identities "Direct link to heading") ---------------------------------------------------------------------------------------------------------------- **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](https://docs.semaphore.pse.dev/V1/usage#insert-identities) for more information. Broadcast signals[​](https://docs.semaphore.pse.dev/V1/contract-api#broadcast-signals "Direct link to heading") ---------------------------------------------------------------------------------------------------------------- **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](https://docs.semaphore.pse.dev/V1/usage#broadcast-signals) for more information. * [Constructor](https://docs.semaphore.pse.dev/V1/contract-api#constructor) * [Add, deactivate, or reactivate external nullifiers](https://docs.semaphore.pse.dev/V1/contract-api#add-deactivate-or-reactivate-external-nullifiers) * [Insert identities](https://docs.semaphore.pse.dev/V1/contract-api#insert-identities) * [Broadcast signals](https://docs.semaphore.pse.dev/V1/contract-api#broadcast-signals) --- # Credits | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V1/creditsandresources#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V1**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V1 * 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 --- # How it works | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V1/howitworks#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V1**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V1 On this page Inserting identities[​](https://docs.semaphore.pse.dev/V1/howitworks#inserting-identities "Direct link to heading") -------------------------------------------------------------------------------------------------------------------- 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, which is a random 32-byte value. 3. An identity trapdoor, which 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](https://docs.semaphore.pse.dev/V1/contract-api) for more information. Broadcasting signals[​](https://docs.semaphore.pse.dev/V1/howitworks#broadcasting-signals "Direct link to heading") -------------------------------------------------------------------------------------------------------------------- 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[​](https://docs.semaphore.pse.dev/V1/howitworks#the-zk-snark-circuit "Direct link to heading") 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[​](https://docs.semaphore.pse.dev/V1/howitworks#that-the-identity-commitment-exists-in-the-merkle-tree "Direct link to heading") **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[​](https://docs.semaphore.pse.dev/V1/howitworks#that-the-signal-was-only-broadcasted-once "Direct link to heading") **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[​](https://docs.semaphore.pse.dev/V1/howitworks#that-the-signal-was-truly-broadcasted-by-the-user-who-generated-the-proof "Direct link to heading") **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[​](https://docs.semaphore.pse.dev/V1/howitworks#cryptographic-primitives "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------- Semaphore uses MiMC for the Merkle tree, Pedersen commitments 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. * [Inserting identities](https://docs.semaphore.pse.dev/V1/howitworks#inserting-identities) * [Broadcasting signals](https://docs.semaphore.pse.dev/V1/howitworks#broadcasting-signals) * [The zk-SNARK circuit](https://docs.semaphore.pse.dev/V1/howitworks#the-zk-snark-circuit) * [That the identity commitment exists in the Merkle tree](https://docs.semaphore.pse.dev/V1/howitworks#that-the-identity-commitment-exists-in-the-merkle-tree) * [That the signal was only broadcasted once](https://docs.semaphore.pse.dev/V1/howitworks#that-the-signal-was-only-broadcasted-once) * [That the signal was truly broadcasted by the user who generated the proof](https://docs.semaphore.pse.dev/V1/howitworks#that-the-signal-was-truly-broadcasted-by-the-user-who-generated-the-proof) * [Cryptographic primitives](https://docs.semaphore.pse.dev/V1/howitworks#cryptographic-primitives) --- # libsemaphore | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V1/libsemaphore#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V1**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V1 On this page [`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[​](https://docs.semaphore.pse.dev/V1/libsemaphore#available-types-interfaces-and-functions "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------- ### Types[​](https://docs.semaphore.pse.dev/V1/libsemaphore#types "Direct link to heading") **`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[​](https://docs.semaphore.pse.dev/V1/libsemaphore#interfaces "Direct link to heading") **`EddsaKeyPair`** Encapsulates an `EddsaPublicKey` and an `EddsaPrivateKey`. 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. interface Identity { keypair: EddsaKeyPair identityNullifier: SnarkBigInt identityTrapdoor: SnarkBigInt} **`SnarkProof`** Note that `broadcastSignal()` accepts a `uint256[8]` array for its `_proof` parameter. See `genBroadcastSignalParams()`. interface SnarkProof { pi_a: SnarkBigInt[] pi_b: SnarkBigInt[][] pi_c: SnarkBigInt[]} ### Functions[​](https://docs.semaphore.pse.dev/V1/libsemaphore#functions "Direct link to heading") **`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: ["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)`** Encapsulates `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: 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 commitments; 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 commitment * `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: { 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. * [Available types, interfaces, and functions](https://docs.semaphore.pse.dev/V1/libsemaphore#available-types-interfaces-and-functions) * [Types](https://docs.semaphore.pse.dev/V1/libsemaphore#types) * [Interfaces](https://docs.semaphore.pse.dev/V1/libsemaphore#interfaces) * [Functions](https://docs.semaphore.pse.dev/V1/libsemaphore#functions) --- # Multi-party trusted setup | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V1/trustedsetup#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V1**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V1 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. --- # Usage | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V1/usage#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V1**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V1 On this page 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 nullifiers[​](https://docs.semaphore.pse.dev/V1/usage#add-deactivate-or-reactivate-external-nullifiers "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 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[​](https://docs.semaphore.pse.dev/V1/usage#set-broadcast-permissioning "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------- 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[​](https://docs.semaphore.pse.dev/V1/usage#insert-identities "Direct link to heading") --------------------------------------------------------------------------------------------------------- To generate an identity commitment, use the `libsemaphore` functions `genIdentity()` and `genIdentityCommitment()` Typescript (or Javascript) functions: 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: ["e82cc2b8654705e427df423c6300307a873a2e637028fab3163cf95b18bb172e","a02e517dfb3a4184adaa951d02bfe0fe092d1ee34438721d798db75b8db083","15c6540bf7bddb0616984fccda7e954a0fb5ea4679ac686509dc4bd7ba9c3b"] To convert this string back into an `Identity`, use `unSerialiseIdentity()`. `const id: Identity = unSerialiseIdentity(serialisedId)` Broadcast signals[​](https://docs.semaphore.pse.dev/V1/usage#broadcast-signals "Direct link to heading") --------------------------------------------------------------------------------------------------------- First obtain the leaves of the identity tree (in sequence, up to the user's identity commitment, or more). const leaves = Next, load the circuit from disk (or from a remote source): 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): 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): const proof = await genProof(result.witness, provingKey) Generate the `broadcastSignal()` parameters: const publicSignals = genPublicSignals(result.witness, circuit)const params = genBroadcastSignalParams(result, proof, publicSignals) Finally, invoke `broadcastSignal()` with the parameters: const tx = await semaphoreClientContract.broadcastSignal( ethers.utils.toUtf8Bytes(signal), params.proof, params.root, params.nullifiersHash, external_nullifier, { gasLimit: 500000 }) * [Add, deactivate, or reactivate external nullifiers](https://docs.semaphore.pse.dev/V1/usage#add-deactivate-or-reactivate-external-nullifiers) * [Set broadcast permissioning](https://docs.semaphore.pse.dev/V1/usage#set-broadcast-permissioning) * [Insert identities](https://docs.semaphore.pse.dev/V1/usage#insert-identities) * [Broadcast signals](https://docs.semaphore.pse.dev/V1/usage#broadcast-signals) --- # Quick start | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V1/quickstart#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V1**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V1 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: git clone [email protected]: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: # Start from the base directory./circuits/scripts/download_snarks.sh To generate the above files locally instead, run: # 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`): # Start from the base directorycd contracts && \npm run compileSol Run tests while still in the `contracts/` directory: # The first command tests the Merkle tree contract and the second# tests the Semaphore contractnpm run test-semaphore && \npm run test-mt --- # Quick setup | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2/quick-setup#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V2 On this page 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 [quick-setup](https://github.com/semaphore-protocol/quick-setup) repository. 1. [**Create a Node.js project**](https://docs.semaphore.pse.dev/V2/quick-setup#create-a-nodejs-project) 2. [**Install Hardhat**](https://docs.semaphore.pse.dev/V2/quick-setup#install-hardhat) 3. [**Install Semaphore packages**](https://docs.semaphore.pse.dev/V2/quick-setup#install-semaphore-packages) 4. [**Create the Semaphore contract**](https://docs.semaphore.pse.dev/V2/quick-setup#create-the-semaphore-contract) 5. [**Create a Hardhat task**](https://docs.semaphore.pse.dev/V2/quick-setup#create-a-hardhat-task) 6. [**Test your contracts**](https://docs.semaphore.pse.dev/V2/quick-setup#test-your-contract) 7. [**Deploy your contract**](https://docs.semaphore.pse.dev/V2/quick-setup#deploy-your-contract) Create a Node.js project[​](https://docs.semaphore.pse.dev/V2/quick-setup#create-a-nodejs-project "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------- 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. mkdir semaphore-examplecd semaphore-example 4. In your terminal, run `yarn init` to initialize the Node.js project. Install Hardhat[​](https://docs.semaphore.pse.dev/V2/quick-setup#install-hardhat "Direct link to heading") ----------------------------------------------------------------------------------------------------------- [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/) : yarn add hardhat --dev 2. Use `yarn` to run `hardhat` and create a JavaScript project: yarn hardhat# At the prompt, select "Create a JavaScript project"# and then enter through the prompts. Install Semaphore packages[​](https://docs.semaphore.pse.dev/V2/quick-setup#install-semaphore-packages "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------------- Semaphore provides contracts, JavaScript libraries and a Hardhat plugin for developers building zero-knowledge applications. * `@semaphore-protocol/contracts` provides contracts to manage groups and verify Semaphore proofs on-chain. * JavaScript libraries help developers build zero-knowledge applications. * `@semaphore-protocol/hardhat` allows developers Hardhat tasks to deploy verifiers and Semaphore contracts. To install these dependencies for your project, do the following: 1. Use `yarn` to install `@semaphore-protocol/contracts`: yarn add @semaphore-protocol/[email protected] 2. Use `yarn` to install the Semaphore JavaScript libraries and the Hardhat plugin: yarn add @semaphore-protocol/[email protected] @semaphore-protocol/[email protected] @semaphore-protocol/[email protected] @semaphore-protocol/[email protected] --dev For more detail about _Semaphore contracts_, see [Contracts](https://docs.semaphore.pse.dev/technical-reference/contracts) . To view the source of our packages, see the [semaphore](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1#-packages) repository. Create the Semaphore contract[​](https://docs.semaphore.pse.dev/V2/quick-setup#create-the-semaphore-contract "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------------------- Create a `Greeter` contract that uses the `Semaphore.sol` contract: 1. Rename `Lock.sol` to `Greeter.sol` and replace the content with the following: ./contracts/Greeter.sol //SPDX-License-Identifier: MITpragma solidity ^0.8.0;import "@semaphore-protocol/contracts/interfaces/ISemaphore.sol";/// @title Greeter contract./// @dev The following code is just an example to show how Semaphore can be used.contract Greeter { event NewGreeting(bytes32 greeting); event NewUser(uint256 identityCommitment, bytes32 username); ISemaphore public semaphore; uint256 groupId; mapping(uint256 => bytes32) users; constructor(address semaphoreAddress, uint256 _groupId) { semaphore = ISemaphore(semaphoreAddress); groupId = _groupId; semaphore.createGroup(groupId, 20, 0, address(this)); } function joinGroup(uint256 identityCommitment, bytes32 username) external { semaphore.addMember(groupId, identityCommitment); users[identityCommitment] = username; emit NewUser(identityCommitment, username); } function greet( bytes32 greeting, uint256 merkleTreeRoot, uint256 nullifierHash, uint256[8] calldata proof ) external { semaphore.verifyProof(groupId, merkleTreeRoot, greeting, nullifierHash, groupId, proof); emit NewGreeting(greeting); }} Create a Hardhat task[​](https://docs.semaphore.pse.dev/V2/quick-setup#create-a-hardhat-task "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------- 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 `Greeter` contract, do the following: 1. Create a `tasks` folder and add a `./tasks/deploy.js` file that contains the following: ./tasks/deploy.js const { task, types } = require("hardhat/config")task("deploy", "Deploy a Greeter contract") .addOptionalParam("semaphore", "Semaphore contract address", undefined, types.address) .addParam("group", "Group identifier", 42, types.int) .addOptionalParam("logs", "Print the logs", true, types.boolean) .setAction(async ({ logs, semaphore: semaphoreAddress, group: groupId }, { ethers, run }) => { if (!semaphoreAddress) { const { address: verifierAddress } = await run("deploy:verifier", { logs, merkleTreeDepth: 20 }) const { address } = await run("deploy:semaphore", { logs, verifiers: [ { merkleTreeDepth: 20, contractAddress: verifierAddress } ] }) semaphoreAddress = address } const Greeter = await ethers.getContractFactory("Greeter") const greeter = await Greeter.deploy(semaphoreAddress, groupId) await greeter.deployed() if (logs) { console.log(`Greeter contract has been deployed to: ${greeter.address}`) } return greeter }) 2. In your `hardhat.config.js` file, add the following: ./hardhat.config.js require("@nomiclabs/hardhat-waffle")require("@semaphore-protocol/hardhat")require("./tasks/deploy") // Your deploy task.module.exports = { solidity: "0.8.4"} Test your contract[​](https://docs.semaphore.pse.dev/V2/quick-setup#test-your-contract "Direct link to heading") ----------------------------------------------------------------------------------------------------------------- [`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: yarn add -D @nomiclabs/hardhat-waffle 'ethereum-waffle@^3.0.0' \ @nomiclabs/hardhat-ethers 'ethers@^5.0.0' chai 2. Download the Semaphore [zk trusted setup files](http://www.trusted-setup-pse.org/) and copy them to the `./static` folder. cd staticwget http://www.trusted-setup-pse.org/semaphore/20/semaphore.zkeywget http://www.trusted-setup-pse.org/semaphore/20/semaphore.wasm Learn more about [trusted setup files](https://docs.semaphore.pse.dev/V2/glossary#trusted-setup-files) . 3. Rename the `Lock.js` test file to `Greeter.js` and replace the content with the following: ./test/Greeter.js const { Identity } = require("@semaphore-protocol/identity")const { Group } = require("@semaphore-protocol/group")const { generateProof, packToSolidityProof, verifyProof } = require("@semaphore-protocol/proof")const { expect } = require("chai")const { run, ethers } = require("hardhat")describe("Greeter", function () { let greeter const users = [] const groupId = 42 const group = new Group() before(async () => { greeter = await run("deploy", { logs: false, group: groupId }) users.push({ identity: new Identity(), username: ethers.utils.formatBytes32String("anon1") }) users.push({ identity: new Identity(), username: ethers.utils.formatBytes32String("anon2") }) group.addMember(users[0].identity.generateCommitment()) group.addMember(users[1].identity.generateCommitment()) }) describe("# joinGroup", () => { it("Should allow users to join the group", async () => { for (let i = 0; i < group.members.length; i++) { const transaction = greeter.joinGroup(group.members[i], users[i].username) await expect(transaction).to.emit(greeter, "NewUser").withArgs(group.members[i], users[i].username) } }) }) describe("# greet", () => { const wasmFilePath = "./static/semaphore.wasm" const zkeyFilePath = "./static/semaphore.zkey" it("Should allow users to greet", async () => { const greeting = ethers.utils.formatBytes32String("Hello World") const fullProof = await generateProof(users[1].identity, group, groupId, greeting, { wasmFilePath, zkeyFilePath }) const solidityProof = packToSolidityProof(fullProof.proof) const transaction = greeter.greet( greeting, fullProof.publicSignals.merkleRoot, fullProof.publicSignals.nullifierHash, solidityProof ) await expect(transaction).to.emit(greeter, "NewGreeting").withArgs(greeting) }) })}) 4. Run the following `yarn` commands to compile and test your contract: yarn hardhat compileyarn hardhat test Deploy your contract[​](https://docs.semaphore.pse.dev/V2/quick-setup#deploy-your-contract "Direct link to heading") --------------------------------------------------------------------------------------------------------------------- To deploy your contract in a local Hardhat network (and use it in your dApp), run the following `yarn` commands: yarn hardhat nodeyarn hardhat deploy --group 42 --network localhost # In another tab. For a more complete demo that provides a starting point for your dApp, see [semaphore-boilerplate](https://github.com/semaphore-protocol/boilerplate/) . * [Create a Node.js project](https://docs.semaphore.pse.dev/V2/quick-setup#create-a-nodejs-project) * [Install Hardhat](https://docs.semaphore.pse.dev/V2/quick-setup#install-hardhat) * [Install Semaphore packages](https://docs.semaphore.pse.dev/V2/quick-setup#install-semaphore-packages) * [Create the Semaphore contract](https://docs.semaphore.pse.dev/V2/quick-setup#create-the-semaphore-contract) * [Create a Hardhat task](https://docs.semaphore.pse.dev/V2/quick-setup#create-a-hardhat-task) * [Test your contract](https://docs.semaphore.pse.dev/V2/quick-setup#test-your-contract) * [Deploy your contract](https://docs.semaphore.pse.dev/V2/quick-setup#deploy-your-contract) --- # Credits | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2/credits#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/credits) ** (V4). Version: V2 Semaphore V2 is the work of several people, for a complete list of contributors you can visit our [Github pages](https://github.com/semaphore-protocol/semaphore/graphs/contributors) . * [Barry WhiteHat](https://github.com/barryWhiteHat) * [Kobi Gurkan](https://github.com/kobigurk) * [Koh Wei Jie](https://github.com/weijiekoh) * [Andrija Novakovic](https://github.com/akinovak) * [Cedoor](https://github.com/cedoor) --- # Quick setup | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/quick-setup#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V3 On this page Semaphore provides an official CLI to set up your project with Hardhat. If your NPM version is 5.2 or higher you can use NPX: npx @semaphore-protocol/cli@^3 create my-app --template monorepo-ethers Otherwise, install `@semaphore-protocol/cli@^3` globally and run the `create` command: npm i -g @semaphore-protocol/cli@^3semaphore create my-app --template monorepo-ethers info The supported templates are: [`contracts-hardhat`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/cli-template-contracts-hardhat) , [`monorepo-ethers`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/cli-template-monorepo-ethers) , [`monorepo-subgraph`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/cli-template-monorepo-subgraph) . info The [`semaphore CLI`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/cli) can also be used to get group data from a supported network (e.g `semaphore get-groups --network arbitrum-goerli`). To start working on your project, install the dependencies: * npm * Yarn * pnpm cd my-appnpm i cd my-appyarn cd my-apppnpm install Output[​](https://docs.semaphore.pse.dev/V3/quick-setup#output "Direct link to heading") ----------------------------------------------------------------------------------------- The `create` command will create a directory called my-app (or whatever name you choose) inside the current folder. That directory will contain the initial project structure, which includes a simple contract, a task to deploy it, some tests and a Next.js application (the web-app folder) to interact with that contract. my-app├── .yarn├── apps│ └── contracts│ │ └── contracts| │ │ └── Feedback.sol│ │ └── scripts| │ │ └── download-snark-artifacts.ts│ │ └── tasks| │ │ └── deploy.ts│ │ └── test| │ │ └── Feedback.ts│ │ └── hardhat.config.ts│ │ └── package.json│ │ └── tsconfig.json│ └── web-app├── scripts│ └── copy-contracts-artifacts.ts├── .editorconfig├── .env├── .env.example├── .eslintignore├── .eslintrc.json├── .gitignore├── .prettierignore├── .prettierrc.json├── .yarnrc.yml├── package.json├── README.md└── tsconfig.json The `Feedback.sol` contract creates a Semaphore group, allows users to join that group with their Semaphore identity, and finally allows group members to send an anonymous feedback. Usage[​](https://docs.semaphore.pse.dev/V3/quick-setup#usage "Direct link to heading") --------------------------------------------------------------------------------------- ### Compile contracts[​](https://docs.semaphore.pse.dev/V3/quick-setup#compile-contracts "Direct link to heading") Go to the `contracts` folder: cd apps/contracts And compile your contracts: * npm * Yarn * pnpm npm run compile yarn compile pnpm compile ### Test contracts[​](https://docs.semaphore.pse.dev/V3/quick-setup#test-contracts "Direct link to heading") Test your contracts: * npm * Yarn * pnpm npm test yarn test pnpm test Generate a test coverage report: * npm * Yarn * pnpm npm run test:coverage yarn test:coverage pnpm test:coverage Or a test gas report: * npm * Yarn * pnpm npm run test:report-gas yarn test:report-gas pnpm test:report-gas ### Deploy contracts[​](https://docs.semaphore.pse.dev/V3/quick-setup#deploy-contracts "Direct link to heading") Follow the instructions below to deploy your contracts: 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. 2. Go to the `apps/contracts` folder and deploy your contract. * npm * Yarn * pnpm npm run deploy -- --semaphore --group --network arbitrum-goerli yarn deploy --semaphore --group --network arbitrum-goerli pnpm deploy --semaphore --group --network arbitrum-goerli note Check the Semaphore contract addresses [here](https://docs.semaphore.pse.dev/V3/deployed-contracts) . caution The group id is a number. ### Start app[​](https://docs.semaphore.pse.dev/V3/quick-setup#start-app "Direct link to heading") Start the application: * npm * Yarn * pnpm npm run dev yarn dev pnpm dev * [Output](https://docs.semaphore.pse.dev/V3/quick-setup#output) * [Usage](https://docs.semaphore.pse.dev/V3/quick-setup#usage) * [Compile contracts](https://docs.semaphore.pse.dev/V3/quick-setup#compile-contracts) * [Test contracts](https://docs.semaphore.pse.dev/V3/quick-setup#test-contracts) * [Deploy contracts](https://docs.semaphore.pse.dev/V3/quick-setup#deploy-contracts) * [Start app](https://docs.semaphore.pse.dev/V3/quick-setup#start-app) --- # What Is Semaphore? | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V2 On this page Overview[​](https://docs.semaphore.pse.dev/V2#overview "Direct link to heading") --------------------------------------------------------------------------------- [Semaphore](https://github.com/semaphore-protocol/semaphore) is a [zero-knowledge](https://z.cash/technology/zksnarks) protocol that allows you to cast a signal (for example, a vote or endorsement) as a provable group member without revealing your identity. Additionally, it provides a simple mechanism to prevent double-signaling. Use cases include private voting, whistleblowing, anonymous DAOs and mixers. Features[​](https://docs.semaphore.pse.dev/V2#features "Direct link to heading") --------------------------------------------------------------------------------- With Semaphore, you can allow your users to do the following: 1. [Create a Semaphore identity](https://docs.semaphore.pse.dev/V2/guides/identities) . 2. [Add their Semaphore identity to a group (i.e. _Merkle tree_)](https://docs.semaphore.pse.dev/V2/guides/groups) . 3. [Send a verifiable, anonymous signal (e.g a vote or endorsement)](https://docs.semaphore.pse.dev/V2/guides/proofs) . When a user broadcasts a signal (for example: a vote), Semaphore zero-knowledge proofs can ensure that the user has joined the group and hasn't already cast a signal with their nullifier. Semaphore uses on-chain Solidity contracts and off-chain JavaScript libraries that work in tandem. * Off chain, JavaScript libraries can be used to create identities, manage groups and generate proofs. * On chain, Solidity contracts can be used to manage groups and verify proofs. Developer benefits[​](https://docs.semaphore.pse.dev/V2#developer-benefits "Direct link to heading") ----------------------------------------------------------------------------------------------------- Semaphore is designed to be a simple and generic _privacy layer_ for decentralized applications (dApps) on Ethereum. It encourages modular application design, allowing dApp developers to choose and customize the on-chain and off-chain components they need. About the code[​](https://docs.semaphore.pse.dev/V2#about-the-code "Direct link to heading") --------------------------------------------------------------------------------------------- The core of the protocol is the [circuit logic](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/circuits/scheme.png) . In addition to circuits, Semaphore provides [Solidity contracts](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts) and [JavaScript libraries](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1#-packages) that allow developers to generate zero-knowledge proofs and verify them with minimal effort. ### Audits[​](https://docs.semaphore.pse.dev/V2#audits "Direct link to heading") | Version | Report | Scope | | --- | --- | --- | | v2.0.0 | [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 | [Semaphore\_2.5.0\_Audit.pdf](https://github.com/semaphore-protocol/semaphore/files/9845008/Semaphore_2.5.0_Audit.pdf) | `contracts`, `libraries` | info If you are using the previous version of Semaphore, see the [Semaphore V1](https://docs.semaphore.pse.dev/V1) documentation. * [Overview](https://docs.semaphore.pse.dev/V2#overview) * [Features](https://docs.semaphore.pse.dev/V2#features) * [Developer benefits](https://docs.semaphore.pse.dev/V2#developer-benefits) * [About the code](https://docs.semaphore.pse.dev/V2#about-the-code) * [Audits](https://docs.semaphore.pse.dev/V2#audits) --- # Deployed contracts | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2/deployed-contracts#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/deployed-contracts) ** (V4). Version: V2 On this page Verifiers[​](https://docs.semaphore.pse.dev/V2/deployed-contracts#verifiers "Direct link to heading") ------------------------------------------------------------------------------------------------------ | Contract | Goerli | Arbitrum One | | --- | --- | --- | | Verifier16.sol | [0xA525...6629](https://goerli.etherscan.io/address/0xA5253ba39381Aa99c4C2C5A4D5C2deC036d06629) | [0x6143...1609](https://arbiscan.io/address/0x6143ECd9Fd1A00EDe1046d456f8aab53a7D71609) | | Verifier17.sol | [0xe041...01Ab](https://goerli.etherscan.io/address/0xe0418A5f8fBF051D6cbc41Ff29855Dd2a02201Ab) | [0xAc12...Fb02](https://arbiscan.io/address/0xAc12fFFE354D6446eb50dd33E683B78FED73Fb02) | | Verifier18.sol | [0x7CdB...6797](https://goerli.etherscan.io/address/0x7CdB3336d7d7c55Bce0FB1508594C54521656797) | [0x610a...C701](https://arbiscan.io/address/0x610aeF0F2da3CD1C8bDefe4BDB434Ee146E0C701) | | Verifier19.sol | [0xbd87...190B](https://goerli.etherscan.io/address/0xbd870921d8A5398a3314C950d1fc63b8C3AB190B) | [0x5477...FCb4](https://arbiscan.io/address/0x5477725177035bbC9d70443eb921D29749D6FCb4) | | Verifier20.sol | [0x2a96...E099](https://goerli.etherscan.io/address/0x2a96c5696F85e3d2aa918496806B5c5a4D93E099) | [0x3fB2...3136](https://arbiscan.io/address/0x3fB2C0988a37b76e760c44e6516aF720935f3136) | | Verifier21.sol | [0x5Ec7...67Cd](https://goerli.etherscan.io/address/0x5Ec7d851a52A2a25CEc528F42a7ACA8EcF4667Cd) | [0xDc8f...7DF8](https://arbiscan.io/address/0xDc8f6B8A42836d4566256f4c6C53131DFD127DF8) | | Verifier22.sol | [0x919d...aA5b](https://goerli.etherscan.io/address/0x919d3d9c05FA7411e334deA5a763354fC7B6aA5b) | [0x6962...32f2](https://arbiscan.io/address/0x6962b5e706be5278eeCb01c286b50A48484632f2) | | Verifier23.sol | [0x6391...E552](https://goerli.etherscan.io/address/0x63917b00a6dA7865bEfdd107AfC83CC2e6BDE552) | [0x41e4...dF6B](https://arbiscan.io/address/0x41e4796Bd89B4BF04013b559c93fC32E9a2BdF6B) | | Verifier24.sol | [0xd05C...0E7D](https://goerli.etherscan.io/address/0xd05CAd7d940114c1419098EE3cEA0776ab510E7D) | [0xD528...5b60](https://arbiscan.io/address/0xD528B1D1408ab3583af4694F92b0aFEbE33d5b60) | | Verifier25.sol | [0x6D98...5ACb](https://goerli.etherscan.io/address/0x6D9862e6140D94E932d94c8BcE74a0BDD0ea5ACb) | [0x1683...33e7](https://arbiscan.io/address/0x1683a27EF9c10c5286dB56412E1272cD0Ca733e7) | | Verifier26.sol | [0x8c29...6c77](https://goerli.etherscan.io/address/0x8c29e0b77e32f704F03eeCE01c041192A5EB6c77) | [0x7819...4C00](https://arbiscan.io/address/0x78194bB665d1E33b97eE45B1A755c15717E94C00) | | Verifier27.sol | [0x066c...9c4C](https://goerli.etherscan.io/address/0x066cC22f8CA2A8D90D7Ff77D8a10A27e629c9c4C) | [0x997D...6E42](https://arbiscan.io/address/0x997Dac00E6701Ef7F3518280E5a9922801126E42) | | Verifier28.sol | [0x698F...6D15](https://goerli.etherscan.io/address/0x698F9507f504E2BD238be7da56E8D9fee60C6D15) | [0xDd3C...68c6](https://arbiscan.io/address/0xDd3C7f4cBA2467aE41c0F614A3c3E24bC80268c6) | | Verifier29.sol | [0xbBfC...6346](https://goerli.etherscan.io/address/0xbBfC2E201C3c3c6F50063c3Edb4746c6Fcb36346) | [0xe53e...60Cd](https://arbiscan.io/address/0xe53eF12093933D5df5691EAbA3821bD1c1EB60Cd) | | Verifier30.sol | [0x06bc...4bD1](https://goerli.etherscan.io/address/0x06bcD633988c1CE7Bd134DbE2C12119b6f3E4bD1) | [0x7FeA...340e](https://arbiscan.io/address/0x7FeA07c536ABBB0E7FB3c833376EE4EaDc21340e) | | Verifier31.sol | [0x133b...cCFE](https://goerli.etherscan.io/address/0x133b69Ce47BF20C49368354914DF47519Ca6cCFE) | [0xe453...2178](https://arbiscan.io/address/0xe4539a592df18936202480FBe77E47DE012F2178) | | Verifier32.sol | [0xe297...2e2D](https://goerli.etherscan.io/address/0xe2978F79cb4AF62e5C990EE5c7E12fb22ee22e2D) | [0x98c9...32F4](https://arbiscan.io/address/0x98c90845A7870e215cBd7265DDC653E6c07032F4) | Semaphore[​](https://docs.semaphore.pse.dev/V2/deployed-contracts#semaphore "Direct link to heading") ------------------------------------------------------------------------------------------------------ | Contract | Goerli | Arbitrum One | | --- | --- | --- | | Semaphore.sol | [0x5259...262f](https://goerli.etherscan.io/address/0x5259d32659F1806ccAfcE593ED5a89eBAb85262f) | [0x8633...A604](https://arbiscan.io/address/0x86337c87A56117f8264bbaBA70e5a522C6E8A604) | | IncrementalBinaryTree.sol | [0x61AE...B236](https://goerli.etherscan.io/address/0x61AE89E372492e53D941DECaaC9821649fa9B236) | [0x91cD...3948](https://arbiscan.io/address/0x91cD2B8573629d00BeC72EA1188d446897BD3948) | | PoseidonT3.sol | [0xe0A4...350F](https://goerli.etherscan.io/address/0xe0A452533853310C371b50Bd91BB9DCC8961350F) | [0xe0c8...61d0](https://arbiscan.io/address/0xe0c8d1e53D9Bfc9071F6564755FCFf6cC0dB61d0) | * [Verifiers](https://docs.semaphore.pse.dev/V2/deployed-contracts#verifiers) * [Semaphore](https://docs.semaphore.pse.dev/V2/deployed-contracts#semaphore) --- # Glossary | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2/glossary#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/glossary) ** (V4). Version: V2 On this page Semaphore identity[​](https://docs.semaphore.pse.dev/V2/glossary#semaphore-identity "Direct link to heading") -------------------------------------------------------------------------------------------------------------- The identity of a user in the Semaphore protocol. An identity contains the following three values: * [Identity commitment](https://docs.semaphore.pse.dev/V2/glossary#identity-commitment) : the public value. * Identity trapdoor and identity nullifier: secret values known only by the user. Semaphore group[​](https://docs.semaphore.pse.dev/V2/glossary#semaphore-group "Direct link to heading") -------------------------------------------------------------------------------------------------------- A group is a binary incremental [Merkle tree](https://docs.semaphore.pse.dev/V2/glossary#merkle-tree) in which each leaf contains an [identity commitment](https://docs.semaphore.pse.dev/V2/glossary#identity-commitment) for a user. The identity commitment proves that the user is a group member without revealing the Semaphore identity of the user. Semaphore uses the **Poseidon** hash function to create Merkle trees. For more information, see the [Poseidon website](https://www.poseidon-hash.info/) . Identity commitment[​](https://docs.semaphore.pse.dev/V2/glossary#identity-commitment "Direct link to heading") ---------------------------------------------------------------------------------------------------------------- The public [Semaphore identity](https://docs.semaphore.pse.dev/V2/glossary#semaphore-identity) value used in [Semaphore groups](https://docs.semaphore.pse.dev/V2/glossary#semaphore-group) . Semaphore uses the **Poseidon** hash function to create the identity commitment from the Semaphore identity secret values. For more information, see the [Poseidon website](https://www.poseidon-hash.info/) . Merkle tree[​](https://docs.semaphore.pse.dev/V2/glossary#merkle-tree "Direct link to heading") ------------------------------------------------------------------------------------------------ A tree in which every leaf (i.e., a node that doesn't have children) is labelled with the cryptographic hash of a data block, and every node that isn't a leaf is labelled with the cryptographic hash of its child node labels. In zero-knowledge protocols, Merkle trees can be used to efficiently summarize and validate large data sets. To validate that a tree contains a specific leaf, a verifier only needs a portion of the complete data structure. For more information, see [Merkle tree in Wikipedia](https://en.wikipedia.org/wiki/Merkle_tree) . Nullifier[​](https://docs.semaphore.pse.dev/V2/glossary#nullifier "Direct link to heading") -------------------------------------------------------------------------------------------- A value used to prevent double entry or double signalling. See [Circuit nullifier hash](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#nullifier-hash) . Relay[​](https://docs.semaphore.pse.dev/V2/glossary#relay "Direct link to heading") ------------------------------------------------------------------------------------ A third-party who receives a fee for including relayed transactions in the blockchain (McMenamin, Daza, and Fitz. [https://eprint.iacr.org/2022/155.pdf](https://eprint.iacr.org/2022/155.pdf) , p.3). To preserve the anonymity of the user broadcasting a signal with Semaphore, an application may use a relayer to post the signal transaction to Ethereum on behalf of the user. Applications may provide rewards for relayers and implement front-running prevention mechanisms, such as requiring the signals to include the relayer’s address, binding the signal to that specific address ([https://semaphore.pse.dev/whitepaper-v1.pdf](https://semaphore.pse.dev/whitepaper-v1.pdf) , p.6). Trusted setup files[​](https://docs.semaphore.pse.dev/V2/glossary#trusted-setup-files "Direct link to heading") ---------------------------------------------------------------------------------------------------------------- The secure, verifiable parameters generated by Semaphore's trusted setup ceremony. Semaphore uses the trusted setup files to generate and verify valid zero-knowledge proofs. To generate or verify valid zero-knowledge proofs with Semaphore, applications must include the following Semaphore _trusted setup_ files: * semaphore.zkey * semaphore.wasm * semaphore.json For a complete list of ready-to-use files, see [trusted-setup-pse.org](https://www.trusted-setup-pse.org/) . To learn more, see the [trusted setup ceremony](https://storage.googleapis.com/trustedsetup-a86f4.appspot.com/semaphore/semaphore_top_index.html) . * [Semaphore identity](https://docs.semaphore.pse.dev/V2/glossary#semaphore-identity) * [Semaphore group](https://docs.semaphore.pse.dev/V2/glossary#semaphore-group) * [Identity commitment](https://docs.semaphore.pse.dev/V2/glossary#identity-commitment) * [Merkle tree](https://docs.semaphore.pse.dev/V2/glossary#merkle-tree) * [Nullifier](https://docs.semaphore.pse.dev/V2/glossary#nullifier) * [Relay](https://docs.semaphore.pse.dev/V2/glossary#relay) * [Trusted setup files](https://docs.semaphore.pse.dev/V2/glossary#trusted-setup-files) --- # Resources | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2/resources#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/resources) ** (V4). Version: V2 [Semaphore V2 is Live!](https://medium.com/privacy-scaling-explorations/semaphore-v2-is-live-f263e9372579) - Privacy and Scaling Explorations [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 --- # Identities | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2/guides/identities#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/guides/identities) ** (V4). Version: V2 On this page In order to join a [Semaphore group](https://docs.semaphore.pse.dev/V2/glossary#semaphore-group) , a user must first create a [Semaphore identity](https://docs.semaphore.pse.dev/V2/glossary#semaphore-identity) . A Semaphore identity contains two values generated with the identity: * 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[​](https://docs.semaphore.pse.dev/V2/guides/identities#create-identities "Direct link to heading") --------------------------------------------------------------------------------------------------------------------- In your code, use the [`@semaphore-protocol/identity`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/identity) library to create a Semaphore identity _deterministically_ (from the hash of a message) or _randomly_. * [**Create random identities**](https://docs.semaphore.pse.dev/V2/guides/identities#create-random-identities) * [**Create deterministic identities**](https://docs.semaphore.pse.dev/V2/guides/identities#create-deterministic-identities) ### Create random identities[​](https://docs.semaphore.pse.dev/V2/guides/identities#create-random-identities "Direct link to heading") To create a random identity, instantiate `Identity` without any parameters--for example: import { Identity } from "@semaphore-protocol/identity"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_. 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 Ethereum private keys and are used to generate Semaphore zero-knowledge proofs and authenticate signals. ### Create deterministic identities[​](https://docs.semaphore.pse.dev/V2/guides/identities#create-deterministic-identities "Direct link to heading") If you pass a message as a parameter, Semaphore generates `trapdoor` and `nullifier` 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. Given that the hash is deterministic, anyone with the same message can recreate the same identity. const identity = new Identity("secret-message") tip Building a system to save or recover secret values of Semaphore identities is nontrivial. You may choose to delegate such functionality to existing wallets such as Metamask--for example: 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. 3. The user can now recreate their Semaphore identity whenever they want by signing the same message with their Ethereum account in Metamask. Save your identities[​](https://docs.semaphore.pse.dev/V2/guides/identities#save-your-identities "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------- You can output an identity as a JSON string that you can save and reuse later. The `Identity.toString()` method generates a JSON array from an identity--for example: console.log(identity.toString()) // View the identity trapdoor and nullifier.// '["8255d...", "62c41..."]' The array contains the trapdoor and nullifier. To reuse the saved identity, pass the JSON to the `Identity()` constructor. const identity2 = new Identity(identity.toString()) * [Create identities](https://docs.semaphore.pse.dev/V2/guides/identities#create-identities) * [Create random identities](https://docs.semaphore.pse.dev/V2/guides/identities#create-random-identities) * [Create deterministic identities](https://docs.semaphore.pse.dev/V2/guides/identities#create-deterministic-identities) * [Save your identities](https://docs.semaphore.pse.dev/V2/guides/identities#save-your-identities) --- # Subgraph | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2/subgraph#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/subgraph) ** (V4). Version: V2 On this page [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. Semaphore's subgraph allows you to retrieve data from the [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/Semaphore.sol) smart contract. tip The Graph protocol uses the [GraphQL](https://graphql.org/) query language. For examples, see the [GraphQL API documentation](https://thegraph.com/docs/developer/graphql-api) . Visit the [subgraph repository](https://github.com/semaphore-protocol/subgraph) to see the list of Semaphore subgraphs. Schema[​](https://docs.semaphore.pse.dev/V2/subgraph#schema "Direct link to heading") -------------------------------------------------------------------------------------- ### MerkleTree[​](https://docs.semaphore.pse.dev/V2/subgraph#merkletree "Direct link to heading") * `id`: unique identifier among all MerkleTree entities, * `depth`: Merkle tree depth, * `root`: Merkle tree root, * `zeroValue`: Merkle tree zero value, * `numberOfLeaves`: total number of tree leaves, * `group`: link to the Group entity. ### Group[​](https://docs.semaphore.pse.dev/V2/subgraph#group "Direct link to heading") * `id`: unique identifier among all Group entities, * `merkleTree`: link to the MerkleTree entity, * `timestamp`: block timestamp, * `admin`: admin of the group, * `members`: list of group members. * `verifiedProofs`: list of group proofs. ### Member[​](https://docs.semaphore.pse.dev/V2/subgraph#member "Direct link to heading") * `id`: unique identifier among all Member entities, * `identityCommitment`: Semaphore identity commitment, * `timestamp`: block timestamp, * `index`: index of the tree leaf, * `group`: link to the Group entity. ### VerifiedProof[​](https://docs.semaphore.pse.dev/V2/subgraph#verifiedproof "Direct link to heading") * `id`: unique identifier among all VerifiedProof entities, * `signal`: user's signal, * `merkleTreeRoot`: Merkle tree root, * `nullifierHash`: nullifier hash, * `externalNullifier`: external nullifier, * `timestamp`: block timestamp, * `group`: link to the Group entity. * [Schema](https://docs.semaphore.pse.dev/V2/subgraph#schema) * [MerkleTree](https://docs.semaphore.pse.dev/V2/subgraph#merkletree) * [Group](https://docs.semaphore.pse.dev/V2/subgraph#group) * [Member](https://docs.semaphore.pse.dev/V2/subgraph#member) * [VerifiedProof](https://docs.semaphore.pse.dev/V2/subgraph#verifiedproof) --- # Groups | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2/guides/groups#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/guides/groups) ** (V4). Version: V2 On this page Use Semaphore in your application or smart contract to create off-chain and on-chain groups. A [Semaphore group](https://docs.semaphore.pse.dev/V2/glossary#semaphore-group) contains [identity commitments](https://docs.semaphore.pse.dev/V2/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. A Semaphore group is an [incremental Merkle tree](https://docs.semaphore.pse.dev/V2/glossary#merkle-tree) , and group members (i.e., [identity commitments](https://docs.semaphore.pse.dev/V2/glossary#identity-commitment) ) are tree leaves. Semaphore groups set the following two parameters: * **Tree depth**: the maximum number of members a group can contain (`max size = 2 ^ tree depth`). * **Zero value**: the value used to calculate the zero nodes of the incremental Merkle tree. Learn how to work with groups. * [**Off-chain groups**](https://docs.semaphore.pse.dev/V2/guides/groups#off-chain-groups) * [**On-chain groups**](https://docs.semaphore.pse.dev/V2/guides/groups#on-chain-groups) Off-chain groups[​](https://docs.semaphore.pse.dev/V2/guides/groups#off-chain-groups "Direct link to heading") --------------------------------------------------------------------------------------------------------------- * [Create a group](https://docs.semaphore.pse.dev/V2/guides/groups#create-a-group) * [Add members](https://docs.semaphore.pse.dev/V2/guides/groups#add-members) * [Remove or update members](https://docs.semaphore.pse.dev/V2/guides/groups#remove-or-update-members) ### Create a group[​](https://docs.semaphore.pse.dev/V2/guides/groups#create-a-group "Direct link to heading") Use the [`@semaphore-protocol/group`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/group) library `Group` class to create an off-chain group. #### Options[​](https://docs.semaphore.pse.dev/V2/guides/groups#options "Direct link to heading") * **Tree depth**: (_default `20`_) the maximum number of members a group can contain (`max size = 2 ^ tree depth`). * **Zero value**: (_default `BigInt(0)`_) the value for a tree node that doesn't have a member assigned. To create a group with default _`treeDepth`_ and _`zeroValue`_, call the `Group` constructor without parameters--for example: import { Group } from "@semaphore-protocol/group"// Default parameters: treeDepth = 20, zeroValue = BigInt(0).const group = new Group() The following example code passes _`treeDepth`_ to create a group for `2 ^ 30 = 1073741824` members: import { Group } from "@semaphore-protocol/group"const group = new Group(30) The following example code creates a group with a _`zeroValue`_ of `BigInt(1)`: import { Group } from "@semaphore-protocol/group"const group = new Group(20, BigInt(1)) ### Add members[​](https://docs.semaphore.pse.dev/V2/guides/groups#add-members "Direct link to heading") Use the `Group addMember` function to add a member (identity commitment) to a group--for example: group.addMember(identityCommitment) To add a batch of members to a group, pass an array to the `Group addMembers` function--for example: group.addMembers([identityCommitment1, identityCommitment2]) ### Remove or update members[​](https://docs.semaphore.pse.dev/V2/guides/groups#remove-or-update-members "Direct link to heading") To remove members from a group, pass the member index to the `Group removeMember` function--for example: group.removeMember(0) To update members in a group, pass the member index and the new value to the `Group updateMember` function--for example: group.updateMember(0, 2) caution Removing a member from a group sets the node value to `zeroValue`. Given that the node isn't removed, and the length of the `group.members` array doesn't change. On-chain groups[​](https://docs.semaphore.pse.dev/V2/guides/groups#on-chain-groups "Direct link to heading") ------------------------------------------------------------------------------------------------------------- The [`SemaphoreGroups`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/contracts/base/SemaphoreGroups.sol) contract uses the [`IncrementalBinaryTree`](https://github.com/privacy-scaling-explorations/zk-kit/blob/main/packages/incremental-merkle-tree.sol/contracts/IncrementalBinaryTree.sol) library and provides methods to create and manage groups. info You can import `SemaphoreGroups` and other Semaphore contracts from the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts) NPM module. Alternatively, you can use an already deployed [`Semaphore`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/contracts/Semaphore.sol) contract and use its group external functions. * [Off-chain groups](https://docs.semaphore.pse.dev/V2/guides/groups#off-chain-groups) * [Create a group](https://docs.semaphore.pse.dev/V2/guides/groups#create-a-group) * [Add members](https://docs.semaphore.pse.dev/V2/guides/groups#add-members) * [Remove or update members](https://docs.semaphore.pse.dev/V2/guides/groups#remove-or-update-members) * [On-chain groups](https://docs.semaphore.pse.dev/V2/guides/groups#on-chain-groups) --- # Circuits | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/technical-reference/circuits) ** (V4). Version: V2 On this page The [Semaphore circuit](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/circuits) is the heart of the protocol and consists of three parts: * [**Proof of membership**](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#proof-of-membership) * [**Nullifier hash**](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#nullifier-hash) * [**Signal**](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#signal) ![Semaphore circuit](https://github.com/semaphore-protocol/semaphore/raw/v2.6.1/packages/circuits/scheme.png) The diagram above shows how the input signals are used in the Semaphore circuit and how the outputs are calculated. Proof of membership[​](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#proof-of-membership "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------ The circuit hashes the hash of the identity nullifier with the identity trapdoor to generate an identity commitment. Then, it verifies the proof of membership against the Merkle root and the identity commitment. **Private inputs:** * `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, * `identityNullifier`: the 32-byte identity secret used as nullifier, * `identityTrapdoor`: the 32-byte identity secret used as trapdoor. **Public outputs:** * `root`: The Merkle root of the tree. Nullifier hash[​](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#nullifier-hash "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------- The circuit hashes the identity nullifier with the external nullifier and then checks that the result matches the provided nullifier hash. Nullifier hashes saved in a Semaphore smart contract allow the contract to reject a proof that contains a used nullifier hash. **Private inputs:** * `identityNullifier`: the 32-byte identity secret used as a nullifier. **Public inputs:** * `externalNullifier`: the 32-byte external nullifier. **Public outputs:** * `nullifierHash`: the hash of the identity nullifier and the external nullifier; used to prevent double-signaling. Signal[​](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#signal "Direct link to heading") ---------------------------------------------------------------------------------------------------------- The circuit calculates a dummy square of the signal hash to prevent any tampering with the proof. **Public inputs:** * `signalHash`: the hash of the user's signal. * [Proof of membership](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#proof-of-membership) * [Nullifier hash](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#nullifier-hash) * [Signal](https://docs.semaphore.pse.dev/V2/technical-reference/circuits#signal) --- # Proofs | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2/guides/proofs#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/guides/proofs) ** (V4). Version: V2 On this page Learn how to use Semaphore to generate and verify zero-knowledge proofs. Once a user joins their [Semaphore identity](https://docs.semaphore.pse.dev/V2/glossary#semaphore-identity) to a [Semaphore group](https://docs.semaphore.pse.dev/V2/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. Developers can use Semaphore for the following: * [**Generate a proof off-chain**](https://docs.semaphore.pse.dev/V2/guides/proofs#generate-a-proof-off-chain) * [**Verify a proof off-chain**](https://docs.semaphore.pse.dev/V2/guides/proofs#verify-a-proof-off-chain) * [**Verify a proof on-chain**](https://docs.semaphore.pse.dev/V2/guides/proofs#verify-a-proof-on-chain) Generate a proof off-chain[​](https://docs.semaphore.pse.dev/V2/guides/proofs#generate-a-proof-off-chain "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------- Use the [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/proof) library to generate an off-chain proof. To generate a proof, pass the following properties 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](https://docs.semaphore.pse.dev/V2/glossary#trusted-setup-files) . In the voting system use case, once all the voters have joined their [identities](https://docs.semaphore.pse.dev/guides/identities#create-identities) to the ballot [group](https://docs.semaphore.pse.dev/guides/groups) , a voter can generate a proof to vote for a proposal. In the call to `generateProof`, the voting system passes the unique ballot ID (the [Merkle tree](https://docs.semaphore.pse.dev/V2/glossary#merkle-tree) root of the group) as the `externalNullifier` to prevent the voter signaling more than once for the ballot. The following code sample shows how to use `generateProof` to generate the voting proof: import { generateProof } from "@semaphore-protocol/proof"const externalNullifier = group.rootconst signal = "proposal_1"const fullProof = await generateProof(identity, group, externalNullifier, signal, { zkeyFilePath: "./semaphore.zkey", wasmFilePath: "./semaphore.wasm"}) Verify a proof off-chain[​](https://docs.semaphore.pse.dev/V2/guides/proofs#verify-a-proof-off-chain "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------- Use the [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/proof) library to verify a Semaphore proof off-chain. To verify a proof, pass the following to the `verifyProof` function: * _`proof`_: the Semaphore proof. * _`verificationKey`_: the JavaScript object in the `semaphore.json` [trusted setup file](https://docs.semaphore.pse.dev/V2/glossary#trusted-setup-files) . The following code sample shows how to parse the verification key object from `semaphore.json` and verify the previously generated proof: import { verifyProof } from "@semaphore-protocol/proof"const verificationKey = JSON.parse(fs.readFileSync("./semaphore.json", "utf-8"))await verifyProof(verificationKey, fullProof) // true or false. `verifyProof` returns a Promise that resolves to `true` or `false`. Verify a proof on-chain[​](https://docs.semaphore.pse.dev/V2/guides/proofs#verify-a-proof-on-chain "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------- Use the [`SemaphoreCore`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/contracts/base/SemaphoreCore.sol) contract to verify proofs on-chain. It uses a verifier deployed to Ethereum and provides methods hash the signal and verify a proof. info You can import `SemaphoreCore` and other Semaphore contracts from the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts) NPM module. To verify Semaphore proofs in your contract, import `SemaphoreCore` and pass the following to the `_verifyProof` internal method: * _`signal`_: The Semaphore signal to prove. * _`root`_: The root of the Merkle tree. * _`nullifierHash`_: a [nullifier hash](https://docs.semaphore.pse.dev/V2/guides/proofs#retrieve-a-nullifier-hash) . * _`externalNullifier`_: The external nullifier. * _`proof`_: A [_Solidity-compatible_ Semaphore proof](https://docs.semaphore.pse.dev/V2/guides/proofs#generate-a-solidity-compatible-proof) . * _`verifier`_: The verifier address. Remember to save the `nullifierHash` on-chain to avoid double-signaling. Alternatively, you can use an already deployed [`Semaphore`](https://github.com/semaphore-protocol/semaphore/blob/v2.6.1/packages/contracts/contracts/Semaphore.sol) contract and use its `verifyProof` external function. ### Generate a Solidity-compatible proof[​](https://docs.semaphore.pse.dev/V2/guides/proofs#generate-a-solidity-compatible-proof "Direct link to heading") To transform a proof to be compatible with Solidity contracts, pass the proof to the `packToSolidityProof` utility function--for example: import { packToSolidityProof } from "@semaphore-protocol/proof"const solidityProof = packToSolidityProof(fullProof.proof) Semaphore returns a new Solidity-compatible instance of the proof. ### Retrieve a nullifier hash[​](https://docs.semaphore.pse.dev/V2/guides/proofs#retrieve-a-nullifier-hash "Direct link to heading") To get the Semaphore proof nullifier hash, access the proof's `publicSignals.nullifierHash` property--for example: const { nullifierHash } = fullProof.publicSignals * [Generate a proof off-chain](https://docs.semaphore.pse.dev/V2/guides/proofs#generate-a-proof-off-chain) * [Verify a proof off-chain](https://docs.semaphore.pse.dev/V2/guides/proofs#verify-a-proof-off-chain) * [Verify a proof on-chain](https://docs.semaphore.pse.dev/V2/guides/proofs#verify-a-proof-on-chain) * [Generate a Solidity-compatible proof](https://docs.semaphore.pse.dev/V2/guides/proofs#generate-a-solidity-compatible-proof) * [Retrieve a nullifier hash](https://docs.semaphore.pse.dev/V2/guides/proofs#retrieve-a-nullifier-hash) --- # Credits | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/credits#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/credits) ** (V4). Version: V3 Semaphore is the work of several people, for a complete list of contributors you can visit our [Github pages](https://github.com/semaphore-protocol/semaphore/graphs/contributors) . * [Barry WhiteHat](https://github.com/barryWhiteHat) * [Kobi Gurkan](https://github.com/kobigurk) * [Koh Wei Jie](https://github.com/weijiekoh) * [Andrija Novakovic](https://github.com/akinovak) * [Cedoor](https://github.com/cedoor) * [Rachel Aux](https://github.com/rachelaux) * [Andy Guzman](https://github.com/aguzmant103) * [Vivian Plasencia](https://github.com/vplasencia) * [LauNaMu](https://github.com/0xyNaMu) --- # What Is Semaphore? | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V3 On this page Overview[​](https://docs.semaphore.pse.dev/V3#overview "Direct link to heading") --------------------------------------------------------------------------------- [Semaphore](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2) is a [zero-knowledge](https://z.cash/technology/zksnarks) protocol that allows you to cast a signal (for example, a vote or endorsement) as a provable group member without revealing your identity. Additionally, it provides a simple mechanism to prevent double-signaling. Use cases include private voting, whistleblowing, anonymous DAOs and mixers. Features[​](https://docs.semaphore.pse.dev/V3#features "Direct link to heading") --------------------------------------------------------------------------------- With Semaphore, you can allow your users to do the following: 1. [Create a Semaphore identity](https://docs.semaphore.pse.dev/V3/guides/identities) . 2. [Add their Semaphore identity to a group (i.e. _Merkle tree_)](https://docs.semaphore.pse.dev/V3/guides/groups) . 3. [Send a verifiable, anonymous signal (e.g a vote or endorsement)](https://docs.semaphore.pse.dev/V3/guides/proofs) . When a user broadcasts a signal (for example: a vote), Semaphore zero-knowledge proofs can ensure that the user has joined the group and hasn't already cast a signal with their nullifier. Semaphore uses on-chain Solidity contracts and off-chain JavaScript libraries that work in tandem. * Off chain, JavaScript libraries can be used to create identities, manage groups and generate proofs. * On chain, Solidity contracts can be used to manage groups and verify proofs. Developer benefits[​](https://docs.semaphore.pse.dev/V3#developer-benefits "Direct link to heading") ----------------------------------------------------------------------------------------------------- Semaphore is designed to be a simple and generic _privacy layer_ for decentralized applications (dApps) on Ethereum. It encourages modular application design, allowing dApp developers to choose and customize the on-chain and off-chain components they need. About the code[​](https://docs.semaphore.pse.dev/V3#about-the-code "Direct link to heading") --------------------------------------------------------------------------------------------- The core of the protocol is the [circuit logic](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/circuits/scheme.png) . In addition to circuits, Semaphore provides [Solidity contracts](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/contracts) and [JavaScript libraries](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2#-packages) that allow developers to generate zero-knowledge proofs and verify them with minimal effort. ### Trusted Setup Ceremony[​](https://docs.semaphore.pse.dev/V3#trusted-setup-ceremony "Direct link to heading") The [secure parameters](https://docs.semaphore.pse.dev/V3/glossary#trusted-setup-files) for generating valid proofs with Semaphore circuits were generated in a [Trusted Setup Ceremony](https://storage.googleapis.com/trustedsetup-a86f4.appspot.com/semaphore/semaphore_top_index.html) that was completed with over 300 participants on [29 March 2022](https://etherscan.io/tx/0xec6dbe68883c7593c2bea82f55af18b3aeb5cc146e026d0083a9b3faa9aa0b65#eventlog) . ### Audits[​](https://docs.semaphore.pse.dev/V3#audits "Direct link to heading") | 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` | info If you are using one of the previous versions of Semaphore, see the [Semaphore V1](https://docs.semaphore.pse.dev/V1) or the [Semaphore V2](https://docs.semaphore.pse.dev/V2) documentation. * [Overview](https://docs.semaphore.pse.dev/V3#overview) * [Features](https://docs.semaphore.pse.dev/V3#features) * [Developer benefits](https://docs.semaphore.pse.dev/V3#developer-benefits) * [About the code](https://docs.semaphore.pse.dev/V3#about-the-code) * [Trusted Setup Ceremony](https://docs.semaphore.pse.dev/V3#trusted-setup-ceremony) * [Audits](https://docs.semaphore.pse.dev/V3#audits) --- # Contracts | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2/technical-reference/contracts#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/technical-reference/contracts) ** (V4). Version: V2 On this page Semaphore includes three types of contracts: * [**Base contracts**](https://docs.semaphore.pse.dev/V2/technical-reference/contracts#base-contracts) * [**Extension contracts**](https://docs.semaphore.pse.dev/V2/technical-reference/contracts#extension-contracts) * [**Verifiers**](https://docs.semaphore.pse.dev/V2/technical-reference/contracts#verifiers) info To use Semaphore contracts and interfaces in your project, install the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts) NPM package. Base contracts[​](https://docs.semaphore.pse.dev/V2/technical-reference/contracts#base-contracts "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------- Semaphore provides the following base contracts: * [`SemaphoreCore.sol`](https://github.com/semaphore-protocol/semaphore/blob/v2.6.1/packages/contracts/contracts/base/SemaphoreCore.sol) : contains the functions to verify Semaphore proofs; * [`SemaphoreGroups.sol`](https://github.com/semaphore-protocol/semaphore/blob/v2.6.1/packages/contracts/contracts/base/SemaphoreGroups.sol) : contains the functions to create groups and add/remove members. These contracts are closely related to the protocol. You can inherit them in your contract or you can use [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/contracts/Semaphore.sol) , which inherits them for you. See our [deployed contracts](https://docs.semaphore.pse.dev/V2/deployed-contracts#semaphore) to find the addresses for your network. info While some dApps may use on-chain groups, others may prefer to use off-chain groups, saving only their tree roots in the contract. Extension contracts[​](https://docs.semaphore.pse.dev/V2/technical-reference/contracts#extension-contracts "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------- * [`SemaphoreVoting.sol`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/contracts/extensions/SemaphoreVoting.sol) : voting contract that contains the essential functions to create polls, add voters, and anonymously cast votes. * [`SemaphoreWhistleblowing.sol`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/contracts/extensions/SemaphoreWhistleblowing.sol) : whistleblowing contract that contains the essential functions to create entities (for example: non-profit organizations), add whistleblowers, and anonymously publish leaks. These contracts extend the protocol to provide application logic for specific use-cases. More extensions will be added in the future. Verifiers[​](https://docs.semaphore.pse.dev/V2/technical-reference/contracts#verifiers "Direct link to heading") ----------------------------------------------------------------------------------------------------------------- To verify Semaphore proofs, the [`SemaphoreCore.sol`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/contracts/base/SemaphoreCore.sol) contract requires the address of a deployed verifier contract. You can choose to manually deploy the [verifier](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/contracts/verifiers) you prefer or you can use one of our [deployed verifiers](https://docs.semaphore.pse.dev/V2/deployed-contracts#verifiers) . Each verifier name indicates the tree depth that it can verify. For example, given a Semaphore proof generated with a tree depth `20`: * The `Verifier20.sol` contract can verify the proof. * The [group](https://docs.semaphore.pse.dev/V2/guides/groups) used for the proof can have a maximum `2^20=1048576` members. * [Base contracts](https://docs.semaphore.pse.dev/V2/technical-reference/contracts#base-contracts) * [Extension contracts](https://docs.semaphore.pse.dev/V2/technical-reference/contracts#extension-contracts) * [Verifiers](https://docs.semaphore.pse.dev/V2/technical-reference/contracts#verifiers) --- # Glossary | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/glossary#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/glossary) ** (V4). Version: V3 On this page Semaphore identity[​](https://docs.semaphore.pse.dev/V3/glossary#semaphore-identity "Direct link to heading") -------------------------------------------------------------------------------------------------------------- The identity of a user in the Semaphore protocol. An identity contains the following three values: * [Identity commitment](https://docs.semaphore.pse.dev/V3/glossary#identity-commitment) : the public value. * Identity trapdoor and identity nullifier: secret values known only by the user. Identity commitment[​](https://docs.semaphore.pse.dev/V3/glossary#identity-commitment "Direct link to heading") ---------------------------------------------------------------------------------------------------------------- The public [Semaphore identity](https://docs.semaphore.pse.dev/V3/glossary#semaphore-identity) value used in [Semaphore groups](https://docs.semaphore.pse.dev/V3/glossary#semaphore-group) . Semaphore uses the [Poseidon](https://www.poseidon-hash.info/) hash function to create the identity commitment from the Semaphore identity secret values. Semaphore group[​](https://docs.semaphore.pse.dev/V3/glossary#semaphore-group "Direct link to heading") -------------------------------------------------------------------------------------------------------- A group is a binary incremental [Merkle tree](https://docs.semaphore.pse.dev/V3/glossary#merkle-tree) in which each leaf contains an [identity commitment](https://docs.semaphore.pse.dev/V3/glossary#identity-commitment) for a user. The identity commitment proves that the user is a group member without revealing the Semaphore identity of the user. Semaphore uses the **Poseidon** hash function to create Merkle trees. For more information, see the [Poseidon website](https://www.poseidon-hash.info/) . Merkle tree[​](https://docs.semaphore.pse.dev/V3/glossary#merkle-tree "Direct link to heading") ------------------------------------------------------------------------------------------------ A tree in which every leaf (i.e., a node that doesn't have children) is labelled with the cryptographic hash of a data block, and every node that isn't a leaf is labelled with the cryptographic hash of its child node labels. In zero-knowledge protocols, Merkle trees can be used to efficiently summarize and validate large data sets. To validate that a tree contains a specific leaf, a verifier only needs a portion of the complete data structure. For more information, see [Merkle tree in Wikipedia](https://en.wikipedia.org/wiki/Merkle_tree) . Nullifier[​](https://docs.semaphore.pse.dev/V3/glossary#nullifier "Direct link to heading") -------------------------------------------------------------------------------------------- A value used to prevent double entry or double signaling. See [Circuit nullifier hash](https://docs.semaphore.pse.dev/V3/technical-reference/circuits#nullifier-hash) . Relay[​](https://docs.semaphore.pse.dev/V3/glossary#relay "Direct link to heading") ------------------------------------------------------------------------------------ A third-party who receives a fee for including relayed transactions in the blockchain (McMenamin, Daza, and Fitz. [https://eprint.iacr.org/2022/155.pdf](https://eprint.iacr.org/2022/155.pdf) , p.3). To preserve the anonymity of the user broadcasting a signal with Semaphore, an application may use a relayer to post the signal transaction to Ethereum on behalf of the user. Applications may provide rewards for relayers and implement front-running prevention mechanisms, such as requiring the signals to include the relayer’s address, binding the signal to that specific address ([https://semaphore.pse.dev/whitepaper-v1.pdf](https://semaphore.pse.dev/whitepaper-v1.pdf) , p.6). Trusted setup files[​](https://docs.semaphore.pse.dev/V3/glossary#trusted-setup-files "Direct link to heading") ---------------------------------------------------------------------------------------------------------------- The secure, verifiable parameters generated by Semaphore's trusted setup ceremony. Semaphore uses the trusted setup files to generate and verify valid zero-knowledge proofs. To generate or verify valid zero-knowledge proofs with Semaphore, applications must include the following Semaphore _trusted setup_ files: * semaphore.zkey * semaphore.wasm * semaphore.json For a complete list of ready-to-use files, see [trusted-setup-pse.org](https://www.trusted-setup-pse.org/) . To learn more, see the [trusted setup ceremony](https://storage.googleapis.com/trustedsetup-a86f4.appspot.com/semaphore/semaphore_top_index.html) . Signals[​](https://docs.semaphore.pse.dev/V3/glossary#signals "Direct link to heading") ---------------------------------------------------------------------------------------- The term "signals" in Semaphore refers to the values the user broadcasts when voting, confirming, sending a message and so on. On the other hand, "[signals](https://docs.circom.io/circom-language/signals/) " in Circom refers to data that contain elements within the field of Z/pZ. In Circom, "signals" can be defined as input or output, and are considered intermediate signals otherwise. * [Semaphore identity](https://docs.semaphore.pse.dev/V3/glossary#semaphore-identity) * [Identity commitment](https://docs.semaphore.pse.dev/V3/glossary#identity-commitment) * [Semaphore group](https://docs.semaphore.pse.dev/V3/glossary#semaphore-group) * [Merkle tree](https://docs.semaphore.pse.dev/V3/glossary#merkle-tree) * [Nullifier](https://docs.semaphore.pse.dev/V3/glossary#nullifier) * [Relay](https://docs.semaphore.pse.dev/V3/glossary#relay) * [Trusted setup files](https://docs.semaphore.pse.dev/V3/glossary#trusted-setup-files) * [Signals](https://docs.semaphore.pse.dev/V3/glossary#signals) --- # Private voting use case | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V2**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V2 On this page The private voting use case describes how Semaphore interacts with your users and Ethereum to allow users to cast private votes in your application. Learn how Semaphore enables applications to do the following: * Register members as voters. * Allow members to vote anonymously. * Prove voter membership. * Record and prove votes. * Prevent double-voting. Roles[​](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#roles "Direct link to heading") ---------------------------------------------------------------------------------------------------- * **[Developer or community admin](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#developer-or-community-admin) ** * **[Community member (dApp user)](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#community-member) ** * **[Relay](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#relay) ** ### Developer or community admin[​](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#developer-or-community-admin "Direct link to heading") As a developer or community admin, you deploy the following: * **Smart contract on Ethereum**: implements the Semaphore **base contract** to create a poll (Semaphore **group** that members join to vote), post transactions, and verify proofs on Ethereum. * **Decentralized application (dApp)**: your application that provides a user interface (UI) where members join a poll and vote on a proposal. ### Community member[​](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#community-member "Direct link to heading") Community members connect their wallets to the dApp to take the following actions: 1. Verify ownership of the community token. 2. Generate an anonymous ID. 3. Cast a vote. ### Relay[​](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#relay "Direct link to heading") To preserve anonymity and avoid disclosing the member's wallet address, the dApp may use a [relay](https://docs.semaphore.pse.dev/V2/glossary#relay) to broadcast the vote. The relay calls the **contract** function that then posts the member's vote transaction to Ethereum. Private voting[​](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#private-voting "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------- Consider a scenario where your community issues a token that users can mint. The token might be a Proof of Attendance (POAP), NFT, or social token that your users can mint to receive membership and vote in your community. The voting scenario has the following steps: 1. [Create a poll](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#create-a-poll) : Coordinator creates a poll, or _group_, in which members can vote on a proposal. 2. [Register voters](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#register-voters) : Members join the poll to vote. 3. [Record votes](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#record-votes) : Once the poll opens, members may cast one vote, or _signal_, on the topic. ### Create a poll[​](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#create-a-poll "Direct link to heading") A community coordinator or dApp administrator uses the deployed smart contract to create an on-chain (Ethereum) poll, a [Semaphore group](https://docs.semaphore.pse.dev/V2/guides/groups) that members can join and cast votes to. In the following sample code, the voting contract declares a `createPoll` function that uses the Semaphore base `_createGroup` function: https://github.com/semaphore-protocol/semaphore/blob/v3.15.1/packages/contracts/contracts/extensions/SemaphoreVoting.sol function createPoll( uint256 pollId, address coordinator, uint8 depth) public override { require(address(verifiers[depth]) != address(0), "SemaphoreVoting: depth value is not supported"); _createGroup(pollId, depth, 0); Poll memory poll; poll.coordinator = coordinator; polls[pollId] = poll; emit PollCreated(pollId, coordinator);} A poll is a Semaphore [group](https://docs.semaphore.pse.dev/V2/guides/groups) that stores the following: * A topic to vote on. * The public ID of the poll creator. * [Semaphore IDs](https://docs.semaphore.pse.dev/V2/guides/identities) of members who joined the poll. To create the poll, the administrator calls the smart contract function--for example: SemaphoreVoting.createPoll(pollId, coordinator, depth) Next, learn how to [register voters](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#register-voters) for the poll. ### Register voters[​](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#register-voters "Direct link to heading") Before a user can register to vote, the dApp needs to verify membership by checking the user's wallet for the NFT. To grant access to the wallet, the user clicks a `Connect wallet` button in the dApp and allows the dApp to check for the NFT. Once a member is verified, the dApp provides the following member interactions: 1. [Generate a private identity](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#generate-a-private-identity) . 2. [Join a poll](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#join-a-poll) . info To learn how to connect to Ethereum wallets, visit the [ethers.js Getting Started documentation](https://docs.ethers.io/v5/getting-started) . #### Generate a private identity[​](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#generate-a-private-identity "Direct link to heading") To generate a private identity, the member completes a form in the dApp UI. With the form values and the `@semaphore-protocol/identity` library, the dApp prompts the member to sign a wallet message and then generates the signed private identity. The private identity is known only to the member and can be used in future interactions with the dApp. Next, learn how members [join a poll](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#join-a-poll) . #### Join a poll[​](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#join-a-poll "Direct link to heading") Once the member has a private identity for the dApp, the member may select a poll to vote in. When the member selects a poll, the dApp does the following: 1. Uses the `@semaphore-protocol/identity` library to generate an anonymous Semaphore ID, or _identity commitment_, from the private identity. 2. Calls a contract function that adds the new Semaphore ID to the on-chain poll. With a member registered for a poll, learn how the dApp [records votes](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#record-votes) . ### Record votes[​](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#record-votes "Direct link to heading") Once members have joined a poll, the coordinator starts the poll to allow voting. When a member votes (for example, by selecting a radio button), then the dApp takes the following actions: 1. Uses the `@semaphore-protocol/proof` library to create a proof of the vote, the poll identifier, the Semaphore ID, and a [nullifier](https://docs.semaphore.pse.dev/V2/glossary#nullifier) that prevents double-voting. 2. Sends the vote proof to the [relay](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#relay) . ### Related[​](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#related "Direct link to heading") * To get started developing with Semaphore, see the [Quick setup](https://docs.semaphore.pse.dev/V2/quick-setup) guide. * For an example app that you can use to start your own project, see [Semaphore boilerplate](https://github.com/semaphore-protocol/boilerplate) . * [Roles](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#roles) * [Developer or community admin](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#developer-or-community-admin) * [Community member](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#community-member) * [Relay](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#relay) * [Private voting](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#private-voting) * [Create a poll](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#create-a-poll) * [Register voters](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#register-voters) * [Record votes](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#record-votes) * [Related](https://docs.semaphore.pse.dev/V2/use-cases/private-voting#related) --- # Deployed contracts | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/deployed-contracts#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/deployed-contracts) ** (V4). Version: V3 | Contract | Goerli\* | Sepolia | Mumbai | Optimism Goerli\* | Arbitrum Goerli\* | Arbitrum One | | --- | --- | --- | --- | --- | --- | --- | | Semaphore.sol | [0x3889...6131](https://goerli.etherscan.io/address/0x3889927F0B5Eb1a02C6E2C20b39a1Bd4EAd76131) | [0x3889...6131](https://sepolia.etherscan.io/address/0x3889927F0B5Eb1a02C6E2C20b39a1Bd4EAd76131) | [0x3889...6131](https://mumbai.polygonscan.com/address/0x3889927F0B5Eb1a02C6E2C20b39a1Bd4EAd76131) | [0x3889...6131](https://goerli-optimism.etherscan.io/address/0x3889927F0B5Eb1a02C6E2C20b39a1Bd4EAd76131) | [0x3889...6131](https://goerli.arbiscan.io/address/0x3889927F0B5Eb1a02C6E2C20b39a1Bd4EAd76131) | [0xc60E...1520](https://arbiscan.io/address/0xc60E0Ee1a2770d5F619858C641f14FC4a6401520) | | SemaphoreVerifier.sol | [0xb908...217C](https://goerli.etherscan.io/address/0xb908Bcb798e5353fB90155C692BddE3b4937217C) | [0xb908...217C](https://sepolia.etherscan.io/address/0xb908Bcb798e5353fB90155C692BddE3b4937217C) | [0xb908...217C](https://mumbai.polygonscan.com/address/0xb908Bcb798e5353fB90155C692BddE3b4937217C) | [0xb908...217C](https://goerli-optimism.etherscan.io/address/0xb908Bcb798e5353fB90155C692BddE3b4937217C) | [0xb908...217C](https://goerli.arbiscan.io/address/0xb908Bcb798e5353fB90155C692BddE3b4937217C) | [0xCAbe...4d07](https://arbiscan.io/address/0xCAbeED6cB96a287000aBd834b0B79c05e6Ea4d07) | | Pairing.sol | [0xEe44...d7e8](https://goerli.etherscan.io/address/0xEe44c1e83A768E80A3588B409f1A010f9D1dd7e8) | [0xEe44...d7e8](https://sepolia.etherscan.io/address/0xEe44c1e83A768E80A3588B409f1A010f9D1dd7e8) | [0xEe44...d7e8](https://mumbai.polygonscan.com/address/0xEe44c1e83A768E80A3588B409f1A010f9D1dd7e8) | [0xEe44...d7e8](https://goerli-optimism.etherscan.io/address/0xEe44c1e83A768E80A3588B409f1A010f9D1dd7e8) | [0xEe44...d7e8](https://goerli.arbiscan.io/address/0xEe44c1e83A768E80A3588B409f1A010f9D1dd7e8) | [0xE3a4...A74C](https://arbiscan.io/address/0xE3a4C2FE9f025405cA6F60f6E960B4558604A74C) | | IncrementalBinaryTree.sol | [0x4621...7F49](https://goerli.etherscan.io/address/0x4621EE309EAc747425F0FEd51931dDC241A27F49) | [0x4621...7F49](https://sepolia.etherscan.io/address/0x4621EE309EAc747425F0FEd51931dDC241A27F49) | [0x4621...7F49](https://mumbai.polygonscan.com/address/0x4621EE309EAc747425F0FEd51931dDC241A27F49) | [0x4621...7F49](https://goerli-optimism.etherscan.io/address/0x4621EE309EAc747425F0FEd51931dDC241A27F49) | [0x4621...7F49](https://goerli.arbiscan.io/address/0x4621EE309EAc747425F0FEd51931dDC241A27F49) | [0xcDF8...fFb0](https://arbiscan.io/address/0xcDF8efE6334c68aF283C83f2F14648da51fcfFb0) | | PoseidonT3.sol | [0xe136...2595](https://goerli.etherscan.io/address/0xe136aBACf78E05988154ed85F4Ea911105302595) | [0xe136...2595](https://sepolia.etherscan.io/address/0xe136aBACf78E05988154ed85F4Ea911105302595) | [0xe136...2595](https://mumbai.polygonscan.com/address/0xe136aBACf78E05988154ed85F4Ea911105302595) | [0xe136...2595](https://goerli-optimism.etherscan.io/address/0xe136aBACf78E05988154ed85F4Ea911105302595) | [0xe136...2595](https://goerli.arbiscan.io/address/0xe136aBACf78E05988154ed85F4Ea911105302595) | [0xe0c8...61d0](https://arbiscan.io/address/0xe0c8d1e53D9Bfc9071F6564755FCFf6cC0dB61d0) | caution The Goerli testnet is planned to be deprecated in Q4 2023. Please, check the following links for more information. * Goerli: [https://ethereum.org/en/developers/docs/networks/#goerli](https://ethereum.org/en/developers/docs/networks/#goerli) * Optimism Goerli: [https://community.optimism.io/docs/useful-tools/networks/#op-goerli](https://community.optimism.io/docs/useful-tools/networks/#op-goerli) * Arbitrum Goerli: [https://docs.arbitrum.io/for-devs/concepts/public-chains#arbitrum-goerli](https://docs.arbitrum.io/for-devs/concepts/public-chains#arbitrum-goerli) ::: --- # Credits | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/credits#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 Semaphore is the work of several people, for a complete list of contributors you can visit the Semaphore [Github insights](https://github.com/semaphore-protocol/semaphore/graphs/contributors) . * [Barry WhiteHat](https://github.com/barryWhiteHat) * [Kobi Gurkan](https://github.com/kobigurk) * [Koh Wei Jie](https://github.com/weijiekoh) * [Andrija Novakovic](https://github.com/akinovak) * [Cedoor](https://github.com/cedoor) * [Rachel Aux](https://github.com/rachelaux) * [Andy Guzman](https://github.com/aguzmant103) * [Vivian Plasencia](https://github.com/vplasencia) * [LauNaMu](https://github.com/0xyNaMu) * [0xjei](https://github.com/0xjei) * [Mari Poveda](https://github.com/maripoveda) * [Gauthier](https://github.com/sripwoud) --- # Subgraph | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/subgraph#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/subgraph) ** (V4). Version: V3 On this page [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. Semaphore's subgraph allows you to retrieve data from the [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/contracts/Semaphore.sol) smart contract. tip The Graph protocol uses the [GraphQL](https://graphql.org/) query language. For examples, see the [GraphQL API documentation](https://thegraph.com/docs/developer/graphql-api) . Visit the [subgraph repository](https://github.com/semaphore-protocol/subgraph) to see the list of Semaphore subgraphs. Schema[​](https://docs.semaphore.pse.dev/V3/subgraph#schema "Direct link to heading") -------------------------------------------------------------------------------------- ### MerkleTree[​](https://docs.semaphore.pse.dev/V3/subgraph#merkletree "Direct link to heading") * `id`: unique identifier among all MerkleTree entities, * `depth`: Merkle tree depth, * `root`: Merkle tree root, * `zeroValue`: Merkle tree zero value, * `numberOfLeaves`: total number of tree leaves, * `group`: link to the Group entity. ### Group[​](https://docs.semaphore.pse.dev/V3/subgraph#group "Direct link to heading") * `id`: unique identifier among all Group entities, * `merkleTree`: link to the MerkleTree entity, * `timestamp`: block timestamp, * `admin`: admin of the group, * `members`: list of group members. * `verifiedProofs`: list of group proofs. ### Member[​](https://docs.semaphore.pse.dev/V3/subgraph#member "Direct link to heading") * `id`: unique identifier among all Member entities, * `identityCommitment`: Semaphore identity commitment, * `timestamp`: block timestamp, * `index`: index of the tree leaf, * `group`: link to the Group entity. ### VerifiedProof[​](https://docs.semaphore.pse.dev/V3/subgraph#verifiedproof "Direct link to heading") * `id`: unique identifier among all VerifiedProof entities, * `signal`: user's signal, * `merkleTreeRoot`: Merkle tree root, * `nullifierHash`: nullifier hash, * `externalNullifier`: external nullifier, * `timestamp`: block timestamp, * `group`: link to the Group entity. * [Schema](https://docs.semaphore.pse.dev/V3/subgraph#schema) * [MerkleTree](https://docs.semaphore.pse.dev/V3/subgraph#merkletree) * [Group](https://docs.semaphore.pse.dev/V3/subgraph#group) * [Member](https://docs.semaphore.pse.dev/V3/subgraph#member) * [VerifiedProof](https://docs.semaphore.pse.dev/V3/subgraph#verifiedproof) --- # Fetching data | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/guides/fetching-data#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/) ** (V4). Version: V3 On this page To fetch on-chain data from the [Semaphore.sol](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/contracts/contracts/Semaphore.sol) contract, you can use the [@semaphore-protocol/data](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/data) library. There are two ways to do this, using [`SemaphoreSubgraph`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/data/src/subgraph.ts) or [`SemaphoreEthers`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/data/src/ethers.ts) . The `SemaphoreSubgraph` class uses the [Semaphore subgraph](https://github.com/semaphore-protocol/subgraph) , which uses [The Graph Protocol](https://thegraph.com/) under the hood, and the `SemaphoreEthers` class uses [Ethers](https://github.com/ethers-io/ethers.js/) . * [**Fetch data using SemaphoreSubgraph**](https://docs.semaphore.pse.dev/V3/guides/fetching-data#fetch-data-using-semaphoresubgraph) * [**Fetch data using SemaphoreEthers**](https://docs.semaphore.pse.dev/V3/guides/fetching-data#fetch-data-using-semaphoreethers) Install library[​](https://docs.semaphore.pse.dev/V3/guides/fetching-data#install-library "Direct link to heading") -------------------------------------------------------------------------------------------------------------------- * npm * Yarn * pnpm npm install @semaphore-protocol/data@^3 yarn add @semaphore-protocol/data@^3 pnpm add @semaphore-protocol/data@^3 Fetch data using SemaphoreSubgraph[​](https://docs.semaphore.pse.dev/V3/guides/fetching-data#fetch-data-using-semaphoresubgraph "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------- To fetch data using the Semaphore subgraph you can use the [`SemaphoreSubgraph`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/data/src/subgraph.ts) class from the [@semaphore-protocol/data](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/data) package. import { SemaphoreSubgraph } from "@semaphore-protocol/data"const semaphoreSubgraph = new SemaphoreSubgraph()// or:const semaphoreSubgraph = new SemaphoreSubgraph("arbitrum")// or:const semaphoreSubgraph = new SemaphoreSubgraph( "https://api.studio.thegraph.com/query/14377//") ### Get group Ids[​](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group-ids "Direct link to heading") const groupIds = await semaphoreSubgraph.getGroupIds() ### Get groups[​](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-groups "Direct link to heading") const groups = await semaphoreSubgraph.getGroups()// orconst groups = await semaphoreSubgraph.getGroups({ members: true, verifiedProofs: true }) ### Get group[​](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group "Direct link to heading") const group = await semaphoreSubgraph.getGroup("42")// orconst { members, verifiedProofs } = semaphoreSubgraph.getGroup("42", { members: true, verifiedProofs: true }) ### Check if an identity commitment is a member of a group[​](https://docs.semaphore.pse.dev/V3/guides/fetching-data#check-if-an-identity-commitment-is-a-member-of-a-group "Direct link to heading") await semaphoreSubgraph.isGroupMember( "42", "16948514235341957898454876473214737047419402240398321289450170535251226167324") info You can create an off-chain group using the SemaphoreSubgraph class to fetch members like so: import { Group } from "@semaphore-protocol/group"import { SemaphoreSubgraph } from "@semaphore-protocol/data"const groupId = "3"const semaphoreSubgraph = new SemaphoreSubgraph("sepolia")const { members } = await semaphoreSubgraph.getGroup(groupId, { members: true })const group = new Group(groupId, 20, members) Fetch data using SemaphoreEthers[​](https://docs.semaphore.pse.dev/V3/guides/fetching-data#fetch-data-using-semaphoreethers "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------------------------ To fetch data using Ethers you can use the [`SemaphoreEthers`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/data/src/ethers.ts) class from the [@semaphore-protocol/data](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/data) package. import { SemaphoreEthers } from "@semaphore-protocol/data"const semaphoreEthers = new SemaphoreEthers()// or:const semaphoreEthers = new SemaphoreEthers("homestead", { address: "semaphore-address", startBlock: 0})// or:const semaphoreEthers = new SemaphoreEthers("http://127.0.0.1:8545", { address: "semaphore-address"}) ### Get group Ids[​](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group-ids-1 "Direct link to heading") const groupIds = await semaphoreEthers.getGroupIds() ### Get group[​](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group-1 "Direct link to heading") const group = await semaphoreEthers.getGroup("42") ### Get group admin[​](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group-admin "Direct link to heading") const admin = await semaphoreEthers.getGroupAdmin("42") ### Get group members[​](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group-members "Direct link to heading") const members = await semaphoreEthers.getGroupMembers("42") ### Get group verified proofs[​](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group-verified-proofs "Direct link to heading") const verifiedProofs = await semaphoreEthers.getGroupVerifiedProofs("42") info You can create an off-chain group using the SemaphoreEthers class to fetch members like so: import { Group } from "@semaphore-protocol/group"import { SemaphoreEthers } from "@semaphore-protocol/data"const groupId = "3"const semaphoreEthers = new SemaphoreEthers("sepolia")const members = await semaphoreEthers.getGroupMembers(groupId)const group = new Group(groupId, 20, members) * [Install library](https://docs.semaphore.pse.dev/V3/guides/fetching-data#install-library) * [Fetch data using SemaphoreSubgraph](https://docs.semaphore.pse.dev/V3/guides/fetching-data#fetch-data-using-semaphoresubgraph) * [Get group Ids](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group-ids) * [Get groups](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-groups) * [Get group](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group) * [Check if an identity commitment is a member of a group](https://docs.semaphore.pse.dev/V3/guides/fetching-data#check-if-an-identity-commitment-is-a-member-of-a-group) * [Fetch data using SemaphoreEthers](https://docs.semaphore.pse.dev/V3/guides/fetching-data#fetch-data-using-semaphoreethers) * [Get group Ids](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group-ids-1) * [Get group](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group-1) * [Get group admin](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group-admin) * [Get group members](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group-members) * [Get group verified proofs](https://docs.semaphore.pse.dev/V3/guides/fetching-data#get-group-verified-proofs) --- # Benchmarks | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/benchmarks#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page Semaphore v4 introduces new features and performance improvements. Detailed changes are available in the [release changelog](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) . The primary changes in benchmark values are driven by the two major protocol updates: * New [Identity schema](https://github.com/semaphore-protocol/semaphore/tree/main/packages/identity) . * [LeanIMT](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/lean-imt) : New optimized IMT. New Identity schema[​](https://docs.semaphore.pse.dev/benchmarks#new-identity-schema "Direct link to heading") --------------------------------------------------------------------------------------------------------------- Semaphore v4 includes a new schema for the identities allowing the creation and verification of signatures. Although the new Identity package is slightly slower than the one in Semaphore v3 (by just a few milliseconds), the trade-off is minimal considering the included functionality. The new identity schema adds additional constraints to the Semaphore v4 circuit; however, this does not negatively impact overall performance of the protocol. LeanIMT[​](https://docs.semaphore.pse.dev/benchmarks#leanimt "Direct link to heading") --------------------------------------------------------------------------------------- Semaphore v4 uses the LeanIMT data structure for group operations, an improvement over the IMT used in v3. For further details, see the [LeanIMT paper](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/papers/leanimt) . The LeanIMT offers dynamic depth, resulting in faster and more cost-effective group operations, across Node.js, browser and smart contracts. Semaphore v4 support tree depths from 1 to 32, while v3 supports depths from 16 to 32, both for proof generation and verification. System Specifications and Software environment[​](https://docs.semaphore.pse.dev/benchmarks#system-specifications-and-software-environment "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------------------------------------------------- All the benchmarks were run in an environment with these properties: **System Specifications** Computer: MacBook Pro Chip: Apple M2 Pro Memory (RAM): 16 GB Operating System: macOS Sequoia version 15.6.1 **Software environment** Node.js version: 23.10.0 Browser: Google Chrome Version 139.0.7258.156 (Official Build) (arm64) Running the benchmarks[​](https://docs.semaphore.pse.dev/benchmarks#running-the-benchmarks "Direct link to heading") --------------------------------------------------------------------------------------------------------------------- ### Javascript and Circom[​](https://docs.semaphore.pse.dev/benchmarks#javascript-and-circom "Direct link to heading") GitHub repository to the run Node.js, browser and Circom benchmarks: [https://github.com/vplasencia/semaphore-benchmarks](https://github.com/vplasencia/semaphore-benchmarks) ### Solidity[​](https://docs.semaphore.pse.dev/benchmarks#solidity "Direct link to heading") GitHub repository to run the Solidity benchmarks: [https://github.com/semaphore-protocol/semaphore](https://github.com/semaphore-protocol/semaphore) Semaphore V3 benchmarks were obtained using the code from the latest v3 Git tag (`v3.15.2`), with the Solidity optimizer enabled. Node.js benchmarks[​](https://docs.semaphore.pse.dev/benchmarks#nodejs-benchmarks "Direct link to heading") ------------------------------------------------------------------------------------------------------------ ### Identities[​](https://docs.semaphore.pse.dev/benchmarks#identities "Direct link to heading") ![Identities](https://docs.semaphore.pse.dev/assets/images/identity-node-benchmarks-73a0da49aea3d81c4a70a1c75af393b1.png) ### Create Group[​](https://docs.semaphore.pse.dev/benchmarks#create-group "Direct link to heading") Create group, either empty or with initial members. ![Create Group](https://docs.semaphore.pse.dev/assets/images/create-group-node-benchmarks-d36698d62e7cd6fa2f59cd219f74fc96.png) ### Add Member[​](https://docs.semaphore.pse.dev/benchmarks#add-member "Direct link to heading") Add a member to groups with different sizes. ![Add Member](https://docs.semaphore.pse.dev/assets/images/add-member-node-benchmarks-434e75a259cca8039ab7acf30007a575.png) ### Generate Proof[​](https://docs.semaphore.pse.dev/benchmarks#generate-proof "Direct link to heading") Generate a proof using groups with different numbers of members. ![Generate Proof](https://docs.semaphore.pse.dev/assets/images/generate-proof-node-benchmarks-df8b967ee3ac32e73b57cb2723ea7def.png) ### Verify Proof[​](https://docs.semaphore.pse.dev/benchmarks#verify-proof "Direct link to heading") Verify a proof using groups with different numbers of members. ![Verify Proof](https://docs.semaphore.pse.dev/assets/images/verify-proof-node-benchmarks-116947cf0638739cd268155181fd704c.png) Browser benchmarks[​](https://docs.semaphore.pse.dev/benchmarks#browser-benchmarks "Direct link to heading") ------------------------------------------------------------------------------------------------------------- Main functions used in the browser. ![Browser benchmarks](https://docs.semaphore.pse.dev/assets/images/browser-benchmarks-0945d64a0e6fdba3be13253bd7886b34.png) Circuit benchmarks[​](https://docs.semaphore.pse.dev/benchmarks#circuit-benchmarks "Direct link to heading") ------------------------------------------------------------------------------------------------------------- Tree depth = 20 ### Semaphore V3[​](https://docs.semaphore.pse.dev/benchmarks#semaphore-v3 "Direct link to heading") ![Circuit benchmarks Semaphore v3](https://docs.semaphore.pse.dev/assets/images/semaphore-v3-circuits-benchmarks-81bc99a2f1cb3d8cfc337f0e8ed52921.png) ### Semaphore V4[​](https://docs.semaphore.pse.dev/benchmarks#semaphore-v4 "Direct link to heading") ![Circuit benchmarks Semaphore v4](https://docs.semaphore.pse.dev/assets/images/semaphore-v4-circuits-benchmarks-0d13501bebb6af5cdccbfc0ec7ab109e.png) Contracts[​](https://docs.semaphore.pse.dev/benchmarks#contracts "Direct link to heading") ------------------------------------------------------------------------------------------- ![Contract Benchmarks](https://docs.semaphore.pse.dev/assets/images/contract-benchmarks-149ef9bc7091c6f660ea60e792cfccbc.png) ### Semaphore V3 gas report[​](https://docs.semaphore.pse.dev/benchmarks#semaphore-v3-gas-report "Direct link to heading") ![Contracts benchmarks Semaphore v3](https://docs.semaphore.pse.dev/assets/images/semaphore-v3-contracts-benchmarks-eec7051de6fa442b4f6b9bb9e285dc50.png) ### Semaphore V4 gas report[​](https://docs.semaphore.pse.dev/benchmarks#semaphore-v4-gas-report "Direct link to heading") ![Contracts benchmarks Semaphore v4](https://docs.semaphore.pse.dev/assets/images/semaphore-v4-contracts-benchmarks-6cdd95e0eff3900dbf026165b28d50cb.png) * [New Identity schema](https://docs.semaphore.pse.dev/benchmarks#new-identity-schema) * [LeanIMT](https://docs.semaphore.pse.dev/benchmarks#leanimt) * [System Specifications and Software environment](https://docs.semaphore.pse.dev/benchmarks#system-specifications-and-software-environment) * [Running the benchmarks](https://docs.semaphore.pse.dev/benchmarks#running-the-benchmarks) * [Javascript and Circom](https://docs.semaphore.pse.dev/benchmarks#javascript-and-circom) * [Solidity](https://docs.semaphore.pse.dev/benchmarks#solidity) * [Node.js benchmarks](https://docs.semaphore.pse.dev/benchmarks#nodejs-benchmarks) * [Identities](https://docs.semaphore.pse.dev/benchmarks#identities) * [Create Group](https://docs.semaphore.pse.dev/benchmarks#create-group) * [Add Member](https://docs.semaphore.pse.dev/benchmarks#add-member) * [Generate Proof](https://docs.semaphore.pse.dev/benchmarks#generate-proof) * [Verify Proof](https://docs.semaphore.pse.dev/benchmarks#verify-proof) * [Browser benchmarks](https://docs.semaphore.pse.dev/benchmarks#browser-benchmarks) * [Circuit benchmarks](https://docs.semaphore.pse.dev/benchmarks#circuit-benchmarks) * [Semaphore V3](https://docs.semaphore.pse.dev/benchmarks#semaphore-v3) * [Semaphore V4](https://docs.semaphore.pse.dev/benchmarks#semaphore-v4) * [Contracts](https://docs.semaphore.pse.dev/benchmarks#contracts) * [Semaphore V3 gas report](https://docs.semaphore.pse.dev/benchmarks#semaphore-v3-gas-report) * [Semaphore V4 gas report](https://docs.semaphore.pse.dev/benchmarks#semaphore-v4-gas-report) --- # Resources | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/resources#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/resources) ** (V4). Version: V3 On this page Articles[​](https://docs.semaphore.pse.dev/V3/resources#articles "Direct link to heading") ------------------------------------------------------------------------------------------- [Community Proposal: Semaphore: Zero-Knowledge Signaling on Ethereum (Whitepaper v1)](https://semaphore.pse.dev/whitepaper-v1.pdf) - Kobi Gurkan, Koh Wei Jie and Barry WhiteHat [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 [Semaphore V2 is Live!](https://medium.com/privacy-scaling-explorations/semaphore-v2-is-live-f263e9372579) - Privacy and Scaling Explorations [Zero-Knowledge Group Membership Management With Semaphore](https://medium.com/javascript-in-plain-english/zero-knowledge-group-membership-management-with-the-semaphore-protocol-1a63126de81c) - Laszlo Fazekas Videos[​](https://docs.semaphore.pse.dev/V3/resources#videos "Direct link to heading") --------------------------------------------------------------------------------------- [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 [Succinct Proofs in Ethereum](https://www.youtube.com/watch?v=TtsDNneTDDY) - Barry WhiteHat during the 2nd ZKProof Workshop [Semaphore Roadmap for Ethereum](https://www.youtube.com/watch?v=gOub903iWFs) - Barry WhiteHat at Zcon1 [Proposal: Semaphore - Zero-Knowledge Signaling on Ethereum](https://www.youtube.com/watch?v=y5uV9eRb3-w) - Kobi Gurkan and Koh Wei Jie at ZKProof Home Edition [Anonymous Signalling on Ethereum](https://www.youtube.com/watch?v=dxAfL91Sbw4) - Cedoor at Devcon 6 Bogotá * [Articles](https://docs.semaphore.pse.dev/V3/resources#articles) * [Videos](https://docs.semaphore.pse.dev/V3/resources#videos) --- # Glossary | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/glossary#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page Identity[​](https://docs.semaphore.pse.dev/glossary#identity "Direct link to heading") --------------------------------------------------------------------------------------- The identity of a user in the Semaphore protocol. A Semaphore identity consists of an [EdDSA](https://en.wikipedia.org/wiki/EdDSA) public/private key pair and a [commitment](https://docs.semaphore.pse.dev/glossary#identity-commitment) . Semaphore uses an [EdDSA](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/eddsa-poseidon) implementation based on [Baby Jubjub](https://eips.ethereum.org/EIPS/eip-2494) and [Poseidon](https://www.poseidon-hash.info/) . Identity commitment[​](https://docs.semaphore.pse.dev/glossary#identity-commitment "Direct link to heading") ------------------------------------------------------------------------------------------------------------- The public [Semaphore identity](https://docs.semaphore.pse.dev/glossary#identity) value used in [Semaphore groups](https://docs.semaphore.pse.dev/glossary#group) . Semaphore uses the [Poseidon](https://www.poseidon-hash.info/) hash function to create the identity commitment from the Semaphore identity public key. Group[​](https://docs.semaphore.pse.dev/glossary#group "Direct link to heading") --------------------------------------------------------------------------------- A group is a [Merkle tree](https://docs.semaphore.pse.dev/glossary#merkle-tree) in which each leaf is an [identity commitment](https://docs.semaphore.pse.dev/glossary#identity-commitment) for a user. Semaphore uses the [LeanIMT](https://zkkit.pse.dev/classes/_zk_kit_lean_imt.LeanIMT.html) implementation, which is an optimized binary incremental Merkle tree. The tree nodes are calculated using [Poseidon](https://www.poseidon-hash.info/) . Merkle tree[​](https://docs.semaphore.pse.dev/glossary#merkle-tree "Direct link to heading") --------------------------------------------------------------------------------------------- A [tree](https://en.wikipedia.org/wiki/Merkle_tree) in which every leaf (i.e., a node that doesn't have children) is labelled with the cryptographic hash of a data block, and every node that isn't a leaf is labelled with the cryptographic hash of its child node labels. In zero-knowledge protocols, Merkle trees can be used to efficiently summarize and validate large data sets. To validate that a tree contains a specific leaf, a verifier only needs a portion of the complete data structure. Scope[​](https://docs.semaphore.pse.dev/glossary#scope "Direct link to heading") --------------------------------------------------------------------------------- A value used like a topic on which users can generate a valid proof only once. The scope is supposed to be used to generate the [nullifier](https://docs.semaphore.pse.dev/glossary#nullifier) . Nullifier[​](https://docs.semaphore.pse.dev/glossary#nullifier "Direct link to heading") ----------------------------------------------------------------------------------------- A value designed to be a unique identifier and used to prevent the same zero-knowledge proof from being used twice. In Semaphore, the nullifier is the hash of the scope and private key of the user's Semaphore identity. Message[​](https://docs.semaphore.pse.dev/glossary#message "Direct link to heading") ------------------------------------------------------------------------------------- The term "message" in Semaphore refers to the value the user broadcasts when voting, confirming, sending a text message and so on. Relay[​](https://docs.semaphore.pse.dev/glossary#relay "Direct link to heading") --------------------------------------------------------------------------------- A third-party who could receive a fee for including relayed transactions in the blockchain (McMenamin, Daza, and Fitz. [https://eprint.iacr.org/2022/155.pdf](https://eprint.iacr.org/2022/155.pdf) , p.3). To preserve the anonymity of the user broadcasting a message with Semaphore, an application may use a relayer to send the transaction to Ethereum on behalf of the user. Trusted setup[​](https://docs.semaphore.pse.dev/glossary#trusted-setup "Direct link to heading") ------------------------------------------------------------------------------------------------- A trusted setup in the context of zero-knowledge proofs, particularly zk-SNARKs, is a preparatory phase where [certain parameters](https://docs.semaphore.pse.dev/glossary#trusted-setup-files) are generated for later use in creating and verifying proofs. This process must be conducted by trusted parties, as any retained secret information (toxic waste) could compromise the system's integrity by enabling the creation of false proofs. Trusted setup files[​](https://docs.semaphore.pse.dev/glossary#trusted-setup-files "Direct link to heading") ------------------------------------------------------------------------------------------------------------- The secure, verifiable parameters generated by Semaphore's trusted setup ceremony. Semaphore uses the trusted setup files to generate and verify valid zero-knowledge proofs. The [Semaphore circuit](https://docs.semaphore.pse.dev/technical-reference/circuits) includes a parameter to set the tree's maximum depth (MAX\_DEPTH). During the trusted setup, parameters are specifically generated for each circuit instance, aligning with their designated MAX\_DEPTH (from 1 to 32). * [Identity](https://docs.semaphore.pse.dev/glossary#identity) * [Identity commitment](https://docs.semaphore.pse.dev/glossary#identity-commitment) * [Group](https://docs.semaphore.pse.dev/glossary#group) * [Merkle tree](https://docs.semaphore.pse.dev/glossary#merkle-tree) * [Scope](https://docs.semaphore.pse.dev/glossary#scope) * [Nullifier](https://docs.semaphore.pse.dev/glossary#nullifier) * [Message](https://docs.semaphore.pse.dev/glossary#message) * [Relay](https://docs.semaphore.pse.dev/glossary#relay) * [Trusted setup](https://docs.semaphore.pse.dev/glossary#trusted-setup) * [Trusted setup files](https://docs.semaphore.pse.dev/glossary#trusted-setup-files) --- # Troubleshooting | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/troubleshooting#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/troubleshooting) ** (V4). Version: V3 On this page If these suggestions do not work, feel free to ask in the [Semaphore Discussions](https://github.com/semaphore-protocol/semaphore/discussions) or in the [Semaphore Telegram](https://semaphore.pse.dev/telegram) . Using Semaphore in the frontend[​](https://docs.semaphore.pse.dev/V3/troubleshooting#using-semaphore-in-the-frontend "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------------------- Semaphore works with any JavaScript frontend framework, but the [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/proof) package is using [snarkjs](https://github.com/iden3/snarkjs) , which uses Node.js modules which are not compatible with frontend frameworks and there are some changes that we need to do to make it work on the client side. ### Semaphore with Nextjs[​](https://docs.semaphore.pse.dev/V3/troubleshooting#semaphore-with-nextjs "Direct link to heading") You will see an error like this: Module not found: Can't resolve 'fs' To solve this, in your `next.config.js` file, inside the `nextConfig` object, add: webpack: (config, { isServer }) => { if (!isServer) { config.resolve.fallback = { fs: false } } return config } Your `next.config.js` file would be something like this: /** @type {import('next').NextConfig} */const nextConfig = { reactStrictMode: true, webpack: (config, { isServer }) => { if (!isServer) { config.resolve.fallback = { fs: false } } return config }}module.exports = nextConfig ### Semaphore with React + Vite or Vuejs + Vite[​](https://docs.semaphore.pse.dev/V3/troubleshooting#semaphore-with-react--vite-or-vuejs--vite "Direct link to heading") You will see an error like this: readman.js:43 Uncaught ReferenceError: process is not defined at stringToBase64 (threadman.js:43:5) at threadman.js:50:22 To solve that: 1- Install `@esbuild-plugins/node-globals-polyfill` and `@esbuild-plugins/node-modules-polyfill` * npm * Yarn * pnpm npm install @esbuild-plugins/node-globals-polyfill yarn add @esbuild-plugins/node-globals-polyfill pnpm add @esbuild-plugins/node-globals-polyfill * npm * Yarn * pnpm npm install @esbuild-plugins/node-modules-polyfill yarn add @esbuild-plugins/node-modules-polyfill pnpm add @esbuild-plugins/node-modules-polyfill 2- Modify the `vite.config.ts` to add them: import { NodeGlobalsPolyfillPlugin } from "@esbuild-plugins/node-globals-polyfill"import { NodeModulesPolyfillPlugin } from "@esbuild-plugins/node-modules-polyfill" and in `defineConfig` add: optimizeDeps: { esbuildOptions: { // Enable esbuild polyfill plugins plugins: [ NodeGlobalsPolyfillPlugin({ process: true, buffer: true }), NodeModulesPolyfillPlugin() ] }} Your `vite.config.ts` should be something like: import { fileURLToPath, URL } from "node:url"import { defineConfig } from "vite"import vue from "@vitejs/plugin-vue"import { NodeGlobalsPolyfillPlugin } from "@esbuild-plugins/node-globals-polyfill"import { NodeModulesPolyfillPlugin } from "@esbuild-plugins/node-modules-polyfill"// https://vitejs.dev/config/export default defineConfig({ plugins: [vue()], resolve: { alias: { "@": fileURLToPath(new URL("./src", import.meta.url)) } }, optimizeDeps: { esbuildOptions: { // Enable esbuild polyfill plugins plugins: [ NodeGlobalsPolyfillPlugin({ process: true, buffer: true }), NodeModulesPolyfillPlugin() ] } }}) info In case of React with Vite, if you see a red wavy underline on every Semaphore module which says `Could not find a declaration file for module ...`, change the `moduleResolution` from `bundler` to `Node` in the `tsconfig.json` file inside `compilerOptions`. Your `tsconfig.json` file would be something like this: { "compilerOptions": { "target": "ESNext", "lib": ["DOM", "DOM.Iterable", "ESNext"], "module": "ESNext", "skipLibCheck": true, /* Bundler mode */ "moduleResolution": "Node", "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", /* Linting */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }]} Semaphore Groups[​](https://docs.semaphore.pse.dev/V3/troubleshooting#semaphore-groups "Direct link to heading") ----------------------------------------------------------------------------------------------------------------- ### Creating a Group[​](https://docs.semaphore.pse.dev/V3/troubleshooting#creating-a-group "Direct link to heading") When you create a group and the transaction is reverted, make sure that the group id you are using does not exist on the network you are using. To check that, you can use the [Semaphore CLI](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/cli) with the command `get-groups` and the network you are using and then, make sure that your group id is not part of that list. You can also use the [Semaphore explorer](https://explorer.semaphore.pse.dev/) . Semaphore Proofs[​](https://docs.semaphore.pse.dev/V3/troubleshooting#semaphore-proofs "Direct link to heading") ----------------------------------------------------------------------------------------------------------------- ### Transaction reverted when using the same external nullifier[​](https://docs.semaphore.pse.dev/V3/troubleshooting#transaction-reverted-when-using-the-same-external-nullifier "Direct link to heading") When you generate a proof using the same external nullifier you used to verify a proof before, the transaction will be reverted because that external nullifier was already used. If you want to send and verify several proofs from the same identity, you should use a different external nullifier each time you generate a proof. * [Using Semaphore in the frontend](https://docs.semaphore.pse.dev/V3/troubleshooting#using-semaphore-in-the-frontend) * [Semaphore with Nextjs](https://docs.semaphore.pse.dev/V3/troubleshooting#semaphore-with-nextjs) * [Semaphore with React + Vite or Vuejs + Vite](https://docs.semaphore.pse.dev/V3/troubleshooting#semaphore-with-react--vite-or-vuejs--vite) * [Semaphore Groups](https://docs.semaphore.pse.dev/V3/troubleshooting#semaphore-groups) * [Creating a Group](https://docs.semaphore.pse.dev/V3/troubleshooting#creating-a-group) * [Semaphore Proofs](https://docs.semaphore.pse.dev/V3/troubleshooting#semaphore-proofs) * [Transaction reverted when using the same external nullifier](https://docs.semaphore.pse.dev/V3/troubleshooting#transaction-reverted-when-using-the-same-external-nullifier) --- # Circuits | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/technical-reference/circuits#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/technical-reference/circuits) ** (V4). Version: V3 On this page The [Semaphore circuit](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/circuits) is the heart of the protocol and consists of three parts: * [**Proof of membership**](https://docs.semaphore.pse.dev/V3/technical-reference/circuits#proof-of-membership) * [**Nullifier hash**](https://docs.semaphore.pse.dev/V3/technical-reference/circuits#nullifier-hash) * [**Signal**](https://docs.semaphore.pse.dev/V3/technical-reference/circuits#signal) ![Semaphore circuit](https://github.com/semaphore-protocol/semaphore/raw/v3.15.2/packages/circuits/scheme.png) The diagram above shows how the input signals are used in the Semaphore circuit and how the outputs are calculated. Proof of membership[​](https://docs.semaphore.pse.dev/V3/technical-reference/circuits#proof-of-membership "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------ The circuit hashes the hash of the identity nullifier with the identity trapdoor to generate an identity commitment. Then, it verifies the proof of membership against the Merkle root and the identity commitment. **Private inputs:** * `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, * `identityNullifier`: the 32-byte identity secret used as nullifier, * `identityTrapdoor`: the 32-byte identity secret used as trapdoor. **Public outputs:** * `root`: The Merkle root of the tree. Nullifier hash[​](https://docs.semaphore.pse.dev/V3/technical-reference/circuits#nullifier-hash "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------- The circuit hashes the identity nullifier with the external nullifier and then checks that the result matches the provided nullifier hash. Nullifier hashes saved in a Semaphore smart contract allow the contract to reject a proof that contains a used nullifier hash. **Private inputs:** * `identityNullifier`: the 32-byte identity secret used as a nullifier. **Public inputs:** * `externalNullifier`: the 32-byte external nullifier. **Public outputs:** * `nullifierHash`: the hash of the identity nullifier and the external nullifier; used to prevent double-signaling. Signal[​](https://docs.semaphore.pse.dev/V3/technical-reference/circuits#signal "Direct link to heading") ---------------------------------------------------------------------------------------------------------- The circuit calculates a dummy square of the signal hash to prevent any tampering with the proof. **Public inputs:** * `signalHash`: the hash of the user's signal. * [Proof of membership](https://docs.semaphore.pse.dev/V3/technical-reference/circuits#proof-of-membership) * [Nullifier hash](https://docs.semaphore.pse.dev/V3/technical-reference/circuits#nullifier-hash) * [Signal](https://docs.semaphore.pse.dev/V3/technical-reference/circuits#signal) --- # Contracts | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/technical-reference/contracts#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/technical-reference/contracts) ** (V4). Version: V3 On this page Semaphore includes two types of contracts: * [**Base contracts**](https://docs.semaphore.pse.dev/V3/technical-reference/contracts#base-contracts) * [**Extension contracts**](https://docs.semaphore.pse.dev/V3/technical-reference/contracts#extension-contracts) And [**Semaphore.sol**](https://docs.semaphore.pse.dev/V3/technical-reference/contracts#semaphoresol) , the main contract deployed on the networks supported by Semaphore. info To use Semaphore contracts and interfaces in your project, install the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/contracts) NPM package. Base contracts[​](https://docs.semaphore.pse.dev/V3/technical-reference/contracts#base-contracts "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------- Semaphore provides the following base contracts: * [`SemaphoreVerifier.sol`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/contracts/contracts/base/SemaphoreVerifier.sol) : contains a function to verify Semaphore proofs; * [`SemaphoreGroups.sol`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/contracts/contracts/base/SemaphoreGroups.sol) : contains the functions to create groups and add/remove/update members. These contracts are closely related to the protocol. You can use them in your contract or you can use [**Semaphore.sol**](https://docs.semaphore.pse.dev/V3/technical-reference/contracts#semaphoresol) , which integrates them for you. info While some DApps may use on-chain groups, others may prefer to use off-chain groups, saving only their tree roots in the contract. Extension contracts[​](https://docs.semaphore.pse.dev/V3/technical-reference/contracts#extension-contracts "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------- * [`SemaphoreVoting.sol`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/contracts/contracts/extensions/SemaphoreVoting.sol) : voting contract that contains the essential functions to create polls, add voters, and anonymously cast votes; * [`SemaphoreWhistleblowing.sol`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/contracts/contracts/extensions/SemaphoreWhistleblowing.sol) : whistleblowing contract that contains the essential functions to create entities (for example: non-profit organizations), add whistleblowers, and anonymously publish leaks. These contracts extend the protocol to provide application logic for specific use-cases. More extensions will be added in the future. Semaphore.sol[​](https://docs.semaphore.pse.dev/V3/technical-reference/contracts#semaphoresol "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------ [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/contracts/contracts/Semaphore.sol) is based on the base contracts. It integrates them and additionally provides: * a system to allow only admins (i.e. Ethereum accounts or smart contracts) to manage groups; * a mechanism to save the [nullifier hashes](https://docs.semaphore.pse.dev/V3/technical-reference/circuits#nullifier-hash) of each group and prevent double-signaling; * a mechanism to allow Semaphore proofs generated with old Merkle roots to be verified for a certain period of time defined by the group admin. info See our [deployed contracts](https://docs.semaphore.pse.dev/V3/deployed-contracts) to find the addresses for your network. * [Base contracts](https://docs.semaphore.pse.dev/V3/technical-reference/contracts#base-contracts) * [Extension contracts](https://docs.semaphore.pse.dev/V3/technical-reference/contracts#extension-contracts) * [Semaphore.sol](https://docs.semaphore.pse.dev/V3/technical-reference/contracts#semaphoresol) --- # Deployed contracts | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/deployed-contracts#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 Sepolia ------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://sepolia.etherscan.io/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://sepolia.etherscan.io/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://sepolia.etherscan.io/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Ethereum -------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://etherscan.io/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://etherscan.io/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://etherscan.io/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Arbitrum-sepolia ---------------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://sepolia.arbiscan.io/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://sepolia.arbiscan.io/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://sepolia.arbiscan.io/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Optimism-sepolia ---------------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://sepolia-optimism.etherscan.io/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://sepolia-optimism.etherscan.io/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://sepolia-optimism.etherscan.io/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Matic-amoy ---------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://amoy.polygonscan.com/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://amoy.polygonscan.com/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://amoy.polygonscan.com/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Arbitrum -------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://arbiscan.io/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://arbiscan.io/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://arbiscan.io/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Matic ----- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://polygonscan.com/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://polygonscan.com/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://polygonscan.com/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Optimism -------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://optimistic.etherscan.io/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://optimistic.etherscan.io/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://optimistic.etherscan.io/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Base-sepolia ------------ * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://sepolia.basescan.org/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://sepolia.basescan.org/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://sepolia.basescan.org/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Linea-sepolia ------------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://sepolia.lineascan.build/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://sepolia.lineascan.build/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://sepolia.lineascan.build/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Base ---- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://basescan.org/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://basescan.org/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://basescan.org/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Linea ----- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://lineascan.build/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://lineascan.build/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://lineascan.build/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Scroll-sepolia -------------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://sepolia.scrollscan.com/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://sepolia.scrollscan.com/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://sepolia.scrollscan.com/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) --- # Resources | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/resources#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page Articles[​](https://docs.semaphore.pse.dev/resources#articles "Direct link to heading") ---------------------------------------------------------------------------------------- Videos[​](https://docs.semaphore.pse.dev/resources#videos "Direct link to heading") ------------------------------------------------------------------------------------ * [Articles](https://docs.semaphore.pse.dev/resources#articles) * [Videos](https://docs.semaphore.pse.dev/resources#videos) --- # FAQ | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/faq#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page Where can I ask questions about Semaphore?[​](https://docs.semaphore.pse.dev/faq#where-can-i-ask-questions-about-semaphore "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- You can ask questions about Semaphore on [Telegram](https://semaphore.pse.dev/telegram) or by opening a [Semaphore Discussion](https://github.com/semaphore-protocol/semaphore/discussions) . The most frequent questions will be listed below. Why should I prevent proofs from being verified twice?[​](https://docs.semaphore.pse.dev/faq#why-should-i-prevent-proofs-from-being-verified-twice "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Since zero-knowledge proofs are completely anonymous, it is important to prevent those generated by eligible identities from being reused by a malicious party. For example, in an anonymous voting application a valid proof could be reused to vote again. What is the difference between the "nullifier" and "scope"?[​](https://docs.semaphore.pse.dev/faq#what-is-the-difference-between-the-nullifier-and-scope "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The [scope](https://docs.semaphore.pse.dev/glossary#scope) is used like a topic on which users can generate a valid proof only once. The scope is a public value and every one can see what the scope of a proof is. The [nullifier](https://docs.semaphore.pse.dev/glossary#nullifier) is the hash of the private key of the identity and the scope, and it is used to check if the same proof with that specific scope has already been generated by the same user. The nullifier is also a public value and it is what is actually stored to prevent, for example, double-voting. In the case of a voting application, if you have a group and you want all members of this group to vote only once, you can use the id of the group as the scope. When a user votes the first time, you can store the hash of voter's private key and the group id (i.e., the nullifier) and prevent double-voting by checking if that hash already exists. See the [Semaphore circuits](https://docs.semaphore.pse.dev/technical-reference/circuits) for more technical information, or the [Semaphore boilerplate](https://github.com/semaphore-protocol/boilerplate/tree/main) for a real use-case. Where can I find examples of applications using Semaphore?[​](https://docs.semaphore.pse.dev/faq#where-can-i-find-examples-of-applications-using-semaphore "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can find a complete list of applications that are using Semaphore on the [Semaphore website](https://semaphore.pse.dev/projects) . How can I start a project using Semaphore?[​](https://docs.semaphore.pse.dev/faq#how-can-i-start-a-project-using-semaphore "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------------------------- There are three ways you can start using Semaphore in your project: using the [CLI](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli) , using the [boilerplate](https://github.com/semaphore-protocol/boilerplate/tree/main) as a template or forking it, or installing the Semaphore [packages](https://docs.semaphore.pse.dev/guides/identities) manually. How can I contribute to the protocol?[​](https://docs.semaphore.pse.dev/faq#how-can-i-contribute-to-the-protocol "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------------- There are several ways you could contribute to the protocol, you can find more information about on [Github](https://github.com/semaphore-protocol#ways-to-contribute) . * [Where can I ask questions about Semaphore?](https://docs.semaphore.pse.dev/faq#where-can-i-ask-questions-about-semaphore) * [Why should I prevent proofs from being verified twice?](https://docs.semaphore.pse.dev/faq#why-should-i-prevent-proofs-from-being-verified-twice) * [What is the difference between the "nullifier" and "scope"?](https://docs.semaphore.pse.dev/faq#what-is-the-difference-between-the-nullifier-and-scope) * [Where can I find examples of applications using Semaphore?](https://docs.semaphore.pse.dev/faq#where-can-i-find-examples-of-applications-using-semaphore) * [How can I start a project using Semaphore?](https://docs.semaphore.pse.dev/faq#how-can-i-start-a-project-using-semaphore) * [How can I contribute to the protocol?](https://docs.semaphore.pse.dev/faq#how-can-i-contribute-to-the-protocol) --- # Groups | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/guides/groups#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/guides/groups) ** (V4). Version: V3 On this page A [Semaphore group](https://docs.semaphore.pse.dev/V3/glossary#semaphore-group) contains [identity commitments](https://docs.semaphore.pse.dev/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. A Semaphore group is an [incremental Merkle tree](https://docs.semaphore.pse.dev/V3/glossary#merkle-tree) , and group members (i.e., [identity commitments](https://docs.semaphore.pse.dev/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. Learn how to work with groups. * [**Off-chain groups**](https://docs.semaphore.pse.dev/V3/guides/groups#off-chain-groups) * [**On-chain groups**](https://docs.semaphore.pse.dev/V3/guides/groups#on-chain-groups) Off-chain groups[​](https://docs.semaphore.pse.dev/V3/guides/groups#off-chain-groups "Direct link to heading") --------------------------------------------------------------------------------------------------------------- * [Create a group](https://docs.semaphore.pse.dev/V3/guides/groups#create-a-group) * [Add members](https://docs.semaphore.pse.dev/V3/guides/groups#add-members) * [Remove or update members](https://docs.semaphore.pse.dev/V3/guides/groups#remove-or-update-members) ### Create a group[​](https://docs.semaphore.pse.dev/V3/guides/groups#create-a-group "Direct link to heading") 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. #### Install library:[​](https://docs.semaphore.pse.dev/V3/guides/groups#install-library "Direct link to heading") * npm * Yarn * pnpm npm install @semaphore-protocol/group@^3 yarn add @semaphore-protocol/group@^3 pnpm add @semaphore-protocol/group@^3 To create a group with default _`treeDepth`_, call the `Group` constructor without the second parameter. For example: 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: import { Group } from "@semaphore-protocol/group"const group = new Group(1, 30) You can also initialize a group with multiple members by passing the list of identity commitments (members) as the third parameter when creating the group: import { Group } from "@semaphore-protocol/group"const members = [ "11237622825477336339577122413451117718539783476837539122310492284566644730311", "9332663527862709610616009715800254142772436825222910251631161087138559093425", "13255821893820536903335282929376140649646180444238593676033702344407594536519"]const group = new Group(1, 20, members) ### Add members[​](https://docs.semaphore.pse.dev/V3/guides/groups#add-members "Direct link to heading") Use the `Group addMember` function to add a member (identity commitment) to a group. For example: group.addMember(identityCommitment) To add a batch of members to a group, pass an array to the `Group addMembers` function. For example: group.addMembers([identityCommitment1, identityCommitment2]) caution When you use the same Semaphore identity across multiple groups, if an attacker takes control of that identity all the groups it is part of will be compromised. Consider using different identities for each group. ### Remove or update members[​](https://docs.semaphore.pse.dev/V3/guides/groups#remove-or-update-members "Direct link to heading") To remove members from a group, pass the member index to the `Group removeMember` function. For example: group.removeMember(0) To update members in a group, pass the member index and the new value to the `Group updateMember` function. For example: group.updateMember(0, 2) caution Removing a member from a group sets the node value to a special value (i.e. `zeroValue`). Given that the node isn't removed, and the length of the `group.members` array doesn't change. On-chain groups[​](https://docs.semaphore.pse.dev/V3/guides/groups#on-chain-groups "Direct link to heading") ------------------------------------------------------------------------------------------------------------- The [`SemaphoreGroups`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/contracts/contracts/base/SemaphoreGroups.sol) contract uses the [`IncrementalBinaryTree`](https://github.com/privacy-scaling-explorations/zk-kit/blob/main/packages/incremental-merkle-tree.sol/contracts/IncrementalBinaryTree.sol) library and provides methods to create and manage groups. info You can import `SemaphoreGroups.sol` and other Semaphore contracts from the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/contracts) NPM module. Alternatively, you can use an already deployed [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/contracts/contracts/Semaphore.sol) contract and use its group external functions. caution `Semaphore.sol` does not check if a member with a specific identity commitment already exists in a group. This check must be done off-chain. caution `Semaphore.sol` includes a mechanism to verify Semaphore proofs created with old Merkle tree roots, the duration of which can be defined by the admin in the `createGroup` function. Members of a group could then continue to generate valid proofs even after being removed. For more info see the issue [#98](https://github.com/semaphore-protocol/semaphore/issues/98) . * [Off-chain groups](https://docs.semaphore.pse.dev/V3/guides/groups#off-chain-groups) * [Create a group](https://docs.semaphore.pse.dev/V3/guides/groups#create-a-group) * [Add members](https://docs.semaphore.pse.dev/V3/guides/groups#add-members) * [Remove or update members](https://docs.semaphore.pse.dev/V3/guides/groups#remove-or-update-members) * [On-chain groups](https://docs.semaphore.pse.dev/V3/guides/groups#on-chain-groups) --- # Subgraph | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/subgraph#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page [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. 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 The Graph protocol uses the [GraphQL](https://graphql.org/) query language. For examples, see the [GraphQL API documentation](https://thegraph.com/docs/developer/graphql-api) . Visit the [Semaphore subgraph](https://github.com/semaphore-protocol/semaphore/tree/main/apps/subgraph) to see the list of networks supported by Semaphore and its URLs. Schema[​](https://docs.semaphore.pse.dev/subgraph#schema "Direct link to heading") ----------------------------------------------------------------------------------- apps/subgraph/schema.graphql * [Schema](https://docs.semaphore.pse.dev/subgraph#schema) --- # Identities | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/guides/identities#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/guides/identities) ** (V4). Version: V3 On this page In order to join a [Semaphore group](https://docs.semaphore.pse.dev/V3/glossary#semaphore-group) , a user must first create a [Semaphore identity](https://docs.semaphore.pse.dev/V3/glossary#semaphore-identity) . A Semaphore identity contains two values generated with the identity: * 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[​](https://docs.semaphore.pse.dev/V3/guides/identities#create-identities "Direct link to heading") --------------------------------------------------------------------------------------------------------------------- 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**](https://docs.semaphore.pse.dev/V3/guides/identities#create-random-identities) * [**Create deterministic identities**](https://docs.semaphore.pse.dev/V3/guides/identities#create-deterministic-identities) ### Install library:[​](https://docs.semaphore.pse.dev/V3/guides/identities#install-library "Direct link to heading") * npm * Yarn * pnpm npm install @semaphore-protocol/identity@^3 yarn add @semaphore-protocol/identity@^3 pnpm add @semaphore-protocol/identity@^3 ### Create random identities[​](https://docs.semaphore.pse.dev/V3/guides/identities#create-random-identities "Direct link to heading") To create a random identity, instantiate `Identity` without any parameters. For example: import { Identity } from "@semaphore-protocol/identity"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_. 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 Ethereum private keys and are used to generate Semaphore zero-knowledge proofs and authenticate signals. ### Create deterministic identities[​](https://docs.semaphore.pse.dev/V3/guides/identities#create-deterministic-identities "Direct link to heading") If you pass a message as a parameter, Semaphore generates `trapdoor` and `nullifier` 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. Given that the hash is deterministic, anyone with the same message can recreate the same identity. const identity = new Identity("secret-message") tip Building a system to save or recover secret values of Semaphore identities is nontrivial. You may choose to delegate such functionality to existing wallets such as Metamask. For example: 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. 3. The user can now recreate their Semaphore identity whenever they want by signing the same message with their Ethereum account in Metamask. Save your identities[​](https://docs.semaphore.pse.dev/V3/guides/identities#save-your-identities "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------- You can output an identity as a JSON string that you can save and reuse later. The `Identity.toString()` method generates a JSON array from an identity. For example: console.log(identity.toString()) // View the identity trapdoor and nullifier.// '["8255d...", "62c41..."]' The array contains the trapdoor and nullifier. To reuse the saved identity, pass the JSON to the `Identity()` constructor. const identity2 = new Identity(identity.toString()) * [Create identities](https://docs.semaphore.pse.dev/V3/guides/identities#create-identities) * [Install library:](https://docs.semaphore.pse.dev/V3/guides/identities#install-library) * [Create random identities](https://docs.semaphore.pse.dev/V3/guides/identities#create-random-identities) * [Create deterministic identities](https://docs.semaphore.pse.dev/V3/guides/identities#create-deterministic-identities) * [Save your identities](https://docs.semaphore.pse.dev/V3/guides/identities#save-your-identities) --- # Getting started | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/getting-started#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page Semaphore provides an official CLI to set up your project with Hardhat. If your NPM version is 5.2 or higher you can use NPX: npx @semaphore-protocol/cli create my-app --template monorepo-ethers Otherwise, install `@semaphore-protocol/cli` globally and run the `create` command: npm i -g @semaphore-protocol/clisemaphore create my-app --template monorepo-ethers info The supported templates are: [`contracts-hardhat`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-contracts-hardhat) , [`monorepo-ethers`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-monorepo-ethers) , [`monorepo-subgraph`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-monorepo-subgraph) . info The [`semaphore CLI`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli) can also be used to get group data from a supported network (e.g. `semaphore get-groups --network sepolia`). To start working on your project, install the dependencies: cd my-appyarn Output[​](https://docs.semaphore.pse.dev/getting-started#output "Direct link to heading") ------------------------------------------------------------------------------------------ The `create` command will create a directory called my-app (or whatever name you choose) inside the current folder. That directory will contain the initial project structure, which includes a simple contract, a task to deploy it, some tests and a Next.js application (the web-app folder) to interact with that contract. my-app├── .yarn├── apps│ └── contracts│ │ └── contracts| │ │ └── Feedback.sol│ │ └── tasks| │ │ └── deploy.ts│ │ └── test| │ │ └── Feedback.ts│ │ └── hardhat.config.ts│ │ └── package.json│ │ └── tsconfig.json│ └── web-app├── .editorconfig├── .env├── .env.example├── .eslintignore├── .eslintrc.json├── .gitignore├── .prettierignore├── .prettierrc.json├── .yarnrc.yml├── package.json├── README.md└── tsconfig.json The `Feedback.sol` contract creates a Semaphore group, allows users to join that group with their Semaphore identity, and finally allows group members to send an anonymous feedback. Usage[​](https://docs.semaphore.pse.dev/getting-started#usage "Direct link to heading") ---------------------------------------------------------------------------------------- ### Compile contracts[​](https://docs.semaphore.pse.dev/getting-started#compile-contracts "Direct link to heading") Go to the `contracts` folder: cd apps/contracts And compile your contracts: yarn compile ### Test contracts[​](https://docs.semaphore.pse.dev/getting-started#test-contracts "Direct link to heading") Test your contracts: yarn test Generate a test coverage report: yarn test:coverage Or a test gas report: yarn test:report-gas ### Deploy contracts[​](https://docs.semaphore.pse.dev/getting-started#deploy-contracts "Direct link to heading") Follow the instructions below to deploy your contracts: 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. 2. Go to the `apps/contracts` folder and deploy your contract. yarn deploy --semaphore --network sepolia note Check the Semaphore contract addresses [here](https://docs.semaphore.pse.dev/deployed-contracts) . caution The group id is a number. ### Start app[​](https://docs.semaphore.pse.dev/getting-started#start-app "Direct link to heading") Start the application: yarn dev info If you want to see the code of a comprehensive application built on top of Semaphore see the [boilerplate](https://github.com/semaphore-protocol/boilerplate/tree/main) . For more info about the core libraries, keep reading the next guides. * [Output](https://docs.semaphore.pse.dev/getting-started#output) * [Usage](https://docs.semaphore.pse.dev/getting-started#usage) * [Compile contracts](https://docs.semaphore.pse.dev/getting-started#compile-contracts) * [Test contracts](https://docs.semaphore.pse.dev/getting-started#test-contracts) * [Deploy contracts](https://docs.semaphore.pse.dev/getting-started#deploy-contracts) * [Start app](https://docs.semaphore.pse.dev/getting-started#start-app) --- # Proofs | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/guides/proofs#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/guides/proofs) ** (V4). Version: V3 On this page Once a user joins their [Semaphore identity](https://docs.semaphore.pse.dev/V3/glossary#semaphore-identity) to a [Semaphore group](https://docs.semaphore.pse.dev/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. Developers can use Semaphore for the following: * [**Generate a proof off-chain**](https://docs.semaphore.pse.dev/V3/guides/proofs#generate-a-proof-off-chain) * [**Verify a proof off-chain**](https://docs.semaphore.pse.dev/V3/guides/proofs#verify-a-proof-off-chain) * [**Verify a proof on-chain**](https://docs.semaphore.pse.dev/V3/guides/proofs#verify-a-proof-on-chain) Generate a proof off-chain[​](https://docs.semaphore.pse.dev/V3/guides/proofs#generate-a-proof-off-chain "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------------- 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](https://docs.semaphore.pse.dev/V3/glossary#trusted-setup-files) . #### Install library:[​](https://docs.semaphore.pse.dev/V3/guides/proofs#install-library "Direct link to heading") * npm * Yarn * pnpm npm install @semaphore-protocol/proof@^3 yarn add @semaphore-protocol/proof@^3 pnpm add @semaphore-protocol/proof@^3 In the voting system use case, once all the voters have joined their [identities](https://docs.semaphore.pse.dev/V3/guides/identities#create-identities) to the ballot [group](https://docs.semaphore.pse.dev/V3/guides/groups) , a voter can generate a proof to vote for a proposal. In the call to `generateProof`, the voting system passes the unique ballot ID (the [Merkle tree](https://docs.semaphore.pse.dev/V3/glossary#merkle-tree) root of the group) as the `externalNullifier` to prevent the voter signaling more than once for the ballot. The following code sample shows how to use `generateProof` to generate the voting proof: import { generateProof } from "@semaphore-protocol/proof"const externalNullifier = group.rootconst signal = 1const fullProof = await generateProof(identity, group, externalNullifier, signal, { zkeyFilePath: "./semaphore.zkey", wasmFilePath: "./semaphore.wasm"}) info If you are generating the proof on the client side, you can avoid adding the snark artifacts because they are fetched automatically: const fullProof = await generateProof(identity, group, externalNullifier, signal) Verify a proof off-chain[​](https://docs.semaphore.pse.dev/V3/guides/proofs#verify-a-proof-off-chain "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------- 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. The following code sample shows how to verify the previously generated proof: import { verifyProof } from "@semaphore-protocol/proof"await verifyProof(fullProof, 20) // true or false. `verifyProof` returns a Promise that resolves to `true` or `false`. Verify a proof on-chain[​](https://docs.semaphore.pse.dev/V3/guides/proofs#verify-a-proof-on-chain "Direct link to heading") ----------------------------------------------------------------------------------------------------------------------------- Use the [`Semaphore.sol`](https://docs.semaphore.pse.dev/V3/technical-reference/contracts#semaphoresol) contract to verify proofs on-chain. info See our [deployed contracts](https://docs.semaphore.pse.dev/V3/deployed-contracts) to find the addresses for your network. 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. 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. * [Generate a proof off-chain](https://docs.semaphore.pse.dev/V3/guides/proofs#generate-a-proof-off-chain) * [Verify a proof off-chain](https://docs.semaphore.pse.dev/V3/guides/proofs#verify-a-proof-off-chain) * [Verify a proof on-chain](https://docs.semaphore.pse.dev/V3/guides/proofs#verify-a-proof-on-chain) --- # Troubleshooting | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/troubleshooting#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page If these suggestions do not work, feel free to ask for more help and support on [Github Discussions](https://github.com/semaphore-protocol/semaphore/discussions) or [Telegram](https://semaphore.pse.dev/telegram) . Transaction reverted when using the same nullifier[​](https://docs.semaphore.pse.dev/troubleshooting#transaction-reverted-when-using-the-same-nullifier "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When you generate a proof using the same [scope](https://docs.semaphore.pse.dev/glossary#scope) you used to validate a proof before, the transaction will be reverted because that scope (and thus the [nullifier](https://docs.semaphore.pse.dev/glossary#nullifier) ) has already been used. If you want to send and validate several proofs from the same identity, you need to use a different scope for each time you generate a proof. * [Transaction reverted when using the same nullifier](https://docs.semaphore.pse.dev/troubleshooting#transaction-reverted-when-using-the-same-nullifier) --- # Contracts | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/technical-reference/contracts#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page Semaphore contracts are designed with minimal yet essential code, enabling developers to efficiently manage on-chain groups and verify or validate zero-knowledge proofs. There are three contracts: * [`SemaphoreVerifier.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/base/SemaphoreVerifier.sol) * [`SemaphoreGroups.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/base/SemaphoreGroups.sol) * [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) info To use Semaphore contracts and interfaces in your project, install the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/contracts) NPM package. SemaphoreVerifier.sol[​](https://docs.semaphore.pse.dev/technical-reference/contracts#semaphoreverifiersol "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------- `SemaphoreVerifier.sol` is an extended version of the Groth16 verifier generated by default with [SnarkJS](https://github.com/iden3/snarkjs) . It contains a function for verifying proofs and a list of verification keys parameters. Since the Semaphore circuit is compiled with a `MAX_DEPTH` range from 1 to 32 during the [trusted setup](https://docs.semaphore.pse.dev/glossary#trusted-setup) , the verifier must contain the parameters of the verification keys of each instance. SemaphoreGroups.sol[​](https://docs.semaphore.pse.dev/technical-reference/contracts#semaphoregroupssol "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------------- `SemaphoreGroups.sol` is an abstract contract which contains the functions required to create on-chain groups, and add/remove/update members. Each group is assigned an admin, which can be an Ethereum account or another contract. This contract uses the [`LeanIMT.sol`](https://github.com/privacy-scaling-explorations/zk-kit/blob/main/packages/imt.sol/contracts/internal/InternalLeanIMT.sol) ZK-Kit library, an optimized binary incremental Merkle tree with [Poseidon](https://www.poseidon-hash.info/) . Semaphore.sol[​](https://docs.semaphore.pse.dev/technical-reference/contracts#semaphoresol "Direct link to heading") --------------------------------------------------------------------------------------------------------------------- `Semaphore.sol` inherits `SemaphoreGroups.sol` and adds functions to verify (`verifyProof`) or validate (`validateProof`) a Semaphore proof. The only constructor parameter is the `SemaphoreVerifier.sol` address, which must be deployed separately. The `verifyProof` function contains code for checking whether a Semaphore proof is true or false. It is a read-only view function that in addition to verifying the proof also includes a mechanism for keeping track of proofs generated with old Merkle roots, i.e. group instances that contained fewer or different members. The `validateProof` function first checks whether a proof with the same nullifier has already been validated, and then verifies the proof with the `verifyProof` function and saves the nullifier. This function also creates a log with the group id and the proof, which can then additionally be verified off-chain. info Semaphore contracts are deployed on the main testnets and Arbitrum One. See the [deployed contracts](https://docs.semaphore.pse.dev/deployed-contracts) to check the addresses. * [SemaphoreVerifier.sol](https://docs.semaphore.pse.dev/technical-reference/contracts#semaphoreverifiersol) * [SemaphoreGroups.sol](https://docs.semaphore.pse.dev/technical-reference/contracts#semaphoregroupssol) * [Semaphore.sol](https://docs.semaphore.pse.dev/technical-reference/contracts#semaphoresol) --- # FAQ | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/V3/faq#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** This is documentation for Semaphore **V3**, which is no longer actively maintained. For up-to-date documentation, see the **[latest version](https://docs.semaphore.pse.dev/faq) ** (V4). Version: V3 On this page What is Semaphore?[​](https://docs.semaphore.pse.dev/V3/faq#what-is-semaphore "Direct link to heading") -------------------------------------------------------------------------------------------------------- Semaphore is a zero-knowledge protocol that allows users to prove their membership in a group and send signals such as votes, feedback, or text messages without revealing the user’s identity. This means that signals have no connection to the identities. It also provides a simple mechanism to prevent double-signaling, which means you cannot verify the same proof twice. Where can I ask questions about Semaphore?[​](https://docs.semaphore.pse.dev/V3/faq#where-can-i-ask-questions-about-semaphore "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------------------------- You can ask questions about Semaphore on [Telegram](https://semaphore.pse.dev/telegram) or by opening a [Semaphore Discussion](https://github.com/semaphore-protocol/semaphore/discussions) . Why do identities require both the `identity trapdoor` and the `identity nullifier`?[​](https://docs.semaphore.pse.dev/V3/faq#why-do-identities-require-both-the-identity-trapdoor-and-the-identity-nullifier "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Having two private values provides an additional security layer. If someone breaks the nullifier hash (imagine there is some malleability that Poseidon preimage is easy to find when hashed with specific value X, which is the external nullifier chosen by devs), the attacker can find all messages the same person sent, but they cannot find which person, because there is also the trapdoor, which could be more difficult to break. What is the difference between the `identity nullifier`, `external nullifier` and `nullifier hash`?[​](https://docs.semaphore.pse.dev/V3/faq#what-is-the-difference-between-the-identity-nullifier-external-nullifier-and-nullifier-hash "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The identity nullifier is one of the user's secret values, whereas the external nullifier can be used like a topic on which users can generate a valid proof (e.g. send anonymous votes) a limited number of times. Both the identity nullifier and the external nullifier are used to prevent the same proof from being verified twice, which means that if a user generates the same proof (with same identity and same external nullifier) twice, the second one will not be valid. Finally, the nullifier hash is just the hash of the identity nullifier and the external nullifier which is used to check if the same proof has already been generated. In the case of a voting application, if you have a group and you want all members of this group to vote only once, you can use the id of the group as an external nullifier. When a user votes the first time, you can save the hash of their identity nullifier and the group id (i.e. the nullifier hash) and prevent double-voting by checking if that hash already exists. See the [Semaphore circuits](https://docs.semaphore.pse.dev/technical-reference/circuits) for more technical information, or the [Semaphore boilerplate](https://github.com/semaphore-protocol/boilerplate/tree/version/3) for a real use-case. Why should I prevent proofs from being verified twice?[​](https://docs.semaphore.pse.dev/V3/faq#why-should-i-prevent-proofs-from-being-verified-twice "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Since zero-knowledge proofs are completely anonymous, it is important to prevent those generated by eligible identities from being reused by a malicious party. In an anonymous voting application for example, without any checks, a valid proof could be reused to vote again. Where can I find examples of applications using Semaphore?[​](https://docs.semaphore.pse.dev/V3/faq#where-can-i-find-examples-of-applications-using-semaphore "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can find some applications that are using Semaphore in [this blog post](https://mirror.xyz/privacy-scaling-explorations.eth/Yi4muh-vzDZmIqJIcM9Mawu2e7jw8MRnwxvhFcyfns8) . How can I start a project using Semaphore?[​](https://docs.semaphore.pse.dev/V3/faq#how-can-i-start-a-project-using-semaphore "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------------------------------- There are three ways you can start using Semaphore in your project: using the [Semaphore CLI](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/cli) , using the [Semaphore boilerplate](https://github.com/semaphore-protocol/boilerplate/tree/version/3) as a template or forking it, or installing the Semaphore packages manually. ### Semaphore CLI[​](https://docs.semaphore.pse.dev/V3/faq#semaphore-cli "Direct link to heading") To create a new project you could use `npx` or install the [Semaphore CLI](https://github.com/semaphore-protocol/semaphore/tree/v3.15.2/packages/cli) globally using `npm` and then create the new project using the `semaphore create` command. See the [Quick Setup](https://docs.semaphore.pse.dev/quick-setup) for more information. There are three supported templates right now: `contracts-hardhat`, `monorepo-ethers` and `monorepo-subgraph`. * `contracts-hardhat`: It contains a basic Semaphore use case. It comes with a sample contract, a test for that contract and a sample task that deploys that contract. * `monorepo-ethers`: It is a complete application that demonstrates a basic Semaphore use case. It comes with a sample contract, a test for that contract and a sample task that deploys that contract. It also contains a frontend to play around with the contract. This template uses [Ethers](https://github.com/ethers-io/ethers.js/) under the hood to get on-chain data. * `monorepo-subgraph`: It is the same as the monorepo-ethers template, but uses [The Graph protocol](https://thegraph.com/) under the hood to get on-chain data. The Semaphore CLI can also be used to get group data from a supported network. There are commands like: `get-groups`, `get-group`, `get-members`, `get-proofs`: * `get-groups`: It shows the list of groups from a supported network. * `get-group`: It shows the data of a group from a supported network. * `get-members`: It shows the members of a group from a supported network. * `get-proofs`: It shows the proofs of a group from a supported network. ### Semaphore boilerplate[​](https://docs.semaphore.pse.dev/V3/faq#semaphore-boilerplate "Direct link to heading") To create a project, you could also use the [Semaphore boilerplate](https://github.com/semaphore-protocol/boilerplate/tree/version/3) . You could fork it or use it as a template. The Semaphore CLI templates and the Semaphore boilerplate contain the same code, which is a feedback application where you can create an identity, join a group, and send your feedback anonymously. They are almost the same, the only difference is that the templates use plain CSS so you can decide the CSS framework or library you want to use and the boilerplate uses [ChakraUI](https://chakra-ui.com/) by default. You can also try the live Semaphore boilerplate app here: [https://demo.semaphore.pse.dev](https://demo.semaphore.pse.dev/) . ### Manual install[​](https://docs.semaphore.pse.dev/V3/faq#manual-install "Direct link to heading") Alternatively, you can also install all packages manually using npm or yarn following the [Semaphore documentation](https://docs.semaphore.pse.dev/) . How can I contribute to the protocol?[​](https://docs.semaphore.pse.dev/V3/faq#how-can-i-contribute-to-the-protocol "Direct link to heading") ---------------------------------------------------------------------------------------------------------------------------------------------- There are several ways you could contribute to the protocol, you can find more information about it here: [https://github.com/semaphore-protocol#ways-to-contribute](https://github.com/semaphore-protocol#ways-to-contribute) . * [What is Semaphore?](https://docs.semaphore.pse.dev/V3/faq#what-is-semaphore) * [Where can I ask questions about Semaphore?](https://docs.semaphore.pse.dev/V3/faq#where-can-i-ask-questions-about-semaphore) * [Why do identities require both the `identity trapdoor` and the `identity nullifier`?](https://docs.semaphore.pse.dev/V3/faq#why-do-identities-require-both-the-identity-trapdoor-and-the-identity-nullifier) * [What is the difference between the `identity nullifier`, `external nullifier` and `nullifier hash`?](https://docs.semaphore.pse.dev/V3/faq#what-is-the-difference-between-the-identity-nullifier-external-nullifier-and-nullifier-hash) * [Why should I prevent proofs from being verified twice?](https://docs.semaphore.pse.dev/V3/faq#why-should-i-prevent-proofs-from-being-verified-twice) * [Where can I find examples of applications using Semaphore?](https://docs.semaphore.pse.dev/V3/faq#where-can-i-find-examples-of-applications-using-semaphore) * [How can I start a project using Semaphore?](https://docs.semaphore.pse.dev/V3/faq#how-can-i-start-a-project-using-semaphore) * [Semaphore CLI](https://docs.semaphore.pse.dev/V3/faq#semaphore-cli) * [Semaphore boilerplate](https://docs.semaphore.pse.dev/V3/faq#semaphore-boilerplate) * [Manual install](https://docs.semaphore.pse.dev/V3/faq#manual-install) * [How can I contribute to the protocol?](https://docs.semaphore.pse.dev/V3/faq#how-can-i-contribute-to-the-protocol) --- # Proofs | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/guides/proofs#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page Once a user joins a [Semaphore group](https://docs.semaphore.pse.dev/glossary#group) with their [Semaphore identity](https://docs.semaphore.pse.dev/glossary#identity) , the user can send their anonymous [message](https://docs.semaphore.pse.dev/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. A unique [nullifier](https://docs.semaphore.pse.dev/glossary#nullifier) is also generated for each proof that can be used to check whether that proof has already been validated. Install package[​](https://docs.semaphore.pse.dev/guides/proofs#install-package "Direct link to heading") ---------------------------------------------------------------------------------------------------------- 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. * npm * Yarn * pnpm npm install @semaphore-protocol/proof yarn add @semaphore-protocol/proof pnpm add @semaphore-protocol/proof info Semaphore also provides `@semaphore-protocol/core`, which includes the functions of the following core packages: `@semaphore-protocol/identity`, `@semaphore-protocol/group`, `@semaphore-protocol/proof`. Generate a proof[​](https://docs.semaphore.pse.dev/guides/proofs#generate-a-proof "Direct link to heading") ------------------------------------------------------------------------------------------------------------ ### 1\. Create the identity[​](https://docs.semaphore.pse.dev/guides/proofs#1-create-the-identity "Direct link to heading") In order for a user to generate a proof, it is necessary to create a Semaphore identity. If you do not know how to create an identity, see the previous [guide](https://docs.semaphore.pse.dev/guides/identities) on identities. ### 2\. Create the group[​](https://docs.semaphore.pse.dev/guides/proofs#2-create-the-group "Direct link to heading") Before generating a proof you also need to create a Semaphore group containing the commitment of the Semaphore identity of the user who will generate the proof. If you do not know how to create a group, see the previous [guide](https://docs.semaphore.pse.dev/guides/groups) on groups. If your group is on-chain, you can use the [`@semaphore-protocol/data`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/data) library to fetch the group members and re-create the off-chain group. For example: import { SemaphoreSubgraph } from "@semaphore-protocol/data"import { Group } from "@semaphore-protocol/group"const semaphoreSubgraph = new SemaphoreSubgraph("sepolia")const { members } = await semaphoreSubgraph.getGroup("42", { members: true })const group = new Group(members) ### 3\. Choose the scope[​](https://docs.semaphore.pse.dev/guides/proofs#3-choose-the-scope "Direct link to heading") Each proof requires a [scope](https://docs.semaphore.pse.dev/glossary#scope) , on which each user may only generate one valid proof. The scope, together with the user's private key, is used to generate the nullifier, which is the value you can actually use to check whether a proof with that scope has already been generated by that user. In a voting application where double-voting must be prevented, the scope could be the ballot id, or the Merkle root of the group. ### 4\. Generate the anonymous message[​](https://docs.semaphore.pse.dev/guides/proofs#4-generate-the-anonymous-message "Direct link to heading") Finally, you can generate the proof with the anonymous message using the `generateProof` function. For example: import { generateProof } from "@semaphore-protocol/proof"const scope = group.rootconst message = 1const proof = await generateProof(identity, group, message, scope) Verify a proof[​](https://docs.semaphore.pse.dev/guides/proofs#verify-a-proof "Direct link to heading") -------------------------------------------------------------------------------------------------------- To verify a proof, pass the proof you generated to the `verifyProof` function. For example: import { verifyProof } from "@semaphore-protocol/proof"await verifyProof(proof) // true or false. If you want to validate a proof on-chain, you can use [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts) and the [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) contract, as explained in the previous [guide](https://docs.semaphore.pse.dev/guides/groups#install-package-1) , and use the `validateProof` function. For example: function validateProof(ISemaphore.SemaphoreProof calldata proof) external { semaphore.validateProof(groupId, proof);} * [Install package](https://docs.semaphore.pse.dev/guides/proofs#install-package) * [Generate a proof](https://docs.semaphore.pse.dev/guides/proofs#generate-a-proof) * [1\. Create the identity](https://docs.semaphore.pse.dev/guides/proofs#1-create-the-identity) * [2\. Create the group](https://docs.semaphore.pse.dev/guides/proofs#2-create-the-group) * [3\. Choose the scope](https://docs.semaphore.pse.dev/guides/proofs#3-choose-the-scope) * [4\. Generate the anonymous message](https://docs.semaphore.pse.dev/guides/proofs#4-generate-the-anonymous-message) * [Verify a proof](https://docs.semaphore.pse.dev/guides/proofs#verify-a-proof) --- # Circuits | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/technical-reference/circuits#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page 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](https://docs.semaphore.pse.dev/technical-reference/circuits#proof-of-membership) * [Nullifier](https://docs.semaphore.pse.dev/technical-reference/circuits#nullifier) * [Message](https://docs.semaphore.pse.dev/technical-reference/circuits#message) ![Semaphore circuit](https://github.com/semaphore-protocol/semaphore/raw/main/packages/circuits/scheme.png) The diagram above shows how the input signals are used in the Semaphore circuit and how the outputs are calculated. Proof of membership[​](https://docs.semaphore.pse.dev/technical-reference/circuits#proof-of-membership "Direct link to heading") --------------------------------------------------------------------------------------------------------------------------------- The circuit derive the public key from the secret and hashes the public key to generate an identity commitment. Then, it verifies the proof of membership against the Merkle root and the identity commitment. **Private inputs:** * `merkleProofLength`: the actual number of nodes in the Merkle proof path, * `merkleProofIndices[MAX_DEPTH]`: the list of 0s and 1s to calculate the hashes of the nodes at the correct position, * `merkleProofSiblings[MAX_DEPTH]`: the list of siblings nodes to be used to calculate the hashes of the nodes up to the root, * `secret`: the EdDSA [secret scalar](https://www.rfc-editor.org/rfc/rfc8032#section-5.1.5) derived from the private key. **Public outputs:** * `merkleRoot`: The Merkle root of the tree. Nullifier[​](https://docs.semaphore.pse.dev/technical-reference/circuits#nullifier "Direct link to heading") ------------------------------------------------------------------------------------------------------------- The circuit hashes the secret with the scope and then checks that the result matches the provided nullifier. **Private inputs:** * `secret`: the EdDSA [secret scalar](https://www.rfc-editor.org/rfc/rfc8032#section-5.1.5) derived from the private key. **Public inputs:** * `scope`: the value used like a topic on which users can generate a valid proof only once. **Public outputs:** * `nullifier`: the value designed to be a unique identifier and used to prevent the same proof from being used twice. Message[​](https://docs.semaphore.pse.dev/technical-reference/circuits#message "Direct link to heading") --------------------------------------------------------------------------------------------------------- The circuit calculates a dummy square of the message to prevent any tampering with the proof. **Public inputs:** * `message`: the anonymous value the user broadcasts. * [Proof of membership](https://docs.semaphore.pse.dev/technical-reference/circuits#proof-of-membership) * [Nullifier](https://docs.semaphore.pse.dev/technical-reference/circuits#nullifier) * [Message](https://docs.semaphore.pse.dev/technical-reference/circuits#message) --- # Identities | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/guides/identities#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page In order to join a [Semaphore group](https://docs.semaphore.pse.dev/glossary#group) , a user must first create a [Semaphore identity](https://docs.semaphore.pse.dev/glossary#identity) . A Semaphore identity contains three values generated with the identity: * 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. Install package[​](https://docs.semaphore.pse.dev/guides/identities#install-package "Direct link to heading") -------------------------------------------------------------------------------------------------------------- In your code, use the [`@semaphore-protocol/identity`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/identity) package to manage Semaphore identities. * npm * Yarn * pnpm npm install @semaphore-protocol/identity yarn add @semaphore-protocol/identity pnpm add @semaphore-protocol/identity info Semaphore also provides `@semaphore-protocol/core`, which includes the functions of the following core packages: `@semaphore-protocol/identity`, `@semaphore-protocol/group`, `@semaphore-protocol/proof`. Create identities[​](https://docs.semaphore.pse.dev/guides/identities#create-identities "Direct link to heading") ------------------------------------------------------------------------------------------------------------------ ### Create random identities[​](https://docs.semaphore.pse.dev/guides/identities#create-random-identities "Direct link to heading") To create a random identity, instantiate `Identity` without any parameters. For example: import { Identity } from "@semaphore-protocol/identity"const { privateKey, publicKey, commitment } = new Identity() The new identity contains your private key, your public key, and its associated commitment, which serves as a public representation of the identity (similar to an Ethereum address). ### Create deterministic identities[​](https://docs.semaphore.pse.dev/guides/identities#create-deterministic-identities "Direct link to heading") If you pass a previously used private key or any secret value that acts as your private key as parameter, you can deterministically generate a Semaphore identity. const identity1 = new Identity(privateKey)// orconst identity2 = new Identity("secret-value") tip Building a system to save or recover secret values of Semaphore identities is nontrivial. You may choose to delegate such functionality to existing wallets such as Metamask. For example: 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. Privacy risk If a user signs the **same message** on multiple websites using MetaMask, all those websites will be able to **generate the same Semaphore identity**. This undermines anonymity and may allow third parties to **link identities across platforms** or even **gain control over a user's identity**. To mitigate this, encourage users to sign **unique messages per application** or implement safeguards that detect and warn about reuse. Sign and verify messages[​](https://docs.semaphore.pse.dev/guides/identities#sign-and-verify-messages "Direct link to heading") -------------------------------------------------------------------------------------------------------------------------------- Semaphore V4 uses asymmetric cryptography and in particular EdDSA to generate the identity keys. It is therefore also possible to sign messages and verify their signatures. ### Sign a message[​](https://docs.semaphore.pse.dev/guides/identities#sign-a-message "Direct link to heading") Any Semaphore identity can sign a message by simply passing a string, number or buffer. const message = "Hello World"const signature = identity1.signMessage(message) ### Verify a signature[​](https://docs.semaphore.pse.dev/guides/identities#verify-a-signature "Direct link to heading") After a message is signed, anyone can verify the signature using the message itself, the signature, and the signer's public key. // Static method.Identity.verifySignature(message, signature, identity1.publicKey) Export and import an identity[​](https://docs.semaphore.pse.dev/guides/identities#export-and-import-an-identity "Direct link to heading") ------------------------------------------------------------------------------------------------------------------------------------------ A Semaphore Identity can be exported and then imported later for reuse. ### Export an identity[​](https://docs.semaphore.pse.dev/guides/identities#export-an-identity "Direct link to heading") Returns the private key encoded as a base64 string. import { Identity } from "@semaphore-protocol/identity"const identity = new Identity()const privateKey = identity.export() ### Import an identity[​](https://docs.semaphore.pse.dev/guides/identities#import-an-identity "Direct link to heading") Returns a Semaphore identity based on a private key encoded as a base64 string. import { Identity } from "@semaphore-protocol/identity"const identity = new Identity()const privateKey = identity.export()const identity2 = Identity.import(privateKey) * [Install package](https://docs.semaphore.pse.dev/guides/identities#install-package) * [Create identities](https://docs.semaphore.pse.dev/guides/identities#create-identities) * [Create random identities](https://docs.semaphore.pse.dev/guides/identities#create-random-identities) * [Create deterministic identities](https://docs.semaphore.pse.dev/guides/identities#create-deterministic-identities) * [Sign and verify messages](https://docs.semaphore.pse.dev/guides/identities#sign-and-verify-messages) * [Sign a message](https://docs.semaphore.pse.dev/guides/identities#sign-a-message) * [Verify a signature](https://docs.semaphore.pse.dev/guides/identities#verify-a-signature) * [Export and import an identity](https://docs.semaphore.pse.dev/guides/identities#export-and-import-an-identity) * [Export an identity](https://docs.semaphore.pse.dev/guides/identities#export-an-identity) * [Import an identity](https://docs.semaphore.pse.dev/guides/identities#import-an-identity) --- # Groups | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/guides/groups#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page A [Semaphore group](https://docs.semaphore.pse.dev/glossary#group) contains [identity commitments](https://docs.semaphore.pse.dev/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. info Semaphore V4 uses the [ZK-Kit](https://github.com/privacy-scaling-explorations/zk-kit) LeanIMT (i.e., Lean Incremental Merkle Tree) [Solidity](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/imt.sol/contracts) and [JavaScript](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/imt) implementations for managing groups. Groups are Merkle trees, and the group members (i.e., identity commitments) are their leaves. Off-chain groups[​](https://docs.semaphore.pse.dev/guides/groups#off-chain-groups "Direct link to heading") ------------------------------------------------------------------------------------------------------------ Use the [`@semaphore-protocol/group`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/group) package to manage off-chain groups. ### Install package[​](https://docs.semaphore.pse.dev/guides/groups#install-package "Direct link to heading") * npm * Yarn * pnpm npm install @semaphore-protocol/group yarn add @semaphore-protocol/group pnpm add @semaphore-protocol/group info Semaphore also provides `@semaphore-protocol/core`, which includes the functions of the following core packages: `@semaphore-protocol/identity`, `@semaphore-protocol/group`, `@semaphore-protocol/proof`. ### Create a group[​](https://docs.semaphore.pse.dev/guides/groups#create-a-group "Direct link to heading") To create a group instantiate `Group` without any parameters. For example: import { Group } from "@semaphore-protocol/group"const group1 = new Group() You can also initialize a group with multiple members by passing the list of identity commitments as the first parameter when creating the group: const members = [ 11237622825477336339577122413451117718539783476837539122310492284566644730311n, 9332663527862709610616009715800254142772436825222910251631161087138559093425n, 13255821893820536903335282929376140649646180444238593676033702344407594536519n]const group2 = new Group(members) ### Add members[​](https://docs.semaphore.pse.dev/guides/groups#add-members "Direct link to heading") Use the `addMember` method to add a member to a group. For example: import { Identity } from "@semaphore-protocol/identity"const { commitment } = new Identity()group1.addMember(commitment) To add a batch of members to a group, pass an array to the `addMembers` method. For example: group1.addMembers(members) caution When you use the same Semaphore identity across multiple groups, if an attacker takes control of that identity all the groups it is part of will be compromised. Consider using different identities for each group. ### Remove or update members[​](https://docs.semaphore.pse.dev/guides/groups#remove-or-update-members "Direct link to heading") To remove members from a group, pass the member index to the `removeMember` method. For example: group.removeMember(0) To update members in a group, pass the member index and the new value to the `updateMember` method. For example: group.updateMember(0, 2n) caution Removing a member from a group sets its value to 0. Given that the member isn't removed, the number of members (i.e., `group.size` on `group.members.length`) doesn't change. ### Generate a Merkle proof[​](https://docs.semaphore.pse.dev/guides/groups#generate-a-merkle-proof "Direct link to heading") Semaphore groups are [Merkle trees](https://docs.semaphore.pse.dev/glossary#merkle-tree) , and it is therefore possible to calculate the Merkle proof of a group member (i.e., tree leaf) by passing the index of the member to the `generateMerkleProof`. For example: group.generateMerkleProof(0) On-chain groups[​](https://docs.semaphore.pse.dev/guides/groups#on-chain-groups "Direct link to heading") ---------------------------------------------------------------------------------------------------------- Semaphore provides [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) , a contract designed for managing on-chain groups ([deployed](https://docs.semaphore.pse.dev/deployed-contracts) on major testnets). Use the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts) package to import the `ISemaphore.sol` interface in your contract and start using its functions. ### Install package[​](https://docs.semaphore.pse.dev/guides/groups#install-package-1 "Direct link to heading") * npm * Yarn * pnpm npm install @semaphore-protocol/contracts yarn add @semaphore-protocol/contracts pnpm add @semaphore-protocol/contracts ### Create a group[​](https://docs.semaphore.pse.dev/guides/groups#create-a-group-1 "Direct link to heading") 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: pragma solidity ^0.8.23;import "@semaphore-protocol/contracts/interfaces/ISemaphore.sol";contract YourContract { ISemaphore public semaphore; uint256 public groupId; constructor(ISemaphore _semaphore) { semaphore = _semaphore; 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. 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[​](https://docs.semaphore.pse.dev/guides/groups#add-members-1 "Direct link to heading") Use the `addMember` function to add a member to a group. For example: function addMember(uint256 identityCommitment) external { semaphore.addMember(groupId, identityCommitment);} To add a batch of members to a group, pass an array to the `addMembers` function. For example: function addMembers(uint256[] calldata identityCommitments) external { semaphore.addMembers(groupId, identityCommitments);} ### Remove or update members[​](https://docs.semaphore.pse.dev/guides/groups#remove-or-update-members-1 "Direct link to heading") To update members in a group, pass the identity commitment of the member you want to update, its new identity commitment and the siblings of the Merkle proof for that member. For example: function updateMember(uint256 identityCommitment, uint256 newIdentityCommitment, uint256[] calldata merkleProofSiblings) external { semaphore.updateMember(groupId, identityCommitment, newIdentityCommitment, merkleProofSiblings);} info To calculate the Merkle proof of a group member you can use the `generateMerkleProof` method of the JavaScript `Group` class described above. To remove members from a group, pass the identity commitment of the member you want to remove and the siblings of the Merkle proof for that member. For example: function removeMember(uint256 identityCommitment, uint256[] calldata merkleProofSiblings) external { semaphore.removeMember(groupId, identityCommitment, merkleProofSiblings);} 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`. * [Off-chain groups](https://docs.semaphore.pse.dev/guides/groups#off-chain-groups) * [Install package](https://docs.semaphore.pse.dev/guides/groups#install-package) * [Create a group](https://docs.semaphore.pse.dev/guides/groups#create-a-group) * [Add members](https://docs.semaphore.pse.dev/guides/groups#add-members) * [Remove or update members](https://docs.semaphore.pse.dev/guides/groups#remove-or-update-members) * [Generate a Merkle proof](https://docs.semaphore.pse.dev/guides/groups#generate-a-merkle-proof) * [On-chain groups](https://docs.semaphore.pse.dev/guides/groups#on-chain-groups) * [Install package](https://docs.semaphore.pse.dev/guides/groups#install-package-1) * [Create a group](https://docs.semaphore.pse.dev/guides/groups#create-a-group-1) * [Add members](https://docs.semaphore.pse.dev/guides/groups#add-members-1) * [Remove or update members](https://docs.semaphore.pse.dev/guides/groups#remove-or-update-members-1) --- # Code editors and LLM setup | Semaphore [Skip to main content](https://docs.semaphore.pse.dev/llm-setup#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Version: V4 On this page LLMs often rely on outdated or generic information. Use this guide to help set up your code editor to pull in more accurate, up-to-date documentation and examples. It will help provide better answers and generate more accurate Semaphore code using LLMs (large language models) and MCP (Model Context Protocol) servers. Quick use[​](https://docs.semaphore.pse.dev/llm-setup#quick-use "Direct link to heading") ------------------------------------------------------------------------------------------ [llms.txt](https://docs.semaphore.pse.dev/llms.txt) is a compact, text version of the Semaphore docs. Add this link directly to your chat window for enhanced context. Permanent setup[​](https://docs.semaphore.pse.dev/llm-setup#permanent-setup "Direct link to heading") ------------------------------------------------------------------------------------------------------ Depending on your IDE, you can add custom docs to VS Code, Cursor or others. Example for Cursor... 1. Press `CMD + Shift + P` (unix), `Ctrl + Shift + P` (Windows) 2. Type `Add new custom docs`. 3. Add [https://docs.semaphore.pse.dev/llms.txt](https://docs.semaphore.pse.dev/llms.txt) 4. In chat you can know `@docs` and choose `semaphore` to provide additional context. Refer to the documentation of your IDE to properly set it up. MCP Server[​](https://docs.semaphore.pse.dev/llm-setup#mcp-server "Direct link to heading") -------------------------------------------------------------------------------------------- Depending on your IDE, you can add a MCP server to communicate your docs to the AI model. * [Context7 MCP server](https://github.com/upstash/context7) is a server that provides many libraries, incl. Semaphore. Example for Cursor... 1. Press `CMD + Shift + J` (unix), `Ctrl + Shift + J` (Windows) 2. Click on `MCP` on the sidebar 3. Click `Add new global MCP server` 4. Add the following code to `mcp.json` { "mcpServers": { "Context7": { "type": "stdio", "command": "npx", "args": ["-y", "@upstash/context7-mcp@latest"] } }} You can now prompt anything about Semaphore and write `use context7` at the end of your prompt. E.g. `create a new Semaphore identity in TypeScript. use context`. This will call the MCP tool and automatically fetch the latest documentation. Refer to the documentation of your IDE to properly set it up. * [Quick use](https://docs.semaphore.pse.dev/llm-setup#quick-use) * [Permanent setup](https://docs.semaphore.pse.dev/llm-setup#permanent-setup) * [MCP Server](https://docs.semaphore.pse.dev/llm-setup#mcp-server) --- # What Is Semaphore? | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página Overview[​](https://docs.semaphore.pse.dev/es/#overview "Enlace directo al encabezado") ---------------------------------------------------------------------------------------- [Semaphore](https://github.com/semaphore-protocol/semaphore/tree/main) is a [zero-knowledge](https://z.cash/technology/zksnarks) protocol that allows you to cast a message (for example, a vote or endorsement) as a provable group member without revealing your identity. Additionally, it provides a simple mechanism to prevent double-signaling. Use cases include private voting, whistleblowing, anonymous DAOs and mixers. For in-depth technical details about Semaphore, refer to the [Semaphore V4 Specification](https://github.com/zkspecs/zkspecs/blob/main/specs/3/README.md) . Features[​](https://docs.semaphore.pse.dev/es/#features "Enlace directo al encabezado") ---------------------------------------------------------------------------------------- With Semaphore, you can allow your users to do the following: 1. [Create a Semaphore identity](https://docs.semaphore.pse.dev/es/guides/identities) . 2. [Add their Semaphore identity to a group (i.e. _Merkle tree_)](https://docs.semaphore.pse.dev/es/guides/groups) . 3. [Send a verifiable, anonymous message (e.g a vote or endorsement)](https://docs.semaphore.pse.dev/es/guides/proofs) . When a user broadcasts a message, Semaphore zero-knowledge proofs can ensure that the user has joined the group and hasn't already cast a message with their nullifier. Semaphore uses on-chain Solidity contracts and off-chain JavaScript libraries that work in tandem. * Off chain, JavaScript libraries can be used to create identities, manage groups and generate proofs. * On chain, Solidity contracts can be used to manage groups and verify proofs. Developer benefits[​](https://docs.semaphore.pse.dev/es/#developer-benefits "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------ Semaphore is designed to be a simple and generic _privacy layer_ for decentralized applications (dApps) on Ethereum. It encourages modular application design, allowing dApp developers to choose and customize the on-chain and off-chain components they need. About the code[​](https://docs.semaphore.pse.dev/es/#about-the-code "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------- The core of the protocol is the [circuit logic](https://github.com/semaphore-protocol/semaphore/tree/main/packages/circuits/src/semaphore.circom) . In addition to circuits, Semaphore provides [Solidity contracts](https://github.com/semaphore-protocol/semaphore/tree/main/packages/contracts) and [JavaScript libraries](https://github.com/semaphore-protocol/semaphore/tree/main#-packages) that allow developers to generate zero-knowledge proofs and verify them with minimal effort. Trusted Setup Ceremony[​](https://docs.semaphore.pse.dev/es/#trusted-setup-ceremony "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------- The [secure parameters](https://snark-artifacts.pse.dev/) for generating valid proofs with Semaphore circuits were generated in a [Trusted Setup Ceremony](https://ceremony.pse.dev/projects/Semaphore%20V4%20Ceremony) that was completed with over 400 participants on [13 July 2024](https://etherscan.io/block/20300394) . ### Audits[​](https://docs.semaphore.pse.dev/es/#audits "Enlace directo al encabezado") | 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` | * [Overview](https://docs.semaphore.pse.dev/es/#overview) * [Features](https://docs.semaphore.pse.dev/es/#features) * [Developer benefits](https://docs.semaphore.pse.dev/es/#developer-benefits) * [About the code](https://docs.semaphore.pse.dev/es/#about-the-code) * [Trusted Setup Ceremony](https://docs.semaphore.pse.dev/es/#trusted-setup-ceremony) * [Audits](https://docs.semaphore.pse.dev/es/#audits) --- # Búsqueda en la documentación | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/search#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Búsqueda en la documentación ============================ [](https://www.algolia.com/) --- # What Is Semaphore? | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V1#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V1**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V1 En esta página Overview[​](https://docs.semaphore.pse.dev/es/V1#overview "Enlace directo al encabezado") ------------------------------------------------------------------------------------------ [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[​](https://docs.semaphore.pse.dev/es/V1#basic-features "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------ 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 contract’s 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[​](https://docs.semaphore.pse.dev/es/V1#external-nullifiers "Enlace directo al encabezado") 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[​](https://docs.semaphore.pse.dev/es/V1#about-the-code "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------ 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. * [Overview](https://docs.semaphore.pse.dev/es/V1#overview) * [Basic features](https://docs.semaphore.pse.dev/es/V1#basic-features) * [External nullifiers](https://docs.semaphore.pse.dev/es/V1#external-nullifiers) * [About the code](https://docs.semaphore.pse.dev/es/V1#about-the-code) --- # Security audit | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V1/audit#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V1**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V1 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/semaphore-protocol/semaphore/blob/main/apps/docs/versioned_docs/version-V1/audit.md) . After three rounds of fixes, all security and performance issues were fixed, and the few remaining issues are minor and do not affect security. --- # Contract API | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V1/contract-api#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V1**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V1 En esta página Constructor[​](https://docs.semaphore.pse.dev/es/V1/contract-api#constructor "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------- **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[​](https://docs.semaphore.pse.dev/es/V1/contract-api#add-deactivate-or-reactivate-external-nullifiiers "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- **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[​](https://docs.semaphore.pse.dev/es/V1/contract-api#insert-identities "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------- **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](https://docs.semaphore.pse.dev/es/V1/usage#insert-identities) for more information. Broadcast signals[​](https://docs.semaphore.pse.dev/es/V1/contract-api#broadcast-signals "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------- **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](https://docs.semaphore.pse.dev/es/V1/usage#broadcast-signals) for more information. * [Constructor](https://docs.semaphore.pse.dev/es/V1/contract-api#constructor) * [Add, deactivate, or reactivate external nullifiiers](https://docs.semaphore.pse.dev/es/V1/contract-api#add-deactivate-or-reactivate-external-nullifiiers) * [Insert identities](https://docs.semaphore.pse.dev/es/V1/contract-api#insert-identities) * [Broadcast signals](https://docs.semaphore.pse.dev/es/V1/contract-api#broadcast-signals) --- # How it works | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V1/howitworks#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V1**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V1 En esta página Inserting identities[​](https://docs.semaphore.pse.dev/es/V1/howitworks#inserting-identities "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------------------- 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](https://docs.semaphore.pse.dev/es/V1/contract-api) for more information. Broadcasting signals[​](https://docs.semaphore.pse.dev/es/V1/howitworks#broadcasting-signals "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------------------- 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[​](https://docs.semaphore.pse.dev/es/V1/howitworks#the-zk-snark-circuit "Enlace directo al encabezado") 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[​](https://docs.semaphore.pse.dev/es/V1/howitworks#that-the-identity-commitment-exists-in-the-merkle-tree "Enlace directo al encabezado") **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[​](https://docs.semaphore.pse.dev/es/V1/howitworks#that-the-signal-was-only-broadcasted-once "Enlace directo al encabezado") **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[​](https://docs.semaphore.pse.dev/es/V1/howitworks#that-the-signal-was-truly-broadcasted-by-the-user-who-generated-the-proof "Enlace directo al encabezado") **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[​](https://docs.semaphore.pse.dev/es/V1/howitworks#cryptographic-primitives "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------- 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. * [Inserting identities](https://docs.semaphore.pse.dev/es/V1/howitworks#inserting-identities) * [Broadcasting signals](https://docs.semaphore.pse.dev/es/V1/howitworks#broadcasting-signals) * [The zk-SNARK circuit](https://docs.semaphore.pse.dev/es/V1/howitworks#the-zk-snark-circuit) * [That the identity commitment exists in the Merkle tree](https://docs.semaphore.pse.dev/es/V1/howitworks#that-the-identity-commitment-exists-in-the-merkle-tree) * [That the signal was only broadcasted once](https://docs.semaphore.pse.dev/es/V1/howitworks#that-the-signal-was-only-broadcasted-once) * [That the signal was truly broadcasted by the user who generated the proof](https://docs.semaphore.pse.dev/es/V1/howitworks#that-the-signal-was-truly-broadcasted-by-the-user-who-generated-the-proof) * [Cryptographic primitives](https://docs.semaphore.pse.dev/es/V1/howitworks#cryptographic-primitives) --- # Quick start | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V1/quickstart#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V1**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V1 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: git clone [email protected]: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: # Start from the base directory./circuits/scripts/download_snarks.sh To generate the above files locally instead, run: # 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`): # Start from the base directorycd contracts && \npm run compileSol Run tests while still in the `contracts/` directory: # The first command tests the Merkle tree contract and the second# tests the Semaphore contractnpm run test-semaphore && \npm run test-mt --- # libsemaphore | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V1/libsemaphore#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V1**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V1 En esta página [`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[​](https://docs.semaphore.pse.dev/es/V1/libsemaphore#available-types-interfaces-and-functions "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ### Types[​](https://docs.semaphore.pse.dev/es/V1/libsemaphore#types "Enlace directo al encabezado") **`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[​](https://docs.semaphore.pse.dev/es/V1/libsemaphore#interfaces "Enlace directo al encabezado") **`EddsaKeyPair`** Encapsulates an `EddsaPublicKey` and an `EddsaPrivateKey`. 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. interface Identity { keypair: EddsaKeyPair identityNullifier: SnarkBigInt identityTrapdoor: SnarkBigInt} **`SnarkProof`** Note that `broadcastSignal()` accepts a `uint256[8]` array for its `_proof` parameter. See `genBroadcastSignalParams()`. interface SnarkProof { pi_a: SnarkBigInt[] pi_b: SnarkBigInt[][] pi_c: SnarkBigInt[]} ### Functions[​](https://docs.semaphore.pse.dev/es/V1/libsemaphore#functions "Enlace directo al encabezado") **`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: ["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: 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: { 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. * [Available types, interfaces, and functions](https://docs.semaphore.pse.dev/es/V1/libsemaphore#available-types-interfaces-and-functions) * [Types](https://docs.semaphore.pse.dev/es/V1/libsemaphore#types) * [Interfaces](https://docs.semaphore.pse.dev/es/V1/libsemaphore#interfaces) * [Functions](https://docs.semaphore.pse.dev/es/V1/libsemaphore#functions) --- # Multi-party trusted setup | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V1/trustedsetup#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V1**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V1 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. --- # Usage | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V1/usage#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V1**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V1 En esta página 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[​](https://docs.semaphore.pse.dev/es/V1/usage#add-deactivate-or-reactivate-external-nullifiiers "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 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[​](https://docs.semaphore.pse.dev/es/V1/usage#set-broadcast-permissioning "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------------- 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[​](https://docs.semaphore.pse.dev/es/V1/usage#insert-identities "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------ To generate an identity commitment, use the `libsemaphore` functions `genIdentity()` and `genIdentityCommitment()` Typescript (or Javascript) functions: 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: ["e82cc2b8654705e427df423c6300307a873a2e637028fab3163cf95b18bb172e","a02e517dfb3a4184adaa951d02bfe0fe092d1ee34438721d798db75b8db083","15c6540bf7bddb0616984fccda7e954a0fb5ea4679ac686509dc4bd7ba9c3b"] To convert this string back into an `Identity`, use `unSerialiseIdentity()`. `const id: Identity = unSerialiseIdentity(serialisedId)` Broadcast signals[​](https://docs.semaphore.pse.dev/es/V1/usage#broadcast-signals "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------ First obtain the leaves of the identity tree (in sequence, up to the user's identity commitment, or more). const leaves = Next, load the circuit from disk (or from a remote source): 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): 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): const proof = await genProof(result.witness, provingKey) Generate the `broadcastSignal()` parameters: const publicSignals = genPublicSignals(result.witness, circuit)const params = genBroadcastSignalParams(result, proof, publicSignals) Finally, invoke `broadcastSignal()` with the parameters: const tx = await semaphoreClientContract.broadcastSignal( ethers.utils.toUtf8Bytes(signal), params.proof, params.root, params.nullifiersHash, external_nullifier, { gasLimit: 500000 }) * [Add, deactivate, or reactivate external nullifiiers](https://docs.semaphore.pse.dev/es/V1/usage#add-deactivate-or-reactivate-external-nullifiiers) * [Set broadcast permissioning](https://docs.semaphore.pse.dev/es/V1/usage#set-broadcast-permissioning) * [Insert identities](https://docs.semaphore.pse.dev/es/V1/usage#insert-identities) * [Broadcast signals](https://docs.semaphore.pse.dev/es/V1/usage#broadcast-signals) --- # Credits | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2/credits#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/credits) ** (V4). Versión: V2 Semaphore V2 is the work of several people, for a complete list of contributors you can visit our [Github pages](https://github.com/semaphore-protocol/semaphore/graphs/contributors) . * [Barry WhiteHat](https://github.com/barryWhiteHat) * [Kobi Gurkan](https://github.com/kobigurk) * [Koh Wei Jie](https://github.com/weijiekoh) * [Andrija Novakovic](https://github.com/akinovak) * [Cedoor](https://github.com/cedoor) --- # Proofs | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/guides/proofs#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página Once a user joins a [Semaphore group](https://docs.semaphore.pse.dev/es/glossary#group) with their [Semaphore identity](https://docs.semaphore.pse.dev/es/glossary#identity) , the user can send their anonymous [message](https://docs.semaphore.pse.dev/es/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. A unique [nullifier](https://docs.semaphore.pse.dev/es/glossary#nullifier) is also generated for each proof that can be used to check whether that proof has already been validated. Install package[​](https://docs.semaphore.pse.dev/es/guides/proofs#install-package "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------- 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. * npm * Yarn * pnpm npm install @semaphore-protocol/proof yarn add @semaphore-protocol/proof pnpm add @semaphore-protocol/proof información Semaphore also provides `@semaphore-protocol/core`, which includes the functions of the following core packages: `@semaphore-protocol/identity`, `@semaphore-protocol/group`, `@semaphore-protocol/proof`. Generate a proof[​](https://docs.semaphore.pse.dev/es/guides/proofs#generate-a-proof "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------------- ### 1\. Create the identity[​](https://docs.semaphore.pse.dev/es/guides/proofs#1-create-the-identity "Enlace directo al encabezado") In order for a user to generate a proof, it is necessary to create a Semaphore identity. If you do not know how to create an identity, see the previous [guide](https://docs.semaphore.pse.dev/es/guides/identities) on identities. ### 2\. Create the group[​](https://docs.semaphore.pse.dev/es/guides/proofs#2-create-the-group "Enlace directo al encabezado") Before generating a proof you also need to create a Semaphore group containing the commitment of the Semaphore identity of the user who will generate the proof. If you do not know how to create a group, see the previous [guide](https://docs.semaphore.pse.dev/es/guides/groups) on groups. If your group is on-chain, you can use the [`@semaphore-protocol/data`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/data) library to fetch the group members and re-create the off-chain group. For example: import { SemaphoreSubgraph } from "@semaphore-protocol/data"import { Group } from "@semaphore-protocol/group"const semaphoreSubgraph = new SemaphoreSubgraph("sepolia")const { members } = await semaphoreSubgraph.getGroup("42", { members: true })const group = new Group(members) ### 3\. Choose the scope[​](https://docs.semaphore.pse.dev/es/guides/proofs#3-choose-the-scope "Enlace directo al encabezado") Each proof requires a [scope](https://docs.semaphore.pse.dev/es/glossary#scope) , on which each user may only generate one valid proof. The scope, together with the user's private key, is used to generate the nullifier, which is the value you can actually use to check whether a proof with that scope has already been generated by that user. In a voting application where double-voting must be prevented, the scope could be the ballot id, or the Merkle root of the group. ### 4\. Generate the anonymous message[​](https://docs.semaphore.pse.dev/es/guides/proofs#4-generate-the-anonymous-message "Enlace directo al encabezado") Finally, you can generate the proof with the anonymous message using the `generateProof` function. For example: import { generateProof } from "@semaphore-protocol/proof"const scope = group.rootconst message = 1const proof = await generateProof(identity, group, message, scope) Verify a proof[​](https://docs.semaphore.pse.dev/es/guides/proofs#verify-a-proof "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------- To verify a proof, pass the proof you generated to the `verifyProof` function. For example: import { verifyProof } from "@semaphore-protocol/proof"await verifyProof(proof) // true or false. If you want to validate a proof on-chain, you can use [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts) and the [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) contract, as explained in the previous [guide](https://docs.semaphore.pse.dev/es/guides/groups#install-package-1) , and use the `validateProof` function. For example: function validateProof(ISemaphore.SemaphoreProof calldata proof) external { semaphore.validateProof(groupId, proof);} * [Install package](https://docs.semaphore.pse.dev/es/guides/proofs#install-package) * [Generate a proof](https://docs.semaphore.pse.dev/es/guides/proofs#generate-a-proof) * [1\. Create the identity](https://docs.semaphore.pse.dev/es/guides/proofs#1-create-the-identity) * [2\. Create the group](https://docs.semaphore.pse.dev/es/guides/proofs#2-create-the-group) * [3\. Choose the scope](https://docs.semaphore.pse.dev/es/guides/proofs#3-choose-the-scope) * [4\. Generate the anonymous message](https://docs.semaphore.pse.dev/es/guides/proofs#4-generate-the-anonymous-message) * [Verify a proof](https://docs.semaphore.pse.dev/es/guides/proofs#verify-a-proof) --- # Circuits | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/technical-reference/circuits#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página 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](https://docs.semaphore.pse.dev/es/technical-reference/circuits#proof-of-membership) * [Nullifier](https://docs.semaphore.pse.dev/es/technical-reference/circuits#nullifier) * [Message](https://docs.semaphore.pse.dev/es/technical-reference/circuits#message) ![Semaphore circuit](https://github.com/semaphore-protocol/semaphore/raw/main/packages/circuits/scheme.png) The diagram above shows how the input signals are used in the Semaphore circuit and how the outputs are calculated. Proof of membership[​](https://docs.semaphore.pse.dev/es/technical-reference/circuits#proof-of-membership "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------ The circuit derive the public key from the secret and hashes the public key to generate an identity commitment. Then, it verifies the proof of membership against the Merkle root and the identity commitment. **Private inputs:** * `merkleProofLength`: the actual number of nodes in the Merkle proof path, * `merkleProofIndices[MAX_DEPTH]`: the list of 0s and 1s to calculate the hashes of the nodes at the correct position, * `merkleProofSiblings[MAX_DEPTH]`: the list of siblings nodes to be used to calculate the hashes of the nodes up to the root, * `secret`: the EdDSA [secret scalar](https://www.rfc-editor.org/rfc/rfc8032#section-5.1.5) derived from the private key. **Public outputs:** * `merkleRoot`: The Merkle root of the tree. Nullifier[​](https://docs.semaphore.pse.dev/es/technical-reference/circuits#nullifier "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------- The circuit hashes the secret with the scope and then checks that the result matches the provided nullifier. **Private inputs:** * `secret`: the EdDSA [secret scalar](https://www.rfc-editor.org/rfc/rfc8032#section-5.1.5) derived from the private key. **Public inputs:** * `scope`: the value used like a topic on which users can generate a valid proof only once. **Public outputs:** * `nullifier`: the value designed to be a unique identifier and used to prevent the same proof from being used twice. Message[​](https://docs.semaphore.pse.dev/es/technical-reference/circuits#message "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------ The circuit calculates a dummy square of the message to prevent any tampering with the proof. **Public inputs:** * `message`: the anonymous value the user broadcasts. * [Proof of membership](https://docs.semaphore.pse.dev/es/technical-reference/circuits#proof-of-membership) * [Nullifier](https://docs.semaphore.pse.dev/es/technical-reference/circuits#nullifier) * [Message](https://docs.semaphore.pse.dev/es/technical-reference/circuits#message) --- # Subgraph | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/subgraph#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página [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. 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 The Graph protocol uses the [GraphQL](https://graphql.org/) query language. For examples, see the [GraphQL API documentation](https://thegraph.com/docs/developer/graphql-api) . Visit the [Semaphore subgraph](https://github.com/semaphore-protocol/semaphore/tree/main/apps/subgraph) to see the list of networks supported by Semaphore and its URLs. Schema[​](https://docs.semaphore.pse.dev/es/subgraph#schema "Enlace directo al encabezado") -------------------------------------------------------------------------------------------- apps/subgraph/schema.graphql * [Schema](https://docs.semaphore.pse.dev/es/subgraph#schema) --- # Unknown \# Semaphore V4 - llms.txt > Zero-knowledge protocol for anonymous group membership and signaling ## Quick Reference ### Core Concept Semaphore allows users to cast messages (votes, endorsements) as provable group members without revealing identity, with built-in double-signaling prevention. \*\*Key Components:\*\* - \*\*Identity\*\*: User's cryptographic identity (private key, public key, commitment) - \*\*Group\*\*: Merkle tree of identity commitments - \*\*Proof\*\*: Zero-knowledge proof of group membership + message - \*\*Nullifier\*\*: Unique identifier preventing double-signaling - \*\*Scope\*\*: Topic/context that limits one proof per user ### Essential Packages \`\`\`bash # Core functionality npm install @semaphore-protocol/core # Individual packages npm install @semaphore-protocol/identity npm install @semaphore-protocol/group npm install @semaphore-protocol/proof npm install @semaphore-protocol/contracts \`\`\` ## Common Patterns ### 1. Identity Management \`\`\`javascript import { Identity } from "@semaphore-protocol/identity" // Random identity const identity = new Identity() const { privateKey, publicKey, commitment } = identity // Deterministic identity (from secret) const deterministicIdentity = new Identity("secret-value") // Sign/verify messages const message = "Hello World" const signature = identity.signMessage(message) const isValid = Identity.verifySignature(message, signature, identity.publicKey) // Export/import const exported = identity.export() // base64 private key const imported = Identity.import(exported) \`\`\` ### 2. Group Operations \`\`\`javascript import { Group } from "@semaphore-protocol/group" // Create group const group = new Group() const groupWithMembers = new Group(\[commitment1, commitment2\]) // Manage members group.addMember(identity.commitment) group.addMembers(\[commitment1, commitment2\]) group.removeMember(0) // sets to 0, doesn't change size group.updateMember(0, newCommitment) // Generate Merkle proof const merkleProof = group.generateMerkleProof(0) \`\`\` ### 3. Proof Generation & Verification \`\`\`javascript import { generateProof, verifyProof } from "@semaphore-protocol/proof" // Generate proof const scope = group.root // or any unique scope const message = 1 const proof = await generateProof(identity, group, message, scope) // Verify proof const isValid = await verifyProof(proof) \`\`\` ### 4. On-Chain Integration \`\`\`solidity // Contract setup import "@semaphore-protocol/contracts/interfaces/ISemaphore.sol"; contract YourContract { ISemaphore public semaphore; uint256 public groupId; constructor(ISemaphore \_semaphore) { semaphore = \_semaphore; groupId = semaphore.createGroup(); } // Validate proof on-chain function validateProof(ISemaphore.SemaphoreProof calldata proof) external { semaphore.validateProof(groupId, proof); } } \`\`\` ## Configuration Reference ### Circuit Parameters - \*\*MAX\_DEPTH\*\*: 1-32 (Merkle tree depth) - \*\*Default proof validity\*\*: 1 hour for old Merkle roots ### Key Security Settings - \*\*Identity reuse warning\*\*: Same identity across groups compromises all groups - \*\*Nullifier uniqueness\*\*: Prevents double-signaling within same scope - \*\*Message tampering\*\*: Circuit calculates dummy square to prevent tampering ## Troubleshooting ### Common Issues \*\*"Proof verification failed"\*\* - Check group contains identity commitment - Verify scope matches between generation and verification - Ensure Merkle proof is current (within validity window) \*\*"Nullifier already exists"\*\* - User already submitted proof with this scope - Use different scope or implement nullifier tracking \*\*"Identity commitment not found"\*\* - Add identity to group before generating proof - Verify correct group is being used ## Architecture Overview ### Circuit Structure The Semaphore circuit proves three things: 1. \*\*Membership\*\*: User belongs to group (Merkle proof verification) 2. \*\*Authorization\*\*: Same user created message and proof (nullifier check) 3. \*\*Message integrity\*\*: Message hasn't been tampered with ### Contract Architecture - \*\*SemaphoreVerifier.sol\*\*: Groth16 proof verification - \*\*SemaphoreGroups.sol\*\*: Group management (abstract) - \*\*Semaphore.sol\*\*: Complete implementation with proof validation ## Extended Resources ### 📚 Complete Guides - \[Getting Started Tutorial\](https://docs.semaphore.pse.dev/getting-started) - Full project setup with CLI - \[Identities Deep Dive\](https://docs.semaphore.pse.dev/guides/identities) - Advanced identity management - \[Groups Management\](https://docs.semaphore.pse.dev/guides/groups) - Comprehensive group operations - \[Proof Generation\](https://docs.semaphore.pse.dev/guides/proofs) - Detailed proof workflows ### 🔧 Technical References - \[Semaphore V4 Specification\](https://github.com/zkspecs/zkspecs/blob/main/specs/3/README.md) - Protocol specification - \[Circuit Documentation\](https://docs.semaphore.pse.dev/technical-reference/circuits) - Circuit internals - \[Contract Reference\](https://docs.semaphore.pse.dev/technical-reference/contracts) - Solidity implementation details - \[Deployed Contracts\](https://docs.semaphore.pse.dev/deployed-contracts) - Network addresses ### 🛠️ Development Tools - \[GitHub Repository\](https://github.com/semaphore-protocol/semaphore) - Source code and examples - \[CLI Templates\](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli) - Project boilerplates - \[Boilerplate App\](https://github.com/semaphore-protocol/boilerplate) - Complete example application ### 🔐 Security & Audits - \[Trusted Setup Ceremony\](https://ceremony.pse.dev/projects/Semaphore%20V4%20Ceremony) - 400+ participants, July 2024 - \[Security Audits\](https://docs.semaphore.pse.dev/#audits) - PSE and Veridise audit reports - \[Best Practices Guide\](https://docs.semaphore.pse.dev/) - Security considerations section ### 🌐 Community & Support - \[Documentation\](https://docs.semaphore.pse.dev/) - Complete documentation - \[GitHub Discussions\](https://github.com/semaphore-protocol/semaphore/discussions) - Community support - \[PSE Website\](https://pse.dev/) - Privacy & Scaling Explorations team ### 📊 Data & Indexing - \[@semaphore-protocol/data\](https://github.com/semaphore-protocol/semaphore/tree/main/packages/data) - On-chain data fetching - \[Subgraph Templates\](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-monorepo-subgraph) - Graph Protocol integration ## Quick Start Commands \`\`\`bash # Create new project npx @semaphore-protocol/cli create my-app --template monorepo-ethers # Get on-chain groups semaphore get-groups --network sepolia # Deploy contract yarn deploy --semaphore \--group \--network sepolia \`\`\` ## Use Cases - \*\*Private Voting\*\*: Anonymous ballots with double-vote prevention - \*\*Whistleblowing\*\*: Anonymous reporting with verified membership - \*\*Anonymous DAOs\*\*: Governance without identity disclosure - \*\*Mixers\*\*: Privacy-preserving value transfers - \*\*Anonymous Authentication\*\*: Prove membership without revealing identity --- # What Is Semaphore? | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V2 En esta página Overview[​](https://docs.semaphore.pse.dev/es/V2#overview "Enlace directo al encabezado") ------------------------------------------------------------------------------------------ [Semaphore](https://github.com/semaphore-protocol/semaphore) is a [zero-knowledge](https://z.cash/technology/zksnarks) protocol that allows you to cast a signal (for example, a vote or endorsement) as a provable group member without revealing your identity. Additionally, it provides a simple mechanism to prevent double-signaling. Use cases include private voting, whistleblowing, anonymous DAOs and mixers. Features[​](https://docs.semaphore.pse.dev/es/V2#features "Enlace directo al encabezado") ------------------------------------------------------------------------------------------ With Semaphore, you can allow your users to do the following: 1. [Create a Semaphore identity](https://docs.semaphore.pse.dev/es/V2/guides/identities) . 2. [Add their Semaphore identity to a group (i.e. _Merkle tree_)](https://docs.semaphore.pse.dev/es/V2/guides/groups) . 3. [Send a verifiable, anonymous signal (e.g a vote or endorsement)](https://docs.semaphore.pse.dev/es/V2/guides/proofs) . When a user broadcasts a signal (for example: a vote), Semaphore zero-knowledge proofs can ensure that the user has joined the group and hasn't already cast a signal with their nullifier. Semaphore uses on-chain Solidity contracts and off-chain JavaScript libraries that work in tandem. * Off chain, JavaScript libraries can be used to create identities, manage groups and generate proofs. * On chain, Solidity contracts can be used to manage groups and verify proofs. Developer benefits[​](https://docs.semaphore.pse.dev/es/V2#developer-benefits "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------- Semaphore is designed to be a simple and generic _privacy layer_ for decentralized applications (dApps) on Ethereum. It encourages modular application design, allowing dApp developers to choose and customize the on-chain and off-chain components they need. About the code[​](https://docs.semaphore.pse.dev/es/V2#about-the-code "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------ The core of the protocol is the [circuit logic](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/circuits/scheme.png) . In addition to circuits, Semaphore provides [Solidity contracts](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts) and [JavaScript libraries](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1#-packages) that allow developers to generate zero-knowledge proofs and verify them with minimal effort. ### Audits[​](https://docs.semaphore.pse.dev/es/V2#audits "Enlace directo al encabezado") | Version | Report | Scope | | --- | --- | --- | | v2.0.0 | [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 | [Semaphore\_2.5.0\_Audit.pdf](https://github.com/semaphore-protocol/semaphore/files/9845008/Semaphore_2.5.0_Audit.pdf) | `contracts`, `libraries` | información If you are using the previous version of Semaphore, see the [Semaphore V1](https://docs.semaphore.pse.dev/es/V1) documentation. * [Overview](https://docs.semaphore.pse.dev/es/V2#overview) * [Features](https://docs.semaphore.pse.dev/es/V2#features) * [Developer benefits](https://docs.semaphore.pse.dev/es/V2#developer-benefits) * [About the code](https://docs.semaphore.pse.dev/es/V2#about-the-code) * [Audits](https://docs.semaphore.pse.dev/es/V2#audits) --- # Contracts | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/technical-reference/contracts#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página Semaphore contracts are designed with minimal yet essential code, enabling developers to efficiently manage on-chain groups and verify or validate zero-knowledge proofs. There are three contracts: * [`SemaphoreVerifier.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/base/SemaphoreVerifier.sol) * [`SemaphoreGroups.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/base/SemaphoreGroups.sol) * [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) información To use Semaphore contracts and interfaces in your project, install the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/contracts) NPM package. SemaphoreVerifier.sol[​](https://docs.semaphore.pse.dev/es/technical-reference/contracts#semaphoreverifiersol "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------------------------------- `SemaphoreVerifier.sol` is an extended version of the Groth16 verifier generated by default with [SnarkJS](https://github.com/iden3/snarkjs) . It contains a function for verifying proofs and a list of verification keys parameters. Since the Semaphore circuit is compiled with a `MAX_DEPTH` range from 1 to 32 during the [trusted setup](https://docs.semaphore.pse.dev/es/glossary#trusted-setup) , the verifier must contain the parameters of the verification keys of each instance. SemaphoreGroups.sol[​](https://docs.semaphore.pse.dev/es/technical-reference/contracts#semaphoregroupssol "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------ `SemaphoreGroups.sol` is an abstract contract which contains the functions required to create on-chain groups, and add/remove/update members. Each group is assigned an admin, which can be an Ethereum account or another contract. This contract uses the [`LeanIMT.sol`](https://github.com/privacy-scaling-explorations/zk-kit/blob/main/packages/imt.sol/contracts/internal/InternalLeanIMT.sol) ZK-Kit library, an optimized binary incremental Merkle tree with [Poseidon](https://www.poseidon-hash.info/) . Semaphore.sol[​](https://docs.semaphore.pse.dev/es/technical-reference/contracts#semaphoresol "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------ `Semaphore.sol` inherits `SemaphoreGroups.sol` and adds functions to verify (`verifyProof`) or validate (`validateProof`) a Semaphore proof. The only constructor parameter is the `SemaphoreVerifier.sol` address, which must be deployed separately. The `verifyProof` function contains code for checking whether a Semaphore proof is true or false. It is a read-only view function that in addition to verifying the proof also includes a mechanism for keeping track of proofs generated with old Merkle roots, i.e. group instances that contained fewer or different members. The `validateProof` function first checks whether a proof with the same nullifier has already been validated, and then verifies the proof with the `verifyProof` function and saves the nullifier. This function also creates a log with the group id and the proof, which can then additionally be verified off-chain. información Semaphore contracts are deployed on the main testnets and Arbitrum One. See the [deployed contracts](https://docs.semaphore.pse.dev/es/deployed-contracts) to check the addresses. * [SemaphoreVerifier.sol](https://docs.semaphore.pse.dev/es/technical-reference/contracts#semaphoreverifiersol) * [SemaphoreGroups.sol](https://docs.semaphore.pse.dev/es/technical-reference/contracts#semaphoregroupssol) * [Semaphore.sol](https://docs.semaphore.pse.dev/es/technical-reference/contracts#semaphoresol) --- # Identities | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/guides/identities#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página In order to join a [Semaphore group](https://docs.semaphore.pse.dev/es/glossary#group) , a user must first create a [Semaphore identity](https://docs.semaphore.pse.dev/es/glossary#identity) . A Semaphore identity contains three values generated with the identity: * 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. Install package[​](https://docs.semaphore.pse.dev/es/guides/identities#install-package "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------------- In your code, use the [`@semaphore-protocol/identity`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/identity) package to manage Semaphore identities. * npm * Yarn * pnpm npm install @semaphore-protocol/identity yarn add @semaphore-protocol/identity pnpm add @semaphore-protocol/identity información Semaphore also provides `@semaphore-protocol/core`, which includes the functions of the following core packages: `@semaphore-protocol/identity`, `@semaphore-protocol/group`, `@semaphore-protocol/proof`. Create identities[​](https://docs.semaphore.pse.dev/es/guides/identities#create-identities "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------------------- ### Create random identities[​](https://docs.semaphore.pse.dev/es/guides/identities#create-random-identities "Enlace directo al encabezado") To create a random identity, instantiate `Identity` without any parameters. For example: import { Identity } from "@semaphore-protocol/identity"const { privateKey, publicKey, commitment } = new Identity() The new identity contains your private key, your public key, and its associated commitment, which serves as a public representation of the identity (similar to an Ethereum address). ### Create deterministic identities[​](https://docs.semaphore.pse.dev/es/guides/identities#create-deterministic-identities "Enlace directo al encabezado") If you pass a previously used private key or any secret value that acts as your private key as parameter, you can deterministically generate a Semaphore identity. const identity1 = new Identity(privateKey)// orconst identity2 = new Identity("secret-value") tip Building a system to save or recover secret values of Semaphore identities is nontrivial. You may choose to delegate such functionality to existing wallets such as Metamask. For example: 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. Privacy risk If a user signs the **same message** on multiple websites using MetaMask, all those websites will be able to **generate the same Semaphore identity**. This undermines anonymity and may allow third parties to **link identities across platforms** or even **gain control over a user's identity**. To mitigate this, encourage users to sign **unique messages per application** or implement safeguards that detect and warn about reuse. Sign and verify messages[​](https://docs.semaphore.pse.dev/es/guides/identities#sign-and-verify-messages "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------------------------------- Semaphore V4 uses asymmetric cryptography and in particular EdDSA to generate the identity keys. It is therefore also possible to sign messages and verify their signatures. ### Sign a message[​](https://docs.semaphore.pse.dev/es/guides/identities#sign-a-message "Enlace directo al encabezado") Any Semaphore identity can sign a message by simply passing a string, number or buffer. const message = "Hello World"const signature = identity1.signMessage(message) ### Verify a signature[​](https://docs.semaphore.pse.dev/es/guides/identities#verify-a-signature "Enlace directo al encabezado") After a message is signed, anyone can verify the signature using the message itself, the signature, and the signer's public key. // Static method.Identity.verifySignature(message, signature, identity1.publicKey) Export and import an identity[​](https://docs.semaphore.pse.dev/es/guides/identities#export-and-import-an-identity "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------------------------------------------- A Semaphore Identity can be exported and then imported later for reuse. ### Export an identity[​](https://docs.semaphore.pse.dev/es/guides/identities#export-an-identity "Enlace directo al encabezado") Returns the private key encoded as a base64 string. import { Identity } from "@semaphore-protocol/identity"const identity = new Identity()const privateKey = identity.export() ### Import an identity[​](https://docs.semaphore.pse.dev/es/guides/identities#import-an-identity "Enlace directo al encabezado") Returns a Semaphore identity based on a private key encoded as a base64 string. import { Identity } from "@semaphore-protocol/identity"const identity = new Identity()const privateKey = identity.export()const identity2 = Identity.import(privateKey) * [Install package](https://docs.semaphore.pse.dev/es/guides/identities#install-package) * [Create identities](https://docs.semaphore.pse.dev/es/guides/identities#create-identities) * [Create random identities](https://docs.semaphore.pse.dev/es/guides/identities#create-random-identities) * [Create deterministic identities](https://docs.semaphore.pse.dev/es/guides/identities#create-deterministic-identities) * [Sign and verify messages](https://docs.semaphore.pse.dev/es/guides/identities#sign-and-verify-messages) * [Sign a message](https://docs.semaphore.pse.dev/es/guides/identities#sign-a-message) * [Verify a signature](https://docs.semaphore.pse.dev/es/guides/identities#verify-a-signature) * [Export and import an identity](https://docs.semaphore.pse.dev/es/guides/identities#export-and-import-an-identity) * [Export an identity](https://docs.semaphore.pse.dev/es/guides/identities#export-an-identity) * [Import an identity](https://docs.semaphore.pse.dev/es/guides/identities#import-an-identity) --- # ¿Qué es Semaphore? | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V3 En esta página General[​](https://docs.semaphore.pse.dev/es/V3#general "Enlace directo al encabezado") ---------------------------------------------------------------------------------------- [Semaphore](https://github.com/semaphore-protocol/semaphore) es un protocolo que utiliza [conocimiento cero (zero-knowledge)](https://z.cash/technology/zksnarks) y permite emitir una señal (por ejemplo: un voto o una aprobación) como una persona probablemente miembro de un grupo sin revelar su identidad. Además, proporciona un mecanismo sencillo para impedir que un mismo usuario emita dos señales. Algunos de los potenciales casos de uso son: votaciones, denuncias, DAOs anónimas y mezcladores. Características[​](https://docs.semaphore.pse.dev/es/V3#caracter%C3%ADsticas "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------- Con Semaphore puede permitir que sus usuarios realicen las siguientes acciones: 1. [Crear una identidad Semaphore](https://docs.semaphore.pse.dev/es/V3/guides/identities) . 2. [Agregar su identidad Semaphore a un grupo (es decir: _Árbol de Merkle_)](https://docs.semaphore.pse.dev/es/V3/guides/groups) . 3. [Enviar una señal anónima, verificable (ej. un voto o una aprobación)](https://docs.semaphore.pse.dev/es/V3/guides/proofs) . Cuando un usuario emite una señal (por ejemplo: un voto), las pruebas de conocimiento cero (ZKP) pueden asegurar que el usuario se ha incorporado al grupo y aún no ha emitido una señal con su nullifier (anulador). Semaphore utiliza contratos internos a la cadena en Solidity y librerías de JavaScript externas a la cadena que funcionan de forma conjunta. * Externos a la cadena (off-chain), se pueden utilizar librerías de Javascript para crear identidades, organizar grupos y generar pruebas. * Internos a la cadena (on-chain), se pueden utilizar contratos en Solidity para organizar grupos y verificar pruebas. Beneficios para desarrolladores[​](https://docs.semaphore.pse.dev/es/V3#beneficios-para-desarrolladores "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------------------------- Semaphore está diseñado para ser un _componente de privacidad_ simple y genérico para aplicaciones descentralizadas (dApps) en Ethereum. Promueve el diseño modular de las aplicaciones, lo que permite que los desarrolladores de las dApps escojan y personalicen los componentes que necesitan externos e internos a la cadena. Respecto al código[​](https://docs.semaphore.pse.dev/es/V3#respecto-al-c%C3%B3digo "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------- La base del protocolo es la [lógica de circuitos](https://github.com/semaphore-protocol/semaphore/tree/main/packages/circuits/scheme.png) (circuit logic). Además de los circuitos, Semaphore ofrece [contratos en Solidity](https://github.com/semaphore-protocol/semaphore/tree/main/packages/contracts) y [librerías en JavaScript](https://github.com/semaphore-protocol/semaphore#-packages) que permiten que los desarrolladores generen pruebas de conocimiento cero (ZKP) y las verifiquen con un esfuerzo mínimo. ### Ceremonia de configuración de confianza (Trusted Setup Ceremony)[​](https://docs.semaphore.pse.dev/es/V3#ceremonia-de-configuraci%C3%B3n-de-confianza-trusted-setup-ceremony "Enlace directo al encabezado") Los [parámetros seguros](https://docs.semaphore.pse.dev/es/V3/glossary#archivos-confiables-de-configuraci%C3%B3n-trusted-setup-files) para generar pruebas válidas con los circuitos Semaphore fueron generados en una [ceremonia de configuración de confianza](https://storage.googleapis.com/trustedsetup-a86f4.appspot.com/semaphore/semaphore_top_index.html) que se completó con más de 300 participantes el [29 de Marzo de 2022](https://etherscan.io/tx/0xec6dbe68883c7593c2bea82f55af18b3aeb5cc146e026d0083a9b3faa9aa0b65#eventlog) . ### Auditorías[​](https://docs.semaphore.pse.dev/es/V3#auditor%C3%ADas "Enlace directo al encabezado") | Versión | Auditores | Reporte | Alcance | | --- | --- | --- | --- | | 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/9845008/Semaphore_2.5.0_Audit.pdf) | `circuits`, `contracts` | información Si está utilizando una de las versiones anteriores de Semaphore, vea la documentación de [Semaphore V1](https://docs.semaphore.pse.dev/es/V1) o de [Semaphore V2](https://docs.semaphore.pse.dev/es/V2) . * [General](https://docs.semaphore.pse.dev/es/V3#general) * [Características](https://docs.semaphore.pse.dev/es/V3#caracter%C3%ADsticas) * [Beneficios para desarrolladores](https://docs.semaphore.pse.dev/es/V3#beneficios-para-desarrolladores) * [Respecto al código](https://docs.semaphore.pse.dev/es/V3#respecto-al-c%C3%B3digo) * [Ceremonia de configuración de confianza (Trusted Setup Ceremony)](https://docs.semaphore.pse.dev/es/V3#ceremonia-de-configuraci%C3%B3n-de-confianza-trusted-setup-ceremony) * [Auditorías](https://docs.semaphore.pse.dev/es/V3#auditor%C3%ADas) --- # Resources | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2/resources#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/resources) ** (V4). Versión: V2 [Semaphore V2 is Live!](https://medium.com/privacy-scaling-explorations/semaphore-v2-is-live-f263e9372579) - Privacy and Scaling Explorations [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 --- # Glossary | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2/glossary#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/glossary) ** (V4). Versión: V2 En esta página Semaphore identity[​](https://docs.semaphore.pse.dev/es/V2/glossary#semaphore-identity "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------------- The identity of a user in the Semaphore protocol. An identity contains the following three values: * [Identity commitment](https://docs.semaphore.pse.dev/es/V2/glossary#identity-commitment) : the public value. * Identity trapdoor and identity nullifier: secret values known only by the user. Semaphore group[​](https://docs.semaphore.pse.dev/es/V2/glossary#semaphore-group "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------- A group is a binary incremental [Merkle tree](https://docs.semaphore.pse.dev/es/V2/glossary#merkle-tree) in which each leaf contains an [identity commitment](https://docs.semaphore.pse.dev/es/V2/glossary#identity-commitment) for a user. The identity commitment proves that the user is a group member without revealing the Semaphore identity of the user. Semaphore uses the **Poseidon** hash function to create Merkle trees. For more information, see the [Poseidon website](https://www.poseidon-hash.info/) . Identity commitment[​](https://docs.semaphore.pse.dev/es/V2/glossary#identity-commitment "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------- The public [Semaphore identity](https://docs.semaphore.pse.dev/es/V2/glossary#semaphore-identity) value used in [Semaphore groups](https://docs.semaphore.pse.dev/es/V2/glossary#semaphore-group) . Semaphore uses the **Poseidon** hash function to create the identity commitment from the Semaphore identity secret values. For more information, see the [Poseidon website](https://www.poseidon-hash.info/) . Merkle tree[​](https://docs.semaphore.pse.dev/es/V2/glossary#merkle-tree "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------- A tree in which every leaf (i.e., a node that doesn't have children) is labelled with the cryptographic hash of a data block, and every node that isn't a leaf is labelled with the cryptographic hash of its child node labels. In zero-knowledge protocols, Merkle trees can be used to efficiently summarize and validate large data sets. To validate that a tree contains a specific leaf, a verifier only needs a portion of the complete data structure. For more information, see [Merkle tree in Wikipedia](https://en.wikipedia.org/wiki/Merkle_tree) . Nullifier[​](https://docs.semaphore.pse.dev/es/V2/glossary#nullifier "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------- A value used to prevent double entry or double signalling. See [Circuit nullifier hash](https://docs.semaphore.pse.dev/es/V2/technical-reference/circuits#nullifier-hash) . Relay[​](https://docs.semaphore.pse.dev/es/V2/glossary#relay "Enlace directo al encabezado") --------------------------------------------------------------------------------------------- A third-party who receives a fee for including relayed transactions in the blockchain (McMenamin, Daza, and Fitz. [https://eprint.iacr.org/2022/155.pdf](https://eprint.iacr.org/2022/155.pdf) , p.3). To preserve the anonymity of the user broadcasting a signal with Semaphore, an application may use a relayer to post the signal transaction to Ethereum on behalf of the user. Applications may provide rewards for relayers and implement front-running prevention mechanisms, such as requiring the signals to include the relayer’s address, binding the signal to that specific address ([https://semaphore.pse.dev/whitepaper-v1.pdf](https://semaphore.pse.dev/whitepaper-v1.pdf) , p.6). Trusted setup files[​](https://docs.semaphore.pse.dev/es/V2/glossary#trusted-setup-files "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------- The secure, verifiable parameters generated by Semaphore's trusted setup ceremony. Semaphore uses the trusted setup files to generate and verify valid zero-knowledge proofs. To generate or verify valid zero-knowledge proofs with Semaphore, applications must include the following Semaphore _trusted setup_ files: * semaphore.zkey * semaphore.wasm * semaphore.json For a complete list of ready-to-use files, see [trusted-setup-pse.org](https://www.trusted-setup-pse.org/) . To learn more, see the [trusted setup ceremony](https://storage.googleapis.com/trustedsetup-a86f4.appspot.com/semaphore/semaphore_top_index.html) . * [Semaphore identity](https://docs.semaphore.pse.dev/es/V2/glossary#semaphore-identity) * [Semaphore group](https://docs.semaphore.pse.dev/es/V2/glossary#semaphore-group) * [Identity commitment](https://docs.semaphore.pse.dev/es/V2/glossary#identity-commitment) * [Merkle tree](https://docs.semaphore.pse.dev/es/V2/glossary#merkle-tree) * [Nullifier](https://docs.semaphore.pse.dev/es/V2/glossary#nullifier) * [Relay](https://docs.semaphore.pse.dev/es/V2/glossary#relay) * [Trusted setup files](https://docs.semaphore.pse.dev/es/V2/glossary#trusted-setup-files) --- # Identities | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2/guides/identities#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/guides/identities) ** (V4). Versión: V2 En esta página In order to join a [Semaphore group](https://docs.semaphore.pse.dev/es/V2/glossary#semaphore-group) , a user must first create a [Semaphore identity](https://docs.semaphore.pse.dev/es/V2/glossary#semaphore-identity) . A Semaphore identity contains two values generated with the identity: * 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[​](https://docs.semaphore.pse.dev/es/V2/guides/identities#create-identities "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------ In your code, use the [`@semaphore-protocol/identity`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/identity) library to create a Semaphore identity _deterministically_ (from the hash of a message) or _randomly_. * [**Create random identities**](https://docs.semaphore.pse.dev/es/V2/guides/identities#create-random-identities) * [**Create deterministic identities**](https://docs.semaphore.pse.dev/es/V2/guides/identities#create-deterministic-identities) ### Create random identities[​](https://docs.semaphore.pse.dev/es/V2/guides/identities#create-random-identities "Enlace directo al encabezado") To create a random identity, instantiate `Identity` without any parameters--for example: import { Identity } from "@semaphore-protocol/identity"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_. 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 Ethereum private keys and are used to generate Semaphore zero-knowledge proofs and authenticate signals. ### Create deterministic identities[​](https://docs.semaphore.pse.dev/es/V2/guides/identities#create-deterministic-identities "Enlace directo al encabezado") If you pass a message as a parameter, Semaphore generates `trapdoor` and `nullifier` 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. Given that the hash is deterministic, anyone with the same message can recreate the same identity. const identity = new Identity("secret-message") tip Building a system to save or recover secret values of Semaphore identities is nontrivial. You may choose to delegate such functionality to existing wallets such as Metamask--for example: 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. 3. The user can now recreate their Semaphore identity whenever they want by signing the same message with their Ethereum account in Metamask. Save your identities[​](https://docs.semaphore.pse.dev/es/V2/guides/identities#save-your-identities "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------ You can output an identity as a JSON string that you can save and reuse later. The `Identity.toString()` method generates a JSON array from an identity--for example: console.log(identity.toString()) // View the identity trapdoor and nullifier.// '["8255d...", "62c41..."]' The array contains the trapdoor and nullifier. To reuse the saved identity, pass the JSON to the `Identity()` constructor. const identity2 = new Identity(identity.toString()) * [Create identities](https://docs.semaphore.pse.dev/es/V2/guides/identities#create-identities) * [Create random identities](https://docs.semaphore.pse.dev/es/V2/guides/identities#create-random-identities) * [Create deterministic identities](https://docs.semaphore.pse.dev/es/V2/guides/identities#create-deterministic-identities) * [Save your identities](https://docs.semaphore.pse.dev/es/V2/guides/identities#save-your-identities) --- # Troubleshooting | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/troubleshooting#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página If these suggestions do not work, feel free to ask for more help and support on [Github Discussions](https://github.com/semaphore-protocol/semaphore/discussions) or [Telegram](https://semaphore.pse.dev/telegram) . Transaction reverted when using the same nullifier[​](https://docs.semaphore.pse.dev/es/troubleshooting#transaction-reverted-when-using-the-same-nullifier "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- When you generate a proof using the same [scope](https://docs.semaphore.pse.dev/es/glossary#scope) you used to validate a proof before, the transaction will be reverted because that scope (and thus the [nullifier](https://docs.semaphore.pse.dev/es/glossary#nullifier) ) has already been used. If you want to send and validate several proofs from the same identity, you need to use a different scope for each time you generate a proof. * [Transaction reverted when using the same nullifier](https://docs.semaphore.pse.dev/es/troubleshooting#transaction-reverted-when-using-the-same-nullifier) --- # Proofs | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2/guides/proofs#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/guides/proofs) ** (V4). Versión: V2 En esta página Learn how to use Semaphore to generate and verify zero-knowledge proofs. Once a user joins their [Semaphore identity](https://docs.semaphore.pse.dev/es/V2/glossary#semaphore-identity) to a [Semaphore group](https://docs.semaphore.pse.dev/es/V2/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. Developers can use Semaphore for the following: * [**Generate a proof off-chain**](https://docs.semaphore.pse.dev/es/V2/guides/proofs#generate-a-proof-off-chain) * [**Verify a proof off-chain**](https://docs.semaphore.pse.dev/es/V2/guides/proofs#verify-a-proof-off-chain) * [**Verify a proof on-chain**](https://docs.semaphore.pse.dev/es/V2/guides/proofs#verify-a-proof-on-chain) Generate a proof off-chain[​](https://docs.semaphore.pse.dev/es/V2/guides/proofs#generate-a-proof-off-chain "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------------------- Use the [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/proof) library to generate an off-chain proof. To generate a proof, pass the following properties 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](https://docs.semaphore.pse.dev/es/V2/glossary#trusted-setup-files) . In the voting system use case, once all the voters have joined their [identities](https://docs.semaphore.pse.dev/es/V2/guides/identities#create-identities) to the ballot [group](https://docs.semaphore.pse.dev/es/V2/guides/groups) , a voter can generate a proof to vote for a proposal. In the call to `generateProof`, the voting system passes the unique ballot ID (the [Merkle tree](https://docs.semaphore.pse.dev/es/V2/glossary#merkle-tree) root of the group) as the `externalNullifier` to prevent the voter signaling more than once for the ballot. The following code sample shows how to use `generateProof` to generate the voting proof: import { generateProof } from "@semaphore-protocol/proof"const externalNullifier = group.rootconst signal = "proposal_1"const fullProof = await generateProof(identity, group, externalNullifier, signal, { zkeyFilePath: "./semaphore.zkey", wasmFilePath: "./semaphore.wasm"}) Verify a proof off-chain[​](https://docs.semaphore.pse.dev/es/V2/guides/proofs#verify-a-proof-off-chain "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------------------------- Use the [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/proof) library to verify a Semaphore proof off-chain. To verify a proof, pass the following to the `verifyProof` function: * _`proof`_: the Semaphore proof. * _`verificationKey`_: the JavaScript object in the `semaphore.json` [trusted setup file](https://docs.semaphore.pse.dev/es/V2/glossary#trusted-setup-files) . The following code sample shows how to parse the verification key object from `semaphore.json` and verify the previously generated proof: import { verifyProof } from "@semaphore-protocol/proof"const verificationKey = JSON.parse(fs.readFileSync("./semaphore.json", "utf-8"))await verifyProof(verificationKey, fullProof) // true or false. `verifyProof` returns a Promise that resolves to `true` or `false`. Verify a proof on-chain[​](https://docs.semaphore.pse.dev/es/V2/guides/proofs#verify-a-proof-on-chain "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------------- Use the [`SemaphoreCore`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/contracts/base/SemaphoreCore.sol) contract to verify proofs on-chain. It uses a verifier deployed to Ethereum and provides methods hash the signal and verify a proof. información You can import `SemaphoreCore` and other Semaphore contracts from the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts) NPM module. To verify Semaphore proofs in your contract, import `SemaphoreCore` and pass the following to the `_verifyProof` internal method: * _`signal`_: The Semaphore signal to prove. * _`root`_: The root of the Merkle tree. * _`nullifierHash`_: a [nullifier hash](https://docs.semaphore.pse.dev/es/V2/guides/proofs#retrieve-a-nullifier-hash) . * _`externalNullifier`_: The external nullifier. * _`proof`_: A [_Solidity-compatible_ Semaphore proof](https://docs.semaphore.pse.dev/es/V2/guides/proofs#generate-a-solidity-compatible-proof) . * _`verifier`_: The verifier address. Remember to save the `nullifierHash` on-chain to avoid double-signaling. Alternatively, you can use an already deployed [`Semaphore`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/Semaphore.sol) contract and use its `verifiyProof` external function. ### Generate a Solidity-compatible proof[​](https://docs.semaphore.pse.dev/es/V2/guides/proofs#generate-a-solidity-compatible-proof "Enlace directo al encabezado") To transform a proof to be compatible with Solidity contracts, pass the proof to the `packToSolidityProof` utility function--for example: import { packToSolidityProof } from "@semaphore-protocol/proof"const solidityProof = packToSolidityProof(fullProof.proof) Semaphore returns a new Solidity-compatible instance of the proof. ### Retrieve a nullifier hash[​](https://docs.semaphore.pse.dev/es/V2/guides/proofs#retrieve-a-nullifier-hash "Enlace directo al encabezado") To get the Semaphore proof nullifier hash, access the proof's `publicSignals.nullifierHash` property--for example: const { nullifierHash } = fullProof.publicSignals * [Generate a proof off-chain](https://docs.semaphore.pse.dev/es/V2/guides/proofs#generate-a-proof-off-chain) * [Verify a proof off-chain](https://docs.semaphore.pse.dev/es/V2/guides/proofs#verify-a-proof-off-chain) * [Verify a proof on-chain](https://docs.semaphore.pse.dev/es/V2/guides/proofs#verify-a-proof-on-chain) * [Generate a Solidity-compatible proof](https://docs.semaphore.pse.dev/es/V2/guides/proofs#generate-a-solidity-compatible-proof) * [Retrieve a nullifier hash](https://docs.semaphore.pse.dev/es/V2/guides/proofs#retrieve-a-nullifier-hash) --- # Circuits | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2/technical-reference/circuits#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/technical-reference/circuits) ** (V4). Versión: V2 En esta página The [Semaphore circuit](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/circuits) is the heart of the protocol and consists of three parts: * [**Proof of membership**](https://docs.semaphore.pse.dev/es/V2/technical-reference/circuits#proof-of-membership) * [**Nullifier hash**](https://docs.semaphore.pse.dev/es/V2/technical-reference/circuits#nullifier-hash) * [**Signal**](https://docs.semaphore.pse.dev/es/V2/technical-reference/circuits#signal) ![Semaphore circuit](https://github.com/semaphore-protocol/semaphore/raw/v2.6.1/packages/circuits/scheme.png) The diagram above shows how the input signals are used in the Semaphore circuit and how the outputs are calculated. Proof of membership[​](https://docs.semaphore.pse.dev/es/V2/technical-reference/circuits#proof-of-membership "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------------------------------------- The circuit hashes the hash of the identity nullifier with the identity trapdoor to generate an identity commitment. Then, it verifies the proof of membership against the Merkle root and the identity commitment. **Private inputs:** * `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, * `identityNullifier`: the 32-byte identity secret used as nullifier, * `identityTrapdoor`: the 32-byte identity secret used as trapdoor. **Public outputs:** * `root`: The Merkle root of the tree. Nullifier hash[​](https://docs.semaphore.pse.dev/es/V2/technical-reference/circuits#nullifier-hash "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------------------------- The circuit hashes the identity nullifier with the external nullifier and then checks that the result matches the provided nullifier hash. Nullifier hashes saved in a Semaphore smart contract allow the contract to reject a proof that contains a used nullifier hash. **Private inputs:** * `identityNullifier`: the 32-byte identity secret used as a nullifier. **Public inputs:** * `externalNullifier`: the 32-byte external nullifier. **Public outputs:** * `nullifierHash`: the hash of the identity nullifier and the external nullifier; used to prevent double-signaling. **Procedure:** Signal[​](https://docs.semaphore.pse.dev/es/V2/technical-reference/circuits#signal "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------- The circuit calculates a dummy square of the signal hash to prevent any tampering with the proof. **Public inputs:** * `signalHash`: the hash of the user's signal. * [Proof of membership](https://docs.semaphore.pse.dev/es/V2/technical-reference/circuits#proof-of-membership) * [Nullifier hash](https://docs.semaphore.pse.dev/es/V2/technical-reference/circuits#nullifier-hash) * [Signal](https://docs.semaphore.pse.dev/es/V2/technical-reference/circuits#signal) --- # Subgraph | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2/subgraph#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/subgraph) ** (V4). Versión: V2 En esta página [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. Semaphore's subgraph allows you to retrieve data from the [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/Semaphore.sol) smart contract. tip The Graph protocol uses the [GraphQL](https://graphql.org/) query lanaguage. For examples, see the [GraphQL API documentation](https://thegraph.com/docs/developer/graphql-api) . Visit the [subgraph repository](https://github.com/semaphore-protocol/subgraph) to see the list of Semaphore subgraphs. Schema[​](https://docs.semaphore.pse.dev/es/V2/subgraph#schema "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------- ### MerkleTree[​](https://docs.semaphore.pse.dev/es/V2/subgraph#merkletree "Enlace directo al encabezado") * `id`: unique identifier among all MerkleTree entities, * `depth`: Merkle tree depth, * `root`: Merkle tree root, * `zeroValue`: Merkle tree zero value, * `numberOfLeaves`: total number of tree leaves, * `group`: link to the Group entity. ### Group[​](https://docs.semaphore.pse.dev/es/V2/subgraph#group "Enlace directo al encabezado") * `id`: unique identifier among all Group entities, * `merkleTree`: link to the MerkleTree entity, * `timestamp`: block timestamp, * `admin`: admin of the group, * `members`: list of group members. * `verifiedProofs`: list of group proofs. ### Member[​](https://docs.semaphore.pse.dev/es/V2/subgraph#member "Enlace directo al encabezado") * `id`: unique identifier among all Member entities, * `identityCommitment`: Semaphore identity commitment, * `timestamp`: block timestamp, * `index`: index of the tree leaf, * `group`: link to the Group entity. ### VerifiedProof[​](https://docs.semaphore.pse.dev/es/V2/subgraph#verifiedproof "Enlace directo al encabezado") * `id`: unique identifier among all VerifiedProof entities, * `signal`: user's signal, * `merkleTreeRoot`: Merkle tree root, * `nullifierHash`: nullifier hash, * `externalNullifier`: external nullifier, * `timestamp`: block timestamp, * `group`: link to the Group entity. * [Schema](https://docs.semaphore.pse.dev/es/V2/subgraph#schema) * [MerkleTree](https://docs.semaphore.pse.dev/es/V2/subgraph#merkletree) * [Group](https://docs.semaphore.pse.dev/es/V2/subgraph#group) * [Member](https://docs.semaphore.pse.dev/es/V2/subgraph#member) * [VerifiedProof](https://docs.semaphore.pse.dev/es/V2/subgraph#verifiedproof) --- # Deployed contracts | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2/deployed-contracts#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/deployed-contracts) ** (V4). Versión: V2 En esta página Verifiers[​](https://docs.semaphore.pse.dev/es/V2/deployed-contracts#verifiers "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------- | Contract | Goerli | Arbitrum One | | --- | --- | --- | | Verifier16.sol | [0xA525...6629](https://goerli.etherscan.io/address/0xA5253ba39381Aa99c4C2C5A4D5C2deC036d06629) | [0x6143...1609](https://arbiscan.io/address/0x6143ECd9Fd1A00EDe1046d456f8aab53a7D71609) | | Verifier17.sol | [0xe041...01Ab](https://goerli.etherscan.io/address/0xe0418A5f8fBF051D6cbc41Ff29855Dd2a02201Ab) | [0xAc12...Fb02](https://arbiscan.io/address/0xAc12fFFE354D6446eb50dd33E683B78FED73Fb02) | | Verifier18.sol | [0x7CdB...6797](https://goerli.etherscan.io/address/0x7CdB3336d7d7c55Bce0FB1508594C54521656797) | [0x610a...C701](https://arbiscan.io/address/0x610aeF0F2da3CD1C8bDefe4BDB434Ee146E0C701) | | Verifier19.sol | [0xbd87...190B](https://goerli.etherscan.io/address/0xbd870921d8A5398a3314C950d1fc63b8C3AB190B) | [0x5477...FCb4](https://arbiscan.io/address/0x5477725177035bbC9d70443eb921D29749D6FCb4) | | Verifier20.sol | [0x2a96...E099](https://goerli.etherscan.io/address/0x2a96c5696F85e3d2aa918496806B5c5a4D93E099) | [0x3fB2...3136](https://arbiscan.io/address/0x3fB2C0988a37b76e760c44e6516aF720935f3136) | | Verifier21.sol | [0x5Ec7...67Cd](https://goerli.etherscan.io/address/0x5Ec7d851a52A2a25CEc528F42a7ACA8EcF4667Cd) | [0xDc8f...7DF8](https://arbiscan.io/address/0xDc8f6B8A42836d4566256f4c6C53131DFD127DF8) | | Verifier22.sol | [0x919d...aA5b](https://goerli.etherscan.io/address/0x919d3d9c05FA7411e334deA5a763354fC7B6aA5b) | [0x6962...32f2](https://arbiscan.io/address/0x6962b5e706be5278eeCb01c286b50A48484632f2) | | Verifier23.sol | [0x6391...E552](https://goerli.etherscan.io/address/0x63917b00a6dA7865bEfdd107AfC83CC2e6BDE552) | [0x41e4...dF6B](https://arbiscan.io/address/0x41e4796Bd89B4BF04013b559c93fC32E9a2BdF6B) | | Verifier24.sol | [0xd05C...0E7D](https://goerli.etherscan.io/address/0xd05CAd7d940114c1419098EE3cEA0776ab510E7D) | [0xD528...5b60](https://arbiscan.io/address/0xD528B1D1408ab3583af4694F92b0aFEbE33d5b60) | | Verifier25.sol | [0x6D98...5ACb](https://goerli.etherscan.io/address/0x6D9862e6140D94E932d94c8BcE74a0BDD0ea5ACb) | [0x1683...33e7](https://arbiscan.io/address/0x1683a27EF9c10c5286dB56412E1272cD0Ca733e7) | | Verifier26.sol | [0x8c29...6c77](https://goerli.etherscan.io/address/0x8c29e0b77e32f704F03eeCE01c041192A5EB6c77) | [0x7819...4C00](https://arbiscan.io/address/0x78194bB665d1E33b97eE45B1A755c15717E94C00) | | Verifier27.sol | [0x066c...9c4C](https://goerli.etherscan.io/address/0x066cC22f8CA2A8D90D7Ff77D8a10A27e629c9c4C) | [0x997D...6E42](https://arbiscan.io/address/0x997Dac00E6701Ef7F3518280E5a9922801126E42) | | Verifier28.sol | [0x698F...6D15](https://goerli.etherscan.io/address/0x698F9507f504E2BD238be7da56E8D9fee60C6D15) | [0xDd3C...68c6](https://arbiscan.io/address/0xDd3C7f4cBA2467aE41c0F614A3c3E24bC80268c6) | | Verifier29.sol | [0xbBfC...6346](https://goerli.etherscan.io/address/0xbBfC2E201C3c3c6F50063c3Edb4746c6Fcb36346) | [0xe53e...60Cd](https://arbiscan.io/address/0xe53eF12093933D5df5691EAbA3821bD1c1EB60Cd) | | Verifier30.sol | [0x06bc...4bD1](https://goerli.etherscan.io/address/0x06bcD633988c1CE7Bd134DbE2C12119b6f3E4bD1) | [0x7FeA...340e](https://arbiscan.io/address/0x7FeA07c536ABBB0E7FB3c833376EE4EaDc21340e) | | Verifier31.sol | [0x133b...cCFE](https://goerli.etherscan.io/address/0x133b69Ce47BF20C49368354914DF47519Ca6cCFE) | [0xe453...2178](https://arbiscan.io/address/0xe4539a592df18936202480FBe77E47DE012F2178) | | Verifier32.sol | [0xe297...2e2D](https://goerli.etherscan.io/address/0xe2978F79cb4AF62e5C990EE5c7E12fb22ee22e2D) | [0x98c9...32F4](https://arbiscan.io/address/0x98c90845A7870e215cBd7265DDC653E6c07032F4) | Semaphore[​](https://docs.semaphore.pse.dev/es/V2/deployed-contracts#semaphore "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------- | Contract | Goerli | Arbitrum One | | --- | --- | --- | | Semaphore.sol | [0x5259...262f](https://goerli.etherscan.io/address/0x5259d32659F1806ccAfcE593ED5a89eBAb85262f) | [0x8633...A604](https://arbiscan.io/address/0x86337c87A56117f8264bbaBA70e5a522C6E8A604) | | IncrementalBinaryTree.sol | [0x61AE...B236](https://goerli.etherscan.io/address/0x61AE89E372492e53D941DECaaC9821649fa9B236) | [0x91cD...3948](https://arbiscan.io/address/0x91cD2B8573629d00BeC72EA1188d446897BD3948) | | PoseidonT3.sol | [0xe0A4...350F](https://goerli.etherscan.io/address/0xe0A452533853310C371b50Bd91BB9DCC8961350F) | [0xe0c8...61d0](https://arbiscan.io/address/0xe0c8d1e53D9Bfc9071F6564755FCFf6cC0dB61d0) | * [Verifiers](https://docs.semaphore.pse.dev/es/V2/deployed-contracts#verifiers) * [Semaphore](https://docs.semaphore.pse.dev/es/V2/deployed-contracts#semaphore) --- # Contracts | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2/technical-reference/contracts#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/technical-reference/contracts) ** (V4). Versión: V2 En esta página Semaphore includes three types of contracts: * [**Base contracts**](https://docs.semaphore.pse.dev/es/V2/technical-reference/contracts#base-contracts) * [**Extension contracts**](https://docs.semaphore.pse.dev/es/V2/technical-reference/contracts#extension-contracts) * [**Verifiers**](https://docs.semaphore.pse.dev/es/V2/technical-reference/contracts#verifiers) información To use Semaphore contracts and interfaces in your project, install the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts) NPM package. Base contracts[​](https://docs.semaphore.pse.dev/es/V2/technical-reference/contracts#base-contracts "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------ Semaphore provides the following base contracts: * [`SemaphoreCore.sol`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/base/SemaphoreCore.sol) : contains the functions to verify Semaphore proofs; * [`SemaphoreGroups.sol`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/base/SemaphoreGroups.sol) : contains the functions to create groups and add/remove members. These contracts are closely related to the protocol. You can inherit them in your contract or you can use [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/Semaphore.sol) , which inherits them for you. See our [deployed contracts](https://docs.semaphore.pse.dev/es/V2/deployed-contracts#semaphore) to find the addresses for your network. información While some dApps may use on-chain groups, others may prefer to use off-chain groups, saving only their tree roots in the contract. Extension contracts[​](https://docs.semaphore.pse.dev/es/V2/technical-reference/contracts#extension-contracts "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------------------------------- * [`SemaphoreVoting.sol`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/extensions/SemaphoreVoting.sol) : voting contract that contains the essential functions to create polls, add voters, and anonymously cast votes. * [`SemaphoreWhistleblowing.sol`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/extensions/SemaphoreWhistleblowing.sol) : whistleblowing contract that contains the essential functions to create entities (for example: non-profit organizations), add whistleblowers, and anonymously publish leaks. These contracts extend the protocol to provide application logic for specific use-cases. More extensions will be added in the future. Verifiers[​](https://docs.semaphore.pse.dev/es/V2/technical-reference/contracts#verifiers "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------- To verify Semaphore proofs, the [`SemaphoreCore.sol`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/base/SemaphoreCore.sol) contract requires the address of a deployed verifier contract. You can choose to manually deploy the [verifier](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/verifiers) you prefer or you can use one of our [deployed verifiers](https://docs.semaphore.pse.dev/es/V2/deployed-contracts#verifiers) . Each verifier name indicates the tree depth that it can verify. For example, given a Semaphore proof generated with a tree depth `20`: * The `Verifier20.sol` contract can verify the proof. * The [group](https://docs.semaphore.pse.dev/es/guides/groups) used for the proof can have a maximum `2^20=1048576` members. * [Base contracts](https://docs.semaphore.pse.dev/es/V2/technical-reference/contracts#base-contracts) * [Extension contracts](https://docs.semaphore.pse.dev/es/V2/technical-reference/contracts#extension-contracts) * [Verifiers](https://docs.semaphore.pse.dev/es/V2/technical-reference/contracts#verifiers) --- # Créditos | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/credits#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/credits) ** (V4). Versión: V3 Semaphore es el esfuerzo de varias personas, para ver una lista completa de contribuidores puede visitar nuestras [páginas en Github](https://github.com/semaphore-protocol/semaphore/graphs/contributors) . * [Barry WhiteHat](https://github.com/barryWhiteHat) * [Kobi Gurkan](https://github.com/kobigurk) * [Koh Wei Jie](https://github.com/weijiekoh) * [Andrija Novakovic](https://github.com/akinovak) * [Cedoor](https://github.com/cedoor) * [Rachel Aux](https://github.com/rachelaux) * [Andy Guzman](https://github.com/aguzmant103) * [Vivian Plasencia](https://github.com/vplasencia) * [LauNaMu](https://github.com/0xyNaMu) --- # Glosario | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/glossary#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/glossary) ** (V4). Versión: V3 En esta página Identidad Semaphore[​](https://docs.semaphore.pse.dev/es/V3/glossary#identidad-semaphore "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------- La identidad de un usuario en el protocolo Semaphore. Una identidad contiene los tres valores que se mencionan a continuación: * [Compromiso de identidad](https://docs.semaphore.pse.dev/es/V3/glossary#compromiso-de-identidad-identity-commitment) (identity commitment): el valor público. * Identidad trampilla (identity trapdoor) y anulador de identidad (identity nullifier): valores secretos que únicamente son del conocimiento del usuario. Compromiso de identidad (Identity commitment)[​](https://docs.semaphore.pse.dev/es/V3/glossary#compromiso-de-identidad-identity-commitment "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- El valor público de la [identidad Semaphore](https://docs.semaphore.pse.dev/es/V3/glossary#identidad-semaphore) utilizado en los [grupos Semaphore](https://docs.semaphore.pse.dev/es/V3/glossary#grupo-semaphore) . Semaphore utiliza la función hash [Poseidon](https://www.poseidon-hash.info/) para crear un compromiso de identidad a partir de los valores secretos de la identidad Semaphore. Grupo Semaphore[​](https://docs.semaphore.pse.dev/es/V3/glossary#grupo-semaphore "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------- Un grupo es un [árbol de Merkle](https://docs.semaphore.pse.dev/es/V3/glossary#%C3%A1rbol-de-merkle-merkle-tree) binario e incremental en el que cada hoja contiene un [compromiso de identidad](https://docs.semaphore.pse.dev/es/V3/glossary#compromiso-de-identidad-identity-commitment) para un usuario. El compromiso de identidad comprueba que un usuario es un miembro del grupo sin revelar la identidad Semaphore del usuario. Semaphore utiliza la función hash **Poseidon** para crear árboles de Merkle. Para mayor información, vea el [sitio web de Poseidon](https://www.poseidon-hash.info/) . Árbol de Merkle (Merkle tree)[​](https://docs.semaphore.pse.dev/es/V3/glossary#%C3%A1rbol-de-merkle-merkle-tree "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------------ Un árbol en el que cada hoja (es decir, un nodo que no tiene hijos) es etiquetado con el hash criptográfico de un bloque de datos, y cada nodo, que no es una hoja, es etiquetado con el hash criptográfico de las etiquetas de sus nodos hijos. En los protocolos de conocimiento zero (ZK), los árboles de Merkle pueden ser utilizados para resumir y validar de forma eficiente grandes conjuntos de datos. Para validar que un árbol contiene una hoja en específico, un verificador sólo necesita una porción de la estructura completa de datos. Para más información, vea [árbol de Merkle en Wikipedia](https://es.wikipedia.org/wiki/%C3%81rbol_de_Merkle) . Anulador (Nullifier)[​](https://docs.semaphore.pse.dev/es/V3/glossary#anulador-nullifier "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------- Un valor utilizado para prevenir registros dobles o dos señales emitidas por el mismo usuario. Ver [hash de circuito nullifier](https://docs.semaphore.pse.dev/es/V3/technical-reference/circuits#hash-anulador-nullifier-hash) . Retransmisor (Relayer)[​](https://docs.semaphore.pse.dev/es/V3/glossary#retransmisor-relayer "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------------------- Un tercero que recibe una comisión por incluir transacciones retransmitidas en la blockchain (McMenamin, Daza, and Fitz. [https://eprint.iacr.org/2022/155.pdf](https://eprint.iacr.org/2022/155.pdf) , p.3). Para preservar la anonimidad del usuario emitiendo una señal con Semaphore, una aplicación puede utilizar un retransmisor para publicar la transacción de la señal en Ethereum en nombre del usuario. Las aplicaciones pueden ofrecer recompensas a los retransmisores e implementar mecanismos para prevenir ventajas maliciosas, como requerir que las señales incluyan la dirección del retransmisor, vinculando así la señal a esa dirección en específico ([https://semaphore.pse.dev/whitepaper-v1.pdf](https://semaphore.pse.dev/whitepaper-v1.pdf) , p.6). Archivos confiables de configuración (Trusted setup files)[​](https://docs.semaphore.pse.dev/es/V3/glossary#archivos-confiables-de-configuraci%C3%B3n-trusted-setup-files "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Los parámetros verificables y seguros generados por la ceremonia de configuración de confianza de Semaphore. Semaphore utiliza los archivos confiables de configuración para generar y verificar pruebas válidas de conocimiento cero. Para generar o verificar pruebas válidas de conocimiento cero con Semaphore, las aplicaciones deben incluir los siguientes archivos _confiables de configuración_ de Semaphore. * semaphore.zkey * semaphore.wasm * semaphore.json Para ver una lista completa de archivos listos para utilizarse, vea [trusted-setup-pse.org](https://www.trusted-setup-pse.org/) . Para aprender más, vea la [ceremonia de configuración de confianza](https://storage.googleapis.com/trustedsetup-a86f4.appspot.com/semaphore/semaphore_top_index.html) (trusted setup ceremony). Señales (Signals)[​](https://docs.semaphore.pse.dev/es/V3/glossary#se%C3%B1ales-signals "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------ El término "señales" en Semaphore se refiere a los valores que el usuario transmite al votar, confirmar, enviar un mensaje, etc. Por otro lado, "[señales](https://docs.circom.io/circom-language/signals/) " en Circom se refiere a datos que contienen elementos dentro del campo de Z/pZ. En Circom, las "señales" se pueden definir como entrada o salida y, de lo contrario, se consideran señales intermedias. * [Identidad Semaphore](https://docs.semaphore.pse.dev/es/V3/glossary#identidad-semaphore) * [Compromiso de identidad (Identity commitment)](https://docs.semaphore.pse.dev/es/V3/glossary#compromiso-de-identidad-identity-commitment) * [Grupo Semaphore](https://docs.semaphore.pse.dev/es/V3/glossary#grupo-semaphore) * [Árbol de Merkle (Merkle tree)](https://docs.semaphore.pse.dev/es/V3/glossary#%C3%A1rbol-de-merkle-merkle-tree) * [Anulador (Nullifier)](https://docs.semaphore.pse.dev/es/V3/glossary#anulador-nullifier) * [Retransmisor (Relayer)](https://docs.semaphore.pse.dev/es/V3/glossary#retransmisor-relayer) * [Archivos confiables de configuración (Trusted setup files)](https://docs.semaphore.pse.dev/es/V3/glossary#archivos-confiables-de-configuraci%C3%B3n-trusted-setup-files) * [Señales (Signals)](https://docs.semaphore.pse.dev/es/V3/glossary#se%C3%B1ales-signals) --- # Groups | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/guides/groups#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página A [Semaphore group](https://docs.semaphore.pse.dev/es/glossary#group) contains [identity commitments](https://docs.semaphore.pse.dev/es/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. información Semaphore V4 uses the [ZK-Kit](https://github.com/privacy-scaling-explorations/zk-kit) LeanIMT (i.e., Lean Incremental Merkle Tree) [Solidity](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/imt.sol/contracts) and [JavaScript](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/imt) implementations for managing groups. Groups are Merkle trees, and the group members (i.e., identity commitments) are their leaves. Off-chain groups[​](https://docs.semaphore.pse.dev/es/guides/groups#off-chain-groups "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------------- Use the [`@semaphore-protocol/group`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/group) package to manage off-chain groups. ### Install package[​](https://docs.semaphore.pse.dev/es/guides/groups#install-package "Enlace directo al encabezado") * npm * Yarn * pnpm npm install @semaphore-protocol/group yarn add @semaphore-protocol/group pnpm add @semaphore-protocol/group información Semaphore also provides `@semaphore-protocol/core`, which includes the functions of the following core packages: `@semaphore-protocol/identity`, `@semaphore-protocol/group`, `@semaphore-protocol/proof`. ### Create a group[​](https://docs.semaphore.pse.dev/es/guides/groups#create-a-group "Enlace directo al encabezado") To create a group instantiate `Group` without any parameters. For example: import { Group } from "@semaphore-protocol/group"const group1 = new Group() You can also initialize a group with multiple members by passing the list of identity commitments as the first parameter when creating the group: const members = [ 11237622825477336339577122413451117718539783476837539122310492284566644730311n, 9332663527862709610616009715800254142772436825222910251631161087138559093425n, 13255821893820536903335282929376140649646180444238593676033702344407594536519n]const group2 = new Group(members) ### Add members[​](https://docs.semaphore.pse.dev/es/guides/groups#add-members "Enlace directo al encabezado") Use the `addMember` method to add a member to a group. For example: import { Identity } from "@semaphore-protocol/identity"const { commitment } = new Identity()group1.addMember(commitment) To add a batch of members to a group, pass an array to the `addMembers` method. For example: group1.addMembers(members) precaución When you use the same Semaphore identity across multiple groups, if an attacker takes control of that identity all the groups it is part of will be compromised. Consider using different identities for each group. ### Remove or update members[​](https://docs.semaphore.pse.dev/es/guides/groups#remove-or-update-members "Enlace directo al encabezado") To remove members from a group, pass the member index to the `removeMember` method. For example: group.removeMember(0) To update members in a group, pass the member index and the new value to the `updateMember` method. For example: group.updateMember(0, 2n) precaución Removing a member from a group sets its value to 0. Given that the member isn't removed, the number of members (i.e., `group.size` on `group.members.length`) doesn't change. ### Generate a Merkle proof[​](https://docs.semaphore.pse.dev/es/guides/groups#generate-a-merkle-proof "Enlace directo al encabezado") Semaphore groups are [Merkle trees](https://docs.semaphore.pse.dev/es/glossary#merkle-tree) , and it is therefore possible to calculate the Merkle proof of a group member (i.e., tree leaf) by passing the index of the member to the `generateMerkleProof`. For example: group.generateMerkleProof(0) On-chain groups[​](https://docs.semaphore.pse.dev/es/guides/groups#on-chain-groups "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------- Semaphore provides [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) , a contract designed for managing on-chain groups ([deployed](https://docs.semaphore.pse.dev/es/deployed-contracts) on major testnets). Use the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts) package to import the `ISemaphore.sol` interface in your contract and start using its functions. ### Install package[​](https://docs.semaphore.pse.dev/es/guides/groups#install-package-1 "Enlace directo al encabezado") * npm * Yarn * pnpm npm install @semaphore-protocol/contracts yarn add @semaphore-protocol/contracts pnpm add @semaphore-protocol/contracts ### Create a group[​](https://docs.semaphore.pse.dev/es/guides/groups#create-a-group-1 "Enlace directo al encabezado") 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: pragma solidity ^0.8.23;import "@semaphore-protocol/contracts/interfaces/ISemaphore.sol";contract YourContract { ISemaphore public semaphore; uint256 public groupId; constructor(ISemaphore _semaphore) { semaphore = _semaphore; 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. 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[​](https://docs.semaphore.pse.dev/es/guides/groups#add-members-1 "Enlace directo al encabezado") Use the `addMember` function to add a member to a group. For example: function addMember(uint256 identityCommitment) external { semaphore.addMember(groupId, identityCommitment);} To add a batch of members to a group, pass an array to the `addMembers` function. For example: function addMembers(uint256[] calldata identityCommitments) external { semaphore.addMembers(groupId, identityCommitments);} ### Remove or update members[​](https://docs.semaphore.pse.dev/es/guides/groups#remove-or-update-members-1 "Enlace directo al encabezado") To update members in a group, pass the identity commitment of the member you want to update, its new identity commitment and the siblings of the Merkle proof for that member. For example: function updateMember(uint256 identityCommitment, uint256 newIdentityCommitment, uint256[] calldata merkleProofSiblings) external { semaphore.updateMember(groupId, identityCommitment, newIdentityCommitment, merkleProofSiblings);} información To calculate the Merkle proof of a group member you can use the `generateMerkleProof` method of the JavaScript `Group` class described above. To remove members from a group, pass the identity commitment of the member you want to remove and the siblings of the Merkle proof for that member. For example: function removeMember(uint256 identityCommitment, uint256[] calldata merkleProofSiblings) external { semaphore.removeMember(groupId, identityCommitment, merkleProofSiblings);} información 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`. * [Off-chain groups](https://docs.semaphore.pse.dev/es/guides/groups#off-chain-groups) * [Install package](https://docs.semaphore.pse.dev/es/guides/groups#install-package) * [Create a group](https://docs.semaphore.pse.dev/es/guides/groups#create-a-group) * [Add members](https://docs.semaphore.pse.dev/es/guides/groups#add-members) * [Remove or update members](https://docs.semaphore.pse.dev/es/guides/groups#remove-or-update-members) * [Generate a Merkle proof](https://docs.semaphore.pse.dev/es/guides/groups#generate-a-merkle-proof) * [On-chain groups](https://docs.semaphore.pse.dev/es/guides/groups#on-chain-groups) * [Install package](https://docs.semaphore.pse.dev/es/guides/groups#install-package-1) * [Create a group](https://docs.semaphore.pse.dev/es/guides/groups#create-a-group-1) * [Add members](https://docs.semaphore.pse.dev/es/guides/groups#add-members-1) * [Remove or update members](https://docs.semaphore.pse.dev/es/guides/groups#remove-or-update-members-1) --- # Private voting use case | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V2 En esta página The private voting use case describes how Semaphore interacts with your users and Ethereum to allow users to cast private votes in your application. Learn how Semaphore enables applications to do the following: * Register members as voters. * Allow members to vote anonymously. * Prove voter membership. * Record and prove votes. * Prevent double-voting. Roles[​](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#roles "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------- * **[Developer or community admin](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#developer-or-community-admin) ** * **[Community member (dApp user)](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#community-member) ** * **[Relay](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#relay) ** ### Developer or community admin[​](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#developer-or-community-admin "Enlace directo al encabezado") As a developer or community admin, you deploy the following: * **Smart contract on Ethereum**: implements the Semaphore **base contract** to create a poll (Semaphore **group** that members join to vote), post transactions, and verify proofs on Ethereum. * **Decentralized application (dApp)**: your application that provides a user interface (UI) where members join a poll and vote on a proposal. ### Community member[​](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#community-member "Enlace directo al encabezado") Community members connect their wallets to the dApp to take the following actions: 1. Verify ownership of the community token. 2. Generate an anonymous ID. 3. Cast a vote. ### Relay[​](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#relay "Enlace directo al encabezado") To preserve anonymity and avoid disclosing the member's wallet address, the dApp may use a [relay](https://docs.semaphore.pse.dev/es/V2/glossary#relay) to broadcast the vote. The relay calls the **contract** function that then posts the member's vote transaction to Ethereum. Private voting[​](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#private-voting "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------- Consider a scenario where your community issues a token that users can mint. The token might be a Proof of Attendance (POAP), NFT, or social token that your users can mint to receive membership and vote in your community. The voting scenario has the following steps: 1. [Create a poll](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#create-a-poll) : Coordinator creates a poll, or _group_, in which members can vote on a proposal. 2. [Register voters](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#register-voters) : Members join the poll to vote. 3. [Record votes](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#record-votes) : Once the poll opens, members may cast one vote, or _signal_, on the topic. ### Create a poll[​](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#create-a-poll "Enlace directo al encabezado") A community coordinator or dApp administrator uses the deployed smart contract to create an on-chain (Ethereum) poll, a [Semaphore group](https://docs.semaphore.pse.dev/es/V2/guides/groups) that members can join and cast votes to. In the following sample code, the voting contract declares a `createPoll` function that uses the Semaphore base `_createGroup` function: https://github.com/semaphore-protocol/semaphore/blob/v3.15.1/packages/contracts/contracts/extensions/SemaphoreVoting.sol function createPoll( uint256 pollId, address coordinator, uint8 depth) public override { require(address(verifiers[depth]) != address(0), "SemaphoreVoting: depth value is not supported"); _createGroup(pollId, depth, 0); Poll memory poll; poll.coordinator = coordinator; polls[pollId] = poll; emit PollCreated(pollId, coordinator);} A poll is a Semaphore [group](https://docs.semaphore.pse.dev/es/V2/guides/groups) that stores the following: * A topic to vote on. * The public ID of the poll creator. * [Semaphore IDs](https://docs.semaphore.pse.dev/es/V2/guides/identities) of members who joined the poll. To create the poll, the administrator calls the smart contract function--for example: SemaphoreVoting.createPoll(pollId, coordinator, depth) Next, learn how to [register voters](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#register-voters) for the poll. ### Register voters[​](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#register-voters "Enlace directo al encabezado") Before a user can register to vote, the dApp needs to verify membership by checking the user's wallet for the NFT. To grant access to the wallet, the user clicks a `Connect wallet` button in the dApp and allows the dApp to check for the NFT. Once a member is verified, the dApp provides the following member interactions: 1. [Generate a private identity](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#generate-a-private-identity) . 2. [Join a poll](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#join-a-poll) . información To learn how to connect to Ethereum wallets, visit the \[ethers.js Getting Started documentation\](([https://docs.ethers.io/v5/getting-started](https://docs.ethers.io/v5/getting-started) ). #### Generate a private identity[​](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#generate-a-private-identity "Enlace directo al encabezado") To generate a private identity, the member completes a form in the dApp UI. With the form values and the `@semaphore-protocol/identity` library, the dApp prompts the member to sign a wallet message and then generates the signed private identity. The private identity is known only to the member and can be used in future interactions with the dApp. Next, learn how members [join a poll](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#join-a-poll) . #### Join a poll[​](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#join-a-poll "Enlace directo al encabezado") Once the member has a private identity for the dApp, the member may select a poll to vote in. When the member selects a poll, the dApp does the following: 1. Uses the `@semaphore-protocol/identity` library to generate an anonymous Semaphore ID, or _identity commitment_, from the private identity. 2. Calls a contract function that adds the new Semaphore ID to the on-chain poll. With a member registered for a poll, learn how the dApp [records votes](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#record-votes) . ### Record votes[​](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#record-votes "Enlace directo al encabezado") Once members have joined a poll, the coordinator starts the poll to allow voting. When a member votes (for example, by selecting a radio button), then the dApp takes the following actions: 1. Uses the `@semaphore-protocol/proof` library to create a proof of the vote, the poll identifier, the Semaphore ID, and a [nullifier](https://docs.semaphore.pse.dev/es/V2/glossary#nullifier) that prevents double-voting. 2. Sends the vote proof to the [relay](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#relay) . ### Related[​](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#related "Enlace directo al encabezado") * To get started developing with Semaphore, see the [Quick setup](https://docs.semaphore.pse.dev/es/V2/quick-setup) guide. * For an example app that you can use to start your own project, see [Semaphore boilerplate](https://github.com/semaphore-protocol/boilerplate) . * [Roles](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#roles) * [Developer or community admin](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#developer-or-community-admin) * [Community member](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#community-member) * [Relay](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#relay) * [Private voting](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#private-voting) * [Create a poll](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#create-a-poll) * [Register voters](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#register-voters) * [Record votes](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#record-votes) * [Related](https://docs.semaphore.pse.dev/es/V2/use-cases/private-voting#related) --- # Contratos desplegados | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/deployed-contracts#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/deployed-contracts) ** (V4). Versión: V3 | Contrato | Goerli\* | Sepolia | Mumbai | Optimism Goerli\* | Arbitrum Goerli\* | Arbitrum One | | --- | --- | --- | --- | --- | --- | --- | | Semaphore.sol | [0x3889...6131](https://goerli.etherscan.io/address/0x3889927F0B5Eb1a02C6E2C20b39a1Bd4EAd76131) | [0x3889...6131](https://sepolia.etherscan.io/address/0x3889927F0B5Eb1a02C6E2C20b39a1Bd4EAd76131) | [0x3889...6131](https://mumbai.polygonscan.com/address/0x3889927F0B5Eb1a02C6E2C20b39a1Bd4EAd76131) | [0x3889...6131](https://goerli-optimism.etherscan.io/address/0x3889927F0B5Eb1a02C6E2C20b39a1Bd4EAd76131) | [0x3889...6131](https://goerli.arbiscan.io/address/0x3889927F0B5Eb1a02C6E2C20b39a1Bd4EAd76131) | [0xc60E...1520](https://arbiscan.io/address/0xc60E0Ee1a2770d5F619858C641f14FC4a6401520) | | SemaphoreVerifier.sol | [0xb908...217C](https://goerli.etherscan.io/address/0xb908Bcb798e5353fB90155C692BddE3b4937217C) | [0xb908...217C](https://sepolia.etherscan.io/address/0xb908Bcb798e5353fB90155C692BddE3b4937217C) | [0xb908...217C](https://mumbai.polygonscan.com/address/0xb908Bcb798e5353fB90155C692BddE3b4937217C) | [0xb908...217C](https://goerli-optimism.etherscan.io/address/0xb908Bcb798e5353fB90155C692BddE3b4937217C) | [0xb908...217C](https://goerli.arbiscan.io/address/0xb908Bcb798e5353fB90155C692BddE3b4937217C) | [0xCAbe...4d07](https://arbiscan.io/address/0xCAbeED6cB96a287000aBd834b0B79c05e6Ea4d07) | | Pairing.sol | [0xEe44...d7e8](https://goerli.etherscan.io/address/0xEe44c1e83A768E80A3588B409f1A010f9D1dd7e8) | [0xEe44...d7e8](https://sepolia.etherscan.io/address/0xEe44c1e83A768E80A3588B409f1A010f9D1dd7e8) | [0xEe44...d7e8](https://mumbai.polygonscan.com/address/0xEe44c1e83A768E80A3588B409f1A010f9D1dd7e8) | [0xEe44...d7e8](https://goerli-optimism.etherscan.io/address/0xEe44c1e83A768E80A3588B409f1A010f9D1dd7e8) | [0xEe44...d7e8](https://goerli.arbiscan.io/address/0xEe44c1e83A768E80A3588B409f1A010f9D1dd7e8) | [0xE3a4...A74C](https://arbiscan.io/address/0xE3a4C2FE9f025405cA6F60f6E960B4558604A74C) | | IncrementalBinaryTree.sol | [0x4621...7F49](https://goerli.etherscan.io/address/0x4621EE309EAc747425F0FEd51931dDC241A27F49) | [0x4621...7F49](https://sepolia.etherscan.io/address/0x4621EE309EAc747425F0FEd51931dDC241A27F49) | [0x4621...7F49](https://mumbai.polygonscan.com/address/0x4621EE309EAc747425F0FEd51931dDC241A27F49) | [0x4621...7F49](https://goerli-optimism.etherscan.io/address/0x4621EE309EAc747425F0FEd51931dDC241A27F49) | [0x4621...7F49](https://goerli.arbiscan.io/address/0x4621EE309EAc747425F0FEd51931dDC241A27F49) | [0xcDF8...fFb0](https://arbiscan.io/address/0xcDF8efE6334c68aF283C83f2F14648da51fcfFb0) | | PoseidonT3.sol | [0xe136...2595](https://goerli.etherscan.io/address/0xe136aBACf78E05988154ed85F4Ea911105302595) | [0xe136...2595](https://sepolia.etherscan.io/address/0xe136aBACf78E05988154ed85F4Ea911105302595) | [0xe136...2595](https://mumbai.polygonscan.com/address/0xe136aBACf78E05988154ed85F4Ea911105302595) | [0xe136...2595](https://goerli-optimism.etherscan.io/address/0xe136aBACf78E05988154ed85F4Ea911105302595) | [0xe136...2595](https://goerli.arbiscan.io/address/0xe136aBACf78E05988154ed85F4Ea911105302595) | [0xe0c8...61d0](https://arbiscan.io/address/0xe0c8d1e53D9Bfc9071F6564755FCFf6cC0dB61d0) | precaución Está previsto que la testnet Goerli deje de funcionar en el cuarto trimestre de 2023. Consulte los siguientes enlaces para obtener más información. * Goerli: [https://ethereum.org/en/developers/docs/networks/#goerli](https://ethereum.org/en/developers/docs/networks/#goerli) * Optimism Goerli: [https://community.optimism.io/docs/useful-tools/networks/#op-goerli](https://community.optimism.io/docs/useful-tools/networks/#op-goerli) * Arbitrum Goerli: [https://docs.arbitrum.io/for-devs/concepts/public-chains#arbitrum-goerli](https://docs.arbitrum.io/for-devs/concepts/public-chains#arbitrum-goerli) ::: --- # Credits | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/credits#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 Semaphore is the work of several people, for a complete list of contributors you can visit the Semaphore [Github insights](https://github.com/semaphore-protocol/semaphore/graphs/contributors) . * [Barry WhiteHat](https://github.com/barryWhiteHat) * [Kobi Gurkan](https://github.com/kobigurk) * [Koh Wei Jie](https://github.com/weijiekoh) * [Andrija Novakovic](https://github.com/akinovak) * [Cedoor](https://github.com/cedoor) * [Rachel Aux](https://github.com/rachelaux) * [Andy Guzman](https://github.com/aguzmant103) * [Vivian Plasencia](https://github.com/vplasencia) * [LauNaMu](https://github.com/0xyNaMu) * [0xjei](https://github.com/0xjei) * [Mari Poveda](https://github.com/maripoveda) * [Gauthier](https://github.com/sripwoud) --- # Quick setup | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2/quick-setup#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V2 En esta página 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 [quick-setup](https://github.com/semaphore-protocol/quick-setup) repository. 1. [**Create a Node.js project**](https://docs.semaphore.pse.dev/es/V2/quick-setup#create-a-nodejs-project) 2. [**Install Hardhat**](https://docs.semaphore.pse.dev/es/V2/quick-setup#install-hardhat) 3. [**Install Semaphore packages**](https://docs.semaphore.pse.dev/es/V2/quick-setup#install-semaphore-packages) 4. [**Create the Semaphore contract**](https://docs.semaphore.pse.dev/es/V2/quick-setup#create-the-semaphore-contract) 5. [**Create a Hardhat task**](https://docs.semaphore.pse.dev/es/V2/quick-setup#create-a-hardhat-task) 6. [**Test your contracts**](https://docs.semaphore.pse.dev/es/V2/quick-setup#test-your-contract) 7. [**Deploy your contract**](https://docs.semaphore.pse.dev/es/V2/quick-setup#deploy-your-contract) Create a Node.js project[​](https://docs.semaphore.pse.dev/es/V2/quick-setup#create-a-nodejs-project "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------- 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. mkdir semaphore-examplecd semaphore-example 4. In your terminal, run `yarn init` to initialize the Node.js project. Install Hardhat[​](https://docs.semaphore.pse.dev/es/V2/quick-setup#install-hardhat "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------- [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/) : yarn add hardhat --dev 2. Use `yarn` to run `hardhat` and create a JavaScript project: yarn hardhat# At the prompt, select "Create a JavaScript project"# and then enter through the prompts. Install Semaphore packages[​](https://docs.semaphore.pse.dev/es/V2/quick-setup#install-semaphore-packages "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------ Semaphore provides contracts, JavaScript libraries and a Hardhat plugin for developers building zero-knowledge applications. * `@semaphore-protocol/contracts` provides contracts to manage groups and verify Semaphore proofs on-chain. * JavaScript libraries help developers build zero-knowledge applications. * `@semaphore-protocol/hardhat` allow developers Hardhat tasks to deploy verifiers and Semaphore contracts. To install these dependencies for your project, do the following: 1. Use `yarn` to install `@semaphore-protocol/contracts`: yarn add @semaphore-protocol/[email protected] 2. Use `yarn` to install the Semaphore JavaScript libraries and the Hardhat plugin: yarn add @semaphore-protocol/[email protected] @semaphore-protocol/[email protected] @semaphore-protocol/[email protected] @semaphore-protocol/[email protected] --dev For more detail about _Semaphore contracts_, see [Contracts](https://docs.semaphore.pse.dev/technical-reference/contracts) . To view the source of our packages, see the [semaphore](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1#-packages) repository. Create the Semaphore contract[​](https://docs.semaphore.pse.dev/es/V2/quick-setup#create-the-semaphore-contract "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------------ Create a `Greeter` contract that uses the `Semaphore.sol` contract: 1. Rename `Lock.sol` to `Greeter.sol` and replace the content with the following: ./contracts/Greeter.sol //SPDX-License-Identifier: MITpragma solidity ^0.8.0;import "@semaphore-protocol/contracts/interfaces/ISemaphore.sol";/// @title Greeter contract./// @dev The following code is just an example to show how Semaphore can be used.contract Greeter { event NewGreeting(bytes32 greeting); event NewUser(uint256 identityCommitment, bytes32 username); ISemaphore public semaphore; uint256 groupId; mapping(uint256 => bytes32) users; constructor(address semaphoreAddress, uint256 _groupId) { semaphore = ISemaphore(semaphoreAddress); groupId = _groupId; semaphore.createGroup(groupId, 20, 0, address(this)); } function joinGroup(uint256 identityCommitment, bytes32 username) external { semaphore.addMember(groupId, identityCommitment); users[identityCommitment] = username; emit NewUser(identityCommitment, username); } function greet( bytes32 greeting, uint256 merkleTreeRoot, uint256 nullifierHash, uint256[8] calldata proof ) external { semaphore.verifyProof(groupId, merkleTreeRoot, greeting, nullifierHash, groupId, proof); emit NewGreeting(greeting); }} Create a Hardhat task[​](https://docs.semaphore.pse.dev/es/V2/quick-setup#create-a-hardhat-task "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------- 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 `Greeter` contract, do the following: 1. Create a `tasks` folder and add a `./tasks/deploy.js` file that contains the following: ./tasks/deploy.js const { task, types } = require("hardhat/config")task("deploy", "Deploy a Greeter contract") .addOptionalParam("semaphore", "Semaphore contract address", undefined, types.address) .addParam("group", "Group identifier", 42, types.int) .addOptionalParam("logs", "Print the logs", true, types.boolean) .setAction(async ({ logs, semaphore: semaphoreAddress, group: groupId }, { ethers, run }) => { if (!semaphoreAddress) { const { address: verifierAddress } = await run("deploy:verifier", { logs, merkleTreeDepth: 20 }) const { address } = await run("deploy:semaphore", { logs, verifiers: [ { merkleTreeDepth: 20, contractAddress: verifierAddress } ] }) semaphoreAddress = address } const Greeter = await ethers.getContractFactory("Greeter") const greeter = await Greeter.deploy(semaphoreAddress, groupId) await greeter.deployed() if (logs) { console.log(`Greeter contract has been deployed to: ${greeter.address}`) } return greeter }) 2. In your `hardhat.config.js` file, add the following: ./hardhat.config.js require("@nomiclabs/hardhat-waffle")require("@semaphore-protocol/hardhat")require("./tasks/deploy") // Your deploy task.module.exports = { solidity: "0.8.4"} Test your contract[​](https://docs.semaphore.pse.dev/es/V2/quick-setup#test-your-contract "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------- [`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: yarn add -D @nomiclabs/hardhat-waffle 'ethereum-waffle@^3.0.0' \ @nomiclabs/hardhat-ethers 'ethers@^5.0.0' chai 2. Download the Semaphore [zk trusted setup files](http://www.trusted-setup-pse.org/) and copy them to the `./static` folder. cd staticwget http://www.trusted-setup-pse.org/semaphore/20/semaphore.zkeywget http://www.trusted-setup-pse.org/semaphore/20/semaphore.wasm Learn more about [trusted setup files](https://docs.semaphore.pse.dev/es/V2/glossary#trusted-setup-files) . 3. Rename the `Lock.js` test file to `Greeter.js` and replace the content with the following: ./test/Greeter.js const { Identity } = require("@semaphore-protocol/identity")const { Group } = require("@semaphore-protocol/group")const { generateProof, packToSolidityProof, verifyProof } = require("@semaphore-protocol/proof")const { expect } = require("chai")const { run, ethers } = require("hardhat")describe("Greeter", function () { let greeter const users = [] const groupId = 42 const group = new Group() before(async () => { greeter = await run("deploy", { logs: false, group: groupId }) users.push({ identity: new Identity(), username: ethers.utils.formatBytes32String("anon1") }) users.push({ identity: new Identity(), username: ethers.utils.formatBytes32String("anon2") }) group.addMember(users[0].identity.generateCommitment()) group.addMember(users[1].identity.generateCommitment()) }) describe("# joinGroup", () => { it("Should allow users to join the group", async () => { for (let i = 0; i < group.members.length; i++) { const transaction = greeter.joinGroup(group.members[i], users[i].username) await expect(transaction).to.emit(greeter, "NewUser").withArgs(group.members[i], users[i].username) } }) }) describe("# greet", () => { const wasmFilePath = "./static/semaphore.wasm" const zkeyFilePath = "./static/semaphore.zkey" it("Should allow users to greet", async () => { const greeting = ethers.utils.formatBytes32String("Hello World") const fullProof = await generateProof(users[1].identity, group, groupId, greeting, { wasmFilePath, zkeyFilePath }) const solidityProof = packToSolidityProof(fullProof.proof) const transaction = greeter.greet( greeting, fullProof.publicSignals.merkleRoot, fullProof.publicSignals.nullifierHash, solidityProof ) await expect(transaction).to.emit(greeter, "NewGreeting").withArgs(greeting) }) })}) 4. Run the following `yarn` commands to compile and test your contract: yarn hardhat compileyarn hardhat test Deploy your contract[​](https://docs.semaphore.pse.dev/es/V2/quick-setup#deploy-your-contract "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------ To deploy your contract in a local Hardhat network (and use it in your dApp), run the following `yarn` commands: yarn hardhat nodeyarn hardhat deploy --group 42 --network localhost # In another tab. For a more complete demo that provides a starting point for your dApp, see [semaphore-boilerplate](https://github.com/semaphore-protocol/boilerplate/) . * [Create a Node.js project](https://docs.semaphore.pse.dev/es/V2/quick-setup#create-a-nodejs-project) * [Install Hardhat](https://docs.semaphore.pse.dev/es/V2/quick-setup#install-hardhat) * [Install Semaphore packages](https://docs.semaphore.pse.dev/es/V2/quick-setup#install-semaphore-packages) * [Create the Semaphore contract](https://docs.semaphore.pse.dev/es/V2/quick-setup#create-the-semaphore-contract) * [Create a Hardhat task](https://docs.semaphore.pse.dev/es/V2/quick-setup#create-a-hardhat-task) * [Test your contract](https://docs.semaphore.pse.dev/es/V2/quick-setup#test-your-contract) * [Deploy your contract](https://docs.semaphore.pse.dev/es/V2/quick-setup#deploy-your-contract) --- # Configuración rápida | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/quick-setup#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V3 En esta página Semaphore ofrece un CLI oficial para configurar su proyecto con Hardhat. Si su NPM es versión 5.2 or más reciente puede utilizar NPX: npx @semaphore-protocol/cli@^3 create my-app --template monorepo-ethers De lo contrario, instale `@semaphore-protocol/cli@^3` de forma global y corra el comando `init`: npm i -g @semaphore-protocol/cli@^3semaphore create my-app --template monorepo-ethers información Los templates soportados son: [`contracts-hardhat`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-contracts-hardhat) , [`monorepo-ethers`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-monorepo-ethers) , [`monorepo-subgraph`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-monorepo-subgraph) información El CLI [`semaphore`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli) también se puede utilizar para obtener información de los grupos que existen dentro de las redes soportadas por Semaphore (por ejemplo: `semaphore get-groups --network goerli`). Para comenzar a trabajar en su proyecto, instale las siguientes dependencias: * npm * Yarn * pnpm cd my-appnpm i cd my-appyarn cd my-apppnpm install Output[​](https://docs.semaphore.pse.dev/es/V3/quick-setup#output "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------- El comando `create` creará un directorio con el nombre my-app (o cualquier nombre que usted escoja) dentro de la carpeta actual. Ese directorio contendrá la estructura inicial del proyecto, que incluye un contrato simple (contract), una tarea (task) para desplegar lo, algunas pruebas (test) y una aplicación de Next.js (la carpeta web-app) para interactuar con el contrato. my-app├── .yarn├── apps│ └── contracts│ │ └── contracts| │ │ └── Feedback.sol│ │ └── scripts| │ │ └── download-snark-artifacts.ts│ │ └── tasks| │ │ └── deploy.ts│ │ └── test| │ │ └── Feedback.ts│ │ └── hardhat.config.ts│ │ └── package.json│ │ └── tsconfig.json│ └── web-app├── scripts│ └── copy-contracts-artifacts.ts├── .editorconfig├── .env├── .env.example├── .eslintignore├── .eslintrc.json├── .gitignore├── .prettierignore├── .prettierrc.json├── .yarnrc.yml├── package.json├── README.md└── tsconfig.json El contrato `Feedback.sol` crea un grupo Semaphore, permite que los usuarios se unan a ese grupo con su identidad Semaphore, y, finalmente, permite que los miembros de ese grupo envíen un feedback anónimo. Uso[​](https://docs.semaphore.pse.dev/es/V3/quick-setup#uso "Enlace directo al encabezado") -------------------------------------------------------------------------------------------- ### Compilar contratos[​](https://docs.semaphore.pse.dev/es/V3/quick-setup#compilar-contratos "Enlace directo al encabezado") Vaya a la carpeta `contracts`: cd apps/contracts Y compile sus contratos al correr: * npm * Yarn * pnpm npm run compile yarn compile pnpm compile ### Pruebe los contratos[​](https://docs.semaphore.pse.dev/es/V3/quick-setup#pruebe-los-contratos "Enlace directo al encabezado") Pruebe sus contratos al correr: * npm * Yarn * pnpm npm test yarn test pnpm test Genere un reporte de la prueba de cobertura: * npm * Yarn * pnpm npm run test:coverage yarn test:coverage pnpm test:coverage O un reporte de la prueba de gas: * npm * Yarn * pnpm npm run test:report-gas yarn test:report-gas pnpm test:report-gas ### Desplegar contratos[​](https://docs.semaphore.pse.dev/es/V3/quick-setup#desplegar-contratos "Enlace directo al encabezado") Siga las instrucciones a continuación para desplegar sus contratos: En la carpeta raíz del proyecto: 1. Agregue sus variables de entorno en el archivo `.env`. nota 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. * npm * Yarn * pnpm npm run deploy -- --semaphore --group --network goerli yarn deploy --semaphore --group --network goerli pnpm deploy --semaphore --group --network goerli nota Revise las direcciones de los contratos de Semaphore [aquí](https://docs.semaphore.pse.dev/es/V3/deployed-contracts) . precaución El group id (id del grupo) es un número. ### Inicie la app[​](https://docs.semaphore.pse.dev/es/V3/quick-setup#inicie-la-app "Enlace directo al encabezado") Inicie la aplicación: * npm * Yarn * pnpm npm run dev yarn dev pnpm dev * [Output](https://docs.semaphore.pse.dev/es/V3/quick-setup#output) * [Uso](https://docs.semaphore.pse.dev/es/V3/quick-setup#uso) * [Compilar contratos](https://docs.semaphore.pse.dev/es/V3/quick-setup#compilar-contratos) * [Pruebe los contratos](https://docs.semaphore.pse.dev/es/V3/quick-setup#pruebe-los-contratos) * [Desplegar contratos](https://docs.semaphore.pse.dev/es/V3/quick-setup#desplegar-contratos) * [Inicie la app](https://docs.semaphore.pse.dev/es/V3/quick-setup#inicie-la-app) --- # FAQ | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/faq#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/faq) ** (V4). Versión: V3 En esta página ¿Qué es Semaphore?[​](https://docs.semaphore.pse.dev/es/V3/faq#qu%C3%A9-es-semaphore "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------------- Semaphore es un protocolo de conocimiento cero (zero-knowledge) que permite a los usuarios demostrar su pertenencia a un grupo y enviar señales como votos, comentarios o mensajes de texto sin revelar la identidad del usuario. Esto significa que las señales no tienen conexión con las identidades. También proporciona un mecanismo simple para evitar la doble señalización, lo que significa que no puede verificar la misma prueba dos veces. ¿Dónde puedo hacer preguntas sobre Semaphore?[​](https://docs.semaphore.pse.dev/es/V3/faq#d%C3%B3nde-puedo-hacer-preguntas-sobre-semaphore "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Puede hacer preguntas sobre Semaphore en [Telegram](https://semaphore.pse.dev/telegram) o abriendo un [Semaphore Discussion](https://github.com/semaphore-protocol/semaphore/discussions) . ¿Por qué las identidades requieren tanto `identity trapdoor` como `identity nullifier`?[​](https://docs.semaphore.pse.dev/es/V3/faq#por-qu%C3%A9-las-identidades-requieren-tanto-identity-trapdoor-como-identity-nullifier "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Tener dos valores privados proporciona una capa de seguridad adicional. Si alguien rompe el hash del nullifier (imagínese que existe cierta maleabilidad de que la preimagen de Poseidón es fácil de encontrar cuando se aplica un hash con un valor específico X, que es el external nullifier elegido por los desarrolladores), el atacante puede encontrar todos los mensajes que envió la misma persona, pero no puede encontrar a quién, porque también está el trapdoor, que podría ser más difícil de romper. ¿Cuál es la diferencia entre `identity nullifier`, `external nullifier` y `nullifier hash`?[​](https://docs.semaphore.pse.dev/es/V3/faq#cu%C3%A1l-es-la-diferencia-entre-identity-nullifier-external-nullifier-y-nullifier-hash "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- El identity nullifier (anulador de identidad) es uno de los valores secretos del usuario, mientras que el external nullifier (anulador externo) se puede utilizar como un tema sobre el que los usuarios pueden generar una prueba válida (por ejemplo, enviar votos anónimos) un número limitado de veces. Tanto el identity nullifier como el external nullifier se utilizan para evitar que la misma prueba se verifique dos veces, lo que significa que si un usuario genera la misma prueba (con la misma identidad y el mismo external nullifier) dos veces, la segunda no será válida. Finalmente, el nullifier hash (hash del anulador) es solo el hash del identity nullifier y el external nullifier que se utiliza para comprobar si ya se ha generado la misma prueba. En el caso de una aplicación de votación, si tiene un grupo y desea que todos los miembros de este grupo voten solo una vez, puede usar la identificación del grupo como external nullifier. Cuando un usuario vota por primera vez, puede guardar el hash de su identity nullifier y la identificación del grupo (es decir, el nullifier hash) y evitar la doble votación comprobando si ese hash ya existe. Vea los [circuitos de Semaphore](https://docs.semaphore.pse.dev/technical-reference/circuits) para más información técnica, o el [Semaphore boilerplate](https://github.com/semaphore-protocol/boilerplate) para un caso de uso real. ¿Por qué debo evitar que las pruebas se verifiquen dos veces?[​](https://docs.semaphore.pse.dev/es/V3/faq#por-qu%C3%A9-debo-evitar-que-las-pruebas-se-verifiquen-dos-veces "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Dado que las pruebas de conocimiento cero son completamente anónimas, es importante evitar que las generadas por identidades elegibles sean reutilizadas por una parte malintencionada. En una aplicación de voto anónimo, por ejemplo, sin chequeos, se podría reutilizar una prueba válida para volver a votar. ¿Dónde puedo encontrar ejemplos de aplicaciones que utilicen Semaphore?[​](https://docs.semaphore.pse.dev/es/V3/faq#d%C3%B3nde-puedo-encontrar-ejemplos-de-aplicaciones-que-utilicen-semaphore "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Puede encontrar algunas aplicaciones que usan Semaphore en [este blog post](https://mirror.xyz/privacy-scaling-explorations.eth/Yi4muh-vzDZmIqJIcM9Mawu2e7jw8MRnwxvhFcyfns8) . ¿Cómo puedo iniciar un proyecto usando Semaphore?[​](https://docs.semaphore.pse.dev/es/V3/faq#c%C3%B3mo-puedo-iniciar-un-proyecto-usando-semaphore "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Hay tres formas de comenzar a usar Semaphore en su proyecto: usando la [Semaphore CLI](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli) , usando el [Semaphore boilerplate](https://github.com/semaphore-protocol/boilerplate) como una plantilla o bifurcándolo, o instalando los paquetes de Semaphore manualmente. ### Semaphore CLI[​](https://docs.semaphore.pse.dev/es/V3/faq#semaphore-cli "Enlace directo al encabezado") Para crear un nuevo proyecto podrías usar `npx` o instalar la [Semaphore CLI](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli) globalmente usando `npm` y entonces crear un nuevo proyecto usando el comando `semaphore create`. Vea [Configuración Rápida](https://docs.semaphore.pse.dev/quick-setup) para más información. Hay tres plantillas soportadas en este momento: `contracts-hardhat`, `monorepo-ethers` y `monorepo-subgraph`. * `contracts-hardhat`: Contiene un caso de uso básico de Semaphore. Viene con un contrato de muestra, una prueba (test) para ese contrato y una tarea (task) de muestra que implementa (deploys) ese contrato. * `monorepo-ethers`: Es una aplicación completa que demuestra un caso de uso básico de Semaphore. Viene con un contrato de muestra, una prueba para ese contrato y una tarea de muestra que implementa ese contrato. También contiene una interfaz para usar el contrato. Esta plantilla usa [Ethers](https://github.com/ethers-io/ethers.js/) por detrás para obtener datos on-chain. * `monorepo-subgraph`: Es lo mismo que la plantilla `monorepo-ethers`, pero usa [The Graph protocol](https://thegraph.com/) por detrás para obtener datos on-chain. La Semaphore CLI también se puede usar para obtener datos de grupo de una red soportada. Hay comandos como: `get-groups`, `get-group`, `get-members`, `get-proofs`: * `get-groups`: Muestra la lista de grupos de una red soportada. * `get-group`: Muestra los datos de un grupo de una red soportada. * `get-members`: Muestra los miembros de un grupo de una red soportada. * `get-proofs`: Muestra las pruebas de un grupo de una red soportada. ### Semaphore boilerplate[​](https://docs.semaphore.pse.dev/es/V3/faq#semaphore-boilerplate "Enlace directo al encabezado") Para crear un proyecto, también puede utilizar el [Semaphore boilerplate](https://github.com/semaphore-protocol/boilerplate) . Puede bifurcarlo o usarlo como plantilla. Las plantillas de la Semaphore CLI y el Semaphore boilerplate contienen el mismo código, que es una aplicación de feedback en la que puede crear una identidad, unirse a un grupo, y enviar su feedback de forma anónima. Son casi lo mismo, la única diferencia es que las plantillas usan CSS para que pueda decidir el framework de CSS o librería que desea usar y el boilerplate usa [ChakraUI](https://chakra-ui.com/) por defecto. También puede probar la aplicación Semaphore boilerplate en vivo aquí: [https://demo.semaphore.pse.dev](https://demo.semaphore.pse.dev/) . ### Instalación manual[​](https://docs.semaphore.pse.dev/es/V3/faq#instalaci%C3%B3n-manual "Enlace directo al encabezado") Alternativamente, también puede instalar todos los paquetes manualmente usando npm o yarn siguiendo la [documentación de Semaphore](https://docs.semaphore.pse.dev/) . ¿Cómo puedo contribuir al protocolo?[​](https://docs.semaphore.pse.dev/es/V3/faq#c%C3%B3mo-puedo-contribuir-al-protocolo "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------------------------------------------------- Hay varias formas de contribuir al protocolo, puede encontrar más información al respecto aquí: [https://github.com/semaphore-protocol#ways-to-contribute](https://github.com/semaphore-protocol#ways-to-contribute) . * [¿Qué es Semaphore?](https://docs.semaphore.pse.dev/es/V3/faq#qu%C3%A9-es-semaphore) * [¿Dónde puedo hacer preguntas sobre Semaphore?](https://docs.semaphore.pse.dev/es/V3/faq#d%C3%B3nde-puedo-hacer-preguntas-sobre-semaphore) * [¿Por qué las identidades requieren tanto `identity trapdoor` como `identity nullifier`?](https://docs.semaphore.pse.dev/es/V3/faq#por-qu%C3%A9-las-identidades-requieren-tanto-identity-trapdoor-como-identity-nullifier) * [¿Cuál es la diferencia entre `identity nullifier`, `external nullifier` y `nullifier hash`?](https://docs.semaphore.pse.dev/es/V3/faq#cu%C3%A1l-es-la-diferencia-entre-identity-nullifier-external-nullifier-y-nullifier-hash) * [¿Por qué debo evitar que las pruebas se verifiquen dos veces?](https://docs.semaphore.pse.dev/es/V3/faq#por-qu%C3%A9-debo-evitar-que-las-pruebas-se-verifiquen-dos-veces) * [¿Dónde puedo encontrar ejemplos de aplicaciones que utilicen Semaphore?](https://docs.semaphore.pse.dev/es/V3/faq#d%C3%B3nde-puedo-encontrar-ejemplos-de-aplicaciones-que-utilicen-semaphore) * [¿Cómo puedo iniciar un proyecto usando Semaphore?](https://docs.semaphore.pse.dev/es/V3/faq#c%C3%B3mo-puedo-iniciar-un-proyecto-usando-semaphore) * [Semaphore CLI](https://docs.semaphore.pse.dev/es/V3/faq#semaphore-cli) * [Semaphore boilerplate](https://docs.semaphore.pse.dev/es/V3/faq#semaphore-boilerplate) * [Instalación manual](https://docs.semaphore.pse.dev/es/V3/faq#instalaci%C3%B3n-manual) * [¿Cómo puedo contribuir al protocolo?](https://docs.semaphore.pse.dev/es/V3/faq#c%C3%B3mo-puedo-contribuir-al-protocolo) --- # Credits | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V1/creditsandresources#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V1**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V1 * 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 --- # Subgrafo | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/subgraph#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/subgraph) ** (V4). Versión: V3 En esta página [The Graph](https://thegraph.com/) es un protocolo para indexar redes como Ethererum o IPFS. Las personas dueñas de los sitios publica _subgrafos_ que exponen los datos del sitio para que cualquiera los pueda consultar. El subgrafo de Semaphore le permite obtener datos del contrato inteligente [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/Semaphore.sol) . tip El protocolo The Graph utiliza el lenguaje de consulta [GraphQL](https://graphql.org/) . Para ver ejemplos visite [GraphQL API documentation](https://thegraph.com/docs/developer/graphql-api) . Para ver la lista de subgrafos de Semaphore visite el [repositorio de subgrafos](https://github.com/semaphore-protocol/subgraph) . Esquema[​](https://docs.semaphore.pse.dev/es/V3/subgraph#esquema "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------- ### Árbol de Merkle[​](https://docs.semaphore.pse.dev/es/V3/subgraph#%C3%A1rbol-de-merkle "Enlace directo al encabezado") * `id`: identificador único entre todas las entidades de árboles de Merkle, * `depth`: profundidad del árbol de Merkle, * `root`: raíz del árbol de Merkle, * `zeroValue`: valor cero del árbol de Merkle, * `numberOfLeaves`: número total de hojas en el árbol, * `group`: link a la entidad del grupo. ### Grupo[​](https://docs.semaphore.pse.dev/es/V3/subgraph#grupo "Enlace directo al encabezado") * `id`: identificador único entre todas las entidades del grupo, * `merkleTree`: link a la entidad del árbol de Merkle, * `timestamp`: timestamp (registro de tiempo) del bloque, * `admin`: administrador del grupo, * `members`: lista de los miembros del grupo, * `verifiedProofs`: lista de las pruebas del grupo. ### Miembro[​](https://docs.semaphore.pse.dev/es/V3/subgraph#miembro "Enlace directo al encabezado") * `id`: identificador único entre todos los miembros, * `identityCommitment`: compromiso de identidad Semaphore, * `timestamp`: timestamp del bloque, * `index`: índice de la hoja del árbol, * `group`: link a la entidad del grupo. ### PruebaVerificada[​](https://docs.semaphore.pse.dev/es/V3/subgraph#pruebaverificada "Enlace directo al encabezado") * `id`: identificador único entre todas las entidades con una prueba verificada (VerifiedProof), * `signal`: señal del usuario, * `merkleTreeRoot`: raíz del árbol de Merkle, * `nullifierHash`: hash nullifier (anulador), * `externalNullifier`: nullifier externo, * `timestamp`: timestamp del bloque, * `group`: link a la entidad del grupo. * [Esquema](https://docs.semaphore.pse.dev/es/V3/subgraph#esquema) * [Árbol de Merkle](https://docs.semaphore.pse.dev/es/V3/subgraph#%C3%A1rbol-de-merkle) * [Grupo](https://docs.semaphore.pse.dev/es/V3/subgraph#grupo) * [Miembro](https://docs.semaphore.pse.dev/es/V3/subgraph#miembro) * [PruebaVerificada](https://docs.semaphore.pse.dev/es/V3/subgraph#pruebaverificada) --- # Circuitos | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/technical-reference/circuits#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/technical-reference/circuits) ** (V4). Versión: V3 En esta página El [circuito Semaphore](https://github.com/semaphore-protocol/semaphore/tree/main/packages/circuits) es el corazón del protocolo y está compuesto por tres partes: * [**Prueba de membresía**](https://docs.semaphore.pse.dev/es/V3/technical-reference/circuits#prueba-de-membres%C3%ADa) * [**Nullifier hash**](https://docs.semaphore.pse.dev/es/V3/technical-reference/circuits#hash-anulador-nullifier-hash) (hash anulador) * [**Señal**](https://docs.semaphore.pse.dev/es/V3/technical-reference/circuits#se%C3%B1al) ![Semaphore circuit](https://github.com/semaphore-protocol/semaphore/raw/main/packages/circuits/scheme.png) El diagrama anterior muestra cómo se utilizan las señales de entrada en el circuito Semaphore y cómo se calculan los resultados. Prueba de membresía[​](https://docs.semaphore.pse.dev/es/V3/technical-reference/circuits#prueba-de-membres%C3%ADa "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------------------------- El circuito resume criptográficamente (hashes) el nullifier hash de la identidad utilizando la identity trapdoor (identidad trampilla) para generar el compromiso de identidad. Después de esto, el circuito verifica la prueba de membresía contra la raíz de Merkle y el compromiso de identidad. **Insumos (inputs) privados:** * `treeSiblings[nLevels]`: los valores a lo largo del camino de Merkle rumbo al compromiso de identidad del usuario, * `treePathIndices[nLevels]`: la dirección (0/1) por nivel del árbol correspondiente al camino de Merkle rumbo al compromiso de identidad del usuario, * `identityNullifier`: la identidad secreta de 32-bits utilizada como anulador, * `identityTrapdoor`: la identidad secreta de 32-bits utilizada como trampilla. **Resultados (outputs) públicos:** * `root`: La raíz de Merkle del árbol. Hash anulador (Nullifier hash)[​](https://docs.semaphore.pse.dev/es/V3/technical-reference/circuits#hash-anulador-nullifier-hash "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------------------------------------------------------- El circuito resume criptográficamente (hashes) el identity nullifier con el nullifier externo y después revisa que el resultado coincida con el nullifier hash provisto. Los nullifier hashes guardados en un contrato inteligente Semaphore permiten que el contrato rechace las pruebas que contengan un nullifier hash ya utilizado. **Insumos (inputs) privados:** * `identityNullifier`: el identity secret (secreto de identidad) de 32 bits que se utiliza como nullifier. **Insumos (inputs) públicos:** * `externalNullifier`: el nullifier externo de 32 bits. **Resultados (outputs) públicos:** * `nullifierHash`: el hash del identity nullifier y del nullifier externo; se utiliza para prevenir que el mismo usuario emita dos señales. **Procedimiento:** Señal[​](https://docs.semaphore.pse.dev/es/V3/technical-reference/circuits#se%C3%B1al "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------- El circuito calcula un cuadrado ficticio del hash de la señal para prevenir que se altere la prueba. **Insumos (inputs) públicos:** * `signalHash`: El hash de la señal del usuario. * [Prueba de membresía](https://docs.semaphore.pse.dev/es/V3/technical-reference/circuits#prueba-de-membres%C3%ADa) * [Hash anulador (Nullifier hash)](https://docs.semaphore.pse.dev/es/V3/technical-reference/circuits#hash-anulador-nullifier-hash) * [Señal](https://docs.semaphore.pse.dev/es/V3/technical-reference/circuits#se%C3%B1al) --- # Obteniendo datos | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/) ** (V4). Versión: V3 En esta página Para obtener datos on-chain del contrato [Semaphore.sol](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) , puedes usar la librería [@semaphore-protocol/data](https://github.com/semaphore-protocol/semaphore/tree/main/packages/data) . Hay dos formas para hacer esto, usando [`SemaphoreSubgraph`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/data/src/subgraph.ts) o [`SemaphoreEthers`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/data/src/ethers.ts) . La clase `SemaphoreSubgraph` usa el [subgrafo de Semaphore](https://github.com/semaphore-protocol/subgraph) , el cual usa [The Graph Protocol](https://thegraph.com/) detrás del telón, y la clase `SemaphoreEthers` usa [Ethers](https://github.com/ethers-io/ethers.js/) . * [**Obtener datos usando SemaphoreSubgraph**](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-datos-usando-semaphoresubgraph) * [**Obtener datos usando SemaphoreEthers**](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-datos-usando-semaphoreethers) Instalar librería[​](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#instalar-librer%C3%ADa "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------------- * npm * Yarn * pnpm npm install @semaphore-protocol/data@^3 yarn add @semaphore-protocol/data@^3 pnpm add @semaphore-protocol/data@^3 Obtener datos usando SemaphoreSubgraph[​](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-datos-usando-semaphoresubgraph "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Para obtener datos usando el subgrafo de Semaphore puedes usar la clase [`SemaphoreSubgraph`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/data/src/subgraph.ts) del paquete [@semaphore-protocol/data](https://github.com/semaphore-protocol/semaphore/tree/main/packages/data) . import { SemaphoreSubgraph } from "@semaphore-protocol/data"const semaphoreSubgraph = new SemaphoreSubgraph()// or:const semaphoreSubgraph = new SemaphoreSubgraph("arbitrum")// or:const semaphoreSubgraph = new SemaphoreSubgraph( "https://api.studio.thegraph.com/query/14377//") ### Obtener Ids de los grupos[​](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-ids-de-los-grupos "Enlace directo al encabezado") const groupIds = await semaphoreSubgraph.getGroupIds() ### Obtener los grupos[​](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-los-grupos "Enlace directo al encabezado") const groups = await semaphoreSubgraph.getGroups()// orconst groups = await semaphoreSubgraph.getGroups({ members: true, verifiedProofs: true }) ### Obtener un grupo[​](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-un-grupo "Enlace directo al encabezado") const group = await semaphoreSubgraph.getGroup("42")// orconst { members, verifiedProofs } = semaphoreSubgraph.getGroup("42", { members: true, verifiedProofs: true }) ### Comprueba si un identity commitment es miembro de un grupo[​](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#comprueba-si-un-identity-commitment-es-miembro-de-un-grupo "Enlace directo al encabezado") await semaphoreSubgraph.isGroupMember( "42", "16948514235341957898454876473214737047419402240398321289450170535251226167324") información Puedes crear un grupo off-chain usando la clase SemaphoreSubgraph para obtener los miembros de la siguiente forma: import { Group } from "@semaphore-protocol/group"import { SemaphoreSubgraph } from "@semaphore-protocol/data"const groupId = "3"const semaphoreSubgraph = new SemaphoreSubgraph("sepolia")const { members } = await semaphoreSubgraph.getGroup(groupId, { members: true })const group = new Group(groupId, 20, members) Obtener datos usando SemaphoreEthers[​](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-datos-usando-semaphoreethers "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Para obtener datos usando Ethers puedes usar la clase [`SemaphoreEthers`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/data/src/ethers.ts) del paquete [@semaphore-protocol/data](https://github.com/semaphore-protocol/semaphore/tree/main/packages/data) . import { SemaphoreEthers } from "@semaphore-protocol/data"const semaphoreEthers = new SemaphoreEthers()// or:const semaphoreEthers = new SemaphoreEthers("homestead", { address: "semaphore-address", startBlock: 0})// or:const semaphoreEthers = new SemaphoreEthers("http://localhost:8545", { address: "semaphore-address"}) ### Obtener Ids de los grupos[​](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-ids-de-los-grupos-1 "Enlace directo al encabezado") const groupIds = await semaphoreEthers.getGroupIds() ### Obtener un grupo[​](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-un-grupo-1 "Enlace directo al encabezado") const group = await semaphoreEthers.getGroup("42") ### Obtener el admin de un grupo[​](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-el-admin-de-un-grupo "Enlace directo al encabezado") const admin = await semaphoreEthers.getGroupAdmin("42") ### Obtener los miembros de un grupo[​](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-los-miembros-de-un-grupo "Enlace directo al encabezado") const members = await semaphoreEthers.getGroupMembers("42") ### Obtener las pruebas verificadas de un grupo[​](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-las-pruebas-verificadas-de-un-grupo "Enlace directo al encabezado") const verifiedProofs = await semaphoreEthers.getGroupVerifiedProofs("42") información Puedes crear un grupo off-chain usando la clase SemaphoreEthers para obtener los miembros de la siguiente forma: import { Group } from "@semaphore-protocol/group"import { SemaphoreEthers } from "@semaphore-protocol/data"const groupId = "3"const semaphoreEthers = new SemaphoreEthers("sepolia")const members = await semaphoreEthers.getGroupMembers(groupId)const group = new Group(groupId, 20, members) * [Instalar librería](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#instalar-librer%C3%ADa) * [Obtener datos usando SemaphoreSubgraph](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-datos-usando-semaphoresubgraph) * [Obtener Ids de los grupos](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-ids-de-los-grupos) * [Obtener los grupos](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-los-grupos) * [Obtener un grupo](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-un-grupo) * [Comprueba si un identity commitment es miembro de un grupo](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#comprueba-si-un-identity-commitment-es-miembro-de-un-grupo) * [Obtener datos usando SemaphoreEthers](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-datos-usando-semaphoreethers) * [Obtener Ids de los grupos](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-ids-de-los-grupos-1) * [Obtener un grupo](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-un-grupo-1) * [Obtener el admin de un grupo](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-el-admin-de-un-grupo) * [Obtener los miembros de un grupo](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-los-miembros-de-un-grupo) * [Obtener las pruebas verificadas de un grupo](https://docs.semaphore.pse.dev/es/V3/guides/fetching-data#obtener-las-pruebas-verificadas-de-un-grupo) --- # Grupos | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/guides/groups#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/guides/groups) ** (V4). Versión: V3 En esta página Un [grupo Semaphore](https://docs.semaphore.pse.dev/es/V3/glossary#grupo-semaphore) contiene los [identity commitments](https://docs.semaphore.pse.dev/es/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. Un grupo Semaphore es un [árbol de Merkle incremental](https://docs.semaphore.pse.dev/es/V3/glossary#%C3%A1rbol-de-merkle-merkle-tree) , y los miembros del grupo (por ejemplo, [identity commitments](https://docs.semaphore.pse.dev/es/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. Aprenda cómo trabajar con grupos. * [**Grupos off-chain**](https://docs.semaphore.pse.dev/es/V3/guides/groups#grupos-off-chain-externos-a-la-cadena) * [**Grupos on-chain**](https://docs.semaphore.pse.dev/es/V3/guides/groups#grupos-on-chain) Grupos off-chain (externos a la cadena)[​](https://docs.semaphore.pse.dev/es/V3/guides/groups#grupos-off-chain-externos-a-la-cadena "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------------------------------------------- * [Crear un grupo](https://docs.semaphore.pse.dev/es/V3/guides/groups#crear-un-grupo) * [Añadir miembros](https://docs.semaphore.pse.dev/es/V3/guides/groups#a%C3%B1adir-miembros) * [Remover o actualizar miembros](https://docs.semaphore.pse.dev/es/V3/guides/groups#remover-o-actualizar-miembros) ### Crear un grupo[​](https://docs.semaphore.pse.dev/es/V3/guides/groups#crear-un-grupo "Enlace directo al encabezado") 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. #### Instalar librería:[​](https://docs.semaphore.pse.dev/es/V3/guides/groups#instalar-librer%C3%ADa "Enlace directo al encabezado") * npm * Yarn * pnpm npm install @semaphore-protocol/group@^3 yarn add @semaphore-protocol/group@^3 pnpm add @semaphore-protocol/group@^3 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: 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: import { Group } from "@semaphore-protocol/group"const group = new Group(1, 30) También puede inicializar un grupo con varios miembros pasando la lista de identity commitments (miembros) como tercer parámetro al crear el grupo: import { Group } from "@semaphore-protocol/group"const members = [ "11237622825477336339577122413451117718539783476837539122310492284566644730311", "9332663527862709610616009715800254142772436825222910251631161087138559093425", "13255821893820536903335282929376140649646180444238593676033702344407594536519"]const group = new Group(1, 20, members) ### Añadir miembros[​](https://docs.semaphore.pse.dev/es/V3/guides/groups#a%C3%B1adir-miembros "Enlace directo al encabezado") Utiliza la función `Group addMember` para añadir un miembro (es decir su "identity commitment") a un grupo. Por ejemplo: group.addMember(identityCommitment) Para añadir un lote de miembros a un grupo, pasa una selección por la función `Group addMembers`. Por ejemplo: group.addMembers([identityCommitment1, identityCommitment2]) precaución Cuando utiliza la misma identidad Semaphore en varios grupos, si un atacante toma control de esa identidad, todos los grupos de los que forma parte estarán comprometidos. Considere utilizar identidades diferentes para cada grupo. ### Remover o actualizar miembros[​](https://docs.semaphore.pse.dev/es/V3/guides/groups#remover-o-actualizar-miembros "Enlace directo al encabezado") Para remover miembros de un equipo, pasa el índice del miembro por la función `Group removeMember`. Por ejemplo: group.removeMember(0) Para actualizar los miembros dentro de un grupo, pasa el índice del miembro y el nuevo valor por la función `Group updateMember`. Por ejemplo: group.updateMember(0, 2) precaución Remover a un miembro de un grupo configura el valor del nodo a un valor especial (ejemplo, `zeroValue`). Dado que ese nodo no se remueve y el largo de la selección de `group.members` no cambia. Grupos on-chain[​](https://docs.semaphore.pse.dev/es/V3/guides/groups#grupos-on-chain "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------- El contrato [`SemaphoreGroups`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/base/SemaphoreGroups.sol) utiliza la librería del [`IncrementalBinaryTree`](https://github.com/privacy-scaling-explorations/zk-kit/blob/main/packages/incremental-merkle-tree.sol/contracts/IncrementalBinaryTree.sol) (árbol binario incremental) y provee métodos para crear y administrar grupos. :::información puede importar el contrato `SemaphoreGroups.sol` y otros contratos Semaphore del módulo NPM [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/contracts) . ::: Alternativamente, puede utilizar un contrato [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) ya desplegado y utilizar sus funciones externas para grupos. precaución `Semaphore.sol` no revisa si un miembro con un identity commitment en específico ya existe en un grupo. Esta revisión se debe realizar off-chain. precaución `Semaphore.sol` incluye un mecanismo para verificar pruebas Semaphore creadas con raíces de árboles de Merkle antiguas. La duración de este mecanismo puede ser definido por el admin en la función `createGroup`. Por lo tanto, los miembros de un grupo pueden continuar generando pruebas válidas incluso después de ser removidos. Para más información ver el issue [#98](https://github.com/semaphore-protocol/semaphore/issues/98) . * [Grupos off-chain (externos a la cadena)](https://docs.semaphore.pse.dev/es/V3/guides/groups#grupos-off-chain-externos-a-la-cadena) * [Crear un grupo](https://docs.semaphore.pse.dev/es/V3/guides/groups#crear-un-grupo) * [Añadir miembros](https://docs.semaphore.pse.dev/es/V3/guides/groups#a%C3%B1adir-miembros) * [Remover o actualizar miembros](https://docs.semaphore.pse.dev/es/V3/guides/groups#remover-o-actualizar-miembros) * [Grupos on-chain](https://docs.semaphore.pse.dev/es/V3/guides/groups#grupos-on-chain) --- # Recursos | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/resources#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/resources) ** (V4). Versión: V3 En esta página Artículos[​](https://docs.semaphore.pse.dev/es/V3/resources#art%C3%ADculos "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------------- [Propuesta de la comunidad: Semaphore: Señalización de conocimiento cero (ZK) en Ethereum (v1 Whitepaper)](https://semaphore.pse.dev/whitepaper-v1.pdf) - Kobi Gurkan, Koh Wei Jie y Barry WhiteHat [Para Mezcladores y más allá: presentando Semaphore, una herramienta de privacidad construida en Ethereum](https://medium.com/coinmonks/to-mixers-and-beyond-presenting-semaphore-a-privacy-gadget-built-on-ethereum-4c8b00857c9b) - Koh Wei Jie [¡La versión 2 de Semaphore está lista!](https://medium.com/privacy-scaling-explorations/semaphore-v2-is-live-f263e9372579) - Privacy and Scaling Explorations Videos[​](https://docs.semaphore.pse.dev/es/V3/resources#videos "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------ [Privacidad en Ethereum](https://www.youtube.com/watch?v=maDHYyj30kg) - Barry WhiteHat en el Meetup de Ethereum en Taipei [Snarks para mezclar, enviar señales y escalabilidad](https://www.youtube.com/watch?v=lv6iK9qezBY) - Barry WhiteHat en Devcon 4 [Privacidad en Ethereum](https://www.youtube.com/watch?v=zBUo7G95wYE) - Barry WhiteHat en Devcon 5 [Un mezclador de Ethereum trustless utilizando señalizaciones de conocimiento cero (ZK)](https://www.youtube.com/watch?v=GzVT16lFOHU) - Koh Wei Jie y Barry WhiteHat en Devcon 5 [Implementación de aplicaciones de señalizaciones de conocimiento cero (ZK)](https://www.youtube.com/watch?v=7wd2aAN2jXI) - Koh Wei Jie en Devcon 5 [Roadmap para Semaphore en Ethereum](https://www.youtube.com/watch?v=gOub903iWFs) - Barry WhiteHat en Zcon1 [Pruebas concisas en Ethereum](https://www.youtube.com/watch?v=TtsDNneTDDY) - Barry WhiteHat en el 2ndo ZKProof Workshop [Propuesta: Semaphore - Señalización de conocimiento cero (ZK) en Ethereum](https://www.youtube.com/watch?v=y5uV9eRb3-w) - Kobi Gurkan y Koh Wei Jie en el ZKProof Home Edition [Señalizaciones anónimas en Ethereum](https://www.youtube.com/watch?v=dxAfL91Sbw4) - Cedoor en Devcon 6 Bogotá * [Artículos](https://docs.semaphore.pse.dev/es/V3/resources#art%C3%ADculos) * [Videos](https://docs.semaphore.pse.dev/es/V3/resources#videos) --- # Contratos | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/technical-reference/contracts#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/technical-reference/contracts) ** (V4). Versión: V3 En esta página Semaphore incluye dos tipos de contratos: * [**Contratos base**](https://docs.semaphore.pse.dev/es/V3/technical-reference/contracts#contratos-base) * [**Contratos para la extensión**](https://docs.semaphore.pse.dev/es/V3/technical-reference/contracts#contratos-para-la-extensi%C3%B3n) así como [**Semaphore.sol**](https://docs.semaphore.pse.dev/es/V3/technical-reference/contracts#semaphoresol) , el principal contrato desplegado en las redes soportadas por Semaphore. información Para utilizar los contratos e interfaces Semaphore en su proyecto, instale el paquete NPM [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/contracts) . Contratos base[​](https://docs.semaphore.pse.dev/es/V3/technical-reference/contracts#contratos-base "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------ Semaphore ofrece los siguientes contratos base: * [`SemaphoreVerifier.sol`](https://github.com/semaphore-protocol/semaphore/blob/v3.15.2/packages/contracts/contracts/base/SemaphoreVerifier.sol) : contiene una función para verificar pruebas Semaphore; * [`SemaphoreGroups.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/base/SemaphoreGroups.sol) : contiene las funciones para crear grupos y añadir/remover/actualizar miembros. Los contratos base están relacionados de forma muy cercana al protocolo. Puede utilizarlos en su contrato o puede utilizar [**Semaphore.sol**](https://docs.semaphore.pse.dev/es/V3/technical-reference/contracts#semaphoresol) que ya los tiene integrados. información Si bien algunas dApps pueden utilizar grupos internos a la cadena, otros puede que prefieran utilizar grupos externos a la cadena, por lo que únicamente guardarán las raíces de sus árboles en el contrato. Contratos para la extensión[​](https://docs.semaphore.pse.dev/es/V3/technical-reference/contracts#contratos-para-la-extensi%C3%B3n "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------------------------------- * [`SemaphoreVoting.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/extensions/SemaphoreVoting.sol) : contrato para votaciones que contiene las funciones esenciales para crear encuestas, añadir electores, y emitir votos de forma anónima; * [`SemaphoreWhistleblowing.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/extensions/SemaphoreWhistleblowing.sol) : contrato para denuncias que contiene las funciones esenciales para crear entidades (por ejemplo: organizaciones sin fines de lucro), añade denunciantes, y filtraciones publicadas de forma anónima. Estos contratos extienden las capacidades del protocolo y proveen una aplicación lógica para casos de uso específicos. En un futuro se incluirán más extensiones. Semaphore.sol[​](https://docs.semaphore.pse.dev/es/V3/technical-reference/contracts#semaphoresol "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------------------------- [`Semaphore.sol`](https://github.com/semaphore-protocol/semaphore/blob/main/packages/contracts/contracts/Semaphore.sol) utiliza los contratos base como punto de partida, los integra y de forma adicional brinda: * un sistema que solamente permite que administradores (ej. cuentas de Ethereum o contratos inteligentes) controlen grupos; * un mecanismo que guarda los [hashes anuladores](https://docs.semaphore.pse.dev/es/V3/technical-reference/circuits#hash-anulador-nullifier-hash) (nullifier hashes) de cada grupo y evita que el mismo miembro emita dos señales; * un mecanismo que permite que pruebas Semaphore generadas con raíces de Merkle antiguas sean verificadas por un periodo de tiempo determinado por el administrador del grupo. información Visitando [contratos desplegados](https://docs.semaphore.pse.dev/es/V3/deployed-contracts) puede encontrar las direcciones correspondientes a su red. * [Contratos base](https://docs.semaphore.pse.dev/es/V3/technical-reference/contracts#contratos-base) * [Contratos para la extensión](https://docs.semaphore.pse.dev/es/V3/technical-reference/contracts#contratos-para-la-extensi%C3%B3n) * [Semaphore.sol](https://docs.semaphore.pse.dev/es/V3/technical-reference/contracts#semaphoresol) --- # Identidades | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/guides/identities#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/guides/identities) ** (V4). Versión: V3 En esta página Para unirse a un [grupo Semaphore](https://docs.semaphore.pse.dev/es/V3/glossary#grupo-semaphore) , un usuario primero deberá crear una [identidad Semaphore](https://docs.semaphore.pse.dev/es/V3/glossary#identidad-semaphore) . Una identidad Semaphore contiene dos valores generados junto con la 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[​](https://docs.semaphore.pse.dev/es/V3/guides/identities#crear-identidades "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------ 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**](https://docs.semaphore.pse.dev/es/V3/guides/identities#crear-identidades-aleatorias) * [**Crear identidades determinísticas**](https://docs.semaphore.pse.dev/es/V3/guides/identities#crear-identidades-determin%C3%ADsticas) ### Instalar librería:[​](https://docs.semaphore.pse.dev/es/V3/guides/identities#instalar-librer%C3%ADa "Enlace directo al encabezado") * npm * Yarn * pnpm npm install @semaphore-protocol/identity@^3 yarn add @semaphore-protocol/identity@^3 pnpm add @semaphore-protocol/identity@^3 ### Crear identidades aleatorias[​](https://docs.semaphore.pse.dev/es/V3/guides/identities#crear-identidades-aleatorias "Enlace directo al encabezado") Para crear una identidad aleatoria, represente `Identity` sin algún parámetro. Por ejemplo: import { Identity } from "@semaphore-protocol/identity"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). 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 Ethereum y se utilizan para generar pruebas de conocimiento cero (ZKP) Semaphore y autenticar señales. ### Crear identidades determinísticas[​](https://docs.semaphore.pse.dev/es/V3/guides/identities#crear-identidades-determin%C3%ADsticas "Enlace directo al encabezado") Si transmite un mensaje como un parámetro, Semaphore genera `trapdoor` y `nullifier` 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. Dado que el hash es determinístico, cualquier persona con el mismo mensaje puede recrear la misma identidad. const identity = new Identity("secret-message") tip Crear un sistema que guarde o recupere valores secretos de identidades Semaphore no es trivial. Puede elegir delegar este tipo de funcionalidad a carteras existente como Metamask. Por ejemplo: 1. En Metamask, un usuario firma un mensaje con la llave privada de su cuenta Ethereum. 2. En la aplicación que usted ofrece, el usuario crea una identidad determinística con el mensaje firmado. 3. Ahora el usuario puede recrear su identidad Semaphore cuando quiera al firmar el mismo mensaje con su cuenta Ethereum en Metamask. Guarde sus identidades[​](https://docs.semaphore.pse.dev/es/V3/guides/identities#guarde-sus-identidades "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------------------------- Puede generar una identidad como una cadena de caractéres JSON que puede guardar y reutilizar más tarde. El método `Identity.toString()` genera una matriz JSON a partir de una identidad. Por ejemplo: console.log(identity.toString()) // Ver la identidad trampilla y anulador.// '["8255d...", "62c41..."]' La matriz contiene la trapdoor y el nullifier. Para reutilizar la identidad guardada, transforme la cadena JSON al constructor `Identity()`. const identity2 = new Identity(identity.toString()) * [Crear identidades](https://docs.semaphore.pse.dev/es/V3/guides/identities#crear-identidades) * [Instalar librería:](https://docs.semaphore.pse.dev/es/V3/guides/identities#instalar-librer%C3%ADa) * [Crear identidades aleatorias](https://docs.semaphore.pse.dev/es/V3/guides/identities#crear-identidades-aleatorias) * [Crear identidades determinísticas](https://docs.semaphore.pse.dev/es/V3/guides/identities#crear-identidades-determin%C3%ADsticas) * [Guarde sus identidades](https://docs.semaphore.pse.dev/es/V3/guides/identities#guarde-sus-identidades) --- # Resources | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/resources#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página Articles[​](https://docs.semaphore.pse.dev/es/resources#articles "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------- Videos[​](https://docs.semaphore.pse.dev/es/resources#videos "Enlace directo al encabezado") --------------------------------------------------------------------------------------------- * [Articles](https://docs.semaphore.pse.dev/es/resources#articles) * [Videos](https://docs.semaphore.pse.dev/es/resources#videos) --- # Benchmarks | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/benchmarks#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página Semaphore v4 introduces new features and performance improvements. Detailed changes are available in the [release changelog](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) . The primary changes in benchmark values are driven by the two major protocol updates: * New [Identity schema](https://github.com/semaphore-protocol/semaphore/tree/main/packages/identity) . * [LeanIMT](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/lean-imt) : New optimized IMT. New Identity schema[​](https://docs.semaphore.pse.dev/es/benchmarks#new-identity-schema "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------ Semaphore v4 includes a new schema for the identities allowing the creation and verification of signatures. Although the new Identity package is slightly slower than the one in Semaphore v3 (by just a few milliseconds), the trade-off is minimal considering the included functionality. The new identity schema adds additional constraints to the Semaphore v4 circuit; however, this does not negatively impact overall performance of the protocol. LeanIMT[​](https://docs.semaphore.pse.dev/es/benchmarks#leanimt "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------ Semaphore v4 uses the LeanIMT data structure for group operations, an improvement over the IMT used in v3. For further details, see the [LeanIMT paper](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/papers/leanimt) . The LeanIMT offers dynamic depth, resulting in faster and more cost-effective group operations, across Node.js, browser and smart contracts. Semaphore v4 support tree depths from 1 to 32, while v3 supports depths from 16 to 32, both for proof generation and verification. System Specifications and Software environment[​](https://docs.semaphore.pse.dev/es/benchmarks#system-specifications-and-software-environment "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ All the benchmarks were run in an environment with these properties: **System Specifications** Computer: MacBook Pro Chip: Apple M2 Pro Memory (RAM): 16 GB Operating System: macOS Sequoia version 15.6.1 **Software environment** Node.js version: 23.10.0 Browser: Google Chrome Version 139.0.7258.156 (Official Build) (arm64) Running the benchmarks[​](https://docs.semaphore.pse.dev/es/benchmarks#running-the-benchmarks "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------ ### Javascript and Circom[​](https://docs.semaphore.pse.dev/es/benchmarks#javascript-and-circom "Enlace directo al encabezado") GitHub repository to the run Node.js, browser and Circom benchmarks: [https://github.com/vplasencia/semaphore-benchmarks](https://github.com/vplasencia/semaphore-benchmarks) ### Solidity[​](https://docs.semaphore.pse.dev/es/benchmarks#solidity "Enlace directo al encabezado") GitHub repository to run the Solidity benchmarks: [https://github.com/semaphore-protocol/semaphore](https://github.com/semaphore-protocol/semaphore) Semaphore V3 benchmarks were obtained using the code from the latest v3 Git tag (`v3.15.2`), with the Solidity optimizer enabled. Node.js benchmarks[​](https://docs.semaphore.pse.dev/es/benchmarks#nodejs-benchmarks "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------------- ### Identities[​](https://docs.semaphore.pse.dev/es/benchmarks#identities "Enlace directo al encabezado") ![Identities](https://docs.semaphore.pse.dev/es/assets/images/identity-node-benchmarks-73a0da49aea3d81c4a70a1c75af393b1.png) ### Create Group[​](https://docs.semaphore.pse.dev/es/benchmarks#create-group "Enlace directo al encabezado") Create group, either empty or with initial members. ![Create Group](https://docs.semaphore.pse.dev/es/assets/images/create-group-node-benchmarks-d36698d62e7cd6fa2f59cd219f74fc96.png) ### Add Member[​](https://docs.semaphore.pse.dev/es/benchmarks#add-member "Enlace directo al encabezado") Add a member to groups with different sizes. ![Add Member](https://docs.semaphore.pse.dev/es/assets/images/add-member-node-benchmarks-434e75a259cca8039ab7acf30007a575.png) ### Generate Proof[​](https://docs.semaphore.pse.dev/es/benchmarks#generate-proof "Enlace directo al encabezado") Generate a proof using groups with different numbers of members. ![Generate Proof](https://docs.semaphore.pse.dev/es/assets/images/generate-proof-node-benchmarks-df8b967ee3ac32e73b57cb2723ea7def.png) ### Verify Proof[​](https://docs.semaphore.pse.dev/es/benchmarks#verify-proof "Enlace directo al encabezado") Verify a proof using groups with different numbers of members. ![Verify Proof](https://docs.semaphore.pse.dev/es/assets/images/verify-proof-node-benchmarks-116947cf0638739cd268155181fd704c.png) Browser benchmarks[​](https://docs.semaphore.pse.dev/es/benchmarks#browser-benchmarks "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------- Main functions used in the browser. ![Browser benchmarks](https://docs.semaphore.pse.dev/es/assets/images/browser-benchmarks-0945d64a0e6fdba3be13253bd7886b34.png) Circuit benchmarks[​](https://docs.semaphore.pse.dev/es/benchmarks#circuit-benchmarks "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------- Tree depth = 20 ### Semaphore V3[​](https://docs.semaphore.pse.dev/es/benchmarks#semaphore-v3 "Enlace directo al encabezado") ![Circuit benchmarks Semaphore v3](https://docs.semaphore.pse.dev/es/assets/images/semaphore-v3-circuits-benchmarks-81bc99a2f1cb3d8cfc337f0e8ed52921.png) ### Semaphore V4[​](https://docs.semaphore.pse.dev/es/benchmarks#semaphore-v4 "Enlace directo al encabezado") ![Circuit benchmarks Semaphore v4](https://docs.semaphore.pse.dev/es/assets/images/semaphore-v4-circuits-benchmarks-0d13501bebb6af5cdccbfc0ec7ab109e.png) Contracts[​](https://docs.semaphore.pse.dev/es/benchmarks#contracts "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------- ![Contract Benchmarks](https://docs.semaphore.pse.dev/es/assets/images/contract-benchmarks-149ef9bc7091c6f660ea60e792cfccbc.png) ### Semaphore V3 gas report[​](https://docs.semaphore.pse.dev/es/benchmarks#semaphore-v3-gas-report "Enlace directo al encabezado") ![Contracts benchmarks Semaphore v3](https://docs.semaphore.pse.dev/es/assets/images/semaphore-v3-contracts-benchmarks-eec7051de6fa442b4f6b9bb9e285dc50.png) ### Semaphore V4 gas report[​](https://docs.semaphore.pse.dev/es/benchmarks#semaphore-v4-gas-report "Enlace directo al encabezado") ![Contracts benchmarks Semaphore v4](https://docs.semaphore.pse.dev/es/assets/images/semaphore-v4-contracts-benchmarks-6cdd95e0eff3900dbf026165b28d50cb.png) * [New Identity schema](https://docs.semaphore.pse.dev/es/benchmarks#new-identity-schema) * [LeanIMT](https://docs.semaphore.pse.dev/es/benchmarks#leanimt) * [System Specifications and Software environment](https://docs.semaphore.pse.dev/es/benchmarks#system-specifications-and-software-environment) * [Running the benchmarks](https://docs.semaphore.pse.dev/es/benchmarks#running-the-benchmarks) * [Javascript and Circom](https://docs.semaphore.pse.dev/es/benchmarks#javascript-and-circom) * [Solidity](https://docs.semaphore.pse.dev/es/benchmarks#solidity) * [Node.js benchmarks](https://docs.semaphore.pse.dev/es/benchmarks#nodejs-benchmarks) * [Identities](https://docs.semaphore.pse.dev/es/benchmarks#identities) * [Create Group](https://docs.semaphore.pse.dev/es/benchmarks#create-group) * [Add Member](https://docs.semaphore.pse.dev/es/benchmarks#add-member) * [Generate Proof](https://docs.semaphore.pse.dev/es/benchmarks#generate-proof) * [Verify Proof](https://docs.semaphore.pse.dev/es/benchmarks#verify-proof) * [Browser benchmarks](https://docs.semaphore.pse.dev/es/benchmarks#browser-benchmarks) * [Circuit benchmarks](https://docs.semaphore.pse.dev/es/benchmarks#circuit-benchmarks) * [Semaphore V3](https://docs.semaphore.pse.dev/es/benchmarks#semaphore-v3) * [Semaphore V4](https://docs.semaphore.pse.dev/es/benchmarks#semaphore-v4) * [Contracts](https://docs.semaphore.pse.dev/es/benchmarks#contracts) * [Semaphore V3 gas report](https://docs.semaphore.pse.dev/es/benchmarks#semaphore-v3-gas-report) * [Semaphore V4 gas report](https://docs.semaphore.pse.dev/es/benchmarks#semaphore-v4-gas-report) --- # Deployed contracts | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/deployed-contracts#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 Sepolia ------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://sepolia.etherscan.io/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://sepolia.etherscan.io/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://sepolia.etherscan.io/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Ethereum -------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://etherscan.io/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://etherscan.io/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://etherscan.io/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Arbitrum-sepolia ---------------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://sepolia.arbiscan.io/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://sepolia.arbiscan.io/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://sepolia.arbiscan.io/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Optimism-sepolia ---------------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://sepolia-optimism.etherscan.io/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://sepolia-optimism.etherscan.io/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://sepolia-optimism.etherscan.io/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Matic-amoy ---------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://amoy.polygonscan.com/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://amoy.polygonscan.com/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://amoy.polygonscan.com/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Arbitrum -------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://arbiscan.io/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://arbiscan.io/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://arbiscan.io/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Matic ----- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://polygonscan.com/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://polygonscan.com/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://polygonscan.com/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Optimism -------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://optimistic.etherscan.io/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://optimistic.etherscan.io/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://optimistic.etherscan.io/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Base-sepolia ------------ * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://sepolia.basescan.org/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://sepolia.basescan.org/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://sepolia.basescan.org/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Linea-sepolia ------------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://sepolia.lineascan.build/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://sepolia.lineascan.build/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://sepolia.lineascan.build/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Base ---- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://basescan.org/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://basescan.org/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://basescan.org/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Linea ----- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://lineascan.build/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://lineascan.build/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://lineascan.build/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) Scroll-sepolia -------------- * SemaphoreVerifier: [0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8](https://sepolia.scrollscan.com/address/0x4DeC9E3784EcC1eE002001BfE91deEf4A48931f8) * PoseidonT3: [0xB43122Ecb241DD50062641f089876679fd06599a](https://sepolia.scrollscan.com/address/0xB43122Ecb241DD50062641f089876679fd06599a) * Semaphore: [0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D](https://sepolia.scrollscan.com/address/0x8A1fd199516489B0Fb7153EB5f075cDAC83c693D) --- # Pruebas | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/guides/proofs#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/guides/proofs) ** (V4). Versión: V3 En esta página Una vez que un usuario liga su [identidad Semaphore](https://docs.semaphore.pse.dev/es/V3/glossary#identidad-semaphore) a un [grupo Semaphore](https://docs.semaphore.pse.dev/es/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. Las y los desarrolladores pueden utilizar Semaphore para realizar las siguientes acciones: * [**Generar una prueba externa a la cadena (off-chain)**](https://docs.semaphore.pse.dev/es/V3/guides/proofs#generar-una-prueba-off-chain) * [**Verificar una prueba externa a la cadena (off-chain)**](https://docs.semaphore.pse.dev/es/V3/guides/proofs#verificar-una-prueba-off-chain) * [**Verificar una prueba interna a la cadena (on-chain)**](https://docs.semaphore.pse.dev/es/V3/guides/proofs#verificar-una-prueba-on-chain) Generar una prueba off-chain[​](https://docs.semaphore.pse.dev/es/V3/guides/proofs#generar-una-prueba-off-chain "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------------------------------ 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](https://docs.semaphore.pse.dev/es/V3/glossary#archivos-confiables-de-configuraci%C3%B3n-trusted-setup-files) . #### Instalar librería:[​](https://docs.semaphore.pse.dev/es/V3/guides/proofs#instalar-librer%C3%ADa "Enlace directo al encabezado") * npm * Yarn * pnpm npm install @semaphore-protocol/proof@^3 yarn add @semaphore-protocol/proof@^3 pnpm add @semaphore-protocol/proof@^3 En el caso de uso de un sistema de votación, una vez que todos los votantes hayan ligado sus [identidades](https://docs.semaphore.pse.dev/es/V3/guides/identities#crear-identidades) al [grupo](https://docs.semaphore.pse.dev/es/V3/guides/groups) de la votación, un votante puede generar una prueba para votar por una propuesta. En el llamado para `generateProof`(generar la prueba), el sistema de votación envía el ID único de la votación (la raíz del [árbol de Merkle](https://docs.semaphore.pse.dev/es/V3/glossary#%C3%A1rbol-de-merkle-merkle-tree) del grupo) como el `externalNullifier` para impedir que el votante emita más de una señal para esta votación. La siguiente muestra de código demuestra cómo utilizar `generateProof` para generar una prueba de votación: import { generateProof } from "@semaphore-protocol/proof"const externalNullifier = group.rootconst signal = 1const fullProof = await generateProof(identity, group, externalNullifier, signal, { zkeyFilePath: "./semaphore.zkey", wasmFilePath: "./semaphore.wasm"}) información Si estás generando la prueba en el lado del cliente, puedes evitar agregar los artefactos de snark porque se obtienen automáticamente: const fullProof = await generateProof(identity, group, externalNullifier, signal) Verificar una prueba off-chain[​](https://docs.semaphore.pse.dev/es/V3/guides/proofs#verificar-una-prueba-off-chain "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------------------------------------- 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. La siguiente muestra de código demuestra cómo verificar la prueba generada previamente: import { verifyProof } from "@semaphore-protocol/proof"await verifyProof(fullProof, 20) // verdadero o falso. `verifyProof` devolverá una Promesa que determina uno de los dos valores `verdadero` o `falso`. Verificar una prueba on-chain[​](https://docs.semaphore.pse.dev/es/V3/guides/proofs#verificar-una-prueba-on-chain "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------------------------- Utilice el contrato [`Semaphore.sol`](https://docs.semaphore.pse.dev/es/V3/technical-reference/contracts#semaphoresol) para verificar pruebas on-chain. información Vea nuestros [contratos desplegados](https://docs.semaphore.pse.dev/es/V3/deployed-contracts) para encontrar las direcciones adecuadas para su red. 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. información 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) . * [Generar una prueba off-chain](https://docs.semaphore.pse.dev/es/V3/guides/proofs#generar-una-prueba-off-chain) * [Verificar una prueba off-chain](https://docs.semaphore.pse.dev/es/V3/guides/proofs#verificar-una-prueba-off-chain) * [Verificar una prueba on-chain](https://docs.semaphore.pse.dev/es/V3/guides/proofs#verificar-una-prueba-on-chain) --- # Glossary | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/glossary#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página Identity[​](https://docs.semaphore.pse.dev/es/glossary#identity "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------ The identity of a user in the Semaphore protocol. A Semaphore identity consists of an [EdDSA](https://en.wikipedia.org/wiki/EdDSA) public/private key pair and a [commitment](https://docs.semaphore.pse.dev/es/glossary#identity-commitment) . Semaphore uses an [EdDSA](https://github.com/privacy-scaling-explorations/zk-kit/tree/main/packages/eddsa-poseidon) implementation based on [Baby Jubjub](https://eips.ethereum.org/EIPS/eip-2494) and [Poseidon](https://www.poseidon-hash.info/) . Identity commitment[​](https://docs.semaphore.pse.dev/es/glossary#identity-commitment "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------- The public [Semaphore identity](https://docs.semaphore.pse.dev/es/glossary#identity) value used in [Semaphore groups](https://docs.semaphore.pse.dev/es/glossary#group) . Semaphore uses the [Poseidon](https://www.poseidon-hash.info/) hash function to create the identity commitment from the Semaphore identity public key. Group[​](https://docs.semaphore.pse.dev/es/glossary#group "Enlace directo al encabezado") ------------------------------------------------------------------------------------------ A group is a [Merkle tree](https://docs.semaphore.pse.dev/es/glossary#merkle-tree) in which each leaf is an [identity commitment](https://docs.semaphore.pse.dev/es/glossary#identity-commitment) for a user. Semaphore uses the [LeanIMT](https://zkkit.pse.dev/classes/_zk_kit_lean_imt.LeanIMT.html) implementation, which is an optimized binary incremental Merkle tree. The tree nodes are calculated using [Poseidon](https://www.poseidon-hash.info/) . Merkle tree[​](https://docs.semaphore.pse.dev/es/glossary#merkle-tree "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------ A [tree](https://en.wikipedia.org/wiki/Merkle_tree) in which every leaf (i.e., a node that doesn't have children) is labelled with the cryptographic hash of a data block, and every node that isn't a leaf is labelled with the cryptographic hash of its child node labels. In zero-knowledge protocols, Merkle trees can be used to efficiently summarize and validate large data sets. To validate that a tree contains a specific leaf, a verifier only needs a portion of the complete data structure. Scope[​](https://docs.semaphore.pse.dev/es/glossary#scope "Enlace directo al encabezado") ------------------------------------------------------------------------------------------ A value used like a topic on which users can generate a valid proof only once. The scope is supposed to be used to generate the [nullifier](https://docs.semaphore.pse.dev/es/glossary#nullifier) . Nullifier[​](https://docs.semaphore.pse.dev/es/glossary#nullifier "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------- A value designed to be a unique identifier and used to prevent the same zero-knowledge proof from being used twice. In Semaphore, the nullifier is the hash of the scope and private key of the user's Semaphore identity. Message[​](https://docs.semaphore.pse.dev/es/glossary#message "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------- The term "message" in Semaphore refers to the value the user broadcasts when voting, confirming, sending a text message and so on. Relay[​](https://docs.semaphore.pse.dev/es/glossary#relay "Enlace directo al encabezado") ------------------------------------------------------------------------------------------ A third-party who could receive a fee for including relayed transactions in the blockchain (McMenamin, Daza, and Fitz. [https://eprint.iacr.org/2022/155.pdf](https://eprint.iacr.org/2022/155.pdf) , p.3). To preserve the anonymity of the user broadcasting a message with Semaphore, an application may use a relayer to send the transaction to Ethereum on behalf of the user. Trusted setup[​](https://docs.semaphore.pse.dev/es/glossary#trusted-setup "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------- A trusted setup in the context of zero-knowledge proofs, particularly zk-SNARKs, is a preparatory phase where [certain parameters](https://docs.semaphore.pse.dev/es/glossary#trusted-setup-files) are generated for later use in creating and verifying proofs. This process must be conducted by trusted parties, as any retained secret information (toxic waste) could compromise the system's integrity by enabling the creation of false proofs. Trusted setup files[​](https://docs.semaphore.pse.dev/es/glossary#trusted-setup-files "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------- The secure, verifiable parameters generated by Semaphore's trusted setup ceremony. Semaphore uses the trusted setup files to generate and verify valid zero-knowledge proofs. The [Semaphore circuit](https://docs.semaphore.pse.dev/es/technical-reference/circuits) includes a parameter to set the tree's maximum depth (MAX\_DEPTH). During the trusted setup, parameters are specifically generated for each circuit instance, aligning with their designated MAX\_DEPTH (from 1 to 32). * [Identity](https://docs.semaphore.pse.dev/es/glossary#identity) * [Identity commitment](https://docs.semaphore.pse.dev/es/glossary#identity-commitment) * [Group](https://docs.semaphore.pse.dev/es/glossary#group) * [Merkle tree](https://docs.semaphore.pse.dev/es/glossary#merkle-tree) * [Scope](https://docs.semaphore.pse.dev/es/glossary#scope) * [Nullifier](https://docs.semaphore.pse.dev/es/glossary#nullifier) * [Message](https://docs.semaphore.pse.dev/es/glossary#message) * [Relay](https://docs.semaphore.pse.dev/es/glossary#relay) * [Trusted setup](https://docs.semaphore.pse.dev/es/glossary#trusted-setup) * [Trusted setup files](https://docs.semaphore.pse.dev/es/glossary#trusted-setup-files) --- # FAQ | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/faq#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página Where can I ask questions about Semaphore?[​](https://docs.semaphore.pse.dev/es/faq#where-can-i-ask-questions-about-semaphore "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------------------------------------- You can ask questions about Semaphore on [Telegram](https://semaphore.pse.dev/telegram) or by opening a [Semaphore Discussion](https://github.com/semaphore-protocol/semaphore/discussions) . The most frequent questions will be listed below. Why should I prevent proofs from being verified twice?[​](https://docs.semaphore.pse.dev/es/faq#why-should-i-prevent-proofs-from-being-verified-twice "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Since zero-knowledge proofs are completely anonymous, it is important to prevent those generated by eligible identities from being reused by a malicious party. For example, in an anonymous voting application a valid proof could be reused to vote again. What is the difference between the "nullifier" and "scope"?[​](https://docs.semaphore.pse.dev/es/faq#what-is-the-difference-between-the-nullifier-and-scope "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- The [scope](https://docs.semaphore.pse.dev/es/glossary#scope) is used like a topic on which users can generate a valid proof only once. The scope is a public value and every one can see what the scope of a proof is. The [nullifier](https://docs.semaphore.pse.dev/es/glossary#nullifier) is the hash of the private key of the identity and the scope, and it is used to check if the same proof with that specific scope has already been generated by the same user. The nullifier is also a public value and it is what is actually stored to prevent, for example, double-voting. In the case of a voting application, if you have a group and you want all members of this group to vote only once, you can use the id of the group as the scope. When a user votes the first time, you can store the hash of voter's private key and the group id (i.e., the nullifier) and prevent double-voting by checking if that hash already exists. See the [Semaphore circuits](https://docs.semaphore.pse.dev/es/technical-reference/circuits) for more technical information, or the [Semaphore boilerplate](https://github.com/semaphore-protocol/boilerplate/tree/main) for a real use-case. Where can I find examples of applications using Semaphore?[​](https://docs.semaphore.pse.dev/es/faq#where-can-i-find-examples-of-applications-using-semaphore "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- You can find a complete list of applications that are using Semaphore on the [Semaphore website](https://semaphore.pse.dev/projects) . How can I start a project using Semaphore?[​](https://docs.semaphore.pse.dev/es/faq#how-can-i-start-a-project-using-semaphore "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------------------------------------- There are three ways you can start using Semaphore in your project: using the [CLI](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli) , using the [boilerplate](https://github.com/semaphore-protocol/boilerplate/tree/main) as a template or forking it, or installing the Semaphore [packages](https://docs.semaphore.pse.dev/es/guides/identities) manually. How can I contribute to the protocol?[​](https://docs.semaphore.pse.dev/es/faq#how-can-i-contribute-to-the-protocol "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------------------------------------- There are several ways you could contribute to the protocol, you can find more information about on [Github](https://github.com/semaphore-protocol#ways-to-contribute) . * [Where can I ask questions about Semaphore?](https://docs.semaphore.pse.dev/es/faq#where-can-i-ask-questions-about-semaphore) * [Why should I prevent proofs from being verified twice?](https://docs.semaphore.pse.dev/es/faq#why-should-i-prevent-proofs-from-being-verified-twice) * [What is the difference between the "nullifier" and "scope"?](https://docs.semaphore.pse.dev/es/faq#what-is-the-difference-between-the-nullifier-and-scope) * [Where can I find examples of applications using Semaphore?](https://docs.semaphore.pse.dev/es/faq#where-can-i-find-examples-of-applications-using-semaphore) * [How can I start a project using Semaphore?](https://docs.semaphore.pse.dev/es/faq#how-can-i-start-a-project-using-semaphore) * [How can I contribute to the protocol?](https://docs.semaphore.pse.dev/es/faq#how-can-i-contribute-to-the-protocol) --- # Groups | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V2/guides/groups#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V2**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/guides/groups) ** (V4). Versión: V2 En esta página Use Semaphore in your application or smart contract to create off-chain and on-chain groups. A [Semaphore group](https://docs.semaphore.pse.dev/es/V2/glossary#semaphore-group) contains [identity commitments](https://docs.semaphore.pse.dev/es/V2/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. A Semaphore group is an [incremental Merkle tree](https://docs.semaphore.pse.dev/es/V2/glossary#merkle-tree) , and group members (i.e., identity commitments) are tree leaves. Semaphore groups set the following two parameters: * **Tree depth**: the maximum number of members a group can contain (`max size = 2 ^ tree depth`). * **Zero value**: the value used to calculate the zero nodes of the incremental Merkle tree. Learn how to work with groups. * [**Off-chain groups**](https://docs.semaphore.pse.dev/es/V2/guides/groups#off-chain-groups) * [**On-chain groups**](https://docs.semaphore.pse.dev/es/V2/guides/groups#on-chain-groups) Off-chain groups[​](https://docs.semaphore.pse.dev/es/V2/guides/groups#off-chain-groups "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------------------------------ * [Create a group](https://docs.semaphore.pse.dev/es/V2/guides/groups#create-a-group) * [Add members](https://docs.semaphore.pse.dev/es/V2/guides/groups#add-members) * [Remove or update members](https://docs.semaphore.pse.dev/es/V2/guides/groups#remove-or-update-members) ### Create a group[​](https://docs.semaphore.pse.dev/es/V2/guides/groups#create-a-group "Enlace directo al encabezado") Use the [`@semaphore-protocol/group`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/group) library `Group` class to create an off-chain group. #### Options[​](https://docs.semaphore.pse.dev/es/V2/guides/groups#options "Enlace directo al encabezado") * **Tree depth**: (_default `20`_) the maximum number of members a group can contain (`max size = 2 ^ tree depth`). * **Zero value**: (_default `BigInt(0)`_) the value for a tree node that doesn't have a member assigned. To create a group with default _`treeDepth`_ and _`zeroValue`_, call the `Group` constructor without parameters--for example: import { Group } from "@semaphore-protocol/group"// Default parameters: treeDepth = 20, zeroValue = BigInt(0).const group = new Group() The following example code passes _`treeDepth`_ to create a group for `2 ^ 30 = 1073741824` members: import { Group } from "@semaphore-protocol/group"const group = new Group(30) The following example code creates a group with a _`zeroValue`_ of `BigInt(1)`: import { Group } from "@semaphore-protocol/group"const group = new Group(20, BigInt(1)) ### Add members[​](https://docs.semaphore.pse.dev/es/V2/guides/groups#add-members "Enlace directo al encabezado") Use the `Group addMember` function to add a member (identity commitment) to a group--for example: group.addMember(identityCommitment) To add a batch of members to a group, pass an array to the `Group addMembers` function--for example: group.addMembers([identityCommitment1, identityCommitment2]) ### Remove or update members[​](https://docs.semaphore.pse.dev/es/V2/guides/groups#remove-or-update-members "Enlace directo al encabezado") To remove members from a group, pass the member index to the `Group removeMember` function--for example: group.removeMember(0) To update members in a group, pass the member index and the new value to the `Group updateMember` function--for example: group.updateMember(0, 2) precaución Removing a member from a group sets the node value to `zeroValue`. Given that the node isn't removed, and the length of the `group.members` array doesn't change. On-chain groups[​](https://docs.semaphore.pse.dev/es/V2/guides/groups#on-chain-groups "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------- The [`SemaphoreGroups`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/contracts/base/SemaphoreGroups.sol) contract uses the [`IncrementalBinaryTree`](https://github.com/privacy-scaling-explorations/zk-kit/blob/main/packages/incremental-merkle-tree.sol/contracts/IncrementalBinaryTree.sol) library and provides methods to create and manage groups. información You can import `SemaphoreGroups` and other Semaphore contracts from the [`@semaphore-protocol/contracts`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts) NPM module. Alternatively, you can use an already deployed [`Semaphore`](https://github.com/semaphore-protocol/semaphore/tree/v2.6.1/packages/contracts/contracts/Semaphore.sol) contract and use its group external functions. * [Off-chain groups](https://docs.semaphore.pse.dev/es/V2/guides/groups#off-chain-groups) * [Create a group](https://docs.semaphore.pse.dev/es/V2/guides/groups#create-a-group) * [Add members](https://docs.semaphore.pse.dev/es/V2/guides/groups#add-members) * [Remove or update members](https://docs.semaphore.pse.dev/es/V2/guides/groups#remove-or-update-members) * [On-chain groups](https://docs.semaphore.pse.dev/es/V2/guides/groups#on-chain-groups) --- # Getting started | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/getting-started#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página Semaphore provides an official CLI to set up your project with Hardhat. If your NPM version is 5.2 or higher you can use NPX: npx @semaphore-protocol/cli create my-app --template monorepo-ethers Otherwise, install `@semaphore-protocol/cli` globally and run the `create` command: npm i -g @semaphore-protocol/clisemaphore create my-app --template monorepo-ethers información The supported templates are: [`contracts-hardhat`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-contracts-hardhat) , [`monorepo-ethers`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-monorepo-ethers) , [`monorepo-subgraph`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli-template-monorepo-subgraph) . información The [`semaphore CLI`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli) can also be used to get group data from a supported network (e.g. `semaphore get-groups --network sepolia`). To start working on your project, install the dependencies: cd my-appyarn Output[​](https://docs.semaphore.pse.dev/es/getting-started#output "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------- The `create` command will create a directory called my-app (or whatever name you choose) inside the current folder. That directory will contain the initial project structure, which includes a simple contract, a task to deploy it, some tests and a Next.js application (the web-app folder) to interact with that contract. my-app├── .yarn├── apps│ └── contracts│ │ └── contracts| │ │ └── Feedback.sol│ │ └── tasks| │ │ └── deploy.ts│ │ └── test| │ │ └── Feedback.ts│ │ └── hardhat.config.ts│ │ └── package.json│ │ └── tsconfig.json│ └── web-app├── .editorconfig├── .env├── .env.example├── .eslintignore├── .eslintrc.json├── .gitignore├── .prettierignore├── .prettierrc.json├── .yarnrc.yml├── package.json├── README.md└── tsconfig.json The `Feedback.sol` contract creates a Semaphore group, allows users to join that group with their Semaphore identity, and finally allows group members to send an anonymous feedback. Usage[​](https://docs.semaphore.pse.dev/es/getting-started#usage "Enlace directo al encabezado") ------------------------------------------------------------------------------------------------- ### Compile contracts[​](https://docs.semaphore.pse.dev/es/getting-started#compile-contracts "Enlace directo al encabezado") Go to the `contracts` folder: cd apps/contracts And compile your contracts: yarn compile ### Test contracts[​](https://docs.semaphore.pse.dev/es/getting-started#test-contracts "Enlace directo al encabezado") Test your contracts: yarn test Generate a test coverage report: yarn test:coverage Or a test gas report: yarn test:report-gas ### Deploy contracts[​](https://docs.semaphore.pse.dev/es/getting-started#deploy-contracts "Enlace directo al encabezado") Follow the instructions below to deploy your contracts: In the project root folder: 1. Add your environment variables in the `.env` file. nota 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. yarn deploy --semaphore --network sepolia nota Check the Semaphore contract addresses [here](https://docs.semaphore.pse.dev/es/deployed-contracts) . precaución The group id is a number. ### Start app[​](https://docs.semaphore.pse.dev/es/getting-started#start-app "Enlace directo al encabezado") Start the application: yarn dev información If you want to see the code of a comprehensive application built on top of Semaphore see the [boilerplate](https://github.com/semaphore-protocol/boilerplate/tree/main) . For more info about the core libraries, keep reading the next guides. * [Output](https://docs.semaphore.pse.dev/es/getting-started#output) * [Usage](https://docs.semaphore.pse.dev/es/getting-started#usage) * [Compile contracts](https://docs.semaphore.pse.dev/es/getting-started#compile-contracts) * [Test contracts](https://docs.semaphore.pse.dev/es/getting-started#test-contracts) * [Deploy contracts](https://docs.semaphore.pse.dev/es/getting-started#deploy-contracts) * [Start app](https://docs.semaphore.pse.dev/es/getting-started#start-app) --- # Solución de problemas | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/V3/troubleshooting#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Esta es documentación para Semaphore **V3**, que ya no se mantiene activamente. Para la documentación actualizada, vea **[última versión](https://docs.semaphore.pse.dev/es/troubleshooting) ** (V4). Versión: V3 En esta página Si estas sugerencias no funcionan, no dude en preguntar en las [Semaphore Discussions](https://github.com/semaphore-protocol/semaphore/discussions) o en el canal [Semaphore Telegram](https://semaphore.pse.dev/telegram) . Usando Semaphore en the frontend[​](https://docs.semaphore.pse.dev/es/V3/troubleshooting#usando-semaphore-en-the-frontend "Enlace directo al encabezado") ---------------------------------------------------------------------------------------------------------------------------------------------------------- Semaphore funciona con cualquier framework de JavaScript, pero el paquete [`@semaphore-protocol/proof`](https://github.com/semaphore-protocol/semaphore/tree/main/packages/proof) está usando [snarkjs](https://github.com/iden3/snarkjs) , que usa módulos Node.js que no son compatibles con los frameworks de frontend y hay algunos cambios que debemos hacer para que funcione en el lado del cliente. ### Semaphore con Nextjs[​](https://docs.semaphore.pse.dev/es/V3/troubleshooting#semaphore-con-nextjs "Enlace directo al encabezado") Verá un error como este: Module not found: Can't resolve 'fs' Para resolver esto, en su archivo `next.config.js`, dentro del objeto `nextConfig`, agregue: webpack: (config, { isServer }) => { if (!isServer) { config.resolve.fallback = { fs: false } } return config } Su fichero `next.config.js` sería algo como esto: /** @type {import('next').NextConfig} */const nextConfig = { reactStrictMode: true, webpack: (config, { isServer }) => { if (!isServer) { config.resolve.fallback = { fs: false } } return config }}module.exports = nextConfig ### Semaphore con React + Vite o Vuejs + Vite[​](https://docs.semaphore.pse.dev/es/V3/troubleshooting#semaphore-con-react--vite-o-vuejs--vite "Enlace directo al encabezado") Verá un error como este: readman.js:43 Uncaught ReferenceError: process is not defined at stringToBase64 (threadman.js:43:5) at threadman.js:50:22 Para resolver eso: 1- Instale `@esbuild-plugins/node-globals-polyfill` y `@esbuild-plugins/node-modules-polyfill` * npm * Yarn * pnpm npm install @esbuild-plugins/node-globals-polyfill yarn add @esbuild-plugins/node-globals-polyfill pnpm add @esbuild-plugins/node-globals-polyfill * npm * Yarn * pnpm npm install @esbuild-plugins/node-modules-polyfill yarn add @esbuild-plugins/node-modules-polyfill pnpm add @esbuild-plugins/node-modules-polyfill 2- Modifique `vite.config.ts` para añadirlos: import { NodeGlobalsPolyfillPlugin } from "@esbuild-plugins/node-globals-polyfill"import { NodeModulesPolyfillPlugin } from "@esbuild-plugins/node-modules-polyfill" y en `defineConfig` agregue: optimizeDeps: { esbuildOptions: { // Enable esbuild polyfill plugins plugins: [ NodeGlobalsPolyfillPlugin({ process: true, buffer: true }), NodeModulesPolyfillPlugin() ] }} Su fichero `vite.config.ts` debería ser algo como: import { fileURLToPath, URL } from "node:url"import { defineConfig } from "vite"import vue from "@vitejs/plugin-vue"import { NodeGlobalsPolyfillPlugin } from "@esbuild-plugins/node-globals-polyfill"import { NodeModulesPolyfillPlugin } from "@esbuild-plugins/node-modules-polyfill"// https://vitejs.dev/config/export default defineConfig({ plugins: [vue()], resolve: { alias: { "@": fileURLToPath(new URL("./src", import.meta.url)) } }, optimizeDeps: { esbuildOptions: { // Enable esbuild polyfill plugins plugins: [ NodeGlobalsPolyfillPlugin({ process: true, buffer: true }), NodeModulesPolyfillPlugin() ] } }}) información En caso de React con Vite, si ve un subrayado ondulado rojo en cada módulo Semaphore que dice `Could not find a declaration file for module ...`, cambie el `moduleResolution` de `bundler` a `Node` en el fichero `tsconfig.json` dentro de `compilerOptions`. Su fichero `tsconfig.json` sería algo así: { "compilerOptions": { "target": "ESNext", "lib": ["DOM", "DOM.Iterable", "ESNext"], "module": "ESNext", "skipLibCheck": true, /* Bundler mode */ "moduleResolution": "Node", "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", /* Linting */ "strict": true, "noUnusedLocals": true, "noUnusedParameters": true, "noFallthroughCasesInSwitch": true }, "include": ["src"], "references": [{ "path": "./tsconfig.node.json" }]} Grupos de Semaphore[​](https://docs.semaphore.pse.dev/es/V3/troubleshooting#grupos-de-semaphore "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------------- ### Creando un Grupo[​](https://docs.semaphore.pse.dev/es/V3/troubleshooting#creando-un-grupo "Enlace directo al encabezado") Cuando crea un grupo y se revierte la transacción, asegúrese de que la identificación del grupo que está utilizando no existe en la red que está utilizando. Para comprobarlo, puede utilizar la [Semaphore CLI](https://github.com/semaphore-protocol/semaphore/tree/main/packages/cli) con el comando `get-groups` y la red que está utilizando y luego, asegúrese de que su id de grupo no sea parte de esa lista. También puede utilizar el [Semaphore explorer](https://explorer.semaphore.pse.dev/) . Semaphore Proofs[​](https://docs.semaphore.pse.dev/es/V3/troubleshooting#semaphore-proofs "Enlace directo al encabezado") -------------------------------------------------------------------------------------------------------------------------- ### Transacción revertida al usar el mismo external nullifier[​](https://docs.semaphore.pse.dev/es/V3/troubleshooting#transacci%C3%B3n-revertida-al-usar-el-mismo-external-nullifier "Enlace directo al encabezado") 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. * [Usando Semaphore en the frontend](https://docs.semaphore.pse.dev/es/V3/troubleshooting#usando-semaphore-en-the-frontend) * [Semaphore con Nextjs](https://docs.semaphore.pse.dev/es/V3/troubleshooting#semaphore-con-nextjs) * [Semaphore con React + Vite o Vuejs + Vite](https://docs.semaphore.pse.dev/es/V3/troubleshooting#semaphore-con-react--vite-o-vuejs--vite) * [Grupos de Semaphore](https://docs.semaphore.pse.dev/es/V3/troubleshooting#grupos-de-semaphore) * [Creando un Grupo](https://docs.semaphore.pse.dev/es/V3/troubleshooting#creando-un-grupo) * [Semaphore Proofs](https://docs.semaphore.pse.dev/es/V3/troubleshooting#semaphore-proofs) * [Transacción revertida al usar el mismo external nullifier](https://docs.semaphore.pse.dev/es/V3/troubleshooting#transacci%C3%B3n-revertida-al-usar-el-mismo-external-nullifier) --- # Code editors and LLM setup | Semaphore [Saltar al contenido principal](https://docs.semaphore.pse.dev/es/llm-setup#__docusaurus_skipToContent_fallback) **[Semaphore V4](https://github.com/semaphore-protocol/semaphore/releases/tag/v4.0.0) is out 🎉 [Try it out](https://docs.semaphore.pse.dev/getting-started) and let us know if you have any feedback on [Telegram](https://semaphore.pse.dev/telegram) or [Github](https://github.com/orgs/semaphore-protocol/discussions) !** Versión: V4 En esta página LLMs often rely on outdated or generic information. Use this guide to help set up your code editor to pull in more accurate, up-to-date documentation and examples. It will help provide better answers and generate more accurate Semaphore code using LLMs (large language models) and MCP (Model Context Protocol) servers. Quick use[​](https://docs.semaphore.pse.dev/es/llm-setup#quick-use "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------- [llms.txt](https://docs.semaphore.pse.dev/llms.txt) is a compact, text version of the Semaphore docs. Add this link directly to your chat window for enhanced context. Permanent setup[​](https://docs.semaphore.pse.dev/es/llm-setup#permanent-setup "Enlace directo al encabezado") --------------------------------------------------------------------------------------------------------------- Depending on your IDE, you can add custom docs to VS Code, Cursor or others. Example for Cursor... 1. Press `CMD + Shift + P` (unix), `Ctrl + Shift + P` (Windows) 2. Type `Add new custom docs`. 3. Add [https://docs.semaphore.pse.dev/llms.txt](https://docs.semaphore.pse.dev/llms.txt) 4. In chat you can know `@docs` and choose `semaphore` to provide additional context. Refer to the documentation of your IDE to properly set it up. MCP Server[​](https://docs.semaphore.pse.dev/es/llm-setup#mcp-server "Enlace directo al encabezado") ----------------------------------------------------------------------------------------------------- Depending on your IDE, you can add a MCP server to communicate your docs to the AI model. * [Context7 MCP server](https://github.com/upstash/context7) is a server that provides many libraries, incl. Semaphore. Example for Cursor... 1. Press `CMD + Shift + J` (unix), `Ctrl + Shift + J` (Windows) 2. Click on `MCP` on the sidebar 3. Click `Add new global MCP server` 4. Add the following code to `mcp.json` { "mcpServers": { "Context7": { "type": "stdio", "command": "npx", "args": ["-y", "@upstash/context7-mcp@latest"] } }} You can now prompt anything about Semaphore and write `use context7` at the end of your prompt. E.g. `create a new Semaphore identity in TypeScript. use context`. This will call the MCP tool and automatically fetch the latest documentation. Refer to the documentation of your IDE to properly set it up. * [Quick use](https://docs.semaphore.pse.dev/es/llm-setup#quick-use) * [Permanent setup](https://docs.semaphore.pse.dev/es/llm-setup#permanent-setup) * [MCP Server](https://docs.semaphore.pse.dev/es/llm-setup#mcp-server) ---