---
sidebar_position: 2
title: Groups
---

import Tabs from "@theme/Tabs"
import TabItem from "@theme/TabItem"

# Semaphore groups

A [Semaphore group](/V3/glossary/#semaphore-group) contains [identity commitments](/V3/glossary/#identity-commitment) of group members.
Example uses of groups include the following:

- poll question that attendees join to rate an event,
- ballot that members join to vote on a proposal,
- whistleblowers who are verified employees of an organization.

A Semaphore group is an [incremental Merkle tree](/V3/glossary/#merkle-tree), and group members (i.e., [identity commitments](/V3/glossary/#identity-commitment)) are tree leaves.
Semaphore groups set the following three parameters:

- **Group id**: a unique identifier for the group;
- **Tree depth**: the maximum number of members a group can contain (`max size = 2 ^ tree depth`);
- **Members**: the list of members to initialize the group.

Learn how to work with groups.

- [**Off-chain groups**](#off-chain-groups)
- [**On-chain groups**](#on-chain-groups)

## Off-chain groups

- [Create a group](#create-a-group)
- [Add members](#add-members)
- [Remove or update members](#remove-or-update-members)

### Create a group

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:

<Tabs
  defaultValue="npm"
  groupId="package-managers"
  values={[
{label: 'npm', value: 'npm'},
{label: 'Yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]}
>
  <TabItem value="npm">
    ```bash
    npm install @semaphore-protocol/group@^3
    ```
  </TabItem>

  <TabItem value="yarn">
    ```bash
    yarn add @semaphore-protocol/group@^3
    ```
  </TabItem>

  <TabItem value="pnpm">
    ```bash
    pnpm add @semaphore-protocol/group@^3
    ```
  </TabItem>
</Tabs>

To create a group with default *`treeDepth`*, call the `Group` constructor without the second parameter. For example:

```ts
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:

```ts
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:

```ts
import { Group } from "@semaphore-protocol/group"

const members = [
  "11237622825477336339577122413451117718539783476837539122310492284566644730311",
  "9332663527862709610616009715800254142772436825222910251631161087138559093425",
  "13255821893820536903335282929376140649646180444238593676033702344407594536519"
]
const group = new Group(1, 20, members)
```

### Add members

Use the `Group addMember` function to add a member (identity commitment) to a group. For example:

```ts
group.addMember(identityCommitment)
```

To add a batch of members to a group, pass an array to the `Group addMembers` function. For example:

```ts
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

To remove members from a group, pass the member index to the `Group removeMember` function. For example:

```ts
group.removeMember(0)
```

To update members in a group, pass the member index and the new value to the `Group updateMember` function. For example:

```ts
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

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).
:::
