@crisp-e3/contracts 0.5.9 → 0.5.11
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/contracts/CRISPProgram.sol +38 -13
- package/contracts/CRISPVerifier.sol +2164 -2142
- package/contracts/Mocks/MockEnclave.sol +11 -10
- package/package.json +4 -4
|
@@ -16,6 +16,14 @@ import { HonkVerifier } from "./CRISPVerifier.sol";
|
|
|
16
16
|
contract CRISPProgram is IE3Program, Ownable {
|
|
17
17
|
using InternalLazyIMT for LazyIMTData;
|
|
18
18
|
|
|
19
|
+
/// @notice Enum to represent credit modes
|
|
20
|
+
enum CreditMode {
|
|
21
|
+
/// @notice Everyone has constant credits
|
|
22
|
+
CONSTANT,
|
|
23
|
+
/// @notice Credits are custom (can be based on token balance, etc)
|
|
24
|
+
CUSTOM
|
|
25
|
+
}
|
|
26
|
+
|
|
19
27
|
/// @notice Struct to store all data related to a voting round
|
|
20
28
|
struct RoundData {
|
|
21
29
|
uint256 merkleRoot;
|
|
@@ -23,6 +31,7 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
23
31
|
mapping(address slot => uint40 index) voteSlots;
|
|
24
32
|
LazyIMTData votes;
|
|
25
33
|
uint256 numOptions;
|
|
34
|
+
CreditMode creditMode;
|
|
26
35
|
}
|
|
27
36
|
|
|
28
37
|
// Constants
|
|
@@ -40,13 +49,11 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
40
49
|
HonkVerifier private immutable honkVerifier;
|
|
41
50
|
|
|
42
51
|
// Mappings
|
|
43
|
-
mapping(address => bool) public authorizedContracts;
|
|
44
52
|
mapping(uint256 e3Id => RoundData) e3Data;
|
|
45
53
|
|
|
46
54
|
// Errors
|
|
47
55
|
error CallerNotAuthorized();
|
|
48
56
|
error E3AlreadyInitialized();
|
|
49
|
-
error E3DoesNotExist();
|
|
50
57
|
error EnclaveAddressZero();
|
|
51
58
|
error Risc0VerifierAddressZero();
|
|
52
59
|
error InvalidHonkVerifier();
|
|
@@ -58,6 +65,9 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
58
65
|
error SlotIsEmpty();
|
|
59
66
|
error MerkleRootNotSet();
|
|
60
67
|
error InvalidNumOptions();
|
|
68
|
+
error InputDeadlinePassed(uint256 e3Id, uint256 deadline);
|
|
69
|
+
error KeyNotPublished(uint256 e3Id);
|
|
70
|
+
error E3NotAcceptingInputs(uint256 e3Id);
|
|
61
71
|
|
|
62
72
|
// Events
|
|
63
73
|
event InputPublished(uint256 indexed e3Id, bytes encryptedVote, uint256 index);
|
|
@@ -75,7 +85,6 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
75
85
|
enclave = _enclave;
|
|
76
86
|
risc0Verifier = _risc0Verifier;
|
|
77
87
|
honkVerifier = _honkVerifier;
|
|
78
|
-
authorizedContracts[address(_enclave)] = true;
|
|
79
88
|
imageId = _imageId;
|
|
80
89
|
}
|
|
81
90
|
|
|
@@ -117,14 +126,17 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
117
126
|
bytes calldata,
|
|
118
127
|
bytes calldata customParams
|
|
119
128
|
) external returns (bytes32) {
|
|
120
|
-
if (
|
|
129
|
+
if (msg.sender != address(enclave) && msg.sender != owner()) revert CallerNotAuthorized();
|
|
121
130
|
if (e3Data[e3Id].paramsHash != bytes32(0)) revert E3AlreadyInitialized();
|
|
122
131
|
|
|
123
132
|
// decode custom params to get the number of options
|
|
124
|
-
(, , uint256 numOptions) = abi.decode(customParams, (address, uint256, uint256));
|
|
133
|
+
(, , uint256 numOptions, CreditMode creditMode, ) = abi.decode(customParams, (address, uint256, uint256, CreditMode, uint256));
|
|
125
134
|
if (numOptions < 2) revert InvalidNumOptions();
|
|
126
135
|
|
|
136
|
+
// we need to know the number of options for decoding the tally
|
|
127
137
|
e3Data[e3Id].numOptions = numOptions;
|
|
138
|
+
// we want to save the credit mode so it can be verified on chain by everyone
|
|
139
|
+
e3Data[e3Id].creditMode = creditMode;
|
|
128
140
|
|
|
129
141
|
e3Data[e3Id].paramsHash = keccak256(e3ProgramParams);
|
|
130
142
|
|
|
@@ -135,9 +147,24 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
135
147
|
}
|
|
136
148
|
|
|
137
149
|
/// @inheritdoc IE3Program
|
|
138
|
-
function
|
|
139
|
-
|
|
140
|
-
|
|
150
|
+
function publishInput(uint256 e3Id, bytes memory data) external {
|
|
151
|
+
E3 memory e3 = enclave.getE3(e3Id);
|
|
152
|
+
|
|
153
|
+
// check that we are in the correct stage
|
|
154
|
+
IEnclave.E3Stage stage = enclave.getE3Stage(e3Id);
|
|
155
|
+
if (stage != IEnclave.E3Stage.KeyPublished) {
|
|
156
|
+
revert KeyNotPublished(e3Id);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// check that we are not past the input deadline
|
|
160
|
+
if (block.timestamp > e3.inputWindow[1]) {
|
|
161
|
+
revert InputDeadlinePassed(e3Id, e3.inputWindow[1]);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// check that we are within the input window
|
|
165
|
+
if (block.timestamp < e3.inputWindow[0]) {
|
|
166
|
+
revert E3NotAcceptingInputs(e3Id);
|
|
167
|
+
}
|
|
141
168
|
|
|
142
169
|
// We need to ensure that the CRISP admin set the merkle root of the census.
|
|
143
170
|
if (e3Data[e3Id].merkleRoot == 0) revert MerkleRootNotSet();
|
|
@@ -151,9 +178,6 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
151
178
|
|
|
152
179
|
(uint40 voteIndex, bytes32 previousEncryptedVoteCommitment) = _processVote(e3Id, slotAddress, encryptedVoteCommitment);
|
|
153
180
|
|
|
154
|
-
// Fetch E3 to get committee public key
|
|
155
|
-
E3 memory e3 = enclave.getE3(e3Id);
|
|
156
|
-
|
|
157
181
|
// Set the public inputs for the proof. Order must match Noir circuit.
|
|
158
182
|
bytes32[] memory noirPublicInputs = new bytes32[](7);
|
|
159
183
|
noirPublicInputs[0] = previousEncryptedVoteCommitment;
|
|
@@ -232,12 +256,13 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
232
256
|
|
|
233
257
|
/// @inheritdoc IE3Program
|
|
234
258
|
function verify(uint256 e3Id, bytes32 ciphertextOutputHash, bytes memory proof) external view override returns (bool) {
|
|
235
|
-
|
|
259
|
+
bytes32 paramsHash = getParamsHash(e3Id);
|
|
260
|
+
|
|
236
261
|
bytes32 inputRoot = bytes32(e3Data[e3Id].votes._root(TREE_DEPTH));
|
|
237
262
|
bytes memory journal = new bytes(396); // (32 + 1) * 4 * 3
|
|
238
263
|
|
|
239
264
|
_encodeLengthPrefixAndHash(journal, 0, ciphertextOutputHash);
|
|
240
|
-
_encodeLengthPrefixAndHash(journal, 132,
|
|
265
|
+
_encodeLengthPrefixAndHash(journal, 132, paramsHash);
|
|
241
266
|
_encodeLengthPrefixAndHash(journal, 264, inputRoot);
|
|
242
267
|
|
|
243
268
|
risc0Verifier.verify(proof, imageId, sha256(journal));
|