@semaphore-protocol/contracts 0.1.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  //SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.4;
2
+ pragma solidity 0.8.4;
3
3
 
4
4
  import "../interfaces/ISemaphoreVoting.sol";
5
5
  import "../base/SemaphoreCore.sol";
@@ -8,100 +8,109 @@ import "../base/SemaphoreGroups.sol";
8
8
  /// @title Semaphore voting contract.
9
9
  /// @dev The following code allows you to create polls, add voters and allow them to vote anonymously.
10
10
  contract SemaphoreVoting is ISemaphoreVoting, SemaphoreCore, SemaphoreGroups {
11
- /// @dev Gets a tree depth and returns its verifier address.
12
- mapping(uint8 => IVerifier) internal verifiers;
13
-
14
- /// @dev Gets a poll id and returns the poll data.
15
- mapping(uint256 => Poll) internal polls;
16
-
17
- /// @dev Since there can be multiple verifier contracts (each associated with a certain tree depth),
18
- /// it is necessary to pass the addresses of the previously deployed contracts with the associated
19
- /// tree depth. Depending on the depth chosen when creating the poll, a certain verifier will be
20
- /// used to verify that the proof is correct.
21
- /// @param depths: Three depths used in verifiers.
22
- /// @param verifierAddresses: Verifier addresses.
23
- constructor(uint8[] memory depths, address[] memory verifierAddresses) {
24
- require(
25
- depths.length == verifierAddresses.length,
26
- "SemaphoreVoting: parameters lists does not have the same length"
27
- );
28
-
29
- for (uint8 i = 0; i < depths.length; i++) {
30
- verifiers[depths[i]] = IVerifier(verifierAddresses[i]);
11
+ /// @dev Gets a tree depth and returns its verifier address.
12
+ mapping(uint256 => IVerifier) internal verifiers;
13
+
14
+ /// @dev Gets a poll id and returns the poll data.
15
+ mapping(uint256 => Poll) internal polls;
16
+
17
+ /// @dev Initializes the Semaphore verifiers used to verify the user's ZK proofs.
18
+ /// @param _verifiers: List of Semaphore verifiers (address and related Merkle tree depth).
19
+ constructor(Verifier[] memory _verifiers) {
20
+ for (uint8 i = 0; i < _verifiers.length; ) {
21
+ verifiers[_verifiers[i].merkleTreeDepth] = IVerifier(_verifiers[i].contractAddress);
22
+
23
+ unchecked {
24
+ ++i;
25
+ }
26
+ }
31
27
  }
32
- }
33
28
 
34
- /// @dev Checks if the poll coordinator is the transaction sender.
35
- /// @param pollId: Id of the poll.
36
- modifier onlyCoordinator(uint256 pollId) {
37
- require(polls[pollId].coordinator == _msgSender(), "SemaphoreVoting: caller is not the poll coordinator");
38
- _;
39
- }
29
+ /// @dev Checks if the poll coordinator is the transaction sender.
30
+ /// @param pollId: Id of the poll.
31
+ modifier onlyCoordinator(uint256 pollId) {
32
+ if (polls[pollId].coordinator != _msgSender()) {
33
+ revert Semaphore__CallerIsNotThePollCoordinator();
34
+ }
40
35
 
41
- /// @dev See {ISemaphoreVoting-createPoll}.
42
- function createPoll(
43
- uint256 pollId,
44
- address coordinator,
45
- uint8 depth
46
- ) public override {
47
- require(address(verifiers[depth]) != address(0), "SemaphoreVoting: depth value is not supported");
36
+ _;
37
+ }
38
+
39
+ /// @dev See {ISemaphoreVoting-createPoll}.
40
+ function createPoll(
41
+ uint256 pollId,
42
+ address coordinator,
43
+ uint256 merkleTreeDepth
44
+ ) public override {
45
+ if (address(verifiers[merkleTreeDepth]) == address(0)) {
46
+ revert Semaphore__MerkleTreeDepthIsNotSupported();
47
+ }
48
48
 
49
- _createGroup(pollId, depth, 0);
49
+ _createGroup(pollId, merkleTreeDepth, 0);
50
50
 
51
- Poll memory poll;
51
+ Poll memory poll;
52
52
 
53
- poll.coordinator = coordinator;
53
+ poll.coordinator = coordinator;
54
54
 
55
- polls[pollId] = poll;
55
+ polls[pollId] = poll;
56
+
57
+ emit PollCreated(pollId, coordinator);
58
+ }
56
59
 
57
- emit PollCreated(pollId, coordinator);
58
- }
60
+ /// @dev See {ISemaphoreVoting-addVoter}.
61
+ function addVoter(uint256 pollId, uint256 identityCommitment) public override onlyCoordinator(pollId) {
62
+ if (polls[pollId].state != PollState.Created) {
63
+ revert Semaphore__PollHasAlreadyBeenStarted();
64
+ }
59
65
 
60
- /// @dev See {ISemaphoreVoting-addVoter}.
61
- function addVoter(uint256 pollId, uint256 identityCommitment) public override onlyCoordinator(pollId) {
62
- require(polls[pollId].state == PollState.Created, "SemaphoreVoting: voters can only be added before voting");
66
+ _addMember(pollId, identityCommitment);
67
+ }
63
68
 
64
- _addMember(pollId, identityCommitment);
65
- }
69
+ /// @dev See {ISemaphoreVoting-addVoter}.
70
+ function startPoll(uint256 pollId, uint256 encryptionKey) public override onlyCoordinator(pollId) {
71
+ if (polls[pollId].state != PollState.Created) {
72
+ revert Semaphore__PollHasAlreadyBeenStarted();
73
+ }
66
74
 
67
- /// @dev See {ISemaphoreVoting-addVoter}.
68
- function startPoll(uint256 pollId, uint256 encryptionKey) public override onlyCoordinator(pollId) {
69
- require(polls[pollId].state == PollState.Created, "SemaphoreVoting: poll has already been started");
75
+ polls[pollId].state = PollState.Ongoing;
70
76
 
71
- polls[pollId].state = PollState.Ongoing;
77
+ emit PollStarted(pollId, _msgSender(), encryptionKey);
78
+ }
72
79
 
73
- emit PollStarted(pollId, _msgSender(), encryptionKey);
74
- }
80
+ /// @dev See {ISemaphoreVoting-castVote}.
81
+ function castVote(
82
+ bytes32 vote,
83
+ uint256 nullifierHash,
84
+ uint256 pollId,
85
+ uint256[8] calldata proof
86
+ ) public override onlyCoordinator(pollId) {
87
+ Poll memory poll = polls[pollId];
75
88
 
76
- /// @dev See {ISemaphoreVoting-castVote}.
77
- function castVote(
78
- bytes32 vote,
79
- uint256 nullifierHash,
80
- uint256 pollId,
81
- uint256[8] calldata proof
82
- ) public override onlyCoordinator(pollId) {
83
- Poll memory poll = polls[pollId];
89
+ if (poll.state != PollState.Ongoing) {
90
+ revert Semaphore__PollIsNotOngoing();
91
+ }
84
92
 
85
- require(poll.state == PollState.Ongoing, "SemaphoreVoting: vote can only be cast in an ongoing poll");
93
+ uint256 merkleTreeDepth = getMerkleTreeDepth(pollId);
94
+ uint256 merkleTreeRoot = getMerkleTreeRoot(pollId);
86
95
 
87
- uint8 depth = getDepth(pollId);
88
- uint256 root = getRoot(pollId);
89
- IVerifier verifier = verifiers[depth];
96
+ IVerifier verifier = verifiers[merkleTreeDepth];
90
97
 
91
- _verifyProof(vote, root, nullifierHash, pollId, proof, verifier);
98
+ _verifyProof(vote, merkleTreeRoot, nullifierHash, pollId, proof, verifier);
92
99
 
93
- // Prevent double-voting (nullifierHash = hash(pollId + identityNullifier)).
94
- _saveNullifierHash(nullifierHash);
100
+ // Prevent double-voting (nullifierHash = hash(pollId + identityNullifier)).
101
+ _saveNullifierHash(nullifierHash);
95
102
 
96
- emit VoteAdded(pollId, vote);
97
- }
103
+ emit VoteAdded(pollId, vote);
104
+ }
98
105
 
99
- /// @dev See {ISemaphoreVoting-publishDecryptionKey}.
100
- function endPoll(uint256 pollId, uint256 decryptionKey) public override onlyCoordinator(pollId) {
101
- require(polls[pollId].state == PollState.Ongoing, "SemaphoreVoting: poll is not ongoing");
106
+ /// @dev See {ISemaphoreVoting-publishDecryptionKey}.
107
+ function endPoll(uint256 pollId, uint256 decryptionKey) public override onlyCoordinator(pollId) {
108
+ if (polls[pollId].state != PollState.Ongoing) {
109
+ revert Semaphore__PollIsNotOngoing();
110
+ }
102
111
 
103
- polls[pollId].state = PollState.Ended;
112
+ polls[pollId].state = PollState.Ended;
104
113
 
105
- emit PollEnded(pollId, _msgSender(), decryptionKey);
106
- }
114
+ emit PollEnded(pollId, _msgSender(), decryptionKey);
115
+ }
107
116
  }
@@ -1,5 +1,5 @@
1
1
  //SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.4;
2
+ pragma solidity 0.8.4;
3
3
 
4
4
  import "../interfaces/ISemaphoreWhistleblowing.sol";
5
5
  import "../base/SemaphoreCore.sol";
@@ -10,79 +10,80 @@ import "../base/SemaphoreGroups.sol";
10
10
  /// organization, newspaper) and to allow them to publish news leaks anonymously.
11
11
  /// Leaks can be IPFS hashes, permanent links or other kinds of reference.
12
12
  contract SemaphoreWhistleblowing is ISemaphoreWhistleblowing, SemaphoreCore, SemaphoreGroups {
13
- /// @dev Gets a tree depth and returns its verifier address.
14
- mapping(uint8 => IVerifier) internal verifiers;
15
-
16
- /// @dev Gets an editor address and return their entity.
17
- mapping(address => uint256) private entities;
18
-
19
- /// @dev Since there can be multiple verifier contracts (each associated with a certain tree depth),
20
- /// it is necessary to pass the addresses of the previously deployed contracts with the associated
21
- /// tree depth. Depending on the depth chosen when creating the entity, a certain verifier will be
22
- /// used to verify that the proof is correct.
23
- /// @param depths: Three depths used in verifiers.
24
- /// @param verifierAddresses: Verifier addresses.
25
- constructor(uint8[] memory depths, address[] memory verifierAddresses) {
26
- require(
27
- depths.length == verifierAddresses.length,
28
- "SemaphoreWhistleblowing: parameters lists does not have the same length"
29
- );
30
-
31
- for (uint8 i = 0; i < depths.length; i++) {
32
- verifiers[depths[i]] = IVerifier(verifierAddresses[i]);
13
+ /// @dev Gets a tree depth and returns its verifier address.
14
+ mapping(uint256 => IVerifier) internal verifiers;
15
+
16
+ /// @dev Gets an editor address and return their entity.
17
+ mapping(address => uint256) private entities;
18
+
19
+ /// @dev Initializes the Semaphore verifiers used to verify the user's ZK proofs.
20
+ /// @param _verifiers: List of Semaphore verifiers (address and related Merkle tree depth).
21
+ constructor(Verifier[] memory _verifiers) {
22
+ for (uint8 i = 0; i < _verifiers.length; ) {
23
+ verifiers[_verifiers[i].merkleTreeDepth] = IVerifier(_verifiers[i].contractAddress);
24
+
25
+ unchecked {
26
+ ++i;
27
+ }
28
+ }
29
+ }
30
+
31
+ /// @dev Checks if the editor is the transaction sender.
32
+ /// @param entityId: Id of the entity.
33
+ modifier onlyEditor(uint256 entityId) {
34
+ if (entityId != entities[_msgSender()]) {
35
+ revert Semaphore__CallerIsNotTheEditor();
36
+ }
37
+
38
+ _;
39
+ }
40
+
41
+ /// @dev See {ISemaphoreWhistleblowing-createEntity}.
42
+ function createEntity(
43
+ uint256 entityId,
44
+ address editor,
45
+ uint256 merkleTreeDepth
46
+ ) public override {
47
+ if (address(verifiers[merkleTreeDepth]) == address(0)) {
48
+ revert Semaphore__MerkleTreeDepthIsNotSupported();
49
+ }
50
+
51
+ _createGroup(entityId, merkleTreeDepth, 0);
52
+
53
+ entities[editor] = entityId;
54
+
55
+ emit EntityCreated(entityId, editor);
56
+ }
57
+
58
+ /// @dev See {ISemaphoreWhistleblowing-addWhistleblower}.
59
+ function addWhistleblower(uint256 entityId, uint256 identityCommitment) public override onlyEditor(entityId) {
60
+ _addMember(entityId, identityCommitment);
61
+ }
62
+
63
+ /// @dev See {ISemaphoreWhistleblowing-removeWhistleblower}.
64
+ function removeWhistleblower(
65
+ uint256 entityId,
66
+ uint256 identityCommitment,
67
+ uint256[] calldata proofSiblings,
68
+ uint8[] calldata proofPathIndices
69
+ ) public override onlyEditor(entityId) {
70
+ _removeMember(entityId, identityCommitment, proofSiblings, proofPathIndices);
71
+ }
72
+
73
+ /// @dev See {ISemaphoreWhistleblowing-publishLeak}.
74
+ function publishLeak(
75
+ bytes32 leak,
76
+ uint256 nullifierHash,
77
+ uint256 entityId,
78
+ uint256[8] calldata proof
79
+ ) public override onlyEditor(entityId) {
80
+ uint256 merkleTreeDepth = getMerkleTreeDepth(entityId);
81
+ uint256 merkleTreeRoot = getMerkleTreeRoot(entityId);
82
+
83
+ IVerifier verifier = verifiers[merkleTreeDepth];
84
+
85
+ _verifyProof(leak, merkleTreeRoot, nullifierHash, entityId, proof, verifier);
86
+
87
+ emit LeakPublished(entityId, leak);
33
88
  }
34
- }
35
-
36
- /// @dev Checks if the editor is the transaction sender.
37
- /// @param entityId: Id of the entity.
38
- modifier onlyEditor(uint256 entityId) {
39
- require(entityId == entities[_msgSender()], "SemaphoreWhistleblowing: caller is not the editor");
40
- _;
41
- }
42
-
43
- /// @dev See {ISemaphoreWhistleblowing-createEntity}.
44
- function createEntity(
45
- uint256 entityId,
46
- address editor,
47
- uint8 depth
48
- ) public override {
49
- require(address(verifiers[depth]) != address(0), "SemaphoreWhistleblowing: depth value is not supported");
50
-
51
- _createGroup(entityId, depth, 0);
52
-
53
- entities[editor] = entityId;
54
-
55
- emit EntityCreated(entityId, editor);
56
- }
57
-
58
- /// @dev See {ISemaphoreWhistleblowing-addWhistleblower}.
59
- function addWhistleblower(uint256 entityId, uint256 identityCommitment) public override onlyEditor(entityId) {
60
- _addMember(entityId, identityCommitment);
61
- }
62
-
63
- /// @dev See {ISemaphoreWhistleblowing-removeWhistleblower}.
64
- function removeWhistleblower(
65
- uint256 entityId,
66
- uint256 identityCommitment,
67
- uint256[] calldata proofSiblings,
68
- uint8[] calldata proofPathIndices
69
- ) public override onlyEditor(entityId) {
70
- _removeMember(entityId, identityCommitment, proofSiblings, proofPathIndices);
71
- }
72
-
73
- /// @dev See {ISemaphoreWhistleblowing-publishLeak}.
74
- function publishLeak(
75
- bytes32 leak,
76
- uint256 nullifierHash,
77
- uint256 entityId,
78
- uint256[8] calldata proof
79
- ) public override onlyEditor(entityId) {
80
- uint8 depth = getDepth(entityId);
81
- uint256 root = getRoot(entityId);
82
- IVerifier verifier = verifiers[depth];
83
-
84
- _verifyProof(leak, root, nullifierHash, entityId, proof, verifier);
85
-
86
- emit LeakPublished(entityId, leak);
87
- }
88
89
  }
@@ -1,72 +1,115 @@
1
1
  //SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.4;
2
+ pragma solidity 0.8.4;
3
3
 
4
4
  /// @title Semaphore interface.
5
5
  /// @dev Interface of a Semaphore contract.
6
6
  interface ISemaphore {
7
- struct Verifier {
8
- address contractAddress;
9
- uint8 merkleTreeDepth;
10
- }
7
+ error Semaphore__CallerIsNotTheGroupAdmin();
8
+ error Semaphore__MerkleTreeDepthIsNotSupported();
9
+ error Semaphore__MerkleTreeRootIsExpired();
10
+ error Semaphore__MerkleTreeRootIsNotPartOfTheGroup();
11
11
 
12
- /// @dev Emitted when an admin is assigned to a group.
13
- /// @param groupId: Id of the group.
14
- /// @param oldAdmin: Old admin of the group.
15
- /// @param newAdmin: New admin of the group.
16
- event GroupAdminUpdated(uint256 indexed groupId, address indexed oldAdmin, address indexed newAdmin);
12
+ struct Verifier {
13
+ address contractAddress;
14
+ uint256 merkleTreeDepth;
15
+ }
17
16
 
18
- /// @dev Emitted when a Semaphore proof is verified.
19
- /// @param groupId: Id of the group.
20
- /// @param signal: Semaphore signal.
21
- event ProofVerified(uint256 indexed groupId, bytes32 signal);
17
+ /// It defines all the parameters needed to check whether a
18
+ /// zero-knowledge proof generated with a certain Merkle tree is still valid.
19
+ struct MerkleTreeExpiry {
20
+ uint256 rootDuration;
21
+ mapping(uint256 => uint256) rootCreationDates;
22
+ }
22
23
 
23
- /// @dev Saves the nullifier hash to avoid double signaling and emits an event
24
- /// if the zero-knowledge proof is valid.
25
- /// @param groupId: Id of the group.
26
- /// @param signal: Semaphore signal.
27
- /// @param nullifierHash: Nullifier hash.
28
- /// @param externalNullifier: External nullifier.
29
- /// @param proof: Zero-knowledge proof.
30
- function verifyProof(
31
- uint256 groupId,
32
- bytes32 signal,
33
- uint256 nullifierHash,
34
- uint256 externalNullifier,
35
- uint256[8] calldata proof
36
- ) external;
24
+ /// @dev Emitted when an admin is assigned to a group.
25
+ /// @param groupId: Id of the group.
26
+ /// @param oldAdmin: Old admin of the group.
27
+ /// @param newAdmin: New admin of the group.
28
+ event GroupAdminUpdated(uint256 indexed groupId, address indexed oldAdmin, address indexed newAdmin);
37
29
 
38
- /// @dev Creates a new group. Only the admin will be able to add or remove members.
39
- /// @param groupId: Id of the group.
40
- /// @param depth: Depth of the tree.
41
- /// @param zeroValue: Zero value of the tree.
42
- /// @param admin: Admin of the group.
43
- function createGroup(
44
- uint256 groupId,
45
- uint8 depth,
46
- uint256 zeroValue,
47
- address admin
48
- ) external;
30
+ /// @dev Emitted when a Semaphore proof is verified.
31
+ /// @param groupId: Id of the group.
32
+ /// @param signal: Semaphore signal.
33
+ event ProofVerified(uint256 indexed groupId, bytes32 signal);
49
34
 
50
- /// @dev Updates the group admin.
51
- /// @param groupId: Id of the group.
52
- /// @param newAdmin: New admin of the group.
53
- function updateGroupAdmin(uint256 groupId, address newAdmin) external;
35
+ /// @dev Saves the nullifier hash to avoid double signaling and emits an event
36
+ /// if the zero-knowledge proof is valid.
37
+ /// @param groupId: Id of the group.
38
+ /// @param merkleTreeRoot: Root of the Merkle tree.
39
+ /// @param signal: Semaphore signal.
40
+ /// @param nullifierHash: Nullifier hash.
41
+ /// @param externalNullifier: External nullifier.
42
+ /// @param proof: Zero-knowledge proof.
43
+ function verifyProof(
44
+ uint256 groupId,
45
+ uint256 merkleTreeRoot,
46
+ bytes32 signal,
47
+ uint256 nullifierHash,
48
+ uint256 externalNullifier,
49
+ uint256[8] calldata proof
50
+ ) external;
54
51
 
55
- /// @dev Adds a new member to an existing group.
56
- /// @param groupId: Id of the group.
57
- /// @param identityCommitment: New identity commitment.
58
- function addMember(uint256 groupId, uint256 identityCommitment) external;
52
+ /// @dev Creates a new group. Only the admin will be able to add or remove members.
53
+ /// @param groupId: Id of the group.
54
+ /// @param depth: Depth of the tree.
55
+ /// @param zeroValue: Zero value of the tree.
56
+ /// @param admin: Admin of the group.
57
+ function createGroup(
58
+ uint256 groupId,
59
+ uint256 depth,
60
+ uint256 zeroValue,
61
+ address admin
62
+ ) external;
59
63
 
60
- /// @dev Removes a member from an existing group. A proof of membership is
61
- /// needed to check if the node to be removed is part of the tree.
62
- /// @param groupId: Id of the group.
63
- /// @param identityCommitment: Identity commitment to be deleted.
64
- /// @param proofSiblings: Array of the sibling nodes of the proof of membership.
65
- /// @param proofPathIndices: Path of the proof of membership.
66
- function removeMember(
67
- uint256 groupId,
68
- uint256 identityCommitment,
69
- uint256[] calldata proofSiblings,
70
- uint8[] calldata proofPathIndices
71
- ) external;
64
+ /// @dev Creates a new group. Only the admin will be able to add or remove members.
65
+ /// @param groupId: Id of the group.
66
+ /// @param depth: Depth of the tree.
67
+ /// @param zeroValue: Zero value of the tree.
68
+ /// @param admin: Admin of the group.
69
+ /// @param merkleTreeRootDuration: Time before the validity of a root expires.
70
+ function createGroup(
71
+ uint256 groupId,
72
+ uint256 depth,
73
+ uint256 zeroValue,
74
+ address admin,
75
+ uint256 merkleTreeRootDuration
76
+ ) external;
77
+
78
+ /// @dev Updates the group admin.
79
+ /// @param groupId: Id of the group.
80
+ /// @param newAdmin: New admin of the group.
81
+ function updateGroupAdmin(uint256 groupId, address newAdmin) external;
82
+
83
+ /// @dev Adds a new member to an existing group.
84
+ /// @param groupId: Id of the group.
85
+ /// @param identityCommitment: New identity commitment.
86
+ function addMember(uint256 groupId, uint256 identityCommitment) external;
87
+
88
+ /// @dev Updates an identity commitment of an existing group. A proof of membership is
89
+ /// needed to check if the node to be updated is part of the tree.
90
+ /// @param groupId: Id of the group.
91
+ /// @param identityCommitment: Existing identity commitment to be updated.
92
+ /// @param newIdentityCommitment: New identity commitment.
93
+ /// @param proofSiblings: Array of the sibling nodes of the proof of membership.
94
+ /// @param proofPathIndices: Path of the proof of membership.
95
+ function updateMember(
96
+ uint256 groupId,
97
+ uint256 identityCommitment,
98
+ uint256 newIdentityCommitment,
99
+ uint256[] calldata proofSiblings,
100
+ uint8[] calldata proofPathIndices
101
+ ) external;
102
+
103
+ /// @dev Removes a member from an existing group. A proof of membership is
104
+ /// needed to check if the node to be removed is part of the tree.
105
+ /// @param groupId: Id of the group.
106
+ /// @param identityCommitment: Identity commitment to be removed.
107
+ /// @param proofSiblings: Array of the sibling nodes of the proof of membership.
108
+ /// @param proofPathIndices: Path of the proof of membership.
109
+ function removeMember(
110
+ uint256 groupId,
111
+ uint256 identityCommitment,
112
+ uint256[] calldata proofSiblings,
113
+ uint8[] calldata proofPathIndices
114
+ ) external;
72
115
  }
@@ -1,10 +1,12 @@
1
1
  //SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.4;
2
+ pragma solidity 0.8.4;
3
3
 
4
4
  /// @title SemaphoreCore interface.
5
5
  /// @dev Interface of SemaphoreCore contract.
6
6
  interface ISemaphoreCore {
7
- /// @notice Emitted when a proof is verified correctly and a new nullifier hash is added.
8
- /// @param nullifierHash: Hash of external and identity nullifiers.
9
- event NullifierHashAdded(uint256 nullifierHash);
7
+ error Semaphore__YouAreUsingTheSameNillifierTwice();
8
+
9
+ /// @notice Emitted when a proof is verified correctly and a new nullifier hash is added.
10
+ /// @param nullifierHash: Hash of external and identity nullifiers.
11
+ event NullifierHashAdded(uint256 nullifierHash);
10
12
  }
@@ -1,39 +1,55 @@
1
1
  //SPDX-License-Identifier: MIT
2
- pragma solidity ^0.8.4;
2
+ pragma solidity 0.8.4;
3
3
 
4
4
  /// @title SemaphoreGroups interface.
5
5
  /// @dev Interface of a SemaphoreGroups contract.
6
6
  interface ISemaphoreGroups {
7
- /// @dev Emitted when a new group is created.
8
- /// @param groupId: Id of the group.
9
- /// @param depth: Depth of the tree.
10
- /// @param zeroValue: Zero value of the tree.
11
- event GroupCreated(uint256 indexed groupId, uint8 depth, uint256 zeroValue);
12
-
13
- /// @dev Emitted when a new identity commitment is added.
14
- /// @param groupId: Group id of the group.
15
- /// @param identityCommitment: New identity commitment.
16
- /// @param root: New root hash of the tree.
17
- event MemberAdded(uint256 indexed groupId, uint256 identityCommitment, uint256 root);
18
-
19
- /// @dev Emitted when a new identity commitment is removed.
20
- /// @param groupId: Group id of the group.
21
- /// @param identityCommitment: New identity commitment.
22
- /// @param root: New root hash of the tree.
23
- event MemberRemoved(uint256 indexed groupId, uint256 identityCommitment, uint256 root);
24
-
25
- /// @dev Returns the last root hash of a group.
26
- /// @param groupId: Id of the group.
27
- /// @return Root hash of the group.
28
- function getRoot(uint256 groupId) external view returns (uint256);
29
-
30
- /// @dev Returns the depth of the tree of a group.
31
- /// @param groupId: Id of the group.
32
- /// @return Depth of the group tree.
33
- function getDepth(uint256 groupId) external view returns (uint8);
34
-
35
- /// @dev Returns the number of tree leaves of a group.
36
- /// @param groupId: Id of the group.
37
- /// @return Number of tree leaves.
38
- function getNumberOfLeaves(uint256 groupId) external view returns (uint256);
7
+ error Semaphore__GroupDoesNotExist();
8
+ error Semaphore__GroupAlreadyExists();
9
+ error Semaphore__GroupIdIsNotLessThanSnarkScalarField();
10
+
11
+ /// @dev Emitted when a new group is created.
12
+ /// @param groupId: Id of the group.
13
+ /// @param merkleTreeDepth: Depth of the tree.
14
+ /// @param zeroValue: Zero value of the tree.
15
+ event GroupCreated(uint256 indexed groupId, uint256 merkleTreeDepth, uint256 zeroValue);
16
+
17
+ /// @dev Emitted when a new identity commitment is added.
18
+ /// @param groupId: Group id of the group.
19
+ /// @param identityCommitment: New identity commitment.
20
+ /// @param merkleTreeRoot: New root hash of the tree.
21
+ event MemberAdded(uint256 indexed groupId, uint256 identityCommitment, uint256 merkleTreeRoot);
22
+
23
+ /// @dev Emitted when an identity commitment is updated.
24
+ /// @param groupId: Group id of the group.
25
+ /// @param identityCommitment: New identity commitment.
26
+ /// @param newIdentityCommitment: New identity commitment.
27
+ /// @param merkleTreeRoot: New root hash of the tree.
28
+ event MemberUpdated(
29
+ uint256 indexed groupId,
30
+ uint256 identityCommitment,
31
+ uint256 newIdentityCommitment,
32
+ uint256 merkleTreeRoot
33
+ );
34
+
35
+ /// @dev Emitted when a new identity commitment is removed.
36
+ /// @param groupId: Group id of the group.
37
+ /// @param identityCommitment: Existing identity commitment to be removed.
38
+ /// @param merkleTreeRoot: New root hash of the tree.
39
+ event MemberRemoved(uint256 indexed groupId, uint256 identityCommitment, uint256 merkleTreeRoot);
40
+
41
+ /// @dev Returns the last root hash of a group.
42
+ /// @param groupId: Id of the group.
43
+ /// @return Root hash of the group.
44
+ function getMerkleTreeRoot(uint256 groupId) external view returns (uint256);
45
+
46
+ /// @dev Returns the depth of the tree of a group.
47
+ /// @param groupId: Id of the group.
48
+ /// @return Depth of the group tree.
49
+ function getMerkleTreeDepth(uint256 groupId) external view returns (uint256);
50
+
51
+ /// @dev Returns the number of tree leaves of a group.
52
+ /// @param groupId: Id of the group.
53
+ /// @return Number of tree leaves.
54
+ function getNumberOfMerkleTreeLeaves(uint256 groupId) external view returns (uint256);
39
55
  }