@semaphore-protocol/contracts 0.1.0 → 0.2.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.
- package/Semaphore.sol +84 -84
- package/base/SemaphoreCore.sol +41 -41
- package/base/SemaphoreGroups.sol +70 -70
- package/extensions/SemaphoreVoting.sol +74 -74
- package/extensions/SemaphoreWhistleblowing.sol +61 -61
- package/interfaces/ISemaphore.sol +58 -58
- package/interfaces/ISemaphoreCore.sol +3 -3
- package/interfaces/ISemaphoreGroups.sol +27 -27
- package/interfaces/ISemaphoreNullifiers.sol +6 -6
- package/interfaces/ISemaphoreVoting.sol +59 -59
- package/interfaces/ISemaphoreWhistleblowing.sol +43 -43
- package/interfaces/IVerifier.sol +6 -6
- package/package.json +36 -36
- package/{base/Verifier.sol → verifiers/Verifier16.sol} +40 -53
- package/verifiers/Verifier17.sol +237 -0
- package/verifiers/Verifier18.sol +237 -0
- package/verifiers/Verifier19.sol +237 -0
- package/verifiers/Verifier20.sol +237 -0
- package/verifiers/Verifier21.sol +237 -0
- package/verifiers/Verifier22.sol +237 -0
- package/verifiers/Verifier23.sol +237 -0
- package/verifiers/Verifier24.sol +237 -0
- package/verifiers/Verifier25.sol +237 -0
- package/verifiers/Verifier26.sol +237 -0
- package/verifiers/Verifier27.sol +237 -0
- package/verifiers/Verifier28.sol +237 -0
- package/verifiers/Verifier29.sol +237 -0
- package/verifiers/Verifier30.sol +237 -0
- package/verifiers/Verifier31.sol +237 -0
- package/verifiers/Verifier32.sol +237 -0
package/Semaphore.sol
CHANGED
|
@@ -8,89 +8,89 @@ import "./base/SemaphoreGroups.sol";
|
|
|
8
8
|
|
|
9
9
|
/// @title Semaphore
|
|
10
10
|
contract Semaphore is ISemaphore, SemaphoreCore, SemaphoreGroups {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
11
|
+
/// @dev Gets a tree depth and returns its verifier address.
|
|
12
|
+
mapping(uint8 => IVerifier) public verifiers;
|
|
13
|
+
|
|
14
|
+
/// @dev Gets a group id and returns the group admin address.
|
|
15
|
+
mapping(uint256 => address) public groupAdmins;
|
|
16
|
+
|
|
17
|
+
/// @dev Checks if the group admin is the transaction sender.
|
|
18
|
+
/// @param groupId: Id of the group.
|
|
19
|
+
modifier onlyGroupAdmin(uint256 groupId) {
|
|
20
|
+
require(groupAdmins[groupId] == _msgSender(), "Semaphore: caller is not the group admin");
|
|
21
|
+
_;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/// @dev Checks if there is a verifier for the given tree depth.
|
|
25
|
+
/// @param depth: Depth of the tree.
|
|
26
|
+
modifier onlySupportedDepth(uint8 depth) {
|
|
27
|
+
require(address(verifiers[depth]) != address(0), "Semaphore: tree depth is not supported");
|
|
28
|
+
_;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// @dev Initializes the Semaphore verifiers used to verify the user's ZK proofs.
|
|
32
|
+
/// @param _verifiers: List of Semaphore verifiers (address and related Merkle tree depth).
|
|
33
|
+
constructor(Verifier[] memory _verifiers) {
|
|
34
|
+
for (uint8 i = 0; i < _verifiers.length; i++) {
|
|
35
|
+
verifiers[_verifiers[i].merkleTreeDepth] = IVerifier(_verifiers[i].contractAddress);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/// @dev See {ISemaphore-createGroup}.
|
|
40
|
+
function createGroup(
|
|
41
|
+
uint256 groupId,
|
|
42
|
+
uint8 depth,
|
|
43
|
+
uint256 zeroValue,
|
|
44
|
+
address admin
|
|
45
|
+
) external override onlySupportedDepth(depth) {
|
|
46
|
+
_createGroup(groupId, depth, zeroValue);
|
|
47
|
+
|
|
48
|
+
groupAdmins[groupId] = admin;
|
|
49
|
+
|
|
50
|
+
emit GroupAdminUpdated(groupId, address(0), admin);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// @dev See {ISemaphore-updateGroupAdmin}.
|
|
54
|
+
function updateGroupAdmin(uint256 groupId, address newAdmin) external override onlyGroupAdmin(groupId) {
|
|
55
|
+
groupAdmins[groupId] = newAdmin;
|
|
56
|
+
|
|
57
|
+
emit GroupAdminUpdated(groupId, _msgSender(), newAdmin);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/// @dev See {ISemaphore-addMember}.
|
|
61
|
+
function addMember(uint256 groupId, uint256 identityCommitment) external override onlyGroupAdmin(groupId) {
|
|
62
|
+
_addMember(groupId, identityCommitment);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/// @dev See {ISemaphore-removeMember}.
|
|
66
|
+
function removeMember(
|
|
67
|
+
uint256 groupId,
|
|
68
|
+
uint256 identityCommitment,
|
|
69
|
+
uint256[] calldata proofSiblings,
|
|
70
|
+
uint8[] calldata proofPathIndices
|
|
71
|
+
) external override onlyGroupAdmin(groupId) {
|
|
72
|
+
_removeMember(groupId, identityCommitment, proofSiblings, proofPathIndices);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/// @dev See {ISemaphore-verifyProof}.
|
|
76
|
+
function verifyProof(
|
|
77
|
+
uint256 groupId,
|
|
78
|
+
bytes32 signal,
|
|
79
|
+
uint256 nullifierHash,
|
|
80
|
+
uint256 externalNullifier,
|
|
81
|
+
uint256[8] calldata proof
|
|
82
|
+
) external override {
|
|
83
|
+
uint256 root = getRoot(groupId);
|
|
84
|
+
uint8 depth = getDepth(groupId);
|
|
85
|
+
|
|
86
|
+
require(depth != 0, "Semaphore: group does not exist");
|
|
87
|
+
|
|
88
|
+
IVerifier verifier = verifiers[depth];
|
|
89
|
+
|
|
90
|
+
_verifyProof(signal, root, nullifierHash, externalNullifier, proof, verifier);
|
|
91
|
+
|
|
92
|
+
_saveNullifierHash(nullifierHash);
|
|
93
|
+
|
|
94
|
+
emit ProofVerified(groupId, signal);
|
|
36
95
|
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/// @dev See {ISemaphore-createGroup}.
|
|
40
|
-
function createGroup(
|
|
41
|
-
uint256 groupId,
|
|
42
|
-
uint8 depth,
|
|
43
|
-
uint256 zeroValue,
|
|
44
|
-
address admin
|
|
45
|
-
) external override onlySupportedDepth(depth) {
|
|
46
|
-
_createGroup(groupId, depth, zeroValue);
|
|
47
|
-
|
|
48
|
-
groupAdmins[groupId] = admin;
|
|
49
|
-
|
|
50
|
-
emit GroupAdminUpdated(groupId, address(0), admin);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/// @dev See {ISemaphore-updateGroupAdmin}.
|
|
54
|
-
function updateGroupAdmin(uint256 groupId, address newAdmin) external override onlyGroupAdmin(groupId) {
|
|
55
|
-
groupAdmins[groupId] = newAdmin;
|
|
56
|
-
|
|
57
|
-
emit GroupAdminUpdated(groupId, _msgSender(), newAdmin);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/// @dev See {ISemaphore-addMember}.
|
|
61
|
-
function addMember(uint256 groupId, uint256 identityCommitment) external override onlyGroupAdmin(groupId) {
|
|
62
|
-
_addMember(groupId, identityCommitment);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/// @dev See {ISemaphore-removeMember}.
|
|
66
|
-
function removeMember(
|
|
67
|
-
uint256 groupId,
|
|
68
|
-
uint256 identityCommitment,
|
|
69
|
-
uint256[] calldata proofSiblings,
|
|
70
|
-
uint8[] calldata proofPathIndices
|
|
71
|
-
) external override onlyGroupAdmin(groupId) {
|
|
72
|
-
_removeMember(groupId, identityCommitment, proofSiblings, proofPathIndices);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/// @dev See {ISemaphore-verifyProof}.
|
|
76
|
-
function verifyProof(
|
|
77
|
-
uint256 groupId,
|
|
78
|
-
bytes32 signal,
|
|
79
|
-
uint256 nullifierHash,
|
|
80
|
-
uint256 externalNullifier,
|
|
81
|
-
uint256[8] calldata proof
|
|
82
|
-
) external override {
|
|
83
|
-
uint256 root = getRoot(groupId);
|
|
84
|
-
uint8 depth = getDepth(groupId);
|
|
85
|
-
|
|
86
|
-
require(depth != 0, "Semaphore: group does not exist");
|
|
87
|
-
|
|
88
|
-
IVerifier verifier = verifiers[depth];
|
|
89
|
-
|
|
90
|
-
_verifyProof(signal, root, nullifierHash, externalNullifier, proof, verifier);
|
|
91
|
-
|
|
92
|
-
_saveNullifierHash(nullifierHash);
|
|
93
|
-
|
|
94
|
-
emit ProofVerified(groupId, signal);
|
|
95
|
-
}
|
|
96
96
|
}
|
package/base/SemaphoreCore.sol
CHANGED
|
@@ -10,50 +10,50 @@ import "../interfaces/IVerifier.sol";
|
|
|
10
10
|
/// nullifier to prevent double-signaling. External nullifier and Merkle trees (i.e. groups) must be
|
|
11
11
|
/// managed externally.
|
|
12
12
|
contract SemaphoreCore is ISemaphoreCore {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
/// @dev Gets a nullifier hash and returns true or false.
|
|
14
|
+
/// It is used to prevent double-signaling.
|
|
15
|
+
mapping(uint256 => bool) internal nullifierHashes;
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
17
|
+
/// @dev Asserts that no nullifier already exists and if the zero-knowledge proof is valid.
|
|
18
|
+
/// Otherwise it reverts.
|
|
19
|
+
/// @param signal: Semaphore signal.
|
|
20
|
+
/// @param root: Root of the Merkle tree.
|
|
21
|
+
/// @param nullifierHash: Nullifier hash.
|
|
22
|
+
/// @param externalNullifier: External nullifier.
|
|
23
|
+
/// @param proof: Zero-knowledge proof.
|
|
24
|
+
/// @param verifier: Verifier address.
|
|
25
|
+
function _verifyProof(
|
|
26
|
+
bytes32 signal,
|
|
27
|
+
uint256 root,
|
|
28
|
+
uint256 nullifierHash,
|
|
29
|
+
uint256 externalNullifier,
|
|
30
|
+
uint256[8] calldata proof,
|
|
31
|
+
IVerifier verifier
|
|
32
|
+
) internal view {
|
|
33
|
+
require(!nullifierHashes[nullifierHash], "SemaphoreCore: you cannot use the same nullifier twice");
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
uint256 signalHash = _hashSignal(signal);
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
verifier.verifyProof(
|
|
38
|
+
[proof[0], proof[1]],
|
|
39
|
+
[[proof[2], proof[3]], [proof[4], proof[5]]],
|
|
40
|
+
[proof[6], proof[7]],
|
|
41
|
+
[root, nullifierHash, signalHash, externalNullifier]
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
/// @dev Stores the nullifier hash to prevent double-signaling.
|
|
46
|
+
/// Attention! Remember to call it when you verify a proof if you
|
|
47
|
+
/// need to prevent double-signaling.
|
|
48
|
+
/// @param nullifierHash: Semaphore nullifier hash.
|
|
49
|
+
function _saveNullifierHash(uint256 nullifierHash) internal {
|
|
50
|
+
nullifierHashes[nullifierHash] = true;
|
|
51
|
+
}
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
53
|
+
/// @dev Creates a keccak256 hash of the signal.
|
|
54
|
+
/// @param signal: Semaphore signal.
|
|
55
|
+
/// @return Hash of the signal.
|
|
56
|
+
function _hashSignal(bytes32 signal) private pure returns (uint256) {
|
|
57
|
+
return uint256(keccak256(abi.encodePacked(signal))) >> 8;
|
|
58
|
+
}
|
|
59
59
|
}
|
package/base/SemaphoreGroups.sol
CHANGED
|
@@ -10,74 +10,74 @@ import "@openzeppelin/contracts/utils/Context.sol";
|
|
|
10
10
|
/// @dev The following code allows you to create groups, add and remove members.
|
|
11
11
|
/// You can use getters to obtain informations about groups (root, depth, number of leaves).
|
|
12
12
|
abstract contract SemaphoreGroups is Context, ISemaphoreGroups {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
13
|
+
using IncrementalBinaryTree for IncrementalTreeData;
|
|
14
|
+
|
|
15
|
+
/// @dev Gets a group id and returns the group/tree data.
|
|
16
|
+
mapping(uint256 => IncrementalTreeData) internal groups;
|
|
17
|
+
|
|
18
|
+
/// @dev Creates a new group by initializing the associated tree.
|
|
19
|
+
/// @param groupId: Id of the group.
|
|
20
|
+
/// @param depth: Depth of the tree.
|
|
21
|
+
/// @param zeroValue: Zero value of the tree.
|
|
22
|
+
function _createGroup(
|
|
23
|
+
uint256 groupId,
|
|
24
|
+
uint8 depth,
|
|
25
|
+
uint256 zeroValue
|
|
26
|
+
) internal virtual {
|
|
27
|
+
require(groupId < SNARK_SCALAR_FIELD, "SemaphoreGroups: group id must be < SNARK_SCALAR_FIELD");
|
|
28
|
+
require(getDepth(groupId) == 0, "SemaphoreGroups: group already exists");
|
|
29
|
+
|
|
30
|
+
groups[groupId].init(depth, zeroValue);
|
|
31
|
+
|
|
32
|
+
emit GroupCreated(groupId, depth, zeroValue);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// @dev Adds an identity commitment to an existing group.
|
|
36
|
+
/// @param groupId: Id of the group.
|
|
37
|
+
/// @param identityCommitment: New identity commitment.
|
|
38
|
+
function _addMember(uint256 groupId, uint256 identityCommitment) internal virtual {
|
|
39
|
+
require(getDepth(groupId) != 0, "SemaphoreGroups: group does not exist");
|
|
40
|
+
|
|
41
|
+
groups[groupId].insert(identityCommitment);
|
|
42
|
+
|
|
43
|
+
uint256 root = getRoot(groupId);
|
|
44
|
+
|
|
45
|
+
emit MemberAdded(groupId, identityCommitment, root);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/// @dev Removes an identity commitment from an existing group. A proof of membership is
|
|
49
|
+
/// needed to check if the node to be deleted is part of the tree.
|
|
50
|
+
/// @param groupId: Id of the group.
|
|
51
|
+
/// @param identityCommitment: Existing identity commitment to be deleted.
|
|
52
|
+
/// @param proofSiblings: Array of the sibling nodes of the proof of membership.
|
|
53
|
+
/// @param proofPathIndices: Path of the proof of membership.
|
|
54
|
+
function _removeMember(
|
|
55
|
+
uint256 groupId,
|
|
56
|
+
uint256 identityCommitment,
|
|
57
|
+
uint256[] calldata proofSiblings,
|
|
58
|
+
uint8[] calldata proofPathIndices
|
|
59
|
+
) internal virtual {
|
|
60
|
+
require(getDepth(groupId) != 0, "SemaphoreGroups: group does not exist");
|
|
61
|
+
|
|
62
|
+
groups[groupId].remove(identityCommitment, proofSiblings, proofPathIndices);
|
|
63
|
+
|
|
64
|
+
uint256 root = getRoot(groupId);
|
|
65
|
+
|
|
66
|
+
emit MemberRemoved(groupId, identityCommitment, root);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// @dev See {ISemaphoreGroups-getRoot}.
|
|
70
|
+
function getRoot(uint256 groupId) public view virtual override returns (uint256) {
|
|
71
|
+
return groups[groupId].root;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/// @dev See {ISemaphoreGroups-getDepth}.
|
|
75
|
+
function getDepth(uint256 groupId) public view virtual override returns (uint8) {
|
|
76
|
+
return groups[groupId].depth;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/// @dev See {ISemaphoreGroups-getNumberOfLeaves}.
|
|
80
|
+
function getNumberOfLeaves(uint256 groupId) public view virtual override returns (uint256) {
|
|
81
|
+
return groups[groupId].numberOfLeaves;
|
|
82
|
+
}
|
|
83
83
|
}
|
|
@@ -8,100 +8,100 @@ 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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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]);
|
|
31
|
+
}
|
|
31
32
|
}
|
|
32
|
-
}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
+
}
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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");
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
_createGroup(pollId, depth, 0);
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
Poll memory poll;
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
poll.coordinator = coordinator;
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
polls[pollId] = poll;
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
emit PollCreated(pollId, coordinator);
|
|
58
|
+
}
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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");
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
_addMember(pollId, identityCommitment);
|
|
65
|
+
}
|
|
66
66
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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");
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
polls[pollId].state = PollState.Ongoing;
|
|
72
72
|
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
emit PollStarted(pollId, _msgSender(), encryptionKey);
|
|
74
|
+
}
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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];
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
require(poll.state == PollState.Ongoing, "SemaphoreVoting: vote can only be cast in an ongoing poll");
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
87
|
+
uint8 depth = getDepth(pollId);
|
|
88
|
+
uint256 root = getRoot(pollId);
|
|
89
|
+
IVerifier verifier = verifiers[depth];
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
_verifyProof(vote, root, nullifierHash, pollId, proof, verifier);
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
// Prevent double-voting (nullifierHash = hash(pollId + identityNullifier)).
|
|
94
|
+
_saveNullifierHash(nullifierHash);
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
emit VoteAdded(pollId, vote);
|
|
97
|
+
}
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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");
|
|
102
102
|
|
|
103
|
-
|
|
103
|
+
polls[pollId].state = PollState.Ended;
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
emit PollEnded(pollId, _msgSender(), decryptionKey);
|
|
106
|
+
}
|
|
107
107
|
}
|