diff --git a/.github/scripts/downloadZkeys.ts b/.github/scripts/downloadZkeys.ts index da4f700f48..e355bb5e4f 100644 --- a/.github/scripts/downloadZkeys.ts +++ b/.github/scripts/downloadZkeys.ts @@ -6,7 +6,7 @@ import path from "path"; const ZKEY_PATH = path.resolve(process.argv.slice(3)[0]); const ZKEYS_URLS = { - test: "https://maci-develop-fra.s3.eu-central-1.amazonaws.com/v1.3.0/maci_artifacts_10-2-1-2_test.tar.gz", + test: "https://maci-develop-fra.s3.eu-central-1.amazonaws.com/v2.0.0/maci_artifacts_10-2-1-2_test.tar.gz", prod: "https://maci-develop-fra.s3.eu-central-1.amazonaws.com/v1.2.0/maci_artifacts_6-9-2-3_prod.tar.gz", }; const ARCHIVE_NAME = path.resolve(ZKEY_PATH, "maci_keys.tar.gz"); diff --git a/circuits/circom/circuits.json b/circuits/circom/circuits.json index 203c696876..22650b1349 100644 --- a/circuits/circom/circuits.json +++ b/circuits/circom/circuits.json @@ -11,7 +11,8 @@ "currentSbCommitment", "newSbCommitment", "pollEndTimestamp", - "actualStateTreeDepth" + "actualStateTreeDepth", + "coordinatorPublicKeyHash" ] }, "ProcessMessagesNonQv_10-2-1-2_test": { @@ -26,7 +27,8 @@ "currentSbCommitment", "newSbCommitment", "pollEndTimestamp", - "actualStateTreeDepth" + "actualStateTreeDepth", + "coordinatorPublicKeyHash" ] }, "TallyVotes_10-1-2_test": { diff --git a/circuits/circom/core/non-qv/processMessages.circom b/circuits/circom/core/non-qv/processMessages.circom index e0057d4c26..05dda47029 100644 --- a/circuits/circom/core/non-qv/processMessages.circom +++ b/circuits/circom/core/non-qv/processMessages.circom @@ -60,8 +60,6 @@ include "../../trees/incrementalQuinaryTree.circom"; signal input msgSubrootPathElements[msgTreeDepth - msgBatchDepth][MESSAGE_TREE_ARITY - 1]; // The coordinator's private key. signal input coordPrivKey; - // The cooordinator's public key (derived from the contract). - signal input coordPubKey[2]; // The ECDH public key per message. signal input encPubKeys[batchSize][2]; // The current state root (before the processing). @@ -74,6 +72,8 @@ include "../../trees/incrementalQuinaryTree.circom"; signal input batchEndIndex; // The batch index of current message batch signal input index; + // The coordinator public key hash + signal input coordinatorPublicKeyHash; // The state leaves upon which messages are applied. // transform(currentStateLeaf[4], message5) => newStateLeaf4 @@ -185,7 +185,8 @@ include "../../trees/incrementalQuinaryTree.circom"; // based on the given private key - that is, the prover knows the // coordinator's private key. var derivedPubKey[2] = PrivToPubKey()(coordPrivKey); - derivedPubKey === coordPubKey; + var derivedPubKeyHash = PoseidonHasher(2)(derivedPubKey); + derivedPubKeyHash === coordinatorPublicKeyHash; // Decrypt each Message into a Command. // The command i-th is composed by the following fields. diff --git a/circuits/circom/core/qv/processMessages.circom b/circuits/circom/core/qv/processMessages.circom index e012f63afd..f1ad356f36 100644 --- a/circuits/circom/core/qv/processMessages.circom +++ b/circuits/circom/core/qv/processMessages.circom @@ -60,8 +60,6 @@ template ProcessMessages( signal input msgSubrootPathElements[msgTreeDepth - msgBatchDepth][MESSAGE_TREE_ARITY - 1]; // The coordinator's private key. signal input coordPrivKey; - // The cooordinator's public key (derived from the contract). - signal input coordPubKey[2]; // The ECDH public key per message. signal input encPubKeys[batchSize][2]; // The current state root (before the processing). @@ -74,6 +72,8 @@ template ProcessMessages( signal input batchEndIndex; // The batch index of current message batch signal input index; + // The coordinator public key hash + signal input coordinatorPublicKeyHash; // The state leaves upon which messages are applied. // transform(currentStateLeaf[4], message5) => newStateLeaf4 @@ -180,7 +180,8 @@ template ProcessMessages( // based on the given private key - that is, the prover knows the // coordinator's private key. var derivedPubKey[2] = PrivToPubKey()(coordPrivKey); - derivedPubKey === coordPubKey; + var derivedPubKeyHash = PoseidonHasher(2)(derivedPubKey); + derivedPubKeyHash === coordinatorPublicKeyHash; // Decrypt each Message into a Command. // The command i-th is composed by the following fields. diff --git a/circuits/circom/test/ProcessMessages_10-2-1-2_test.circom b/circuits/circom/test/ProcessMessages_10-2-1-2_test.circom index 6dc034fa6f..9272a45ae0 100644 --- a/circuits/circom/test/ProcessMessages_10-2-1-2_test.circom +++ b/circuits/circom/test/ProcessMessages_10-2-1-2_test.circom @@ -3,4 +3,4 @@ pragma circom 2.0.0; include ".././core/qv/processMessages.circom"; -component main {public[numSignUps, index, batchEndIndex, msgRoot, currentSbCommitment, newSbCommitment, pollEndTimestamp, actualStateTreeDepth]} = ProcessMessages(10, 2, 1, 2); +component main {public[numSignUps, index, batchEndIndex, msgRoot, currentSbCommitment, newSbCommitment, pollEndTimestamp, actualStateTreeDepth, coordinatorPublicKeyHash]} = ProcessMessages(10, 2, 1, 2); diff --git a/circuits/ts/__tests__/CeremonyParams.test.ts b/circuits/ts/__tests__/CeremonyParams.test.ts index c288bd6cd3..8d2f21a3a6 100644 --- a/circuits/ts/__tests__/CeremonyParams.test.ts +++ b/circuits/ts/__tests__/CeremonyParams.test.ts @@ -22,12 +22,6 @@ describe("Ceremony param tests", () => { stateLeafBatchDepth: 2, }; - const maxValues = { - maxUsers: STATE_TREE_ARITY ** params.stateTreeDepth, - maxMessages: MESSAGE_TREE_ARITY ** params.messageTreeDepth, - maxVoteOptions: MESSAGE_TREE_ARITY ** params.voteOptionTreeDepth, - }; - const treeDepths = { intStateTreeDepth: params.messageBatchTreeDepth, messageTreeDepth: params.messageTreeDepth, @@ -56,7 +50,7 @@ describe("Ceremony param tests", () => { "msgs", "msgSubrootPathElements", "coordPrivKey", - "coordPubKey", + "coordinatorPublicKeyHash", "encPubKeys", "currentStateRoot", "currentStateLeaves", @@ -100,7 +94,6 @@ describe("Ceremony param tests", () => { pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -152,7 +145,10 @@ describe("Ceremony param tests", () => { it("should produce the correct state root and ballot root", async () => { // The current roots - const emptyBallot = new Ballot(poll.maxValues.maxVoteOptions, poll.treeDepths.voteOptionTreeDepth); + const emptyBallot = new Ballot( + MESSAGE_TREE_ARITY ** poll.treeDepths.voteOptionTreeDepth, + poll.treeDepths.voteOptionTreeDepth, + ); const emptyBallotHash = emptyBallot.hash(); const ballotTree = new IncrementalQuinTree(params.stateTreeDepth, emptyBallot.hash(), STATE_TREE_ARITY, hash5); ballotTree.insert(emptyBallot.hash()); @@ -236,7 +232,6 @@ describe("Ceremony param tests", () => { pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, diff --git a/circuits/ts/__tests__/ProcessMessages.test.ts b/circuits/ts/__tests__/ProcessMessages.test.ts index 3d039a7f94..05d8e77912 100644 --- a/circuits/ts/__tests__/ProcessMessages.test.ts +++ b/circuits/ts/__tests__/ProcessMessages.test.ts @@ -1,19 +1,12 @@ import { expect } from "chai"; import { type WitnessTester } from "circomkit"; -import { MaciState, Poll, STATE_TREE_ARITY } from "maci-core"; +import { MaciState, MESSAGE_TREE_ARITY, Poll, STATE_TREE_ARITY } from "maci-core"; import { IncrementalQuinTree, hash2 } from "maci-crypto"; import { PrivKey, Keypair, PCommand, Message, Ballot, PubKey } from "maci-domainobjs"; import { IProcessMessagesInputs } from "../types"; -import { - STATE_TREE_DEPTH, - duration, - maxValues, - messageBatchSize, - treeDepths, - voiceCreditBalance, -} from "./utils/constants"; +import { STATE_TREE_DEPTH, duration, messageBatchSize, treeDepths, voiceCreditBalance } from "./utils/constants"; import { circomkitInstance } from "./utils/utils"; describe("ProcessMessage circuit", function test() { @@ -31,7 +24,7 @@ describe("ProcessMessage circuit", function test() { "msgs", "msgSubrootPathElements", "coordPrivKey", - "coordPubKey", + "coordinatorPublicKeyHash", "encPubKeys", "currentStateRoot", "currentStateLeaves", @@ -84,7 +77,6 @@ describe("ProcessMessage circuit", function test() { pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -162,7 +154,6 @@ describe("ProcessMessage circuit", function test() { pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -212,7 +203,10 @@ describe("ProcessMessage circuit", function test() { it("should produce the correct state root and ballot root", async () => { // The current roots - const emptyBallot = new Ballot(poll.maxValues.maxVoteOptions, poll.treeDepths.voteOptionTreeDepth); + const emptyBallot = new Ballot( + MESSAGE_TREE_ARITY ** poll.treeDepths.voteOptionTreeDepth, + poll.treeDepths.voteOptionTreeDepth, + ); const emptyBallotHash = emptyBallot.hash(); const ballotTree = new IncrementalQuinTree(STATE_TREE_DEPTH, emptyBallot.hash(), STATE_TREE_ARITY, hash2); @@ -266,7 +260,6 @@ describe("ProcessMessage circuit", function test() { pollId = maciState.deployPoll( BigInt(2 + duration), // BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -298,7 +291,10 @@ describe("ProcessMessage circuit", function test() { it("should produce the correct state root and ballot root", async () => { // The current roots - const emptyBallot = new Ballot(poll.maxValues.maxVoteOptions, poll.treeDepths.voteOptionTreeDepth); + const emptyBallot = new Ballot( + MESSAGE_TREE_ARITY ** poll.treeDepths.voteOptionTreeDepth, + poll.treeDepths.voteOptionTreeDepth, + ); const emptyBallotHash = emptyBallot.hash(); const ballotTree = new IncrementalQuinTree(STATE_TREE_DEPTH, emptyBallot.hash(), STATE_TREE_ARITY, hash2); @@ -350,7 +346,6 @@ describe("ProcessMessage circuit", function test() { pollId = maciState.deployPoll( BigInt(2 + duration), // BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -427,7 +422,6 @@ describe("ProcessMessage circuit", function test() { // Sign up and publish const id = state.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -486,7 +480,6 @@ describe("ProcessMessage circuit", function test() { pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -556,7 +549,10 @@ describe("ProcessMessage circuit", function test() { it("should produce the correct state root and ballot root", async () => { // The current roots - const emptyBallot = new Ballot(poll.maxValues.maxVoteOptions, poll.treeDepths.voteOptionTreeDepth); + const emptyBallot = new Ballot( + MESSAGE_TREE_ARITY ** poll.treeDepths.voteOptionTreeDepth, + poll.treeDepths.voteOptionTreeDepth, + ); const emptyBallotHash = emptyBallot.hash(); const ballotTree = new IncrementalQuinTree(STATE_TREE_DEPTH, emptyBallot.hash(), STATE_TREE_ARITY, hash2); @@ -603,7 +599,6 @@ describe("ProcessMessage circuit", function test() { pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -678,7 +673,10 @@ describe("ProcessMessage circuit", function test() { it("should produce the correct state root and ballot root", async () => { // The current roots - const emptyBallot = new Ballot(poll.maxValues.maxVoteOptions, poll.treeDepths.voteOptionTreeDepth); + const emptyBallot = new Ballot( + MESSAGE_TREE_ARITY ** poll.treeDepths.voteOptionTreeDepth, + poll.treeDepths.voteOptionTreeDepth, + ); const emptyBallotHash = emptyBallot.hash(); const ballotTree = new IncrementalQuinTree(STATE_TREE_DEPTH, emptyBallot.hash(), STATE_TREE_ARITY, hash2); @@ -728,7 +726,6 @@ describe("ProcessMessage circuit", function test() { pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -822,7 +819,10 @@ describe("ProcessMessage circuit", function test() { it("should produce the correct state root and ballot root", async () => { // The current roots - const emptyBallot = new Ballot(poll.maxValues.maxVoteOptions, poll.treeDepths.voteOptionTreeDepth); + const emptyBallot = new Ballot( + MESSAGE_TREE_ARITY ** poll.treeDepths.voteOptionTreeDepth, + poll.treeDepths.voteOptionTreeDepth, + ); const emptyBallotHash = emptyBallot.hash(); const ballotTree = new IncrementalQuinTree(STATE_TREE_DEPTH, emptyBallot.hash(), STATE_TREE_ARITY, hash2); diff --git a/circuits/ts/__tests__/TallyVotes.test.ts b/circuits/ts/__tests__/TallyVotes.test.ts index b7776d83cc..6d2568b39a 100644 --- a/circuits/ts/__tests__/TallyVotes.test.ts +++ b/circuits/ts/__tests__/TallyVotes.test.ts @@ -4,7 +4,7 @@ import { Keypair, PCommand, Message } from "maci-domainobjs"; import { ITallyVotesInputs } from "../types"; -import { STATE_TREE_DEPTH, duration, maxValues, messageBatchSize, voiceCreditBalance } from "./utils/constants"; +import { STATE_TREE_DEPTH, duration, messageBatchSize, voiceCreditBalance } from "./utils/constants"; import { generateRandomIndex, circomkitInstance } from "./utils/utils"; describe("TallyVotes circuit", function test() { @@ -80,7 +80,6 @@ describe("TallyVotes circuit", function test() { pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -154,7 +153,6 @@ describe("TallyVotes circuit", function test() { pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -224,7 +222,6 @@ describe("TallyVotes circuit", function test() { const pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, diff --git a/circuits/ts/__tests__/utils/constants.ts b/circuits/ts/__tests__/utils/constants.ts index 590e66b9dd..815aa371b9 100644 --- a/circuits/ts/__tests__/utils/constants.ts +++ b/circuits/ts/__tests__/utils/constants.ts @@ -1,11 +1,6 @@ export const STATE_TREE_DEPTH = 10; export const voiceCreditBalance = BigInt(100); export const duration = 30; -export const maxValues = { - maxUsers: 25, - maxMessages: 25, - maxVoteOptions: 25, -}; export const treeDepths = { intStateTreeDepth: 5, messageTreeDepth: 2, diff --git a/circuits/ts/types.ts b/circuits/ts/types.ts index bd05e8a98a..78dd1a54ce 100644 --- a/circuits/ts/types.ts +++ b/circuits/ts/types.ts @@ -54,7 +54,7 @@ export interface IProcessMessagesInputs { msgs: bigint[]; msgSubrootPathElements: bigint[][]; coordPrivKey: bigint; - coordPubKey: [bigint, bigint]; + coordinatorPublicKeyHash: bigint; encPubKeys: bigint[]; currentStateRoot: bigint; currentStateLeaves: bigint[]; diff --git a/cli/ts/commands/proveOnChain.ts b/cli/ts/commands/proveOnChain.ts index ed3dbd7c17..27636c3e77 100644 --- a/cli/ts/commands/proveOnChain.ts +++ b/cli/ts/commands/proveOnChain.ts @@ -11,7 +11,7 @@ import { Verifier__factory as VerifierFactory, } from "maci-contracts/typechain-types"; import { MESSAGE_TREE_ARITY, STATE_TREE_ARITY } from "maci-core"; -import { G1Point, G2Point, hashLeftRight } from "maci-crypto"; +import { G1Point, G2Point } from "maci-crypto"; import { VerifyingKey } from "maci-domainobjs"; import fs from "fs"; @@ -214,13 +214,9 @@ export const proveOnChain = async ({ logError("currentSbCommitment mismatch."); } - const coordPubKeyHashOnChain = BigInt(await pollContract.coordinatorPubKeyHash()); - if ( - hashLeftRight( - BigInt((circuitInputs.coordPubKey as BigNumberish[])[0]), - BigInt((circuitInputs.coordPubKey as BigNumberish[])[1]), - ).toString() !== coordPubKeyHashOnChain.toString() - ) { + const coordPubKeyHashOnChain = await pollContract.coordinatorPubKeyHash(); + + if (circuitInputs.coordinatorPublicKeyHash.toString() !== coordPubKeyHashOnChain.toString()) { logError("coordPubKey mismatch."); } diff --git a/cli/ts/commands/publish.ts b/cli/ts/commands/publish.ts index f74e506797..5b48285949 100644 --- a/cli/ts/commands/publish.ts +++ b/cli/ts/commands/publish.ts @@ -1,4 +1,5 @@ import { MACI__factory as MACIFactory, Poll__factory as PollFactory } from "maci-contracts/typechain-types"; +import { MESSAGE_TREE_ARITY } from "maci-core"; import { genRandomSalt } from "maci-crypto"; import { type IG1ContractParams, @@ -86,9 +87,9 @@ export const publish = async ({ const pollContract = PollFactory.connect(pollContracts.poll, signer); - const maxValues = await pollContract.maxValues(); + const treeDepths = await pollContract.treeDepths(); const coordinatorPubKeyResult = await pollContract.coordinatorPubKey(); - const maxVoteOptions = Number(maxValues.maxVoteOptions); + const maxVoteOptions = Number(BigInt(MESSAGE_TREE_ARITY) ** treeDepths.voteOptionTreeDepth); // validate the vote options index against the max leaf index on-chain if (maxVoteOptions < voteOptionIndex) { @@ -172,11 +173,11 @@ export const publishBatch = async ({ const pollContract = PollFactory.connect(pollContracts.poll, signer); - const [maxValues, coordinatorPubKeyResult] = await Promise.all([ - pollContract.maxValues(), + const [treeDepths, coordinatorPubKeyResult] = await Promise.all([ + pollContract.treeDepths(), pollContract.coordinatorPubKey(), ]); - const maxVoteOptions = Number(maxValues.maxVoteOptions); + const maxVoteOptions = Number(BigInt(MESSAGE_TREE_ARITY) ** treeDepths.voteOptionTreeDepth); // validate the vote options index against the max leaf index on-chain messages.forEach(({ stateIndex, voteOptionIndex, salt, nonce }) => { diff --git a/contracts/contracts/MACI.sol b/contracts/contracts/MACI.sol index cf12f86008..469649dc80 100644 --- a/contracts/contracts/MACI.sol +++ b/contracts/contracts/MACI.sol @@ -199,14 +199,8 @@ contract MACI is IMACI, DomainObjs, Params, Utilities { uint256 voteOptionTreeDepth = _treeDepths.voteOptionTreeDepth; - MaxValues memory maxValues = MaxValues({ - maxMessages: uint256(MESSAGE_TREE_ARITY) ** _treeDepths.messageTreeDepth, - maxVoteOptions: uint256(MESSAGE_TREE_ARITY) ** voteOptionTreeDepth - }); - address p = pollFactory.deploy( _duration, - maxValues, _treeDepths, _coordinatorPubKey, address(this), diff --git a/contracts/contracts/MessageProcessor.sol b/contracts/contracts/MessageProcessor.sol index 94946318ec..8c037a6459 100644 --- a/contracts/contracts/MessageProcessor.sol +++ b/contracts/contracts/MessageProcessor.sol @@ -146,6 +146,7 @@ contract MessageProcessor is Ownable, SnarkCommon, Hasher, CommonUtilities, IMes ) public view override returns (uint256[] memory publicInputs) { (, uint8 messageTreeSubDepth, uint8 messageTreeDepth, uint8 voteOptionTreeDepth) = poll.treeDepths(); (, AccQueue messageAq) = poll.extContracts(); + uint256 coordinatorPubKeyHash = poll.coordinatorPubKeyHash(); uint256 messageBatchSize = TREE_ARITY ** messageTreeSubDepth; (uint256 numSignUps, uint256 numMessages) = poll.numSignUpsAndMessages(); (uint256 deployTime, uint256 duration) = poll.getDeployTimeAndDuration(); @@ -155,15 +156,16 @@ contract MessageProcessor is Ownable, SnarkCommon, Hasher, CommonUtilities, IMes batchEndIndex = numMessages; } - publicInputs = new uint256[](8); + publicInputs = new uint256[](9); publicInputs[0] = numSignUps; publicInputs[1] = deployTime + duration; publicInputs[2] = messageAq.getMainRoot(messageTreeDepth); publicInputs[3] = poll.actualStateTreeDepth(); publicInputs[4] = batchEndIndex; publicInputs[5] = _currentMessageBatchIndex; - publicInputs[6] = (sbCommitment == 0 ? poll.currentSbCommitment() : sbCommitment); - publicInputs[7] = _newSbCommitment; + publicInputs[6] = coordinatorPubKeyHash; + publicInputs[7] = (sbCommitment == 0 ? poll.currentSbCommitment() : sbCommitment); + publicInputs[8] = _newSbCommitment; } /// @notice Verify the proof for processMessage diff --git a/contracts/contracts/Poll.sol b/contracts/contracts/Poll.sol index df897e546a..2b003fd774 100644 --- a/contracts/contracts/Poll.sol +++ b/contracts/contracts/Poll.sol @@ -57,15 +57,18 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll { /// to be used as public input for the circuit uint8 public actualStateTreeDepth; - /// @notice Max values for the poll - MaxValues public maxValues; - /// @notice Depths of the merkle trees TreeDepths public treeDepths; /// @notice The contracts used by the Poll ExtContracts public extContracts; + /// @notice The max number of messages + uint256 public immutable maxMessages; + + /// @notice The number of children per node in the merkle trees + uint256 internal constant TREE_ARITY = 5; + error VotingPeriodOver(); error VotingPeriodNotOver(); error PollAlreadyInit(); @@ -82,13 +85,11 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll { /// @notice Each MACI instance can have multiple Polls. /// When a Poll is deployed, its voting period starts immediately. /// @param _duration The duration of the voting period, in seconds - /// @param _maxValues The maximum number of messages and vote options /// @param _treeDepths The depths of the merkle trees /// @param _coordinatorPubKey The coordinator's public key /// @param _extContracts The external contracts constructor( uint256 _duration, - MaxValues memory _maxValues, TreeDepths memory _treeDepths, PubKey memory _coordinatorPubKey, ExtContracts memory _extContracts, @@ -107,14 +108,14 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll { extContracts = _extContracts; // store duration of the poll duration = _duration; - // store max values - maxValues = _maxValues; // store tree depth treeDepths = _treeDepths; // Record the current timestamp deployTime = block.timestamp; // store the empty ballot root emptyBallotRoot = _emptyBallotRoot; + // store max messages + maxMessages = TREE_ARITY ** _treeDepths.messageTreeDepth; } /// @notice A modifier that causes the function to revert if the voting period is @@ -159,7 +160,7 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll { /// @inheritdoc IPoll function publishMessage(Message memory _message, PubKey calldata _encPubKey) public virtual isWithinVotingDeadline { // we check that we do not exceed the max number of messages - if (numMessages >= maxValues.maxMessages) revert TooManyMessages(); + if (numMessages >= maxMessages) revert TooManyMessages(); // check if the public key is on the curve if (!CurveBabyJubJub.isOnCurve(_encPubKey.x, _encPubKey.y)) { @@ -223,7 +224,7 @@ contract Poll is Params, Utilities, SnarkCommon, IPoll { // dynamically determine the actual depth of the state tree uint8 depth = 1; - while (uint40(2) ** uint40(depth) < _numSignups) { + while (uint40(1 << depth) < _numSignups) { depth++; } diff --git a/contracts/contracts/PollFactory.sol b/contracts/contracts/PollFactory.sol index d35f71d4e9..bca7b98f8c 100644 --- a/contracts/contracts/PollFactory.sol +++ b/contracts/contracts/PollFactory.sol @@ -13,9 +13,6 @@ import { IPollFactory } from "./interfaces/IPollFactory.sol"; /// @notice A factory contract which deploys Poll contracts. It allows the MACI contract /// size to stay within the limit set by EIP-170. contract PollFactory is Params, DomainObjs, IPollFactory { - // custom error - error InvalidMaxValues(); - /// @notice The PollFactory constructor // solhint-disable-next-line no-empty-blocks constructor() payable {} @@ -23,20 +20,11 @@ contract PollFactory is Params, DomainObjs, IPollFactory { /// @inheritdoc IPollFactory function deploy( uint256 _duration, - MaxValues calldata _maxValues, TreeDepths calldata _treeDepths, PubKey calldata _coordinatorPubKey, address _maci, uint256 _emptyBallotRoot ) public virtual returns (address pollAddr) { - /// @notice Validate _maxValues - /// maxVoteOptions must be less than 2 ** 50 due to circuit limitations; - /// it will be packed as a 50-bit value along with other values as one - /// of the inputs (aka packedVal) - if (_maxValues.maxVoteOptions >= (2 ** 50)) { - revert InvalidMaxValues(); - } - /// @notice deploy a new AccQueue contract to store messages AccQueue messageAq = new AccQueueQuinaryMaci(_treeDepths.messageTreeSubDepth); @@ -44,7 +32,7 @@ contract PollFactory is Params, DomainObjs, IPollFactory { ExtContracts memory extContracts = ExtContracts({ maci: IMACI(_maci), messageAq: messageAq }); // deploy the poll - Poll poll = new Poll(_duration, _maxValues, _treeDepths, _coordinatorPubKey, extContracts, _emptyBallotRoot); + Poll poll = new Poll(_duration, _treeDepths, _coordinatorPubKey, extContracts, _emptyBallotRoot); // Make the Poll contract own the messageAq contract, so only it can // run enqueue/merge diff --git a/contracts/contracts/interfaces/IPoll.sol b/contracts/contracts/interfaces/IPoll.sol index e4b3978a57..df15584d3e 100644 --- a/contracts/contracts/interfaces/IPoll.sol +++ b/contracts/contracts/interfaces/IPoll.sol @@ -54,11 +54,6 @@ interface IPoll { view returns (uint8 intStateTreeDepth, uint8 messageTreeSubDepth, uint8 messageTreeDepth, uint8 voteOptionTreeDepth); - /// @notice Get the max values for the poll - /// @return maxMessages The maximum number of messages - /// @return maxVoteOptions The maximum number of vote options - function maxValues() external view returns (uint256 maxMessages, uint256 maxVoteOptions); - /// @notice Get the external contracts /// @return maci The IMACI contract /// @return messageAq The AccQueue contract diff --git a/contracts/contracts/interfaces/IPollFactory.sol b/contracts/contracts/interfaces/IPollFactory.sol index 54f61ebf42..79b3663aac 100644 --- a/contracts/contracts/interfaces/IPollFactory.sol +++ b/contracts/contracts/interfaces/IPollFactory.sol @@ -9,7 +9,6 @@ import { DomainObjs } from "../utilities/DomainObjs.sol"; interface IPollFactory { /// @notice Deploy a new Poll contract and AccQueue contract for messages. /// @param _duration The duration of the poll - /// @param _maxValues The max values for the poll /// @param _treeDepths The depths of the merkle trees /// @param _coordinatorPubKey The coordinator's public key /// @param _maci The MACI contract interface reference @@ -17,7 +16,6 @@ interface IPollFactory { /// @return The deployed Poll contract function deploy( uint256 _duration, - Params.MaxValues memory _maxValues, Params.TreeDepths memory _treeDepths, DomainObjs.PubKey memory _coordinatorPubKey, address _maci, diff --git a/contracts/contracts/utilities/Params.sol b/contracts/contracts/utilities/Params.sol index 06fb4bdd33..6e1f174cd3 100644 --- a/contracts/contracts/utilities/Params.sol +++ b/contracts/contracts/utilities/Params.sol @@ -18,12 +18,6 @@ contract Params { uint8 voteOptionTreeDepth; } - /// @notice A struct holding the max values for the poll - struct MaxValues { - uint256 maxMessages; - uint256 maxVoteOptions; - } - /// @notice A struct holding the external contracts /// that are to be passed to a Poll contract on /// deployment diff --git a/contracts/tasks/deploy/poll/01-poll.ts b/contracts/tasks/deploy/poll/01-poll.ts index f830b95388..106b39c106 100644 --- a/contracts/tasks/deploy/poll/01-poll.ts +++ b/contracts/tasks/deploy/poll/01-poll.ts @@ -85,7 +85,7 @@ deployment.deployTask("poll:deploy-poll", "Deploy poll").then((task) => } const pollContract = await deployment.getContract({ name: EContracts.Poll, address: pollContractAddress }); - const [maxValues, extContracts] = await Promise.all([pollContract.maxValues(), pollContract.extContracts()]); + const extContracts = await pollContract.extContracts(); const messageProcessorContract = await deployment.getContract({ name: EContracts.MessageProcessor, @@ -109,7 +109,6 @@ deployment.deployTask("poll:deploy-poll", "Deploy poll").then((task) => contract: pollContract, args: [ pollDuration, - maxValues.map((value) => value.toString()), { intStateTreeDepth, messageTreeSubDepth, diff --git a/contracts/tasks/helpers/Prover.ts b/contracts/tasks/helpers/Prover.ts index 087d111e4e..6f90a90ecf 100644 --- a/contracts/tasks/helpers/Prover.ts +++ b/contracts/tasks/helpers/Prover.ts @@ -1,5 +1,5 @@ /* eslint-disable no-console, no-await-in-loop */ -import { G1Point, G2Point, hashLeftRight } from "maci-crypto"; +import { G1Point, G2Point } from "maci-crypto"; import { VerifyingKey } from "maci-domainobjs"; import type { IVerifyingKeyStruct, Proof } from "../../ts/types"; @@ -156,13 +156,7 @@ export class Prover { this.validateCommitment(circuitInputs.currentSbCommitment as BigNumberish, currentSbCommitmentOnChain); - const coordPubKeyHashOnChain = BigInt(coordinatorPubKeyHash); - const coordPubKeyHashOffChain = hashLeftRight( - BigInt((circuitInputs.coordPubKey as BigNumberish[])[0]), - BigInt((circuitInputs.coordPubKey as BigNumberish[])[1]), - ).toString(); - - if (coordPubKeyHashOffChain !== coordPubKeyHashOnChain.toString()) { + if (circuitInputs.coordinatorPublicKeyHash.toString() !== coordinatorPubKeyHash.toString()) { throw new Error("coordPubKey mismatch."); } diff --git a/contracts/tests/MACI.test.ts b/contracts/tests/MACI.test.ts index ecf23bb10a..0d4d13a4c8 100644 --- a/contracts/tests/MACI.test.ts +++ b/contracts/tests/MACI.test.ts @@ -10,14 +10,7 @@ import { EMode } from "../ts/constants"; import { getDefaultSigner, getSigners } from "../ts/utils"; import { MACI, Poll as PollContract, Poll__factory as PollFactory, Verifier, VkRegistry } from "../typechain-types"; -import { - STATE_TREE_DEPTH, - duration, - initialVoiceCreditBalance, - maxValues, - messageBatchSize, - treeDepths, -} from "./constants"; +import { STATE_TREE_DEPTH, duration, initialVoiceCreditBalance, messageBatchSize, treeDepths } from "./constants"; import { timeTravel, deployTestContracts } from "./utils"; describe("MACI", function test() { @@ -226,13 +219,7 @@ describe("MACI", function test() { expect(receipt?.status).to.eq(1); pollId = (await maciContract.nextPollId()) - 1n; - const p = maciState.deployPoll( - BigInt(deployTime + duration), - maxValues, - treeDepths, - messageBatchSize, - coordinator, - ); + const p = maciState.deployPoll(BigInt(deployTime + duration), treeDepths, messageBatchSize, coordinator); expect(p.toString()).to.eq(pollId.toString()); // publish the NOTHING_UP_MY_SLEEVE message diff --git a/contracts/tests/MessageProcessor.test.ts b/contracts/tests/MessageProcessor.test.ts index 355caab4b9..5f204bc030 100644 --- a/contracts/tests/MessageProcessor.test.ts +++ b/contracts/tests/MessageProcessor.test.ts @@ -23,7 +23,6 @@ import { STATE_TREE_DEPTH, duration, initialVoiceCreditBalance, - maxValues, messageBatchSize, testProcessVk, testTallyVk, @@ -83,7 +82,7 @@ describe("MessageProcessor", () => { const deployTime = block!.timestamp; // deploy local poll - const p = maciState.deployPoll(BigInt(deployTime + duration), maxValues, treeDepths, messageBatchSize, coordinator); + const p = maciState.deployPoll(BigInt(deployTime + duration), treeDepths, messageBatchSize, coordinator); expect(p.toString()).to.eq(pollId.toString()); // publish the NOTHING_UP_MY_SLEEVE message diff --git a/contracts/tests/Poll.test.ts b/contracts/tests/Poll.test.ts index 4fe27804d1..5be25b4c56 100644 --- a/contracts/tests/Poll.test.ts +++ b/contracts/tests/Poll.test.ts @@ -23,7 +23,6 @@ import { STATE_TREE_DEPTH, duration, initialVoiceCreditBalance, - maxValues, messageBatchSize, treeDepths, } from "./constants"; @@ -73,13 +72,7 @@ describe("Poll", () => { pollContract = PollFactory.connect(pollContracts.poll, signer); // deploy local poll - const p = maciState.deployPoll( - BigInt(deployTime + duration), - maxValues, - treeDepths, - messageBatchSize, - coordinator, - ); + const p = maciState.deployPoll(BigInt(deployTime + duration), treeDepths, messageBatchSize, coordinator); expect(p.toString()).to.eq(pollId.toString()); // publish the NOTHING_UP_MY_SLEEVE message const messageData = [NOTHING_UP_MY_SLEEVE]; @@ -112,12 +105,6 @@ describe("Poll", () => { expect(dd[1].toString()).to.eq(duration.toString()); }); - it("should have the correct max values set", async () => { - const mv = await pollContract.maxValues(); - expect(mv[0].toString()).to.eq(maxValues.maxMessages.toString()); - expect(mv[1].toString()).to.eq(maxValues.maxVoteOptions.toString()); - }); - it("should have the correct tree depths set", async () => { const td = await pollContract.treeDepths(); expect(td[0].toString()).to.eq(treeDepths.intStateTreeDepth.toString()); diff --git a/contracts/tests/PollFactory.test.ts b/contracts/tests/PollFactory.test.ts index b14558f491..50a0b12ea8 100644 --- a/contracts/tests/PollFactory.test.ts +++ b/contracts/tests/PollFactory.test.ts @@ -5,7 +5,7 @@ import { Keypair } from "maci-domainobjs"; import { deployPollFactory, genEmptyBallotRoots, getDefaultSigner } from "../ts"; import { PollFactory } from "../typechain-types"; -import { maxValues, STATE_TREE_DEPTH, treeDepths } from "./constants"; +import { STATE_TREE_DEPTH, treeDepths } from "./constants"; describe("pollFactory", () => { let pollFactory: PollFactory; @@ -25,7 +25,6 @@ describe("pollFactory", () => { it("should allow anyone to deploy a new poll", async () => { const tx = await pollFactory.deploy( "100", - maxValues, treeDepths, coordinatorPubKey.asContractParam(), ZeroAddress, @@ -34,21 +33,5 @@ describe("pollFactory", () => { const receipt = await tx.wait(); expect(receipt?.status).to.eq(1); }); - - it("should revert when called with an invalid param for max values", async () => { - await expect( - pollFactory.deploy( - "100", - { - maxMessages: maxValues.maxMessages, - maxVoteOptions: 2 ** 50, - }, - treeDepths, - coordinatorPubKey.asContractParam(), - ZeroAddress, - emptyBallotRoot, - ), - ).to.be.revertedWithCustomError(pollFactory, "InvalidMaxValues"); - }); }); }); diff --git a/contracts/tests/Tally.test.ts b/contracts/tests/Tally.test.ts index 227fe9136b..0f57fc33c5 100644 --- a/contracts/tests/Tally.test.ts +++ b/contracts/tests/Tally.test.ts @@ -25,7 +25,6 @@ import { STATE_TREE_DEPTH, duration, initialVoiceCreditBalance, - maxValues, messageBatchSize, testProcessVk, testTallyVk, @@ -88,7 +87,7 @@ describe("TallyVotes", () => { tallyContract = TallyFactory.connect(pollContracts.tally, signer); // deploy local poll - const p = maciState.deployPoll(BigInt(deployTime + duration), maxValues, treeDepths, messageBatchSize, coordinator); + const p = maciState.deployPoll(BigInt(deployTime + duration), treeDepths, messageBatchSize, coordinator); expect(p.toString()).to.eq(pollId.toString()); // publish the NOTHING_UP_MY_SLEEVE message const messageData = [NOTHING_UP_MY_SLEEVE]; @@ -248,7 +247,6 @@ describe("TallyVotes", () => { // deploy local poll const p = maciState.deployPoll( BigInt(deployTime + updatedDuration), - maxValues, { ...treeDepths, intStateTreeDepth, @@ -377,7 +375,6 @@ describe("TallyVotes", () => { // deploy local poll const p = maciState.deployPoll( BigInt(deployTime + updatedDuration), - maxValues, { ...treeDepths, intStateTreeDepth, diff --git a/contracts/tests/TallyNonQv.test.ts b/contracts/tests/TallyNonQv.test.ts index bd31764b5b..6f6ef2cdd0 100644 --- a/contracts/tests/TallyNonQv.test.ts +++ b/contracts/tests/TallyNonQv.test.ts @@ -21,15 +21,7 @@ import { Tally__factory as TallyFactory, } from "../typechain-types"; -import { - STATE_TREE_DEPTH, - duration, - maxValues, - messageBatchSize, - testProcessVk, - testTallyVk, - treeDepths, -} from "./constants"; +import { STATE_TREE_DEPTH, duration, messageBatchSize, testProcessVk, testTallyVk, treeDepths } from "./constants"; import { timeTravel, deployTestContracts } from "./utils"; describe("TallyVotesNonQv", () => { @@ -84,7 +76,7 @@ describe("TallyVotesNonQv", () => { tallyContract = TallyFactory.connect(pollContracts.tally, signer); // deploy local poll - const p = maciState.deployPoll(BigInt(deployTime + duration), maxValues, treeDepths, messageBatchSize, coordinator); + const p = maciState.deployPoll(BigInt(deployTime + duration), treeDepths, messageBatchSize, coordinator); expect(p.toString()).to.eq(pollId.toString()); // publish the NOTHING_UP_MY_SLEEVE message const messageData = [NOTHING_UP_MY_SLEEVE]; diff --git a/contracts/tests/constants.ts b/contracts/tests/constants.ts index 76960a201e..6786d07f8a 100644 --- a/contracts/tests/constants.ts +++ b/contracts/tests/constants.ts @@ -1,4 +1,4 @@ -import { MaxValues, TreeDepths, STATE_TREE_ARITY, MESSAGE_TREE_ARITY } from "maci-core"; +import { TreeDepths, STATE_TREE_ARITY, MESSAGE_TREE_ARITY } from "maci-core"; import { G1Point, G2Point } from "maci-crypto"; import { VerifyingKey } from "maci-domainobjs"; @@ -42,10 +42,6 @@ export const testTallyVkNonQv = new VerifyingKey( ); export const initialVoiceCreditBalance = 100; -export const maxValues: MaxValues = { - maxMessages: MESSAGE_TREE_ARITY ** MESSAGE_TREE_DEPTH, - maxVoteOptions: 25, -}; export const treeDepths: TreeDepths = { intStateTreeDepth: 1, diff --git a/contracts/ts/genMaciState.ts b/contracts/ts/genMaciState.ts index c6cf76d728..395dcd19e7 100644 --- a/contracts/ts/genMaciState.ts +++ b/contracts/ts/genMaciState.ts @@ -113,20 +113,13 @@ export const genMaciStateFromContract = async ( const pollContractAddress = pollContractAddresses.get(pollId)!; const pollContract = PollFactory.connect(pollContractAddress, provider); - const [coordinatorPubKeyOnChain, [deployTime, duration], onChainMaxValues, onChainTreeDepths] = await Promise.all([ - pollContract.coordinatorPubKey(), + const [coordinatorPubKeyHashOnChain, [deployTime, duration], onChainTreeDepths] = await Promise.all([ + pollContract.coordinatorPubKeyHash(), pollContract.getDeployTimeAndDuration().then((values) => values.map(Number)), - pollContract.maxValues(), pollContract.treeDepths(), ]); - assert(coordinatorPubKeyOnChain[0].toString() === coordinatorKeypair.pubKey.rawPubKey[0].toString()); - assert(coordinatorPubKeyOnChain[1].toString() === coordinatorKeypair.pubKey.rawPubKey[1].toString()); - - const maxValues = { - maxMessages: Number(onChainMaxValues.maxMessages), - maxVoteOptions: Number(onChainMaxValues.maxVoteOptions), - }; + assert(coordinatorKeypair.pubKey.hash().toString() === coordinatorPubKeyHashOnChain.toString()); const treeDepths = { intStateTreeDepth: Number(onChainTreeDepths.intStateTreeDepth), @@ -218,7 +211,6 @@ export const genMaciStateFromContract = async ( case action.type === "DeployPoll" && action.data.pollId?.toString() === pollId.toString(): { maciState.deployPoll( BigInt(deployTime + duration), - maxValues, treeDepths, batchSizes.messageBatchSize, coordinatorKeypair, diff --git a/core/ts/MaciState.ts b/core/ts/MaciState.ts index 62b9bbd7ec..9a79fd4458 100644 --- a/core/ts/MaciState.ts +++ b/core/ts/MaciState.ts @@ -1,6 +1,6 @@ import { type PubKey, type Keypair, StateLeaf, blankStateLeaf } from "maci-domainobjs"; -import type { IJsonMaciState, IJsonPoll, IMaciState, MaxValues, TreeDepths } from "./utils/types"; +import type { IJsonMaciState, IJsonPoll, IMaciState, TreeDepths } from "./utils/types"; import { Poll } from "./Poll"; import { STATE_TREE_ARITY } from "./utils/constants"; @@ -56,7 +56,6 @@ export class MaciState implements IMaciState { /** * Deploy a new poll with the given parameters. * @param pollEndTimestamp - The Unix timestamp at which the poll ends. - * @param maxValues - The maximum number of values for each vote option. * @param treeDepths - The depths of the tree. * @param messageBatchSize - The batch size for processing messages. * @param coordinatorKeypair - The keypair of the MACI round coordinator. @@ -64,7 +63,6 @@ export class MaciState implements IMaciState { */ deployPoll( pollEndTimestamp: bigint, - maxValues: MaxValues, treeDepths: TreeDepths, messageBatchSize: number, coordinatorKeypair: Keypair, @@ -77,7 +75,6 @@ export class MaciState implements IMaciState { messageBatchSize, tallyBatchSize: STATE_TREE_ARITY ** treeDepths.intStateTreeDepth, }, - maxValues, this, ); diff --git a/core/ts/Poll.ts b/core/ts/Poll.ts index a38b61a291..459c4fec82 100644 --- a/core/ts/Poll.ts +++ b/core/ts/Poll.ts @@ -30,7 +30,6 @@ import type { MaciState } from "./MaciState"; import type { CircuitInputs, TreeDepths, - MaxValues, BatchSizes, IPoll, IJsonPoll, @@ -55,14 +54,16 @@ export class Poll implements IPoll { batchSizes: BatchSizes; - maxValues: MaxValues; - // the depth of the state tree stateTreeDepth: number; // the actual depth of the state tree (can be <= stateTreeDepth) actualStateTreeDepth: number; + maxVoteOptions: number; + + maxMessages: number; + pollEndTimestamp: bigint; ballots: Ballot[] = []; @@ -124,7 +125,6 @@ export class Poll implements IPoll { * @param coordinatorKeypair - The keypair of the coordinator. * @param treeDepths - The depths of the trees used in the poll. * @param batchSizes - The sizes of the batches used in the poll. - * @param maxValues - The maximum values the MACI circuits can accept. * @param maciStateRef - The reference to the MACI state. */ constructor( @@ -132,14 +132,12 @@ export class Poll implements IPoll { coordinatorKeypair: Keypair, treeDepths: TreeDepths, batchSizes: BatchSizes, - maxValues: MaxValues, maciStateRef: MaciState, ) { this.pollEndTimestamp = pollEndTimestamp; this.coordinatorKeypair = coordinatorKeypair; this.treeDepths = treeDepths; this.batchSizes = batchSizes; - this.maxValues = maxValues; this.maciStateRef = maciStateRef; this.pollId = BigInt(maciStateRef.polls.size); this.stateTreeDepth = maciStateRef.stateTreeDepth; @@ -152,11 +150,13 @@ export class Poll implements IPoll { hash5, ); - this.tallyResult = new Array(this.maxValues.maxVoteOptions).fill(0n) as bigint[]; - this.perVOSpentVoiceCredits = new Array(this.maxValues.maxVoteOptions).fill(0n) as bigint[]; + this.maxVoteOptions = MESSAGE_TREE_ARITY ** this.treeDepths.voteOptionTreeDepth; + this.maxMessages = MESSAGE_TREE_ARITY ** this.treeDepths.messageTreeDepth; + this.tallyResult = new Array(this.maxVoteOptions).fill(0n) as bigint[]; + this.perVOSpentVoiceCredits = new Array(this.maxVoteOptions).fill(0n) as bigint[]; // we put a blank state leaf to prevent a DoS attack - this.emptyBallot = Ballot.genBlankBallot(this.maxValues.maxVoteOptions, treeDepths.voteOptionTreeDepth); + this.emptyBallot = Ballot.genBlankBallot(this.maxVoteOptions, treeDepths.voteOptionTreeDepth); this.ballots.push(this.emptyBallot); } @@ -243,7 +243,7 @@ export class Poll implements IPoll { } // If the vote option index is invalid, do nothing - if (command.voteOptionIndex < 0n || command.voteOptionIndex >= BigInt(this.maxValues.maxVoteOptions)) { + if (command.voteOptionIndex < 0n || command.voteOptionIndex >= BigInt(this.maxVoteOptions)) { throw new ProcessMessageError(ProcessMessageErrors.InvalidVoteOptionIndex); } @@ -539,7 +539,7 @@ export class Poll implements IPoll { // this might be unnecessary but we do it to prevent a possible DoS attack // from voters who could potentially encrypt a message in such as way that // when decrypted it results in a valid state leaf index but an invalid vote option index - if (command.voteOptionIndex < this.maxValues.maxVoteOptions) { + if (command.voteOptionIndex < this.maxVoteOptions) { currentVoteWeights.unshift(ballot.votes[Number(command.voteOptionIndex)]); // create a new quinary tree and add all votes we have so far @@ -655,6 +655,7 @@ export class Poll implements IPoll { // ensure we pass the dynamic tree depth circuitInputs.actualStateTreeDepth = this.actualStateTreeDepth.toString(); + circuitInputs.coordinatorPublicKeyHash = this.coordinatorKeypair.pubKey.hash(); return stringifyBigInts(circuitInputs) as unknown as IProcessMessagesCircuitInputs; }; @@ -747,7 +748,6 @@ export class Poll implements IPoll { msgs, msgSubrootPathElements: messageSubrootPath.pathElements, coordPrivKey: this.coordinatorKeypair.privKey.asCircuitInputs(), - coordPubKey: this.coordinatorKeypair.pubKey.asCircuitInputs(), encPubKeys: encPubKeys.map((x) => x.asCircuitInputs()), currentStateRoot, currentBallotRoot, @@ -859,7 +859,7 @@ export class Poll implements IPoll { ballots.push(this.ballots[i]); // for each possible vote option we loop and calculate - for (let j = 0; j < this.maxValues.maxVoteOptions; j += 1) { + for (let j = 0; j < this.maxVoteOptions; j += 1) { const v = this.ballots[i].votes[j]; // the vote itself will be a quadratic vote (sqrt(voiceCredits)) @@ -873,7 +873,7 @@ export class Poll implements IPoll { } } - const emptyBallot = new Ballot(this.maxValues.maxVoteOptions, this.treeDepths.voteOptionTreeDepth); + const emptyBallot = new Ballot(this.maxVoteOptions, this.treeDepths.voteOptionTreeDepth); // pad the ballots array while (ballots.length < batchSize) { @@ -1013,7 +1013,7 @@ export class Poll implements IPoll { ballots.push(this.ballots[i]); // for each possible vote option we loop and calculate - for (let j = 0; j < this.maxValues.maxVoteOptions; j += 1) { + for (let j = 0; j < this.maxVoteOptions; j += 1) { const v = this.ballots[i].votes[j]; this.tallyResult[j] += v; @@ -1023,7 +1023,7 @@ export class Poll implements IPoll { } } - const emptyBallot = new Ballot(this.maxValues.maxVoteOptions, this.treeDepths.voteOptionTreeDepth); + const emptyBallot = new Ballot(this.maxVoteOptions, this.treeDepths.voteOptionTreeDepth); // pad the ballots array while (ballots.length < batchSize) { @@ -1167,10 +1167,6 @@ export class Poll implements IPoll { tallyBatchSize: Number(this.batchSizes.tallyBatchSize.toString()), messageBatchSize: Number(this.batchSizes.messageBatchSize.toString()), }, - { - maxMessages: Number(this.maxValues.maxMessages.toString()), - maxVoteOptions: Number(this.maxValues.maxVoteOptions.toString()), - }, this.maciStateRef, ); @@ -1236,8 +1232,8 @@ export class Poll implements IPoll { this.treeDepths.voteOptionTreeDepth === p.treeDepths.voteOptionTreeDepth && this.batchSizes.tallyBatchSize === p.batchSizes.tallyBatchSize && this.batchSizes.messageBatchSize === p.batchSizes.messageBatchSize && - this.maxValues.maxMessages === p.maxValues.maxMessages && - this.maxValues.maxVoteOptions === p.maxValues.maxVoteOptions && + this.maxMessages === p.maxMessages && + this.maxVoteOptions === p.maxVoteOptions && this.messages.length === p.messages.length && this.encPubKeys.length === p.encPubKeys.length && this.numSignups === p.numSignups; @@ -1268,7 +1264,6 @@ export class Poll implements IPoll { pollEndTimestamp: this.pollEndTimestamp.toString(), treeDepths: this.treeDepths, batchSizes: this.batchSizes, - maxValues: this.maxValues, messages: this.messages.map((message) => message.toJSON()), commands: this.commands.map((command) => command.toJSON()), ballots: this.ballots.map((ballot) => ballot.toJSON()), @@ -1288,14 +1283,7 @@ export class Poll implements IPoll { * @returns a new Poll instance */ static fromJSON(json: IJsonPoll, maciState: MaciState): Poll { - const poll = new Poll( - BigInt(json.pollEndTimestamp), - new Keypair(), - json.treeDepths, - json.batchSizes, - json.maxValues, - maciState, - ); + const poll = new Poll(BigInt(json.pollEndTimestamp), new Keypair(), json.treeDepths, json.batchSizes, maciState); // set all properties poll.ballots = json.ballots.map((ballot) => Ballot.fromJSON(ballot)); diff --git a/core/ts/__benchmarks__/index.ts b/core/ts/__benchmarks__/index.ts index a53a6d7a1a..ef9bb44ccf 100644 --- a/core/ts/__benchmarks__/index.ts +++ b/core/ts/__benchmarks__/index.ts @@ -6,7 +6,6 @@ import { MaciState } from ".."; import { COORDINATOR_KEYPAIR, DURATION, - MAX_VALUES, MESSAGE_BATCH_SIZE, STATE_TREE_DEPTH, TREE_DEPTHS, @@ -35,7 +34,6 @@ export default function runCore(): void { const pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + DURATION), - MAX_VALUES, TREE_DEPTHS, MESSAGE_BATCH_SIZE, COORDINATOR_KEYPAIR, @@ -44,7 +42,7 @@ export default function runCore(): void { poll.updatePoll(BigInt(maciState.stateLeaves.length)); - // 24 valid votes + // 4 valid votes for (let i = 0; i < MESSAGE_BATCH_SIZE - 1; i += 1) { const userKeypair = users[i]; @@ -65,7 +63,7 @@ export default function runCore(): void { poll.publishMessage(message, ecdhKeypair.pubKey); } - // 24 invalid votes + // 4 invalid votes for (let i = 0; i < MESSAGE_BATCH_SIZE - 1; i += 1) { const userKeypair = users[i]; const command = new PCommand( diff --git a/core/ts/__benchmarks__/utils/constants.ts b/core/ts/__benchmarks__/utils/constants.ts index 04861ae48f..c3dc2833c0 100644 --- a/core/ts/__benchmarks__/utils/constants.ts +++ b/core/ts/__benchmarks__/utils/constants.ts @@ -2,18 +2,13 @@ import { Keypair } from "maci-domainobjs"; export const VOICE_CREDIT_BALANCE = 100n; export const DURATION = 30; -export const MESSAGE_BATCH_SIZE = 25; +export const MESSAGE_BATCH_SIZE = 5; export const COORDINATOR_KEYPAIR = new Keypair(); export const STATE_TREE_DEPTH = 10; -export const MAX_VALUES = { - maxUsers: 25, - maxMessages: 25, - maxVoteOptions: 25, -}; export const TREE_DEPTHS = { intStateTreeDepth: 2, - messageTreeDepth: 3, + messageTreeDepth: 2, messageTreeSubDepth: 2, - voteOptionTreeDepth: 4, + voteOptionTreeDepth: 2, }; diff --git a/core/ts/__tests__/MaciState.test.ts b/core/ts/__tests__/MaciState.test.ts index 9539b66738..3d855e45a6 100644 --- a/core/ts/__tests__/MaciState.test.ts +++ b/core/ts/__tests__/MaciState.test.ts @@ -7,14 +7,7 @@ import { MaciState } from "../MaciState"; import { STATE_TREE_DEPTH } from "../utils/constants"; import { IJsonMaciState } from "../utils/types"; -import { - coordinatorKeypair, - duration, - maxValues, - messageBatchSize, - treeDepths, - voiceCreditBalance, -} from "./utils/constants"; +import { coordinatorKeypair, duration, messageBatchSize, treeDepths, voiceCreditBalance } from "./utils/constants"; describe("MaciState", function test() { this.timeout(100000); @@ -36,7 +29,6 @@ describe("MaciState", function test() { m1.signUp(userKeypair.pubKey, voiceCreditBalance, BigInt(Math.floor(Date.now() / 1000))); pollId = m1.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -106,12 +98,12 @@ describe("MaciState", function test() { // modify poll.maxValues.maxMessages const m16 = m1.copy(); - m16.polls.get(pollId)!.maxValues.maxMessages += 1; + m16.polls.get(pollId)!.maxMessages += 1; expect(m1.equals(m16)).not.to.eq(true); // modify poll.maxValues.maxVoteOptions const m17 = m1.copy(); - m17.polls.get(pollId)!.maxValues.maxVoteOptions += 1; + m17.polls.get(pollId)!.maxVoteOptions += 1; expect(m1.equals(m17)).not.to.eq(true); // modify poll.messages diff --git a/core/ts/__tests__/Poll.test.ts b/core/ts/__tests__/Poll.test.ts index 7de35c2fc6..4cb968ae2f 100644 --- a/core/ts/__tests__/Poll.test.ts +++ b/core/ts/__tests__/Poll.test.ts @@ -3,16 +3,9 @@ import { PCommand, Keypair, StateLeaf, PrivKey, Ballot } from "maci-domainobjs"; import { MaciState } from "../MaciState"; import { Poll } from "../Poll"; -import { STATE_TREE_DEPTH } from "../utils/constants"; +import { MESSAGE_TREE_ARITY, STATE_TREE_DEPTH } from "../utils/constants"; -import { - coordinatorKeypair, - duration, - maxValues, - messageBatchSize, - treeDepths, - voiceCreditBalance, -} from "./utils/constants"; +import { coordinatorKeypair, duration, messageBatchSize, treeDepths, voiceCreditBalance } from "./utils/constants"; describe("Poll", function test() { this.timeout(90000); @@ -21,7 +14,6 @@ describe("Poll", function test() { const maciState = new MaciState(STATE_TREE_DEPTH); const pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -122,7 +114,7 @@ describe("Poll", function test() { const command = new PCommand( BigInt(user1StateIndex), user1Keypair.pubKey, - BigInt(maxValues.maxVoteOptions), + BigInt(MESSAGE_TREE_ARITY ** treeDepths.voteOptionTreeDepth), // voice credits spent would be this value ** this value 1n, 1n, @@ -241,7 +233,6 @@ describe("Poll", function test() { const maciState = new MaciState(STATE_TREE_DEPTH); const pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -281,11 +272,11 @@ describe("Poll", function test() { it("should throw if the state has not been copied prior to calling processMessages", () => { const tmpPoll = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, ); + expect(() => maciState.polls.get(tmpPoll)?.processMessages(pollId)).to.throw( "You must update the poll with the correct data first", ); @@ -334,7 +325,6 @@ describe("Poll", function test() { const maciState = new MaciState(STATE_TREE_DEPTH); const pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -422,7 +412,6 @@ describe("Poll", function test() { const maciState = new MaciState(STATE_TREE_DEPTH); const pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -492,7 +481,6 @@ describe("Poll", function test() { // deploy a second poll const secondPollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -541,7 +529,6 @@ describe("Poll", function test() { const maciState = new MaciState(STATE_TREE_DEPTH); const pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -560,7 +547,6 @@ describe("Poll", function test() { const maciState = new MaciState(STATE_TREE_DEPTH); const pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -586,7 +572,6 @@ describe("Poll", function test() { const maciState = new MaciState(STATE_TREE_DEPTH); const pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, diff --git a/core/ts/__tests__/e2e.test.ts b/core/ts/__tests__/e2e.test.ts index 0c354409fb..daa5c517f5 100644 --- a/core/ts/__tests__/e2e.test.ts +++ b/core/ts/__tests__/e2e.test.ts @@ -6,14 +6,7 @@ import { MaciState } from "../MaciState"; import { Poll } from "../Poll"; import { STATE_TREE_DEPTH, STATE_TREE_ARITY, MESSAGE_TREE_ARITY } from "../utils/constants"; -import { - coordinatorKeypair, - duration, - maxValues, - messageBatchSize, - treeDepths, - voiceCreditBalance, -} from "./utils/constants"; +import { coordinatorKeypair, duration, messageBatchSize, treeDepths, voiceCreditBalance } from "./utils/constants"; import { TestHarness, calculateTotal } from "./utils/utils"; describe("MaciState/Poll e2e", function test() { @@ -53,7 +46,6 @@ describe("MaciState/Poll e2e", function test() { // deploy a poll pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -156,7 +148,6 @@ describe("MaciState/Poll e2e", function test() { // deploy a poll pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -269,7 +260,6 @@ describe("MaciState/Poll e2e", function test() { // deploy a poll pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -365,7 +355,6 @@ describe("MaciState/Poll e2e", function test() { pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -467,7 +456,6 @@ describe("MaciState/Poll e2e", function test() { pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, @@ -477,7 +465,7 @@ describe("MaciState/Poll e2e", function test() { }); it("should process votes correctly", () => { - // 24 valid votes + // 4 valid votes for (let i = 0; i < messageBatchSize - 1; i += 1) { const userKeypair = users[i]; @@ -500,7 +488,7 @@ describe("MaciState/Poll e2e", function test() { expect(poll.messages.length).to.eq(messageBatchSize - 1); - // 24 invalid votes + // 4 invalid votes for (let i = 0; i < messageBatchSize - 1; i += 1) { const userKeypair = users[i]; const command = new PCommand( @@ -576,10 +564,14 @@ describe("MaciState/Poll e2e", function test() { // Recall that each user `i` cast the same number of votes for // their option `i` - for (let i = 0; i < poll.tallyResult.length - 1; i += 1) { + for (let i = 0; i < messageBatchSize - 1; i += 1) { expect(poll.tallyResult[i].toString()).to.eq(voteWeight.toString()); } + for (let i = messageBatchSize; i < poll.tallyResult.length - 1; i += 1) { + expect(poll.tallyResult[i].toString()).to.eq("0"); + } + expect(poll.hasUntalliedBallots()).to.eq(false); expect(() => { @@ -607,7 +599,6 @@ describe("MaciState/Poll e2e", function test() { pollId = maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, diff --git a/core/ts/__tests__/utils/constants.ts b/core/ts/__tests__/utils/constants.ts index 1e6c2215a2..de07f75e7d 100644 --- a/core/ts/__tests__/utils/constants.ts +++ b/core/ts/__tests__/utils/constants.ts @@ -2,17 +2,12 @@ import { Keypair } from "maci-domainobjs"; export const voiceCreditBalance = 100n; export const duration = 30; -export const messageBatchSize = 25; +export const messageBatchSize = 5; export const coordinatorKeypair = new Keypair(); -export const maxValues = { - maxUsers: 25, - maxMessages: 25, - maxVoteOptions: 25, -}; export const treeDepths = { intStateTreeDepth: 2, - messageTreeDepth: 3, + messageTreeDepth: 2, messageTreeSubDepth: 2, - voteOptionTreeDepth: 4, + voteOptionTreeDepth: 2, }; diff --git a/core/ts/__tests__/utils/utils.ts b/core/ts/__tests__/utils/utils.ts index 25f6452836..404cd86226 100644 --- a/core/ts/__tests__/utils/utils.ts +++ b/core/ts/__tests__/utils/utils.ts @@ -5,7 +5,7 @@ import { MaciState } from "../../MaciState"; import { Poll } from "../../Poll"; import { STATE_TREE_DEPTH } from "../../utils/constants"; -import { duration, maxValues, messageBatchSize, treeDepths, voiceCreditBalance } from "./constants"; +import { duration, messageBatchSize, treeDepths, voiceCreditBalance } from "./constants"; /** * Calculates the total of a tally result @@ -36,7 +36,6 @@ export class TestHarness { constructor() { this.pollId = this.maciState.deployPoll( BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, this.coordinatorKeypair, diff --git a/core/ts/index.ts b/core/ts/index.ts index 521eb92f76..844418da51 100644 --- a/core/ts/index.ts +++ b/core/ts/index.ts @@ -8,7 +8,6 @@ export type { ITallyCircuitInputs, IProcessMessagesCircuitInputs, CircuitInputs, - MaxValues, TreeDepths, BatchSizes, IJsonMaciState, diff --git a/core/ts/utils/types.ts b/core/ts/utils/types.ts index f44d1b9443..f4ffb0a9fc 100644 --- a/core/ts/utils/types.ts +++ b/core/ts/utils/types.ts @@ -42,16 +42,6 @@ export interface BatchSizes { messageBatchSize: number; } -/** - * This interface defines the maximum values that the circuit can handle. - * @property maxMessages - The maximum number of messages. - * @property maxVoteOptions - The maximum number of vote options. - */ -export interface MaxValues { - maxMessages: number; - maxVoteOptions: number; -} - /** * Represents the public API of the MaciState class. */ @@ -61,7 +51,6 @@ export interface IMaciState { // This method is used for deploying poll. deployPoll( pollEndTimestamp: bigint, - maxValues: MaxValues, treeDepths: TreeDepths, messageBatchSize: number, coordinatorKeypair: Keypair, @@ -99,7 +88,6 @@ export interface IJsonPoll { pollEndTimestamp: string; treeDepths: TreeDepths; batchSizes: BatchSizes; - maxValues: MaxValues; messages: unknown[]; commands: IJsonPCommand[]; ballots: IJsonBallot[]; @@ -150,10 +138,10 @@ export interface IProcessMessagesCircuitInputs { index: string; maxVoteOptions: string; msgRoot: string; + coordinatorPublicKeyHash: string; msgs: string[]; msgSubrootPathElements: string[][]; coordPrivKey: string; - coordPubKey: string; encPubKeys: string[]; currentStateRoot: string; currentBallotRoot: string; diff --git a/integrationTests/ts/__tests__/integration.test.ts b/integrationTests/ts/__tests__/integration.test.ts index 7e455cc2ec..8fdc8bf921 100644 --- a/integrationTests/ts/__tests__/integration.test.ts +++ b/integrationTests/ts/__tests__/integration.test.ts @@ -18,7 +18,7 @@ import { DeployedContracts, } from "maci-cli"; import { getDefaultSigner } from "maci-contracts"; -import { MaciState, MaxValues, TreeDepths } from "maci-core"; +import { MaciState, TreeDepths } from "maci-core"; import { genPubKey, genRandomSalt } from "maci-crypto"; import { Keypair, PCommand, PrivKey, PubKey } from "maci-domainobjs"; @@ -105,11 +105,6 @@ describe("Integration tests", function test() { // 3. deploy maci contracts = await deploy({ stateTreeDepth: STATE_TREE_DEPTH, initialVoiceCredits, signer }); - const maxValues: MaxValues = { - maxMessages: 25, - maxVoteOptions: 25, - }; - // 4. create a poll await deployPoll({ pollDuration: duration, @@ -134,7 +129,6 @@ describe("Integration tests", function test() { pollId = maciState.deployPoll( BigInt(Date.now() + duration * 60000), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, diff --git a/subgraph/src/maci.ts b/subgraph/src/maci.ts index 0511eb0c97..39ea8c25a0 100644 --- a/subgraph/src/maci.ts +++ b/subgraph/src/maci.ts @@ -6,7 +6,7 @@ import { Poll } from "../generated/schema"; import { Poll as PollTemplate } from "../generated/templates"; import { Poll as PollContract } from "../generated/templates/Poll/Poll"; -import { ONE_BIG_INT } from "./utils/constants"; +import { ONE_BIG_INT, MESSAGE_TREE_ARITY } from "./utils/constants"; import { createOrLoadMACI, createOrLoadUser, createOrLoadAccount } from "./utils/entity"; export function handleDeployPoll(event: DeployPollEvent): void { @@ -14,15 +14,14 @@ export function handleDeployPoll(event: DeployPollEvent): void { const poll = new Poll(event.params.pollAddr.poll); const contract = PollContract.bind(event.params.pollAddr.poll); - const maxValues = contract.maxValues(); const treeDepths = contract.treeDepths(); const durations = contract.getDeployTimeAndDuration(); poll.pollId = event.params._pollId; poll.messageProcessor = event.params.pollAddr.messageProcessor; poll.tally = event.params.pollAddr.tally; - poll.maxMessages = maxValues.value0; - poll.maxVoteOption = maxValues.value1; + poll.maxMessages = GraphBN.fromI32(MESSAGE_TREE_ARITY ** treeDepths.getMessageTreeDepth()); + poll.maxVoteOption = GraphBN.fromI32(MESSAGE_TREE_ARITY ** treeDepths.getVoteOptionTreeDepth()); poll.treeDepth = GraphBN.fromI32(treeDepths.value0); poll.duration = durations.value1; poll.mode = GraphBN.fromI32(event.params._mode); diff --git a/subgraph/src/utils/constants.ts b/subgraph/src/utils/constants.ts index cdd436764c..69662db273 100644 --- a/subgraph/src/utils/constants.ts +++ b/subgraph/src/utils/constants.ts @@ -1,3 +1,4 @@ import { BigInt as GraphBN } from "@graphprotocol/graph-ts"; export const ONE_BIG_INT = GraphBN.fromU32(1); +export const MESSAGE_TREE_ARITY = 5; diff --git a/subgraph/tests/common.ts b/subgraph/tests/common.ts index d3cec07095..e73a59702b 100644 --- a/subgraph/tests/common.ts +++ b/subgraph/tests/common.ts @@ -9,11 +9,6 @@ export const DEFAULT_MESSAGE_PROCESSOR_ADDRESS = Address.fromString("0x000000000 export const DEFAULT_TALLY_ADDRESS = Address.fromString("0x0000000000000000000000000000000000000003"); export function mockPollContract(): void { - createMockedFunction(DEFAULT_POLL_ADDRESS, "maxValues", "maxValues():(uint256,uint256)").returns([ - ethereum.Value.fromI32(10), - ethereum.Value.fromI32(20), - ]); - createMockedFunction(DEFAULT_POLL_ADDRESS, "treeDepths", "treeDepths():(uint8,uint8,uint8,uint8)").returns([ ethereum.Value.fromI32(1), ethereum.Value.fromI32(2), diff --git a/website/versioned_docs/version-v2.0_alpha/core-concepts/key-change.md b/website/versioned_docs/version-v2.0_alpha/core-concepts/key-change.md index 593c8b17b0..52ee9a765c 100644 --- a/website/versioned_docs/version-v2.0_alpha/core-concepts/key-change.md +++ b/website/versioned_docs/version-v2.0_alpha/core-concepts/key-change.md @@ -85,7 +85,6 @@ user2StateIndex = maciState.signUp(user2Keypair.pubKey, voiceCreditBalance, BigI pollId = maciState.deployPoll( duration, BigInt(Math.floor(Date.now() / 1000) + duration), - maxValues, treeDepths, messageBatchSize, coordinatorKeypair, diff --git a/website/versioned_docs/version-v2.0_alpha/core-concepts/spec.md b/website/versioned_docs/version-v2.0_alpha/core-concepts/spec.md index 7397696aeb..a126a1bc71 100644 --- a/website/versioned_docs/version-v2.0_alpha/core-concepts/spec.md +++ b/website/versioned_docs/version-v2.0_alpha/core-concepts/spec.md @@ -569,15 +569,15 @@ The integration tests and shell scripts in the `cli` directory provide examples ### 5.1. MACI -| Function | Permissions | Notes | -| ----------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -| `init(VkRegistry _vkRegistry, MessageAqFactory _messageAqFactory)` | Coordinator only | Initialise factory, helper and registry contracts that share equal ownership | -| `signUp(PubKey memory _pubKey, bytes memory _signUpGatekeeperData, bytes memory _initialVoiceCreditProxyData)` | Executable only during the sign-up period and after initialisation | Participant registration and voice credit assignment | -| `mergeStateAqSubRoots(uint256 _numSrQueueOps, uint256 _pollId)` | Executable only by poll contract `_pollId` and after initialisation | Merge queued state leaves to form the state tree subroots | -| `mergeStateAq(uint256 _pollId)` | Executable only by poll contract `_pollId` and after initialisation | Merge the state subroots to form the state root | -| `getStateTreeRoot()` | Non-applicable | Query the state root | -| `deployPoll(uint256 _duration, MaxValues memory _maxValues, TreeDepths memory _treeDepths, PubKey memory _coordinatorPubKey)` | Executable only after initialisation | Create a new poll | -| `getPoll(uint256 _pollId)` | Non-applicable | Query a poll address | +| Function | Permissions | Notes | +| -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------- | +| `init(VkRegistry _vkRegistry, MessageAqFactory _messageAqFactory)` | Coordinator only | Initialise factory, helper and registry contracts that share equal ownership | +| `signUp(PubKey memory _pubKey, bytes memory _signUpGatekeeperData, bytes memory _initialVoiceCreditProxyData)` | Executable only during the sign-up period and after initialisation | Participant registration and voice credit assignment | +| `mergeStateAqSubRoots(uint256 _numSrQueueOps, uint256 _pollId)` | Executable only by poll contract `_pollId` and after initialisation | Merge queued state leaves to form the state tree subroots | +| `mergeStateAq(uint256 _pollId)` | Executable only by poll contract `_pollId` and after initialisation | Merge the state subroots to form the state root | +| `getStateTreeRoot()` | Non-applicable | Query the state root | +| `deployPoll(uint256 _duration, TreeDepths memory _treeDepths, PubKey memory _coordinatorPubKey)` | Executable only after initialisation | Create a new poll | +| `getPoll(uint256 _pollId)` | Non-applicable | Query a poll address | ### 5.2. Poll @@ -596,10 +596,10 @@ The integration tests and shell scripts in the `cli` directory provide examples ### 5.3. PollFactory -| Function | Permissions | Notes | -| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | --------------------------------------- | -| `setMessageAqFactory(MessageAqFactory _messageAqFactory)` | Coordinator only | Initialise the message factory contract | -| `deploy(uint256 _duration, MaxValues memory _maxValues, TreeDepths memory _treeDepths, BatchSizes memory _batchSizes, PubKey memory _coordinatorPubKey, VkRegistry _vkRegistry, IMACI _maci, address _pollOwner)` | Coordinator only | Create a new poll | +| Function | Permissions | Notes | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------- | --------------------------------------- | +| `setMessageAqFactory(MessageAqFactory _messageAqFactory)` | Coordinator only | Initialise the message factory contract | +| `deploy(uint256 _duration, TreeDepths memory _treeDepths, BatchSizes memory _batchSizes, PubKey memory _coordinatorPubKey, VkRegistry _vkRegistry, IMACI _maci, address _pollOwner)` | Coordinator only | Create a new poll | ### 5.4. VkRegistry @@ -663,16 +663,16 @@ The state tree, message tree, and vote option trees all have an arity of 5. As s | Input signal | Description | | -------------------------------- | --------------------------------------------------------------------------------------- | -| `inputHash` | The SHA256 hash of inputs supplied by the contract | -| `packedVals` | As described below | +| `numSignUps` | Number of users that have completed the sign up | +| `index` | The batch index of current message batch | | `pollEndTimestamp` | The Unix timestamp at which the poll ends | | `msgRoot` | The root of the message tree | | `msgs` | The batch of messages as an array of arrays | | `msgSubrootPathElements` | As described below | -| `coordinatorPubKeyHash` | $\mathsf{poseidon_2}([cPk_x, cPk_y])$ | +| `coordinatorPublicKeyHash` | $\mathsf{poseidon_2}([cPk_x, cPk_y])$ | | `newSbCommitment` | As described below | | `coordPrivKey` | The coordinator's private key | -| `coordPubKey` | The coordinator's public key | +| `batchEndIndex` | The last batch index | | `encPubKeys` | The public keys used to generate shared ECDH encryption keys to encrypt the messages | | `currentStateRoot` | The state root before the commands are applied | | `currentStateLeaves` | The state leaves upon which messages are applied | @@ -687,35 +687,6 @@ The state tree, message tree, and vote option trees all have an arity of 5. As s | `currentVoteWeights` | The existing vote weight for the vote option in the ballot which each command refers to | | `currentVoteWeightsPathElements` | The Merkle path from each vote weight to the vote option root in its ballot | -##### `inputHash` - -All inputs to this circuit are private except for `inputHash`. To save gas during verification, the `PollProcessorAndTallyer` contract hashes the following values using SHA256 and uses the hash as the sole element of $ic$: - -1. `packedVals` -2. `coordinatorPubKeyHash` -3. `msgRoot` -4. `currentSbCommitment` -5. `newSbCommitment` -6. `pollEndTimestamp` - -The hash is computed using the `sha256` Solidity function and is then subject to modulo $p$. - -##### `packedVals` - -`packedVals` is the following values represented as one field element. Consider that a field element is roughly 253 bits. The big-endian bit-representation is as such: - -| Bits | Value | -| ----------- | -------------------------- | -| 1st 53 bits | `0` | -| 2nd 50 bits | `batchEndIndex` | -| 3rd 50 bits | `currentMessageBatchIndex` | -| 4th 50 bits | `numSignUps` | -| 5th 50 bits | `maxVoteOptions` | - -For instance, if `maxVoteOptions` is 25 and `batchEndIndex` is `5`, and all other values are 0, the following is the `packedVals` representation in hexadecimal: - -`140000000000000000000000000000000000019` - ##### `currentSbCommitment` and `newSbCommitment` The `currentSbCommitment` is the $\mathsf{poseidon_3}$ hash of the state tree root, the ballot tree root, and a random salt. The purpose of the random salt, which should be unique to each batch, is to ensure that the value of `currentSbCommitment` always changes even if all the commands in a batch are invalid and therefore do not change the state tree or ballot tree root. @@ -754,14 +725,12 @@ This method requires fewer circuit constraints than if we verified a Merkle proo #### Statements that the circuit proves -1. That the prover knows the preimage to `inputHash` (see above) -2. That the prover knows the preimage to `currentSbCommitment` (that is, the state root, ballot root, and `currentSbSalt`) -3. That `maxVoteOptions <= (5 ^ voteOptionTreeDepth)` -4. That `numSignUps <== (5 ^ stateTreeDepth)` -5. That `coordPubKey` is correctly derived from `coordPrivKey` -6. That `coordPubKey` is the preimage to the Poseidon hash of `coordPubKey` (provided by the contract) -7. That each message in `msgs` exists in the message tree -8. That after decrypting and applying each message, in reverse order, to the corresponding state and ballot leaves, the new state root, new ballot root, and `newSbSalt` are the preimage to `newSbCommitment` +1. That the prover knows the preimage to `currentSbCommitment` (that is, the state root, ballot root, and `currentSbSalt`) +2. That `maxVoteOptions <= (5 ^ voteOptionTreeDepth)` +3. That `numSignUps <== (5 ^ stateTreeDepth)` +4. That `coordinatorPublicKeyHash` is a hash of public key that is correctly derived from `coordPrivKey` +5. That each message in `msgs` exists in the message tree +6. That after decrypting and applying each message, in reverse order, to the corresponding state and ballot leaves, the new state root, new ballot root, and `newSbSalt` are the preimage to `newSbCommitment` #### How messages are decrypted and applied @@ -858,8 +827,8 @@ The coordinator uses the ballot tallying circuit (`tallyVotes.circom`) to genera | Input signal | Description | | --------------------------------------- | ---------------------------------------------------------------- | -| `inputHash` | The SHA256 hash of inputs supplied by the contract | -| `packedVals` | As described below | +| `numSignUps` | The number of users that signup | +| `index` | Start index of given batch | | `sbCommitment` | As described below | | `currentTallyCommitment` | As described below | | `newTallyCommitment` | As described below | @@ -879,35 +848,6 @@ The coordinator uses the ballot tallying circuit (`tallyVotes.circom`) to genera | `newPerVOSpentVoiceCreditsRootSalt` | A random value | | `newSpentVoiceCreditSubtotalSalt` | A random value | -##### `inputHash` - -All inputs to this circuit are private except for `inputHash`. To save gas during verification, the `PollProcessorAndTallyer` contract hashes the following values using SHA256 and uses the hash as the sole element of $ic$: - -1. `packedVals` -2. `sbCommitment` -3. `currentTallyCommitment` -4. `newTallyCommitment` - -The hash is computed using the `sha256` Solidity function and is then subject to modulo $p$. - -##### `packedVals` - -`packedVals` is the following values represented as one field element. Consider that a field element is roughly 253 bits. The big-endian bit-representation is as such: - -| Bits | Value | -| ----------- | ----------------- | -| 1st 53 bits | `0` | -| 2nd 50 bits | `0` | -| 3rd 50 bits | `0` | -| 4th 50 bits | `numSignUps` | -| 5th 50 bits | `batchStartIndex` | - -`numSignUps`, a value provided by the contract, is the number of users who have signed up. This is one less than the number of leaves inserted in the state tree (since the 0th state leaf is a blank state leaf [2.8.1]). `batchStartIndex` is the ballot tree index at which the batch begins. - -For instance, if `numSignUps` is 25 and the batch index is `5`, and all other values are 0, the following is the `packedVals` representation in hexadecimal: - -`64000000000005` - ##### `sbCommitment` The commitment to `stateRoot`, `ballotRoot`, and `sbSalt`: @@ -934,11 +874,10 @@ $\mathsf{poseidon_3}([tc_r, tc_t, tc_p])$ #### Statements that the circuit proves 1. That the coordinator knows the preimage of `sbCommitment` (see above) -2. That the coordinator knows the preimage of `inputHash` (see above) -3. That `batchStartIndex` is less than or equal to `numSignUps` -4. That each ballot in `ballots` is in a member of the ballot tree with the Merkle root `ballotRoot` at indices `batchStartIndex` to `batchStartIndex + (5 ** intStateTreeDepth)` -5. That each set of votes (`votes[i]`) has the Merkle root $blt_r$ whose value equals `ballots[i][1]` -6. That the tally is valid, which is: +2. That `index` is less than or equal to `numSignUps` +3. That each ballot in `ballots` is in a member of the ballot tree with the Merkle root `ballotRoot` at indices `batchStartIndex` to `batchStartIndex + (5 ** intStateTreeDepth)` +4. That each set of votes (`votes[i]`) has the Merkle root $blt_r$ whose value equals `ballots[i][1]` +5. That the tally is valid, which is: - That the sum of votes per vote option is correct - That the sum of voice credits per vote option is correct - That the subtotal of the spent voice credits is correct diff --git a/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/MACI.md b/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/MACI.md index 3921e12a16..682b57cdf1 100644 --- a/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/MACI.md +++ b/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/MACI.md @@ -121,15 +121,10 @@ function deployPoll( revert InvalidPubKey(); } - MaxValues memory maxValues = MaxValues({ - maxMessages: uint256(MESSAGE_TREE_ARITY) ** _treeDepths.messageTreeDepth, - maxVoteOptions: uint256(MESSAGE_TREE_ARITY) ** _treeDepths.voteOptionTreeDepth - }); - // the owner of the message processor and tally contract will be the msg.sender address _msgSender = msg.sender; - address p = pollFactory.deploy(_duration, maxValues, _treeDepths, _coordinatorPubKey, address(this)); + address p = pollFactory.deploy(_duration, _treeDepths, _coordinatorPubKey, address(this)); address mp = messageProcessorFactory.deploy(_verifier, _vkRegistry, p, _msgSender, _mode); address tally = tallyFactory.deploy(_verifier, _vkRegistry, p, mp, _msgSender, _mode); diff --git a/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/Params.md b/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/Params.md index c969a317ec..732e0b2121 100644 --- a/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/Params.md +++ b/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/Params.md @@ -20,12 +20,6 @@ struct TreeDepths { uint8 voteOptionTreeDepth; } -/// @notice A struct holding the max values for the poll -struct MaxValues { - uint256 maxMessages; - uint256 maxVoteOptions; -} - /// @notice A struct holding the external contracts /// that are to be passed to a Poll contract on /// deployment diff --git a/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/Poll.md b/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/Poll.md index b792a93536..60a32cd203 100644 --- a/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/Poll.md +++ b/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/Poll.md @@ -24,7 +24,7 @@ The `publishMessage` function looks as follows: ```js function publishMessage(Message memory _message, PubKey calldata _encPubKey) public virtual isWithinVotingDeadline { // we check that we do not exceed the max number of messages - if (numMessages >= maxValues.maxMessages) revert TooManyMessages(); + if (numMessages >= maxMessages) revert TooManyMessages(); // check if the public key is on the curve if (!CurveBabyJubJub.isOnCurve(_encPubKey.x, _encPubKey.y)) { @@ -72,7 +72,7 @@ function mergeMaciState() public isAfterVotingDeadline { // dynamically determine the actual depth of the state tree uint8 depth = 1; - while (uint40(2) ** uint40(depth) < _numSignups) { + while (uint40(1 << depth) < numberOfLeaves) { depth++; } diff --git a/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/PollFactory.md b/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/PollFactory.md index 8b94f78eeb..574603b139 100644 --- a/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/PollFactory.md +++ b/website/versioned_docs/version-v2.0_alpha/developers-references/smart-contracts/PollFactory.md @@ -14,19 +14,10 @@ Code location: [PollFactory.sol](https://github.com/privacy-scaling-explorations ```ts function deploy( _duration, - MaxValues calldata _maxValues, TreeDepths calldata _treeDepths, PubKey calldata _coordinatorPubKey, address _maci ) public virtual returns (address pollAddr) { - /// @notice Validate _maxValues - /// maxVoteOptions must be less than 2 ** 50 due to circuit limitations; - /// it will be packed as a 50-bit value along with other values as one - /// of the inputs (aka packedVal) - if (_maxValues.maxVoteOptions >= (2 ** 50)) { - revert InvalidMaxValues(); - } - /// @notice deploy a new AccQueue contract to store messages AccQueue messageAq = new AccQueueQuinaryMaci(_treeDepths.messageTreeSubDepth); @@ -34,7 +25,7 @@ function deploy( ExtContracts memory extContracts = ExtContracts({ maci: IMACI(_maci), messageAq: messageAq }); // deploy the poll - Poll poll = new Poll(_duration, _maxValues, _treeDepths, _coordinatorPubKey, extContracts); + Poll poll = new Poll(_duration, _treeDepths, _coordinatorPubKey, extContracts); // Make the Poll contract own the messageAq contract, so only it can // run enqueue/merge diff --git a/website/versioned_docs/version-v2.0_alpha/developers-references/zk-snark-circuits/processMessages.md b/website/versioned_docs/version-v2.0_alpha/developers-references/zk-snark-circuits/processMessages.md index a36743da8b..0597b56bfd 100644 --- a/website/versioned_docs/version-v2.0_alpha/developers-references/zk-snark-circuits/processMessages.md +++ b/website/versioned_docs/version-v2.0_alpha/developers-references/zk-snark-circuits/processMessages.md @@ -37,59 +37,30 @@ A version working with non quadratic voting (non-qv) is also [available](https:/ | Input signal | Description | | -------------------------------- | --------------------------------------------------------------------------------------- | -| `inputHash` | The SHA256 hash of inputs supplied by the contract | -| `packedVals` | Described below | +| `numSignUps` | Number of users that have completed the sign up | +| `index` | The batch index of current message batch | | `pollEndTimestamp` | The Unix timestamp at which the poll ends | | `msgRoot` | The root of the message tree | | `msgs` | The batch of messages as an array of arrays | -| `msgSubrootPathElements` | Described below | -| `coordinatorPubKeyHash` | $poseidon_2([cPk_x, cPk_y])$ | -| `newSbCommitment` | Described below | +| `msgSubrootPathElements` | As described below | +| `coordinatorPublicKeyHash` | $\mathsf{poseidon_2}([cPk_x, cPk_y])$ | +| `newSbCommitment` | As described below | | `coordPrivKey` | The coordinator's private key | -| `coordPubKey` | The coordinator's public key | +| `batchEndIndex` | The last batch index | | `encPubKeys` | The public keys used to generate shared ECDH encryption keys to encrypt the messages | | `currentStateRoot` | The state root before the commands are applied | | `currentStateLeaves` | The state leaves upon which messages are applied | | `currentStateLeavesPathElements` | The Merkle path to each incremental state root | -| `currentSbCommitment` | Described below | -| `currentSbSalt` | Described below | -| `newSbCommitment` | Described below | -| `newSbSalt` | Described below | +| `currentSbCommitment` | As described below | +| `currentSbSalt` | As described below | +| `newSbCommitment` | As described below | +| `newSbSalt` | As described below | | `currentBallotRoot` | The root of the ballot tree before messages are applied | | `currentBallots` | The ballots upon which ballots are applied | | `currentBallotsPathElements` | The Merkle path to each incremental ballot root | | `currentVoteWeights` | The existing vote weight for the vote option in the ballot which each command refers to | | `currentVoteWeightsPathElements` | The Merkle path from each vote weight to the vote option root in its ballot | -##### `inputHash` - -All inputs to this circuit are private except for `inputHash`. To save gas during verification, the `MessageProcessor` contract hashes the following values using SHA256 and uses the hash as the sole element of $ic$: - -1. `packedVals` -2. `coordinatorPubKeyHash` -3. `msgRoot` -4. `currentSbCommitment` -5. `newSbCommitment` -6. `pollEndTimestamp` - -The hash is computed using the `sha256` Solidity function and is then subject to modulo $p$. - -##### `packedVals` - -`packedVals` is the following values represented as one field element. Consider that a field element is roughly 253 bits. The big-endian bit-representation is as such: - -| Bits | Value | -| ----------- | -------------------------- | -| 1st 53 bits | `0` | -| 2nd 50 bits | `batchEndIndex` | -| 3rd 50 bits | `currentMessageBatchIndex` | -| 4th 50 bits | `numSignUps` | -| 5th 50 bits | `maxVoteOptions` | - -For instance, if `maxVoteOptions` is 25 and `batchEndIndex` is `5`, and all other values are 0, the following is the `packedVals` representation in hexadecimal: - -`140000000000000000000000000000000000019` - ##### `currentSbCommitment` and `newSbCommitment` The `currentSbCommitment` is the $poseidon_3$ hash of the state tree root, the ballot tree root, and a random salt. The purpose of the random salt, which should be unique to each batch, is to ensure that the value of `currentSbCommitment` always changes even if all the commands in a batch are invalid and therefore do not change the state tree or ballot tree root. @@ -128,11 +99,9 @@ This method requires fewer circuit constraints than if we verified a Merkle proo #### Statements that the circuit proves -1. That the prover knows the preimage to `inputHash` (see above) -2. That the prover knows the preimage to `currentSbCommitment` (that is, the state root, ballot root, and `currentSbSalt`) -3. That `maxVoteOptions <= (5 ^ voteOptionTreeDepth)` -4. That `numSignUps <= (2 ^ stateTreeDepth)` -5. That `coordPubKey` is correctly derived from `coordPrivKey` -6. That `coordPubKey` is the preimage to the Poseidon hash of `coordPubKey` (provided by the contract) -7. That each message in `msgs` exists in the message tree -8. That after decrypting and applying each message, in reverse order, to the corresponding state and ballot leaves, the new state root, new ballot root, and `newSbSalt` are the preimage to `newSbCommitment` +1. That the prover knows the preimage to `currentSbCommitment` (that is, the state root, ballot root, and `currentSbSalt`) +2. That `maxVoteOptions <= (5 ^ voteOptionTreeDepth)` +3. That `numSignUps <= (2 ^ stateTreeDepth)` +4. That `coordinatorPublicKeyHash` is a hash of public key that is correctly derived from `coordPrivKey` +5. That each message in `msgs` exists in the message tree +6. That after decrypting and applying each message, in reverse order, to the corresponding state and ballot leaves, the new state root, new ballot root, and `newSbSalt` are the preimage to `newSbCommitment` diff --git a/website/versioned_docs/version-v2.0_alpha/developers-references/zk-snark-circuits/tallyVotes.md b/website/versioned_docs/version-v2.0_alpha/developers-references/zk-snark-circuits/tallyVotes.md index 01febd3ac9..854af64e9e 100644 --- a/website/versioned_docs/version-v2.0_alpha/developers-references/zk-snark-circuits/tallyVotes.md +++ b/website/versioned_docs/version-v2.0_alpha/developers-references/zk-snark-circuits/tallyVotes.md @@ -25,8 +25,8 @@ A version working with non quadratic voting (non-qv) is also [available](https:/ | Input signal | Description | | --------------------------------------- | ---------------------------------------------------------------- | -| `inputHash` | The SHA256 hash of inputs supplied by the contract | -| `packedVals` | Described below | +| `numSignUps` | The number of users that signup | +| `index` | Start index of given batch | | `sbCommitment` | Described below | | `currentTallyCommitment` | Described below | | `newTallyCommitment` | Described below | @@ -46,35 +46,6 @@ A version working with non quadratic voting (non-qv) is also [available](https:/ | `newPerVOSpentVoiceCreditsRootSalt` | A random value | | `newSpentVoiceCreditSubtotalSalt` | A random value | -##### `inputHash` - -All inputs to this circuit are private except for `inputHash`. To save gas during verification, the `Tally` contract hashes the following values using SHA256 and uses the hash as the sole element of $ic$: - -1. `packedVals` -2. `sbCommitment` -3. `currentTallyCommitment` -4. `newTallyCommitment` - -The hash is computed using the `sha256` Solidity function and is then subject to modulo $p$. - -##### `packedVals` - -`packedVals` is the following values represented as one field element. Consider that a field element is roughly 253 bits. The big-endian bit-representation is as such: - -| Bits | Value | -| ----------- | ----------------- | -| 1st 53 bits | `0` | -| 2nd 50 bits | `0` | -| 3rd 50 bits | `0` | -| 4th 50 bits | `numSignUps` | -| 5th 50 bits | `batchStartIndex` | - -`numSignUps`, a value provided by the contract, is the number of users who have signed up. This is one less than the number of leaves inserted in the state tree (since the 0th state leaf is a [blank state leaf](/docs/core-concepts/state-leaf)). `batchStartIndex` is the ballot tree index at which the batch begins. - -For instance, if `numSignUps` is 25 and the batch index is `5`, and all other values are 0, the following is the `packedVals` representation in hexadecimal: - -`64000000000005` - ##### `sbCommitment` The commitment to `stateRoot`, `ballotRoot`, and `sbSalt`: @@ -101,9 +72,8 @@ $poseidon_3([tc_r, tc_t, tc_p])$ #### Statements that the circuit proves 1. That the coordinator knows the preimage of `sbCommitment` -2. That the coordinator knows the preimage of `inputHash` -3. That `batchStartIndex` is less than or equal to `numSignUps` -4. That each ballot in `ballots` is in a member of the ballot tree with the Merkle root `ballotRoot` at indices `batchStartIndex` to `batchStartIndex + (5 ** intStateTreeDepth)` -5. That each set of votes (`votes[i]`) has the Merkle root $blt_r$ whose value equals `ballots[i][1]` -6. That the tally is valid, which is: +2. That `index` is less than or equal to `numSignUps` +3. That each ballot in `ballots` is in a member of the ballot tree with the Merkle root `ballotRoot` at indices `batchStartIndex` to `batchStartIndex + (5 ** intStateTreeDepth)` +4. That each set of votes (`votes[i]`) has the Merkle root $blt_r$ whose value equals `ballots[i][1]` +5. That the tally is valid, which is: - That the sum of votes per vote option is correct diff --git a/website/versioned_docs/version-v2.0_alpha/quick-start/installation.md b/website/versioned_docs/version-v2.0_alpha/quick-start/installation.md index fb47444d50..3232f3d415 100644 --- a/website/versioned_docs/version-v2.0_alpha/quick-start/installation.md +++ b/website/versioned_docs/version-v2.0_alpha/quick-start/installation.md @@ -101,25 +101,45 @@ Edit `circuits/circom/circuits` to include the circuits you would like to compil "file": "processMessages", "template": "ProcessMessages", "params": [10, 2, 1, 2], - "pubs": ["inputHash"] + "pubs": [ + "numSignUps", + "index", + "batchEndIndex", + "msgRoot", + "currentSbCommitment", + "newSbCommitment", + "pollEndTimestamp", + "actualStateTreeDepth", + "coordinatorPublicKeyHash" + ] }, "ProcessMessagesNonQv_10-2-1-2_test": { "file": "processMessagesNonQv", "template": "ProcessMessagesNonQv", "params": [10, 2, 1, 2], - "pubs": ["inputHash"] + "pubs": [ + "numSignUps", + "index", + "batchEndIndex", + "msgRoot", + "currentSbCommitment", + "newSbCommitment", + "pollEndTimestamp", + "actualStateTreeDepth", + "coordinatorPublicKeyHash" + ] }, "TallyVotes_10-1-2_test": { "file": "tallyVotes", "template": "TallyVotes", "params": [10, 1, 2], - "pubs": ["inputHash"] + "pubs": ["index", "numSignUps", "sbCommitment", "currentTallyCommitment", "newTallyCommitment"] }, "TallyVotesNonQv_10-1-2_test": { "file": "tallyVotesNonQv", "template": "TallyVotesNonQv", "params": [10, 1, 2], - "pubs": ["inputHash"] + "pubs": ["index", "numSignUps", "sbCommitment", "currentTallyCommitment", "newTallyCommitment"] } } ```