@maci-protocol/circuits 0.0.0-ci.38c76f2 → 0.0.0-ci.3a64a23

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.
@@ -33,14 +33,6 @@ include "./SingleMessageProcessor.circom";
33
33
  var PACKED_COMMAND_LENGTH = 4;
34
34
  var STATE_LEAF_LENGTH = 3;
35
35
  var BALLOT_LENGTH = 2;
36
- var BALLOT_NONCE_INDEX = 0;
37
- var BALLOT_VOTE_OPTION_ROOT_INDEX = 1;
38
- var STATE_LEAF_PUBLIC_X_INDEX = 0;
39
- var STATE_LEAF_PUBLIC_Y_INDEX = 1;
40
- var STATE_LEAF_VOICE_CREDIT_BALANCE_INDEX = 2;
41
- var MESSAGE_TREE_ZERO_VALUE = 8370432830353022751713833565135785980866757267633941821328460903436894336785;
42
- // Number of options for this poll.
43
- var maxVoteOptions = VOTE_OPTION_TREE_ARITY ** voteOptionTreeDepth;
44
36
 
45
37
  // Number of users that have completed the sign up.
46
38
  signal input totalSignups;
@@ -57,7 +49,7 @@ include "./SingleMessageProcessor.circom";
57
49
  // The current state root (before the processing).
58
50
  signal input currentStateRoot;
59
51
  // The actual tree depth (might be <= stateTreeDepth).
60
- // @note it is a public input to ensure fair processing from
52
+ // @note it is a public input to ensure fair processing from
61
53
  // the coordinator (no censoring)
62
54
  signal input actualStateTreeDepth;
63
55
  // The coordinator public key hash
@@ -97,7 +89,7 @@ include "./SingleMessageProcessor.circom";
97
89
 
98
90
  // The index of the first message in the batch, inclusive.
99
91
  signal input index;
100
-
92
+
101
93
  // The index of the last message in the batch to process, exclusive.
102
94
  // This value may be less than index + batchSize if this batch is
103
95
  // the last batch and the total number of messages is not a multiple of the batch size.
@@ -112,7 +104,7 @@ include "./SingleMessageProcessor.circom";
112
104
  var computedCurrentSbCommitment = PoseidonHasher(3)([currentStateRoot, currentBallotRoot, currentSbSalt]);
113
105
  computedCurrentSbCommitment === currentSbCommitment;
114
106
 
115
- // -----------------------------------------------------------------------
107
+ // -----------------------------------------------------------------------
116
108
  // 0. Ensure that the maximum vote options signal is valid and if
117
109
  // the maximum users signal is valid
118
110
  var voteOptionsValid = LessEqThan(32)([voteOptions, VOTE_OPTION_TREE_ARITY ** voteOptionTreeDepth]);
@@ -162,7 +154,7 @@ include "./SingleMessageProcessor.circom";
162
154
 
163
155
  // Decrypt each Message into a Command.
164
156
  // The command i-th is composed by the following fields.
165
- // e.g., command 0 is made of commandsStateIndex[0],
157
+ // e.g., command 0 is made of commandsStateIndex[0],
166
158
  // commandsNewPublicKey[0], ..., commandsPackedCommandOut[0]
167
159
  var computedCommandsStateIndex[batchSize];
168
160
  var computedCommandsNewPublicKey[batchSize][2];
@@ -205,7 +197,7 @@ include "./SingleMessageProcessor.circom";
205
197
  var computedCurrentStateLeavesPathElements[stateTreeDepth][STATE_TREE_ARITY - 1];
206
198
  var computedCurrentBallotPathElements[stateTreeDepth][STATE_TREE_ARITY - 1];
207
199
  var computedCurrentVoteWeightsPathElements[voteOptionTreeDepth][VOTE_OPTION_TREE_ARITY - 1];
