Skip to content

Commit

Permalink
Merge pull request #494 from privacy-scaling-explorations/feat/devcon…
Browse files Browse the repository at this point in the history
…-round-result-page

feat: add result page to devcon round branch
  • Loading branch information
ctrlc03 authored Nov 25, 2024
2 parents 928ebaa + 3bc4910 commit 71e4b11
Show file tree
Hide file tree
Showing 50 changed files with 1,662 additions and 1,570 deletions.
13 changes: 10 additions & 3 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ jobs:
path: |
~/.pnpm-store
node_modules
/home/runner/.cache/Cypress
packages/e2e/.cache-synpress
key: ${{ runner.os }}-node-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-node-
Expand All @@ -84,11 +82,16 @@ jobs:
sudo apt-get install --no-install-recommends -y \
xvfb
- name: Copy .env.example to .env
- name: Copy .env.example to .env (interface)
run: |
cp .env.example .env
working-directory: packages/interface

- name: Copy .env.example to .env (e2e)
run: |
cp .env.example .env
working-directory: packages/e2e

- name: Build
run: pnpm run build

Expand All @@ -99,10 +102,14 @@ jobs:
- name: Build cache
run: xvfb-run pnpm run build:cache
working-directory: packages/e2e
env:
NEXT_PUBLIC_ALCHEMY_ID: ${{ secrets.NEXT_PUBLIC_ALCHEMY_ID }}

- name: Run Playwright tests
run: xvfb-run pnpm run test:playwright:headful
working-directory: packages/e2e
env:
NEXT_PUBLIC_ALCHEMY_ID: ${{ secrets.NEXT_PUBLIC_ALCHEMY_ID }}

- uses: actions/upload-artifact@v4
if: always()
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,4 @@ jobs:
- name: E2E tests
run: |
pnpm run test:e2e
working-directory: packages/coordinator
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Privacy & Scaling Explorations

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
"start:coordinator": "lerna run start --scope=maci-coordinator",
"dev:interface": "lerna run dev --scope=maci-platform-interface",
"test:coordinator": "lerna run test --scope=maci-coordinator",
"test:interface:e2e": "lerna run test:e2e --scope=maci-platform-interface",
"hardhat": "lerna run hardhat --scope=maci-platform-interface"
},
"author": "PSE",
Expand All @@ -38,7 +37,7 @@
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^9.0.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.30.0",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-json": "^4.0.0",
"eslint-plugin-jsx-a11y": "^6.9.0",
"eslint-plugin-prettier": "^5.2.1",
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
"@openzeppelin/contracts": "^5.0.2",
"circomlibjs": "^0.1.7",
"ethers": "^6.13.2",
"ethers": "^6.13.4",
"hardhat": "^2.22.15",
"lowdb": "^1.0.0",
"maci-contracts": "0.0.0-ci.6007edf",
"maci-contracts": "0.0.0-ci.6bdb342",
"maci-core": "^2.4.0",
"maci-crypto": "^2.4.0",
"maci-domainobjs": "^2.4.0",
Expand Down
Binary file removed packages/contracts/proofs.zip
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/contracts/tasks/runner/initPoll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface IInitPollParams {
}

/**
* Command to merge signup and message queues of a MACI contract
* Command to initialize poll
*/
task("initPoll", "Initialize poll")
.addParam("poll", "The poll id", undefined, types.string)
Expand Down
102 changes: 56 additions & 46 deletions packages/contracts/tasks/runner/submitOnChain.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable no-await-in-loop */
/* eslint-disable no-console */
import { BaseContract } from "ethers";
import { task, types } from "hardhat/config";
import { ContractStorage, Deployment, Proof, Prover, type TallyData } from "maci-contracts";

Expand All @@ -14,10 +13,35 @@ import {
type AccQueue,
type MessageProcessor,
type Tally,
type SimpleRegistry,
} from "../../typechain-types";
import { EContracts, ISubmitOnChainParams } from "../helpers/constants";

/**
* Interface that represents read proofs arguments
*/
interface IReadProofsArgs {
files: string[];
folder: string;
type: "tally" | "process";
}

