@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.
- package/README.md +61 -0
- package/Semaphore.sol +145 -85
- package/base/SemaphoreConstants.sol +1 -1
- package/base/SemaphoreCore.sol +44 -42
- package/base/SemaphoreGroups.sol +106 -72
- package/extensions/SemaphoreVoting.sol +84 -75
- package/extensions/SemaphoreWhistleblowing.sol +76 -75
- package/interfaces/ISemaphore.sol +102 -59
- package/interfaces/ISemaphoreCore.sol +6 -4
- package/interfaces/ISemaphoreGroups.sol +49 -33
- package/interfaces/ISemaphoreNullifiers.sol +7 -7
- package/interfaces/ISemaphoreVoting.sol +70 -60
- package/interfaces/ISemaphoreWhistleblowing.sol +57 -49
- package/interfaces/IVerifier.sol +7 -7
- 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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
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
|
-
|
|
49
|
+
_createGroup(pollId, merkleTreeDepth, 0);
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
Poll memory poll;
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
poll.coordinator = coordinator;
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
polls[pollId] = poll;
|
|
56
|
+
|
|
57
|
+
emit PollCreated(pollId, coordinator);
|
|
58
|
+
}
|
|
56
59
|
|
|
57
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
require(polls[pollId].state == PollState.Created, "SemaphoreVoting: voters can only be added before voting");
|
|
66
|
+
_addMember(pollId, identityCommitment);
|
|
67
|
+
}
|
|
63
68
|
|
|
64
|
-
|
|
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
|
-
|
|
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
|
-
|
|
77
|
+
emit PollStarted(pollId, _msgSender(), encryptionKey);
|
|
78
|
+
}
|
|
72
79
|
|
|
73
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
93
|
+
uint256 merkleTreeDepth = getMerkleTreeDepth(pollId);
|
|
94
|
+
uint256 merkleTreeRoot = getMerkleTreeRoot(pollId);
|
|
86
95
|
|
|
87
|
-
|
|
88
|
-
uint256 root = getRoot(pollId);
|
|
89
|
-
IVerifier verifier = verifiers[depth];
|
|
96
|
+
IVerifier verifier = verifiers[merkleTreeDepth];
|
|
90
97
|
|
|
91
|
-
|
|
98
|
+
_verifyProof(vote, merkleTreeRoot, nullifierHash, pollId, proof, verifier);
|
|
92
99
|
|
|
93
|
-
|
|
94
|
-
|
|
100
|
+
// Prevent double-voting (nullifierHash = hash(pollId + identityNullifier)).
|
|
101
|
+
_saveNullifierHash(nullifierHash);
|
|
95
102
|
|
|
96
|
-
|
|
97
|
-
|
|
103
|
+
emit VoteAdded(pollId, vote);
|
|
104
|
+
}
|
|
98
105
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
-
|
|
112
|
+
polls[pollId].state = PollState.Ended;
|
|
104
113
|
|
|
105
|
-
|
|
106
|
-
|
|
114
|
+
emit PollEnded(pollId, _msgSender(), decryptionKey);
|
|
115
|
+
}
|
|
107
116
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
//SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
error Semaphore__CallerIsNotTheGroupAdmin();
|
|
8
|
+
error Semaphore__MerkleTreeDepthIsNotSupported();
|
|
9
|
+
error Semaphore__MerkleTreeRootIsExpired();
|
|
10
|
+
error Semaphore__MerkleTreeRootIsNotPartOfTheGroup();
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
}
|