@maci-protocol/circuits 0.0.0-ci.2653bc0 → 0.0.0-ci.2d2f5fb

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.
Files changed (41) hide show
  1. package/LICENSE +1 -2
  2. package/build/ts/{genZkeys.d.ts → generateZkeys.d.ts} +1 -1
  3. package/build/ts/generateZkeys.d.ts.map +1 -0
  4. package/build/ts/{genZkeys.js → generateZkeys.js} +1 -1
  5. package/build/ts/generateZkeys.js.map +1 -0
  6. package/build/ts/types.d.ts +11 -12
  7. package/build/ts/types.d.ts.map +1 -1
  8. package/build/tsconfig.build.tsbuildinfo +1 -1
  9. package/circom/circuits.json +7 -7
  10. package/circom/coordinator/non-qv/processMessages.circom +106 -107
  11. package/circom/coordinator/non-qv/tallyVotes.circom +38 -32
  12. package/circom/coordinator/qv/processMessages.circom +107 -105
  13. package/circom/coordinator/qv/tallyVotes.circom +56 -54
  14. package/circom/utils/{calculateTotal.circom → CalculateTotal.circom} +2 -0
  15. package/circom/utils/{verifySignature.circom → EdDSAPoseidonVerifier.circom} +40 -66
  16. package/circom/utils/MessageHasher.circom +57 -0
  17. package/circom/utils/MessageToCommand.circom +107 -0
  18. package/circom/utils/PoseidonHasher.circom +29 -0
  19. package/circom/utils/{privToPubKey.circom → PrivateToPublicKey.circom} +12 -10
  20. package/circom/utils/VerifySignature.circom +39 -0
  21. package/circom/utils/full/MessageValidator.circom +93 -0
  22. package/circom/utils/full/StateLeafAndBallotTransformer.circom +122 -0
  23. package/circom/utils/non-qv/{messageValidator.circom → MessageValidator.circom} +15 -13
  24. package/circom/utils/non-qv/{stateLeafAndBallotTransformer.circom → StateLeafAndBallotTransformer.circom} +36 -36
  25. package/circom/utils/qv/{messageValidator.circom → MessageValidator.circom} +15 -13
  26. package/circom/utils/qv/{stateLeafAndBallotTransformer.circom → StateLeafAndBallotTransformer.circom} +36 -36
  27. package/circom/utils/trees/BinaryMerkleRoot.circom +62 -0
  28. package/circom/utils/trees/CheckRoot.circom +49 -0
  29. package/circom/utils/trees/LeafExists.circom +27 -0
  30. package/circom/utils/trees/MerklePathIndicesGenerator.circom +44 -0
  31. package/circom/utils/trees/MerkleTreeInclusionProof.circom +50 -0
  32. package/circom/utils/trees/incrementalQuinaryTree.circom +2 -2
  33. package/circom/voter/PollJoined.circom +43 -0
  34. package/circom/voter/PollJoining.circom +54 -0
  35. package/package.json +15 -12
  36. package/build/ts/genZkeys.d.ts.map +0 -1
  37. package/build/ts/genZkeys.js.map +0 -1
  38. package/circom/utils/hashers.circom +0 -78
  39. package/circom/utils/messageToCommand.circom +0 -78
  40. package/circom/utils/trees/incrementalMerkleTree.circom +0 -198
  41. package/circom/voter/poll.circom +0 -93
@@ -5,12 +5,17 @@ include "./mux1.circom";
5
5
  // zk-kit imports
6
6
  include "./safe-comparators.circom";
7
7
  // local imports
8
- include "../../utils/hashers.circom";
9
- include "../../utils/messageToCommand.circom";
10
- include "../../utils/privToPubKey.circom";
11
- include "../../utils/qv/stateLeafAndBallotTransformer.circom";
8
+ include "../../utils/PoseidonHasher.circom";
9
+ include "../../utils/MessageHasher.circom";
10
+ include "../../utils/MessageToCommand.circom";
11
+ include "../../utils/PrivateToPublicKey.circom";
12
+ include "../../utils/qv/StateLeafAndBallotTransformer.circom";
12
13
  include "../../utils/trees/incrementalQuinaryTree.circom";
13
- include "../../utils/trees/incrementalMerkleTree.circom";
14
+ include "../../utils/trees/MerkleTreeInclusionProof.circom";
15
+ include "../../utils/trees/LeafExists.circom";
16
+ include "../../utils/trees/CheckRoot.circom";
17
+ include "../../utils/trees/MerklePathIndicesGenerator.circom";
18
+ include "../../utils/trees/BinaryMerkleRoot.circom";
14
19
 
