@crisp-e3/contracts 0.5.7 → 0.5.9
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.
|
@@ -10,7 +10,7 @@ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
|
|
|
10
10
|
import { IE3Program } from "@enclave-e3/contracts/contracts/interfaces/IE3Program.sol";
|
|
11
11
|
import { IEnclave } from "@enclave-e3/contracts/contracts/interfaces/IEnclave.sol";
|
|
12
12
|
import { E3 } from "@enclave-e3/contracts/contracts/interfaces/IE3.sol";
|
|
13
|
-
import { LazyIMTData, InternalLazyIMT
|
|
13
|
+
import { LazyIMTData, InternalLazyIMT } from "@zk-kit/lazy-imt.sol/InternalLazyIMT.sol";
|
|
14
14
|
import { HonkVerifier } from "./CRISPVerifier.sol";
|
|
15
15
|
|
|
16
16
|
contract CRISPProgram is IE3Program, Ownable {
|
|
@@ -22,6 +22,7 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
22
22
|
bytes32 paramsHash;
|
|
23
23
|
mapping(address slot => uint40 index) voteSlots;
|
|
24
24
|
LazyIMTData votes;
|
|
25
|
+
uint256 numOptions;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
// Constants
|
|
@@ -29,6 +30,8 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
29
30
|
bytes32 public constant ENCRYPTION_SCHEME_ID = keccak256("fhe.rs:BFV");
|
|
30
31
|
/// @notice The depth of the input Merkle tree.
|
|
31
32
|
uint8 public constant TREE_DEPTH = 20;
|
|
33
|
+
/// @notice Maximum number of bits allocated for vote counts in the plaintext output per option.
|
|
34
|
+
uint256 constant MAX_VOTE_BITS = 50;
|
|
32
35
|
|
|
33
36
|
// State variables
|
|
34
37
|
IEnclave public enclave;
|
|
@@ -54,9 +57,10 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
54
57
|
error InvalidTallyLength();
|
|
55
58
|
error SlotIsEmpty();
|
|
56
59
|
error MerkleRootNotSet();
|
|
60
|
+
error InvalidNumOptions();
|
|
57
61
|
|
|
58
62
|
// Events
|
|
59
|
-
event InputPublished(uint256 indexed e3Id, bytes
|
|
63
|
+
event InputPublished(uint256 indexed e3Id, bytes encryptedVote, uint256 index);
|
|
60
64
|
|
|
61
65
|
/// @notice Initialize the contract, binding it to a specified RISC Zero verifier.
|
|
62
66
|
/// @param _enclave The enclave address
|
|
@@ -106,10 +110,22 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
106
110
|
}
|
|
107
111
|
|
|
108
112
|
/// @inheritdoc IE3Program
|
|
109
|
-
function validate(
|
|
113
|
+
function validate(
|
|
114
|
+
uint256 e3Id,
|
|
115
|
+
uint256,
|
|
116
|
+
bytes calldata e3ProgramParams,
|
|
117
|
+
bytes calldata,
|
|
118
|
+
bytes calldata customParams
|
|
119
|
+
) external returns (bytes32) {
|
|
110
120
|
if (!authorizedContracts[msg.sender] && msg.sender != owner()) revert CallerNotAuthorized();
|
|
111
121
|
if (e3Data[e3Id].paramsHash != bytes32(0)) revert E3AlreadyInitialized();
|
|
112
122
|
|
|
123
|
+
// decode custom params to get the number of options
|
|
124
|
+
(, , uint256 numOptions) = abi.decode(customParams, (address, uint256, uint256));
|
|
125
|
+
if (numOptions < 2) revert InvalidNumOptions();
|
|
126
|
+
|
|
127
|
+
e3Data[e3Id].numOptions = numOptions;
|
|
128
|
+
|
|
113
129
|
e3Data[e3Id].paramsHash = keccak256(e3ProgramParams);
|
|
114
130
|
|
|
115
131
|
// Initialize the votes Merkle tree for this E3 ID.
|
|
@@ -128,60 +144,70 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
128
144
|
|
|
129
145
|
if (data.length == 0) revert EmptyInputData();
|
|
130
146
|
|
|
131
|
-
(bytes memory noirProof, bytes32
|
|
132
|
-
|
|
133
|
-
|
|
147
|
+
(bytes memory noirProof, address slotAddress, bytes32 encryptedVoteCommitment, bytes memory encryptedVote) = abi.decode(
|
|
148
|
+
data,
|
|
149
|
+
(bytes, address, bytes32, bytes)
|
|
150
|
+
);
|
|
134
151
|
|
|
135
|
-
(uint40 voteIndex,
|
|
136
|
-
|
|
137
|
-
// Set public inputs for the proof. Order must match Noir circuit.
|
|
138
|
-
bytes32[] memory noirPublicInputs = new bytes32[](4 + vote.length);
|
|
152
|
+
(uint40 voteIndex, bytes32 previousEncryptedVoteCommitment) = _processVote(e3Id, slotAddress, encryptedVoteCommitment);
|
|
139
153
|
|
|
140
154
|
// Fetch E3 to get committee public key
|
|
141
155
|
E3 memory e3 = enclave.getE3(e3Id);
|
|
142
156
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
noirPublicInputs[
|
|
146
|
-
noirPublicInputs[
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
157
|
+
// Set the public inputs for the proof. Order must match Noir circuit.
|
|
158
|
+
bytes32[] memory noirPublicInputs = new bytes32[](7);
|
|
159
|
+
noirPublicInputs[0] = previousEncryptedVoteCommitment;
|
|
160
|
+
noirPublicInputs[1] = e3.committeePublicKey;
|
|
161
|
+
noirPublicInputs[2] = bytes32(e3Data[e3Id].merkleRoot);
|
|
162
|
+
noirPublicInputs[3] = bytes32(uint256(uint160(slotAddress)));
|
|
163
|
+
noirPublicInputs[4] = bytes32(uint256(previousEncryptedVoteCommitment == bytes32(0) ? 1 : 0));
|
|
164
|
+
noirPublicInputs[5] = bytes32(e3Data[e3Id].numOptions);
|
|
165
|
+
noirPublicInputs[6] = encryptedVoteCommitment;
|
|
150
166
|
|
|
151
167
|
// Check if the ciphertext was encrypted correctly
|
|
152
168
|
if (!honkVerifier.verify(noirProof, noirPublicInputs)) {
|
|
153
169
|
revert InvalidNoirProof();
|
|
154
170
|
}
|
|
155
171
|
|
|
156
|
-
emit InputPublished(e3Id,
|
|
172
|
+
emit InputPublished(e3Id, encryptedVote, voteIndex);
|
|
157
173
|
}
|
|
158
174
|
|
|
159
175
|
/// @notice Decode the tally from the plaintext output
|
|
160
176
|
/// @param e3Id The E3 program ID
|
|
161
|
-
/// @return
|
|
162
|
-
|
|
163
|
-
function decodeTally(uint256 e3Id) public view returns (uint256 yes, uint256 no) {
|
|
164
|
-
// fetch from enclave
|
|
177
|
+
/// @return votes - an array of vote counts for each option
|
|
178
|
+
function decodeTally(uint256 e3Id) public view returns (uint256[] memory votes) {
|
|
165
179
|
E3 memory e3 = enclave.getE3(e3Id);
|
|
166
180
|
|
|
167
|
-
|
|
181
|
+
uint256 numOptions = e3Data[e3Id].numOptions;
|
|
182
|
+
|
|
183
|
+
// If num optionsis not configured, return empty array to avoid decoding errors.
|
|
184
|
+
// Users might be calling this function too early and there's no
|
|
185
|
+
if (numOptions == 0) {
|
|
186
|
+
return new uint256[](0);
|
|
187
|
+
}
|
|
188
|
+
|
|
168
189
|
uint64[] memory tally = _decodeBytesToUint64Array(e3.plaintextOutput);
|
|
169
190
|
|
|
170
|
-
uint256
|
|
191
|
+
uint256 segmentSize = tally.length / numOptions;
|
|
192
|
+
uint256 effectiveSize = segmentSize > MAX_VOTE_BITS ? MAX_VOTE_BITS : segmentSize;
|
|
171
193
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
194
|
+
votes = new uint256[](numOptions);
|
|
195
|
+
|
|
196
|
+
for (uint256 optIdx = 0; optIdx < numOptions; optIdx++) {
|
|
197
|
+
uint256 segmentStart = optIdx * segmentSize;
|
|
198
|
+
// Read only the last effectiveSize bits (where the value is, MSB first)
|
|
199
|
+
uint256 readStart = segmentStart + segmentSize - effectiveSize;
|
|
200
|
+
uint256 value = 0;
|
|
201
|
+
|
|
202
|
+
for (uint256 i = 0; i < effectiveSize; i++) {
|
|
203
|
+
uint256 weight = 2 ** (effectiveSize - 1 - i);
|
|
204
|
+
value += uint256(tally[readStart + i]) * weight;
|
|
205
|
+
}
|
|
177
206
|
|
|
178
|
-
|
|
179
|
-
for (uint256 i = halfD; i < tally.length; i++) {
|
|
180
|
-
uint256 weight = 2 ** (tally.length - 1 - i);
|
|
181
|
-
no += tally[i] * weight;
|
|
207
|
+
votes[optIdx] = value;
|
|
182
208
|
}
|
|
183
209
|
|
|
184
|
-
return
|
|
210
|
+
return votes;
|
|
185
211
|
}
|
|
186
212
|
|
|
187
213
|
/// @notice Get the slot index for a given E3 ID and slot address
|
|
@@ -220,22 +246,26 @@ contract CRISPProgram is IE3Program, Ownable {
|
|
|
220
246
|
|
|
221
247
|
/// @notice Process a vote: insert or update in the merkle tree depending
|
|
222
248
|
/// on whether it's the first vote or an override.
|
|
223
|
-
function _processVote(
|
|
249
|
+
function _processVote(
|
|
250
|
+
uint256 e3Id,
|
|
251
|
+
address slotAddress,
|
|
252
|
+
bytes32 encryptedVoteCommitment
|
|
253
|
+
) internal returns (uint40 voteIndex, bytes32 previousEncryptedVoteCommitment) {
|
|
224
254
|
uint40 storedIndexPlusOne = e3Data[e3Id].voteSlots[slotAddress];
|
|
225
255
|
|
|
226
256
|
// we treat the index 0 as not voted yet
|
|
227
257
|
// any valid index will be index + 1
|
|
228
258
|
if (storedIndexPlusOne == 0) {
|
|
229
259
|
// FIRST VOTE
|
|
230
|
-
|
|
260
|
+
previousEncryptedVoteCommitment = bytes32(0);
|
|
231
261
|
voteIndex = e3Data[e3Id].votes.numberOfLeaves;
|
|
232
262
|
e3Data[e3Id].voteSlots[slotAddress] = voteIndex + 1;
|
|
233
|
-
e3Data[e3Id].votes._insert(
|
|
263
|
+
e3Data[e3Id].votes._insert(uint256(encryptedVoteCommitment));
|
|
234
264
|
} else {
|
|
235
265
|
// RE-VOTE
|
|
236
|
-
isFirstVote = false;
|
|
237
266
|
voteIndex = storedIndexPlusOne - 1;
|
|
238
|
-
e3Data[e3Id].votes.
|
|
267
|
+
previousEncryptedVoteCommitment = bytes32(e3Data[e3Id].votes.elements[voteIndex]);
|
|
268
|
+
e3Data[e3Id].votes._update(uint256(encryptedVoteCommitment), voteIndex);
|
|
239
269
|
}
|
|
240
270
|
}
|
|
241
271
|
|
|
@@ -1,91 +1,88 @@
|
|
|
1
|
-
// SPDX-License-Identifier:
|
|
2
|
-
//
|
|
3
|
-
// This file is provided WITHOUT ANY WARRANTY;
|
|
4
|
-
// without even the implied warranty of MERCHANTABILITY
|
|
5
|
-
// or FITNESS FOR A PARTICULAR PURPOSE.
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright 2022 Aztec
|
|
6
3
|
pragma solidity >=0.8.21;
|
|
7
4
|
|
|
8
|
-
uint256 constant N =
|
|
9
|
-
uint256 constant LOG_N =
|
|
10
|
-
uint256 constant NUMBER_OF_PUBLIC_INPUTS =
|
|
11
|
-
uint256 constant VK_HASH =
|
|
5
|
+
uint256 constant N = 524288;
|
|
6
|
+
uint256 constant LOG_N = 19;
|
|
7
|
+
uint256 constant NUMBER_OF_PUBLIC_INPUTS = 23;
|
|
8
|
+
uint256 constant VK_HASH = 0x2349c3d182cb0307ecfa17d2cb91dcf9e7742a8daa67aa106831c761dd22030d;
|
|
12
9
|
library HonkVerificationKey {
|
|
13
10
|
function loadVerificationKey() internal pure returns (Honk.VerificationKey memory) {
|
|
14
11
|
Honk.VerificationKey memory vk = Honk.VerificationKey({
|
|
15
|
-
circuitSize: uint256(
|
|
16
|
-
logCircuitSize: uint256(
|
|
17
|
-
publicInputsSize: uint256(
|
|
12
|
+
circuitSize: uint256(524288),
|
|
13
|
+
logCircuitSize: uint256(19),
|
|
14
|
+
publicInputsSize: uint256(23),
|
|
18
15
|
ql: Honk.G1Point({
|
|
19
|
-
x: uint256(
|
|
20
|
-
y: uint256(
|
|
16
|
+
x: uint256(0x253c5186ca1b682f7d302cd73b85ea3447a5a2c64fc82b70652f7fc44b203128),
|
|
17
|
+
y: uint256(0x14f602413e183c57d3d3124290ab48b6c8b0cbace773766a573ead30bf5c2f4f)
|
|
21
18
|
}),
|
|
22
19
|
qr: Honk.G1Point({
|
|
23
|
-
x: uint256(
|
|
24
|
-
y: uint256(
|
|
20
|
+
x: uint256(0x2d20633d112c7c7efd2821f2860e9d1287f8f68ddd4b0216bb179078497a571c),
|
|
21
|
+
y: uint256(0x11928235f13ba529b1ee2f75fe26dda5ed5c79ec36028c09ad2bd8b957546344)
|
|
25
22
|
}),
|
|
26
23
|
qo: Honk.G1Point({
|
|
27
|
-
x: uint256(
|
|
28
|
-
y: uint256(
|
|
24
|
+
x: uint256(0x2b570f8e2eccc265f39b9e73778cf6e282554452adb19d2a2406952447d4aa6e),
|
|
25
|
+
y: uint256(0x14afd678c64e0dacd64724504e36bca6eccb5a477a5e2987b6543246b8135a90)
|
|
29
26
|
}),
|
|
30
27
|
q4: Honk.G1Point({
|
|
31
|
-
x: uint256(
|
|
32
|
-
y: uint256(
|
|
28
|
+
x: uint256(0x2d7f53a245e9c855325eeb73c8fea788f5b457293cacfd7e3e332210a27a7d2f),
|
|
29
|
+
y: uint256(0x182d5ef8840426caa829856d7e800ee98509383d9ee637d1facbc11f7a8fba0d)
|
|
33
30
|
}),
|
|
34
31
|
qm: Honk.G1Point({
|
|
35
|
-
x: uint256(
|
|
36
|
-
y: uint256(
|
|
32
|
+
x: uint256(0x19d90118c106191d2f2f0350a56547c943c1ed5910d47dd067761099b54d11f3),
|
|
33
|
+
y: uint256(0x0f8f03c2def6108448f72f5177b6a2eed01250670efb63ea6f5ab65abc2a6885)
|
|
37
34
|
}),
|
|
38
35
|
qc: Honk.G1Point({
|
|
39
|
-
x: uint256(
|
|
40
|
-
y: uint256(
|
|
36
|
+
x: uint256(0x2ead500c79e717f5cdbba88ffef46477c4f30926bf59547a9c141c4158f7c843),
|
|
37
|
+
y: uint256(0x027d6b571b395cf61aae9626f172ce4e41e598456f7b8e535c027e9129b2c98e)
|
|
41
38
|
}),
|
|
42
39
|
qLookup: Honk.G1Point({
|
|
43
|
-
x: uint256(
|
|
44
|
-
y: uint256(
|
|
40
|
+
x: uint256(0x136236e1bfc2af648ac078e134c1b4b9114b11937ebafcdd87f8ca7660715ebb),
|
|
41
|
+
y: uint256(0x02293c705250462935a653b7b993e13e2e8bc6480c45c84976d526cbdbd071df)
|
|
45
42
|
}),
|
|
46
43
|
qArith: Honk.G1Point({
|
|
47
|
-
x: uint256(
|
|
48
|
-
y: uint256(
|
|
44
|
+
x: uint256(0x074e7ead679c76d2c2d6d3f158cb522e71d14a169b2b1d0792cdfdad726f17a4),
|
|
45
|
+
y: uint256(0x21f9acd78d4150858f29c259c07e4552f6ec4bffac6c1e174cfb90e2e26bd68a)
|
|
49
46
|
}),
|
|
50
47
|
qDeltaRange: Honk.G1Point({
|
|
51
|
-
x: uint256(
|
|
52
|
-
y: uint256(
|
|
48
|
+
x: uint256(0x0cebfba75751a4eff3d7855bf0f314e523e2c709a75992eb5674a546627248e3),
|
|
49
|
+
y: uint256(0x16b715150f4de399940c535932174f5c634c9fd9137a94008bb38f89f1350b4c)
|
|
53
50
|
}),
|
|
54
51
|
qElliptic: Honk.G1Point({
|
|
55
|
-
x: uint256(
|
|
56
|
-
y: uint256(
|
|
52
|
+
x: uint256(0x174dba7fa4e38a55a78e43dda6c3fb81a1293285cf33eeb333ee186bb4331563),
|
|
53
|
+
y: uint256(0x0a2ff722359e35596e5abeec834c6cd73f4b06f5f2e837b31364f199f449ca77)
|
|
57
54
|
}),
|
|
58
55
|
qMemory: Honk.G1Point({
|
|
59
|
-
x: uint256(
|
|
60
|
-
y: uint256(
|
|
56
|
+
x: uint256(0x29f116092db8eb3773b017110ca5d3a7b35fa1b064cde91c9e280e20399d7ec2),
|
|
57
|
+
y: uint256(0x1f0e39e18ded75167a270d6e31b9a6ad9a9d1b0d67c365eeb172a3fea4d1371e)
|
|
61
58
|
}),
|
|
62
59
|
qNnf: Honk.G1Point({
|
|
63
|
-
x: uint256(
|
|
64
|
-
y: uint256(
|
|
60
|
+
x: uint256(0x19da50fca27dd36a006892b7cb6b36d7cfdac9d65fec6ae7a1a2e092e0988de5),
|
|
61
|
+
y: uint256(0x08f96f1d8e37be6dc83c9fbb3b912493841e4e81ab28a60c0fc85337cc4ed977)
|
|
65
62
|
}),
|
|
66
63
|
qPoseidon2External: Honk.G1Point({
|
|
67
|
-
x: uint256(
|
|
68
|
-
y: uint256(
|
|
64
|
+
x: uint256(0x2d20446a333063e66c1a552fecdfe12d0fdddeef0034569ac350f3299b09955a),
|
|
65
|
+
y: uint256(0x175e6e8776625134217ce9516a11cbbeab8c4c1c8b41cfb75f43de1f500b07d2)
|
|
69
66
|
}),
|
|
70
67
|
qPoseidon2Internal: Honk.G1Point({
|
|
71
|
-
x: uint256(
|
|
72
|
-
y: uint256(
|
|
68
|
+
x: uint256(0x090a76cca3c754a2ba40abdc2572fff64645060cfa5c48239a1df4dbb8360828),
|
|
69
|
+
y: uint256(0x0499d4c6aed1f78b33a6701459cd069e9bf7262754d2f15074a6c2401950761f)
|
|
73
70
|
}),
|
|
74
71
|
s1: Honk.G1Point({
|
|
75
|
-
x: uint256(
|
|
76
|
-
y: uint256(
|
|
72
|
+
x: uint256(0x012609fcd0fa67214d78f2d5f5e3e2b459a3c4b21531646de7d51d9cd5383aa9),
|
|
73
|
+
y: uint256(0x21394cebbe5f66f3aecf43d318b3cb9fc7640825baba0c5a5c190a20ceeb5edb)
|
|
77
74
|
}),
|
|
78
75
|
s2: Honk.G1Point({
|
|
79
|
-
x: uint256(
|
|
80
|
-
y: uint256(
|
|
76
|
+
x: uint256(0x080c7f024d9c813c60c84fc3e9bcad553c51f276d55e8d7a03c044b41cedef36),
|
|
77
|
+
y: uint256(0x2109db10b2da84ec2c4a1b62689d0952ababe94915293dfee09f1083010e5cfb)
|
|
81
78
|
}),
|
|
82
79
|
s3: Honk.G1Point({
|
|
83
|
-
x: uint256(
|
|
84
|
-
y: uint256(
|
|
80
|
+
x: uint256(0x2f7d6b77cd5c3ee56c255be61d0e90fd7da5898a7ce4850aaf1060513cb7cd9d),
|
|
81
|
+
y: uint256(0x2ce5fdacbf91fc3358f4eba637d60f109f70fa929a6a1bc1f9d86e7856b87dcd)
|
|
85
82
|
}),
|
|
86
83
|
s4: Honk.G1Point({
|
|
87
|
-
x: uint256(
|
|
88
|
-
y: uint256(
|
|
84
|
+
x: uint256(0x1db1540beb4dc13e8519b82205e9b4cb48833040c8b322d626df57e078afecc4),
|
|
85
|
+
y: uint256(0x28eb12f9f02ac092326277365f9eeaff536b8dbf771f9ace22d0e122f922196a)
|
|
89
86
|
}),
|
|
90
87
|
t1: Honk.G1Point({
|
|
91
88
|
x: uint256(0x1f16b037f0b4c96ea2a30a118a44e139881c0db8a4d6c9fde7db5c1c1738e61f),
|
|
@@ -104,28 +101,28 @@ library HonkVerificationKey {
|
|
|
104
101
|
y: uint256(0x2d7e8c1ecb92e2490049b50efc811df63f1ca97e58d5e82852dbec0c29715d71)
|
|
105
102
|
}),
|
|
106
103
|
id1: Honk.G1Point({
|
|
107
|
-
x: uint256(
|
|
108
|
-
y: uint256(
|
|
104
|
+
x: uint256(0x0a10b2e79989b15e3a69bd491cdae007b0bf9c82d9be3d7867b33e2287b91dac),
|
|
105
|
+
y: uint256(0x257794eaba7a0e7aed16e03d4d8c4cf7d878b029f4ea45c559bbc19b5ec4d1de)
|
|
109
106
|
}),
|
|
110
107
|
id2: Honk.G1Point({
|
|
111
|
-
x: uint256(
|
|
112
|
-
y: uint256(
|
|
108
|
+
x: uint256(0x25791b725ea7c712316ac4ffe10fdfcf37bd2b8f9d730ba2e26fa709bc7c3ae0),
|
|
109
|
+
y: uint256(0x15fba3e7928d36dc4dd6d6ff198b928c7246310974d4f74161cfd2781b9d3686)
|
|
113
110
|
}),
|
|
114
111
|
id3: Honk.G1Point({
|
|
115
|
-
x: uint256(
|
|
116
|
-
y: uint256(
|
|
112
|
+
x: uint256(0x270be32427e6404801b9b014f983d80acf18b828c6cf049f430d98fbe34e85e0),
|
|
113
|
+
y: uint256(0x2e7d27a99c4b574557ea6117c390c65072cdfa51a08621141ae26d7e143d0669)
|
|
117
114
|
}),
|
|
118
115
|
id4: Honk.G1Point({
|
|
119
|
-
x: uint256(
|
|
120
|
-
y: uint256(
|
|
116
|
+
x: uint256(0x18e2902febdb3e45358fe65981f338a7ffd1b16edd917de670fabe5d15307e20),
|
|
117
|
+
y: uint256(0x2f6f36f307a0f7012dc3918795312e71a1d4752966c2bc3151e5f5b3151fc236)
|
|
121
118
|
}),
|
|
122
119
|
lagrangeFirst: Honk.G1Point({
|
|
123
120
|
x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001),
|
|
124
121
|
y: uint256(0x0000000000000000000000000000000000000000000000000000000000000002)
|
|
125
122
|
}),
|
|
126
123
|
lagrangeLast: Honk.G1Point({
|
|
127
|
-
x: uint256(
|
|
128
|
-
y: uint256(
|
|
124
|
+
x: uint256(0x12b14f226e24a52e0bc85bc5478c806023107f257430aae49136064dd3315c60),
|
|
125
|
+
y: uint256(0x0dfe490435cf839caf81df5c8a164afc5e3c8646f36bf27c19850b3f913edce4)
|
|
129
126
|
})
|
|
130
127
|
});
|
|
131
128
|
return vk;
|
|
@@ -13,6 +13,34 @@ contract MockEnclave {
|
|
|
13
13
|
bytes public plaintextOutput;
|
|
14
14
|
bytes32 public committeePublicKey;
|
|
15
15
|
|
|
16
|
+
uint256 public nextE3Id;
|
|
17
|
+
|
|
18
|
+
mapping(uint256 => E3) public e3s;
|
|
19
|
+
|
|
20
|
+
function request(address program) external {
|
|
21
|
+
e3s[nextE3Id] = E3({
|
|
22
|
+
seed: 0,
|
|
23
|
+
threshold: [uint32(1), uint32(2)],
|
|
24
|
+
requestBlock: 0,
|
|
25
|
+
startWindow: [uint256(0), uint256(0)],
|
|
26
|
+
duration: 0,
|
|
27
|
+
expiration: 0,
|
|
28
|
+
encryptionSchemeId: bytes32(0),
|
|
29
|
+
e3Program: IE3Program(program),
|
|
30
|
+
e3ProgramParams: bytes(""),
|
|
31
|
+
customParams: abi.encode(address(0), nextE3Id, 2),
|
|
32
|
+
decryptionVerifier: IDecryptionVerifier(address(0)),
|
|
33
|
+
committeePublicKey: committeePublicKey,
|
|
34
|
+
ciphertextOutput: bytes32(0),
|
|
35
|
+
plaintextOutput: plaintextOutput,
|
|
36
|
+
requester: address(0)
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
IE3Program(program).validate(nextE3Id, 0, bytes(""), bytes(""), abi.encode(address(0), nextE3Id, 2));
|
|
40
|
+
|
|
41
|
+
nextE3Id++;
|
|
42
|
+
}
|
|
43
|
+
|
|
16
44
|
function setPlaintextOutput(bytes memory plaintext) external {
|
|
17
45
|
plaintextOutput = plaintext;
|
|
18
46
|
}
|
|
@@ -21,7 +49,7 @@ contract MockEnclave {
|
|
|
21
49
|
committeePublicKey = publicKeyHash;
|
|
22
50
|
}
|
|
23
51
|
|
|
24
|
-
function getE3(uint256
|
|
52
|
+
function getE3(uint256) external view returns (E3 memory) {
|
|
25
53
|
return
|
|
26
54
|
E3({
|
|
27
55
|
seed: 0,
|
|
@@ -33,11 +61,12 @@ contract MockEnclave {
|
|
|
33
61
|
encryptionSchemeId: bytes32(0),
|
|
34
62
|
e3Program: IE3Program(address(0)),
|
|
35
63
|
e3ProgramParams: bytes(""),
|
|
36
|
-
customParams:
|
|
64
|
+
customParams: abi.encode(address(0), 0, 2),
|
|
37
65
|
decryptionVerifier: IDecryptionVerifier(address(0)),
|
|
38
66
|
committeePublicKey: committeePublicKey,
|
|
39
67
|
ciphertextOutput: bytes32(0),
|
|
40
|
-
plaintextOutput: plaintextOutput
|
|
68
|
+
plaintextOutput: plaintextOutput,
|
|
69
|
+
requester: address(0)
|
|
41
70
|
});
|
|
42
71
|
}
|
|
43
72
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// SPDX-License-Identifier: LGPL-3.0-only
|
|
2
|
+
//
|
|
3
|
+
// This file is provided WITHOUT ANY WARRANTY;
|
|
4
|
+
// without even the implied warranty of MERCHANTABILITY
|
|
5
|
+
// or FITNESS FOR A PARTICULAR PURPOSE.
|
|
6
|
+
pragma solidity ^0.8.27;
|
|
7
|
+
|
|
8
|
+
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
9
|
+
|
|
10
|
+
/// @title MockVotingToken
|
|
11
|
+
/// @notice A mock voting token for testing purposes
|
|
12
|
+
/// @dev Public mint function that allows to keep balances to 1e9.
|
|
13
|
+
/// @dev by default CRISP server will scale down voting power by 1e18/2
|
|
14
|
+
/// @dev in this case leaving everyone with a balance of 1 to vote yes or no
|
|
15
|
+
contract MockVotingToken is ERC20 {
|
|
16
|
+
// half of 10e18
|
|
17
|
+
uint256 public constant MAX_BALANCE = 1e9;
|
|
18
|
+
|
|
19
|
+
constructor() ERC20("Mock Voting Token", "MVT") {
|
|
20
|
+
_mint(msg.sender, 1e9);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function mint(address to, uint256) external {
|
|
24
|
+
if (balanceOf(to) + 1e9 > MAX_BALANCE) {
|
|
25
|
+
// silently fail
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
_mint(to, 1e9);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function decimals() public pure override returns (uint8) {
|
|
32
|
+
return 18;
|
|
33
|
+
}
|
|
34
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crisp-e3/contracts",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"contracts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@zk-kit/lazy-imt.sol": "2.0.0-beta.12",
|
|
32
32
|
"poseidon-solidity": "^0.0.5",
|
|
33
33
|
"solady": "^0.1.13",
|
|
34
|
-
"@enclave-e3/contracts": "0.1.
|
|
34
|
+
"@enclave-e3/contracts": "0.1.8"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@nomicfoundation/hardhat-ethers": "4",
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
"typechain": "^8.3.0",
|
|
60
60
|
"typescript": "5.8.3",
|
|
61
61
|
"viem": "2.30.6",
|
|
62
|
-
"@crisp-e3/zk-inputs": "^0.5.
|
|
63
|
-
"@crisp-e3/sdk": "^0.5.
|
|
62
|
+
"@crisp-e3/zk-inputs": "^0.5.9",
|
|
63
|
+
"@crisp-e3/sdk": "^0.5.9"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {
|
|
66
66
|
"compile": "hardhat compile",
|
|
@@ -69,8 +69,9 @@
|
|
|
69
69
|
"ciphernode:add:self": "hardhat ciphernode:add",
|
|
70
70
|
"clean:deployments": "hardhat utils:clean-deployments",
|
|
71
71
|
"deploy:contracts": "hardhat run deploy/deploy.ts",
|
|
72
|
+
"deploy:contracts:mock": "export USE_MOCKS=true PRINT_ENV_VARS=true && pnpm deploy:contracts",
|
|
72
73
|
"deploy:contracts:full": "export DEPLOY_ENCLAVE=true && pnpm deploy:contracts",
|
|
73
|
-
"deploy:contracts:full:mock": "export DEPLOY_ENCLAVE=true
|
|
74
|
+
"deploy:contracts:full:mock": "export DEPLOY_ENCLAVE=true USE_MOCKS=true PRINT_ENV_VARS=true && pnpm deploy:contracts",
|
|
74
75
|
"test": "hardhat test mocha",
|
|
75
76
|
"verify": "hardhat run deploy/verify.ts",
|
|
76
77
|
"updateSubmissionWindow": "hardhat ciphernode:window"
|