@maci-protocol/core 0.0.0-ci.a577366 → 0.0.0-ci.a584b1a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -2
- package/build/ts/MaciState.d.ts +7 -7
- package/build/ts/MaciState.d.ts.map +1 -1
- package/build/ts/MaciState.js +17 -17
- package/build/ts/MaciState.js.map +1 -1
- package/build/ts/Poll.d.ts +28 -28
- package/build/ts/Poll.d.ts.map +1 -1
- package/build/ts/Poll.js +150 -150
- package/build/ts/Poll.js.map +1 -1
- package/build/ts/index.d.ts +2 -2
- package/build/ts/index.d.ts.map +1 -1
- package/build/ts/index.js +5 -5
- package/build/ts/index.js.map +1 -1
- package/build/ts/utils/types.d.ts +30 -30
- package/build/ts/utils/types.d.ts.map +1 -1
- package/build/ts/utils/utils.d.ts +16 -16
- package/build/ts/utils/utils.d.ts.map +1 -1
- package/build/ts/utils/utils.js +21 -21
- package/build/ts/utils/utils.js.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +5 -5
package/build/ts/Poll.js
CHANGED
|
@@ -27,9 +27,9 @@ class Poll {
|
|
|
27
27
|
this.ballots = [];
|
|
28
28
|
this.messages = [];
|
|
29
29
|
this.commands = [];
|
|
30
|
-
this.
|
|
30
|
+
this.encryptionPublicKeys = [];
|
|
31
31
|
this.stateCopied = false;
|
|
32
|
-
this.
|
|
32
|
+
this.publicKeys = [domainobjs_1.padKey];
|
|
33
33
|
// For message processing
|
|
34
34
|
this.numBatchesProcessed = 0;
|
|
35
35
|
this.sbSalts = {};
|
|
@@ -38,7 +38,7 @@ class Poll {
|
|
|
38
38
|
this.spentVoiceCreditSubtotalSalts = {};
|
|
39
39
|
// For vote tallying
|
|
40
40
|
this.tallyResult = [];
|
|
41
|
-
this.
|
|
41
|
+
this.perVoteOptionSpentVoiceCredits = [];
|
|
42
42
|
this.numBatchesTallied = 0;
|
|
43
43
|
this.totalSpentVoiceCredits = 0n;
|
|
44
44
|
// message chain hash
|
|
@@ -48,7 +48,7 @@ class Poll {
|
|
|
48
48
|
// Poll state tree leaves
|
|
49
49
|
this.pollStateLeaves = [domainobjs_1.blankStateLeaf];
|
|
50
50
|
// how many users signed up
|
|
51
|
-
this.
|
|
51
|
+
this.totalSignups = 0n;
|
|
52
52
|
/**
|
|
53
53
|
* Check if user has already joined the poll by checking if the nullifier is registered
|
|
54
54
|
*/
|
|
@@ -56,12 +56,12 @@ class Poll {
|
|
|
56
56
|
/**
|
|
57
57
|
* Join the anonymous user to the Poll (to the tree)
|
|
58
58
|
* @param nullifier - Hashed private key used as nullifier
|
|
59
|
-
* @param
|
|
59
|
+
* @param publicKey - The poll public key.
|
|
60
60
|
* @param newVoiceCreditBalance - New voice credit balance of the user.
|
|
61
61
|
* @returns The index of added state leaf
|
|
62
62
|
*/
|
|
63
|
-
this.joinPoll = (nullifier,
|
|
64
|
-
const stateLeaf = new domainobjs_1.StateLeaf(
|
|
63
|
+
this.joinPoll = (nullifier, publicKey, newVoiceCreditBalance) => {
|
|
64
|
+
const stateLeaf = new domainobjs_1.StateLeaf(publicKey, newVoiceCreditBalance);
|
|
65
65
|
if (this.hasJoined(nullifier)) {
|
|
66
66
|
throw new Error("UserAlreadyJoined");
|
|
67
67
|
}
|
|
@@ -74,11 +74,11 @@ class Poll {
|
|
|
74
74
|
* Update a Poll with data from MaciState.
|
|
75
75
|
* This is the step where we copy the state from the MaciState instance,
|
|
76
76
|
* and set the number of signups we have so far.
|
|
77
|
-
* @note It should be called to generate the state for poll joining with
|
|
78
|
-
* the number of signups in the MaciState. For message processing, you should set
|
|
77
|
+
* @note It should be called to generate the state for poll joining with totalSignups set as
|
|
78
|
+
* the number of signups in the MaciState. For message processing, you should set totalSignups as
|
|
79
79
|
* the number of users who joined the poll.
|
|
80
80
|
*/
|
|
81
|
-
this.updatePoll = (
|
|
81
|
+
this.updatePoll = (totalSignups) => {
|
|
82
82
|
// there might be occasions where we fetch logs after new signups have been made
|
|
83
83
|
// logs are fetched (and MaciState/Poll created locally).
|
|
84
84
|
// If someone signs up after that and we fetch that record
|
|
@@ -86,15 +86,15 @@ class Poll {
|
|
|
86
86
|
// not match. For this, we must only copy up to the number of signups
|
|
87
87
|
// Copy the state tree, ballot tree, state leaves, and ballot leaves
|
|
88
88
|
// start by setting the number of signups
|
|
89
|
-
this.
|
|
90
|
-
// copy up to
|
|
91
|
-
this.
|
|
89
|
+
this.setTotalSignups(totalSignups);
|
|
90
|
+
// copy up to totalSignups state leaves
|
|
91
|
+
this.publicKeys = this.maciStateRef.publicKeys.slice(0, Number(this.totalSignups)).map((x) => x.copy());
|
|
92
92
|
// ensure we have the correct actual state tree depth value
|
|
93
|
-
this.actualStateTreeDepth = Math.max(1, Math.ceil(Math.log2(Number(this.
|
|
93
|
+
this.actualStateTreeDepth = Math.max(1, Math.ceil(Math.log2(Number(this.totalSignups))));
|
|
94
94
|
this.stateTree = new lean_imt_1.LeanIMT(crypto_1.hashLeanIMT);
|
|
95
95
|
// add all leaves
|
|
96
|
-
this.
|
|
97
|
-
this.stateTree?.insert(
|
|
96
|
+
this.publicKeys.forEach((publicKey) => {
|
|
97
|
+
this.stateTree?.insert(publicKey.hash());
|
|
98
98
|
});
|
|
99
99
|
// create a poll state tree
|
|
100
100
|
this.pollStateTree = new crypto_1.IncrementalQuinTree(this.actualStateTreeDepth, domainobjs_1.blankStateLeafHash, constants_1.STATE_TREE_ARITY, crypto_1.hash2);
|
|
@@ -106,7 +106,7 @@ class Poll {
|
|
|
106
106
|
this.ballotTree = new crypto_1.IncrementalQuinTree(Number(this.treeDepths.stateTreeDepth), this.emptyBallotHash, constants_1.STATE_TREE_ARITY, crypto_1.hash2);
|
|
107
107
|
this.ballotTree.insert(this.emptyBallotHash);
|
|
108
108
|
// we fill the ballotTree with empty ballots hashes to match the number of signups in the tree
|
|
109
|
-
while (this.ballots.length < this.
|
|
109
|
+
while (this.ballots.length < this.publicKeys.length) {
|
|
110
110
|
this.ballotTree.insert(this.emptyBallotHash);
|
|
111
111
|
this.ballots.push(this.emptyBallot);
|
|
112
112
|
}
|
|
@@ -115,14 +115,14 @@ class Poll {
|
|
|
115
115
|
/**
|
|
116
116
|
* Process one message.
|
|
117
117
|
* @param message - The message to process.
|
|
118
|
-
* @param
|
|
118
|
+
* @param encryptionPublicKey - The public key associated with the encryption private key.
|
|
119
119
|
* @returns A number of variables which will be used in the zk-SNARK circuit.
|
|
120
120
|
*/
|
|
121
|
-
this.processMessage = (message,
|
|
121
|
+
this.processMessage = (message, encryptionPublicKey, qv = true) => {
|
|
122
122
|
try {
|
|
123
123
|
// Decrypt the message
|
|
124
|
-
const sharedKey = domainobjs_1.Keypair.
|
|
125
|
-
const { command, signature } = domainobjs_1.
|
|
124
|
+
const sharedKey = domainobjs_1.Keypair.generateEcdhSharedKey(this.coordinatorKeypair.privateKey, encryptionPublicKey);
|
|
125
|
+
const { command, signature } = domainobjs_1.VoteCommand.decrypt(message, sharedKey);
|
|
126
126
|
const stateLeafIndex = command.stateIndex;
|
|
127
127
|
// If the state tree index in the command is invalid, do nothing
|
|
128
128
|
if (stateLeafIndex >= BigInt(this.ballots.length) ||
|
|
@@ -135,7 +135,7 @@ class Poll {
|
|
|
135
135
|
// The ballot to update (or not)
|
|
136
136
|
const ballot = this.ballots[Number(stateLeafIndex)];
|
|
137
137
|
// If the signature is invalid, do nothing
|
|
138
|
-
if (!command.verifySignature(signature, stateLeaf.
|
|
138
|
+
if (!command.verifySignature(signature, stateLeaf.publicKey)) {
|
|
139
139
|
throw new errors_1.ProcessMessageError(errors_1.ProcessMessageErrors.InvalidSignature);
|
|
140
140
|
}
|
|
141
141
|
// If the nonce is invalid, do nothing
|
|
@@ -170,7 +170,7 @@ class Poll {
|
|
|
170
170
|
const newStateLeaf = stateLeaf.copy();
|
|
171
171
|
newStateLeaf.voiceCreditBalance = voiceCreditsLeft;
|
|
172
172
|
// if the key changes, this is effectively a key-change message too
|
|
173
|
-
newStateLeaf.
|
|
173
|
+
newStateLeaf.publicKey = command.newPublicKey.copy();
|
|
174
174
|
// Deep-copy the ballot and update its attributes
|
|
175
175
|
const newBallot = ballot.copy();
|
|
176
176
|
// increase the nonce
|
|
@@ -180,17 +180,17 @@ class Poll {
|
|
|
180
180
|
// calculate the path elements for the state tree given the original state tree (before any changes)
|
|
181
181
|
// changes could effectively be made by this new vote - either a key change or vote change
|
|
182
182
|
// would result in a different state leaf
|
|
183
|
-
const originalStateLeafPathElements = this.pollStateTree
|
|
183
|
+
const { pathElements: originalStateLeafPathElements } = this.pollStateTree.genProof(Number(stateLeafIndex));
|
|
184
184
|
// calculate the path elements for the ballot tree given the original ballot tree (before any changes)
|
|
185
185
|
// changes could effectively be made by this new ballot
|
|
186
|
-
const originalBallotPathElements = this.ballotTree
|
|
186
|
+
const { pathElements: originalBallotPathElements } = this.ballotTree.genProof(Number(stateLeafIndex));
|
|
187
187
|
// create a new quinary tree where we insert the votes of the origin (up until this message is processed) ballot
|
|
188
|
-
const
|
|
188
|
+
const voteTree = new crypto_1.IncrementalQuinTree(this.treeDepths.voteOptionTreeDepth, 0n, constants_1.VOTE_OPTION_TREE_ARITY, crypto_1.hash5);
|
|
189
189
|
for (let i = 0; i < this.ballots[0].votes.length; i += 1) {
|
|
190
|
-
|
|
190
|
+
voteTree.insert(ballot.votes[i]);
|
|
191
191
|
}
|
|
192
192
|
// calculate the path elements for the vote option tree given the original vote option tree (before any changes)
|
|
193
|
-
const originalVoteWeightsPathElements =
|
|
193
|
+
const { pathElements: originalVoteWeightsPathElements } = voteTree.genProof(voteOptionIndex);
|
|
194
194
|
// we return the data which is then to be used in the processMessage circuit
|
|
195
195
|
// to generate a proof of processing
|
|
196
196
|
return {
|
|
@@ -219,40 +219,40 @@ class Poll {
|
|
|
219
219
|
* Inserts a Message and the corresponding public key used to generate the
|
|
220
220
|
* ECDH shared key which was used to encrypt said message.
|
|
221
221
|
* @param message - The message to insert
|
|
222
|
-
* @param
|
|
222
|
+
* @param encryptionPublicKey - The public key used to encrypt the message
|
|
223
223
|
*/
|
|
224
|
-
this.publishMessage = (message,
|
|
225
|
-
(0, assert_1.default)(
|
|
224
|
+
this.publishMessage = (message, encryptionPublicKey) => {
|
|
225
|
+
(0, assert_1.default)(encryptionPublicKey.raw[0] < crypto_1.SNARK_FIELD_SIZE && encryptionPublicKey.raw[1] < crypto_1.SNARK_FIELD_SIZE, "The public key is not in the correct range");
|
|
226
226
|
message.data.forEach((d) => {
|
|
227
227
|
(0, assert_1.default)(d < crypto_1.SNARK_FIELD_SIZE, "The message data is not in the correct range");
|
|
228
228
|
});
|
|
229
|
-
// store the encryption
|
|
230
|
-
this.
|
|
229
|
+
// store the encryption public key
|
|
230
|
+
this.encryptionPublicKeys.push(encryptionPublicKey);
|
|
231
231
|
// store the message locally
|
|
232
232
|
this.messages.push(message);
|
|
233
233
|
// add the message hash to the message tree
|
|
234
|
-
const messageHash = message.hash(
|
|
234
|
+
const messageHash = message.hash(encryptionPublicKey);
|
|
235
235
|
// update chain hash
|
|
236
236
|
this.updateChainHash(messageHash);
|
|
237
237
|
// Decrypt the message and store the Command
|
|
238
238
|
// step 1. we generate the shared key
|
|
239
|
-
const sharedKey = domainobjs_1.Keypair.
|
|
239
|
+
const sharedKey = domainobjs_1.Keypair.generateEcdhSharedKey(this.coordinatorKeypair.privateKey, encryptionPublicKey);
|
|
240
240
|
try {
|
|
241
241
|
// step 2. we decrypt it
|
|
242
|
-
const { command } = domainobjs_1.
|
|
242
|
+
const { command } = domainobjs_1.VoteCommand.decrypt(message, sharedKey);
|
|
243
243
|
// step 3. we store it in the commands array
|
|
244
244
|
this.commands.push(command);
|
|
245
245
|
}
|
|
246
246
|
catch (e) {
|
|
247
247
|
// if there is an error we store an empty command
|
|
248
|
-
const
|
|
249
|
-
const command = new domainobjs_1.
|
|
248
|
+
const keypair = new domainobjs_1.Keypair();
|
|
249
|
+
const command = new domainobjs_1.VoteCommand(0n, keypair.publicKey, 0n, 0n, 0n, 0n, 0n);
|
|
250
250
|
this.commands.push(command);
|
|
251
251
|
}
|
|
252
252
|
};
|
|
253
253
|
/**
|
|
254
254
|
* Updates message chain hash
|
|
255
|
-
* @param messageHash hash of message with
|
|
255
|
+
* @param messageHash hash of message with encryptionPublicKey
|
|
256
256
|
*/
|
|
257
257
|
this.updateChainHash = (messageHash) => {
|
|
258
258
|
this.chainHash = (0, crypto_1.hash2)([this.chainHash, messageHash]);
|
|
@@ -266,7 +266,7 @@ class Poll {
|
|
|
266
266
|
* @param args Poll joining circuit inputs
|
|
267
267
|
* @returns stringified circuit inputs
|
|
268
268
|
*/
|
|
269
|
-
this.joiningCircuitInputs = ({
|
|
269
|
+
this.joiningCircuitInputs = ({ maciPrivateKey, stateLeafIndex, pollPublicKey, }) => {
|
|
270
270
|
// calculate the path elements for the state tree given the original state tree
|
|
271
271
|
const { siblings, index } = this.stateTree.generateProof(Number(stateLeafIndex));
|
|
272
272
|
const siblingsLength = siblings.length;
|
|
@@ -284,15 +284,15 @@ class Poll {
|
|
|
284
284
|
}
|
|
285
285
|
const siblingsArray = siblings.map((sibling) => [sibling]);
|
|
286
286
|
// Create nullifier from private key
|
|
287
|
-
const inputNullifier = BigInt(
|
|
287
|
+
const inputNullifier = BigInt(maciPrivateKey.asCircuitInputs());
|
|
288
288
|
const nullifier = (0, crypto_1.poseidon)([inputNullifier, this.pollId]);
|
|
289
289
|
// Get state tree's root
|
|
290
290
|
const stateRoot = this.stateTree.root;
|
|
291
291
|
// Set actualStateTreeDepth as number of initial siblings length
|
|
292
292
|
const actualStateTreeDepth = BigInt(siblingsLength);
|
|
293
293
|
const circuitInputs = {
|
|
294
|
-
|
|
295
|
-
|
|
294
|
+
privateKey: maciPrivateKey.asCircuitInputs(),
|
|
295
|
+
pollPublicKey: pollPublicKey.asCircuitInputs(),
|
|
296
296
|
siblings: siblingsArray,
|
|
297
297
|
indices,
|
|
298
298
|
nullifier,
|
|
@@ -307,7 +307,7 @@ class Poll {
|
|
|
307
307
|
* @param args Poll joined circuit inputs
|
|
308
308
|
* @returns stringified circuit inputs
|
|
309
309
|
*/
|
|
310
|
-
this.joinedCircuitInputs = ({
|
|
310
|
+
this.joinedCircuitInputs = ({ maciPrivateKey, stateLeafIndex, voiceCreditsBalance, }) => {
|
|
311
311
|
// calculate the path elements for the state tree given the original state tree
|
|
312
312
|
const { root: stateRoot, pathElements, pathIndices } = this.pollStateTree.genProof(Number(stateLeafIndex));
|
|
313
313
|
const elementsLength = pathIndices.length;
|
|
@@ -318,7 +318,7 @@ class Poll {
|
|
|
318
318
|
}
|
|
319
319
|
}
|
|
320
320
|
const circuitInputs = {
|
|
321
|
-
|
|
321
|
+
privateKey: maciPrivateKey.asCircuitInputs(),
|
|
322
322
|
pathElements: pathElements.map((item) => item.toString()),
|
|
323
323
|
voiceCreditsBalance: voiceCreditsBalance.toString(),
|
|
324
324
|
pathIndices: pathIndices.map((item) => item.toString()),
|
|
@@ -386,7 +386,7 @@ class Poll {
|
|
|
386
386
|
throw new Error("You must update the poll with the correct data first");
|
|
387
387
|
}
|
|
388
388
|
// Generate circuit inputs
|
|
389
|
-
const circuitInputs = (0, crypto_1.stringifyBigInts)(this.
|
|
389
|
+
const circuitInputs = (0, crypto_1.stringifyBigInts)(this.generateProcessMessagesCircuitInputsPartial(this.currentMessageBatchIndex));
|
|
390
390
|
// we want to store the state leaves at this point in time
|
|
391
391
|
// and the path elements of the state tree
|
|
392
392
|
const currentStateLeaves = [];
|
|
@@ -405,29 +405,29 @@ class Poll {
|
|
|
405
405
|
const idx = this.currentMessageBatchIndex * batchSize - i - 1;
|
|
406
406
|
(0, assert_1.default)(idx >= 0, "The message index must be >= 0");
|
|
407
407
|
let message;
|
|
408
|
-
let
|
|
408
|
+
let encryptionPublicKey;
|
|
409
409
|
if (idx < this.messages.length) {
|
|
410
410
|
message = this.messages[idx];
|
|
411
|
-
|
|
411
|
+
encryptionPublicKey = this.encryptionPublicKeys[idx];
|
|
412
412
|
try {
|
|
413
413
|
// check if the command is valid
|
|
414
|
-
const
|
|
415
|
-
const index =
|
|
414
|
+
const { stateLeafIndex, originalStateLeaf, originalBallot, originalVoteWeight, originalVoteWeightsPathElements, originalStateLeafPathElements, originalBallotPathElements, newStateLeaf, newBallot, } = this.processMessage(message, encryptionPublicKey, qv);
|
|
415
|
+
const index = stateLeafIndex;
|
|
416
416
|
// we add at position 0 the original data
|
|
417
|
-
currentStateLeaves.unshift(
|
|
418
|
-
currentBallots.unshift(
|
|
419
|
-
currentVoteWeights.unshift(
|
|
420
|
-
currentVoteWeightsPathElements.unshift(
|
|
421
|
-
currentStateLeavesPathElements.unshift(
|
|
422
|
-
currentBallotsPathElements.unshift(
|
|
417
|
+
currentStateLeaves.unshift(originalStateLeaf);
|
|
418
|
+
currentBallots.unshift(originalBallot);
|
|
419
|
+
currentVoteWeights.unshift(originalVoteWeight);
|
|
420
|
+
currentVoteWeightsPathElements.unshift(originalVoteWeightsPathElements);
|
|
421
|
+
currentStateLeavesPathElements.unshift(originalStateLeafPathElements);
|
|
422
|
+
currentBallotsPathElements.unshift(originalBallotPathElements);
|
|
423
423
|
// update the state leaves with the new state leaf (result of processing the message)
|
|
424
|
-
this.pollStateLeaves[index] =
|
|
424
|
+
this.pollStateLeaves[index] = newStateLeaf.copy();
|
|
425
425
|
// we also update the state tree with the hash of the new state leaf
|
|
426
|
-
this.pollStateTree?.update(index,
|
|
426
|
+
this.pollStateTree?.update(index, newStateLeaf.hash());
|
|
427
427
|
// store the new ballot
|
|
428
|
-
this.ballots[index] =
|
|
428
|
+
this.ballots[index] = newBallot;
|
|
429
429
|
// update the ballot tree
|
|
430
|
-
this.ballotTree?.update(index,
|
|
430
|
+
this.ballotTree?.update(index, newBallot.hash());
|
|
431
431
|
}
|
|
432
432
|
catch (e) {
|
|
433
433
|
// if the error is not a ProcessMessageError we throw it and exit here
|
|
@@ -446,10 +446,10 @@ class Poll {
|
|
|
446
446
|
// which sends a message that when force decrypted on the circuit
|
|
447
447
|
// results in a valid state index thus forcing the circuit to look
|
|
448
448
|
// for a valid state leaf, and failing to generate a proof
|
|
449
|
-
//
|
|
450
|
-
const sharedKey = domainobjs_1.Keypair.
|
|
449
|
+
// generate shared key
|
|
450
|
+
const sharedKey = domainobjs_1.Keypair.generateEcdhSharedKey(this.coordinatorKeypair.privateKey, encryptionPublicKey);
|
|
451
451
|
// force decrypt it
|
|
452
|
-
const { command } = domainobjs_1.
|
|
452
|
+
const { command } = domainobjs_1.VoteCommand.decrypt(message, sharedKey, true);
|
|
453
453
|
// cache state leaf index
|
|
454
454
|
const stateLeafIndex = command.stateIndex;
|
|
455
455
|
// if the state leaf index is valid then use it
|
|
@@ -467,24 +467,24 @@ class Poll {
|
|
|
467
467
|
if (command.voteOptionIndex < this.voteOptions) {
|
|
468
468
|
currentVoteWeights.unshift(ballot.votes[Number(command.voteOptionIndex)]);
|
|
469
469
|
// create a new quinary tree and add all votes we have so far
|
|
470
|
-
const
|
|
470
|
+
const voteTree = new crypto_1.IncrementalQuinTree(this.treeDepths.voteOptionTreeDepth, 0n, constants_1.VOTE_OPTION_TREE_ARITY, crypto_1.hash5);
|
|
471
471
|
// fill the vote option tree with the votes we have so far
|
|
472
472
|
for (let j = 0; j < this.ballots[0].votes.length; j += 1) {
|
|
473
|
-
|
|
473
|
+
voteTree.insert(ballot.votes[j]);
|
|
474
474
|
}
|
|
475
475
|
// get the path elements for the first vote leaf
|
|
476
|
-
currentVoteWeightsPathElements.unshift(
|
|
476
|
+
currentVoteWeightsPathElements.unshift(voteTree.genProof(Number(command.voteOptionIndex)).pathElements);
|
|
477
477
|
}
|
|
478
478
|
else {
|
|
479
479
|
currentVoteWeights.unshift(ballot.votes[0]);
|
|
480
480
|
// create a new quinary tree and add all votes we have so far
|
|
481
|
-
const
|
|
481
|
+
const voteTree = new crypto_1.IncrementalQuinTree(this.treeDepths.voteOptionTreeDepth, 0n, constants_1.VOTE_OPTION_TREE_ARITY, crypto_1.hash5);
|
|
482
482
|
// fill the vote option tree with the votes we have so far
|
|
483
483
|
for (let j = 0; j < this.ballots[0].votes.length; j += 1) {
|
|
484
|
-
|
|
484
|
+
voteTree.insert(ballot.votes[j]);
|
|
485
485
|
}
|
|
486
486
|
// get the path elements for the first vote leaf
|
|
487
|
-
currentVoteWeightsPathElements.unshift(
|
|
487
|
+
currentVoteWeightsPathElements.unshift(voteTree.genProof(0).pathElements);
|
|
488
488
|
}
|
|
489
489
|
}
|
|
490
490
|
else {
|
|
@@ -496,10 +496,10 @@ class Poll {
|
|
|
496
496
|
// Since the command is invalid, we use a zero vote weight
|
|
497
497
|
currentVoteWeights.unshift(this.ballots[0].votes[0]);
|
|
498
498
|
// create a new quinary tree and add an empty vote
|
|
499
|
-
const
|
|
500
|
-
|
|
499
|
+
const voteTree = new crypto_1.IncrementalQuinTree(this.treeDepths.voteOptionTreeDepth, 0n, constants_1.VOTE_OPTION_TREE_ARITY, crypto_1.hash5);
|
|
500
|
+
voteTree.insert(this.ballots[0].votes[0]);
|
|
501
501
|
// get the path elements for this empty vote weight leaf
|
|
502
|
-
currentVoteWeightsPathElements.unshift(
|
|
502
|
+
currentVoteWeightsPathElements.unshift(voteTree.genProof(0).pathElements);
|
|
503
503
|
}
|
|
504
504
|
}
|
|
505
505
|
else {
|
|
@@ -517,10 +517,10 @@ class Poll {
|
|
|
517
517
|
// Since the command is invalid, we use a zero vote weight
|
|
518
518
|
currentVoteWeights.unshift(this.ballots[0].votes[0]);
|
|
519
519
|
// create a new quinary tree and add an empty vote
|
|
520
|
-
const
|
|
521
|
-
|
|
520
|
+
const voteTree = new crypto_1.IncrementalQuinTree(this.treeDepths.voteOptionTreeDepth, 0n, constants_1.VOTE_OPTION_TREE_ARITY, crypto_1.hash5);
|
|
521
|
+
voteTree.insert(this.ballots[0].votes[0]);
|
|
522
522
|
// get the path elements for this empty vote weight leaf
|
|
523
|
-
currentVoteWeightsPathElements.unshift(
|
|
523
|
+
currentVoteWeightsPathElements.unshift(voteTree.genProof(0).pathElements);
|
|
524
524
|
}
|
|
525
525
|
}
|
|
526
526
|
// store the data in the circuit inputs object
|
|
@@ -543,9 +543,9 @@ class Poll {
|
|
|
543
543
|
this.currentMessageBatchIndex -= 1;
|
|
544
544
|
}
|
|
545
545
|
// ensure newSbSalt differs from currentSbSalt
|
|
546
|
-
let newSbSalt = (0, crypto_1.
|
|
546
|
+
let newSbSalt = (0, crypto_1.generateRandomSalt)();
|
|
547
547
|
while (this.sbSalts[this.currentMessageBatchIndex] === newSbSalt) {
|
|
548
|
-
newSbSalt = (0, crypto_1.
|
|
548
|
+
newSbSalt = (0, crypto_1.generateRandomSalt)();
|
|
549
549
|
}
|
|
550
550
|
this.sbSalts[this.currentMessageBatchIndex] = newSbSalt;
|
|
551
551
|
// store the salt in the circuit inputs
|
|
@@ -555,7 +555,7 @@ class Poll {
|
|
|
555
555
|
// create a commitment to the state and ballot tree roots
|
|
556
556
|
// this will be the hash of the roots with a salt
|
|
557
557
|
circuitInputs.newSbCommitment = (0, crypto_1.hash3)([newStateRoot, newBallotRoot, newSbSalt]);
|
|
558
|
-
const coordinatorPublicKeyHash = this.coordinatorKeypair.
|
|
558
|
+
const coordinatorPublicKeyHash = this.coordinatorKeypair.publicKey.hash();
|
|
559
559
|
// If this is the last batch, release the lock
|
|
560
560
|
if (this.numBatchesProcessed * batchSize >= this.messages.length) {
|
|
561
561
|
this.maciStateRef.pollBeingProcessed = false;
|
|
@@ -572,33 +572,33 @@ class Poll {
|
|
|
572
572
|
* @param index - The index of the partial batch.
|
|
573
573
|
* @returns stringified partial circuit inputs
|
|
574
574
|
*/
|
|
575
|
-
this.
|
|
575
|
+
this.generateProcessMessagesCircuitInputsPartial = (index) => {
|
|
576
576
|
const { messageBatchSize } = this.batchSizes;
|
|
577
577
|
(0, assert_1.default)(index <= this.messages.length, "The index must be <= the number of messages");
|
|
578
|
-
// fill the
|
|
578
|
+
// fill the messages array with a copy of the messages we have
|
|
579
579
|
// plus empty messages to fill the batch
|
|
580
580
|
// @note create a message with state index 0 to add as padding
|
|
581
581
|
// this way the message will look for state leaf 0
|
|
582
582
|
// and no effect will take place
|
|
583
583
|
// create a random key
|
|
584
584
|
const key = new domainobjs_1.Keypair();
|
|
585
|
-
//
|
|
586
|
-
const ecdh = domainobjs_1.Keypair.
|
|
585
|
+
// generate ecdh key
|
|
586
|
+
const ecdh = domainobjs_1.Keypair.generateEcdhSharedKey(key.privateKey, this.coordinatorKeypair.publicKey);
|
|
587
587
|
// create an empty command with state index 0n
|
|
588
|
-
const emptyCommand = new domainobjs_1.
|
|
588
|
+
const emptyCommand = new domainobjs_1.VoteCommand(0n, key.publicKey, 0n, 0n, 0n, 0n, 0n);
|
|
589
589
|
// encrypt it
|
|
590
|
-
const
|
|
590
|
+
const emptyMessage = emptyCommand.encrypt(emptyCommand.sign(key.privateKey), ecdh);
|
|
591
591
|
// copy the messages to a new array
|
|
592
|
-
let
|
|
592
|
+
let messages = this.messages.map((x) => x.asCircuitInputs());
|
|
593
593
|
// pad with our state index 0 message
|
|
594
|
-
while (
|
|
595
|
-
|
|
594
|
+
while (messages.length % messageBatchSize > 0) {
|
|
595
|
+
messages.push(emptyMessage.asCircuitInputs());
|
|
596
596
|
}
|
|
597
597
|
// copy the public keys, pad the array with the last keys if needed
|
|
598
|
-
let
|
|
599
|
-
while (
|
|
598
|
+
let encryptionPublicKeys = this.encryptionPublicKeys.map((x) => x.copy());
|
|
599
|
+
while (encryptionPublicKeys.length % messageBatchSize > 0) {
|
|
600
600
|
// pad with the public key used to encrypt the message with state index 0 (padding)
|
|
601
|
-
|
|
601
|
+
encryptionPublicKeys.push(key.publicKey.copy());
|
|
602
602
|
}
|
|
603
603
|
// validate that the batch index is correct, if not fix it
|
|
604
604
|
// this means that the end will be the last message
|
|
@@ -608,11 +608,11 @@ class Poll {
|
|
|
608
608
|
}
|
|
609
609
|
const batchStartIndex = index > 0 ? (index - 1) * messageBatchSize : 0;
|
|
610
610
|
// we only take the messages we need for this batch
|
|
611
|
-
// it slice
|
|
611
|
+
// it slice messages array from index of first message in current batch to
|
|
612
612
|
// index of last message in current batch
|
|
613
|
-
|
|
613
|
+
messages = messages.slice(batchStartIndex, index * messageBatchSize);
|
|
614
614
|
// then take the ones part of this batch
|
|
615
|
-
|
|
615
|
+
encryptionPublicKeys = encryptionPublicKeys.slice(batchStartIndex, index * messageBatchSize);
|
|
616
616
|
// cache tree roots
|
|
617
617
|
const currentStateRoot = this.pollStateTree.root;
|
|
618
618
|
const currentBallotRoot = this.ballotTree.root;
|
|
@@ -623,15 +623,15 @@ class Poll {
|
|
|
623
623
|
const inputBatchHash = this.batchHashes[index - 1];
|
|
624
624
|
const outputBatchHash = this.batchHashes[index];
|
|
625
625
|
return (0, crypto_1.stringifyBigInts)({
|
|
626
|
-
|
|
626
|
+
totalSignups: BigInt(this.totalSignups),
|
|
627
627
|
batchEndIndex: BigInt(batchEndIndex),
|
|
628
628
|
index: BigInt(batchStartIndex),
|
|
629
629
|
inputBatchHash,
|
|
630
630
|
outputBatchHash,
|
|
631
|
-
|
|
631
|
+
messages,
|
|
632
632
|
actualStateTreeDepth: BigInt(this.actualStateTreeDepth),
|
|
633
|
-
|
|
634
|
-
|
|
633
|
+
coordinatorPrivateKey: this.coordinatorKeypair.privateKey.asCircuitInputs(),
|
|
634
|
+
encryptionPublicKeys: encryptionPublicKeys.map((x) => x.asCircuitInputs()),
|
|
635
635
|
currentStateRoot,
|
|
636
636
|
currentBallotRoot,
|
|
637
637
|
currentSbCommitment,
|
|
@@ -674,12 +674,12 @@ class Poll {
|
|
|
674
674
|
const batchStartIndex = this.numBatchesTallied * batchSize;
|
|
675
675
|
// get the salts needed for the commitments
|
|
676
676
|
const currentResultsRootSalt = batchStartIndex === 0 ? 0n : this.resultRootSalts[batchStartIndex - batchSize];
|
|
677
|
-
const
|
|
677
|
+
const currentPerVoteOptionSpentVoiceCreditsRootSalt = batchStartIndex === 0 ? 0n : this.preVOSpentVoiceCreditsRootSalts[batchStartIndex - batchSize];
|
|
678
678
|
const currentSpentVoiceCreditSubtotalSalt = batchStartIndex === 0 ? 0n : this.spentVoiceCreditSubtotalSalts[batchStartIndex - batchSize];
|
|
679
679
|
// generate a commitment to the current results
|
|
680
|
-
const currentResultsCommitment = (0, crypto_1.
|
|
681
|
-
// generate a commitment to the current per
|
|
682
|
-
const currentPerVOSpentVoiceCreditsCommitment = this.genPerVOSpentVoiceCreditsCommitment(
|
|
680
|
+
const currentResultsCommitment = (0, crypto_1.generateTreeCommitment)(this.tallyResult, currentResultsRootSalt, this.treeDepths.voteOptionTreeDepth);
|
|
681
|
+
// generate a commitment to the current per vote option spent voice credits
|
|
682
|
+
const currentPerVOSpentVoiceCreditsCommitment = this.genPerVOSpentVoiceCreditsCommitment(currentPerVoteOptionSpentVoiceCreditsRootSalt, batchStartIndex, true);
|
|
683
683
|
// generate a commitment to the current spent voice credits
|
|
684
684
|
const currentSpentVoiceCreditsCommitment = this.genSpentVoiceCreditSubtotalCommitment(currentSpentVoiceCreditSubtotalSalt, batchStartIndex, true);
|
|
685
685
|
// the current commitment for the first batch will be 0
|
|
@@ -698,7 +698,7 @@ class Poll {
|
|
|
698
698
|
]);
|
|
699
699
|
const ballots = [];
|
|
700
700
|
const currentResults = this.tallyResult.map((x) => BigInt(x.toString()));
|
|
701
|
-
const
|
|
701
|
+
const currentPerVoteOptionSpentVoiceCredits = this.perVoteOptionSpentVoiceCredits.map((x) => BigInt(x.toString()));
|
|
702
702
|
const currentSpentVoiceCreditSubtotal = BigInt(this.totalSpentVoiceCredits.toString());
|
|
703
703
|
// loop in normal order to tally the ballots one by one
|
|
704
704
|
for (let i = this.numBatchesTallied * batchSize; i < this.numBatchesTallied * batchSize + batchSize; i += 1) {
|
|
@@ -714,7 +714,7 @@ class Poll {
|
|
|
714
714
|
// the vote itself will be a quadratic vote (sqrt(voiceCredits))
|
|
715
715
|
this.tallyResult[j] += v;
|
|
716
716
|
// the per vote option spent voice credits will be the sum of the squares of the votes
|
|
717
|
-
this.
|
|
717
|
+
this.perVoteOptionSpentVoiceCredits[j] += v * v;
|
|
718
718
|
// the total spent voice credits will be the sum of the squares of the votes
|
|
719
719
|
this.totalSpentVoiceCredits += v * v;
|
|
720
720
|
}
|
|
@@ -725,19 +725,19 @@ class Poll {
|
|
|
725
725
|
ballots.push(emptyBallot);
|
|
726
726
|
}
|
|
727
727
|
// generate the new salts
|
|
728
|
-
const newResultsRootSalt = (0, crypto_1.
|
|
729
|
-
const
|
|
730
|
-
const newSpentVoiceCreditSubtotalSalt = (0, crypto_1.
|
|
728
|
+
const newResultsRootSalt = (0, crypto_1.generateRandomSalt)();
|
|
729
|
+
const newPerVoteOptionSpentVoiceCreditsRootSalt = (0, crypto_1.generateRandomSalt)();
|
|
730
|
+
const newSpentVoiceCreditSubtotalSalt = (0, crypto_1.generateRandomSalt)();
|
|
731
731
|
// and save them to be used in the next batch
|
|
732
732
|
this.resultRootSalts[batchStartIndex] = newResultsRootSalt;
|
|
733
|
-
this.preVOSpentVoiceCreditsRootSalts[batchStartIndex] =
|
|
733
|
+
this.preVOSpentVoiceCreditsRootSalts[batchStartIndex] = newPerVoteOptionSpentVoiceCreditsRootSalt;
|
|
734
734
|
this.spentVoiceCreditSubtotalSalts[batchStartIndex] = newSpentVoiceCreditSubtotalSalt;
|
|
735
735
|
// generate the new results commitment with the new salts and data
|
|
736
|
-
const newResultsCommitment = (0, crypto_1.
|
|
736
|
+
const newResultsCommitment = (0, crypto_1.generateTreeCommitment)(this.tallyResult, newResultsRootSalt, this.treeDepths.voteOptionTreeDepth);
|
|
737
737
|
// generate the new spent voice credits commitment with the new salts and data
|
|
738
738
|
const newSpentVoiceCreditsCommitment = this.genSpentVoiceCreditSubtotalCommitment(newSpentVoiceCreditSubtotalSalt, batchStartIndex + batchSize, true);
|
|
739
|
-
// generate the new per
|
|
740
|
-
const newPerVOSpentVoiceCreditsCommitment = this.genPerVOSpentVoiceCreditsCommitment(
|
|
739
|
+
// generate the new per vote option spent voice credits commitment with the new salts and data
|
|
740
|
+
const newPerVOSpentVoiceCreditsCommitment = this.genPerVOSpentVoiceCreditsCommitment(newPerVoteOptionSpentVoiceCreditsRootSalt, batchStartIndex + batchSize, true);
|
|
741
741
|
// generate the new tally commitment
|
|
742
742
|
const newTallyCommitment = (0, crypto_1.hash3)([
|
|
743
743
|
newResultsCommitment,
|
|
@@ -756,7 +756,7 @@ class Poll {
|
|
|
756
756
|
ballotRoot,
|
|
757
757
|
sbSalt,
|
|
758
758
|
index: BigInt(batchStartIndex),
|
|
759
|
-
|
|
759
|
+
totalSignups: BigInt(this.totalSignups),
|
|
760
760
|
sbCommitment,
|
|
761
761
|
currentTallyCommitment,
|
|
762
762
|
newTallyCommitment,
|
|
@@ -767,10 +767,10 @@ class Poll {
|
|
|
767
767
|
currentResultsRootSalt,
|
|
768
768
|
currentSpentVoiceCreditSubtotal,
|
|
769
769
|
currentSpentVoiceCreditSubtotalSalt,
|
|
770
|
-
|
|
771
|
-
|
|
770
|
+
currentPerVoteOptionSpentVoiceCredits,
|
|
771
|
+
currentPerVoteOptionSpentVoiceCreditsRootSalt,
|
|
772
772
|
newResultsRootSalt,
|
|
773
|
-
|
|
773
|
+
newPerVoteOptionSpentVoiceCreditsRootSalt,
|
|
774
774
|
newSpentVoiceCreditSubtotalSalt,
|
|
775
775
|
});
|
|
776
776
|
this.numBatchesTallied += 1;
|
|
@@ -789,7 +789,7 @@ class Poll {
|
|
|
789
789
|
const currentResultsRootSalt = batchStartIndex === 0 ? 0n : this.resultRootSalts[batchStartIndex - batchSize];
|
|
790
790
|
const currentSpentVoiceCreditSubtotalSalt = batchStartIndex === 0 ? 0n : this.spentVoiceCreditSubtotalSalts[batchStartIndex - batchSize];
|
|
791
791
|
// generate a commitment to the current results
|
|
792
|
-
const currentResultsCommitment = (0, crypto_1.
|
|
792
|
+
const currentResultsCommitment = (0, crypto_1.generateTreeCommitment)(this.tallyResult, currentResultsRootSalt, this.treeDepths.voteOptionTreeDepth);
|
|
793
793
|
// generate a commitment to the current spent voice credits
|
|
794
794
|
const currentSpentVoiceCreditsCommitment = this.genSpentVoiceCreditSubtotalCommitment(currentSpentVoiceCreditSubtotalSalt, batchStartIndex, false);
|
|
795
795
|
// the current commitment for the first batch will be 0
|
|
@@ -824,13 +824,13 @@ class Poll {
|
|
|
824
824
|
ballots.push(emptyBallot);
|
|
825
825
|
}
|
|
826
826
|
// generate the new salts
|
|
827
|
-
const newResultsRootSalt = (0, crypto_1.
|
|
828
|
-
const newSpentVoiceCreditSubtotalSalt = (0, crypto_1.
|
|
827
|
+
const newResultsRootSalt = (0, crypto_1.generateRandomSalt)();
|
|
828
|
+
const newSpentVoiceCreditSubtotalSalt = (0, crypto_1.generateRandomSalt)();
|
|
829
829
|
// and save them to be used in the next batch
|
|
830
830
|
this.resultRootSalts[batchStartIndex] = newResultsRootSalt;
|
|
831
831
|
this.spentVoiceCreditSubtotalSalts[batchStartIndex] = newSpentVoiceCreditSubtotalSalt;
|
|
832
832
|
// generate the new results commitment with the new salts and data
|
|
833
|
-
const newResultsCommitment = (0, crypto_1.
|
|
833
|
+
const newResultsCommitment = (0, crypto_1.generateTreeCommitment)(this.tallyResult, newResultsRootSalt, this.treeDepths.voteOptionTreeDepth);
|
|
834
834
|
// generate the new spent voice credits commitment with the new salts and data
|
|
835
835
|
const newSpentVoiceCreditsCommitment = this.genSpentVoiceCreditSubtotalCommitment(newSpentVoiceCreditSubtotalSalt, batchStartIndex + batchSize, false);
|
|
836
836
|
// generate the new tally commitment
|
|
@@ -847,7 +847,7 @@ class Poll {
|
|
|
847
847
|
ballotRoot,
|
|
848
848
|
sbSalt,
|
|
849
849
|
index: BigInt(batchStartIndex),
|
|
850
|
-
|
|
850
|
+
totalSignups: BigInt(this.totalSignups),
|
|
851
851
|
sbCommitment,
|
|
852
852
|
currentTallyCommitment,
|
|
853
853
|
newTallyCommitment,
|
|
@@ -907,7 +907,7 @@ class Poll {
|
|
|
907
907
|
leaves[j] += useQuadraticVoting ? v * v : v;
|
|
908
908
|
}
|
|
909
909
|
}
|
|
910
|
-
return (0, crypto_1.
|
|
910
|
+
return (0, crypto_1.generateTreeCommitment)(leaves, salt, this.treeDepths.voteOptionTreeDepth);
|
|
911
911
|
};
|
|
912
912
|
/**
|
|
913
913
|
* Create a deep copy of the Poll object.
|
|
@@ -922,19 +922,19 @@ class Poll {
|
|
|
922
922
|
tallyBatchSize: Number(this.batchSizes.tallyBatchSize.toString()),
|
|
923
923
|
messageBatchSize: Number(this.batchSizes.messageBatchSize.toString()),
|
|
924
924
|
}, this.maciStateRef, this.voteOptions);
|
|
925
|
-
copied.
|
|
925
|
+
copied.publicKeys = this.publicKeys.map((x) => x.copy());
|
|
926
926
|
copied.pollStateLeaves = this.pollStateLeaves.map((x) => x.copy());
|
|
927
927
|
copied.messages = this.messages.map((x) => x.copy());
|
|
928
928
|
copied.commands = this.commands.map((x) => x.copy());
|
|
929
929
|
copied.ballots = this.ballots.map((x) => x.copy());
|
|
930
|
-
copied.
|
|
930
|
+
copied.encryptionPublicKeys = this.encryptionPublicKeys.map((x) => x.copy());
|
|
931
931
|
if (this.ballotTree) {
|
|
932
932
|
copied.ballotTree = this.ballotTree.copy();
|
|
933
933
|
}
|
|
934
934
|
copied.currentMessageBatchIndex = this.currentMessageBatchIndex;
|
|
935
935
|
copied.maciStateRef = this.maciStateRef;
|
|
936
936
|
copied.tallyResult = this.tallyResult.map((x) => BigInt(x.toString()));
|
|
937
|
-
copied.
|
|
937
|
+
copied.perVoteOptionSpentVoiceCredits = this.perVoteOptionSpentVoiceCredits.map((x) => BigInt(x.toString()));
|
|
938
938
|
copied.numBatchesProcessed = Number(this.numBatchesProcessed.toString());
|
|
939
939
|
copied.numBatchesTallied = Number(this.numBatchesTallied.toString());
|
|
940
940
|
copied.pollId = this.pollId;
|
|
@@ -956,34 +956,34 @@ class Poll {
|
|
|
956
956
|
copied.spentVoiceCreditSubtotalSalts[k] = BigInt(this.spentVoiceCreditSubtotalSalts[k].toString());
|
|
957
957
|
});
|
|
958
958
|
// update the number of signups
|
|
959
|
-
copied.
|
|
959
|
+
copied.setTotalSignups(this.totalSignups);
|
|
960
960
|
return copied;
|
|
961
961
|
};
|
|
962
962
|
/**
|
|
963
963
|
* Check if the Poll object is equal to another Poll object.
|
|
964
|
-
* @param
|
|
964
|
+
* @param poll - The Poll object to compare.
|
|
965
965
|
* @returns True if the two Poll objects are equal, false otherwise.
|
|
966
966
|
*/
|
|
967
|
-
this.equals = (
|
|
968
|
-
const result = this.coordinatorKeypair.equals(
|
|
969
|
-
this.treeDepths.intStateTreeDepth ===
|
|
970
|
-
this.treeDepths.voteOptionTreeDepth ===
|
|
971
|
-
this.batchSizes.tallyBatchSize ===
|
|
972
|
-
this.batchSizes.messageBatchSize ===
|
|
973
|
-
this.maxVoteOptions ===
|
|
974
|
-
this.messages.length ===
|
|
975
|
-
this.
|
|
976
|
-
this.
|
|
967
|
+
this.equals = (poll) => {
|
|
968
|
+
const result = this.coordinatorKeypair.equals(poll.coordinatorKeypair) &&
|
|
969
|
+
this.treeDepths.intStateTreeDepth === poll.treeDepths.intStateTreeDepth &&
|
|
970
|
+
this.treeDepths.voteOptionTreeDepth === poll.treeDepths.voteOptionTreeDepth &&
|
|
971
|
+
this.batchSizes.tallyBatchSize === poll.batchSizes.tallyBatchSize &&
|
|
972
|
+
this.batchSizes.messageBatchSize === poll.batchSizes.messageBatchSize &&
|
|
973
|
+
this.maxVoteOptions === poll.maxVoteOptions &&
|
|
974
|
+
this.messages.length === poll.messages.length &&
|
|
975
|
+
this.encryptionPublicKeys.length === poll.encryptionPublicKeys.length &&
|
|
976
|
+
this.totalSignups === poll.totalSignups;
|
|
977
977
|
if (!result) {
|
|
978
978
|
return false;
|
|
979
979
|
}
|
|
980
980
|
for (let i = 0; i < this.messages.length; i += 1) {
|
|
981
|
-
if (!this.messages[i].equals(
|
|
981
|
+
if (!this.messages[i].equals(poll.messages[i])) {
|
|
982
982
|
return false;
|
|
983
983
|
}
|
|
984
984
|
}
|
|
985
|
-
for (let i = 0; i < this.
|
|
986
|
-
if (!this.
|
|
985
|
+
for (let i = 0; i < this.encryptionPublicKeys.length; i += 1) {
|
|
986
|
+
if (!this.encryptionPublicKeys[i].equals(poll.encryptionPublicKeys[i])) {
|
|
987
987
|
return false;
|
|
988
988
|
}
|
|
989
989
|
}
|
|
@@ -994,20 +994,20 @@ class Poll {
|
|
|
994
994
|
* @param serializedPrivateKey - the serialized private key
|
|
995
995
|
*/
|
|
996
996
|
this.setCoordinatorKeypair = (serializedPrivateKey) => {
|
|
997
|
-
this.coordinatorKeypair = new domainobjs_1.Keypair(domainobjs_1.
|
|
997
|
+
this.coordinatorKeypair = new domainobjs_1.Keypair(domainobjs_1.PrivateKey.deserialize(serializedPrivateKey));
|
|
998
998
|
};
|
|
999
999
|
/**
|
|
1000
1000
|
* Set the number of signups to match the ones from the contract
|
|
1001
|
-
* @param
|
|
1001
|
+
* @param totalSignups - the number of signups
|
|
1002
1002
|
*/
|
|
1003
|
-
this.
|
|
1004
|
-
this.
|
|
1003
|
+
this.setTotalSignups = (totalSignups) => {
|
|
1004
|
+
this.totalSignups = totalSignups;
|
|
1005
1005
|
};
|
|
1006
1006
|
/**
|
|
1007
1007
|
* Get the number of signups
|
|
1008
1008
|
* @returns The number of signups
|
|
1009
1009
|
*/
|
|
1010
|
-
this.
|
|
1010
|
+
this.gettotalSignups = () => this.totalSignups;
|
|
1011
1011
|
this.pollEndTimestamp = pollEndTimestamp;
|
|
1012
1012
|
this.coordinatorKeypair = coordinatorKeypair;
|
|
1013
1013
|
this.treeDepths = treeDepths;
|
|
@@ -1023,7 +1023,7 @@ class Poll {
|
|
|
1023
1023
|
this.currentMessageBatchIndex = 0;
|
|
1024
1024
|
this.pollNullifiers = new Map();
|
|
1025
1025
|
this.tallyResult = new Array(this.maxVoteOptions).fill(0n);
|
|
1026
|
-
this.
|
|
1026
|
+
this.perVoteOptionSpentVoiceCredits = new Array(this.maxVoteOptions).fill(0n);
|
|
1027
1027
|
// we put a blank state leaf to prevent a DoS attack
|
|
1028
1028
|
this.emptyBallot = domainobjs_1.Ballot.genBlankBallot(this.maxVoteOptions, treeDepths.voteOptionTreeDepth);
|
|
1029
1029
|
this.ballots.push(this.emptyBallot);
|
|
@@ -1043,13 +1043,13 @@ class Poll {
|
|
|
1043
1043
|
messages: this.messages.map((message) => message.toJSON()),
|
|
1044
1044
|
commands: this.commands.map((command) => command.toJSON()),
|
|
1045
1045
|
ballots: this.ballots.map((ballot) => ballot.toJSON()),
|
|
1046
|
-
|
|
1046
|
+
encryptionPublicKeys: this.encryptionPublicKeys.map((encryptionPublicKey) => encryptionPublicKey.serialize()),
|
|
1047
1047
|
currentMessageBatchIndex: this.currentMessageBatchIndex,
|
|
1048
|
-
|
|
1048
|
+
publicKeys: this.publicKeys.map((leaf) => leaf.toJSON()),
|
|
1049
1049
|
pollStateLeaves: this.pollStateLeaves.map((leaf) => leaf.toJSON()),
|
|
1050
1050
|
results: this.tallyResult.map((result) => result.toString()),
|
|
1051
1051
|
numBatchesProcessed: this.numBatchesProcessed,
|
|
1052
|
-
|
|
1052
|
+
totalSignups: this.totalSignups.toString(),
|
|
1053
1053
|
chainHash: this.chainHash.toString(),
|
|
1054
1054
|
pollNullifiers: [...this.pollNullifiers.keys()].map((nullifier) => nullifier.toString()),
|
|
1055
1055
|
batchHashes: this.batchHashes.map((batchHash) => batchHash.toString()),
|
|
@@ -1066,9 +1066,9 @@ class Poll {
|
|
|
1066
1066
|
// set all properties
|
|
1067
1067
|
poll.pollStateLeaves = json.pollStateLeaves.map((leaf) => domainobjs_1.StateLeaf.fromJSON(leaf));
|
|
1068
1068
|
poll.ballots = json.ballots.map((ballot) => domainobjs_1.Ballot.fromJSON(ballot));
|
|
1069
|
-
poll.
|
|
1069
|
+
poll.encryptionPublicKeys = json.encryptionPublicKeys.map((key) => domainobjs_1.PublicKey.deserialize(key));
|
|
1070
1070
|
poll.messages = json.messages.map((message) => domainobjs_1.Message.fromJSON(message));
|
|
1071
|
-
poll.commands = json.commands.map((command) => domainobjs_1.
|
|
1071
|
+
poll.commands = json.commands.map((command) => domainobjs_1.VoteCommand.fromJSON(command));
|
|
1072
1072
|
poll.tallyResult = json.results.map((result) => BigInt(result));
|
|
1073
1073
|
poll.currentMessageBatchIndex = json.currentMessageBatchIndex;
|
|
1074
1074
|
poll.numBatchesProcessed = json.numBatchesProcessed;
|
|
@@ -1076,7 +1076,7 @@ class Poll {
|
|
|
1076
1076
|
poll.batchHashes = json.batchHashes.map((batchHash) => BigInt(batchHash));
|
|
1077
1077
|
poll.pollNullifiers = new Map(json.pollNullifiers.map((nullifier) => [BigInt(nullifier), true]));
|
|
1078
1078
|
// copy maci state
|
|
1079
|
-
poll.updatePoll(BigInt(json.
|
|
1079
|
+
poll.updatePoll(BigInt(json.totalSignups));
|
|
1080
1080
|
return poll;
|
|
1081
1081
|
}
|
|
1082
1082
|
}
|