/**
* Read and parse proofs
*
* @param args - read proofs arguments
* @returns proofs
*/
async function readProofs({ files, folder, type }: IReadProofsArgs): Promise<Proof[]> {
return Promise.all(
files
.filter((f) => f.startsWith(`${type}_`) && f.endsWith(".json"))
.sort()
.map(async (file) =>
fs.promises.readFile(`${folder}/${file}`, "utf8").then((result) => JSON.parse(result) as Proof),
),
);
}

/**
* Prove hardhat task for submitting proofs on-chain as well as uploading tally results
*/
Expand Down Expand Up @@ -57,13 +81,15 @@ task("submitOnChain", "Command to prove the result of a poll on-chain")
} = await import("../../typechain-types");

const maciContractAddress = storage.mustGetAddress(EContracts.MACI, network.name);
const maciContract = await deployment.getContract<MACI>({
name: EContracts.MACI,
address: maciContractAddress,
abi: MACIFactory.abi,
});
const vkRegistryContract = await deployment.getContract<VkRegistry>({ name: EContracts.VkRegistry });
const verifierContract = await deployment.getContract<Verifier>({ name: EContracts.Verifier });
const [maciContract, vkRegistryContract, verifierContract] = await Promise.all([
deployment.getContract<MACI>({
name: EContracts.MACI,
address: maciContractAddress,
abi: MACIFactory.abi,
}),
deployment.getContract<VkRegistry>({ name: EContracts.VkRegistry }),
deployment.getContract<Verifier>({ name: EContracts.Verifier }),
]);

const pollContracts = await maciContract.polls(poll);
const pollContract = await deployment.getContract<Poll>({
Expand All @@ -72,39 +98,38 @@ task("submitOnChain", "Command to prove the result of a poll on-chain")
abi: PollFactory.abi,
});

const [, messageAqContractAddress] = await pollContract.extContracts();
const [[, messageAqContractAddress], isStateAqMerged, messageTreeDepth, mpContract, tallyContract] =
await Promise.all([
pollContract.extContracts(),
pollContract.stateMerged(),
pollContract.treeDepths().then((depths) => Number(depths[2])),
deployment.getContract<MessageProcessor>({
name: EContracts.MessageProcessor,
address: pollContracts.messageProcessor,
}),
deployment.getContract<Tally>({
name: EContracts.Tally,
address: pollContracts.tally,
abi: TallyFactory.abi,
}),
]);
const messageAqContract = await deployment.getContract<AccQueue>({
name: EContracts.AccQueue,
address: messageAqContractAddress,
});
const isStateAqMerged = await pollContract.stateMerged();

// Check that the state and message trees have been merged for at least the first poll
if (!isStateAqMerged && poll.toString() === "0") {
throw new Error("The state tree has not been merged yet. Please use the mergeSignups subcommand to do so.");
}

const messageTreeDepth = await pollContract.treeDepths().then((depths) => Number(depths[2]));

// check that the main root is set
const mainRoot = await messageAqContract.getMainRoot(messageTreeDepth.toString());

if (mainRoot.toString() === "0") {
throw new Error("The message tree has not been merged yet. Please use the mergeMessages subcommand to do so.");
}

const mpContract = await deployment.getContract<MessageProcessor>({
name: EContracts.MessageProcessor,
address: pollContracts.messageProcessor,
});

// get the tally contract based on the useQuadraticVoting flag
const tallyContract = await deployment.getContract<Tally>({
name: EContracts.Tally,
address: pollContracts.tally,
abi: TallyFactory.abi,
});

