Skip to content

Commit

Permalink
refactor(circuits): remove duplicate constraints (#1644)
Browse files Browse the repository at this point in the history
  • Loading branch information
ctrlc03 authored Jul 16, 2024
1 parent 63138d1 commit cd7ea49
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 60 deletions.
37 changes: 10 additions & 27 deletions circuits/circom/core/non-qv/processMessages.circom
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,6 @@ template ProcessOneNonQv(stateTreeDepth, voteOptionTreeDepth) {
var STATE_LEAF_VOICE_CREDIT_BALANCE_IDX = 2;
// Timestamp.
var STATE_LEAF_TIMESTAMP_IDX = 3;
var N_BITS = 252;

// Inputs representing the message and the current state.
signal input numSignUps;
Expand Down Expand Up @@ -402,8 +401,8 @@ template ProcessOneNonQv(stateTreeDepth, voteOptionTreeDepth) {

// 1. Transform a state leaf and a ballot with a command.
// The result is a new state leaf, a new ballot, and an isValid signal (0 or 1).
var computedNewSlPubKey[2], computedNewBallotNonce, computedIsValid;
(computedNewSlPubKey, computedNewBallotNonce, computedIsValid) = StateLeafAndBallotTransformerNonQv()(
var computedNewSlPubKey[2], computedNewBallotNonce, computedIsValid, computedIsStateLeafIndexValid, computedIsVoteOptionIndexValid;
(computedNewSlPubKey, computedNewBallotNonce, computedIsValid, computedIsStateLeafIndexValid, computedIsVoteOptionIndexValid) = StateLeafAndBallotTransformerNonQv()(
numSignUps,
maxVoteOptions,
[stateLeaf[STATE_LEAF_PUB_X_IDX], stateLeaf[STATE_LEAF_PUB_Y_IDX]],
Expand All @@ -424,10 +423,9 @@ template ProcessOneNonQv(stateTreeDepth, voteOptionTreeDepth) {
packedCmd
);

// 2. If isValid is equal to zero, generate indices for leaf zero.
// 2. If computedIsStateLeafIndexValid is equal to zero, generate indices for leaf zero.
// Otherwise, generate indices for command.stateIndex.
var stateLeafIndexValid = SafeLessThan(N_BITS)([cmdStateIndex, numSignUps]);
var stateIndexMux = Mux1()([0, cmdStateIndex], stateLeafIndexValid);
var stateIndexMux = Mux1()([0, cmdStateIndex], computedIsStateLeafIndexValid);
var computedStateLeafPathIndices[stateTreeDepth] = MerkleGeneratePathIndices(stateTreeDepth)(stateIndexMux);

// 3. Verify that the original state leaf exists in the given state root.
Expand Down Expand Up @@ -460,14 +458,7 @@ template ProcessOneNonQv(stateTreeDepth, voteOptionTreeDepth) {
b <== currentVoteWeight;
c <== cmdNewVoteWeight;

var voiceCreditAmountValid = SafeGreaterEqThan(252)([
stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX] + b,
c
]);

var computedIsMessageEqual = IsEqual()([2, computedIsValid + voiceCreditAmountValid]);
var voteOptionIndexValid = SafeLessThan(N_BITS)([cmdVoteOptionIndex, maxVoteOptions]);
var cmdVoteOptionIndexMux = Mux1()([0, cmdVoteOptionIndex], voteOptionIndexValid);
var cmdVoteOptionIndexMux = Mux1()([0, cmdVoteOptionIndex], computedIsVoteOptionIndexValid);
var computedCurrentVoteWeightPathIndices[voteOptionTreeDepth] = QuinGeneratePathIndices(voteOptionTreeDepth)(cmdVoteOptionIndexMux);

var computedCurrentVoteWeightQip = QuinTreeInclusionProof(voteOptionTreeDepth)(
Expand All @@ -478,20 +469,13 @@ template ProcessOneNonQv(stateTreeDepth, voteOptionTreeDepth) {

computedCurrentVoteWeightQip === ballot[BALLOT_VO_ROOT_IDX];

var voteWeightMux = Mux1()([currentVoteWeight, cmdNewVoteWeight], computedIsMessageEqual);
var newSlVoiceCreditBalanceMux = Mux1()(
[
stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX],
stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX] + b - c
],
voiceCreditAmountValid
);
var voteWeightMux = Mux1()([currentVoteWeight, cmdNewVoteWeight], computedIsValid);
var voiceCreditBalanceMux = Mux1()(
[
stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX],
newSlVoiceCreditBalanceMux
stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX] + b - c
],
computedIsMessageEqual
computedIsValid
);

// 5.1. Update the ballot's vote option root with the new vote weight.
Expand All @@ -504,7 +488,7 @@ template ProcessOneNonQv(stateTreeDepth, voteOptionTreeDepth) {
// The new vote option root in the ballot
var newBallotVoRootMux = Mux1()(
[ballot[BALLOT_VO_ROOT_IDX], computedNewVoteOptionTreeQip],
computedIsMessageEqual
computedIsValid
);

newBallotVoRoot <== newBallotVoRootMux;
Expand All @@ -527,8 +511,7 @@ template ProcessOneNonQv(stateTreeDepth, voteOptionTreeDepth) {
newStateRoot <== computedNewStateLeafQip;

// 7. Generate a new ballot root.
var newBallotNonceMux = Mux1()([ballot[BALLOT_NONCE_IDX], computedNewBallotNonce], computedIsMessageEqual);
var computedNewBallot = PoseidonHasher(2)([newBallotNonceMux, newBallotVoRoot]);
var computedNewBallot = PoseidonHasher(2)([computedNewBallotNonce, newBallotVoRoot]);
var computedNewBallotQip = MerkleTreeInclusionProof(stateTreeDepth)(
computedNewBallot,
computedStateLeafPathIndices,
Expand Down
37 changes: 10 additions & 27 deletions circuits/circom/core/qv/processMessages.circom
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,6 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
var STATE_LEAF_VOICE_CREDIT_BALANCE_IDX = 2;
// Timestamp.
var STATE_LEAF_TIMESTAMP_IDX = 3;
var N_BITS = 252;

// Inputs representing the message and the current state.
signal input numSignUps;
Expand Down Expand Up @@ -397,8 +396,8 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {

// 1. Transform a state leaf and a ballot with a command.
// The result is a new state leaf, a new ballot, and an isValid signal (0 or 1).
var computedNewSlPubKey[2], computedNewBallotNonce, computedIsValid;
(computedNewSlPubKey, computedNewBallotNonce, computedIsValid) = StateLeafAndBallotTransformer()(
var computedNewSlPubKey[2], computedNewBallotNonce, computedIsValid, computedIsStateLeafIndexValid, computedIsVoteOptionIndexValid;
(computedNewSlPubKey, computedNewBallotNonce, computedIsValid, computedIsStateLeafIndexValid, computedIsVoteOptionIndexValid) = StateLeafAndBallotTransformer()(
numSignUps,
maxVoteOptions,
[stateLeaf[STATE_LEAF_PUB_X_IDX], stateLeaf[STATE_LEAF_PUB_Y_IDX]],
Expand All @@ -419,10 +418,9 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
packedCmd
);

// 2. If isValid is equal to zero, generate indices for leaf zero.
// 2. If computedIsStateLeafIndexValid is equal to zero, generate indices for leaf zero.
// Otherwise, generate indices for command.stateIndex.
var stateLeafIndexValid = SafeLessThan(N_BITS)([cmdStateIndex, numSignUps]);
var stateIndexMux = Mux1()([0, cmdStateIndex], stateLeafIndexValid);
var stateIndexMux = Mux1()([0, cmdStateIndex], computedIsStateLeafIndexValid);
var computedStateLeafPathIndices[stateTreeDepth] = MerkleGeneratePathIndices(stateTreeDepth)(stateIndexMux);

// 3. Verify that the original state leaf exists in the given state root.
Expand Down Expand Up @@ -455,14 +453,7 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
b <== currentVoteWeight * currentVoteWeight;
c <== cmdNewVoteWeight * cmdNewVoteWeight;

var voiceCreditAmountValid = SafeGreaterEqThan(252)([
stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX] + b,
c
]);

var computedIsMessageEqual = IsEqual()([2, computedIsValid + voiceCreditAmountValid]);
var voteOptionIndexValid = SafeLessThan(N_BITS)([cmdVoteOptionIndex, maxVoteOptions]);
var cmdVoteOptionIndexMux = Mux1()([0, cmdVoteOptionIndex], voteOptionIndexValid);
var cmdVoteOptionIndexMux = Mux1()([0, cmdVoteOptionIndex], computedIsVoteOptionIndexValid);
var computedCurrentVoteWeightPathIndices[voteOptionTreeDepth] = QuinGeneratePathIndices(voteOptionTreeDepth)(cmdVoteOptionIndexMux);

var computedCurrentVoteWeightQip = QuinTreeInclusionProof(voteOptionTreeDepth)(
Expand All @@ -473,20 +464,13 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {

computedCurrentVoteWeightQip === ballot[BALLOT_VO_ROOT_IDX];

var voteWeightMux = Mux1()([currentVoteWeight, cmdNewVoteWeight], computedIsMessageEqual);
var newSlVoiceCreditBalanceMux = Mux1()(
[
stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX],
stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX] + b - c
],
voiceCreditAmountValid
);
var voteWeightMux = Mux1()([currentVoteWeight, cmdNewVoteWeight], computedIsValid);
var voiceCreditBalanceMux = Mux1()(
[
stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX],
newSlVoiceCreditBalanceMux
stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX] + b - c
],
computedIsMessageEqual
computedIsValid
);

// 5.1. Update the ballot's vote option root with the new vote weight.
Expand All @@ -499,7 +483,7 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
// The new vote option root in the ballot
var newBallotVoRootMux = Mux1()(
[ballot[BALLOT_VO_ROOT_IDX], computedNewVoteOptionTreeQip],
computedIsMessageEqual
computedIsValid
);

newBallotVoRoot <== newBallotVoRootMux;
Expand All @@ -522,8 +506,7 @@ template ProcessOne(stateTreeDepth, voteOptionTreeDepth) {
newStateRoot <== computedNewStateLeafQip;

// 7. Generate a new ballot root.
var newBallotNonceMux = Mux1()([ballot[BALLOT_NONCE_IDX], computedNewBallotNonce], computedIsMessageEqual);
var computedNewBallot = PoseidonHasher(2)([newBallotNonceMux, newBallotVoRoot]);
var computedNewBallot = PoseidonHasher(2)([computedNewBallotNonce, newBallotVoRoot]);
var computedNewBallotQip = MerkleTreeInclusionProof(stateTreeDepth)(
computedNewBallot,
computedStateLeafPathIndices,
Expand Down
6 changes: 6 additions & 0 deletions circuits/circom/utils/non-qv/messageValidator.circom
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ template MessageValidatorNonQv() {

// True when the command is valid; otherwise false.
signal output isValid;
// True if the state leaf index is valid
signal output isStateLeafIndexValid;
// True if the vote option index is valid
signal output isVoteOptionIndexValid;

// Check (1) - The state leaf index must be valid.
// The check ensure that the stateTreeIndex < numSignUps as first validation.
Expand Down Expand Up @@ -88,4 +92,6 @@ template MessageValidatorNonQv() {
);

isValid <== computedIsUpdateValid;
isStateLeafIndexValid <== computedIsStateLeafIndexValid;
isVoteOptionIndexValid <== computedIsVoteOptionIndexValid;
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,13 @@ template StateLeafAndBallotTransformerNonQv() {

// True when the command is valid; otherwise false.
signal output isValid;
// True if the state leaf index is valid
signal output isStateLeafIndexValid;
// True if the vote option index is valid
signal output isVoteOptionIndexValid;

// Check if the command / message is valid.
var computedMessageValidator = MessageValidatorNonQv()(
var (computedMessageValidator, computedIsStateLeafIndexValid, computedIsVoteOptionIndexValid) = MessageValidatorNonQv()(
cmdStateIndex,
numSignUps,
cmdVoteOptionIndex,
Expand Down Expand Up @@ -102,4 +106,6 @@ template StateLeafAndBallotTransformerNonQv() {
newBallotNonce <== computedNewBallotNonceMux;

isValid <== computedMessageValidator;
isStateLeafIndexValid <== computedIsStateLeafIndexValid;
isVoteOptionIndexValid <== computedIsVoteOptionIndexValid;
}
6 changes: 6 additions & 0 deletions circuits/circom/utils/qv/messageValidator.circom
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ template MessageValidator() {

// True when the command is valid; otherwise false.
signal output isValid;
// True if the state leaf index is valid
signal output isStateLeafIndexValid;
// True if the vote option index is valid
signal output isVoteOptionIndexValid;

// Check (1) - The state leaf index must be valid.
// The check ensure that the stateTreeIndex < numSignUps as first validation.
Expand Down Expand Up @@ -94,5 +98,7 @@ template MessageValidator() {
);

isValid <== computedIsUpdateValid;
isStateLeafIndexValid <== computedIsStateLeafIndexValid;
isVoteOptionIndexValid <== computedIsVoteOptionIndexValid;
}

Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,13 @@ template StateLeafAndBallotTransformer() {

// True when the command is valid; otherwise false.
signal output isValid;
// True if the state leaf index is valid
signal output isStateLeafIndexValid;
// True if the vote option index is valid
signal output isVoteOptionIndexValid;

// Check if the command / message is valid.
var computedMessageValidator = MessageValidator()(
var (computedMessageValidator, computedIsStateLeafIndexValid, computedIsVoteOptionIndexValid) = MessageValidator()(
cmdStateIndex,
numSignUps,
cmdVoteOptionIndex,
Expand Down Expand Up @@ -102,5 +106,7 @@ template StateLeafAndBallotTransformer() {
newBallotNonce <== computedNewBallotNonceMux;

isValid <== computedMessageValidator;
isStateLeafIndexValid <== computedIsStateLeafIndexValid;
isVoteOptionIndexValid <== computedIsVoteOptionIndexValid;
}

Loading

0 comments on commit cd7ea49

Please sign in to comment.