15
20
  /**
16
21
  * Proves the correctness of processing a batch of MACI messages.
@@ -30,32 +35,31 @@ template ProcessMessages(
30
35
  var VOTE_OPTION_TREE_ARITY = 5;
31
36
  // Default for binary trees.
32
37
  var STATE_TREE_ARITY = 2;
33
- var MSG_LENGTH = 10;
34
- var PACKED_CMD_LENGTH = 4;
35
- var STATE_LEAF_LENGTH = 4;
38
+ var MESSAGE_LENGTH = 10;
39
+ var PACKED_COMMAND_LENGTH = 4;
40
+ var STATE_LEAF_LENGTH = 3;
36
41
  var BALLOT_LENGTH = 2;
37
- var BALLOT_NONCE_IDX = 0;
38
- var BALLOT_VO_ROOT_IDX = 1;
39
- var STATE_LEAF_PUB_X_IDX = 0;
40
- var STATE_LEAF_PUB_Y_IDX = 1;
41
- var STATE_LEAF_VOICE_CREDIT_BALANCE_IDX = 2;
42
- var STATE_LEAF_TIMESTAMP_IDX = 3;
43
- var msgTreeZeroValue = 8370432830353022751713833565135785980866757267633941821328460903436894336785;
42
+ var BALLOT_NONCE_INDEX = 0;
43
+ var BALLOT_VOTE_OPTION_ROOT_INDEX = 1;
44
+ var STATE_LEAF_PUBLIC_X_INDEX = 0;
45
+ var STATE_LEAF_PUBLIC_Y_INDEX = 1;
46
+ var STATE_LEAF_VOICE_CREDIT_BALANCE_INDEX = 2;
47
+ var MESSAGE_TREE_ZERO_VALUE = 8370432830353022751713833565135785980866757267633941821328460903436894336785;
44
48
  // Number of options for this poll.
45
49
  var maxVoteOptions = VOTE_OPTION_TREE_ARITY ** voteOptionTreeDepth;
46
50
 
47
51
  // Number of users that have completed the sign up.
48
- signal input numSignUps;
52
+ signal input totalSignups;
49
53
  // Value of chainHash at beginning of batch
50
54
  signal input inputBatchHash;
51
55
  // Value of chainHash at end of batch
52
56
  signal input outputBatchHash;
53
57
  // The messages.
54
- signal input msgs[batchSize][MSG_LENGTH];
58
+ signal input messages[batchSize][MESSAGE_LENGTH];
55
59
  // The coordinator's private key.
56
- signal input coordPrivKey;
60
+ signal input coordinatorPrivateKey;
57
61
  // The ECDH public key per message.
58
- signal input encPubKeys[batchSize][2];
62
+ signal input encryptionPublicKeys[batchSize][2];
59
63
  // The current state root (before the processing).
60
64
  signal input currentStateRoot;
61
65
  // The actual tree depth (might be <= stateTreeDepth).
@@ -118,10 +122,10 @@ template ProcessMessages(
118
122
  var voteOptionsValid = LessEqThan(32)([voteOptions, VOTE_OPTION_TREE_ARITY ** voteOptionTreeDepth]);
119
123
  voteOptionsValid === 1;
120
124
 
121
- // Check numSignUps <= the max number of users (i.e., number of state leaves
125
+ // Check totalSignups <= the max number of users (i.e., number of state leaves
122
126
  // that can fit the state tree).
123
- var numSignUpsValid = LessEqThan(32)([numSignUps, STATE_TREE_ARITY ** stateTreeDepth]);
124
- numSignUpsValid === 1;
127
+ var totalSignupsValid = LessEqThan(32)([totalSignups, STATE_TREE_ARITY ** stateTreeDepth]);
128
+ totalSignupsValid === 1;
125
129
 
126
130
  // Hash each Message to check their existence in the Message tree.
127
131
  var computedMessageHashers[batchSize];
@@ -131,7 +135,7 @@ template ProcessMessages(
131
135
 
132
136
  for (var i = 0; i < batchSize; i++) {
133
137
  // calculate message hash
134
- computedMessageHashers[i] = MessageHasher()(msgs[i], encPubKeys[i]);
138
+ computedMessageHashers[i] = MessageHasher()(messages[i], encryptionPublicKeys[i]);
135
139
  // check if message is valid or not (if index of message is less than index of last valid message in batch)
136
140
  var batchStartIndexValid = SafeLessThan(32)([index + i, batchEndIndex]);
137
141
  // calculate chain hash if message is valid
@@ -155,38 +159,38 @@ template ProcessMessages(
155
159
  // Ensure that the coordinator's public key from the contract is correct
156
160
  // based on the given private key - that is, the prover knows the
157
161
  // coordinator's private key.
158
- var derivedPubKey[2] = PrivToPubKey()(coordPrivKey);
159
- var derivedPubKeyHash = PoseidonHasher(2)(derivedPubKey);
160
- derivedPubKeyHash === coordinatorPublicKeyHash;
162
+ var derivedPublicKey[2] = PrivateToPublicKey()(coordinatorPrivateKey);
163
+ var derivedPublicKeyHash = PoseidonHasher(2)(derivedPublicKey);
164
+ derivedPublicKeyHash === coordinatorPublicKeyHash;
161
165
 
162
166
  // Decrypt each Message into a Command.
163
167
  // The command i-th is composed by the following fields.
164
168
  // e.g., command 0 is made of commandsStateIndex[0],
165
- // commandsNewPubKey[0], ..., commandsPackedCommandOut[0]
169
+ // commandsNewPublicKey[0], ..., commandsPackedCommandOut[0]
166
170
  var computedCommandsStateIndex[batchSize];
167
- var computedCommandsNewPubKey[batchSize][2];
171
+ var computedCommandsNewPublicKey[batchSize][2];
168
172
  var computedCommandsVoteOptionIndex[batchSize];
169
173
  var computedCommandsNewVoteWeight[batchSize];
170
174
  var computedCommandsNonce[batchSize];
171
175
  var computedCommandsPollId[batchSize];
172
176
  var computedCommandsSalt[batchSize];
173
- var computedCommandsSigR8[batchSize][2];
174
- var computedCommandsSigS[batchSize];
175
- var computedCommandsPackedCommandOut[batchSize][PACKED_CMD_LENGTH];
177
+ var computedCommandsSignaturePoint[batchSize][2];
178
+ var computedCommandsSignatureScalar[batchSize];
179
+ var computedCommandsPackedCommandOut[batchSize][PACKED_COMMAND_LENGTH];
176
180
 
177
181
  for (var i = 0; i < batchSize; i++) {
178
182
  (
179
183
  computedCommandsStateIndex[i],
180
- computedCommandsNewPubKey[i],
184
+ computedCommandsNewPublicKey[i],
181
185
  computedCommandsVoteOptionIndex[i],
182
186
  computedCommandsNewVoteWeight[i],
183
187
  computedCommandsNonce[i],
184
188
  computedCommandsPollId[i],
185
189
  computedCommandsSalt[i],
186
- computedCommandsSigR8[i],
187
- computedCommandsSigS[i],
190
+ computedCommandsSignaturePoint[i],
191
+ computedCommandsSignatureScalar[i],
188
192
  computedCommandsPackedCommandOut[i]
189
- ) = MessageToCommand()(msgs[i], coordPrivKey, encPubKeys[i]);
193
+ ) = MessageToCommand()(messages[i], coordinatorPrivateKey, encryptionPublicKeys[i]);
190
194
  }
191
195
 
192
196
  // Process messages in reverse order.
@@ -219,7 +223,7 @@ template ProcessMessages(
219
223
  }
220
224
 
221
225
  (computedNewVoteStateRoot[i], computedNewVoteBallotRoot[i]) = ProcessOne(stateTreeDepth, voteOptionTreeDepth)(
222
- numSignUps,
226
+ totalSignups,
223
227
  stateRoots[i + 1],
224
228
  ballotRoots[i + 1],
225
229
  actualStateTreeDepth,
@@ -230,14 +234,14 @@ template ProcessMessages(
230
234
  currentVoteWeights[i],
231
235
  currentVoteWeightsPathElement,
232
236
  computedCommandsStateIndex[i],
233
- computedCommandsNewPubKey[i],
237
+ computedCommandsNewPublicKey[i],
234
238
  computedCommandsVoteOptionIndex[i],
235
239
  computedCommandsNewVoteWeight[i],
236
240
  computedCommandsNonce[i],
237
241
  computedCommandsPollId[i],
238
242
  computedCommandsSalt[i],
239
- computedCommandsSigR8[i],
240
- computedCommandsSigS[i],
243
+ computedCommandsSignaturePoint[i],
244
+ computedCommandsSignatureScalar[i],
241
245
  computedCommandsPackedCommandOut[i],
242
246
  voteOptions
243
247
  );
@@ -260,28 +264,26 @@ template ProcessMessages(
260
264
  */