const data = {
processProofs: [] as Proof[],
tallyProofs: [] as Proof[],
Expand All @@ -114,22 +139,9 @@ task("submitOnChain", "Command to prove the result of a poll on-chain")
const files = await fs.promises.readdir(outputDir);

// Read process proofs
const processProofFiles = files.filter((f) => f.startsWith("process_") && f.endsWith(".json"));
await Promise.all(
processProofFiles.sort().map(async (file) => {
const proofData = JSON.parse(await fs.promises.readFile(`${outputDir}/${file}`, "utf8")) as Proof;
data.processProofs.push(proofData);
}),
);

data.processProofs = await readProofs({ files, folder: outputDir, type: "process" });
// Read tally proofs
const tallyProofFiles = files.filter((f) => f.startsWith("tally_") && f.endsWith(".json"));
await Promise.all(
tallyProofFiles.sort().map(async (file) => {
const proofData = JSON.parse(await fs.promises.readFile(`${outputDir}/${file}`, "utf8")) as Proof;
data.tallyProofs.push(proofData);
}),
);
data.tallyProofs = await readProofs({ files, folder: outputDir, type: "tally" });

const prover = new Prover({
maciContract,
Expand All @@ -144,18 +156,16 @@ task("submitOnChain", "Command to prove the result of a poll on-chain")
await prover.proveMessageProcessing(data.processProofs);

// read tally data
const tallyData = JSON.parse(await fs.promises.readFile(tallyFile, "utf8")) as unknown as TallyData;
const tallyData = await fs.promises
.readFile(tallyFile, "utf8")
.then((result) => JSON.parse(result) as unknown as TallyData);

await prover.proveTally(data.tallyProofs);

// submit the results with number participants to be taken from the registry
const registryContractAddress = await pollContract.getRegistry();

const registryContract = new BaseContract(
registryContractAddress,
SimpleRegistryFactory.abi,
signer,
) as SimpleRegistry;
const registryContract = SimpleRegistryFactory.connect(registryContractAddress, signer);
const recipientCount = await registryContract.recipientCount();

await prover.submitResults(tallyData, Number.parseInt(recipientCount.toString(), 10));
Expand Down
12 changes: 6 additions & 6 deletions packages/coordinator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@
"dependencies": {
"@graphprotocol/graph-cli": "^0.79.0",
"@nestjs/common": "^10.4.7",
"@nestjs/core": "^10.3.10",
"@nestjs/core": "^10.4.7",
"@nestjs/platform-express": "^10.4.7",
"@nestjs/platform-socket.io": "^10.3.10",
"@nestjs/swagger": "^8.0.3",
"@nestjs/throttler": "^6.0.0",
"@nestjs/websockets": "^10.4.4",
"@nestjs/websockets": "^10.4.7",
"@nomicfoundation/hardhat-ethers": "^3.0.8",
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
"@vercel/blob": "^0.25.0",
Expand All @@ -47,11 +47,11 @@
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"dotenv": "^16.4.5",
"ethers": "^6.13.1",
"ethers": "^6.13.4",
"hardhat": "^2.22.15",
"helmet": "^7.1.0",
"helmet": "^8.0.0",
"lowdb": "^1.0.0",
"maci-circuits": "^2.3.0",
"maci-circuits": "^2.4.0",
"maci-cli": "^2.3.0",
"maci-contracts": "^2.3.0",
"maci-domainobjs": "^2.0.0",
Expand All @@ -75,7 +75,7 @@
"@types/lowdb": "^1.0.15",
"@types/node": "^20.14.11",
"@types/supertest": "^6.0.2",
"fast-check": "^3.22.0",
"fast-check": "^3.23.1",
"jest": "^29.5.0",
"socket.io-client": "^4.7.5",
"supertest": "^7.0.0",
Expand Down
5 changes: 0 additions & 5 deletions packages/coordinator/scripts/uploadRoundMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export interface RoundMetadata {
registrationEndsAt: Date;
votingStartsAt: Date;
votingEndsAt: Date;
tallyFile: string;
}

interface IUploadMetadataProps {
Expand Down Expand Up @@ -137,17 +136,13 @@ export async function collectMetadata(): Promise<RoundMetadata> {

rl.close();

// NOTICE! this is when you use vercel blob storage, if you're using another tool, please change this part.
const vercelStoragePrefix = `https://${process.env.BLOB_READ_WRITE_TOKEN?.split("_")[3]}.public.blob.vercel-storage.com`;

return {
roundId,
description,
startsAt,
registrationEndsAt: new Date(startsAt.getTime() + registrationEndsIn * 1000),
votingStartsAt: new Date(startsAt.getTime() + registrationEndsIn * 1000),
votingEndsAt: new Date(startsAt.getTime() + registrationEndsIn * 1000 + votingEndsIn * 1000),
tallyFile: `${vercelStoragePrefix}/tally-${roundId}.json`,
};
}

Expand Down
Binary file removed packages/interface/metamask-chrome-11.15.1.zip
Binary file not shown.
Loading

0 comments on commit 71e4b11

Please sign in to comment.