@semaphore-protocol/contracts 4.0.0-beta.2 → 4.0.0-beta.4
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 +23 -20
- package/base/Constants.sol +8 -0
- package/base/SemaphoreGroups.sol +16 -16
- package/base/SemaphoreVerifier.sol +4 -2
- package/interfaces/ISemaphore.sol +6 -3
- package/interfaces/ISemaphoreGroups.sol +0 -1
- package/package.json +2 -2
package/Semaphore.sol
CHANGED
|
@@ -4,6 +4,7 @@ pragma solidity 0.8.23;
|
|
|
4
4
|
import {ISemaphore} from "./interfaces/ISemaphore.sol";
|
|
5
5
|
import {ISemaphoreVerifier} from "./interfaces/ISemaphoreVerifier.sol";
|
|
6
6
|
import {SemaphoreGroups} from "./base/SemaphoreGroups.sol";
|
|
7
|
+
import {MIN_DEPTH, MAX_DEPTH} from "./base/Constants.sol";
|
|
7
8
|
|
|
8
9
|
/// @title Semaphore
|
|
9
10
|
/// @dev This contract uses the Semaphore base contracts to provide a complete service
|
|
@@ -17,6 +18,9 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
|
|
|
17
18
|
/// @dev Gets a group id and returns the group parameters.
|
|
18
19
|
mapping(uint256 => Group) public groups;
|
|
19
20
|
|
|
21
|
+
/// @dev Counter to assign an incremental id to the groups.
|
|
22
|
+
uint256 public groupCounter;
|
|
23
|
+
|
|
20
24
|
/// @dev Initializes the Semaphore verifier used to verify the user's ZK proofs.
|
|
21
25
|
/// @param _verifier: Semaphore verifier addresse.
|
|
22
26
|
constructor(ISemaphoreVerifier _verifier) {
|
|
@@ -24,14 +28,24 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
|
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
/// @dev See {SemaphoreGroups-_createGroup}.
|
|
27
|
-
function createGroup(
|
|
31
|
+
function createGroup() external override returns (uint256 groupId) {
|
|
32
|
+
groupId = groupCounter++;
|
|
33
|
+
_createGroup(groupId, msg.sender);
|
|
34
|
+
|
|
35
|
+
groups[groupId].merkleTreeDuration = 1 hours;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/// @dev See {SemaphoreGroups-_createGroup}.
|
|
39
|
+
function createGroup(address admin) external override returns (uint256 groupId) {
|
|
40
|
+
groupId = groupCounter++;
|
|
28
41
|
_createGroup(groupId, admin);
|
|
29
42
|
|
|
30
43
|
groups[groupId].merkleTreeDuration = 1 hours;
|
|
31
44
|
}
|
|
32
45
|
|
|
33
46
|
/// @dev See {ISemaphore-createGroup}.
|
|
34
|
-
function createGroup(
|
|
47
|
+
function createGroup(address admin, uint256 merkleTreeDuration) external override returns (uint256 groupId) {
|
|
48
|
+
groupId = groupCounter++;
|
|
35
49
|
_createGroup(groupId, admin);
|
|
36
50
|
|
|
37
51
|
groups[groupId].merkleTreeDuration = merkleTreeDuration;
|
|
@@ -46,7 +60,7 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
|
|
|
46
60
|
function updateGroupMerkleTreeDuration(
|
|
47
61
|
uint256 groupId,
|
|
48
62
|
uint256 newMerkleTreeDuration
|
|
49
|
-
) external override
|
|
63
|
+
) external override onlyGroupAdmin(groupId) {
|
|
50
64
|
uint256 oldMerkleTreeDuration = groups[groupId].merkleTreeDuration;
|
|
51
65
|
|
|
52
66
|
groups[groupId].merkleTreeDuration = newMerkleTreeDuration;
|
|
@@ -56,18 +70,14 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
|
|
|
56
70
|
|
|
57
71
|
/// @dev See {SemaphoreGroups-_addMember}.
|
|
58
72
|
function addMember(uint256 groupId, uint256 identityCommitment) external override {
|
|
59
|
-
_addMember(groupId, identityCommitment);
|
|
60
|
-
|
|
61
|
-
uint256 merkleTreeRoot = getMerkleTreeRoot(groupId);
|
|
73
|
+
uint256 merkleTreeRoot = _addMember(groupId, identityCommitment);
|
|
62
74
|
|
|
63
75
|
groups[groupId].merkleRootCreationDates[merkleTreeRoot] = block.timestamp;
|
|
64
76
|
}
|
|
65
77
|
|
|
66
78
|
/// @dev See {SemaphoreGroups-_addMembers}.
|
|
67
79
|
function addMembers(uint256 groupId, uint256[] calldata identityCommitments) external override {
|
|
68
|
-
_addMembers(groupId, identityCommitments);
|
|
69
|
-
|
|
70
|
-
uint256 merkleTreeRoot = getMerkleTreeRoot(groupId);
|
|
80
|
+
uint256 merkleTreeRoot = _addMembers(groupId, identityCommitments);
|
|
71
81
|
|
|
72
82
|
groups[groupId].merkleRootCreationDates[merkleTreeRoot] = block.timestamp;
|
|
73
83
|
}
|
|
@@ -79,9 +89,7 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
|
|
|
79
89
|
uint256 newIdentityCommitment,
|
|
80
90
|
uint256[] calldata merkleProofSiblings
|
|
81
91
|
) external override {
|
|
82
|
-
_updateMember(groupId, identityCommitment, newIdentityCommitment, merkleProofSiblings);
|
|
83
|
-
|
|
84
|
-
uint256 merkleTreeRoot = getMerkleTreeRoot(groupId);
|
|
92
|
+
uint256 merkleTreeRoot = _updateMember(groupId, identityCommitment, newIdentityCommitment, merkleProofSiblings);
|
|
85
93
|
|
|
86
94
|
groups[groupId].merkleRootCreationDates[merkleTreeRoot] = block.timestamp;
|
|
87
95
|
}
|
|
@@ -92,18 +100,13 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
|
|
|
92
100
|
uint256 identityCommitment,
|
|
93
101
|
uint256[] calldata merkleProofSiblings
|
|
94
102
|
) external override {
|
|
95
|
-
_removeMember(groupId, identityCommitment, merkleProofSiblings);
|
|
96
|
-
|
|
97
|
-
uint256 merkleTreeRoot = getMerkleTreeRoot(groupId);
|
|
103
|
+
uint256 merkleTreeRoot = _removeMember(groupId, identityCommitment, merkleProofSiblings);
|
|
98
104
|
|
|
99
105
|
groups[groupId].merkleRootCreationDates[merkleTreeRoot] = block.timestamp;
|
|
100
106
|
}
|
|
101
107
|
|
|
102
108
|
/// @dev See {ISemaphore-validateProof}.
|
|
103
|
-
function validateProof(
|
|
104
|
-
uint256 groupId,
|
|
105
|
-
SemaphoreProof calldata proof
|
|
106
|
-
) external override onlyExistingGroup(groupId) {
|
|
109
|
+
function validateProof(uint256 groupId, SemaphoreProof calldata proof) external override {
|
|
107
110
|
// The function will revert if the nullifier that is part of the proof,
|
|
108
111
|
// was already used inside the group with id groupId.
|
|
109
112
|
if (groups[groupId].nullifiers[proof.nullifier]) {
|
|
@@ -136,7 +139,7 @@ contract Semaphore is ISemaphore, SemaphoreGroups {
|
|
|
136
139
|
SemaphoreProof calldata proof
|
|
137
140
|
) public view override onlyExistingGroup(groupId) returns (bool) {
|
|
138
141
|
// The function will revert if the Merkle tree depth is not supported.
|
|
139
|
-
if (proof.merkleTreeDepth <
|
|
142
|
+
if (proof.merkleTreeDepth < MIN_DEPTH || proof.merkleTreeDepth > MAX_DEPTH) {
|
|
140
143
|
revert Semaphore__MerkleTreeDepthIsNotSupported();
|
|
141
144
|
}
|
|
142
145
|
|
package/base/SemaphoreGroups.sol
CHANGED
|
@@ -42,10 +42,6 @@ abstract contract SemaphoreGroups is ISemaphoreGroups {
|
|
|
42
42
|
/// @param groupId: Id of the group.
|
|
43
43
|
/// @param admin: Admin of the group.
|
|
44
44
|
function _createGroup(uint256 groupId, address admin) internal virtual {
|
|
45
|
-
if (admins[groupId] != address(0)) {
|
|
46
|
-
revert Semaphore__GroupAlreadyExists();
|
|
47
|
-
}
|
|
48
|
-
|
|
49
45
|
admins[groupId] = admin;
|
|
50
46
|
|
|
51
47
|
emit GroupCreated(groupId);
|
|
@@ -55,10 +51,7 @@ abstract contract SemaphoreGroups is ISemaphoreGroups {
|
|
|
55
51
|
/// @dev Updates the group admin.
|
|
56
52
|
/// @param groupId: Id of the group.
|
|
57
53
|
/// @param newAdmin: New admin of the group.
|
|
58
|
-
function _updateGroupAdmin(
|
|
59
|
-
uint256 groupId,
|
|
60
|
-
address newAdmin
|
|
61
|
-
) internal virtual onlyExistingGroup(groupId) onlyGroupAdmin(groupId) {
|
|
54
|
+
function _updateGroupAdmin(uint256 groupId, address newAdmin) internal virtual onlyGroupAdmin(groupId) {
|
|
62
55
|
admins[groupId] = newAdmin;
|
|
63
56
|
|
|
64
57
|
emit GroupAdminUpdated(groupId, msg.sender, newAdmin);
|
|
@@ -67,12 +60,13 @@ abstract contract SemaphoreGroups is ISemaphoreGroups {
|
|
|
67
60
|
/// @dev Adds an identity commitment to an existing group.
|
|
68
61
|
/// @param groupId: Id of the group.
|
|
69
62
|
/// @param identityCommitment: New identity commitment.
|
|
63
|
+
/// @return merkleTreeRoot New root hash of the tree.
|
|
70
64
|
function _addMember(
|
|
71
65
|
uint256 groupId,
|
|
72
66
|
uint256 identityCommitment
|
|
73
|
-
) internal virtual
|
|
67
|
+
) internal virtual onlyGroupAdmin(groupId) returns (uint256 merkleTreeRoot) {
|
|
74
68
|
uint256 index = getMerkleTreeSize(groupId);
|
|
75
|
-
|
|
69
|
+
merkleTreeRoot = merkleTrees[groupId]._insert(identityCommitment);
|
|
76
70
|
|
|
77
71
|
emit MemberAdded(groupId, index, identityCommitment, merkleTreeRoot);
|
|
78
72
|
}
|
|
@@ -80,9 +74,13 @@ abstract contract SemaphoreGroups is ISemaphoreGroups {
|
|
|
80
74
|
/// @dev Adds new members to an existing group.
|
|
81
75
|
/// @param groupId: Id of the group.
|
|
82
76
|
/// @param identityCommitments: New identity commitments.
|
|
83
|
-
|
|
77
|
+
/// @return merkleTreeRoot New root hash of the tree.
|
|
78
|
+
function _addMembers(
|
|
79
|
+
uint256 groupId,
|
|
80
|
+
uint256[] calldata identityCommitments
|
|
81
|
+
) internal virtual onlyGroupAdmin(groupId) returns (uint256 merkleTreeRoot) {
|
|
84
82
|
uint256 startIndex = getMerkleTreeSize(groupId);
|
|
85
|
-
|
|
83
|
+
merkleTreeRoot = merkleTrees[groupId]._insertMany(identityCommitments);
|
|
86
84
|
|
|
87
85
|
emit MembersAdded(groupId, startIndex, identityCommitments, merkleTreeRoot);
|
|
88
86
|
}
|
|
@@ -93,14 +91,15 @@ abstract contract SemaphoreGroups is ISemaphoreGroups {
|
|
|
93
91
|
/// @param oldIdentityCommitment: Existing identity commitment to be updated.
|
|
94
92
|
/// @param newIdentityCommitment: New identity commitment.
|
|
95
93
|
/// @param merkleProofSiblings: Array of the sibling nodes of the proof of membership.
|
|
94
|
+
/// @return merkleTreeRoot New root hash of the tree.
|
|
96
95
|
function _updateMember(
|
|
97
96
|
uint256 groupId,
|
|
98
97
|
uint256 oldIdentityCommitment,
|
|
99
98
|
uint256 newIdentityCommitment,
|
|
100
99
|
uint256[] calldata merkleProofSiblings
|
|
101
|
-
) internal virtual
|
|
100
|
+
) internal virtual onlyGroupAdmin(groupId) returns (uint256 merkleTreeRoot) {
|
|
102
101
|
uint256 index = merkleTrees[groupId]._indexOf(oldIdentityCommitment);
|
|
103
|
-
|
|
102
|
+
merkleTreeRoot = merkleTrees[groupId]._update(
|
|
104
103
|
oldIdentityCommitment,
|
|
105
104
|
newIdentityCommitment,
|
|
106
105
|
merkleProofSiblings
|
|
@@ -114,14 +113,15 @@ abstract contract SemaphoreGroups is ISemaphoreGroups {
|
|
|
114
113
|
/// @param groupId: Id of the group.
|
|
115
114
|
/// @param identityCommitment: Existing identity commitment to be removed.
|
|
116
115
|
/// @param merkleProofSiblings: Array of the sibling nodes of the proof of membership.
|
|
116
|
+
/// @return merkleTreeRoot New root hash of the tree.
|
|
117
117
|
function _removeMember(
|
|
118
118
|
uint256 groupId,
|
|
119
119
|
uint256 identityCommitment,
|
|
120
120
|
uint256[] calldata merkleProofSiblings
|
|
121
|
-
) internal virtual
|
|
121
|
+
) internal virtual onlyGroupAdmin(groupId) returns (uint256 merkleTreeRoot) {
|
|
122
122
|
uint256 index = merkleTrees[groupId]._indexOf(identityCommitment);
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
merkleTreeRoot = merkleTrees[groupId]._remove(identityCommitment, merkleProofSiblings);
|
|
125
125
|
|
|
126
126
|
emit MemberRemoved(groupId, index, identityCommitment, merkleTreeRoot);
|
|
127
127
|
}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
pragma solidity 0.8.23;
|
|
5
5
|
|
|
6
|
+
import {MAX_DEPTH} from "./Constants.sol";
|
|
7
|
+
|
|
6
8
|
contract SemaphoreVerifier {
|
|
7
9
|
// Scalar field size
|
|
8
10
|
uint256 constant r = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
|
|
@@ -22,12 +24,12 @@ contract SemaphoreVerifier {
|
|
|
22
24
|
uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
|
|
23
25
|
|
|
24
26
|
// TODO: Add more variables when Semaphore supports tree depth > 12.
|
|
25
|
-
// Right now Semaphore supports tree depth 1-12.
|
|
27
|
+
// Right now Semaphore supports tree depth 1-12. It will support up to 32.
|
|
26
28
|
|
|
27
29
|
// Verification Key points.
|
|
28
30
|
// These values are taken from the verification key json file generated with snarkjs.
|
|
29
31
|
// It allows to use the same verifier to verify proofs for all the tree depths supported by Semaphore.
|
|
30
|
-
uint256[14][
|
|
32
|
+
uint256[14][MAX_DEPTH] VK_POINTS = [
|
|
31
33
|
[
|
|
32
34
|
563562783592406106461234396505774794044312891062077216951605541624542949349,
|
|
33
35
|
16293410697967515504861065986355060225819302510590370360517024529684437085892,
|
|
@@ -56,13 +56,16 @@ interface ISemaphore {
|
|
|
56
56
|
);
|
|
57
57
|
|
|
58
58
|
/// @dev See {SemaphoreGroups-_createGroup}.
|
|
59
|
-
function createGroup(
|
|
59
|
+
function createGroup() external returns (uint256);
|
|
60
|
+
|
|
61
|
+
/// @dev See {SemaphoreGroups-_createGroup}.
|
|
62
|
+
function createGroup(address admin) external returns (uint256);
|
|
60
63
|
|
|
61
64
|
/// @dev It creates a group with a custom Merkle tree duration.
|
|
62
|
-
/// @param groupId: Id of the group.
|
|
63
65
|
/// @param admin: Admin of the group. It can be an Ethereum account or a smart contract.
|
|
64
66
|
/// @param merkleTreeDuration: Merkle tree duration.
|
|
65
|
-
|
|
67
|
+
/// @return Id of the group.
|
|
68
|
+
function createGroup(address admin, uint256 merkleTreeDuration) external returns (uint256);
|
|
66
69
|
|
|
67
70
|
/// @dev See {SemaphoreGroups-_updateGroupAdmin}.
|
|
68
71
|
function updateGroupAdmin(uint256 groupId, address newAdmin) external;
|
|
@@ -4,7 +4,6 @@ pragma solidity 0.8.23;
|
|
|
4
4
|
/// @title SemaphoreGroups contract interface.
|
|
5
5
|
interface ISemaphoreGroups {
|
|
6
6
|
error Semaphore__GroupDoesNotExist();
|
|
7
|
-
error Semaphore__GroupAlreadyExists();
|
|
8
7
|
error Semaphore__CallerIsNotTheGroupAdmin();
|
|
9
8
|
|
|
10
9
|
/// @dev Event emitted when a new group is created.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@semaphore-protocol/contracts",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.4",
|
|
4
4
|
"description": "Semaphore contracts to manage groups and broadcast anonymous signals.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
@@ -30,6 +30,6 @@
|
|
|
30
30
|
"access": "public"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@zk-kit/imt.sol": "2.0.0-beta.
|
|
33
|
+
"@zk-kit/imt.sol": "2.0.0-beta.8"
|
|
34
34
|
}
|
|
35
35
|
}
|