208
-
200
+
209
201
  for (var j = 0; j < stateTreeDepth; j++) {
210
202
  for (var k = 0; k < STATE_TREE_ARITY - 1; k++) {
211
203
  computedCurrentStateLeavesPathElements[j][k] = currentStateLeavesPathElements[i][j][k];
@@ -5,7 +5,6 @@ include "./mux1.circom";
5
5
  // local imports
6
6
  include "../../utils/PoseidonHasher.circom";
7
7
  include "../../utils/trees/MerkleTreeInclusionProof.circom";
8
- include "../../utils/trees/MerklePathIndicesGenerator.circom";
9
8
  include "../../utils/trees/BinaryMerkleRoot.circom";
10
9
  include "../../utils/trees/QuinaryTreeInclusionProof.circom";
11
10
  include "../../utils/trees/QuinaryGeneratePathIndices.circom";
@@ -112,14 +111,13 @@ template SingleMessageProcessorFull(stateTreeDepth, voteOptionTreeDepth) {
112
111
  // 2. If computedIsStateLeafIndexValid is equal to zero, generate indices for leaf zero.
113
112
  // Otherwise, generate indices for command.stateIndex.
114
113
  var stateIndexMux = Mux1()([0, commandStateIndex], computedIsStateLeafIndexValid);
115
- var computedStateLeafPathIndices[stateTreeDepth] = MerklePathIndicesGenerator(stateTreeDepth)(stateIndexMux);
116
114
 
117
115
  // 3. Verify that the original state leaf exists in the given state root.
118
116
  var stateLeafHash = PoseidonHasher(3)(stateLeaf);
119
117
  var computedStateRoot = BinaryMerkleRoot(stateTreeDepth)(
120
118
  stateLeafHash,
121
119
  actualStateTreeDepth,
122
- computedStateLeafPathIndices,
120
+ stateIndexMux,
123
121
  stateLeafPathElements
124
122
  );
125
123
 
@@ -130,6 +128,7 @@ template SingleMessageProcessorFull(stateTreeDepth, voteOptionTreeDepth) {
130
128
  ballot[BALLOT_NONCE_INDEX],
131
129
  ballot[BALLOT_VOTE_OPTION_ROOT_INDEX]
132
130
  ]);
131
+ var computedStateLeafPathIndices[stateTreeDepth] = Num2Bits(stateTreeDepth)(stateIndexMux);
133
132
 
134
133
  var computedBallotRoot = MerkleTreeInclusionProof(stateTreeDepth)(
135
134
  computedBallot,
@@ -186,7 +185,7 @@ template SingleMessageProcessorFull(stateTreeDepth, voteOptionTreeDepth) {
186
185
  var computedNewStateRoot = BinaryMerkleRoot(stateTreeDepth)(
187
186
  computedNewStateLeafhash,
188
187
  actualStateTreeDepth,
189
- computedStateLeafPathIndices,
188
+ stateIndexMux,
190
189
  stateLeafPathElements
191
190
  );
192
191
 
@@ -33,14 +33,6 @@ include "./SingleMessageProcessor.circom";
33
33
  var PACKED_COMMAND_LENGTH = 4;
34
34
  var STATE_LEAF_LENGTH = 3;
35
35
  var BALLOT_LENGTH = 2;
36
- var BALLOT_NONCE_INDEX = 0;
37
- var BALLOT_VOTE_OPTION_ROOT_INDEX = 1;
38
- var STATE_LEAF_PUBLIC_X_INDEX = 0;
39
- var STATE_LEAF_PUBLIC_Y_INDEX = 1;
40
- var STATE_LEAF_VOICE_CREDIT_BALANCE_INDEX = 2;
41
- var MESSAGE_TREE_ZERO_VALUE = 8370432830353022751713833565135785980866757267633941821328460903436894336785;
42
- // Number of options for this poll.
43
- var maxVoteOptions = VOTE_OPTION_TREE_ARITY ** voteOptionTreeDepth;
44
36
 
45
37
  // Number of users that have completed the sign up.
46
38
  signal input totalSignups;
@@ -57,7 +49,7 @@ include "./SingleMessageProcessor.circom";
57
49
  // The current state root (before the processing).
58
50
  signal input currentStateRoot;
59
51
  // The actual tree depth (might be <= stateTreeDepth).
60
- // @note it is a public input to ensure fair processing from
52
+ // @note it is a public input to ensure fair processing from
61
53
  // the coordinator (no censoring)
62
54
  signal input actualStateTreeDepth;
63
55
  // The coordinator public key hash
@@ -97,7 +89,7 @@ include "./SingleMessageProcessor.circom";
97
89
 
98
90
  // The index of the first message in the batch, inclusive.
99
91
  signal input index;
100
-
92
+
101
93
  // The index of the last message in the batch to process, exclusive.
102
94
  // This value may be less than index + batchSize if this batch is
103
95
  // the last batch and the total number of messages is not a multiple of the batch size.
@@ -112,7 +104,7 @@ include "./SingleMessageProcessor.circom";
112
104
  var computedCurrentSbCommitment = PoseidonHasher(3)([currentStateRoot, currentBallotRoot, currentSbSalt]);
113
105
  computedCurrentSbCommitment === currentSbCommitment;
114
106
 
115
- // -----------------------------------------------------------------------
107
+ // -----------------------------------------------------------------------
116
108
  // 0. Ensure that the maximum vote options signal is valid and if
117
109
  // the maximum users signal is valid
118
110
  var voteOptionsValid = LessEqThan(32)([voteOptions, VOTE_OPTION_TREE_ARITY ** voteOptionTreeDepth]);
@@ -162,7 +154,7 @@ include "./SingleMessageProcessor.circom";
162
154
 
163
155
  // Decrypt each Message into a Command.
164
156
  // The command i-th is composed by the following fields.
165
- // e.g., command 0 is made of commandsStateIndex[0],
157
+ // e.g., command 0 is made of commandsStateIndex[0],
166
158
  // commandsNewPublicKey[0], ..., commandsPackedCommandOut[0]
167
159
  var computedCommandsStateIndex[batchSize];
168
160
  var computedCommandsNewPublicKey[batchSize][2];
@@ -205,7 +197,7 @@ include "./SingleMessageProcessor.circom";
205
197
  var computedCurrentStateLeavesPathElements[stateTreeDepth][STATE_TREE_ARITY - 1];
206
198
  var computedCurrentBallotPathElements[stateTreeDepth][STATE_TREE_ARITY - 1];
207
199
  var computedCurrentVoteWeightsPathElements[voteOptionTreeDepth][VOTE_OPTION_TREE_ARITY - 1];
208
-
200
+
209
201
  for (var j = 0; j < stateTreeDepth; j++) {
210
202
  for (var k = 0; k < STATE_TREE_ARITY - 1; k++) {
211
203
  computedCurrentStateLeavesPathElements[j][k] = currentStateLeavesPathElements[i][j][k];
@@ -5,7 +5,6 @@ include "./mux1.circom";
5
5
  // local imports
6
6
  include "../../utils/PoseidonHasher.circom";
7
7
  include "../../utils/trees/MerkleTreeInclusionProof.circom";
8
- include "../../utils/trees/MerklePathIndicesGenerator.circom";
9
8
  include "../../utils/trees/BinaryMerkleRoot.circom";
10
9
  include "../../utils/trees/QuinaryTreeInclusionProof.circom";
11
10
  include "../../utils/trees/QuinaryGeneratePathIndices.circom";
@@ -13,10 +12,10 @@ include "../../utils/non-qv/StateLeafAndBallotTransformer.circom";
13
12
 
14
13
 
15
14
  /**
16
- * Processes one message and updates the state accordingly.
17
- * This template involves complex interactions, including transformations based on message type,
18
- * validations against current states like voice credit balances or vote weights,
19
- * and updates to Merkle trees representing state and ballot information.
15
+ * Processes one message and updates the state accordingly.
16
+ * This template involves complex interactions, including transformations based on message type,
17
+ * validations against current states like voice credit balances or vote weights,
18
+ * and updates to Merkle trees representing state and ballot information.
20
19
  * This is a critical building block for ensuring the integrity and correctness of MACI state.
21
20
  * This template does not support Quadratic Voting (QV).
22
21
  */
@@ -24,7 +23,6 @@ template SingleMessageProcessorNonQv(stateTreeDepth, voteOptionTreeDepth) {
24
23
  // Constants defining the structure and size of state and ballots.
25
24
  var STATE_LEAF_LENGTH = 3;
26
25
  var BALLOT_LENGTH = 2;
27
- var MESSAGE_LENGTH = 10;
28
26
  var PACKED_COMMAND_LENGTH = 4;
29
27
  var VOTE_OPTION_TREE_ARITY = 5;
30
28
  var STATE_TREE_ARITY = 2;
@@ -38,7 +36,6 @@ template SingleMessageProcessorNonQv(stateTreeDepth, voteOptionTreeDepth) {
38
36
  var STATE_LEAF_PUBLIC_Y_INDEX = 1;
39
37
  // Voice Credit balance.
40
38
  var STATE_LEAF_VOICE_CREDIT_BALANCE_INDEX = 2;
41
- var NUMBER_BITS = 252;
42
39
 
43
40
  // Number of users that have completed the sign up.
44
41
  signal input totalSignups;
@@ -108,14 +105,13 @@ template SingleMessageProcessorNonQv(stateTreeDepth, voteOptionTreeDepth) {
108
105
  // 2. If computedIsStateLeafIndexValid is equal to zero, generate indices for leaf zero.
109
106
  // Otherwise, generate indices for command.stateIndex.
110
107
  var stateIndexMux = Mux1()([0, commandStateIndex], computedIsStateLeafIndexValid);
111
- var computedStateLeafPathIndices[stateTreeDepth] = MerklePathIndicesGenerator(stateTreeDepth)(stateIndexMux);
112
108
 
113
109
  // 3. Verify that the original state leaf exists in the given state root.
114
110
  var stateLeafHash = PoseidonHasher(3)(stateLeaf);
115
111
  var stateLeafQip = BinaryMerkleRoot(stateTreeDepth)(
116
112
  stateLeafHash,
117
113
  actualStateTreeDepth,
118
- computedStateLeafPathIndices,
114
+ stateIndexMux,
119
115
  stateLeafPathElements
120
116
  );
121
117
 
@@ -123,9 +119,10 @@ template SingleMessageProcessorNonQv(stateTreeDepth, voteOptionTreeDepth) {
123
119
 
124
120
  // 4. Verify that the original ballot exists in the given ballot root.
125
121
  var computedBallot = PoseidonHasher(2)([
126
- ballot[BALLOT_NONCE_INDEX],
122
+ ballot[BALLOT_NONCE_INDEX],
127
123
  ballot[BALLOT_VOTE_OPTION_ROOT_INDEX]
128
124
  ]);
125
+ var computedStateLeafPathIndices[stateTreeDepth] = Num2Bits(stateTreeDepth)(stateIndexMux);
129
126
 
130
127
  var computedBallotQip = MerkleTreeInclusionProof(stateTreeDepth)(
131
128
  computedBallot,
@@ -182,13 +179,13 @@ template SingleMessageProcessorNonQv(stateTreeDepth, voteOptionTreeDepth) {
182
179
  var computedNewStateLeafQip = BinaryMerkleRoot(stateTreeDepth)(
183
180
  computedNewStateLeafHash,
184
181
  actualStateTreeDepth,
185
- computedStateLeafPathIndices,
182
+ stateIndexMux,
186
183
  stateLeafPathElements
187
184
  );
188
185
 
189
186
  newStateRoot <== computedNewStateLeafQip;
190
-
191
- // 7. Generate a new ballot root.
187
+
188
+ // 7. Generate a new ballot root.
192
189
  var computedNewBallot = PoseidonHasher(2)([computedNewBallotNonce, newBallotVoteOptionRoot]);
193
190
  var computedNewBallotQip = MerkleTreeInclusionProof(stateTreeDepth)(
194
191
  computedNewBallot,
@@ -7,7 +7,6 @@ include "./unpack-element.circom";
7
7
  // local imports
8
8
  include "../../utils/non-qv/ResultCommitmentVerifier.circom";
9
9
  include "../../utils/trees/CheckRoot.circom";
10
- include "../../utils/trees/MerklePathIndicesGenerator.circom";
11
10
  include "../../utils/trees/LeafExists.circom";
12
11
  include "../../utils/trees/QuinaryCheckRoot.circom";
13
12
  include "../../utils/CalculateTotal.circom";
@@ -97,7 +96,7 @@ template VoteTallyNonQv(
97
96
  }
98
97
 
99
98
  var computedBallotSubroot = CheckRoot(tallyProcessingStateTreeDepth)(computedBallotHashers);
100
- var computedBallotPathIndices[STATE_TREE_DEPTH_DIFFERENCE] = MerklePathIndicesGenerator(STATE_TREE_DEPTH_DIFFERENCE)(index / batchSize);
99
+ var computedBallotPathIndices[STATE_TREE_DEPTH_DIFFERENCE] = Num2Bits(STATE_TREE_DEPTH_DIFFERENCE)(index / batchSize);
101
100
 
102
101
  // Verifies each ballot's existence within the ballot tree.
103
102
  LeafExists(STATE_TREE_DEPTH_DIFFERENCE)(
@@ -34,14 +34,6 @@ template MessageProcessorQv(
34
34
  var PACKED_COMMAND_LENGTH = 4;
35
35
  var STATE_LEAF_LENGTH = 3;
36
36
  var BALLOT_LENGTH = 2;
37
- var BALLOT_NONCE_INDEX = 0;
38
- var BALLOT_VOTE_OPTION_ROOT_INDEX = 1;
39
- var STATE_LEAF_PUBLIC_X_INDEX = 0;
40
- var STATE_LEAF_PUBLIC_Y_INDEX = 1;
41
- var STATE_LEAF_VOICE_CREDIT_BALANCE_INDEX = 2;
42
- var MESSAGE_TREE_ZERO_VALUE = 8370432830353022751713833565135785980866757267633941821328460903436894336785;
43
- // Number of options for this poll.
44
- var maxVoteOptions = VOTE_OPTION_TREE_ARITY ** voteOptionTreeDepth;
45
37
 
46
38
  // Number of users that have completed the sign up.
47
39
  signal input totalSignups;
@@ -58,7 +50,7 @@ template MessageProcessorQv(
58
50
  // The current state root (before the processing).
59
51
  signal input currentStateRoot;
60
52
  // The actual tree depth (might be <= stateTreeDepth).
61
- // @note it is a public input to ensure fair processing from
53
+ // @note it is a public input to ensure fair processing from
62
54
  // the coordinator (no censoring)
63
55
  signal input actualStateTreeDepth;
64
56
  // The coordinator public key hash
@@ -98,7 +90,7 @@ template MessageProcessorQv(
98
90
 
99
91
  // The index of the first message in the batch, inclusive.
100
92
  signal input index;
101
-
93
+
102
94
  // The index of the last message in the batch to process, exclusive.
103
95
  // This value may be less than batchSize if this batch is
104
96
  // the last batch and the total number of messages is not a multiple of the batch size.
@@ -160,7 +152,7 @@ template MessageProcessorQv(
160
152
 
161
153
  // Decrypt each Message into a Command.
162
154
  // The command i-th is composed by the following fields.
163
- // e.g., command 0 is made of commandsStateIndex[0],
155
+ // e.g., command 0 is made of commandsStateIndex[0],
164
156
  // commandsNewPublicKey[0], ..., commandsPackedCommandOut[0]
165
157
  var computedCommandsStateIndex[batchSize];
166
158
  var computedCommandsNewPublicKey[batchSize][2];
@@ -203,7 +195,7 @@ template MessageProcessorQv(
203
195
  var computedCurrentStateLeavesPathElements[stateTreeDepth][STATE_TREE_ARITY - 1];
204
196
  var computedCurrentBallotPathElements[stateTreeDepth][STATE_TREE_ARITY - 1];
205
197
  var computedCurrentVoteWeightsPathElements[voteOptionTreeDepth][VOTE_OPTION_TREE_ARITY - 1];
206
-
198
+
207
199
  for (var j = 0; j < stateTreeDepth; j++) {
208
200
  for (var k = 0; k < STATE_TREE_ARITY - 1; k++) {
209
201
  computedCurrentStateLeavesPathElements[j][k] = currentStateLeavesPathElements[i][j][k];
@@ -216,7 +208,7 @@ template MessageProcessorQv(
216
208
  computedCurrentVoteWeightsPathElements[j][k] = currentVoteWeightsPathElements[i][j][k];
217
209
  }
218
210
  }
219
-
211
+
220
212
  (computedNewVoteStateRoot[i], computedNewVoteBallotRoot[i]) = SingleMessageProcessorQv(stateTreeDepth, voteOptionTreeDepth)(
221
213
  totalSignups,
222
214
  stateRoots[i + 1],
@@ -5,17 +5,16 @@ include "./mux1.circom";
5
5
  // local imports
6
6
  include "../../utils/PoseidonHasher.circom";
7
7
  include "../../utils/trees/MerkleTreeInclusionProof.circom";
8
- include "../../utils/trees/MerklePathIndicesGenerator.circom";
9
8
  include "../../utils/trees/BinaryMerkleRoot.circom";
10
9
  include "../../utils/trees/QuinaryTreeInclusionProof.circom";
11
10
  include "../../utils/trees/QuinaryGeneratePathIndices.circom";
12
11
  include "../../utils/qv/StateLeafAndBallotTransformer.circom";
13
12
 
14
13
  /**
15
- * Processes one message and updates the state accordingly.
16
- * This template involves complex interactions, including transformations based on message type,
17
- * validations against current states like voice credit balances or vote weights,
18
- * and updates to Merkle trees representing state and ballot information.
14
+ * Processes one message and updates the state accordingly.
15
+ * This template involves complex interactions, including transformations based on message type,
16
+ * validations against current states like voice credit balances or vote weights,
17
+ * and updates to Merkle trees representing state and ballot information.
19
18
  * This is a critical building block for ensuring the integrity and correctness of MACI state.
20
19
  * This template supports the Quadratic Voting (QV).
21
20
  */
@@ -23,7 +22,6 @@ template SingleMessageProcessorQv(stateTreeDepth, voteOptionTreeDepth) {
23
22
  // Constants defining the structure and size of state and ballots.
24
23
  var STATE_LEAF_LENGTH = 3;
25
24
  var BALLOT_LENGTH = 2;
26
- var MESSAGE_LENGTH = 10;
27
25
  var PACKED_COMMAND_LENGTH = 4;
28
26
  var VOTE_OPTION_TREE_ARITY = 5;
29
27
  var STATE_TREE_ARITY = 2;
@@ -37,7 +35,6 @@ template SingleMessageProcessorQv(stateTreeDepth, voteOptionTreeDepth) {
37
35
  var STATE_LEAF_PUBLIC_Y_INDEX = 1;
38
36
  // Voice Credit balance.
39
37
  var STATE_LEAF_VOICE_CREDIT_BALANCE_INDEX = 2;
40
- var NUMBER_BITS = 252;
41
38
 
42
39
  // Number of users that have completed the sign up.
43
40
  signal input totalSignups;
@@ -112,14 +109,13 @@ template SingleMessageProcessorQv(stateTreeDepth, voteOptionTreeDepth) {
112
109
  // 2. If computedIsStateLeafIndexValid is equal to zero, generate indices for leaf zero.
113
110
  // Otherwise, generate indices for command.stateIndex.
114
111
  var stateIndexMux = Mux1()([0, commandStateIndex], computedIsStateLeafIndexValid);
115
- var computedStateLeafPathIndices[stateTreeDepth] = MerklePathIndicesGenerator(stateTreeDepth)(stateIndexMux);
116
112
 
117
113
  // 3. Verify that the original state leaf exists in the given state root.
118
114
  var stateLeafHash = PoseidonHasher(3)(stateLeaf);
119
115
  var stateLeafQip = BinaryMerkleRoot(stateTreeDepth)(
120
116
  stateLeafHash,
121
117
  actualStateTreeDepth,
122
- computedStateLeafPathIndices,
118
+ stateIndexMux,
123
119
  stateLeafPathElements
124
120
  );
125
121
 
@@ -127,9 +123,10 @@ template SingleMessageProcessorQv(stateTreeDepth, voteOptionTreeDepth) {
127
123
 
128
124
  // 4. Verify that the original ballot exists in the given ballot root.
129
125
  var computedBallot = PoseidonHasher(2)([
130
- ballot[BALLOT_NONCE_INDEX],
126
+ ballot[BALLOT_NONCE_INDEX],
131
127
  ballot[BALLOT_VOTE_OPTION_ROOT_INDEX]
132
128
  ]);
129
+ var computedStateLeafPathIndices[stateTreeDepth] = Num2Bits(stateTreeDepth)(stateIndexMux);
133
130
 
134
131
  var computedBallotQip = MerkleTreeInclusionProof(stateTreeDepth)(
135
132
  computedBallot,
@@ -189,13 +186,13 @@ template SingleMessageProcessorQv(stateTreeDepth, voteOptionTreeDepth) {
189
186
  var computedNewStateLeafQip = BinaryMerkleRoot(stateTreeDepth)(
190
187
  computedNewStateLeafHash,
191
188
  actualStateTreeDepth,
192
- computedStateLeafPathIndices,
189
+ stateIndexMux,
193
190
  stateLeafPathElements
194
191
  );
195
192
 
196
193
  newStateRoot <== computedNewStateLeafQip;
197
-
198
- // 7. Generate a new ballot root.
194
+
195
+ // 7. Generate a new ballot root.
199
196
  var computedNewBallot = PoseidonHasher(2)([computedNewBallotNonce, newBallotVoteOptionRoot]);
200
197
  var computedNewBallotQip = MerkleTreeInclusionProof(stateTreeDepth)(
201
198
  computedNewBallot,
@@ -205,4 +202,3 @@ template SingleMessageProcessorQv(stateTreeDepth, voteOptionTreeDepth) {
205
202
 
206
203
  newBallotRoot <== computedNewBallotQip;
207
204
  }
208
-
@@ -6,7 +6,6 @@ include "./comparators.circom";
6
6
  include "./unpack-element.circom";
7
7
  // local imports
8
8
  include "../../utils/trees/CheckRoot.circom";
9
- include "../../utils/trees/MerklePathIndicesGenerator.circom";
10
9
  include "../../utils/trees/LeafExists.circom";
11
10
  include "../../utils/trees/QuinaryCheckRoot.circom";
12
11
  include "../../utils/qv/ResultCommitmentVerifier.circom";
@@ -102,7 +101,7 @@ template VoteTallyQv(
102
101
  }
103
102
 
104
103
  var computedBallotSubroot = CheckRoot(tallyProcessingStateTreeDepth)(computedBallotHashers);
105
- var computedBallotPathIndices[STATE_TREE_DEPTH_DIFFERENCE] = MerklePathIndicesGenerator(STATE_TREE_DEPTH_DIFFERENCE)(index / batchSize);
104
+ var computedBallotPathIndices[STATE_TREE_DEPTH_DIFFERENCE] = Num2Bits(STATE_TREE_DEPTH_DIFFERENCE)(index / batchSize);
106
105
 
107
106
  // Verifies each ballot's existence within the ballot tree.
108
107
  LeafExists(STATE_TREE_DEPTH_DIFFERENCE)(
@@ -6,7 +6,6 @@ include "./comparators.circom";
6
6
  include "./unpack-element.circom";
7
7
  // local imports
8
8
  include "../../utils/trees/CheckRoot.circom";
9
- include "../../utils/trees/MerklePathIndicesGenerator.circom";
10
9
  include "../../utils/trees/LeafExists.circom";
11
10
  include "../../utils/trees/QuinaryCheckRoot.circom";
12
11
  include "../../utils/qv/ResultCommitmentVerifier.circom";
@@ -129,10 +128,10 @@ template VoteTallyWithIndividualCountsQv(
129
128
  }
130
129
 
131
130
  var computedBallotSubroot = CheckRoot(tallyProcessingStateTreeDepth)(computedBallotHashers);
132
- var computedBallotPathIndices[STATE_TREE_DEPTH_DIFFERENCE] = MerklePathIndicesGenerator(STATE_TREE_DEPTH_DIFFERENCE)(index / ballotBatchSize);
131
+ var computedBallotPathIndices[STATE_TREE_DEPTH_DIFFERENCE] = Num2Bits(STATE_TREE_DEPTH_DIFFERENCE)(index / ballotBatchSize);
133
132
 
134
133
  var computedVoteCountsSubroot = CheckRoot(tallyProcessingStateTreeDepth)(computedVoteCountsHashers);
135
- var computedVoteCountsPathIndices[STATE_TREE_DEPTH_DIFFERENCE] = MerklePathIndicesGenerator(STATE_TREE_DEPTH_DIFFERENCE)(index / voteCountsBatchSize);
134
+ var computedVoteCountsPathIndices[STATE_TREE_DEPTH_DIFFERENCE] = Num2Bits(STATE_TREE_DEPTH_DIFFERENCE)(index / voteCountsBatchSize);
136
135
 
137
136
  // Verifies each ballot's existence within the ballot tree.
138
137
  LeafExists(STATE_TREE_DEPTH_DIFFERENCE)(
@@ -9,6 +9,7 @@ include "./escalarmulany.circom";
9
9
  include "./escalarmulfix.circom";
10
10
  // local imports
11
11
  include "./PoseidonHasher.circom";
12
+ include "./IsOnCurve.circom";
12
13
 
13
14
  /**
14
15
  * Variant of the EdDSAPoseidonVerifier template from circomlib
@@ -37,9 +38,13 @@ template EdDSAPoseidonVerifier() {
37
38
  // Output signal for the validity of the signature.
38
39
  signal output isValid;
39
40
 
41
+ // Verify the public key and signature point are on the BabyJubJub curve.
42
+ var computedIsPkOnCurve = IsOnCurve()(publicKeyX, publicKeyY);
43
+ var computedIsSpOnCurve = IsOnCurve()(signaturePointX, signaturePointY);
44
+
40
45
  // Ensure signatureScalar<Subgroup Order.
41
46
  // convert the signature scalar signatureScalar into its binary representation.
42
- var computedNum2Bits[254] = Num2Bits(254)(signatureScalar);
47
+ var computedNum2Bits[254] = Num2Bits_strict()(signatureScalar);
43
48
 
44
49
  var computedCompConstantIn[254] = computedNum2Bits;
45
50
  computedCompConstantIn[253] = 0;
@@ -82,10 +87,10 @@ template EdDSAPoseidonVerifier() {
82
87
  // Components to handle edge cases and ensure that all conditions
83
88
  // for a valid signature are met, including the
84
89
  // public key not being zero and other integrity checks.
85
- var computedIsAxZero = IsZero()(publicKeyX);
90
+ var computedIsAxZero = IsZero()(computedDouble3XOut);
86
91
  var computedIsAxEqual = IsEqual()([computedIsAxZero, 0]);
87
92
  var computedIsCcZero = IsZero()(computedCompConstant);
88
- var computedIsValid = IsEqual()([computedIsLeftRightValid + computedIsAxEqual + computedIsCcZero, 3]);
93
+ var computedIsValid = IsEqual()([computedIsLeftRightValid + computedIsAxEqual + computedIsCcZero + computedIsPkOnCurve + computedIsSpOnCurve, 5]);
89
94
 
90
95
  isValid <== computedIsValid;
91
96
  }
@@ -0,0 +1,40 @@
1
+ pragma circom 2.0.0;
2
+
3
+ // zk-kit imports
4
+ include "./comparators.circom";
5
+
6
+ /**
7
+ * Returns 0 or 1 depending on if the point is on the BabyJubJub curve or not. The point is on the
8
+ * BabyJubJub curve if the following equation is true: a*x^2 + y^2 == 1 + d*x^2*y^2
9
+ * This template is identical to the BabyCheck template from circomlib, but it returns 0 or 1
10
+ * instead of having a hard constraint.
11
+ * Based on: https://github.com/iden3/circomlib/blob/master/circuits/babyjub.circom
12
+ */
13
+ template IsOnCurve() {
14
+ // x coordinate of the point on the BabyJubJub curve.
15
+ signal input x;
16
+ // y coordinate of the point on the BabyJubJub curve.
17
+ signal input y;
18
+ // True when the point (x, y) satisfies the BabyJubJub curve equation.
19
+ signal output isValid;
20
+
21
+ // x^2 and y^2 intermediate values.
22
+ signal x2;
23
+ signal y2;
24
+ // x^2 * y^2 intermediate value.
25
+ signal x2y2;
26
+
27
+ // BabyJubJub curve parameters.
28
+ var a = 168700;
29
+ var d = 168696;
30
+
31
+ // Compute x^2 and y^2.
32
+ x2 <== x * x;
33
+ y2 <== y * y;
34
+
35
+ // Compute x^2 * y^2.
36
+ x2y2 <== x2 * y2;
37
+
38
+ // Check if a*x^2 + y^2 == 1 + d*x^2*y^2.
39
+ isValid <== IsEqual()([a * x2 + y2, 1 + d * x2y2]);
40
+ }
@@ -119,4 +119,9 @@ template StateLeafAndBallotTransformerFull() {
119
119
  isValid <== computedIsValid;
120
120
  isStateLeafIndexValid <== computedIsStateLeafIndexValid;
121
121
  isVoteOptionIndexValid <== computedIsVoteOptionIndexValid;
122
+
123
+ // Constrain commandPollId and commandSalt using dummy squares.
124
+ // This binds the proof to a specific poll and salt.
125
+ signal commandPollIdSquare <== commandPollId * commandPollId;
126
+ signal commandSaltSquared <== commandSalt * commandSalt;
122
127
  }
@@ -102,4 +102,9 @@ template StateLeafAndBallotTransformerNonQv() {
102
102
  isValid <== computedIsValid;
103
103
  isStateLeafIndexValid <== computedIsStateLeafIndexValid;
104
104
  isVoteOptionIndexValid <== computedIsVoteOptionIndexValid;
105
+
106
+ // Constrain commandPollId and commandSalt using dummy squares.
107
+ // This binds the proof to a specific poll and salt.
108
+ signal commandPollIdSquare <== commandPollId * commandPollId;
109
+ signal commandSaltSquared <== commandSalt * commandSalt;
105
110
  }
@@ -102,4 +102,9 @@ template StateLeafAndBallotTransformer() {
102
102
  isValid <== computedIsValid;
103
103
  isStateLeafIndexValid <== computedIsStateLeafIndexValid;
104
104
  isVoteOptionIndexValid <== computedIsVoteOptionIndexValid;
105
+
106
+ // Constrain commandPollId and commandSalt using dummy squares.
107
+ // This binds the proof to a specific poll and salt.
108
+ signal commandPollIdSquare <== commandPollId * commandPollId;
109
+ signal commandSaltSquared <== commandSalt * commandSalt;
105
110
  }
@@ -25,14 +25,17 @@ template BinaryMerkleRoot(MAX_DEPTH) {
25
25
  signal input leaf;
26
26
  // The depth of the Merkle tree.
27
27
  signal input depth;
28
- // The indices of the leaf node in the Merkle tree.
29
- signal input indices[MAX_DEPTH];
28
+ // The index of the leaf node in the Merkle tree.
29
+ signal input index;
30
30
  // The sibling nodes of the leaf node in the Merkle tree.
31
31
  signal input siblings[MAX_DEPTH][1];
32
32
 
33
33
  // The output of the Merkle tree root.
34
34
  signal output out;
35
35
 
36
+ // The indices of the leaf node in the Merkle tree.
37
+ signal indices[MAX_DEPTH] <== Num2Bits(MAX_DEPTH)(index);
38
+
36
39
  signal nodes[MAX_DEPTH + 1];
37
40
  nodes[0] <== leaf;
38
41
 
@@ -19,8 +19,8 @@ template PollJoined(stateTreeDepth) {
19
19
  signal input voiceCreditsBalance;
20
20
  // Path elements
21
21
  signal input pathElements[stateTreeDepth][STATE_TREE_ARITY - 1];
22
- // Path indices
23
- signal input pathIndices[stateTreeDepth];
22
+ // Index
23
+ signal input index;
24
24
  // Poll State tree root which proves the user is joined
25
25
  signal input stateRoot;
26
26
  // The actual tree depth (might be <= stateTreeDepth) Used in BinaryMerkleRoot
@@ -35,7 +35,7 @@ template PollJoined(stateTreeDepth) {
35
35
  var calculatedRoot = BinaryMerkleRoot(stateTreeDepth)(
36
36
  stateLeaf,
37
37
  actualStateTreeDepth,
38
- pathIndices,
38
+ index,
39
39
  pathElements
40
40
  );
41
41
 
@@ -18,8 +18,8 @@ template PollJoining(stateTreeDepth) {
18
18
  signal input pollPublicKey[2];
19
19
  // Siblings
20
20
  signal input siblings[stateTreeDepth][STATE_TREE_ARITY - 1];
21
- // Indices
22
- signal input indices[stateTreeDepth];
21
+ // Index
22
+ signal input index;
23
23
  // User's hashed private key
24
24
  signal input nullifier;
25
25
  // MACI State tree root which proves the user is signed up
@@ -46,7 +46,7 @@ template PollJoining(stateTreeDepth) {
46
46
  var calculatedRoot = BinaryMerkleRoot(stateTreeDepth)(
47
47
  publicKeyHash,
48
48
  actualStateTreeDepth,
49
- indices,
49
+ index,
50
50
  siblings
51
51
  );
52
52