@semaphore-protocol/contracts 3.15.2 → 4.0.0-alpha

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,28 +1,22 @@
1
1
  //SPDX-License-Identifier: MIT
2
- pragma solidity 0.8.4;
2
+ pragma solidity 0.8.23;
3
3
 
4
4
  /// @title Semaphore contract interface.
5
5
  interface ISemaphore {
6
- error Semaphore__CallerIsNotTheGroupAdmin();
6
+ error Semaphore__GroupHasNoMembers();
7
7
  error Semaphore__MerkleTreeDepthIsNotSupported();
8
8
  error Semaphore__MerkleTreeRootIsExpired();
9
9
  error Semaphore__MerkleTreeRootIsNotPartOfTheGroup();
10
- error Semaphore__YouAreUsingTheSameNillifierTwice();
10
+ error Semaphore__YouAreUsingTheSameNullifierTwice();
11
+ error Semaphore__InvalidProof();
11
12
 
12
- /// It defines all the group parameters, in addition to those in the Merkle tree.
13
+ /// It defines all the group parameters used by Semaphore.sol.
13
14
  struct Group {
14
- address admin;
15
15
  uint256 merkleTreeDuration;
16
16
  mapping(uint256 => uint256) merkleRootCreationDates;
17
- mapping(uint256 => bool) nullifierHashes;
17
+ mapping(uint256 => bool) nullifiers;
18
18
  }
19
19
 
20
- /// @dev Emitted when an admin is assigned to a group.
21
- /// @param groupId: Id of the group.
22
- /// @param oldAdmin: Old admin of the group.
23
- /// @param newAdmin: New admin of the group.
24
- event GroupAdminUpdated(uint256 indexed groupId, address indexed oldAdmin, address indexed newAdmin);
25
-
26
20
  /// @dev Emitted when the Merkle tree duration of a group is updated.
27
21
  /// @param groupId: Id of the group.
28
22
  /// @param oldMerkleTreeDuration: Old Merkle tree duration of the group.
@@ -33,53 +27,34 @@ interface ISemaphore {
33
27
  uint256 newMerkleTreeDuration
34
28
  );
35
29
 
36
- /// @dev Emitted when a Semaphore proof is verified.
30
+ /// @dev Emitted when a Semaphore proof is validated.
37
31
  /// @param groupId: Id of the group.
32
+ /// @param merkleTreeDepth: Depth of the Merkle tree.
38
33
  /// @param merkleTreeRoot: Root of the Merkle tree.
39
- /// @param nullifierHash: Nullifier hash.
40
- /// @param externalNullifier: External nullifier.
41
- /// @param signal: Semaphore signal.
42
- event ProofVerified(
34
+ /// @param nullifier: Nullifier.
35
+ /// @param message: Semaphore message.
36
+ /// @param scope: Scope.
37
+ /// @param proof: Zero-knowledge proof.
38
+ event ProofValidated(
43
39
  uint256 indexed groupId,
40
+ uint256 merkleTreeDepth,
44
41
  uint256 indexed merkleTreeRoot,
45
- uint256 nullifierHash,
46
- uint256 indexed externalNullifier,
47
- uint256 signal
42
+ uint256 nullifier,
43
+ uint256 message,
44
+ uint256 indexed scope,
45
+ uint256[8] proof
48
46
  );
49
47
 
50
- /// @dev Saves the nullifier hash to avoid double signaling and emits an event
51
- /// if the zero-knowledge proof is valid.
52
- /// @param groupId: Id of the group.
53
- /// @param merkleTreeRoot: Root of the Merkle tree.
54
- /// @param signal: Semaphore signal.
55
- /// @param nullifierHash: Nullifier hash.
56
- /// @param externalNullifier: External nullifier.
57
- /// @param proof: Zero-knowledge proof.
58
- function verifyProof(
59
- uint256 groupId,
60
- uint256 merkleTreeRoot,
61
- uint256 signal,
62
- uint256 nullifierHash,
63
- uint256 externalNullifier,
64
- uint256[8] calldata proof
65
- ) external;
66
-
67
- /// @dev Creates a new group. Only the admin will be able to add or remove members.
68
- /// @param groupId: Id of the group.
69
- /// @param depth: Depth of the tree.
70
- /// @param admin: Admin of the group.
71
- function createGroup(uint256 groupId, uint256 depth, address admin) external;
48
+ /// @dev See {SemaphoreGroups-_createGroup}.
49
+ function createGroup(uint256 groupId, address admin) external;
72
50
 
73
- /// @dev Creates a new group. Only the admin will be able to add or remove members.
51
+ /// @dev It creates a group with a custom Merkle tree duration.
74
52
  /// @param groupId: Id of the group.
75
- /// @param depth: Depth of the tree.
76
53
  /// @param admin: Admin of the group.
77
- /// @param merkleTreeRootDuration: Time before the validity of a root expires.
78
- function createGroup(uint256 groupId, uint256 depth, address admin, uint256 merkleTreeRootDuration) external;
54
+ /// @param merkleTreeDuration: Merkle tree duration.
55
+ function createGroup(uint256 groupId, address admin, uint256 merkleTreeDuration) external;
79
56
 
80
- /// @dev Updates the group admin.
81
- /// @param groupId: Id of the group.
82
- /// @param newAdmin: New admin of the group.
57
+ /// @dev See {SemaphoreGroups-_updateGroupAdmin}.
83
58
  function updateGroupAdmin(uint256 groupId, address newAdmin) external;
84
59
 
85
60
  /// @dev Updates the group Merkle tree duration.
@@ -87,41 +62,57 @@ interface ISemaphore {
87
62
  /// @param newMerkleTreeDuration: New Merkle tree duration.
88
63
  function updateGroupMerkleTreeDuration(uint256 groupId, uint256 newMerkleTreeDuration) external;
89
64
 
90
- /// @dev Adds a new member to an existing group.
91
- /// @param groupId: Id of the group.
92
- /// @param identityCommitment: New identity commitment.
65
+ /// @dev See {SemaphoreGroups-_addMember}.
93
66
  function addMember(uint256 groupId, uint256 identityCommitment) external;
94
67
 
95
- /// @dev Adds new members to an existing group.
96
- /// @param groupId: Id of the group.
97
- /// @param identityCommitments: New identity commitments.
68
+ /// @dev See {SemaphoreGroups-_addMembers}.
98
69
  function addMembers(uint256 groupId, uint256[] calldata identityCommitments) external;
99
70
 
100
- /// @dev Updates an identity commitment of an existing group. A proof of membership is
101
- /// needed to check if the node to be updated is part of the tree.
102
- /// @param groupId: Id of the group.
103
- /// @param identityCommitment: Existing identity commitment to be updated.
104
- /// @param newIdentityCommitment: New identity commitment.
105
- /// @param proofSiblings: Array of the sibling nodes of the proof of membership.
106
- /// @param proofPathIndices: Path of the proof of membership.
71
+ /// @dev See {SemaphoreGroups-_updateMember}.
107
72
  function updateMember(
108
73
  uint256 groupId,
109
- uint256 identityCommitment,
74
+ uint256 oldIdentityCommitment,
110
75
  uint256 newIdentityCommitment,
111
- uint256[] calldata proofSiblings,
112
- uint8[] calldata proofPathIndices
76
+ uint256[] calldata merkleProofSiblings
113
77
  ) external;
114
78
 
115
- /// @dev Removes a member from an existing group. A proof of membership is
116
- /// needed to check if the node to be removed is part of the tree.
79
+ /// @dev See {SemaphoreGroups-_removeMember}.
80
+ function removeMember(uint256 groupId, uint256 identityCommitment, uint256[] calldata merkleProofSiblings) external;
81
+
82
+ /// @dev Saves the nullifier hash to avoid double signaling and emits an event
83
+ /// if the zero-knowledge proof is valid.
117
84
  /// @param groupId: Id of the group.
118
- /// @param identityCommitment: Identity commitment to be removed.
119
- /// @param proofSiblings: Array of the sibling nodes of the proof of membership.
120
- /// @param proofPathIndices: Path of the proof of membership.
121
- function removeMember(
85
+ /// @param merkleTreeDepth: Depth of the Merkle tree.
86
+ /// @param merkleTreeRoot: Root of the Merkle tree.
87
+ /// @param nullifier: Nullifier.
88
+ /// @param message: Semaphore message.
89
+ /// @param scope: Scope.
90
+ /// @param proof: Zero-knowledge proof.
91
+ function validateProof(
122
92
  uint256 groupId,
123
- uint256 identityCommitment,
124
- uint256[] calldata proofSiblings,
125
- uint8[] calldata proofPathIndices
93
+ uint256 merkleTreeDepth,
94
+ uint256 merkleTreeRoot,
95
+ uint256 nullifier,
96
+ uint256 message,
97
+ uint256 scope,
98
+ uint256[8] calldata proof
126
99
  ) external;
100
+
101
+ /// @dev Verifies a zero-knowledge proof by returning true or false.
102
+ /// @param groupId: Id of the group.
103
+ /// @param merkleTreeDepth: Depth of the Merkle tree.
104
+ /// @param merkleTreeRoot: Root of the Merkle tree.
105
+ /// @param nullifier: Nullifier.
106
+ /// @param message: Semaphore message.
107
+ /// @param scope: Scope.
108
+ /// @param proof: Zero-knowledge proof.
109
+ function verifyProof(
110
+ uint256 groupId,
111
+ uint256 merkleTreeDepth,
112
+ uint256 merkleTreeRoot,
113
+ uint256 nullifier,
114
+ uint256 message,
115
+ uint256 scope,
116
+ uint256[8] calldata proof
117
+ ) external view returns (bool);
127
118
  }
@@ -1,24 +1,41 @@
1
1
  //SPDX-License-Identifier: MIT
2
- pragma solidity 0.8.4;
2
+ pragma solidity 0.8.23;
3
3
 
4
4
  /// @title SemaphoreGroups contract interface.
5
5
  interface ISemaphoreGroups {
6
6
  error Semaphore__GroupDoesNotExist();
7
7
  error Semaphore__GroupAlreadyExists();
8
+ error Semaphore__CallerIsNotTheGroupAdmin();
8
9
 
9
10
  /// @dev Emitted when a new group is created.
10
11
  /// @param groupId: Id of the group.
11
- /// @param merkleTreeDepth: Depth of the tree.
12
- /// @param zeroValue: Zero value of the tree.
13
- event GroupCreated(uint256 indexed groupId, uint256 merkleTreeDepth, uint256 zeroValue);
12
+ event GroupCreated(uint256 indexed groupId);
13
+
14
+ /// @dev Emitted when an admin is assigned to a group.
15
+ /// @param groupId: Id of the group.
16
+ /// @param oldAdmin: Old admin of the group.
17
+ /// @param newAdmin: New admin of the group.
18
+ event GroupAdminUpdated(uint256 indexed groupId, address indexed oldAdmin, address indexed newAdmin);
14
19
 
15
20
  /// @dev Emitted when a new identity commitment is added.
16
21
  /// @param groupId: Group id of the group.
17
- /// @param index: Identity commitment index.
22
+ /// @param index: Merkle tree leaf index.
18
23
  /// @param identityCommitment: New identity commitment.
19
24
  /// @param merkleTreeRoot: New root hash of the tree.
20
25
  event MemberAdded(uint256 indexed groupId, uint256 index, uint256 identityCommitment, uint256 merkleTreeRoot);
21
26
 
27
+ /// @dev Emitted when many identity commitments are added at the same time.
28
+ /// @param groupId: Group id of the group.
29
+ /// @param startIndex: Index of the first element of the new identity commitments in the merkle tree.
30
+ /// @param identityCommitments: The new identity commitments.
31
+ /// @param merkleTreeRoot: New root hash of the tree.
32
+ event MembersAdded(
33
+ uint256 indexed groupId,
34
+ uint256 startIndex,
35
+ uint256[] identityCommitments,
36
+ uint256 merkleTreeRoot
37
+ );
38
+
22
39
  /// @dev Emitted when an identity commitment is updated.
23
40
  /// @param groupId: Group id of the group.
24
41
  /// @param index: Identity commitment index.
@@ -40,6 +57,18 @@ interface ISemaphoreGroups {
40
57
  /// @param merkleTreeRoot: New root hash of the tree.
41
58
  event MemberRemoved(uint256 indexed groupId, uint256 index, uint256 identityCommitment, uint256 merkleTreeRoot);
42
59
 
60
+ /// @dev Returns true if a member exists in a group.
61
+ /// @param groupId: Id of the group.
62
+ /// @param identityCommitment: Identity commitment.
63
+ /// @return True if the member exists, false otherwise.
64
+ function hasMember(uint256 groupId, uint256 identityCommitment) external view returns (bool);
65
+
66
+ /// @dev Returns the index of a member.
67
+ /// @param groupId: Id of the group.
68
+ /// @param identityCommitment: Identity commitment.
69
+ /// @return Index of member.
70
+ function indexOf(uint256 groupId, uint256 identityCommitment) external view returns (uint256);
71
+
43
72
  /// @dev Returns the last root hash of a group.
44
73
  /// @param groupId: Id of the group.
45
74
  /// @return Root hash of the group.
@@ -53,5 +82,5 @@ interface ISemaphoreGroups {
53
82
  /// @dev Returns the number of tree leaves of a group.
54
83
  /// @param groupId: Id of the group.
55
84
  /// @return Number of tree leaves.
56
- function getNumberOfMerkleTreeLeaves(uint256 groupId) external view returns (uint256);
85
+ function getMerkleTreeSize(uint256 groupId) external view returns (uint256);
57
86
  }
@@ -1,37 +1,13 @@
1
1
  //SPDX-License-Identifier: MIT
2
- pragma solidity 0.8.4;
3
-
4
- import "../base/Pairing.sol";
2
+ pragma solidity 0.8.23;
5
3
 
6
4
  /// @title SemaphoreVerifier contract interface.
7
5
  interface ISemaphoreVerifier {
8
- struct VerificationKey {
9
- Pairing.G1Point alfa1;
10
- Pairing.G2Point beta2;
11
- Pairing.G2Point gamma2;
12
- Pairing.G2Point delta2;
13
- Pairing.G1Point[] IC;
14
- }
15
-
16
- struct Proof {
17
- Pairing.G1Point A;
18
- Pairing.G2Point B;
19
- Pairing.G1Point C;
20
- }
21
-
22
- /// @dev Verifies whether a Semaphore proof is valid.
23
- /// @param merkleTreeRoot: Root of the Merkle tree.
24
- /// @param nullifierHash: Nullifier hash.
25
- /// @param signal: Semaphore signal.
26
- /// @param externalNullifier: External nullifier.
27
- /// @param proof: Zero-knowledge proof.
28
- /// @param merkleTreeDepth: Depth of the tree.
29
6
  function verifyProof(
30
- uint256 merkleTreeRoot,
31
- uint256 nullifierHash,
32
- uint256 signal,
33
- uint256 externalNullifier,
34
- uint256[8] calldata proof,
35
- uint256 merkleTreeDepth
36
- ) external view;
7
+ uint[2] calldata _pA,
8
+ uint[2][2] calldata _pB,
9
+ uint[2] calldata _pC,
10
+ uint[4] calldata _pubSignals,
11
+ uint merkleTreeDepth
12
+ ) external view returns (bool);
37
13
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@semaphore-protocol/contracts",
3
- "version": "3.15.2",
3
+ "version": "4.0.0-alpha",
4
4
  "description": "Semaphore contracts to manage groups and broadcast anonymous signals.",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -30,7 +30,6 @@
30
30
  "access": "public"
31
31
  },
32
32
  "dependencies": {
33
- "@openzeppelin/contracts": "4.7.3",
34
- "@zk-kit/incremental-merkle-tree.sol": "1.3.3"
33
+ "@zk-kit/imt.sol": "2.0.0-beta.5"
35
34
  }
36
35
  }
package/base/Pairing.sol DELETED
@@ -1,151 +0,0 @@
1
- // Copyright 2017 Christian Reitwiessner
2
- // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
3
- // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
4
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
5
- //
6
- // The following Pairing library is a modified version adapted to Semaphore.
7
- //
8
- // SPDX-License-Identifier: MIT
9
- pragma solidity ^0.8.4;
10
-
11
- library Pairing {
12
- error InvalidProof();
13
-
14
- // The prime q in the base field F_q for G1
15
- uint256 constant BASE_MODULUS = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
16
-
17
- // The prime modulus of the scalar field of G1.
18
- uint256 constant SCALAR_MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
19
-
20
- struct G1Point {
21
- uint256 X;
22
- uint256 Y;
23
- }
24
-
25
- // Encoding of field elements is: X[0] * z + X[1]
26
- struct G2Point {
27
- uint256[2] X;
28
- uint256[2] Y;
29
- }
30
-
31
- /// @return the generator of G1
32
- function P1() public pure returns (G1Point memory) {
33
- return G1Point(1, 2);
34
- }
35
-
36
- /// @return the generator of G2
37
- function P2() public pure returns (G2Point memory) {
38
- return
39
- G2Point(
40
- [
41
- 11559732032986387107991004021392285783925812861821192530917403151452391805634,
42
- 10857046999023057135944570762232829481370756359578518086990519993285655852781
43
- ],
44
- [
45
- 4082367875863433681332203403145435568316851327593401208105741076214120093531,
46
- 8495653923123431417604973247489272438418190587263600148770280649306958101930
47
- ]
48
- );
49
- }
50
-
51
- /// @return r the negation of p, i.e. p.addition(p.negate()) should be zero.
52
- function negate(G1Point memory p) public pure returns (G1Point memory r) {
53
- if (p.X == 0 && p.Y == 0) {
54
- return G1Point(0, 0);
55
- }
56
-
57
- // Validate input or revert
58
- if (p.X >= BASE_MODULUS || p.Y >= BASE_MODULUS) {
59
- revert InvalidProof();
60
- }
61
-
62
- // We know p.Y > 0 and p.Y < BASE_MODULUS.
63
- return G1Point(p.X, BASE_MODULUS - p.Y);
64
- }
65
-
66
- /// @return r the sum of two points of G1
67
- function addition(G1Point memory p1, G1Point memory p2) public view returns (G1Point memory r) {
68
- // By EIP-196 all input is validated to be less than the BASE_MODULUS and form points
69
- // on the curve.
70
- uint256[4] memory input;
71
-
72
- input[0] = p1.X;
73
- input[1] = p1.Y;
74
- input[2] = p2.X;
75
- input[3] = p2.Y;
76
-
77
- bool success;
78
-
79
- // solium-disable-next-line security/no-inline-assembly
80
- assembly {
81
- success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60)
82
- }
83
-
84
- if (!success) {
85
- revert InvalidProof();
86
- }
87
- }
88
-
89
- /// @return r the product of a point on G1 and a scalar, i.e.
90
- /// p == p.scalar_mul(1) and p.addition(p) == p.scalar_mul(2) for all points p.
91
- function scalar_mul(G1Point memory p, uint256 s) public view returns (G1Point memory r) {
92
- // By EIP-196 the values p.X and p.Y are verified to be less than the BASE_MODULUS and
93
- // form a valid point on the curve. But the scalar is not verified, so we do that explicitly.
94
- if (s >= SCALAR_MODULUS) {
95
- revert InvalidProof();
96
- }
97
-
98
- uint256[3] memory input;
99
-
100
- input[0] = p.X;
101
- input[1] = p.Y;
102
- input[2] = s;
103
-
104
- bool success;
105
-
106
- // solium-disable-next-line security/no-inline-assembly
107
- assembly {
108
- success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60)
109
- }
110
-
111
- if (!success) {
112
- revert InvalidProof();
113
- }
114
- }
115
-
116
- /// Asserts the pairing check
117
- /// e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1
118
- /// For example pairing([P1(), P1().negate()], [P2(), P2()]) should succeed
119
- function pairingCheck(G1Point[] memory p1, G2Point[] memory p2) public view {
120
- // By EIP-197 all input is verified to be less than the BASE_MODULUS and form elements in their
121
- // respective groups of the right order.
122
- if (p1.length != p2.length) {
123
- revert InvalidProof();
124
- }
125
-
126
- uint256 elements = p1.length;
127
- uint256 inputSize = elements * 6;
128
- uint256[] memory input = new uint256[](inputSize);
129
-
130
- for (uint256 i = 0; i < elements; i++) {
131
- input[i * 6 + 0] = p1[i].X;
132
- input[i * 6 + 1] = p1[i].Y;
133
- input[i * 6 + 2] = p2[i].X[0];
134
- input[i * 6 + 3] = p2[i].X[1];
135
- input[i * 6 + 4] = p2[i].Y[0];
136
- input[i * 6 + 5] = p2[i].Y[1];
137
- }
138
-
139
- uint256[1] memory out;
140
- bool success;
141
-
142
- // solium-disable-next-line security/no-inline-assembly
143
- assembly {
144
- success := staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20)
145
- }
146
-
147
- if (!success || out[0] != 1) {
148
- revert InvalidProof();
149
- }
150
- }
151
- }
@@ -1,96 +0,0 @@
1
- //SPDX-License-Identifier: MIT
2
- pragma solidity 0.8.4;
3
-
4
- import "../interfaces/ISemaphoreVoting.sol";
5
- import "../interfaces/ISemaphoreVerifier.sol";
6
- import "../base/SemaphoreGroups.sol";
7
-
8
- /// @title Semaphore voting contract.
9
- /// @notice It allows users to vote anonymously in a poll.
10
- /// @dev The following code allows you to create polls, add voters and allow them to vote anonymously.
11
- contract SemaphoreVoting is ISemaphoreVoting, SemaphoreGroups {
12
- ISemaphoreVerifier public verifier;
13
-
14
- /// @dev Gets a poll id and returns the poll data.
15
- mapping(uint256 => Poll) internal polls;
16
-
17
- /// @dev Checks if the poll coordinator is the transaction sender.
18
- /// @param pollId: Id of the poll.
19
- modifier onlyCoordinator(uint256 pollId) {
20
- if (polls[pollId].coordinator != _msgSender()) {
21
- revert Semaphore__CallerIsNotThePollCoordinator();
22
- }
23
-
24
- _;
25
- }
26
-
27
- /// @dev Initializes the Semaphore verifier used to verify the user's ZK proofs.
28
- /// @param _verifier: Semaphore verifier address.
29
- constructor(ISemaphoreVerifier _verifier) {
30
- verifier = _verifier;
31
- }
32
-
33
- /// @dev See {ISemaphoreVoting-createPoll}.
34
- function createPoll(uint256 pollId, address coordinator, uint256 merkleTreeDepth) public override {
35
- if (merkleTreeDepth < 16 || merkleTreeDepth > 32) {
36
- revert Semaphore__MerkleTreeDepthIsNotSupported();
37
- }
38
-
39
- _createGroup(pollId, merkleTreeDepth);
40
-
41
- polls[pollId].coordinator = coordinator;
42
-
43
- emit PollCreated(pollId, coordinator);
44
- }
45
-
46
- /// @dev See {ISemaphoreVoting-addVoter}.
47
- function addVoter(uint256 pollId, uint256 identityCommitment) public override onlyCoordinator(pollId) {
48
- if (polls[pollId].state != PollState.Created) {
49
- revert Semaphore__PollHasAlreadyBeenStarted();
50
- }
51
-
52
- _addMember(pollId, identityCommitment);
53
- }
54
-
55
- /// @dev See {ISemaphoreVoting-addVoter}.
56
- function startPoll(uint256 pollId, uint256 encryptionKey) public override onlyCoordinator(pollId) {
57
- if (polls[pollId].state != PollState.Created) {
58
- revert Semaphore__PollHasAlreadyBeenStarted();
59
- }
60
-
61
- polls[pollId].state = PollState.Ongoing;
62
-
63
- emit PollStarted(pollId, _msgSender(), encryptionKey);
64
- }
65
-
66
- /// @dev See {ISemaphoreVoting-castVote}.
67
- function castVote(uint256 vote, uint256 nullifierHash, uint256 pollId, uint256[8] calldata proof) public override {
68
- if (polls[pollId].state != PollState.Ongoing) {
69
- revert Semaphore__PollIsNotOngoing();
70
- }
71
-
72
- if (polls[pollId].nullifierHashes[nullifierHash]) {
73
- revert Semaphore__YouAreUsingTheSameNillifierTwice();
74
- }
75
-
76
- uint256 merkleTreeDepth = getMerkleTreeDepth(pollId);
77
- uint256 merkleTreeRoot = getMerkleTreeRoot(pollId);
78
-
79
- verifier.verifyProof(merkleTreeRoot, nullifierHash, vote, pollId, proof, merkleTreeDepth);
80
-
81
- polls[pollId].nullifierHashes[nullifierHash] = true;
82
-
83
- emit VoteAdded(pollId, vote);
84
- }
85
-
86
- /// @dev See {ISemaphoreVoting-publishDecryptionKey}.
87
- function endPoll(uint256 pollId, uint256 decryptionKey) public override onlyCoordinator(pollId) {
88
- if (polls[pollId].state != PollState.Ongoing) {
89
- revert Semaphore__PollIsNotOngoing();
90
- }
91
-
92
- polls[pollId].state = PollState.Ended;
93
-
94
- emit PollEnded(pollId, _msgSender(), decryptionKey);
95
- }
96
- }
@@ -1,77 +0,0 @@
1
- //SPDX-License-Identifier: MIT
2
- pragma solidity 0.8.4;
3
-
4
- import "../interfaces/ISemaphoreWhistleblowing.sol";
5
- import "../interfaces/ISemaphoreVerifier.sol";
6
- import "../base/SemaphoreGroups.sol";
7
-
8
- /// @title Semaphore whistleblowing contract.
9
- /// @notice It allows users to leak information anonymously .
10
- /// @dev The following code allows you to create entities for whistleblowers (e.g. non-profit
11
- /// organization, newspaper) and allow them to leak anonymously.
12
- /// Leaks can be IPFS hashes, permanent links or other kinds of references.
13
- contract SemaphoreWhistleblowing is ISemaphoreWhistleblowing, SemaphoreGroups {
14
- ISemaphoreVerifier public verifier;
15
-
16
- /// @dev Gets an entity id and return its editor address.
17
- mapping(uint256 => address) private entities;
18
-
19
- /// @dev Checks if the editor is the transaction sender.
20
- /// @param entityId: Id of the entity.
21
- modifier onlyEditor(uint256 entityId) {
22
- if (entities[entityId] != _msgSender()) {
23
- revert Semaphore__CallerIsNotTheEditor();
24
- }
25
-
26
- _;
27
- }
28
-
29
- /// @dev Initializes the Semaphore verifier used to verify the user's ZK proofs.
30
- /// @param _verifier: Semaphore verifier address.
31
- constructor(ISemaphoreVerifier _verifier) {
32
- verifier = _verifier;
33
- }
34
-
35
- /// @dev See {ISemaphoreWhistleblowing-createEntity}.
36
- function createEntity(uint256 entityId, address editor, uint256 merkleTreeDepth) public override {
37
- if (merkleTreeDepth < 16 || merkleTreeDepth > 32) {
38
- revert Semaphore__MerkleTreeDepthIsNotSupported();
39
- }
40
-
41
- _createGroup(entityId, merkleTreeDepth);
42
-
43
- entities[entityId] = editor;
44
-
45
- emit EntityCreated(entityId, editor);
46
- }
47
-
48
- /// @dev See {ISemaphoreWhistleblowing-addWhistleblower}.
49
- function addWhistleblower(uint256 entityId, uint256 identityCommitment) public override onlyEditor(entityId) {
50
- _addMember(entityId, identityCommitment);
51
- }
52
-
53
- /// @dev See {ISemaphoreWhistleblowing-removeWhistleblower}.
54
- function removeWhistleblower(
55
- uint256 entityId,
56
- uint256 identityCommitment,
57
- uint256[] calldata proofSiblings,
58
- uint8[] calldata proofPathIndices
59
- ) public override onlyEditor(entityId) {
60
- _removeMember(entityId, identityCommitment, proofSiblings, proofPathIndices);
61
- }
62
-
63
- /// @dev See {ISemaphoreWhistleblowing-publishLeak}.
64
- function publishLeak(
65
- uint256 leak,
66
- uint256 nullifierHash,
67
- uint256 entityId,
68
- uint256[8] calldata proof
69
- ) public override {
70
- uint256 merkleTreeDepth = getMerkleTreeDepth(entityId);
71
- uint256 merkleTreeRoot = getMerkleTreeRoot(entityId);
72
-
73
- verifier.verifyProof(merkleTreeRoot, nullifierHash, leak, entityId, proof, merkleTreeDepth);
74
-
75
- emit LeakPublished(entityId, leak);
76
- }
77
- }