261
265
  template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
262
266
  // Constants defining the structure and size of state and ballots.
263
- var STATE_LEAF_LENGTH = 4;
267
+ var STATE_LEAF_LENGTH = 3;
264
268
  var BALLOT_LENGTH = 2;
265
- var MSG_LENGTH = 10;
266
- var PACKED_CMD_LENGTH = 4;
269
+ var MESSAGE_LENGTH = 10;
270
+ var PACKED_COMMAND_LENGTH = 4;
267
271
  var VOTE_OPTION_TREE_ARITY = 5;
268
272
  var STATE_TREE_ARITY = 2;
269
- var BALLOT_NONCE_IDX = 0;
270
- // Ballot vote option (VO) root index.
271
- var BALLOT_VO_ROOT_IDX = 1;
273
+ var BALLOT_NONCE_INDEX = 0;
274
+ // Ballot vote option (vote option) root index.
275
+ var BALLOT_VOTE_OPTION_ROOT_INDEX = 1;
272
276
 
273
277
  // Indices for elements within a state leaf.
274
278
  // Public key.
275
- var STATE_LEAF_PUB_X_IDX = 0;
276
- var STATE_LEAF_PUB_Y_IDX = 1;
279
+ var STATE_LEAF_PUBLIC_X_INDEX = 0;
280
+ var STATE_LEAF_PUBLIC_Y_INDEX = 1;
277
281
  // Voice Credit balance.
278
- var STATE_LEAF_VOICE_CREDIT_BALANCE_IDX = 2;
279
- // Timestamp.
280
- var STATE_LEAF_TIMESTAMP_IDX = 3;
281
- var N_BITS = 252;
282
+ var STATE_LEAF_VOICE_CREDIT_BALANCE_INDEX = 2;
283
+ var NUMBER_BITS = 252;
282
284
 
283
285
  // Number of users that have completed the sign up.
284
- signal input numSignUps;
286
+ signal input totalSignups;
285
287
  // The current value of the state tree root.
286
288
  signal input currentStateRoot;
287
289
  // The current value of the ballot tree root.
@@ -303,16 +305,16 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
303
305
  signal input currentVoteWeightsPathElements[voteOptionTreeDepth][VOTE_OPTION_TREE_ARITY - 1];
304
306
 
305
307
  // Inputs related to the command being processed.
306
- signal input cmdStateIndex;
307
- signal input cmdNewPubKey[2];
308
- signal input cmdVoteOptionIndex;
309
- signal input cmdNewVoteWeight;
310
- signal input cmdNonce;
311
- signal input cmdPollId;
312
- signal input cmdSalt;
313
- signal input cmdSigR8[2];
314
- signal input cmdSigS;
315
- signal input packedCmd[PACKED_CMD_LENGTH];
308
+ signal input commandStateIndex;
309
+ signal input commandPublicKey[2];
310
+ signal input commandVoteOptionIndex;
311
+ signal input commandNewVoteWeight;
312
+ signal input commandNonce;
313
+ signal input commandPollId;
314
+ signal input commandSalt;
315
+ signal input commandSignaturePoint[2];
316
+ signal input commandSignatureScalar;
317
+ signal input packedCommand[PACKED_COMMAND_LENGTH];
316
318
 
