Skip to content

Commit

Permalink
Merge pull request #1944 from privacy-scaling-explorations/feature/re…
Browse files Browse the repository at this point in the history
…base-anon-poll-joining

feat: rebase anon poll joining with dev
  • Loading branch information
ctrlc03 authored Dec 4, 2024
2 parents ea5b2fb + 3139d32 commit 2b8f11e
Show file tree
Hide file tree
Showing 136 changed files with 4,671 additions and 5,368 deletions.
2 changes: 1 addition & 1 deletion .github/scripts/downloadZkeys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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/v2.0.0/maci_artifacts_10-2-1-2_test.tar.gz",
test: "https://maci-develop-fra.s3.eu-central-1.amazonaws.com/v3.0.0/maci_artifacts_v3.0.0_test.tar.gz",
prod: "https://maci-develop-fra.s3.eu-central-1.amazonaws.com/v2.0.0/maci_artifacts_14-9-2-3_prod.tar.gz",
};
const ARCHIVE_NAME = path.resolve(ZKEY_PATH, "maci_keys.tar.gz");
Expand Down
5 changes: 0 additions & 5 deletions apps/subgraph/schemas/schema.v1.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ type Poll @entity {
pollId: BigInt! # uint256
duration: BigInt! # uint256
treeDepth: BigInt! # uint8
maxMessages: BigInt!
maxVoteOption: BigInt!
messageProcessor: Bytes! # address
tally: Bytes! # address
Expand All @@ -43,10 +42,6 @@ type Poll @entity {
stateRoot: BigInt # uint256
numSignups: BigInt! # uint256
numMessages: BigInt! # uint256
"merge message tree after ended"
numSrQueueOps: BigInt # uint256
messageRoot: BigInt

"relations"
owner: Bytes!
maci: MACI!
Expand Down
14 changes: 7 additions & 7 deletions apps/subgraph/src/maci.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, MESSAGE_TREE_ARITY } from "./utils/constants";
import { ONE_BIG_INT } from "./utils/constants";
import { createOrLoadMACI, createOrLoadUser, createOrLoadAccount } from "./utils/entity";

export function handleDeployPoll(event: DeployPollEvent): void {
Expand All @@ -17,15 +17,15 @@ export function handleDeployPoll(event: DeployPollEvent): void {
const maciContract = MaciContract.bind(Address.fromBytes(maci.id));
const contracts = maciContract.getPoll(id);
const poll = new Poll(contracts.poll);
const contract = PollContract.bind(contracts.poll);
const treeDepths = contract.treeDepths();
const durations = contract.getDeployTimeAndDuration();
const pollContract = PollContract.bind(contracts.poll);
const maxVoteOptions = pollContract.maxVoteOptions();
const treeDepths = pollContract.treeDepths();
const durations = pollContract.getDeployTimeAndDuration();

poll.pollId = id;
poll.pollId = event.params._pollId;
poll.messageProcessor = contracts.messageProcessor;
poll.tally = contracts.tally;
poll.maxMessages = GraphBN.fromI32(MESSAGE_TREE_ARITY ** treeDepths.getMessageTreeDepth());
poll.maxVoteOption = GraphBN.fromI32(MESSAGE_TREE_ARITY ** treeDepths.getVoteOptionTreeDepth());
poll.maxVoteOption = maxVoteOptions;
poll.treeDepth = GraphBN.fromI32(treeDepths.value0);
poll.duration = durations.value1;
poll.mode = GraphBN.fromI32(event.params._mode);
Expand Down
29 changes: 2 additions & 27 deletions apps/subgraph/src/poll.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
/* eslint-disable no-underscore-dangle */

import { Poll, Vote, MACI } from "../generated/schema";
import {
MergeMaciState as MergeMaciStateEvent,
MergeMessageAq as MergeMessageAqEvent,
MergeMessageAqSubRoots as MergeMessageAqSubRootsEvent,
PublishMessage as PublishMessageEvent,
} from "../generated/templates/Poll/Poll";
import { MergeState as MergeStateEvent, PublishMessage as PublishMessageEvent } from "../generated/templates/Poll/Poll";

import { ONE_BIG_INT } from "./utils/constants";

export function handleMergeMaciState(event: MergeMaciStateEvent): void {
export function handleMergeState(event: MergeStateEvent): void {
const poll = Poll.load(event.address);

if (poll) {
Expand All @@ -29,26 +24,6 @@ export function handleMergeMaciState(event: MergeMaciStateEvent): void {
}
}

export function handleMergeMessageAq(event: MergeMessageAqEvent): void {
const poll = Poll.load(event.address);

if (poll) {
poll.messageRoot = event.params._messageRoot;
poll.updatedAt = event.block.timestamp;
poll.save();
}
}

export function handleMergeMessageAqSubRoots(event: MergeMessageAqSubRootsEvent): void {
const poll = Poll.load(event.address);

if (poll) {
poll.numSrQueueOps = event.params._numSrQueueOps;
poll.updatedAt = event.block.timestamp;
poll.save();
}
}

export function handlePublishMessage(event: PublishMessageEvent): void {
const vote = new Vote(event.transaction.hash.concatI32(event.logIndex.toI32()));
vote.data = event.params._message.data;
Expand Down
1 change: 0 additions & 1 deletion apps/subgraph/src/utils/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { BigInt as GraphBN } from "@graphprotocol/graph-ts";

export const ONE_BIG_INT = GraphBN.fromU32(1);
export const MESSAGE_TREE_ARITY = 5;
10 changes: 3 additions & 7 deletions apps/subgraph/templates/subgraph.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ dataSources:
eventHandlers:
- event: DeployPoll(uint256,indexed uint256,indexed uint256,uint8)
handler: handleDeployPoll
- event: SignUp(uint256,indexed uint256,indexed uint256,uint256,uint256)
- event: SignUp(uint256,indexed uint256,indexed uint256,uint256,uint256,uint256)
handler: handleSignUp
file: ./src/maci.ts
templates:
Expand All @@ -54,12 +54,8 @@ templates:
- name: Poll
file: ./node_modules/maci-contracts/build/artifacts/contracts/Poll.sol/Poll.json
eventHandlers:
- event: MergeMaciState(indexed uint256,indexed uint256)
handler: handleMergeMaciState
- event: MergeMessageAq(indexed uint256)
handler: handleMergeMessageAq
- event: MergeMessageAqSubRoots(indexed uint256)
handler: handleMergeMessageAqSubRoots
- event: MergeState(indexed uint256,indexed uint256)
handler: handleMergeState
- event: PublishMessage((uint256[10]),(uint256,uint256))
handler: handlePublishMessage
file: ./src/poll.ts
10 changes: 6 additions & 4 deletions apps/subgraph/tests/common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Address, ethereum, BigInt } from "@graphprotocol/graph-ts";
import { Address, BigInt, ethereum } from "@graphprotocol/graph-ts";
// eslint-disable-next-line import/no-extraneous-dependencies
import { createMockedFunction } from "matchstick-as";

Expand All @@ -9,11 +9,13 @@ 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, "treeDepths", "treeDepths():(uint8,uint8,uint8,uint8)").returns([
createMockedFunction(DEFAULT_POLL_ADDRESS, "maxVoteOptions", "maxVoteOptions():(uint256)").returns([
ethereum.Value.fromI32(20),
]);

createMockedFunction(DEFAULT_POLL_ADDRESS, "treeDepths", "treeDepths():(uint8,uint8)").returns([
ethereum.Value.fromI32(1),
ethereum.Value.fromI32(2),
ethereum.Value.fromI32(3),
ethereum.Value.fromI32(4),
]);

createMockedFunction(
Expand Down
40 changes: 5 additions & 35 deletions apps/subgraph/tests/poll/poll.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,13 @@ import { test, describe, afterEach, clearStore, assert, beforeEach } from "match

import { MACI, Poll } from "../../generated/schema";
import { handleDeployPoll } from "../../src/maci";
import {
handleMergeMaciState,
handleMergeMessageAq,
handleMergeMessageAqSubRoots,
handlePublishMessage,
} from "../../src/poll";
import { handleMergeState, handlePublishMessage } from "../../src/poll";
import { DEFAULT_POLL_ADDRESS, mockMaciContract, mockPollContract } from "../common";
import { createDeployPollEvent } from "../maci/utils";

import {
createMergeMaciStateEvent,
createMergeMessageAqEvent,
createMergeMessageAqSubRootsEvent,
createPublishMessageEvent,
} from "./utils";
import { createMergeStateEvent, createPublishMessageEvent } from "./utils";

export { handleMergeMaciState, handleMergeMessageAq, handleMergeMessageAqSubRoots, handlePublishMessage };
export { handleMergeState, handlePublishMessage };

describe("Poll", () => {
beforeEach(() => {
Expand All @@ -38,9 +28,9 @@ describe("Poll", () => {
});

test("should handle merge maci state properly", () => {
const event = createMergeMaciStateEvent(DEFAULT_POLL_ADDRESS, BigInt.fromI32(1), BigInt.fromI32(3));
const event = createMergeStateEvent(DEFAULT_POLL_ADDRESS, BigInt.fromI32(1), BigInt.fromI32(3));

handleMergeMaciState(event);
handleMergeState(event);

const poll = Poll.load(event.address)!;
const maci = MACI.load(poll.maci)!;
Expand All @@ -53,26 +43,6 @@ describe("Poll", () => {
assert.assertTrue(maci.polls.load().length === 1);
});

test("should handle merge message queue properly", () => {
const event = createMergeMessageAqEvent(DEFAULT_POLL_ADDRESS, BigInt.fromI32(1));

handleMergeMessageAq(event);

const poll = Poll.load(DEFAULT_POLL_ADDRESS)!;

assert.fieldEquals("Poll", poll.id.toHex(), "messageRoot", "1");
});

test("should handle merge message queue subroots properly", () => {
const event = createMergeMessageAqSubRootsEvent(DEFAULT_POLL_ADDRESS, BigInt.fromI32(1));

handleMergeMessageAqSubRoots(event);

const poll = Poll.load(event.address)!;

assert.fieldEquals("Poll", poll.id.toHex(), "numSrQueueOps", "1");
});

test("should handle publish message properly", () => {
const event = createPublishMessageEvent(
DEFAULT_POLL_ADDRESS,
Expand Down
29 changes: 3 additions & 26 deletions apps/subgraph/tests/poll/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@ import { Address, BigInt as GraphBN, ethereum } from "@graphprotocol/graph-ts";
// eslint-disable-next-line import/no-extraneous-dependencies
import { newMockEvent } from "matchstick-as";

import {
MergeMaciState,
MergeMessageAq,
MergeMessageAqSubRoots,
PublishMessage,
} from "../../generated/templates/Poll/Poll";
import { MergeState, PublishMessage } from "../../generated/templates/Poll/Poll";

export function createMergeMaciStateEvent(address: Address, stateRoot: GraphBN, numSignups: GraphBN): MergeMaciState {
const event = changetype<MergeMaciState>(newMockEvent());
export function createMergeStateEvent(address: Address, stateRoot: GraphBN, numSignups: GraphBN): MergeState {
const event = changetype<MergeState>(newMockEvent());

event.parameters.push(new ethereum.EventParam("_stateRoot", ethereum.Value.fromUnsignedBigInt(stateRoot)));
event.parameters.push(new ethereum.EventParam("_numSignups", ethereum.Value.fromUnsignedBigInt(numSignups)));
Expand All @@ -19,24 +14,6 @@ export function createMergeMaciStateEvent(address: Address, stateRoot: GraphBN,
return event;
}

export function createMergeMessageAqEvent(address: Address, messageRoot: GraphBN): MergeMessageAq {
const event = changetype<MergeMessageAq>(newMockEvent());

event.parameters.push(new ethereum.EventParam("_messageRoot", ethereum.Value.fromUnsignedBigInt(messageRoot)));
event.address = address;

return event;
}

export function createMergeMessageAqSubRootsEvent(address: Address, numSrQueueOps: GraphBN): MergeMessageAqSubRoots {
const event = changetype<MergeMessageAqSubRoots>(newMockEvent());

event.parameters.push(new ethereum.EventParam("_numSrQueueOps", ethereum.Value.fromUnsignedBigInt(numSrQueueOps)));
event.address = address;

return event;
}

export function createPublishMessageEvent(
address: Address,
data: GraphBN[],
Expand Down
2 changes: 1 addition & 1 deletion apps/website/static/img/completingAPoll.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
76 changes: 76 additions & 0 deletions packages/circuits/circom/anon/pollJoining.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
pragma circom 2.0.0;

// circomlib import
include "./mux1.circom";
// zk-kit imports
include "./safe-comparators.circom";
// local imports
include "../utils/hashers.circom";
include "../utils/privToPubKey.circom";
include "../trees/incrementalMerkleTree.circom";

template PollJoining(stateTreeDepth) {
// Constants defining the structure and size of state.
var STATE_LEAF_LENGTH = 4;
var STATE_TREE_ARITY = 2;

// Public key IDs.
var STATE_LEAF_PUB_X_IDX = 0;
var STATE_LEAF_PUB_Y_IDX = 1;
// Voice Credit balance id
var STATE_LEAF_VOICE_CREDIT_BALANCE_IDX = 2;
var N_BITS = 252;

// User's private key
signal input privKey;
// Poll's private key
signal input pollPrivKey;
// Poll's public key
signal input pollPubKey[2];
// The state leaf and related path elements.
signal input stateLeaf[STATE_LEAF_LENGTH];
// Siblings
signal input siblings[stateTreeDepth][STATE_TREE_ARITY - 1];
// Indices
signal input indices[stateTreeDepth];
// User's hashed private key
signal input nullifier;
// User's credits for poll joining (might be <= oldCredits)
signal input credits;
// MACI State tree root which proves the user is signed up
signal input stateRoot;
// The actual tree depth (might be <= stateTreeDepth) Used in BinaryMerkleRoot
signal input actualStateTreeDepth;

var computedNullifier = PoseidonHasher(1)([privKey]);
nullifier === computedNullifier;

// User private to public key
var derivedPubKey[2] = PrivToPubKey()(privKey);
derivedPubKey[0] === stateLeaf[STATE_LEAF_PUB_X_IDX];
derivedPubKey[1] === stateLeaf[STATE_LEAF_PUB_Y_IDX];

// Poll private to public key
var derivedPollPubKey[2] = PrivToPubKey()(pollPrivKey);
derivedPollPubKey[0] === pollPubKey[0];
derivedPollPubKey[1] === pollPubKey[1];

// Inclusion proof
var stateLeafHash = PoseidonHasher(4)(stateLeaf);
var stateLeafQip = BinaryMerkleRoot(stateTreeDepth)(
stateLeafHash,
actualStateTreeDepth,
indices,
siblings
);

stateLeafQip === stateRoot;

// Check credits
var isCreditsValid = SafeLessEqThan(N_BITS)([credits, stateLeaf[STATE_LEAF_VOICE_CREDIT_BALANCE_IDX]]);
isCreditsValid === 1;

// Check nullifier
var hashedPrivKey = PoseidonHasher(1)([privKey]);
hashedPrivKey === nullifier;
}
20 changes: 12 additions & 8 deletions packages/circuits/circom/circuits.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
{
"ProcessMessages_10-2-1-2_test": {
"PollJoining_10_test": {
"file": "./anon/pollJoining",
"template": "PollJoining",
"params": [10],
"pubs": ["nullifier", "credits", "stateRoot", "pollPubKey"]
},
"ProcessMessages_10-20-2_test": {
"file": "./core/qv/processMessages",
"template": "ProcessMessages",
"params": [10, 2, 1, 2],
"params": [10, 20, 2],
"pubs": [
"numSignUps",
"index",
"batchEndIndex",
"msgRoot",
"currentSbCommitment",
"newSbCommitment",
"pollEndTimestamp",
"outputBatchHash",
"actualStateTreeDepth",
"coordinatorPublicKeyHash"
]
},
"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": [
"numSignUps",
"index",
"batchEndIndex",
"msgRoot",
"currentSbCommitment",
"newSbCommitment",
"pollEndTimestamp",
"outputBatchHash",
"actualStateTreeDepth",
"coordinatorPublicKeyHash"
]
Expand Down
Loading

0 comments on commit 2b8f11e

Please sign in to comment.