Skip to main content
Version: v2.0_alpha

MACI Tally Votes Circuit

Repo link

Parameters

#ParameterDescription
0State tree depthAllows (5n)(5^{n}) signups.
1State leaf batch depthAllows (5n)(5^{n}) users' votes to be processed per batch.
2Vote option tree depthAllows (5n)(5^{n}) vote options.

TallyVotes

info

A version working with non quadratic voting (non-qv) is also available. This version is called tallyVotesNonQv and is to be used when the Poll is not using the quadratic voting feature. Note that by default MACI works with quadratic voting.

Input signals

Input signalDescription
inputHashThe SHA256 hash of inputs supplied by the contract
packedValsDescribed below
sbCommitmentDescribed below
currentTallyCommitmentDescribed below
newTallyCommitmentDescribed below
stateRootThe root of the state tree after all messages have been applied
ballotRootThe root of the ballot tree after all messages have been applied
sbSaltThe salt used to produce sbCommitment
ballotsThe ballots in the batch being tallied
ballotPathElementsThe Merkle path to each ballot leaf
votesThe votes in each ballot cast per result
currentResultsThe current tally of votes per vote option
currentResultsRootSaltA random value
currentSpentVoiceCreditSubtotalThe subtotal of voice credits spent across all vote options
currentSpentVoiceCreditSubtotalSaltA random value
currentPerVOSpentVoiceCreditsThe voice credits spent on each vote option so far
currentPerVOSpentVoiceCreditsRootSaltA random value
newResultsRootSaltA random value
newPerVOSpentVoiceCreditsRootSaltA random value
newSpentVoiceCreditSubtotalSaltA 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 icic:

  1. packedVals
  2. sbCommitment
  3. currentTallyCommitment
  4. newTallyCommitment

The hash is computed using the sha256 Solidity function and is then subject to modulo pp.

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:

BitsValue
1st 53 bits0
2nd 50 bits0
3rd 50 bits0
4th 50 bitsnumSignUps
5th 50 bitsbatchStartIndex

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). 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:

poseidon3([stateRoot,ballotRoot,sbSalt])poseidon_3([stateRoot, ballotRoot, sbSalt])

Proving preimage of sbCommitment is one out of the several steps required to prove that the votes were tallied correctly. By establishing that the coordinator knows ballotRoot, the coordinator can (using other parts of the circuit) prove that they know the preimage of the ballot leaves in the batch being tallied.

currentTallyCommitment and newTallyCommitment

A tally is represented by a tally commitment, which is the poseidon3poseidon_3 hash of:

  1. tcrtc_r: a commitment to the votes per option
    • This is the hash of the Merkle root rrr_r of the votes and a salt rsr_s, computed as poseidon2([rr,rs])poseidon_2([r_r, r_s])
  2. tcttc_t: a commitment to the total spent voice credits
    • This is the hash of the total spent voice credits tct_c and a salt tst_s, computed as poseidon2([tc,ts])poseidon_2([t_c, t_s])
  3. tcptc_p: a commitment to the spent voice credits per vote option
    • This is the hash of the Merkle root of the spent voice credits per vote option pvp_v and a salt psp_s, computed as poseidon2([pv,ps])poseidon_2([p_v, p_s])

The tally commitment is computed as such:

poseidon3([tcr,tct,tcp])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 bltrblt_r whose value equals ballots[i][1]
  6. That the tally is valid, which is:
    • That the sum of votes per vote option is correct