Skip to content

Commit cc32fee

Browse files
committed
feat(contracts): update contracts with new imt
1 parent 6b347ff commit cc32fee

File tree

13 files changed

+209
-321
lines changed

13 files changed

+209
-321
lines changed

packages/contracts/contracts/Semaphore.sol

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
2727
_;
2828
}
2929

30-
/// @dev Checks if there is a verifier for the given tree depth.
31-
/// @param merkleTreeDepth: Depth of the tree.
32-
modifier onlySupportedMerkleTreeDepth(uint256 merkleTreeDepth) {
33-
if (merkleTreeDepth < 16 || merkleTreeDepth > 32) {
34-
revert Semaphore__MerkleTreeDepthIsNotSupported();
30+
/// @dev Checks if the group exists.
31+
/// @param groupId: Id of the group.
32+
modifier onlyExistingGroup(uint256 groupId) {
33+
if (groups[groupId].admin == address(0)) {
34+
revert Semaphore__GroupDoesNotExist();
3535
}
36+
3637
_;
3738
}
3839

@@ -43,36 +44,36 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
4344
}
4445

4546
/// @dev See {ISemaphore-createGroup}.
46-
function createGroup(
47-
uint256 groupId,
48-
uint256 merkleTreeDepth,
49-
address admin
50-
) external override onlySupportedMerkleTreeDepth(merkleTreeDepth) {
51-
_createGroup(groupId, merkleTreeDepth);
47+
function createGroup(uint256 groupId, address admin) external override {
48+
if (groups[groupId].admin != address(0)) {
49+
revert Semaphore__GroupAlreadyExists();
50+
}
5251

5352
groups[groupId].admin = admin;
5453
groups[groupId].merkleTreeDuration = 1 hours;
5554

55+
emit GroupCreated(groupId);
5656
emit GroupAdminUpdated(groupId, address(0), admin);
5757
}
5858

5959
/// @dev See {ISemaphore-createGroup}.
60-
function createGroup(
61-
uint256 groupId,
62-
uint256 merkleTreeDepth,
63-
address admin,
64-
uint256 merkleTreeDuration
65-
) external override onlySupportedMerkleTreeDepth(merkleTreeDepth) {
66-
_createGroup(groupId, merkleTreeDepth);
60+
function createGroup(uint256 groupId, address admin, uint256 merkleTreeDuration) external override {
61+
if (groups[groupId].admin != address(0)) {
62+
revert Semaphore__GroupAlreadyExists();
63+
}
6764

6865
groups[groupId].admin = admin;
6966
groups[groupId].merkleTreeDuration = merkleTreeDuration;
7067

68+
emit GroupCreated(groupId);
7169
emit GroupAdminUpdated(groupId, address(0), admin);
7270
}
7371

7472
/// @dev See {ISemaphore-updateGroupAdmin}.
75-
function updateGroupAdmin(uint256 groupId, address newAdmin) external override onlyGroupAdmin(groupId) {
73+
function updateGroupAdmin(
74+
uint256 groupId,
75+
address newAdmin
76+
) external override onlyExistingGroup(groupId) onlyGroupAdmin(groupId) {
7677
groups[groupId].admin = newAdmin;
7778

7879
emit GroupAdminUpdated(groupId, _msgSender(), newAdmin);
@@ -82,7 +83,7 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
8283
function updateGroupMerkleTreeDuration(
8384
uint256 groupId,
8485
uint256 newMerkleTreeDuration
85-
) external override onlyGroupAdmin(groupId) {
86+
) external override onlyExistingGroup(groupId) onlyGroupAdmin(groupId) {
8687
uint256 oldMerkleTreeDuration = groups[groupId].merkleTreeDuration;
8788

8889
groups[groupId].merkleTreeDuration = newMerkleTreeDuration;
@@ -91,7 +92,10 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
9192
}
9293

9394
/// @dev See {ISemaphore-addMember}.
94-
function addMember(uint256 groupId, uint256 identityCommitment) external override onlyGroupAdmin(groupId) {
95+
function addMember(
96+
uint256 groupId,
97+
uint256 identityCommitment
98+
) external override onlyExistingGroup(groupId) onlyGroupAdmin(groupId) {
9599
_addMember(groupId, identityCommitment);
96100

97101
uint256 merkleTreeRoot = getMerkleTreeRoot(groupId);
@@ -103,7 +107,7 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
103107
function addMembers(
104108
uint256 groupId,
105109
uint256[] calldata identityCommitments
106-
) external override onlyGroupAdmin(groupId) {
110+
) external override onlyExistingGroup(groupId) onlyGroupAdmin(groupId) {
107111
for (uint256 i = 0; i < identityCommitments.length; ) {
108112
_addMember(groupId, identityCommitments[i]);
109113

@@ -122,10 +126,9 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
122126
uint256 groupId,
123127
uint256 identityCommitment,
124128
uint256 newIdentityCommitment,
125-
uint256[] calldata proofSiblings,
126-
uint8[] calldata proofPathIndices
127-
) external override onlyGroupAdmin(groupId) {
128-
_updateMember(groupId, identityCommitment, newIdentityCommitment, proofSiblings, proofPathIndices);
129+
uint256[] calldata merkleProofSiblings
130+
) external override onlyExistingGroup(groupId) onlyGroupAdmin(groupId) {
131+
_updateMember(groupId, identityCommitment, newIdentityCommitment, merkleProofSiblings);
129132

130133
uint256 merkleTreeRoot = getMerkleTreeRoot(groupId);
131134

@@ -136,10 +139,9 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
136139
function removeMember(
137140
uint256 groupId,
138141
uint256 identityCommitment,
139-
uint256[] calldata proofSiblings,
140-
uint8[] calldata proofPathIndices
141-
) external override onlyGroupAdmin(groupId) {
142-
_removeMember(groupId, identityCommitment, proofSiblings, proofPathIndices);
142+
uint256[] calldata merkleProofSiblings
143+
) external override onlyExistingGroup(groupId) onlyGroupAdmin(groupId) {
144+
_removeMember(groupId, identityCommitment, merkleProofSiblings);
143145

144146
uint256 merkleTreeRoot = getMerkleTreeRoot(groupId);
145147

@@ -150,15 +152,15 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
150152
function verifyProof(
151153
uint256 groupId,
152154
uint256 merkleTreeRoot,
153-
uint256 signal,
154-
uint256 nullifierHash,
155-
uint256 externalNullifier,
155+
uint256 message,
156+
uint256 nullifier,
157+
uint256 scope,
156158
uint256[8] calldata proof
157-
) external override {
159+
) external override onlyExistingGroup(groupId) {
158160
uint256 merkleTreeDepth = getMerkleTreeDepth(groupId);
159161

160162
if (merkleTreeDepth == 0) {
161-
revert Semaphore__GroupDoesNotExist();
163+
revert Semaphore__GroupHasNoMembers();
162164
}
163165

164166
uint256 currentMerkleTreeRoot = getMerkleTreeRoot(groupId);
@@ -178,14 +180,14 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
178180
}
179181
}
180182

181-
if (groups[groupId].nullifierHashes[nullifierHash]) {
183+
if (groups[groupId].nullifiers[nullifier]) {
182184
revert Semaphore__YouAreUsingTheSameNillifierTwice();
183185
}
184186

185-
verifier.verifyProof(merkleTreeRoot, nullifierHash, signal, externalNullifier, proof, merkleTreeDepth);
187+
verifier.verifyProof(merkleTreeRoot, nullifier, message, scope, proof);
186188

187-
groups[groupId].nullifierHashes[nullifierHash] = true;
189+
groups[groupId].nullifiers[nullifier] = true;
188190

189-
emit ProofVerified(groupId, merkleTreeRoot, nullifierHash, externalNullifier, signal);
191+
emit ProofVerified(groupId, merkleTreeRoot, nullifier, scope, message, proof);
190192
}
191193
}

packages/contracts/contracts/base/SemaphoreGroups.sol

Lines changed: 35 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -2,137 +2,88 @@
22
pragma solidity 0.8.4;
33

44
import "../interfaces/ISemaphoreGroups.sol";
5-
import "@zk-kit/incremental-merkle-tree.sol/IncrementalBinaryTree.sol";
5+
import {InternalLeanIMT, LeanIMTData} from "@zk-kit/imt.sol/internal/InternalLeanIMT.sol";
66
import "@openzeppelin/contracts/utils/Context.sol";
77

88
/// @title Semaphore groups contract.
99
/// @dev This contract allows you to create groups, add, remove and update members.
1010
/// You can use getters to obtain informations about groups (root, depth, number of leaves).
1111
abstract contract SemaphoreGroups is Context, ISemaphoreGroups {
12-
using IncrementalBinaryTree for IncrementalTreeData;
12+
using InternalLeanIMT for LeanIMTData;
1313

1414
/// @dev Gets a group id and returns the tree data.
15-
mapping(uint256 => IncrementalTreeData) internal merkleTrees;
16-
17-
/// @dev Creates a new group by initializing the associated tree.
18-
/// @param groupId: Id of the group.
19-
/// @param merkleTreeDepth: Depth of the tree.
20-
function _createGroup(uint256 groupId, uint256 merkleTreeDepth) internal virtual {
21-
if (getMerkleTreeDepth(groupId) != 0) {
22-
revert Semaphore__GroupAlreadyExists();
23-
}
24-
25-
// The zeroValue is an implicit member of the group, or an implicit leaf of the Merkle tree.
26-
// Although there is a remote possibility that the preimage of
27-
// the hash may be calculated, using this value we aim to minimize the risk.
28-
uint256 zeroValue = uint256(keccak256(abi.encodePacked(groupId))) >> 8;
29-
30-
merkleTrees[groupId].init(merkleTreeDepth, zeroValue);
31-
32-
emit GroupCreated(groupId, merkleTreeDepth, zeroValue);
33-
}
15+
mapping(uint256 => LeanIMTData) internal merkleTrees;
3416

3517
/// @dev Adds an identity commitment to an existing group.
3618
/// @param groupId: Id of the group.
3719
/// @param identityCommitment: New identity commitment.
3820
function _addMember(uint256 groupId, uint256 identityCommitment) internal virtual {
39-
if (getMerkleTreeDepth(groupId) == 0) {
40-
revert Semaphore__GroupDoesNotExist();
41-
}
42-
43-
merkleTrees[groupId].insert(identityCommitment);
44-
45-
uint256 merkleTreeRoot = getMerkleTreeRoot(groupId);
46-
uint256 index = getNumberOfMerkleTreeLeaves(groupId) - 1;
21+
uint256 merkleTreeRoot = merkleTrees[groupId]._insert(identityCommitment);
22+
uint256 leafIndex = getMerkleTreeSize(groupId) - 1;
4723

48-
emit MemberAdded(groupId, index, identityCommitment, merkleTreeRoot);
24+
emit MemberAdded(groupId, leafIndex, identityCommitment, merkleTreeRoot);
4925
}
5026

5127
/// @dev Updates an identity commitment of an existing group. A proof of membership is
5228
/// needed to check if the node to be updated is part of the tree.
5329
/// @param groupId: Id of the group.
54-
/// @param identityCommitment: Existing identity commitment to be updated.
30+
/// @param oldIdentityCommitment: Existing identity commitment to be updated.
5531
/// @param newIdentityCommitment: New identity commitment.
56-
/// @param proofSiblings: Array of the sibling nodes of the proof of membership.
57-
/// @param proofPathIndices: Path of the proof of membership.
32+
/// @param merkleProofSiblings: Array of the sibling nodes of the proof of membership.
5833
function _updateMember(
5934
uint256 groupId,
60-
uint256 identityCommitment,
35+
uint256 oldIdentityCommitment,
6136
uint256 newIdentityCommitment,
62-
uint256[] calldata proofSiblings,
63-
uint8[] calldata proofPathIndices
37+
uint256[] calldata merkleProofSiblings
6438
) internal virtual {
65-
if (getMerkleTreeDepth(groupId) == 0) {
66-
revert Semaphore__GroupDoesNotExist();
67-
}
68-
69-
merkleTrees[groupId].update(identityCommitment, newIdentityCommitment, proofSiblings, proofPathIndices);
70-
71-
uint256 merkleTreeRoot = getMerkleTreeRoot(groupId);
72-
uint256 index = proofPathIndicesToMemberIndex(proofPathIndices);
73-
74-
emit MemberUpdated(groupId, index, identityCommitment, newIdentityCommitment, merkleTreeRoot);
39+
uint256 merkleTreeRoot = merkleTrees[groupId]._update(
40+
oldIdentityCommitment,
41+
newIdentityCommitment,
42+
merkleProofSiblings
43+
);
44+
uint256 leafIndex = merkleTrees[groupId]._indexOf(newIdentityCommitment);
45+
46+
emit MemberUpdated(groupId, leafIndex, oldIdentityCommitment, newIdentityCommitment, merkleTreeRoot);
7547
}
7648

7749
/// @dev Removes an identity commitment from an existing group. A proof of membership is
7850
/// needed to check if the node to be deleted is part of the tree.
7951
/// @param groupId: Id of the group.
8052
/// @param identityCommitment: Existing identity commitment to be removed.
81-
/// @param proofSiblings: Array of the sibling nodes of the proof of membership.
82-
/// @param proofPathIndices: Path of the proof of membership.
53+
/// @param merkleProofSiblings: Array of the sibling nodes of the proof of membership.
8354
function _removeMember(
8455
uint256 groupId,
8556
uint256 identityCommitment,
86-
uint256[] calldata proofSiblings,
87-
uint8[] calldata proofPathIndices
57+
uint256[] calldata merkleProofSiblings
8858
) internal virtual {
89-
if (getMerkleTreeDepth(groupId) == 0) {
90-
revert Semaphore__GroupDoesNotExist();
91-
}
59+
uint256 leafIndex = merkleTrees[groupId]._indexOf(identityCommitment);
60+
uint256 merkleTreeRoot = merkleTrees[groupId]._remove(identityCommitment, merkleProofSiblings);
9261

93-
merkleTrees[groupId].remove(identityCommitment, proofSiblings, proofPathIndices);
62+
emit MemberRemoved(groupId, leafIndex, identityCommitment, merkleTreeRoot);
63+
}
9464

95-
uint256 merkleTreeRoot = getMerkleTreeRoot(groupId);
96-
uint256 index = proofPathIndicesToMemberIndex(proofPathIndices);
65+
/// @dev See {ISemaphoreGroups-hasMember}.
66+
function hasMember(uint256 groupId, uint256 identityCommitment) public view virtual override returns (bool) {
67+
return merkleTrees[groupId]._has(identityCommitment);
68+
}
9769

98-
emit MemberRemoved(groupId, index, identityCommitment, merkleTreeRoot);
70+
/// @dev See {ISemaphoreGroups-indexOf}.
71+
function indexOf(uint256 groupId, uint256 identityCommitment) public view virtual override returns (uint256) {
72+
return merkleTrees[groupId]._indexOf(identityCommitment);
9973
}
10074

10175
/// @dev See {ISemaphoreGroups-getMerkleTreeRoot}.
10276
function getMerkleTreeRoot(uint256 groupId) public view virtual override returns (uint256) {
103-
return merkleTrees[groupId].root;
77+
return merkleTrees[groupId]._root();
10478
}
10579

10680
/// @dev See {ISemaphoreGroups-getMerkleTreeDepth}.
10781
function getMerkleTreeDepth(uint256 groupId) public view virtual override returns (uint256) {
10882
return merkleTrees[groupId].depth;
10983
}
11084

111-
/// @dev See {ISemaphoreGroups-getNumberOfMerkleTreeLeaves}.
112-
function getNumberOfMerkleTreeLeaves(uint256 groupId) public view virtual override returns (uint256) {
113-
return merkleTrees[groupId].numberOfLeaves;
114-
}
115-
116-
/// @dev Converts the path indices of a Merkle proof to the identity commitment index in the tree.
117-
/// @param proofPathIndices: Path of the proof of membership.
118-
/// @return Index of a group member.
119-
function proofPathIndicesToMemberIndex(uint8[] calldata proofPathIndices) private pure returns (uint256) {
120-
uint256 memberIndex = 0;
121-
122-
for (uint8 i = uint8(proofPathIndices.length); i > 0; ) {
123-
if (memberIndex > 0 || proofPathIndices[i - 1] != 0) {
124-
memberIndex *= 2;
125-
126-
if (proofPathIndices[i - 1] == 1) {
127-
memberIndex += 1;
128-
}
129-
}
130-
131-
unchecked {
132-
--i;
133-
}
134-
}
135-
136-
return memberIndex;
85+
/// @dev See {ISemaphoreGroups-getMerkleTreeSize}.
86+
function getMerkleTreeSize(uint256 groupId) public view virtual override returns (uint256) {
87+
return merkleTrees[groupId].size;
13788
}
13889
}

packages/contracts/contracts/base/SemaphoreVerifier.sol

Lines changed: 10 additions & 10 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)