317
319
  // The number of valid vote options for the poll.
318
320
  signal input voteOptions;
@@ -323,40 +325,40 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
323
325
  // Intermediate signals.
324
326
  // currentVoteWeight * currentVoteWeight.
325
327
  signal currentVoteWeightSquare;
326
- // cmdNewVoteWeight * cmdNewVoteWeight.
327
- signal cmdNewVoteWeightSquare;
328
- // equal to newBallotVoRootMux (Mux1).
329
- signal newBallotVoRoot;
328
+ // commandNewVoteWeight * commandNewVoteWeight.
329
+ signal commandNewVoteWeightSquare;
330
+ // equal to newBallotVoteOptionRootMux (Mux1).
331
+ signal newBallotVoteOptionRoot;
330
332
 
331
333
  // 1. Transform a state leaf and a ballot with a command.
332
334
  // The result is a new state leaf, a new ballot, and an isValid signal (0 or 1).
333
- var computedNewSlPubKey[2], computedNewBallotNonce, computedIsValid, computedIsStateLeafIndexValid, computedIsVoteOptionIndexValid;
334
- (computedNewSlPubKey, computedNewBallotNonce, computedIsValid, computedIsStateLeafIndexValid, computedIsVoteOptionIndexValid) = StateLeafAndBallotTransformer()(
335
- numSignUps,
335
+ var computedNewStateLeafPublicKey[2], computedNewBallotNonce, computedIsValid, computedIsStateLeafIndexValid, computedIsVoteOptionIndexValid;
336
+ (computedNewStateLeafPublicKey, computedNewBallotNonce, computedIsValid, computedIsStateLeafIndexValid, computedIsVoteOptionIndexValid) = StateLeafAndBallotTransformer()(
337
+ totalSignups,
336
338
  voteOptions,
337
- [stateLeaf[STATE_LEAF_PUB_X_IDX], stateLeaf[STATE_LEAF_PUB_Y_IDX]],
338
- stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX],
339
- ballot[BALLOT_NONCE_IDX],
339
+ [stateLeaf[STATE_LEAF_PUBLIC_X_INDEX], stateLeaf[STATE_LEAF_PUBLIC_Y_INDEX]],
340
+ stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_INDEX],
341
+ ballot[BALLOT_NONCE_INDEX],
340
342
  currentVoteWeight,
341
- cmdStateIndex,
342
- cmdNewPubKey,
343
- cmdVoteOptionIndex,
344
- cmdNewVoteWeight,
345
- cmdNonce,
346
- cmdPollId,
347
- cmdSalt,
348
- cmdSigR8,
349
- cmdSigS,
350
- packedCmd
343
+ commandStateIndex,
344
+ commandPublicKey,
345
+ commandVoteOptionIndex,
346
+ commandNewVoteWeight,
347
+ commandNonce,
348
+ commandPollId,
349
+ commandSalt,
350
+ commandSignaturePoint,
351
+ commandSignatureScalar,
352
+ packedCommand
351
353
  );
352
354
 
353
355
  // 2. If computedIsStateLeafIndexValid is equal to zero, generate indices for leaf zero.
354
356
  // Otherwise, generate indices for command.stateIndex.
355
- var stateIndexMux = Mux1()([0, cmdStateIndex], computedIsStateLeafIndexValid);
356
- var computedStateLeafPathIndices[stateTreeDepth] = MerkleGeneratePathIndices(stateTreeDepth)(stateIndexMux);
357
+ var stateIndexMux = Mux1()([0, commandStateIndex], computedIsStateLeafIndexValid);
358
+ var computedStateLeafPathIndices[stateTreeDepth] = MerklePathIndicesGenerator(stateTreeDepth)(stateIndexMux);
357
359
 
358
360
  // 3. Verify that the original state leaf exists in the given state root.
359
- var stateLeafHash = PoseidonHasher(4)(stateLeaf);
361
+ var stateLeafHash = PoseidonHasher(3)(stateLeaf);
360
362
  var stateLeafQip = BinaryMerkleRoot(stateTreeDepth)(
361
363
  stateLeafHash,
362
364
  actualStateTreeDepth,
@@ -368,8 +370,8 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
368
370
 
369
371
  // 4. Verify that the original ballot exists in the given ballot root.
370
372
  var computedBallot = PoseidonHasher(2)([
371
- ballot[BALLOT_NONCE_IDX],
372
- ballot[BALLOT_VO_ROOT_IDX]
373
+ ballot[BALLOT_NONCE_INDEX],
374
+ ballot[BALLOT_VOTE_OPTION_ROOT_INDEX]
373
375
  ]);
374
376
 
375
377
  var computedBallotQip = MerkleTreeInclusionProof(stateTreeDepth)(
@@ -381,12 +383,12 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
381
383
  computedBallotQip === currentBallotRoot;
382
384
 
383
385
  // 5. Verify that currentVoteWeight exists in the ballot's vote option root
384
- // at cmdVoteOptionIndex.
386
+ // at commandVoteOptionIndex.
385
387
  currentVoteWeightSquare <== currentVoteWeight * currentVoteWeight;
386
- cmdNewVoteWeightSquare <== cmdNewVoteWeight * cmdNewVoteWeight;
388
+ commandNewVoteWeightSquare <== commandNewVoteWeight * commandNewVoteWeight;
387
389
 
388
- var cmdVoteOptionIndexMux = Mux1()([0, cmdVoteOptionIndex], computedIsVoteOptionIndexValid);
389
- var computedCurrentVoteWeightPathIndices[voteOptionTreeDepth] = QuinGeneratePathIndices(voteOptionTreeDepth)(cmdVoteOptionIndexMux);
390
+ var commandVoteOptionIndexMux = Mux1()([0, commandVoteOptionIndex], computedIsVoteOptionIndexValid);
391
+ var computedCurrentVoteWeightPathIndices[voteOptionTreeDepth] = QuinGeneratePathIndices(voteOptionTreeDepth)(commandVoteOptionIndexMux);
390
392
 
391
393
  var computedCurrentVoteWeightQip = QuinTreeInclusionProof(voteOptionTreeDepth)(
392
394
  currentVoteWeight,
@@ -394,13 +396,13 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
394
396
  currentVoteWeightsPathElements
395
397
  );
396
398
 
397
- computedCurrentVoteWeightQip === ballot[BALLOT_VO_ROOT_IDX];
399
+ computedCurrentVoteWeightQip === ballot[BALLOT_VOTE_OPTION_ROOT_INDEX];
398
400
 
399
- var voteWeightMux = Mux1()([currentVoteWeight, cmdNewVoteWeight], computedIsValid);
401
+ var voteWeightMux = Mux1()([currentVoteWeight, commandNewVoteWeight], computedIsValid);
400
402
  var voiceCreditBalanceMux = Mux1()(
401
403
  [
402
- stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX],
403
- stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX] + currentVoteWeightSquare - cmdNewVoteWeightSquare
404
+ stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_INDEX],
405
+ stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_INDEX] + currentVoteWeightSquare - commandNewVoteWeightSquare
404
406
  ],
