@maci-protocol/core 0.0.0-ci.ab3b4c1 → 0.0.0-ci.acada81
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/README.md +3 -3
- package/build/ts/MaciState.d.ts +2 -2
- package/build/ts/MaciState.d.ts.map +1 -1
- package/build/ts/MaciState.js.map +1 -1
- package/build/ts/Poll.d.ts +12 -9
- package/build/ts/Poll.d.ts.map +1 -1
- package/build/ts/Poll.js +90 -54
- package/build/ts/Poll.js.map +1 -1
- package/build/ts/index.d.ts +1 -1
- package/build/ts/index.d.ts.map +1 -1
- package/build/ts/utils/types.d.ts +11 -6
- package/build/ts/utils/types.d.ts.map +1 -1
- package/build/ts/utils/utils.d.ts +1 -1
- package/build/ts/utils/utils.js +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ contracts in discrete components which are easy to test.
|
|
|
15
15
|
|
|
16
16
|
To this end, this submodule exposes a `MaciState` class and a `Poll` class.
|
|
17
17
|
Developers should instantiate objects from these classes to test MACI. For
|
|
18
|
-
instance, [`MACI.test.ts`](https://github.com/privacy-scaling-explorations/maci/blob/
|
|
18
|
+
instance, [`MACI.test.ts`](https://github.com/privacy-scaling-explorations/maci/blob/main/packages/contracts/tests/MACI.test.ts) creates a
|
|
19
19
|
`MaciState` object and every time it interacts with the MACI smart contract, it
|
|
20
20
|
mirrors said interaction on the `MaciState` and `Poll`. As such, the developer
|
|
21
21
|
can then use their helper functions like `maciState.signUp()`,
|
|
@@ -34,8 +34,8 @@ In testing, whenever a test suite submits a `signUp()` transaction, it should
|
|
|
34
34
|
call `maciState.signUp()` as well, so that the off-chain representation of MACI
|
|
35
35
|
is kept up to date.
|
|
36
36
|
|
|
37
|
-
In production, `
|
|
38
|
-
[`
|
|
37
|
+
In production, `generateMaciStateFromContract()` in
|
|
38
|
+
[`generateMaciState.ts`](https://github.com/privacy-scaling-explorations/maci/blob/main/packages/contracts/ts/generateMaciState.ts) uses this function when it
|
|
39
39
|
scans a MACI contract's event log for signups, so as to bring its `MaciState`
|
|
40
40
|
instance up to date.
|
|
41
41
|
|
package/build/ts/MaciState.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { IncrementalQuinTree } from "@maci-protocol/crypto";
|
|
1
|
+
import { type IncrementalQuinTree } from "@maci-protocol/crypto";
|
|
2
2
|
import { PublicKey, type Keypair } from "@maci-protocol/domainobjs";
|
|
3
3
|
import type { IJsonMaciState, IMaciState, ITreeDepths } from "./utils/types";
|
|
4
4
|
import { Poll } from "./Poll";
|
|
5
|
-
import { EMode } from "./utils/constants";
|
|
5
|
+
import { type EMode } from "./utils/constants";
|
|
6
6
|
/**
|
|
7
7
|
* A representation of the MACI contract.
|
|
8
8
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MaciState.d.ts","sourceRoot":"","sources":["../../ts/MaciState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"MaciState.d.ts","sourceRoot":"","sources":["../../ts/MaciState.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,SAAS,EAAE,KAAK,OAAO,EAAU,MAAM,2BAA2B,CAAC;AAE5E,OAAO,KAAK,EAAE,cAAc,EAAa,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAExF,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,OAAO,EAAE,KAAK,KAAK,EAAoB,MAAM,mBAAmB,CAAC;AAEjE;;GAEG;AACH,qBAAa,SAAU,YAAW,UAAU;IAE1C,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAA2B;IAGnD,UAAU,EAAE,SAAS,EAAE,CAAM;IAG7B,cAAc,EAAE,MAAM,CAAC;IAGvB,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAEhC,YAAY,SAAK;IAGjB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B,yBAAyB,CAAC,EAAE,MAAM,CAAC;IAEnC;;;OAGG;gBACS,cAAc,EAAE,MAAM;IAUlC;;;;OAIG;IACH,MAAM,CAAC,SAAS,EAAE,SAAS,GAAG,MAAM;IAOpC;;;;;;;;;OASG;IACH,UAAU,CACR,gBAAgB,EAAE,MAAM,EACxB,UAAU,EAAE,WAAW,EACvB,gBAAgB,EAAE,MAAM,EACxB,kBAAkB,EAAE,OAAO,EAC3B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,KAAK,GACV,MAAM;IAkBT;;OAEG;IACH,cAAc,IAAI,IAAI;IAItB;;;OAGG;IACH,IAAI,QAAO,SAAS,CAQlB;IAEF;;;;OAIG;IACH,MAAM,GAAI,GAAG,SAAS,KAAG,OAAO,CAsB9B;IAEF;;;OAGG;IACH,MAAM,IAAI,cAAc;IAWxB;;;;OAIG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,SAAS;CAgBjD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MaciState.js","sourceRoot":"","sources":["../../ts/MaciState.ts"],"names":[],"mappings":";;;AACA,0DAA4E;AAI5E,iCAA8B;AAC9B,
|
|
1
|
+
{"version":3,"file":"MaciState.js","sourceRoot":"","sources":["../../ts/MaciState.ts"],"names":[],"mappings":"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"}
|
package/build/ts/Poll.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { IncrementalQuinTree } from "@maci-protocol/crypto";
|
|
2
|
-
import { VoteCommand, Keypair, Ballot, PublicKey, Message, StateLeaf } from "@maci-protocol/domainobjs";
|
|
2
|
+
import { VoteCommand, Keypair, Ballot, PublicKey, Message, StateLeaf, VoteCounts } from "@maci-protocol/domainobjs";
|
|
3
3
|
import { LeanIMT } from "@zk-kit/lean-imt";
|
|
4
|
-
import type { ITreeDepths, IBatchSizes, IPoll, IJsonPoll, IProcessMessagesOutput, ITallyCircuitInputs, IProcessMessagesCircuitInputs, IPollJoiningCircuitInputs, IJoiningCircuitArgs } from "./index";
|
|
5
4
|
import type { MaciState } from "./MaciState";
|
|
6
|
-
import type { IGetVoiceCreditsLeft, IJoinedCircuitArgs, IPollJoinedCircuitInputs } from "./utils/types";
|
|
5
|
+
import type { ITreeDepths, IBatchSizes, IPoll, IJsonPoll, IProcessMessagesOutput, IVoteTallyCircuitInputs, IProcessMessagesCircuitInputs, IPollJoiningCircuitInputs, IJoiningCircuitArgs, IGetVoiceCreditsLeft, IJoinedCircuitArgs, IPollJoinedCircuitInputs } from "./utils/types";
|
|
7
6
|
import { EMode } from "./utils/constants";
|
|
8
7
|
/**
|
|
9
8
|
* A representation of the Poll contract.
|
|
@@ -18,13 +17,15 @@ export declare class Poll implements IPoll {
|
|
|
18
17
|
pollEndTimestamp: bigint;
|
|
19
18
|
ballots: Ballot[];
|
|
20
19
|
ballotTree?: IncrementalQuinTree;
|
|
20
|
+
voteCounts: VoteCounts[];
|
|
21
|
+
voteCountsTree?: IncrementalQuinTree;
|
|
21
22
|
messages: Message[];
|
|
22
23
|
commands: VoteCommand[];
|
|
23
24
|
encryptionPublicKeys: PublicKey[];
|
|
24
25
|
stateCopied: boolean;
|
|
25
26
|
publicKeys: PublicKey[];
|
|
26
27
|
stateTree?: LeanIMT;
|
|
27
|
-
|
|
28
|
+
totalBatchesProcessed: number;
|
|
28
29
|
currentMessageBatchIndex: number;
|
|
29
30
|
maciStateRef: MaciState;
|
|
30
31
|
pollId: bigint;
|
|
@@ -37,7 +38,9 @@ export declare class Poll implements IPoll {
|
|
|
37
38
|
numBatchesTallied: number;
|
|
38
39
|
totalSpentVoiceCredits: bigint;
|
|
39
40
|
emptyBallot: Ballot;
|
|
40
|
-
emptyBallotHash
|
|
41
|
+
emptyBallotHash: bigint;
|
|
42
|
+
emptyVoteCounts: VoteCounts;
|
|
43
|
+
emptyVoteCountsHash: bigint;
|
|
41
44
|
chainHash: bigint;
|
|
42
45
|
batchHashes: bigint[];
|
|
43
46
|
pollStateLeaves: StateLeaf[];
|
|
@@ -163,16 +166,16 @@ export declare class Poll implements IPoll {
|
|
|
163
166
|
/**
|
|
164
167
|
* This method tallies a ballots and updates the tally results.
|
|
165
168
|
*
|
|
166
|
-
* @returns the circuit inputs for the
|
|
169
|
+
* @returns the circuit inputs for the VoteTally circuit.
|
|
167
170
|
*/
|
|
168
|
-
tallyVotes: () =>
|
|
171
|
+
tallyVotes: () => IVoteTallyCircuitInputs;
|
|
169
172
|
/**
|
|
170
173
|
* This method generates a commitment to the total spent voice credits.
|
|
171
174
|
*
|
|
172
175
|
* This is the hash of the total spent voice credits and a salt, computed as Poseidon([totalCredits, _salt]).
|
|
173
176
|
* @param salt - The salt used in the hash function.
|
|
174
177
|
* @param ballotsToCount - The number of ballots to count for the calculation.
|
|
175
|
-
* @param mode - Voting mode, default QV.
|
|
178
|
+
* @param mode - Voting mode, default is QV.
|
|
176
179
|
* @returns Returns the hash of the total spent voice credits and a salt, computed as Poseidon([totalCredits, _salt]).
|
|
177
180
|
*/
|
|
178
181
|
private generateSpentVoiceCreditSubtotalCommitment;
|
|
@@ -223,6 +226,6 @@ export declare class Poll implements IPoll {
|
|
|
223
226
|
* Get the number of signups
|
|
224
227
|
* @returns The number of signups
|
|
225
228
|
*/
|
|
226
|
-
|
|
229
|
+
getTotalSignups: () => bigint;
|
|
227
230
|
}
|
|
228
231
|
//# sourceMappingURL=Poll.d.ts.map
|
package/build/ts/Poll.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Poll.d.ts","sourceRoot":"","sources":["../../ts/Poll.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EAYpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,WAAW,EACX,OAAO,EACP,MAAM,EACN,SAAS,EAET,OAAO,EACP,SAAS,
|
|
1
|
+
{"version":3,"file":"Poll.d.ts","sourceRoot":"","sources":["../../ts/Poll.ts"],"names":[],"mappings":"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"}
|
package/build/ts/Poll.js
CHANGED
|
@@ -26,13 +26,14 @@ class Poll {
|
|
|
26
26
|
*/
|
|
27
27
|
constructor(pollEndTimestamp, coordinatorKeypair, treeDepths, batchSizes, maciStateRef, voteOptions, mode) {
|
|
28
28
|
this.ballots = [];
|
|
29
|
+
this.voteCounts = [];
|
|
29
30
|
this.messages = [];
|
|
30
31
|
this.commands = [];
|
|
31
32
|
this.encryptionPublicKeys = [];
|
|
32
33
|
this.stateCopied = false;
|
|
33
34
|
this.publicKeys = [domainobjs_1.padKey];
|
|
34
35
|
// For message processing
|
|
35
|
-
this.
|
|
36
|
+
this.totalBatchesProcessed = 0;
|
|
36
37
|
this.sbSalts = {};
|
|
37
38
|
this.resultRootSalts = {};
|
|
38
39
|
this.perVoteOptionSpentVoiceCreditsRootSalts = {};
|
|
@@ -103,7 +104,6 @@ class Poll {
|
|
|
103
104
|
this.pollStateTree?.insert(stateLeaf.hash());
|
|
104
105
|
});
|
|
105
106
|
// Create as many ballots as state leaves
|
|
106
|
-
this.emptyBallotHash = this.emptyBallot.hash();
|
|
107
107
|
this.ballotTree = new crypto_1.IncrementalQuinTree(Number(this.treeDepths.stateTreeDepth), this.emptyBallotHash, constants_1.STATE_TREE_ARITY, crypto_1.hash2);
|
|
108
108
|
this.ballotTree.insert(this.emptyBallotHash);
|
|
109
109
|
// we fill the ballotTree with empty ballots hashes to match the number of signups in the tree
|
|
@@ -111,6 +111,13 @@ class Poll {
|
|
|
111
111
|
this.ballotTree.insert(this.emptyBallotHash);
|
|
112
112
|
this.ballots.push(this.emptyBallot);
|
|
113
113
|
}
|
|
114
|
+
this.voteCountsTree = new crypto_1.IncrementalQuinTree(Number(this.treeDepths.stateTreeDepth), this.emptyVoteCountsHash, constants_1.STATE_TREE_ARITY, crypto_1.hash2);
|
|
115
|
+
this.voteCountsTree.insert(this.emptyVoteCountsHash);
|
|
116
|
+
const emptyVoteCounts = domainobjs_1.VoteCounts.generateBlank(this.maxVoteOptions, this.treeDepths.voteOptionTreeDepth);
|
|
117
|
+
while (this.voteCounts.length < this.publicKeys.length) {
|
|
118
|
+
this.voteCountsTree.insert(this.emptyVoteCountsHash);
|
|
119
|
+
this.voteCounts.push(emptyVoteCounts);
|
|
120
|
+
}
|
|
114
121
|
this.stateCopied = true;
|
|
115
122
|
};
|
|
116
123
|
/**
|
|
@@ -159,7 +166,7 @@ class Poll {
|
|
|
159
166
|
if (voiceCreditsLeft < 0n) {
|
|
160
167
|
throw new errors_1.ProcessMessageError(errors_1.ProcessMessageErrors.InsufficientVoiceCredits);
|
|
161
168
|
}
|
|
162
|
-
// If there are some voice credits left for full
|
|
169
|
+
// If there are some voice credits left for full credits mode, do nothing
|
|
163
170
|
if (this.mode === constants_1.EMode.FULL && voiceCreditsLeft > 0n) {
|
|
164
171
|
throw new errors_1.ProcessMessageError(errors_1.ProcessMessageErrors.InvalidVoiceCredits);
|
|
165
172
|
}
|
|
@@ -180,17 +187,17 @@ class Poll {
|
|
|
180
187
|
// calculate the path elements for the state tree given the original state tree (before any changes)
|
|
181
188
|
// changes could effectively be made by this new vote - either a key change or vote change
|
|
182
189
|
// would result in a different state leaf
|
|
183
|
-
const { pathElements: originalStateLeafPathElements } = this.pollStateTree.
|
|
190
|
+
const { pathElements: originalStateLeafPathElements } = this.pollStateTree.generateProof(Number(stateLeafIndex));
|
|
184
191
|
// calculate the path elements for the ballot tree given the original ballot tree (before any changes)
|
|
185
192
|
// changes could effectively be made by this new ballot
|
|
186
|
-
const { pathElements: originalBallotPathElements } = this.ballotTree.
|
|
193
|
+
const { pathElements: originalBallotPathElements } = this.ballotTree.generateProof(Number(stateLeafIndex));
|
|
187
194
|
// create a new quinary tree where we insert the votes of the origin (up until this message is processed) ballot
|
|
188
195
|
const voteTree = new crypto_1.IncrementalQuinTree(this.treeDepths.voteOptionTreeDepth, 0n, constants_1.VOTE_OPTION_TREE_ARITY, crypto_1.hash5);
|
|
189
196
|
for (let i = 0; i < this.ballots[0].votes.length; i += 1) {
|
|
190
197
|
voteTree.insert(ballot.votes[i]);
|
|
191
198
|
}
|
|
192
199
|
// calculate the path elements for the vote option tree given the original vote option tree (before any changes)
|
|
193
|
-
const { pathElements: originalVoteWeightsPathElements } = voteTree.
|
|
200
|
+
const { pathElements: originalVoteWeightsPathElements } = voteTree.generateProof(voteOptionIndex);
|
|
194
201
|
// we return the data which is then to be used in the processMessage circuit
|
|
195
202
|
// to generate a proof of processing
|
|
196
203
|
return {
|
|
@@ -270,14 +277,7 @@ class Poll {
|
|
|
270
277
|
// calculate the path elements for the state tree given the original state tree
|
|
271
278
|
const { siblings, index } = this.stateTree.generateProof(Number(stateLeafIndex));
|
|
272
279
|
const siblingsLength = siblings.length;
|
|
273
|
-
// The index must be converted to a list of indices, 1 for each tree level.
|
|
274
|
-
// The circuit tree depth is this.treeDepths.stateTreeDepth, so the number of siblings must be this.treeDepths.stateTreeDepth,
|
|
275
|
-
// even if the tree depth is actually 3. The missing siblings can be set to 0, as they
|
|
276
|
-
// won't be used to calculate the root in the circuit.
|
|
277
|
-
const indices = [];
|
|
278
280
|
for (let i = 0; i < this.treeDepths.stateTreeDepth; i += 1) {
|
|
279
|
-
// eslint-disable-next-line no-bitwise
|
|
280
|
-
indices.push(BigInt((index >> i) & 1));
|
|
281
281
|
if (i >= siblingsLength) {
|
|
282
282
|
siblings[i] = BigInt(0);
|
|
283
283
|
}
|
|
@@ -294,7 +294,7 @@ class Poll {
|
|
|
294
294
|
privateKey: maciPrivateKey.asCircuitInputs(),
|
|
295
295
|
pollPublicKey: pollPublicKey.asCircuitInputs(),
|
|
296
296
|
siblings: siblingsArray,
|
|
297
|
-
|
|
297
|
+
index: BigInt(index),
|
|
298
298
|
nullifier,
|
|
299
299
|
stateRoot,
|
|
300
300
|
actualStateTreeDepth,
|
|
@@ -309,19 +309,18 @@ class Poll {
|
|
|
309
309
|
*/
|
|
310
310
|
this.joinedCircuitInputs = ({ maciPrivateKey, stateLeafIndex, voiceCreditsBalance, }) => {
|
|
311
311
|
// calculate the path elements for the state tree given the original state tree
|
|
312
|
-
const { root: stateRoot, pathElements, pathIndices } = this.pollStateTree.
|
|
312
|
+
const { root: stateRoot, pathElements, pathIndices } = this.pollStateTree.generateProof(Number(stateLeafIndex));
|
|
313
313
|
const elementsLength = pathIndices.length;
|
|
314
314
|
for (let i = 0; i < this.treeDepths.stateTreeDepth; i += 1) {
|
|
315
315
|
if (i >= elementsLength) {
|
|
316
316
|
pathElements[i] = [0n];
|
|
317
|
-
pathIndices[i] = 0;
|
|
318
317
|
}
|
|
319
318
|
}
|
|
320
319
|
const circuitInputs = {
|
|
321
320
|
privateKey: maciPrivateKey.asCircuitInputs(),
|
|
322
321
|
pathElements: pathElements.map((item) => item.toString()),
|
|
323
322
|
voiceCreditsBalance: voiceCreditsBalance.toString(),
|
|
324
|
-
|
|
323
|
+
index: BigInt(stateLeafIndex),
|
|
325
324
|
actualStateTreeDepth: BigInt(this.actualStateTreeDepth),
|
|
326
325
|
stateRoot,
|
|
327
326
|
};
|
|
@@ -346,7 +345,7 @@ class Poll {
|
|
|
346
345
|
if (this.messages.length > batchSize && this.messages.length % batchSize > 0) {
|
|
347
346
|
totalBatches += 1;
|
|
348
347
|
}
|
|
349
|
-
return this.
|
|
348
|
+
return this.totalBatchesProcessed < totalBatches;
|
|
350
349
|
};
|
|
351
350
|
/**
|
|
352
351
|
* Process _batchSize messages starting from the saved index. This
|
|
@@ -365,7 +364,7 @@ class Poll {
|
|
|
365
364
|
this.processMessages = (pollId, quiet = true) => {
|
|
366
365
|
(0, assert_1.default)(this.hasUnprocessedMessages(), "No more messages to process");
|
|
367
366
|
const batchSize = this.batchSizes.messageBatchSize;
|
|
368
|
-
if (this.
|
|
367
|
+
if (this.totalBatchesProcessed === 0) {
|
|
369
368
|
// Prevent other polls from being processed until this poll has
|
|
370
369
|
// been fully processed
|
|
371
370
|
this.maciStateRef.pollBeingProcessed = true;
|
|
@@ -455,11 +454,11 @@ class Poll {
|
|
|
455
454
|
// if the state leaf index is valid then use it
|
|
456
455
|
if (stateLeafIndex < this.pollStateLeaves.length) {
|
|
457
456
|
currentStateLeaves.unshift(this.pollStateLeaves[Number(stateLeafIndex)].copy());
|
|
458
|
-
currentStateLeavesPathElements.unshift(this.pollStateTree.
|
|
457
|
+
currentStateLeavesPathElements.unshift(this.pollStateTree.generateProof(Number(stateLeafIndex)).pathElements);
|
|
459
458
|
// copy the ballot
|
|
460
459
|
const ballot = this.ballots[Number(stateLeafIndex)].copy();
|
|
461
460
|
currentBallots.unshift(ballot);
|
|
462
|
-
currentBallotsPathElements.unshift(this.ballotTree.
|
|
461
|
+
currentBallotsPathElements.unshift(this.ballotTree.generateProof(Number(stateLeafIndex)).pathElements);
|
|
463
462
|
// @note we check that command.voteOptionIndex is valid so < voteOptions
|
|
464
463
|
// this might be unnecessary but we do it to prevent a possible DoS attack
|
|
465
464
|
// from voters who could potentially encrypt a message in such as way that
|
|
@@ -473,7 +472,7 @@ class Poll {
|
|
|
473
472
|
voteTree.insert(ballot.votes[j]);
|
|
474
473
|
}
|
|
475
474
|
// get the path elements for the first vote leaf
|
|
476
|
-
currentVoteWeightsPathElements.unshift(voteTree.
|
|
475
|
+
currentVoteWeightsPathElements.unshift(voteTree.generateProof(Number(command.voteOptionIndex)).pathElements);
|
|
477
476
|
}
|
|
478
477
|
else {
|
|
479
478
|
currentVoteWeights.unshift(ballot.votes[0]);
|
|
@@ -484,22 +483,22 @@ class Poll {
|
|
|
484
483
|
voteTree.insert(ballot.votes[j]);
|
|
485
484
|
}
|
|
486
485
|
// get the path elements for the first vote leaf
|
|
487
|
-
currentVoteWeightsPathElements.unshift(voteTree.
|
|
486
|
+
currentVoteWeightsPathElements.unshift(voteTree.generateProof(0).pathElements);
|
|
488
487
|
}
|
|
489
488
|
}
|
|
490
489
|
else {
|
|
491
490
|
// just use state leaf index 0
|
|
492
491
|
currentStateLeaves.unshift(this.pollStateLeaves[0].copy());
|
|
493
|
-
currentStateLeavesPathElements.unshift(this.pollStateTree.
|
|
492
|
+
currentStateLeavesPathElements.unshift(this.pollStateTree.generateProof(0).pathElements);
|
|
494
493
|
currentBallots.unshift(this.ballots[0].copy());
|
|
495
|
-
currentBallotsPathElements.unshift(this.ballotTree.
|
|
494
|
+
currentBallotsPathElements.unshift(this.ballotTree.generateProof(0).pathElements);
|
|
496
495
|
// Since the command is invalid, we use a zero vote weight
|
|
497
496
|
currentVoteWeights.unshift(this.ballots[0].votes[0]);
|
|
498
497
|
// create a new quinary tree and add an empty vote
|
|
499
498
|
const voteTree = new crypto_1.IncrementalQuinTree(this.treeDepths.voteOptionTreeDepth, 0n, constants_1.VOTE_OPTION_TREE_ARITY, crypto_1.hash5);
|
|
500
499
|
voteTree.insert(this.ballots[0].votes[0]);
|
|
501
500
|
// get the path elements for this empty vote weight leaf
|
|
502
|
-
currentVoteWeightsPathElements.unshift(voteTree.
|
|
501
|
+
currentVoteWeightsPathElements.unshift(voteTree.generateProof(0).pathElements);
|
|
503
502
|
}
|
|
504
503
|
}
|
|
505
504
|
else {
|
|
@@ -510,17 +509,17 @@ class Poll {
|
|
|
510
509
|
else {
|
|
511
510
|
// Since we don't have a command at that position, use a blank state leaf
|
|
512
511
|
currentStateLeaves.unshift(this.pollStateLeaves[0].copy());
|
|
513
|
-
currentStateLeavesPathElements.unshift(this.pollStateTree.
|
|
512
|
+
currentStateLeavesPathElements.unshift(this.pollStateTree.generateProof(0).pathElements);
|
|
514
513
|
// since the command is invliad we use the blank ballot
|
|
515
514
|
currentBallots.unshift(this.ballots[0].copy());
|
|
516
|
-
currentBallotsPathElements.unshift(this.ballotTree.
|
|
515
|
+
currentBallotsPathElements.unshift(this.ballotTree.generateProof(0).pathElements);
|
|
517
516
|
// Since the command is invalid, we use a zero vote weight
|
|
518
517
|
currentVoteWeights.unshift(this.ballots[0].votes[0]);
|
|
519
518
|
// create a new quinary tree and add an empty vote
|
|
520
519
|
const voteTree = new crypto_1.IncrementalQuinTree(this.treeDepths.voteOptionTreeDepth, 0n, constants_1.VOTE_OPTION_TREE_ARITY, crypto_1.hash5);
|
|
521
520
|
voteTree.insert(this.ballots[0].votes[0]);
|
|
522
521
|
// get the path elements for this empty vote weight leaf
|
|
523
|
-
currentVoteWeightsPathElements.unshift(voteTree.
|
|
522
|
+
currentVoteWeightsPathElements.unshift(voteTree.generateProof(0).pathElements);
|
|
524
523
|
}
|
|
525
524
|
}
|
|
526
525
|
// store the data in the circuit inputs object
|
|
@@ -538,7 +537,7 @@ class Poll {
|
|
|
538
537
|
circuitInputs.currentVoteWeights = currentVoteWeights;
|
|
539
538
|
circuitInputs.currentVoteWeightsPathElements = currentVoteWeightsPathElements;
|
|
540
539
|
// record that we processed one batch
|
|
541
|
-
this.
|
|
540
|
+
this.totalBatchesProcessed += 1;
|
|
542
541
|
if (this.currentMessageBatchIndex > 0) {
|
|
543
542
|
this.currentMessageBatchIndex -= 1;
|
|
544
543
|
}
|
|
@@ -557,7 +556,7 @@ class Poll {
|
|
|
557
556
|
circuitInputs.newSbCommitment = (0, crypto_1.hash3)([newStateRoot, newBallotRoot, newSbSalt]);
|
|
558
557
|
const coordinatorPublicKeyHash = this.coordinatorKeypair.publicKey.hash();
|
|
559
558
|
// If this is the last batch, release the lock
|
|
560
|
-
if (this.
|
|
559
|
+
if (this.totalBatchesProcessed * batchSize >= this.messages.length) {
|
|
561
560
|
this.maciStateRef.pollBeingProcessed = false;
|
|
562
561
|
}
|
|
563
562
|
// ensure we pass the dynamic tree depth
|
|
@@ -662,7 +661,7 @@ class Poll {
|
|
|
662
661
|
/**
|
|
663
662
|
* This method tallies a ballots and updates the tally results.
|
|
664
663
|
*
|
|
665
|
-
* @returns the circuit inputs for the
|
|
664
|
+
* @returns the circuit inputs for the VoteTally circuit.
|
|
666
665
|
*/
|
|
667
666
|
this.tallyVotes = () => {
|
|
668
667
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
@@ -695,6 +694,7 @@ class Poll {
|
|
|
695
694
|
// currentSpentVoiceCreditsCommitment,
|
|
696
695
|
// currentPerVoteOptionSpentVoiceCreditsCommitment
|
|
697
696
|
// ])
|
|
697
|
+
// TODO: use commitment for vote counts
|
|
698
698
|
const currentTallyCommitmentQv = this.mode !== constants_1.EMode.QV || batchStartIndex === 0
|
|
699
699
|
? 0n
|
|
700
700
|
: (0, crypto_1.hash3)([
|
|
@@ -706,39 +706,56 @@ class Poll {
|
|
|
706
706
|
? 0n
|
|
707
707
|
: (0, crypto_1.hashLeftRight)(currentResultsCommitment, currentSpentVoiceCreditsCommitment);
|
|
708
708
|
const currentTallyCommitment = currentTallyCommitmentNonQv || currentTallyCommitmentQv;
|
|
709
|
+
const startIndex = this.numBatchesTallied * batchSize;
|
|
710
|
+
const endIndex = this.numBatchesTallied * batchSize + batchSize;
|
|
709
711
|
const ballots = [];
|
|
712
|
+
const voteCounts = [];
|
|
713
|
+
const voteCountsData = [];
|
|
710
714
|
const currentResults = this.tallyResult.map((x) => BigInt(x.toString()));
|
|
711
715
|
const currentPerVoteOptionSpentVoiceCredits = this.perVoteOptionSpentVoiceCredits.map((x) => BigInt(x.toString()));
|
|
712
716
|
const currentSpentVoiceCreditSubtotal = BigInt(this.totalSpentVoiceCredits.toString());
|
|
713
717
|
// loop in normal order to tally the ballots one by one
|
|
714
|
-
for (let i =
|
|
718
|
+
for (let i = startIndex; i < endIndex; i += 1) {
|
|
715
719
|
// we stop if we have no more ballots to tally
|
|
716
720
|
if (i >= this.ballots.length) {
|
|
717
721
|
break;
|
|
718
722
|
}
|
|
719
723
|
// save to the local ballot array
|
|
720
724
|
ballots.push(this.ballots[i]);
|
|
725
|
+
const ballot = this.ballots[i];
|
|
726
|
+
const newVoteCounts = this.voteCounts[i].copy();
|
|
727
|
+
newVoteCounts.counts = ballot.votes.map((votes, voteOptionIndex) => this.voteCounts[i].counts[voteOptionIndex] + BigInt(votes !== 0n));
|
|
728
|
+
// save to the local vote counts array
|
|
729
|
+
this.voteCountsTree?.update(i, newVoteCounts.hash());
|
|
730
|
+
this.voteCounts[i] = newVoteCounts;
|
|
731
|
+
voteCounts.push(newVoteCounts);
|
|
732
|
+
voteCountsData.push(newVoteCounts.counts);
|
|
721
733
|
// for each possible vote option we loop and calculate
|
|
722
734
|
for (let j = 0; j < this.maxVoteOptions; j += 1) {
|
|
723
|
-
const
|
|
724
|
-
this.tallyResult[j] +=
|
|
735
|
+
const votes = this.ballots[i].votes[j];
|
|
736
|
+
this.tallyResult[j] += votes;
|
|
725
737
|
if (this.mode === constants_1.EMode.QV) {
|
|
726
738
|
// the per vote option spent voice credits will be the sum of the squares of the votes
|
|
727
|
-
this.perVoteOptionSpentVoiceCredits[j] +=
|
|
739
|
+
this.perVoteOptionSpentVoiceCredits[j] += votes * votes;
|
|
728
740
|
// the total spent voice credits will be the sum of the squares of the votes
|
|
729
|
-
this.totalSpentVoiceCredits +=
|
|
741
|
+
this.totalSpentVoiceCredits += votes * votes;
|
|
730
742
|
}
|
|
731
743
|
else {
|
|
732
744
|
// the total spent voice credits will be the sum of the votes
|
|
733
|
-
this.totalSpentVoiceCredits +=
|
|
745
|
+
this.totalSpentVoiceCredits += votes;
|
|
734
746
|
}
|
|
735
747
|
}
|
|
736
748
|
}
|
|
737
749
|
const emptyBallot = new domainobjs_1.Ballot(this.maxVoteOptions, this.treeDepths.voteOptionTreeDepth);
|
|
750
|
+
const emptyVoteCounts = new domainobjs_1.VoteCounts(this.maxVoteOptions, this.treeDepths.voteOptionTreeDepth);
|
|
738
751
|
// pad the ballots array
|
|
739
752
|
while (ballots.length < batchSize) {
|
|
740
753
|
ballots.push(emptyBallot);
|
|
741
754
|
}
|
|
755
|
+
// pad the vote counts array
|
|
756
|
+
while (voteCounts.length < batchSize) {
|
|
757
|
+
voteCounts.push(emptyVoteCounts);
|
|
758
|
+
}
|
|
742
759
|
// generate the new salts
|
|
743
760
|
const newResultsRootSalt = (0, crypto_1.generateRandomSalt)();
|
|
744
761
|
const newPerVoteOptionSpentVoiceCreditsRootSalt = (0, crypto_1.generateRandomSalt)();
|
|
@@ -760,10 +777,14 @@ class Poll {
|
|
|
760
777
|
// cache vars
|
|
761
778
|
const stateRoot = this.pollStateTree.root;
|
|
762
779
|
const ballotRoot = this.ballotTree.root;
|
|
780
|
+
const voteCountsRoot = this.voteCountsTree.root;
|
|
763
781
|
const sbSalt = this.sbSalts[this.currentMessageBatchIndex];
|
|
764
782
|
const sbCommitment = (0, crypto_1.hash3)([stateRoot, ballotRoot, sbSalt]);
|
|
765
|
-
const ballotSubrootProof = this.ballotTree?.
|
|
783
|
+
const ballotSubrootProof = this.ballotTree?.generateSubrootProof(batchStartIndex, batchStartIndex + batchSize);
|
|
784
|
+
const voteCountsSubrootProof = this.voteCountsTree?.generateSubrootProof(batchStartIndex, batchStartIndex + batchSize);
|
|
766
785
|
const votes = ballots.map((x) => x.votes);
|
|
786
|
+
// Don't include these inputs in the circuit inputs until individual vote counts are implemented
|
|
787
|
+
const excludedCircuitInputs = ["voteCountsData", "voteCountsPathElements", "voteCounts", "voteCountsRoot"];
|
|
767
788
|
const circuitInputs = (0, crypto_1.stringifyBigInts)((0, omit_1.default)({
|
|
768
789
|
stateRoot,
|
|
769
790
|
ballotRoot,
|
|
@@ -776,6 +797,10 @@ class Poll {
|
|
|
776
797
|
ballots: ballots.map((x) => x.asCircuitInputs()),
|
|
777
798
|
ballotPathElements: ballotSubrootProof.pathElements,
|
|
778
799
|
votes,
|
|
800
|
+
voteCountsRoot,
|
|
801
|
+
voteCounts: voteCounts.map((x) => x.asCircuitInputs()),
|
|
802
|
+
voteCountsPathElements: voteCountsSubrootProof.pathElements,
|
|
803
|
+
voteCountsData,
|
|
779
804
|
currentResults,
|
|
780
805
|
currentResultsRootSalt,
|
|
781
806
|
currentSpentVoiceCreditSubtotal,
|
|
@@ -787,11 +812,12 @@ class Poll {
|
|
|
787
812
|
newSpentVoiceCreditSubtotalSalt,
|
|
788
813
|
}, this.mode !== constants_1.EMode.QV
|
|
789
814
|
? [
|
|
815
|
+
...excludedCircuitInputs,
|
|
790
816
|
"currentPerVoteOptionSpentVoiceCredits",
|
|
791
817
|
"currentPerVoteOptionSpentVoiceCreditsRootSalt",
|
|
792
818
|
"newPerVoteOptionSpentVoiceCreditsRootSalt",
|
|
793
819
|
]
|
|
794
|
-
: []));
|
|
820
|
+
: [...excludedCircuitInputs]));
|
|
795
821
|
this.numBatchesTallied += 1;
|
|
796
822
|
return circuitInputs;
|
|
797
823
|
};
|
|
@@ -801,7 +827,7 @@ class Poll {
|
|
|
801
827
|
* This is the hash of the total spent voice credits and a salt, computed as Poseidon([totalCredits, _salt]).
|
|
802
828
|
* @param salt - The salt used in the hash function.
|
|
803
829
|
* @param ballotsToCount - The number of ballots to count for the calculation.
|
|
804
|
-
* @param mode - Voting mode, default QV.
|
|
830
|
+
* @param mode - Voting mode, default is QV.
|
|
805
831
|
* @returns Returns the hash of the total spent voice credits and a salt, computed as Poseidon([totalCredits, _salt]).
|
|
806
832
|
*/
|
|
807
833
|
this.generateSpentVoiceCreditSubtotalCommitment = (salt, ballotsToCount, mode = constants_1.EMode.QV) => {
|
|
@@ -811,8 +837,8 @@ class Poll {
|
|
|
811
837
|
break;
|
|
812
838
|
}
|
|
813
839
|
for (let j = 0; j < this.tallyResult.length; j += 1) {
|
|
814
|
-
const
|
|
815
|
-
subtotal += mode === constants_1.EMode.QV ?
|
|
840
|
+
const vote = BigInt(`${this.ballots[i].votes[j]}`);
|
|
841
|
+
subtotal += mode === constants_1.EMode.QV ? vote * vote : vote;
|
|
816
842
|
}
|
|
817
843
|
}
|
|
818
844
|
return (0, crypto_1.hashLeftRight)(subtotal, salt);
|
|
@@ -834,8 +860,8 @@ class Poll {
|
|
|
834
860
|
break;
|
|
835
861
|
}
|
|
836
862
|
for (let j = 0; j < this.tallyResult.length; j += 1) {
|
|
837
|
-
const
|
|
838
|
-
leaves[j] += mode === constants_1.EMode.QV ?
|
|
863
|
+
const vote = this.ballots[i].votes[j];
|
|
864
|
+
leaves[j] += mode === constants_1.EMode.QV ? vote * vote : vote;
|
|
839
865
|
}
|
|
840
866
|
}
|
|
841
867
|
return (0, crypto_1.generateTreeCommitment)(leaves, salt, this.treeDepths.voteOptionTreeDepth);
|
|
@@ -859,14 +885,18 @@ class Poll {
|
|
|
859
885
|
copied.commands = this.commands.map((x) => x.copy());
|
|
860
886
|
copied.ballots = this.ballots.map((x) => x.copy());
|
|
861
887
|
copied.encryptionPublicKeys = this.encryptionPublicKeys.map((x) => x.copy());
|
|
888
|
+
copied.voteCounts = this.voteCounts.map((x) => x.copy());
|
|
862
889
|
if (this.ballotTree) {
|
|
863
890
|
copied.ballotTree = this.ballotTree.copy();
|
|
864
891
|
}
|
|
892
|
+
if (this.voteCountsTree) {
|
|
893
|
+
copied.voteCountsTree = this.voteCountsTree.copy();
|
|
894
|
+
}
|
|
865
895
|
copied.currentMessageBatchIndex = this.currentMessageBatchIndex;
|
|
866
896
|
copied.maciStateRef = this.maciStateRef;
|
|
867
897
|
copied.tallyResult = this.tallyResult.map((x) => BigInt(x.toString()));
|
|
868
898
|
copied.perVoteOptionSpentVoiceCredits = this.perVoteOptionSpentVoiceCredits.map((x) => BigInt(x.toString()));
|
|
869
|
-
copied.
|
|
899
|
+
copied.totalBatchesProcessed = Number(this.totalBatchesProcessed.toString());
|
|
870
900
|
copied.numBatchesTallied = Number(this.numBatchesTallied.toString());
|
|
871
901
|
copied.pollId = this.pollId;
|
|
872
902
|
copied.totalSpentVoiceCredits = BigInt(this.totalSpentVoiceCredits.toString());
|
|
@@ -938,14 +968,14 @@ class Poll {
|
|
|
938
968
|
* Get the number of signups
|
|
939
969
|
* @returns The number of signups
|
|
940
970
|
*/
|
|
941
|
-
this.
|
|
971
|
+
this.getTotalSignups = () => this.totalSignups;
|
|
972
|
+
if (voteOptions > constants_1.VOTE_OPTION_TREE_ARITY ** treeDepths.voteOptionTreeDepth) {
|
|
973
|
+
throw new Error("Vote options cannot be greater than the number of leaves in the vote option tree");
|
|
974
|
+
}
|
|
942
975
|
this.pollEndTimestamp = pollEndTimestamp;
|
|
943
976
|
this.coordinatorKeypair = coordinatorKeypair;
|
|
944
977
|
this.treeDepths = treeDepths;
|
|
945
978
|
this.batchSizes = batchSizes;
|
|
946
|
-
if (voteOptions > constants_1.VOTE_OPTION_TREE_ARITY ** treeDepths.voteOptionTreeDepth) {
|
|
947
|
-
throw new Error("Vote options cannot be greater than the number of leaves in the vote option tree");
|
|
948
|
-
}
|
|
949
979
|
this.voteOptions = voteOptions;
|
|
950
980
|
this.maxVoteOptions = constants_1.VOTE_OPTION_TREE_ARITY ** treeDepths.voteOptionTreeDepth;
|
|
951
981
|
this.maciStateRef = maciStateRef;
|
|
@@ -957,8 +987,12 @@ class Poll {
|
|
|
957
987
|
this.tallyResult = new Array(this.maxVoteOptions).fill(0n);
|
|
958
988
|
this.perVoteOptionSpentVoiceCredits = new Array(this.maxVoteOptions).fill(0n);
|
|
959
989
|
// we put a blank state leaf to prevent a DoS attack
|
|
960
|
-
this.emptyBallot = domainobjs_1.Ballot.
|
|
990
|
+
this.emptyBallot = domainobjs_1.Ballot.generateBlank(this.maxVoteOptions, treeDepths.voteOptionTreeDepth);
|
|
961
991
|
this.ballots.push(this.emptyBallot);
|
|
992
|
+
this.emptyBallotHash = this.emptyBallot.hash();
|
|
993
|
+
this.emptyVoteCounts = domainobjs_1.VoteCounts.generateBlank(this.maxVoteOptions, treeDepths.voteOptionTreeDepth);
|
|
994
|
+
this.voteCounts.push(this.emptyVoteCounts);
|
|
995
|
+
this.emptyVoteCountsHash = this.emptyVoteCounts.hash();
|
|
962
996
|
}
|
|
963
997
|
/**
|
|
964
998
|
* Get voice credits left for the voting command.
|
|
@@ -981,7 +1015,7 @@ class Poll {
|
|
|
981
1015
|
case constants_1.EMode.NON_QV:
|
|
982
1016
|
case constants_1.EMode.FULL: {
|
|
983
1017
|
// for non quadratic voting, we simply remove the exponentiation
|
|
984
|
-
// for full
|
|
1018
|
+
// for full credits voting, it will be zero
|
|
985
1019
|
return stateLeaf.voiceCreditBalance + originalVoteWeight - newVoteWeight;
|
|
986
1020
|
}
|
|
987
1021
|
default: {
|
|
@@ -1004,12 +1038,13 @@ class Poll {
|
|
|
1004
1038
|
messages: this.messages.map((message) => message.toJSON()),
|
|
1005
1039
|
commands: this.commands.map((command) => command.toJSON()),
|
|
1006
1040
|
ballots: this.ballots.map((ballot) => ballot.toJSON()),
|
|
1041
|
+
voteCounts: this.voteCounts.map((voteCounts) => voteCounts.toJSON()),
|
|
1007
1042
|
encryptionPublicKeys: this.encryptionPublicKeys.map((encryptionPublicKey) => encryptionPublicKey.serialize()),
|
|
1008
1043
|
currentMessageBatchIndex: this.currentMessageBatchIndex,
|
|
1009
1044
|
publicKeys: this.publicKeys.map((leaf) => leaf.toJSON()),
|
|
1010
1045
|
pollStateLeaves: this.pollStateLeaves.map((leaf) => leaf.toJSON()),
|
|
1011
1046
|
results: this.tallyResult.map((result) => result.toString()),
|
|
1012
|
-
|
|
1047
|
+
totalBatchesProcessed: this.totalBatchesProcessed,
|
|
1013
1048
|
totalSignups: this.totalSignups.toString(),
|
|
1014
1049
|
chainHash: this.chainHash.toString(),
|
|
1015
1050
|
pollNullifiers: [...this.pollNullifiers.keys()].map((nullifier) => nullifier.toString()),
|
|
@@ -1028,12 +1063,13 @@ class Poll {
|
|
|
1028
1063
|
// set all properties
|
|
1029
1064
|
poll.pollStateLeaves = json.pollStateLeaves.map((leaf) => domainobjs_1.StateLeaf.fromJSON(leaf));
|
|
1030
1065
|
poll.ballots = json.ballots.map((ballot) => domainobjs_1.Ballot.fromJSON(ballot));
|
|
1066
|
+
poll.voteCounts = json.voteCounts.map((voteCounts) => domainobjs_1.VoteCounts.fromJSON(voteCounts));
|
|
1031
1067
|
poll.encryptionPublicKeys = json.encryptionPublicKeys.map((key) => domainobjs_1.PublicKey.deserialize(key));
|
|
1032
1068
|
poll.messages = json.messages.map((message) => domainobjs_1.Message.fromJSON(message));
|
|
1033
1069
|
poll.commands = json.commands.map((command) => domainobjs_1.VoteCommand.fromJSON(command));
|
|
1034
1070
|
poll.tallyResult = json.results.map((result) => BigInt(result));
|
|
1035
1071
|
poll.currentMessageBatchIndex = json.currentMessageBatchIndex;
|
|
1036
|
-
poll.
|
|
1072
|
+
poll.totalBatchesProcessed = json.totalBatchesProcessed;
|
|
1037
1073
|
poll.chainHash = BigInt(json.chainHash);
|
|
1038
1074
|
poll.batchHashes = json.batchHashes.map((batchHash) => BigInt(batchHash));
|
|
1039
1075
|
poll.pollNullifiers = new Map(json.pollNullifiers.map((nullifier) => [BigInt(nullifier), true]));
|