Skip to content

Commit

Permalink
feat(qv): add optional flag to use quadratic voting or not in MACI
Browse files Browse the repository at this point in the history
Amend all parts of the code to support both quadratic and non quadratic voting. Circuits for non
quadratic voting have a slight reduction in constraints (especially processMessages). Tests added
for the feature in both cli e2e, core e2e and unit, and circuits unit tests.
  • Loading branch information
ctrlc03 committed Feb 2, 2024
1 parent a8ee053 commit 86ba854
Show file tree
Hide file tree
Showing 31 changed files with 1,777 additions and 173 deletions.
12 changes: 12 additions & 0 deletions circuits/circom/circuits.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,24 @@
"params": [10, 2, 1, 2],
"pubs": ["inputHash"]
},
"ProcessMessagesNonQv_10-2-1-2_test": {
"file": "processMessagesNonQv",
"template": "ProcessMessagesNonQv",
"params": [10, 2, 1, 2],
"pubs": ["inputHash"]
},
"TallyVotes_10-1-2_test": {
"file": "tallyVotes",
"template": "TallyVotes",
"params": [10, 1, 2],
"pubs": ["inputHash"]
},
"TallyVotesNonQv_10-1-2_test": {
"file": "tallyVotesNonQv",
"template": "TallyVotesNonQv",
"params": [10, 1, 2],
"pubs": ["inputHash"]
},
"SubsidyPerBatch_10-1-2_test": {
"file": "subsidy",
"template": "SubsidyPerBatch",
Expand Down
14 changes: 7 additions & 7 deletions circuits/circom/hasherSha256.circom
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ template Sha256Hasher3() {
signal output hash;

component hasher = Sha256Hasher(length);
for (var i = 0; i < length; i ++) {
for (var i = 0; i < length; i++) {
hasher.in[i] <== in[i];
}
hash <== hasher.hash;
Expand All @@ -37,7 +37,7 @@ template Sha256Hasher4() {
signal output hash;

component hasher = Sha256Hasher(length);
for (var i = 0; i < length; i ++) {
for (var i = 0; i < length; i++) {
hasher.in[i] <== in[i];
}
hash <== hasher.hash;
Expand All @@ -51,7 +51,7 @@ template Sha256Hasher5() {
signal output hash;

component hasher = Sha256Hasher(length);
for (var i = 0; i < length; i ++) {
for (var i = 0; i < length; i++) {
hasher.in[i] <== in[i];
}
hash <== hasher.hash;
Expand All @@ -65,7 +65,7 @@ template Sha256Hasher6() {
signal output hash;

component hasher = Sha256Hasher(length);
for (var i = 0; i < length; i ++) {
for (var i = 0; i < length; i++) {
hasher.in[i] <== in[i];
}
hash <== hasher.hash;
Expand All @@ -79,7 +79,7 @@ template Sha256Hasher10() {
signal output hash;

component hasher = Sha256Hasher(length);
for (var i = 0; i < length; i ++) {
for (var i = 0; i < length; i++) {
hasher.in[i] <== in[i];
}
hash <== hasher.hash;
Expand All @@ -98,8 +98,8 @@ template Sha256Hasher(length) {
}

component sha = Sha256(inBits);
for (var i = 0; i < length; i ++) {
for (var j = 0; j < 256; j ++) {
for (var i = 0; i < length; i++) {
for (var j = 0; j < 256; j++) {
sha.in[(i * 256) + 255 - j] <== n2b[i].out[j];
}
}
Expand Down
2 changes: 1 addition & 1 deletion circuits/circom/messageHasher.circom
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ template MessageHasher() {
component hasher = Hasher13();

// we add all parts of the msg
for (var i = 0; i < 11; i ++) {
for (var i = 0; i < 11; i++) {
hasher.in[i] <== in[i];
}
hasher.in[11] <== encPubKey[0];
Expand Down
4 changes: 2 additions & 2 deletions circuits/circom/messageToCommand.circom
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ template MessageToCommand() {

// save the decrypted message into a packed command signal
signal packedCommand[PACKED_CMD_LENGTH];
for (var i = 0; i < PACKED_CMD_LENGTH; i ++) {
for (var i = 0; i < PACKED_CMD_LENGTH; i++) {
packedCommand[i] <== decryptor.decrypted[i];
}

Expand All @@ -80,7 +80,7 @@ template MessageToCommand() {

// this could be removed and instead
// use packedCommand as output
for (var i = 0; i < PACKED_CMD_LENGTH; i ++) {
for (var i = 0; i < PACKED_CMD_LENGTH; i++) {
packedCommandOut[i] <== packedCommand[i];
}
}
2 changes: 1 addition & 1 deletion circuits/circom/messageValidator.circom
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ template MessageValidator() {
validSignature.R8[0] <== sigR8[0];
validSignature.R8[1] <== sigR8[1];
validSignature.S <== sigS;
for (var i = 0; i < PACKED_CMD_LENGTH; i ++) {
for (var i = 0; i < PACKED_CMD_LENGTH; i++) {
validSignature.preimage[i] <== cmd[i];
}

Expand Down
84 changes: 84 additions & 0 deletions circuits/circom/messageValidatorNonQv.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
pragma circom 2.0.0;

// local imports
include "./verifySignature.circom";
include "./utils.circom";

// template that validates whether a message
// is valid or not
// @note it does not do quadratic voting
template MessageValidatorNonQv() {
// a) Whether the state leaf index is valid
signal input stateTreeIndex;
// how many signups we have in the state tree
signal input numSignUps;
// we check that the state tree index is <= than the number of signups
// as first validation
// it is <= because the state tree index is 1-based
// 0 is for blank state leaf then 1 for the first actual user
// which is where the numSignUps starts
component validStateLeafIndex = SafeLessEqThan(252);
validStateLeafIndex.in[0] <== stateTreeIndex;
validStateLeafIndex.in[1] <== numSignUps;

// b) Whether the max vote option tree index is correct
signal input voteOptionIndex;
signal input maxVoteOptions;
component validVoteOptionIndex = SafeLessThan(252);
validVoteOptionIndex.in[0] <== voteOptionIndex;
validVoteOptionIndex.in[1] <== maxVoteOptions;

// c) Whether the nonce is correct
signal input originalNonce;
signal input nonce;
component validNonce = IsEqual();
// the nonce should be previous nonce + 1
validNonce.in[0] <== originalNonce + 1;
validNonce.in[1] <== nonce;

var PACKED_CMD_LENGTH = 4;
// d) Whether the signature is correct
signal input cmd[PACKED_CMD_LENGTH];
signal input pubKey[2];
signal input sigR8[2];
signal input sigS;

component validSignature = VerifySignature();
validSignature.pubKey[0] <== pubKey[0];
validSignature.pubKey[1] <== pubKey[1];
validSignature.R8[0] <== sigR8[0];
validSignature.R8[1] <== sigR8[1];
validSignature.S <== sigS;
for (var i = 0; i < PACKED_CMD_LENGTH; i++) {
validSignature.preimage[i] <== cmd[i];
}

// e) Whether the state leaf was inserted before the Poll period ended
signal input slTimestamp;
signal input pollEndTimestamp;
component validTimestamp = SafeLessEqThan(252);
validTimestamp.in[0] <== slTimestamp;
validTimestamp.in[1] <== pollEndTimestamp;

// f) Whether there are sufficient voice credits
signal input currentVoiceCreditBalance;
signal input currentVotesForOption;
signal input voteWeight;

// Check that currentVoiceCreditBalance + (currentVotesForOption) >= (voteWeight)
component sufficientVoiceCredits = SafeGreaterEqThan(252);
sufficientVoiceCredits.in[0] <== currentVotesForOption + currentVoiceCreditBalance;
sufficientVoiceCredits.in[1] <== voteWeight;

// if all 6 checks are correct then is IsValid = 1
component validUpdate = IsEqual();
validUpdate.in[0] <== 6;
validUpdate.in[1] <== validSignature.valid +
sufficientVoiceCredits.out +
validNonce.out +
validStateLeafIndex.out +
validTimestamp.out +
validVoteOptionIndex.out;
signal output isValid;
isValid <== validUpdate.out;
}
2 changes: 1 addition & 1 deletion circuits/circom/poseidon/poseidonHashT3.circom
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ template PoseidonHashT3() {
signal output out;

component hasher = Poseidon_OLD(nInputs);
for (var i = 0; i < nInputs; i ++) {
for (var i = 0; i < nInputs; i++) {
hasher.inputs[i] <== inputs[i];
}
out <== hasher.out;
Expand Down
2 changes: 1 addition & 1 deletion circuits/circom/poseidon/poseidonHashT4.circom
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ template PoseidonHashT4() {
signal output out;

component hasher = Poseidon_OLD(nInputs);
for (var i = 0; i < nInputs; i ++) {
for (var i = 0; i < nInputs; i++) {
hasher.inputs[i] <== inputs[i];
}
out <== hasher.out;
Expand Down
2 changes: 1 addition & 1 deletion circuits/circom/poseidon/poseidonHashT5.circom
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ template PoseidonHashT5() {
signal output out;

component hasher = Poseidon_OLD(nInputs);
for (var i = 0; i < nInputs; i ++) {
for (var i = 0; i < nInputs; i++) {
hasher.inputs[i] <== inputs[i];
}
out <== hasher.out;
Expand Down
2 changes: 1 addition & 1 deletion circuits/circom/poseidon/poseidonHashT6.circom
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ template PoseidonHashT6() {
signal output out;

component hasher = Poseidon_OLD(nInputs);
for (var i = 0; i < nInputs; i ++) {
for (var i = 0; i < nInputs; i++) {
hasher.inputs[i] <== inputs[i];
}
out <== hasher.out;
Expand Down
Loading

0 comments on commit 86ba854

Please sign in to comment.