@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.
- package/LICENSE +1 -1
- package/README.md +4 -4
- package/Semaphore.sol +75 -89
- package/base/SemaphoreGroups.sol +94 -82
- package/base/SemaphoreVerifier.sol +358 -104
- package/interfaces/ISemaphore.sol +65 -74
- package/interfaces/ISemaphoreGroups.sol +35 -6
- package/interfaces/ISemaphoreVerifier.sol +7 -31
- package/package.json +2 -3
- package/base/Pairing.sol +0 -151
- package/extensions/SemaphoreVoting.sol +0 -96
- package/extensions/SemaphoreWhistleblowing.sol +0 -77
- package/interfaces/ISemaphoreVoting.sol +0 -78
- package/interfaces/ISemaphoreWhistleblowing.sol +0 -53
|
@@ -1,28 +1,22 @@
|
|
|
1
1
|
//SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity 0.8.
|
|
2
|
+
pragma solidity 0.8.23;
|
|
3
3
|
|
|
4
4
|
/// @title Semaphore contract interface.
|
|
5
5
|
interface ISemaphore {
|
|
6
|
-
error
|
|
6
|
+
error Semaphore__GroupHasNoMembers();
|
|
7
7
|
error Semaphore__MerkleTreeDepthIsNotSupported();
|
|
8
8
|
error Semaphore__MerkleTreeRootIsExpired();
|
|
9
9
|
error Semaphore__MerkleTreeRootIsNotPartOfTheGroup();
|
|
10
|
-
error
|
|
10
|
+
error Semaphore__YouAreUsingTheSameNullifierTwice();
|
|
11
|
+
error Semaphore__InvalidProof();
|
|
11
12
|
|
|
12
|
-
/// It defines all the group parameters
|
|
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)
|
|
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
|
|
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
|
|
40
|
-
/// @param
|
|
41
|
-
/// @param
|
|
42
|
-
|
|
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
|
|
46
|
-
uint256
|
|
47
|
-
uint256
|
|
42
|
+
uint256 nullifier,
|
|
43
|
+
uint256 message,
|
|
44
|
+
uint256 indexed scope,
|
|
45
|
+
uint256[8] proof
|
|
48
46
|
);
|
|
49
47
|
|
|
50
|
-
/// @dev
|
|
51
|
-
|
|
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
|
|
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
|
|
78
|
-
function createGroup(uint256 groupId,
|
|
54
|
+
/// @param merkleTreeDuration: Merkle tree duration.
|
|
55
|
+
function createGroup(uint256 groupId, address admin, uint256 merkleTreeDuration) external;
|
|
79
56
|
|
|
80
|
-
/// @dev
|
|
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
|
|
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
|
|
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
|
|
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
|
|
74
|
+
uint256 oldIdentityCommitment,
|
|
110
75
|
uint256 newIdentityCommitment,
|
|
111
|
-
uint256[] calldata
|
|
112
|
-
uint8[] calldata proofPathIndices
|
|
76
|
+
uint256[] calldata merkleProofSiblings
|
|
113
77
|
) external;
|
|
114
78
|
|
|
115
|
-
/// @dev
|
|
116
|
-
|
|
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
|
|
119
|
-
/// @param
|
|
120
|
-
/// @param
|
|
121
|
-
|
|
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
|
|
124
|
-
uint256
|
|
125
|
-
|
|
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.
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
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:
|
|
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
|
|
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.
|
|
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
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
+
"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
|
-
"@
|
|
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
|
-
}
|