Skip to content

Commit

Permalink
feat: anonymous poll joining milestone 1 (#1625)
Browse files Browse the repository at this point in the history
* feat(poll): add chain hash features

BREAKING CHANGE: message processing is changed

* fix(ipoll): add missing parameter

* fix(poll-tests): add missing parameter maxMessagebatchSize

* feat(poll.ts): add chain hash updating

* test(poll tests): add test for checking chain hash computation

* feat(poll.ts): add batch hashes array computation

* feat(poll.sol): pad zeroes to the maximum size of batch

* feat(messageprocessor): update process messages to use chain hash

* refactor(vkregistry): refactor function call

* feat(processmessages.circom): add chainHash feature in circuits and test for that

* test(processmessages): rearrange test for key-change

* refactor(mergemessages): refactor functions calls which include mergemessages

* refactor(mergemessages): add some more changes about functions call which  include mergemessages

* test(all tests): fixing tests after refactoring code

* refactor(accqueue): remove all calls for accqueue

* fix(currentmessagebatchindex): fix message batch indexing

* refactor(circuit tests): refactor code for circuit testing

* test(ceremonyparams.test): correct constants for CeremonyParams test

* perf(processmessages.circom + contracts): optimize last batch padding, remove unused inputs

* docs(padlastbatch method): update doc comment

* docs(poll.ts): remove stale comments

* docs(test comments): fix typos

* ci(treedepths mock): modify interface for mocked function

* fix(ceremony params test): fix circuit inputs

* test(messagevalidator): fix function calls for messagevalidator circuit in tests

* chore(comments): fix unusefull comments

* refactor(poll.sol): replace external contracts with maci only

* perf(messageprocessor.sol): hardcode initialization for batchHashes array

* docs(comments): fix some more comments

* test(test for pr checks): correct some of tests for PR checks

* ci: 🎡 renamed old ProcessMessages_10-2-1-2_test

* ci: 🎡 correct rapidsnark/build/prover path

* style(reviews): solve some reviews for merging

* refactor(messageaqq): remove more message merging and message aqq

* style(messageaqq): remove more message merging and message aqq

* refactor(messageaqq): remove message aqq from subgraph

* test(coordinator): hide NOT_MERGED_MESSAGE_TREE error

* test(coordinator): fix test about message merging

* test(proveonchain): change chainHash calculation

* test(proveonchain): fix chainHashes declaration

* test(proveonchain): fix chainHash calculation

* test(proveonchain): fix chainHashes calculations

* test(proveonchain): fix chainHashes calculation

* test(proveonchain): fix loop limit

* style(review comments): resolve some of review comments

* style(review comments): resolve some of review comments

* test(lint:ts): fix e2e test because of lint:ts check

* docs(wrong changes): fix wrong changes about documentation that is not in our scope

* refactor(batchsizes): change batchSizes struct with messageBatchSize variable

* refactor(contracts): rollback to provide external contract references

* docs(messageprocessor.sol): fix typo

* refactor(messagebatchsize): chenge messageBatchSize location from Params.sol to Poll.sol

* refactor(maxmessages): remove maxMessages from maxValues

* refactor(sltimestemp): remove slTimestamp from circuits

* refactor(review comments): resolve more review comments

* fix(subgraph): fix bug about maxVoteOptions dunction call

* fix(sltimestamp): fix test for removing slTimestap signal

* refactor(promise.all): refactor promise.all for only one async call

* fix(subgraph): try to fix subgraph build

* revert(.nx folder): remove .nx folder from cli folder

---------

Co-authored-by: radojevicMihailo <[email protected]>
Co-authored-by: Aleksandar Veljković <[email protected]>
Co-authored-by: Boris Cvitak <[email protected]>
  • Loading branch information
4 people authored Jul 12, 2024
1 parent 29c53dc commit e84f610
Show file tree
Hide file tree
Showing 119 changed files with 1,449 additions and 4,886 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/coordinator-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ env:
COORDINATOR_PUBLIC_KEY_PATH: "./pub.key"
COORDINATOR_PRIVATE_KEY_PATH: "./priv.key"
COORDINATOR_TALLY_ZKEY_NAME: "TallyVotes_10-1-2_test"
COORDINATOR_MESSAGE_PROCESS_ZKEY_NAME: "ProcessMessages_10-2-1-2_test"
COORDINATOR_MESSAGE_PROCESS_ZKEY_NAME: "ProcessMessages_10-20-2_test"
COORDINATOR_ZKEY_PATH: "./zkeys/"
COORDINATOR_RAPIDSNARK_EXE: "~/rapidsnark/build/prover"

Expand Down
8 changes: 4 additions & 4 deletions circuits/circom/circuits.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"ProcessMessages_10-2-1-2_test": {
"ProcessMessages_10-20-2_test": {
"file": "./core/qv/processMessages",
"template": "ProcessMessages",
"params": [10, 2, 1, 2],
"params": [10, 20, 2],
"pubs": ["inputHash"]
},
"ProcessMessagesNonQv_10-2-1-2_test": {
"ProcessMessagesNonQv_10-20-2_test": {
"file": "./core/non-qv/processMessages",
"template": "ProcessMessagesNonQv",
"params": [10, 2, 1, 2],
"params": [10, 20, 2],
"pubs": ["inputHash"]
},
"TallyVotes_10-1-2_test": {
Expand Down
98 changes: 32 additions & 66 deletions circuits/circom/core/non-qv/processMessages.circom
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,22 @@ include "../../trees/incrementalQuinaryTree.circom";

/**
* Proves the correctness of processing a batch of MACI messages.
* The msgBatchDepth parameter is known as msgSubtreeDepth and indicates the depth
* of the shortest tree that can fit all the messages in a batch.
* This template does not support Quadratic Voting (QV).
*/
template ProcessMessagesNonQv(
stateTreeDepth,
msgTreeDepth,
msgBatchDepth,
batchSize,
voteOptionTreeDepth
) {
// Must ensure that the trees have a valid structure.
assert(stateTreeDepth > 0);
assert(msgBatchDepth > 0);
assert(batchSize > 0);
assert(voteOptionTreeDepth > 0);
assert(msgTreeDepth >= msgBatchDepth);

// Default for IQT (quinary trees).
var MESSAGE_TREE_ARITY = 5;
var VOTE_OPTION_TREE_ARITY = 5;
// Default for Binary trees.
var STATE_TREE_ARITY = 2;
var batchSize = MESSAGE_TREE_ARITY ** msgBatchDepth;
var MSG_LENGTH = 10;
var PACKED_CMD_LENGTH = 4;
var STATE_LEAF_LENGTH = 4;
Expand All @@ -59,14 +54,12 @@ include "../../trees/incrementalQuinaryTree.circom";
signal numSignUps;
// Number of options for this poll.
signal maxVoteOptions;
// Time when the poll ends.
signal input pollEndTimestamp;
// The existing message tree root.
signal input msgRoot;
// Value of chainHash at beginning of batch
signal input inputBatchHash;
// Value of chainHash at end of batch
signal input outputBatchHash;
// The messages.
signal input msgs[batchSize][MSG_LENGTH];
// Sibling messages.
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).
Expand Down Expand Up @@ -104,16 +97,16 @@ include "../../trees/incrementalQuinaryTree.circom";
signal input currentBallotsPathElements[batchSize][stateTreeDepth][STATE_TREE_ARITY - 1];
// Intermediate vote weights.
signal input currentVoteWeights[batchSize];
signal input currentVoteWeightsPathElements[batchSize][voteOptionTreeDepth][MESSAGE_TREE_ARITY - 1];
signal input currentVoteWeightsPathElements[batchSize][voteOptionTreeDepth][VOTE_OPTION_TREE_ARITY - 1];

// nb. The messages are processed in REVERSE order.
// Therefore, the index of the first message to process does not match the index of the
// first message (e.g., [msg1, msg2, msg3] => first message to process has index 3).

// The index of the first message leaf in the batch, inclusive.
// The index of the first message in the batch, inclusive.
signal batchStartIndex;

// The index of the last message leaf in the batch to process, exclusive.
// The index of the last message in the batch to process, exclusive.
// This value may be less than batchStartIndex + batchSize if this batch is
// the last batch and the total number of messages is not a multiple of the batch size.
signal batchEndIndex;
Expand All @@ -135,16 +128,15 @@ include "../../trees/incrementalQuinaryTree.circom";
var (
computedMaxVoteOptions,
computedNumSignUps,
computedBatchStartIndex,
computedBatchStartIndex,
computedBatchEndIndex,
computedHash
) = ProcessMessagesInputHasher()(
packedVals,
coordPubKey,
msgRoot,
outputBatchHash,
currentSbCommitment,
newSbCommitment,
pollEndTimestamp,
actualStateTreeDepth
);

Expand All @@ -159,60 +151,37 @@ include "../../trees/incrementalQuinaryTree.circom";
// -----------------------------------------------------------------------
// 0. Ensure that the maximum vote options signal is valid and if
// the maximum users signal is valid.
var maxVoValid = LessEqThan(32)([maxVoteOptions, MESSAGE_TREE_ARITY ** voteOptionTreeDepth]);
var maxVoValid = LessEqThan(32)([maxVoteOptions, VOTE_OPTION_TREE_ARITY ** voteOptionTreeDepth]);
maxVoValid === 1;

// Check numSignUps <= the max number of users (i.e., number of state leaves
// that can fit the state tree).
var numSignUpsValid = LessEqThan(32)([numSignUps, STATE_TREE_ARITY ** stateTreeDepth]);
numSignUpsValid === 1;

// Hash each Message to check their existence in the Message tree.
// Hash each Message to check their existence in the Message chain hash.
var computedMessageHashers[batchSize];
var computedChainHashes[batchSize];
var chainHash[batchSize + 1];
chainHash[0] = inputBatchHash;
for (var i = 0; i < batchSize; i++) {
// calculate message hash
computedMessageHashers[i] = MessageHasher()(msgs[i], encPubKeys[i]);
// check if message is valid or not (if index of message is less than index of last valid message in batch)
var batchStartIndexValid = SafeLessThan(32)([batchStartIndex + i, batchEndIndex]);
// calculate chain hash if message is valid
computedChainHashes[i] = PoseidonHasher(2)([chainHash[i], computedMessageHashers[i]]);
// choose between old chain hash value and new chain hash value depending if message is valid or not
chainHash[i + 1] = Mux1()([chainHash[i], computedChainHashes[i]], batchStartIndexValid);
}

// If batchEndIndex - batchStartIndex < batchSize, the remaining
// If batchEndIndex < batchStartIndex + i, the remaining
// message hashes should be the zero value.
// e.g. [m, z, z, z, z] if there is only 1 real message in the batch
// This makes possible to have a batch of messages which is only partially full.
var computedLeaves[batchSize];
var computedPathElements[msgTreeDepth - msgBatchDepth][MESSAGE_TREE_ARITY - 1];
var computedPathIndex[msgTreeDepth - msgBatchDepth];

for (var i = 0; i < batchSize; i++) {
var batchStartIndexValid = SafeLessThan(32)([batchStartIndex + i, batchEndIndex]);
computedLeaves[i] = Mux1()([msgTreeZeroValue, computedMessageHashers[i]], batchStartIndexValid);
}

for (var i = 0; i < msgTreeDepth - msgBatchDepth; i++) {
for (var j = 0; j < MESSAGE_TREE_ARITY - 1; j++) {
computedPathElements[i][j] = msgSubrootPathElements[i][j];
}
}

// Computing the path_index values. Since msgBatchLeavesExists tests
// the existence of a subroot, the length of the proof correspond to the last
// n elements of a proof from the root to a leaf, where n = msgTreeDepth - msgBatchDepth.
// e.g. if batchStartIndex = 25, msgTreeDepth = 4, msgBatchDepth = 2, then path_index = [1, 0].
var computedMsgBatchPathIndices[msgTreeDepth] = QuinGeneratePathIndices(msgTreeDepth)(batchStartIndex);

for (var i = msgBatchDepth; i < msgTreeDepth; i++) {
computedPathIndex[i - msgBatchDepth] = computedMsgBatchPathIndices[i];
}

// Check whether each message exists in the Message tree.
// Otherwise, throws (needs constraint to prevent such a proof).
// To save constraints, compute the subroot of the messages and check
// whether the subroot is a member of the message tree. This means that
// batchSize must be the message tree arity raised to some power (e.g. 5 ^ n).
QuinBatchLeavesExists(msgTreeDepth, msgBatchDepth)(
msgRoot,
computedLeaves,
computedPathIndex,
computedPathElements
);
// Ensure that right output batch hash was sent to circuit
chainHash[batchSize] === outputBatchHash;

// Decrypt each Message to a Command.
// MessageToCommand derives the ECDH shared key from the coordinator's
Expand Down Expand Up @@ -274,7 +243,7 @@ include "../../trees/incrementalQuinaryTree.circom";
// Process as vote type message.
var currentStateLeavesPathElement[stateTreeDepth][STATE_TREE_ARITY - 1];
var currentBallotPathElement[stateTreeDepth][STATE_TREE_ARITY - 1];
var currentVoteWeightsPathElement[voteOptionTreeDepth][MESSAGE_TREE_ARITY - 1];
var currentVoteWeightsPathElement[voteOptionTreeDepth][VOTE_OPTION_TREE_ARITY - 1];

for (var j = 0; j < stateTreeDepth; j++) {
for (var k = 0; k < STATE_TREE_ARITY - 1; k++) {
Expand All @@ -284,15 +253,14 @@ include "../../trees/incrementalQuinaryTree.circom";
}

for (var j = 0; j < voteOptionTreeDepth; j++) {
for (var k = 0; k < MESSAGE_TREE_ARITY - 1; k++) {
for (var k = 0; k < VOTE_OPTION_TREE_ARITY - 1; k++) {
currentVoteWeightsPathElement[j][k] = currentVoteWeightsPathElements[i][j][k];
}
}

(computedNewVoteStateRoot[i], computedNewVoteBallotRoot[i]) = ProcessOneNonQv(stateTreeDepth, voteOptionTreeDepth)(
numSignUps,
maxVoteOptions,
pollEndTimestamp,
stateRoots[i + 1],
ballotRoots[i + 1],
actualStateTreeDepth,
Expand Down Expand Up @@ -336,7 +304,7 @@ template ProcessOneNonQv(stateTreeDepth, voteOptionTreeDepth) {
var BALLOT_LENGTH = 2;
var MSG_LENGTH = 10;
var PACKED_CMD_LENGTH = 4;
var MESSAGE_TREE_ARITY = 5;
var VOTE_OPTION_TREE_ARITY = 5;
var STATE_TREE_ARITY = 2;
var BALLOT_NONCE_IDX = 0;
// Ballot vote option (VO) root index.
Expand All @@ -355,7 +323,6 @@ template ProcessOneNonQv(stateTreeDepth, voteOptionTreeDepth) {
// Inputs representing the message and the current state.
signal input numSignUps;
signal input maxVoteOptions;
signal input pollEndTimestamp;

// The current value of the state tree root.
signal input currentStateRoot;
Expand All @@ -375,7 +342,7 @@ template ProcessOneNonQv(stateTreeDepth, voteOptionTreeDepth) {

// The current vote weight and related path elements.
signal input currentVoteWeight;
signal input currentVoteWeightsPathElements[voteOptionTreeDepth][MESSAGE_TREE_ARITY - 1];
signal input currentVoteWeightsPathElements[voteOptionTreeDepth][VOTE_OPTION_TREE_ARITY - 1];

// Inputs related to the command being processed.
signal input cmdStateIndex;
Expand Down Expand Up @@ -408,8 +375,7 @@ template ProcessOneNonQv(stateTreeDepth, voteOptionTreeDepth) {
maxVoteOptions,
[stateLeaf[STATE_LEAF_PUB_X_IDX], stateLeaf[STATE_LEAF_PUB_Y_IDX]],
stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX],
stateLeaf[STATE_LEAF_TIMESTAMP_IDX],
pollEndTimestamp,
// stateLeaf[STATE_LEAF_TIMESTAMP_IDX],
ballot[BALLOT_NONCE_IDX],
currentVoteWeight,
cmdStateIndex,
Expand Down
Loading

0 comments on commit e84f610

Please sign in to comment.