405
407
  computedIsValid
406
408
  );
@@ -413,23 +415,22 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
413
415
  );
414
416
 
415
417
  // The new vote option root in the ballot
416
- var newBallotVoRootMux = Mux1()(
417
- [ballot[BALLOT_VO_ROOT_IDX], computedNewVoteOptionTreeQip],
418
+ var newBallotVoteOptionRootMux = Mux1()(
419
+ [ballot[BALLOT_VOTE_OPTION_ROOT_INDEX], computedNewVoteOptionTreeQip],
418
420
  computedIsValid
419
421
  );
420
422
 
421
- newBallotVoRoot <== newBallotVoRootMux;
423
+ newBallotVoteOptionRoot <== newBallotVoteOptionRootMux;
422
424
 
423
425
  // 6. Generate a new state root.
424
- var computedNewStateLeafhash = PoseidonHasher(4)([
425
- computedNewSlPubKey[STATE_LEAF_PUB_X_IDX],
426
- computedNewSlPubKey[STATE_LEAF_PUB_Y_IDX],
427
- voiceCreditBalanceMux,
428
- stateLeaf[STATE_LEAF_TIMESTAMP_IDX]
426
+ var computedNewStateLeafHash = PoseidonHasher(3)([
427
+ computedNewStateLeafPublicKey[STATE_LEAF_PUBLIC_X_INDEX],
428
+ computedNewStateLeafPublicKey[STATE_LEAF_PUBLIC_Y_INDEX],
429
+ voiceCreditBalanceMux
429
430
  ]);
430
431
 
431
432
  var computedNewStateLeafQip = BinaryMerkleRoot(stateTreeDepth)(
432
- computedNewStateLeafhash,
433
+ computedNewStateLeafHash,
433
434
  actualStateTreeDepth,
434
435
  computedStateLeafPathIndices,
435
436
  stateLeafPathElements
@@ -438,7 +439,7 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
438
439
  newStateRoot <== computedNewStateLeafQip;
439
440
 
440
441
  // 7. Generate a new ballot root.
441
- var computedNewBallot = PoseidonHasher(2)([computedNewBallotNonce, newBallotVoRoot]);
442
+ var computedNewBallot = PoseidonHasher(2)([computedNewBallotNonce, newBallotVoteOptionRoot]);
442
443
  var computedNewBallotQip = MerkleTreeInclusionProof(stateTreeDepth)(
443
444
  computedNewBallot,
444
445
  computedStateLeafPathIndices,
@@ -447,3 +448,4 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
447
448
 
448
449
  newBallotRoot <== computedNewBallotQip;
449
450
  }
451
+
@@ -5,10 +5,12 @@ include "./comparators.circom";
5
5
  // zk-kit import
6
6
  include "./unpack-element.circom";
7
7
  // local imports
8
- include "../../utils/trees/incrementalMerkleTree.circom";
8
+ include "../../utils/trees/CheckRoot.circom";
9
+ include "../../utils/trees/MerklePathIndicesGenerator.circom";
10
+ include "../../utils/trees/LeafExists.circom";
9
11
  include "../../utils/trees/incrementalQuinaryTree.circom";
10
- include "../../utils/calculateTotal.circom";
11
- include "../../utils/hashers.circom";
12
+ include "../../utils/CalculateTotal.circom";
13
+ include "../../utils/PoseidonHasher.circom";
12
14
 
13
15
  /**
14
16
  * Processes batches of votes and verifies their validity in a Merkle tree structure.
@@ -33,16 +35,16 @@ template TallyVotes(
33
35
  // The number of ballots processed at once, determined by the depth of the intermediate state tree.
34
36
  var batchSize = BALLOT_TREE_ARITY ** intStateTreeDepth;
35
37
  // Number of voting options available, determined by the depth of the vote option tree.
36
- var numVoteOptions = TREE_ARITY ** voteOptionTreeDepth;
38
+ var totalVoteOptions = TREE_ARITY ** voteOptionTreeDepth;
37
39
 
38
40
  // Number of elements in each ballot.
39
41
  var BALLOT_LENGTH = 2;
40
42
  // Index for the nonce in the ballot array.
41
- var BALLOT_NONCE_IDX = 0;
43
+ var BALLOT_NONCE_INDEX = 0;
42
44
  // Index for the voting option root in the ballot array.
43
- var BALLOT_VO_ROOT_IDX = 1;
45
+ var BALLOT_VOTE_OPTION_ROOT_INDEX = 1;
44
46
  // Difference in tree depths, used in path calculations.
45
- var k = stateTreeDepth - intStateTreeDepth;
47
+ var STATE_INT_TREE_DEPTH_DIFFERENCE = stateTreeDepth - intStateTreeDepth;
46
48
 
47
49
  // Root of the state Merkle tree, representing the overall state before voting.
48
50
  signal input stateRoot;
@@ -59,13 +61,13 @@ template TallyVotes(
59
61
  // Start index of given batch
60
62
  signal input index;
61
63
  // Number of users that signup
62
- signal input numSignUps;
64
+ signal input totalSignups;
63
65
  // Ballots and their corresponding path elements for verification in the tree.
64
66
  signal input ballots[batchSize][BALLOT_LENGTH];
65
- signal input ballotPathElements[k][BALLOT_TREE_ARITY - 1];
66
- signal input votes[batchSize][numVoteOptions];
67
+ signal input ballotPathElements[STATE_INT_TREE_DEPTH_DIFFERENCE][BALLOT_TREE_ARITY - 1];
68
+ signal input votes[batchSize][totalVoteOptions];
67
69
  // Current results for each vote option.
68
- signal input currentResults[numVoteOptions];
70
+ signal input currentResults[totalVoteOptions];
69
71
  // Salt for the root of the current results.
70
72
  signal input currentResultsRootSalt;
71
73
  // Total voice credits spent so far.
@@ -73,13 +75,13 @@ template TallyVotes(
73
75
  // Salt for the total spent voice credits.
74
76
  signal input currentSpentVoiceCreditSubtotalSalt;
75
77
  // Spent voice credits per vote option.
76
- signal input currentPerVOSpentVoiceCredits[numVoteOptions];
78
+ signal input currentPerVoteOptionSpentVoiceCredits[totalVoteOptions];
77
79
  // Salt for the root of spent credits per option.
78
- signal input currentPerVOSpentVoiceCreditsRootSalt;
80
+ signal input currentPerVoteOptionSpentVoiceCreditsRootSalt;
79
81
  // Salt for the root of the new results.
80
82
  signal input newResultsRootSalt;
81
83
  // Salt for the new spent credits per vote option root.
82
- signal input newPerVOSpentVoiceCreditsRootSalt;
84
+ signal input newPerVoteOptionSpentVoiceCreditsRootSalt;
83
85
  // Salt for the new total spent voice credits root.
84
86
  signal input newSpentVoiceCreditSubtotalSalt;
85
87
 
@@ -88,21 +90,21 @@ template TallyVotes(
88
90
  computedSbCommitment === sbCommitment;
89
91
 
90
92
  // Validates that the index is within the valid range of sign-ups.
91
- var numSignUpsValid = LessEqThan(50)([index, numSignUps]);
92
- numSignUpsValid === 1;
93
+ var totalSignupsValid = LessEqThan(50)([index, totalSignups]);
94
+ totalSignupsValid === 1;
93
95
 
94
96
  // Hashes each ballot for subroot generation, and checks the existence of the leaf in the Merkle tree.
95
97
  var computedBallotHashers[batchSize];
96
98
 
97
99
  for (var i = 0; i < batchSize; i++) {
98
- computedBallotHashers[i] = PoseidonHasher(2)([ballots[i][BALLOT_NONCE_IDX], ballots[i][BALLOT_VO_ROOT_IDX]]);
100
+ computedBallotHashers[i] = PoseidonHasher(2)([ballots[i][BALLOT_NONCE_INDEX], ballots[i][BALLOT_VOTE_OPTION_ROOT_INDEX]]);
99
101
  }
100
102
 
101
103
  var computedBallotSubroot = CheckRoot(intStateTreeDepth)(computedBallotHashers);
102
- var computedBallotPathIndices[k] = MerkleGeneratePathIndices(k)(index / batchSize);
104
+ var computedBallotPathIndices[STATE_INT_TREE_DEPTH_DIFFERENCE] = MerklePathIndicesGenerator(STATE_INT_TREE_DEPTH_DIFFERENCE)(index / batchSize);
103
105
 
104
106
  // Verifies each ballot's existence within the ballot tree.
105
- LeafExists(k)(
107
+ LeafExists(STATE_INT_TREE_DEPTH_DIFFERENCE)(
106
108
  computedBallotSubroot,
107
109
  ballotPathElements,
108
110
  computedBallotPathIndices,
@@ -113,7 +115,7 @@ template TallyVotes(
113
115
  var computedVoteTree[batchSize];
114
116
  for (var i = 0; i < batchSize; i++) {
115
117
  computedVoteTree[i] = QuinCheckRoot(voteOptionTreeDepth)(votes[i]);
116
- computedVoteTree[i] === ballots[i][BALLOT_VO_ROOT_IDX];
118
+ computedVoteTree[i] === ballots[i][BALLOT_VOTE_OPTION_ROOT_INDEX];
117
119
  }
118
120
 
119
121
  // Calculates new results and spent voice credits based on the current and incoming votes.
@@ -121,8 +123,8 @@ template TallyVotes(
121
123
  var computedIsZero = IsZero()(computedIsFirstBatch);
122
124
 
123
125
  // Tally the new results.
124
- var computedCalculateTotalResult[numVoteOptions];
125
- for (var i = 0; i < numVoteOptions; i++) {
126
+ var computedCalculateTotalResult[totalVoteOptions];
127
+ for (var i = 0; i < totalVoteOptions; i++) {
126
128
  var numsRC[batchSize + 1];
127
129
  numsRC[batchSize] = currentResults[i] * computedIsZero;
128
130
  for (var j = 0; j < batchSize; j++) {
@@ -133,27 +135,27 @@ template TallyVotes(
133
135
  }
134
136
 
135
137
  // Tally the new spent voice credit total.
136
- var numsSVC[batchSize * numVoteOptions + 1];
137
- numsSVC[batchSize * numVoteOptions] = currentSpentVoiceCreditSubtotal * computedIsZero;
138
+ var numsSVC[batchSize * totalVoteOptions + 1];
139
+ numsSVC[batchSize * totalVoteOptions] = currentSpentVoiceCreditSubtotal * computedIsZero;
138
140
  for (var i = 0; i < batchSize; i++) {
139
- for (var j = 0; j < numVoteOptions; j++) {
140
- numsSVC[i * numVoteOptions + j] = votes[i][j] * votes[i][j];
141
+ for (var j = 0; j < totalVoteOptions; j++) {
142
+ numsSVC[i * totalVoteOptions + j] = votes[i][j] * votes[i][j];
141
143
  }
142
144
  }
143
145
 
144
- var computedNewSpentVoiceCreditSubtotal = CalculateTotal(batchSize * numVoteOptions + 1)(numsSVC);
146
+ var computedNewSpentVoiceCreditSubtotal = CalculateTotal(batchSize * totalVoteOptions + 1)(numsSVC);
145
147
 
146
148
  // Tally the spent voice credits per vote option.
147
- var computedNewPerVOSpentVoiceCredits[numVoteOptions];
149
+ var computedNewPerVOSpentVoiceCredits[totalVoteOptions];
148
150
 
149
- for (var i = 0; i < numVoteOptions; i++) {
150
- var computedNumsSVC[batchSize + 1];
151
- computedNumsSVC[batchSize] = currentPerVOSpentVoiceCredits[i] * computedIsZero;
151
+ for (var i = 0; i < totalVoteOptions; i++) {
152
+ var computedTotalVoiceCreditSpent[batchSize + 1];
153
+ computedTotalVoiceCreditSpent[batchSize] = currentPerVoteOptionSpentVoiceCredits[i] * computedIsZero;
152
154
  for (var j = 0; j < batchSize; j++) {
153
- computedNumsSVC[j] = votes[j][i] * votes[j][i];
155
+ computedTotalVoiceCreditSpent[j] = votes[j][i] * votes[j][i];
154
156
  }
155
157
 
156
- computedNewPerVOSpentVoiceCredits[i] = CalculateTotal(batchSize + 1)(computedNumsSVC);
158
+ computedNewPerVOSpentVoiceCredits[i] = CalculateTotal(batchSize + 1)(computedTotalVoiceCreditSpent);
157
159
  }
158
160
 
159
161
  // Verifies the updated results and spent credits, ensuring consistency and correctness of tally updates.
@@ -169,10 +171,10 @@ template TallyVotes(
169
171
  currentSpentVoiceCreditSubtotalSalt,
170
172
  computedNewSpentVoiceCreditSubtotal,
171
173
  newSpentVoiceCreditSubtotalSalt,
172
- currentPerVOSpentVoiceCredits,
173
- currentPerVOSpentVoiceCreditsRootSalt,
174
+ currentPerVoteOptionSpentVoiceCredits,
175
+ currentPerVoteOptionSpentVoiceCreditsRootSalt,
174
176
  computedNewPerVOSpentVoiceCredits,
175
- newPerVOSpentVoiceCreditsRootSalt
177
+ newPerVoteOptionSpentVoiceCreditsRootSalt
176
178
  );
177
179
  }
178
180
 
@@ -185,7 +187,7 @@ template ResultCommitmentVerifier(voteOptionTreeDepth) {
185
187
  // Number of children per node in the tree, defining the tree's branching factor.
186
188
  var TREE_ARITY = 5;
187
189
  // Number of voting options available, determined by the depth of the vote option tree.
188
- var numVoteOptions = TREE_ARITY ** voteOptionTreeDepth;
190
+ var totalVoteOptions = TREE_ARITY ** voteOptionTreeDepth;
189
191
 
190
192
  // Equal to 1 if this is the first batch, otherwise 0.
191
193
  signal input isFirstBatch;
@@ -195,12 +197,12 @@ template ResultCommitmentVerifier(voteOptionTreeDepth) {
195
197
  signal input newTallyCommitment;
196
198
 
197
199
  // Current results for each vote option.
198
- signal input currentResults[numVoteOptions];
200
+ signal input currentResults[totalVoteOptions];
199
201
  // Salt for the root of the current results.
200
202
  signal input currentResultsRootSalt;
201
203
 
202
204
  // New results for each vote option.
203
- signal input newResults[numVoteOptions];
205
+ signal input newResults[totalVoteOptions];
204
206
  // Salt for the root of the new results.
205
207
  signal input newResultsRootSalt;
206
208
 
@@ -215,14 +217,14 @@ template ResultCommitmentVerifier(voteOptionTreeDepth) {
215
217
  signal input newSpentVoiceCreditSubtotalSalt;
216
218
 
217
219
  // Spent voice credits per vote option.
218
- signal input currentPerVOSpentVoiceCredits[numVoteOptions];
220
+ signal input currentPerVoteOptionSpentVoiceCredits[totalVoteOptions];
219
221
  // Salt for the root of spent credits per option.
220
- signal input currentPerVOSpentVoiceCreditsRootSalt;
222
+ signal input currentPerVoteOptionSpentVoiceCreditsRootSalt;
221
223
 
222
224
  // New spent voice credits per vote option.
223
- signal input newPerVOSpentVoiceCredits[numVoteOptions];
225
+ signal input newPerVoteOptionSpentVoiceCredits[totalVoteOptions];
224
226
  // Salt for the root of new spent credits per option.
225
- signal input newPerVOSpentVoiceCreditsRootSalt;
227
+ signal input newPerVoteOptionSpentVoiceCreditsRootSalt;
226
228
 
227
229
  // Compute the commitment to the current results.
228
230
  var computedCurrentResultsRoot = QuinCheckRoot(voteOptionTreeDepth)(currentResults);
@@ -234,14 +236,14 @@ template ResultCommitmentVerifier(voteOptionTreeDepth) {
234
236
  var computedCurrentSpentVoiceCreditsCommitment = PoseidonHasher(2)([currentSpentVoiceCreditSubtotal, currentSpentVoiceCreditSubtotalSalt]);
235
237
 
236
238
  // Compute the root of the spent voice credits per vote option.
237
- var computedCurrentPerVOSpentVoiceCreditsRoot = QuinCheckRoot(voteOptionTreeDepth)(currentPerVOSpentVoiceCredits);
238
- var computedCurrentPerVOSpentVoiceCreditsCommitment = PoseidonHasher(2)([computedCurrentPerVOSpentVoiceCreditsRoot, currentPerVOSpentVoiceCreditsRootSalt]);
239
+ var computedCurrentPerVoteOptionSpentVoiceCreditsRoot = QuinCheckRoot(voteOptionTreeDepth)(currentPerVoteOptionSpentVoiceCredits);
240
+ var computedCurrentPerVoteOptionSpentVoiceCreditsCommitment = PoseidonHasher(2)([computedCurrentPerVoteOptionSpentVoiceCreditsRoot, currentPerVoteOptionSpentVoiceCreditsRootSalt]);
239
241
 
240
242
  // Commit to the current tally.
241
243
  var computedCurrentTallyCommitment = PoseidonHasher(3)([
242
244
  computedCurrentResultsCommitment,
243
245
  computedCurrentSpentVoiceCreditsCommitment,
244
- computedCurrentPerVOSpentVoiceCreditsCommitment
246
+ computedCurrentPerVoteOptionSpentVoiceCreditsCommitment
245
247
  ]);
246
248
 
247
249
  // Check if the current tally commitment is correct only if this is not the first batch.
@@ -249,11 +251,11 @@ template ResultCommitmentVerifier(voteOptionTreeDepth) {
249
251
  // computedIsZero.out is 0 if this is the first batch.
250
252
  var computedIsZero = IsZero()(isFirstBatch);
251
253
 
252
- // hz is 0 if this is the first batch, currentTallyCommitment should be 0 if this is the first batch.
253
- // hz is 1 if this is not the first batch, currentTallyCommitment should not be 0 if this is the first batch.
254
- signal hz;
255
- hz <== computedIsZero * computedCurrentTallyCommitment;
256
- hz === currentTallyCommitment;
254
+ // isFirstCommitment is 0 if this is the first batch, currentTallyCommitment should be 0 if this is the first batch.
255
+ // isFirstCommitment is 1 if this is not the first batch, currentTallyCommitment should not be 0 if this is the first batch.
256
+ signal isFirstCommitment;
257
+ isFirstCommitment <== computedIsZero * computedCurrentTallyCommitment;
258
+ isFirstCommitment === currentTallyCommitment;
257
259
 
258
260
  // Compute the root of the new results.
259
261
  var computedNewResultsRoot = QuinCheckRoot(voteOptionTreeDepth)(newResults);
@@ -263,14 +265,14 @@ template ResultCommitmentVerifier(voteOptionTreeDepth) {
263
265
  var computedNewSpentVoiceCreditsCommitment = PoseidonHasher(2)([newSpentVoiceCreditSubtotal, newSpentVoiceCreditSubtotalSalt]);
264
266
 
265
267
  // Compute the root of the spent voice credits per vote option.
266
- var computedNewPerVOSpentVoiceCreditsRoot = QuinCheckRoot(voteOptionTreeDepth)(newPerVOSpentVoiceCredits);
267
- var computedNewPerVOSpentVoiceCreditsCommitment = PoseidonHasher(2)([computedNewPerVOSpentVoiceCreditsRoot, newPerVOSpentVoiceCreditsRootSalt]);
268
+ var computedNewPerVoteOptionSpentVoiceCreditsRoot = QuinCheckRoot(voteOptionTreeDepth)(newPerVoteOptionSpentVoiceCredits);
269
+ var computedNewPerVoteOptionSpentVoiceCreditsCommitment = PoseidonHasher(2)([computedNewPerVoteOptionSpentVoiceCreditsRoot, newPerVoteOptionSpentVoiceCreditsRootSalt]);
268
270
 
269
271
  // Commit to the new tally.
270
272
  var computedNewTallyCommitment = PoseidonHasher(3)([
271
273
  computedNewResultsCommitment,
272
274
  computedNewSpentVoiceCreditsCommitment,
273
- computedNewPerVOSpentVoiceCreditsCommitment
275
+ computedNewPerVoteOptionSpentVoiceCreditsCommitment
274
276
  ]);
275
277
 
276
278
  computedNewTallyCommitment === newTallyCommitment;