From 31bdaae6de83b6854580f0db898a4c2a0ffd9876 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Fri, 18 Aug 2023 16:49:15 +0100 Subject: [PATCH 01/14] feat(setup) - change S3 path to URL --- ceremonies/README.md | 14 ++-- .../p0tionConfig.json | 74 +++++++++---------- ceremonies/setup_ceremony_config.sh | 2 +- 3 files changed, 42 insertions(+), 48 deletions(-) diff --git a/ceremonies/README.md b/ceremonies/README.md index 64560bb..e8c0bac 100644 --- a/ceremonies/README.md +++ b/ceremonies/README.md @@ -18,7 +18,7 @@ To request a new ceremony to be setup, you will need to submit a PR with a folde - fill the *p0tionConfig.json* file accordingly: + The title of the ceremony will end up being its prefix. Prefixes are simply the title all lowercase, with dashes (*-*) instead of whitespace. For example, given a title of *Example Ceremony*, the prefix will be *example-ceremony*. + Fill the rest of the fields with the desired data, ensuring that each circuit details are correct, and that you chose the required Verification method. - + In the artifacts fields, please add the correct storage path and bucket name - note that we require both the *r1cs* and the *wasm* files. + + In the artifacts fields, please add the correct storage path on AWS (the URL to the artifacts) - note that we require both the *r1cs* and the *wasm* files. + *Note* that you can use [p0tion phase2cli](https://github.com/privacy-scaling-explorations/p0tion) as follows to verify that the config file is correct: * `phase2cli validate --template $PATH_TO_THE_TEMPLATE` - create a directory inside *./ceremonies* and name it with the *prefix* (detailed in the bullet point above). @@ -71,10 +71,8 @@ The script will upload your artifacts to a S3 bucket of your choice (must be own "cfOrVm": "" }, "artifacts": { - "bucket": "", - "region": "", - "r1csLocalFilePath": "", - "wasmLocalFilePath": "" + "r1csStoragePath": "", + "r1csStoragePath": "" }, "name": "", "dynamicThreshold": "", @@ -116,10 +114,8 @@ The script will upload your artifacts to a S3 bucket of your choice (must be own * "st1" * "sc1" - artifacts - an object with the storage path to the r1cs and wasm on s3 - - bucket - a string with the bucket name - - region - the AWS region where the bucket live - - r1csStoragePath - a string with the r1cs storage path e.g. "test-ceremony/circuit.r1cs" - - wasmStoragePath - a string with the wasm storage path e.g. "test-ceremony/circuit.wasm" + - r1csStoragePath - a string with the r1cs storage path on S3 e.g. "https://test-ceremony.region.amazonaws.com/circuit.r1cs" + - wasmStoragePath - a string with the wasm storage path on s3 e.g. "https://test-ceremony.region.amazonaws.com/circuit.wasm" - name - a string with the circuit name - dynamicThreshold - if selected dynamic timeout please enter the threshold here as a number - fixedTimeWindow - if selected fixed timeout please enter the time window here as a number diff --git a/ceremonies/rln-trusted-setup-ceremony/p0tionConfig.json b/ceremonies/rln-trusted-setup-ceremony/p0tionConfig.json index 6a19722..6dcfee6 100644 --- a/ceremonies/rln-trusted-setup-ceremony/p0tionConfig.json +++ b/ceremonies/rln-trusted-setup-ceremony/p0tionConfig.json @@ -21,10 +21,8 @@ "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", - "r1csStoragePath": "withdraw.r1cs", - "wasmStoragePath": "withdraw.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/withdraw.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/withdraw.wasm" }, "name": "RLN-Withdraw", "fixedTimeWindow": 3, @@ -47,8 +45,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln16.r1cs", - "wasmStoragePath": "rln16.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln16.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln16.wasm" }, "name": "RLN-16", "fixedTimeWindow": 3, @@ -71,8 +69,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln17.r1cs", - "wasmStoragePath": "rln17.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln17.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln17.wasm" }, "name": "RLN-17", "fixedTimeWindow": 3, @@ -95,8 +93,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln18.r1cs", - "wasmStoragePath": "rln18.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln18.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln18.wasm" }, "name": "RLN-18", "fixedTimeWindow": 3, @@ -119,8 +117,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln19.r1cs", - "wasmStoragePath": "rln19.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln19.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln19.wasm" }, "name": "RLN-19", "fixedTimeWindow": 3, @@ -143,8 +141,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln20.r1cs", - "wasmStoragePath": "rln20.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln20.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln20.wasm" }, "name": "RLN-20", "fixedTimeWindow": 3, @@ -167,8 +165,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln21.r1cs", - "wasmStoragePath": "rln21.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln21.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln21.wasm" }, "name": "RLN-21", "fixedTimeWindow": 3, @@ -191,8 +189,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln22.r1cs", - "wasmStoragePath": "rln22.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln22.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln22.wasm" }, "name": "RLN-22", "fixedTimeWindow": 3, @@ -215,8 +213,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln23.r1cs", - "wasmStoragePath": "rln23.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln23.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln23.wasm" }, "name": "RLN-23", "fixedTimeWindow": 3, @@ -239,8 +237,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln24.r1cs", - "wasmStoragePath": "rln24.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln24.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln24.wasm" }, "name": "RLN-24", "fixedTimeWindow": 3, @@ -263,8 +261,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln25.r1cs", - "wasmStoragePath": "rln25.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln25.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln25.wasm" }, "name": "RLN-25", "fixedTimeWindow": 3, @@ -286,8 +284,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln26.r1cs", - "wasmStoragePath": "rln26.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln26.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln26.wasm" }, "name": "RLN-26", "dynamicThreshold": 0, @@ -310,8 +308,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln27.r1cs", - "wasmStoragePath": "rln27.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln27.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln27.wasm" }, "name": "RLN-20", "dynamicThreshold": 0, @@ -334,8 +332,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln28.r1cs", - "wasmStoragePath": "rln28.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln28.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln28.wasm" }, "name": "RLN-28", "dynamicThreshold": 0, @@ -358,8 +356,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln29.r1cs", - "wasmStoragePath": "rln29.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln29.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln29.wasm" }, "name": "RLN-20", "dynamicThreshold": 0, @@ -382,8 +380,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln30.r1cs", - "wasmStoragePath": "rln30.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln30.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln30.wasm" }, "name": "RLN-30", "dynamicThreshold": 0, @@ -406,8 +404,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln31.r1cs", - "wasmStoragePath": "rln31.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln31.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln31.wasm" }, "name": "RLN-31", "dynamicThreshold": 0, @@ -430,8 +428,8 @@ "artifacts": { "bucket": "p0tion-test-definitely-setup", "region": "us-east-1", - "r1csStoragePath": "rln32.r1cs", - "wasmStoragePath": "rln32.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln32.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln32.wasm" }, "name": "RLN-32", "dynamicThreshold": 0, diff --git a/ceremonies/setup_ceremony_config.sh b/ceremonies/setup_ceremony_config.sh index 62d692f..32a4f17 100644 --- a/ceremonies/setup_ceremony_config.sh +++ b/ceremonies/setup_ceremony_config.sh @@ -288,7 +288,7 @@ do "compiler": {"version": $compiler_version, "commitHash": $compiler_commit_hash}, "template": {"source": $template_source, "commitHash": $template_commit_hash, "paramConfiguration": $params}, "verification": ($verification_method | if . == "CF" then {"cfOrVm": "CF"} else {"cfOrVm": "VM", "vmConfigurationType": $vm_configuration_type, "vmDiskSize": $vm_disk_size|tonumber, "vmDiskType": $vm_disk_type} end), - "artifacts": {"bucket": $bucket, "region": $region, "r1csStoragePath": ($base_name + ".r1cs"), "wasmStoragePath": ($base_name + ".wasm")}, + "artifacts": {"r1csStoragePath": ("https://" + $bucket + ".s3." + $region + ".amazonaws.com/" + $base_name + ".r1cs"), "wasmStoragePath": ("https://" + $bucket + ".s3." + $region + ".amazonaws.com/" + $base_name + ".wasm")}, "name": $base_name, "sequencePosition": $index|tonumber }') From 61f47a0c693c3043fba41528eca8a69550713318 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Thu, 31 Aug 2023 13:50:07 +0100 Subject: [PATCH 02/14] feat(cleanup) - refactor and add zkey download, multi ceremony banner --- web/.default.env | 10 +- web/src/App.tsx | 2 - web/src/Layout.tsx | 6 - web/src/components/ProjectCard.tsx | 2 +- web/src/context/ProjectPageContext.tsx | 40 +-- web/src/context/StateContext.tsx | 81 ++---- web/src/helpers/constants.ts | 10 + web/src/helpers/firebase.ts | 41 ++- web/src/helpers/interfaces.ts | 72 ++++- web/src/helpers/p0tion.ts | 12 +- web/src/helpers/utils.ts | 6 +- web/src/pages/LandingPage/Banner.tsx | 6 +- web/src/pages/LandingPage/HeroComponent.tsx | 284 +------------------- web/src/pages/LandingPage/LandingPage.tsx | 49 +--- web/src/pages/ProjectPage.tsx | 123 ++++----- 15 files changed, 241 insertions(+), 503 deletions(-) diff --git a/web/.default.env b/web/.default.env index dacade6..6aceb78 100644 --- a/web/.default.env +++ b/web/.default.env @@ -15,4 +15,12 @@ VITE_FIREBASE_APP_ID="YOUR-FIREBASE-APP-ID" # The AWS region where your buckets are located. VITE_AWS_REGION="YOUR-AWS-REGION" # The postfix used to create S3 buckets for storing the ceremonies artifacts. -VITE_CONFIG_CEREMONY_BUCKET_POSTFIX="YOUR-CEREMONY-BUCKET-POSTFIX" \ No newline at end of file +VITE_CONFIG_CEREMONY_BUCKET_POSTFIX="YOUR-CEREMONY-BUCKET-POSTFIX" +# The GitHub auth id +VITE_GITHUB_AUTH_ID="YOUR_GITHUB_AUTH_ID" +# the verify contribution endpoint +VITE_FIREBASE_CF_URL_VERIFY_CONTRIBUTION="YOUR_VERIFY_CONTRIBUTION_ENDPOINT" +# GitHub reputation checks +VITE_GITHUB_FOLLOWERS="YOUR_GITHUB_FOLLOWERS_THRESHOLD" +VITE_GITHUB_FOLLOWING="YOUR_GITHUB_FOLLOWING_THRESHOLD" +VITE_GITHUB_REPOS="YOUR_PUBLIC_GITHUB_REPOS_THRESHOLD" \ No newline at end of file diff --git a/web/src/App.tsx b/web/src/App.tsx index bef27f2..79f2c1b 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -1,9 +1,7 @@ import { BrowserRouter as Router, Routes, Route } from "react-router-dom"; import Layout from "./Layout"; import { StateProvider } from "./context/StateContext"; -// import { LandingPageProvider } from "./context/LandingPageContext"; import { ProjectPageProvider } from "./context/ProjectPageContext"; -// import SearchResults from "./components/SearchResults"; import ProjectPage from "./pages/ProjectPage"; import LandingPage from "./pages/LandingPage/LandingPage"; diff --git a/web/src/Layout.tsx b/web/src/Layout.tsx index e1c3fc3..a4650c3 100644 --- a/web/src/Layout.tsx +++ b/web/src/Layout.tsx @@ -101,12 +101,6 @@ const Layout: React.FC> = () => { - {/* - About - - - Documentation - */} diff --git a/web/src/components/ProjectCard.tsx b/web/src/components/ProjectCard.tsx index 7739f58..31dff6c 100644 --- a/web/src/components/ProjectCard.tsx +++ b/web/src/components/ProjectCard.tsx @@ -10,7 +10,7 @@ import { BreadcrumbItem } from "@chakra-ui/react"; -import { Project } from "../context/StateContext"; +import { Project } from "../helpers/interfaces"; interface ProjectCardProps { diff --git a/web/src/context/ProjectPageContext.tsx b/web/src/context/ProjectPageContext.tsx index caf504a..28c8407 100644 --- a/web/src/context/ProjectPageContext.tsx +++ b/web/src/context/ProjectPageContext.tsx @@ -11,11 +11,13 @@ import { } from "../helpers/firebase"; import { CircuitDocumentReferenceAndData, - ParticipantDocumentReferenceAndData + ParticipantDocumentReferenceAndData, + ProjectData, + ProjectPageContextProps, + ZkeyDownloadLink } from "../helpers/interfaces"; import { checkIfUserContributed, findLargestConstraint, processItems } from "../helpers/utils"; -import { maxConstraintsForBrowser } from "../helpers/constants"; - +import { awsRegion, bucketPostfix, finalContributionIndex, maxConstraintsForBrowser } from "../helpers/constants"; export const ProjectDataSchema = z.object({ circuits: z.optional(z.array(z.any())), @@ -23,17 +25,6 @@ export const ProjectDataSchema = z.object({ contributions: z.optional(z.array(z.any())) }); -export type ProjectData = z.infer; - -export type ProjectPageContextProps = { - hasUserContributed: boolean; - projectData: ProjectData | null; - isLoading: boolean; - runTutorial: boolean; - avatars?: string[]; - largestCircuitConstraints: number, -}; - export const defaultProjectData: ProjectData = {}; type ProjectPageProviderProps = { @@ -47,6 +38,7 @@ const ProjectPageContext = createContext({ runTutorial: false, avatars: [], largestCircuitConstraints: maxConstraintsForBrowser + 1, // contribution on browser has 100000 max constraints + finalZkeys: [] }); export const useProjectPageContext = () => useContext(ProjectPageContext); @@ -58,20 +50,36 @@ export const ProjectPageProvider: React.FC = ({ childr const [avatars, setAvatars] = useState([]); const [hasUserContributed, setHasUserContributed] = useState(false); const [largestCircuitConstraints, setLargestCircuitConstraints] = useState(maxConstraintsForBrowser + 1) // contribution on browser has 100000 max constraints + const [finalZkeys, setFinalZkeys] = useState([]) const { projects } = useStateContext(); const { ceremonyName } = useParams(); const project = projects.find((project) => project.ceremony.data.title === ceremonyName); - const projectId = project?.ceremony.uid || "HmLZ1vjZjhDPU0v3q8kD"; + const projectId = project?.ceremony.uid; useEffect(() => { const fetchData = async () => { setIsLoading(true); try { + if (projectId === undefined) return const circuitsDocs = await getCeremonyCircuits(projectId); const circuits: CircuitDocumentReferenceAndData[] = circuitsDocs.map((document: DocumentData) => ({ uid: document.id, data: document.data })); + const finalZkeys: ZkeyDownloadLink[] = [] + for (const circuit of circuits) { + const { prefix } = circuit.data + finalZkeys.push( + { + zkeyFilename: `${prefix}_${finalContributionIndex}.zkey`, + zkeyURL: `https://${project?.ceremony.data.prefix}${bucketPostfix}.s3.${awsRegion}.amazonaws.com/circuits/${ + prefix + }/contributions/${prefix}_${finalContributionIndex}.zkey` + } + ) + } + + setFinalZkeys(finalZkeys) const participantsDocs = await getAllCollectionDocs(`ceremonies/${projectId}/participants`); const participants: ParticipantDocumentReferenceAndData[] = participantsDocs.map((document: DocumentData) => ({ uid: document.id, data: document.data() })); @@ -108,7 +116,7 @@ export const ProjectPageProvider: React.FC = ({ childr return ( - + {children} ); diff --git a/web/src/context/StateContext.tsx b/web/src/context/StateContext.tsx index cabf7d1..7fde008 100644 --- a/web/src/context/StateContext.tsx +++ b/web/src/context/StateContext.tsx @@ -1,34 +1,9 @@ -// useStateContext.tsx - import React, { useState, createContext, useEffect, useContext } from "react"; -import { CeremonyDocumentReferenceAndData, CeremonyState, CeremonyTimeoutType, CeremonyType, CircuitContributionVerificationMechanism, CircuitDocumentReferenceAndData, ContributionDocumentReferenceAndData, ParticipantDocumentReferenceAndData } from "../helpers/interfaces"; -import { getAllCollectionDocs, getCeremonyCircuits } from "../helpers/firebase"; +import { CeremonyDocumentReferenceAndData, CeremonyState, CeremonyTimeoutType, CeremonyType, CircuitContributionVerificationMechanism, CircuitDocumentReferenceAndData, Project, State, StateProviderProps, WaitingQueue } from "../helpers/interfaces"; +import { getAllCollectionDocs, getCeremonyCircuitsWaitingQueue } from "../helpers/firebase"; import { DocumentData } from 'firebase/firestore' import { commonTerms } from "../helpers/constants"; -export interface Project { - ceremony: CeremonyDocumentReferenceAndData - circuits?: CircuitDocumentReferenceAndData[] | null - participants?: ParticipantDocumentReferenceAndData[] | null - contributions?: ContributionDocumentReferenceAndData[] | null -} - -export interface State { - projects: Project[]; - setProjects: React.Dispatch>; - circuit: CircuitDocumentReferenceAndData; - setCircuit: React.Dispatch>; - search: string; - setSearch: React.Dispatch>; - loading: boolean; - setLoading: React.Dispatch>; - runTutorial: boolean; - setRunTutorial: React.Dispatch>; - user?: string; - setUser?: React.Dispatch>; -} - - export const StateContext = createContext({ projects: [ // Initial project data @@ -125,46 +100,19 @@ export const StateContext = createContext({ setLoading: () => null, runTutorial: false, setRunTutorial: () => null, - setUser: () => {} + setUser: () => {}, + waitingQueue: [{} as WaitingQueue] }); export const useInitialStateContext = () => { - const [projects, setProjects] = useState([ - // Initial project data - ]); + const [projects, setProjects] = useState([]); const [circuit, setCircuit] = useState(); - + const [waitingQueue, setWaitingQueue] = useState([]) const [search, setSearch] = useState(""); const [loading, setLoading] = useState(false); const [runTutorial, setRunTutorial] = useState(false); - // Fetch circuit data and current user - useEffect(() => { - const fetchData = async () => { - /// @todo refactoring needed. - const ceremonyProjectId = "B7HZ7yW6waAWGKLr7GiA" - - if (ceremonyProjectId) { - try { - const circuitsDocs = await getCeremonyCircuits(ceremonyProjectId); - const circuits: CircuitDocumentReferenceAndData[] = circuitsDocs.map( - (document: DocumentData) => ({ uid: document.id, data: document.data }) - ); - - const updatedProjectData = { ...projects, circuits }; - setProjects(updatedProjectData); - setCircuit(circuits[0]) - } catch (error) { - console.error(error); - } - } - }; - - - fetchData(); - }, []); - - // Fetch ceremony data. + // Fetch ceremony data. useEffect(() => { const fetchData = async () => { // 0. Prepare service. @@ -177,6 +125,15 @@ export const useInitialStateContext = () => { const ceremonies: CeremonyDocumentReferenceAndData[] = docs.map((document: DocumentData) => { return { uid: document.id, data: document.data() } }) const projects: Project[] = ceremonies.map((ceremony: CeremonyDocumentReferenceAndData) => { return { ceremony: ceremony } }) + const queue: WaitingQueue[] = [] + for (const project of projects) { + if (project.ceremony.data.state === CeremonyState.OPENED) { + const tmpQueue = await getCeremonyCircuitsWaitingQueue(project.ceremony.uid, project.ceremony.data.title) + queue.push(...tmpQueue) + } + } + + setWaitingQueue(queue) // 3. Store data. setProjects(projects) setLoading(false) @@ -188,13 +145,9 @@ export const useInitialStateContext = () => { },[]) - return { projects, setProjects, circuit, setCircuit, search, setSearch, loading, setLoading, runTutorial, setRunTutorial }; + return { waitingQueue, projects, setProjects, circuit, setCircuit, search, setSearch, loading, setLoading, runTutorial, setRunTutorial }; }; - -type StateProviderProps = { - children: React.ReactNode; -}; export const StateProvider: React.FC = ({ children }) => { const [user, setUser] = useState( diff --git a/web/src/helpers/constants.ts b/web/src/helpers/constants.ts index 222f3cf..2617953 100644 --- a/web/src/helpers/constants.ts +++ b/web/src/helpers/constants.ts @@ -168,4 +168,14 @@ export const localPaths = { export const genesisZkeyIndex = "00000" export const finalContributionIndex = "final" export const bucketPostfix = import.meta.env.VITE_CONFIG_CEREMONY_BUCKET_POSTFIX +export const minRepos = import.meta.env.VITE_GITHUB_REPOS +export const minFollowers = import.meta.env.VITE_GITHUB_FOLLOWERS +export const minFollowing = import.meta.env.VITE_GITHUB_FOLLOWING +export const verifyContributionURL = import.meta.env.VITE_FIREBASE_CF_URL_VERIFY_CONTRIBUTION +export const apiKey = import.meta.env.VITE_FIREBASE_API_KEY +export const authDomain = import.meta.env.VITE_FIREBASE_AUTH_DOMAIN +export const projectId = import.meta.env.VITE_FIREBASE_PROJECT_ID +export const messagingSenderId = import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID +export const appId = import.meta.env.VITE_FIREBASE_APP_ID +export const awsRegion = import.meta.env.VITE_AWS_REGION export const maxConstraintsForBrowser = 1000000 \ No newline at end of file diff --git a/web/src/helpers/firebase.ts b/web/src/helpers/firebase.ts index 8b094b8..182523b 100644 --- a/web/src/helpers/firebase.ts +++ b/web/src/helpers/firebase.ts @@ -18,8 +18,8 @@ import { FirebaseApp, FirebaseOptions, initializeApp } from "firebase/app" // re import { Functions, getFunctions } from "firebase/functions" import { getContributionsCollectionPath, getParticipantsCollectionPath, getTimeoutsCollectionPath, processItems } from "./utils" import { Auth, getAuth } from "firebase/auth" -import { FirebaseDocumentInfo } from "./interfaces" -import { commonTerms } from "./constants" +import { FirebaseDocumentInfo, WaitingQueue } from "./interfaces" +import { apiKey, appId, authDomain, commonTerms, messagingSenderId, projectId } from "./constants" // we init this here so we can use it throughout the functions below export let firestoreDatabase: Firestore @@ -66,11 +66,11 @@ export const initializeFirebaseCoreServices = async (): Promise<{ firebaseFunctions: Functions }> => { const firebaseApp = initializeFirebaseApp({ - apiKey: import.meta.env.VITE_FIREBASE_API_KEY, - authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN, - projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID, - messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID, - appId: import.meta.env.VITE_FIREBASE_APP_ID + apiKey: apiKey, + authDomain: authDomain, + projectId: projectId, + messagingSenderId: messagingSenderId, + appId: appId }) const firestoreDatabase = getFirestoreDatabase(firebaseApp) const firebaseFunctions = getFunctions(firebaseApp, "europe-west1") @@ -314,3 +314,30 @@ export const getCurrentActiveParticipantTimeout = async ( return fromQueryToFirebaseDocumentInfo(participantTimeoutQuerySnap.docs) } + +/** + * Get how many users in the waiting queue per circuit + * @param ceremonyId {string} - the ceremony unique identifier. + * @param ceremonyName {string} - the ceremony name. + * @returns {WaitingQueue[]} + */ +export const getCeremonyCircuitsWaitingQueue = async ( + ceremonyId: string, + ceremonyName: string +): Promise => { + const circuits = await getCeremonyCircuits(ceremonyId) + + const waiting: WaitingQueue[] = [] + for (const circuit of circuits) { + const { waitingQueue, name } = circuit.data + const { contributors } = waitingQueue + + waiting.push({ + ceremonyName: ceremonyName, + circuitName: name, + waitingQueue: contributors.length + }) + } + + return waiting +} \ No newline at end of file diff --git a/web/src/helpers/interfaces.ts b/web/src/helpers/interfaces.ts index 9fd8af3..42404ca 100644 --- a/web/src/helpers/interfaces.ts +++ b/web/src/helpers/interfaces.ts @@ -1,5 +1,6 @@ import { DocumentData, DocumentReference } from "firebase/firestore"; -import { Project } from "../context/StateContext"; +import { z } from "zod"; +import { ProjectDataSchema } from "../context/ProjectPageContext"; /** * Define different states of a ceremony. @@ -376,9 +377,7 @@ export interface ContributionDocumentReferenceAndData { export interface HeroComponentProps { projects: Project[]; - circuit: CircuitDocumentReferenceAndData; - // circuits: CircuitDocumentReferenceAndData[]; - // contributions: ContributionDocumentReferenceAndData[]; + waitingQueue: WaitingQueue[]; } /** @@ -474,4 +473,67 @@ export type ContributionValidity = { contributionId: string circuitId: string valid: boolean -} \ No newline at end of file +} + +/** + * Group the information for downloading a circuit's final zKey + * @typedef {Object} ZkeyDownloadLink + * @property {string} zkeyFilename - the name of the zKey file. + * @property {string} zkeyURL - the url to download the zKey file. + */ +export interface ZkeyDownloadLink { + zkeyFilename: string + zkeyURL: string +} + +/** + * Map a circuit to its waiting queue + * @typedef {Object} WaitingQueue + * @property {string} ceremonyName - the name of the ceremony. + * @property {string} circuitName - the name of the circuit. + * @property {number} waitingQueue - the number of participants in the waiting queue. + */ +export interface WaitingQueue { + ceremonyName: string + circuitName: string + waitingQueue: number +} + +export interface Project { + ceremony: CeremonyDocumentReferenceAndData + circuits?: CircuitDocumentReferenceAndData[] | null + participants?: ParticipantDocumentReferenceAndData[] | null + contributions?: ContributionDocumentReferenceAndData[] | null +} + +export interface State { + projects: Project[]; + setProjects: React.Dispatch>; + circuit: CircuitDocumentReferenceAndData; + setCircuit: React.Dispatch>; + search: string; + setSearch: React.Dispatch>; + loading: boolean; + setLoading: React.Dispatch>; + runTutorial: boolean; + setRunTutorial: React.Dispatch>; + user?: string; + setUser?: React.Dispatch>; + waitingQueue: WaitingQueue[]; +} + +export type ProjectData = z.infer; + +export type ProjectPageContextProps = { + hasUserContributed: boolean; + projectData: ProjectData | null; + isLoading: boolean; + runTutorial: boolean; + avatars?: string[]; + largestCircuitConstraints: number, + finalZkeys?: ZkeyDownloadLink[] +}; + +export type StateProviderProps = { + children: React.ReactNode; +}; \ No newline at end of file diff --git a/web/src/helpers/p0tion.ts b/web/src/helpers/p0tion.ts index 657dd64..7beed5e 100644 --- a/web/src/helpers/p0tion.ts +++ b/web/src/helpers/p0tion.ts @@ -4,7 +4,7 @@ import { getAuth, GithubAuthProvider, signInWithPopup, signOut } from "firebase import { DocumentData, DocumentSnapshot, onSnapshot } from "firebase/firestore"; import { checkParticipantForCeremony, permanentlyStoreCurrentContributionTimeAndHash, progressToNextCircuitForContribution, progressToNextContributionStep, resumeContributionAfterTimeoutExpiration, verifyContribution } from "./functions"; import { checkGitHubReputation, convertToDoubleDigits, downloadCeremonyArtifact, formatHash, formatZkeyIndex, generatePublicAttestation, getBucketName, getGithubProviderUserId, getParticipantsCollectionPath, getSecondsMinutesHoursFromMillis, getZkeyStorageFilePath, handleTweetGeneration, multiPartUpload, publishGist, sleep } from "./utils"; -import { bucketPostfix, commonTerms } from "./constants"; +import { bucketPostfix, commonTerms, minFollowers, minFollowing, minRepos, verifyContributionURL } from "./constants"; import randomf from "randomf" declare global { @@ -80,10 +80,10 @@ export const contribute = async (ceremonyId: string, setStatus: (message: string const reputable = await checkGitHubReputation() if (!reputable) { setStatus(`You do not pass the GitHub reputation checks. - You need to have at least: ${import.meta.env.VITE_GITHUB_REPOS} public - repo${import.meta.env.VITE_GITHUB_REPOS > 1 ? "s" : ""}, ${import.meta.env.VITE_GITHUB_FOLLOWERS} - follower${import.meta.env.VITE_GITHUB_FOLLOWERS > 1 ? "s" : ""}, - and follow ${import.meta.env.VITE_GITHUB_FOLLOWING} user${import.meta.env.VITE_GITHUB_FOLLOWING > 1 ? "s" : ""}. + You need to have at least: ${minRepos} public + repo${minRepos > 1 ? "s" : ""}, ${minFollowers} + follower${minFollowers > 1 ? "s" : ""}, + and follow ${minFollowing} user${minFollowers > 1 ? "s" : ""}. Please fulfil the requirements and login again.`) return } @@ -274,7 +274,7 @@ export const handleStartOrResumeContribution = async ( circuit, bucketName, contributorIdentifier, - String(import.meta.env.VITE_FIREBASE_CF_URL_VERIFY_CONTRIBUTION) + verifyContributionURL ) setStatus("Contribution is valid", false) } catch (error: any) { diff --git a/web/src/helpers/utils.ts b/web/src/helpers/utils.ts index 12b8ffa..0795b86 100644 --- a/web/src/helpers/utils.ts +++ b/web/src/helpers/utils.ts @@ -1,5 +1,5 @@ import { getAuth } from "firebase/auth"; -import { commonTerms, finalContributionIndex, genesisZkeyIndex, localPaths } from "./constants"; +import { commonTerms, finalContributionIndex, genesisZkeyIndex, localPaths, minFollowers, minFollowing, minRepos } from "./constants"; import {firebaseApp, getCeremonyCircuits, getCircuitContributionsFromContributor, getCircuitsCollectionPath, getDocumentById } from "./firebase"; import { completeMultiPartUpload, generateGetObjectPreSignedUrl, generatePreSignedUrlsParts, openMultiPartUpload, temporaryStoreCurrentContributionMultiPartUploadId, temporaryStoreCurrentContributionUploadedChunkData } from "./functions"; import { ChunkWithUrl, Contribution, ContributionValidity, ETagWithPartNumber, FirebaseDocumentInfo, TemporaryParticipantContributionData, Timing } from "./interfaces"; @@ -841,10 +841,6 @@ export const findLargestConstraint = (array: any[]|undefined): number => { * @returns */ export const checkGitHubReputation = async (): Promise => { - const minRepos = import.meta.env.VITE_GITHUB_REPOS - const minFollowers = import.meta.env.VITE_GITHUB_FOLLOWERS - const minFollowing = import.meta.env.VITE_GITHUB_FOLLOWING - const resp = await fetch(`https://api.github.com/user`, { headers: { Authorization: `token ${localStorage.getItem("token")}` diff --git a/web/src/pages/LandingPage/Banner.tsx b/web/src/pages/LandingPage/Banner.tsx index 146eaa2..c630c8e 100644 --- a/web/src/pages/LandingPage/Banner.tsx +++ b/web/src/pages/LandingPage/Banner.tsx @@ -54,9 +54,7 @@ const ScrollBanner: FC = ({ imageArray }) => { h="full" > = ({ imageArray }) => { "100%": { transform: "translate(-30%, 0)" }, } }} - > + > {loopArray.map((item, index) => ( ))} - + ); }; diff --git a/web/src/pages/LandingPage/HeroComponent.tsx b/web/src/pages/LandingPage/HeroComponent.tsx index ee8d9d2..9f9a8d3 100644 --- a/web/src/pages/LandingPage/HeroComponent.tsx +++ b/web/src/pages/LandingPage/HeroComponent.tsx @@ -1,202 +1,35 @@ import { Box, Text, - // Stat, - // StatLabel, - // StatNumber, Heading, - // SimpleGrid, - // Badge, - // Table, - // Tag, - // Tbody, - // Td, - // Th, - // Thead, - // Tooltip, - // Tr, - // Flex, - // useBreakpointValue, - // Icon, VStack, HStack, - // Button, Spacer, SimpleGrid } from "@chakra-ui/react"; import { HeroComponentProps } from "../../helpers/interfaces"; import { ProjectCard } from "../../components/ProjectCard"; import { ScrollBanner } from "./Banner"; -// import { -// bytesToMegabytes, -// parseDate, -// truncateString, -// toBackgroundImagefromSrc, -// projectsPageSteps -// } from "../../helpers/utils"; -// import { FiTarget, FiZap, FiEye, FiUser, FiMapPin, FiWifi } from "react-icons/fi"; // you need to install `react-icons` for this. -// import { Link } from "react-router-dom"; -// import { useEffect, useState } from "react"; -// import Joyride, { STATUS } from "react-joyride"; -export function HeroComponent({ projects, circuit }: HeroComponentProps) { - // const projectsClean = projects.map((project) => ({ - // title: project.ceremony.data.title, - // description: project.ceremony.data.description, - // state: project.ceremony.data.state - // })) +export function HeroComponent({ projects, waitingQueue }: HeroComponentProps) { + const bannerImages: any[] = [] - /// @todo refactor tutorial. - // const [runTutorial, setRunTutorial] = useState(false); - // handle the callback from joyride - // const handleJoyrideCallback = (data: any) => { - // const { status } = data; - // if ([STATUS.FINISHED, STATUS.SKIPPED].includes(status)) { - // // Need to set our running state to false, so we can restart if we click start again. - // setRunTutorial(false); - // } - // }; - - // useEffect(() => { - // setRunTutorial(true); - // }, []); - - // const circuitsClean = circuits.map((circuit) => ({ - // name: circuit.data.name, - // description: circuit.data.description, - // constraints: circuit.data.metadata?.constraints, - // pot: circuit.data.metadata?.pot, - // privateInputs: circuit.data.metadata?.privateInputs, - // publicInputs: circuit.data.metadata?.publicInputs, - // curve: circuit.data.metadata?.curve, - // wires: circuit.data.metadata?.wires, - // completedContributions: circuit.data.waitingQueue?.completedContributions, - // currentContributor: circuit.data.waitingQueue?.currentContributor, - // memoryRequirement: bytesToMegabytes(circuit.data.zKeySizeInBytes ?? Math.pow(1024, 2)) - // .toString() - // .slice(0, 5), - // avgTimingContribution: Math.round(Number(circuit.data.avgTimings?.fullContribution) / 1000), - // maxTiming: Math.round((Number(circuit.data.avgTimings?.fullContribution) * 1.618) / 1000) - // })); - - // const contributionsClean = contributions.map((contribution) => ({ - // doc: contribution.data.files.lastZkeyFilename, - - // verificationComputationTime: contribution.data.verificationComputationTime, - - // valid: contribution.data.valid, - - // lastUpdated: parseDate(contribution.data.lastUpdated), - - // lastZkeyBlake2bHash: truncateString(contribution.data.files.lastZkeyBlake2bHash, 10), - - // transcriptBlake2bHash: truncateString(contribution.data.files.transcriptBlake2bHash, 10) - // })); - - // const columns = useBreakpointValue({ base: 1, md: 2, lg: 2 }); - const bannerImages = [ - { - imageUrl: "https://res.cloudinary.com/pse-qf-maci/image/upload/v1690230945/Banner_qb6zlf.png", - altText: "RLN Phase2 Trusted Setup Ceremony", - bannerText: `RLN Phase2 Trusted Setup Ceremony Waiting Queue: ${ - JSON.stringify(circuit?.data.waitingQueue?.contributors.length) ?? "no circuits!" - } ` - }, - { + for (const queue of waitingQueue) { + bannerImages.push({ imageUrl: "https://res.cloudinary.com/pse-qf-maci/image/upload/v1690230945/Banner_qb6zlf.png", - altText: "RLN Phase2 Trusted Setup Ceremony", - bannerText: `RLN Phase2 Trusted Setup Ceremony Waiting Queue: ${ - JSON.stringify(circuit?.data.waitingQueue?.contributors.length) ?? "no circuits!" + altText: queue.ceremonyName, + bannerText: `${queue.ceremonyName} Waiting Queue for Circuit ${queue.circuitName}: ${ + queue.waitingQueue ?? "no circuits!" } ` - } - // ...add as many images as you need - ]; - + }) + } + return ( <> - {/* @todo move to about */} - {/* - - - {" "} - How it works - - - {" "} - DefinitelySetup is a product designed to run Trusted Setup ceremonies for groth16 - based snarks - powered by p0tion. Thanks to p0tion, PSE can setup and manage trusted - setups for the community (subject to approval). - - - {" "} - Search for ceremonies, contribute your entropy to the system. - - - {" "} - In this website you will be able to browse all ceremonies created with p0tion, as well - as understand how to contribute to it and retrieve the final artifacts. Let's secure - GROTH16 protocols together. - - - - - - - - */} No ceremonies live yet! )} - - {/* CIRCUITS */} - {/* - - {circuitsClean.map((circuit, index) => ( - - - {circuit.name} - {circuit.description} - - - - - Constraints: {circuit.constraints} - - - - Pot: {circuit.pot} - - - - Private Inputs: {circuit.privateInputs} - - - - Public Inputs: {circuit.publicInputs} - - - - Curve: {circuit.curve} - - - - Wires: {circuit.wires} - - - - - - Completed Contributions - {circuit.completedContributions} - - - - - Memory Requirement - {circuit.memoryRequirement} mb - - - Avg Contribution Time - {circuit.avgTimingContribution}s - - - Max Contribution Time - {circuit.maxTiming}s - - - - ))} - - - - - - Contributions - - - - - - - - - - - - - - - {contributionsClean.map((contribution, index) => ( - - - - - - - ))} - -
DocContribution DateContribution TimeHashes
{contribution.doc}{contribution.lastUpdated}{contribution.verificationComputationTime} - - {contribution.lastZkeyBlake2bHash} - -
-
-
*/}
diff --git a/web/src/pages/LandingPage/LandingPage.tsx b/web/src/pages/LandingPage/LandingPage.tsx index 37d568f..0b0eb83 100644 --- a/web/src/pages/LandingPage/LandingPage.tsx +++ b/web/src/pages/LandingPage/LandingPage.tsx @@ -1,17 +1,11 @@ import React, { useContext } from "react"; -// import { Text } from "@chakra-ui/react"; import { StateContext } from "../../context/StateContext"; -// import { useLandingPageContext } from "../../context/LandingPageContext"; - -// import { ProjectData, ProjectDataSchema } from "../../context/ProjectPageContext"; import { HeroComponent } from "./HeroComponent"; import SearchResults from "../../components/SearchResults"; import { CircularProgress } from "@chakra-ui/react"; const LandingPage: React.FC = () => { - const { projects, circuit, search, loading } = useContext(StateContext); - - // const { projectData, isLoading, index } = useLandingPageContext(); + const { projects, waitingQueue, search, loading } = useContext(StateContext); if (loading) { return ( @@ -19,51 +13,12 @@ const LandingPage: React.FC = () => { ) } - // if (isLoading || loading) { - // return Loading...; - // } - - // // const projectId = "A8CVrp2MMx7KO512KFdv"; // aka ceremonyId. - // const project = projects[index]; - - // if (!project || !projectData) { - // return Error loading project.; - // } - - // Validate the project data against the schema - // const validatedProjectData: ProjectData = ProjectDataSchema.parse(projectData); - // console.log("validatedProjectData", validatedProjectData); - // const circuits = validatedProjectData.circuits - // ? validatedProjectData.circuits - // : { - // data: { - // fixedTimeWindow: 10, - // template: { - // source: "todo", - // paramsConfiguration: [2, 3, 4] - // }, - // compiler: { - // version: "0.5.1", - // commitHash: "0xabc" - // }, - // avgTimings: { - // fullContribution: 100 - // }, - // zKeySizeInBytes: 10, - // waitingQueue: { - // completedContributions: 0 - // } - // } - // }; - const render = search ? ( ) : ( ); return render; diff --git a/web/src/pages/ProjectPage.tsx b/web/src/pages/ProjectPage.tsx index b413ea1..0a17184 100644 --- a/web/src/pages/ProjectPage.tsx +++ b/web/src/pages/ProjectPage.tsx @@ -38,12 +38,11 @@ import { } from "@chakra-ui/react"; import { StateContext } from "../context/StateContext"; import { - ProjectData, ProjectDataSchema, useProjectPageContext } from "../context/ProjectPageContext"; import { FaCloudDownloadAlt, FaCopy } from "react-icons/fa"; -import { CeremonyState } from "../helpers/interfaces"; +import { CeremonyState, ProjectData } from "../helpers/interfaces"; import { FiTarget, FiZap, FiEye, FiUser, FiMapPin, FiWifi } from "react-icons/fi"; import { bytesToMegabytes, @@ -65,7 +64,7 @@ type RouteParams = { const ProjectPage: React.FC = () => { const { ceremonyName } = useParams(); const { user, projects, setRunTutorial, runTutorial } = useContext(StateContext); - const { hasUserContributed, projectData, isLoading, avatars, largestCircuitConstraints } = useProjectPageContext(); + const { finalZkeys, hasUserContributed, projectData, isLoading, avatars, largestCircuitConstraints } = useProjectPageContext(); // handle the callback from joyride const handleJoyrideCallback = (data: any) => { const { status } = data; @@ -75,7 +74,6 @@ const ProjectPage: React.FC = () => { } }; - // find a project with the given ceremony name const project = projects.find((p) => p.ceremony.data.title === ceremonyName); @@ -105,6 +103,7 @@ const ProjectPage: React.FC = () => { maxTiming: Math.round((Number(circuit.data.avgTimings?.fullContribution) * 1.618) / 1000) })) ?? []; + // parse contributions and sort by zkey name const contributionsClean = validatedProjectData.contributions?.map((contribution) => ({ doc: contribution.data.files?.lastZkeyFilename ?? "", @@ -116,30 +115,14 @@ const ProjectPage: React.FC = () => { contribution.data?.files?.transcriptBlake2bHash ?? "", 10 ) - })) ?? []; + })).slice().sort((a: any, b: any) => { + const docA = a.doc.toLowerCase() + const docB = b.doc.toLowerCase() - const circuit = validatedProjectData.circuits - ? validatedProjectData.circuits[0] - : { - data: { - fixedTimeWindow: 10, - template: { - source: "todo", - paramsConfiguration: [2, 3, 4] - }, - compiler: { - version: "0.5.1", - commitHash: "0xabc" - }, - avgTimings: { - fullContribution: 100 - }, - zKeySizeInBytes: 10, - waitingQueue: { - completedContributions: 0 - } - } - }; + if (docA < docB) return -1 + if (docA > docB) return 1 + return 0 + }) ?? []; // Commands const contributeCommand = @@ -148,33 +131,27 @@ const ProjectPage: React.FC = () => { : `phase2cli auth && phase2cli contribute -c ${project?.ceremony.data.prefix}`; const installCommand = `npm install -g @p0tion/phase2cli`; const authCommand = `phase2cli auth`; - const zKeyFilename = !circuit || isLoading ? "" : `${circuit.data.prefix}_final.zkey`; - const downloadLink = - !project || !circuit || isLoading - ? "" - : `https://${project?.ceremony.data.prefix}${ - import.meta.env.VITE_CONFIG_CEREMONY_BUCKET_POSTFIX - }.s3.${import.meta.env.VITE_AWS_REGION}.amazonaws.com/circuits/${ - circuit.data.prefix - }/contributions/${zKeyFilename}`; + // Hook for clipboard const { onCopy: copyContribute, hasCopied: copiedContribute } = useClipboard(contributeCommand); const { onCopy: copyInstall, hasCopied: copiedInstall } = useClipboard(installCommand); const { onCopy: copyAuth, hasCopied: copiedAuth } = useClipboard(authCommand); - /// @todo with a bit of refactor, could be used everywhere for downloading files from S3. // Download a file from AWS S3 bucket. - const downloadFileFromS3 = () => { - fetch(downloadLink).then((response) => { - response.blob().then((blob) => { - const fileURL = window.URL.createObjectURL(blob); - - let alink = document.createElement("a"); - alink.href = fileURL; - alink.download = zKeyFilename; - alink.click(); + const downloadFileFromS3 = (index: number, name: string) => { + if (finalZkeys) { + fetch(finalZkeys[index].zkeyURL).then((response) => { + response.blob().then((blob) => { + const fileURL = window.URL.createObjectURL(blob); + + let alink = document.createElement("a"); + alink.href = fileURL; + alink.download = name; + alink.click(); + }); }); - }); + } + }; return ( @@ -258,12 +235,16 @@ const ProjectPage: React.FC = () => { alignSelf={"stretch"} > { - user && !hasUserContributed && largestCircuitConstraints < maxConstraintsForBrowser ? + project.ceremony.data.state === CeremonyState.OPENED && user && !hasUserContributed && largestCircuitConstraints < maxConstraintsForBrowser ? : hasUserContributed ? You have already contributed to this ceremony. Thank you for your participation. : + project.ceremony.data.state !== CeremonyState.OPENED ? + + This ceremony is {project.ceremony.data.state.toLocaleLowerCase()}. + : <> You can contribute to this project by running the CLI commands below. @@ -504,9 +485,9 @@ const ProjectPage: React.FC = () => { letterSpacing={"0.01rem"} > {" "} - DefinitelySetup is powered by p0tion, a framework for setting up, managing and contributing to trusted setup ceremonies. - You can use this page to view the details of a ceremony, and also to download the final zKey, which will be made available - once the ceremony is finalized. + DefinitelySetup is a product designed to run Trusted Setup ceremonies for GROTH16 + based snarks - powered by p0tion. Thanks to p0tion, PSE can setup and manage trusted + setups for the community (subject to approval). {" "} @@ -514,31 +495,43 @@ const ProjectPage: React.FC = () => { {" "} + In this website you will be able to browse all ceremonies created with p0tion, as well + as understand how to contribute to it and retrieve the final artifacts. Let's secure + GROTH16 protocols together.
Please note that when circuits have a large number of constraints (you can usually see that when the memory requirements are greater than 100mb), the contribution might take a long time.
- + Download Final ZKey: - Use the command below to download the final ZKey file from the S3 bucket. + Press the button below to download the final ZKey files from the S3 bucket. - + { + finalZkeys?.map((zkey, index) => { + return ( + + ) + }) + } + From a027f56fa23f2adc98675615ca2908606806a887 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Thu, 31 Aug 2023 14:47:18 +0100 Subject: [PATCH 03/14] feat(verification) add final beacon and last zkeys --- web/src/context/ProjectPageContext.tsx | 46 ++++++++++++--- web/src/helpers/firebase.ts | 26 ++++++++- web/src/helpers/interfaces.ts | 58 ++++++++++++++++--- web/src/pages/ProjectPage.tsx | 78 +++++++++++++++++++++++++- 4 files changed, 189 insertions(+), 19 deletions(-) diff --git a/web/src/context/ProjectPageContext.tsx b/web/src/context/ProjectPageContext.tsx index 28c8407..e4a19d7 100644 --- a/web/src/context/ProjectPageContext.tsx +++ b/web/src/context/ProjectPageContext.tsx @@ -7,16 +7,19 @@ import { getAllCollectionDocs, getCeremonyCircuits, getContributions, + getFinalBeacon, getParticipantsAvatar } from "../helpers/firebase"; import { + CeremonyState, CircuitDocumentReferenceAndData, + FinalBeacon, ParticipantDocumentReferenceAndData, ProjectData, ProjectPageContextProps, ZkeyDownloadLink } from "../helpers/interfaces"; -import { checkIfUserContributed, findLargestConstraint, processItems } from "../helpers/utils"; +import { checkIfUserContributed, findLargestConstraint, formatZkeyIndex, processItems } from "../helpers/utils"; import { awsRegion, bucketPostfix, finalContributionIndex, maxConstraintsForBrowser } from "../helpers/constants"; export const ProjectDataSchema = z.object({ @@ -46,11 +49,13 @@ export const useProjectPageContext = () => useContext(ProjectPageContext); export const ProjectPageProvider: React.FC = ({ children }) => { const navigate = useNavigate(); const { loading: isLoading, setLoading: setIsLoading, runTutorial } = useContext(StateContext); - const [projectData, setProjectData] = useState(defaultProjectData); - const [avatars, setAvatars] = useState([]); - const [hasUserContributed, setHasUserContributed] = useState(false); - const [largestCircuitConstraints, setLargestCircuitConstraints] = useState(maxConstraintsForBrowser + 1) // contribution on browser has 100000 max constraints - const [finalZkeys, setFinalZkeys] = useState([]) + const [ projectData, setProjectData ] = useState(defaultProjectData); + const [ avatars, setAvatars ] = useState([]); + const [ hasUserContributed, setHasUserContributed ] = useState(false); + const [ largestCircuitConstraints, setLargestCircuitConstraints ] = useState(maxConstraintsForBrowser + 1) // contribution on browser has 100000 max constraints + const [ finalZkeys, setFinalZkeys ] = useState([]) + const [ latestZkeys, setLatestZkeys ] = useState([]) + const [ finalBeacon, setFinalBeacon ] = useState() const { projects } = useStateContext(); const { ceremonyName } = useParams(); @@ -62,11 +67,12 @@ export const ProjectPageProvider: React.FC = ({ childr const fetchData = async () => { setIsLoading(true); try { - if (projectId === undefined) return + if (projectId === undefined || project === undefined) return const circuitsDocs = await getCeremonyCircuits(projectId); const circuits: CircuitDocumentReferenceAndData[] = circuitsDocs.map((document: DocumentData) => ({ uid: document.id, data: document.data })); const finalZkeys: ZkeyDownloadLink[] = [] + const lastZkeys: ZkeyDownloadLink[] = [] for (const circuit of circuits) { const { prefix } = circuit.data finalZkeys.push( @@ -77,9 +83,33 @@ export const ProjectPageProvider: React.FC = ({ childr }/contributions/${prefix}_${finalContributionIndex}.zkey` } ) + + // store the latest zkey for each circuit + const { waitingQueue } = circuit.data + + // if it's not finalized then we skip + if (project.ceremony.data.state !== CeremonyState.FINALIZED) continue + + const index = formatZkeyIndex(waitingQueue!.completedContributions) + lastZkeys.push( + { + zkeyFilename: `${prefix}_${index}.zkey`, + zkeyURL: `https://${project?.ceremony.data.prefix}${bucketPostfix}.s3.${awsRegion}.amazonaws.com/circuits/${ + prefix + }/contributions/${prefix}_${index}.zkey` + } + ) } + setLatestZkeys(lastZkeys) setFinalZkeys(finalZkeys) + + // if we have data for the ceremony and it's finalized then we can get the final beacon + if (project.ceremony && project.ceremony.data.state === CeremonyState.FINALIZED) { + const beacon = await getFinalBeacon(projectId, project.ceremony.data.coordinatorId, circuits[0].uid) + setFinalBeacon(beacon) + } + const participantsDocs = await getAllCollectionDocs(`ceremonies/${projectId}/participants`); const participants: ParticipantDocumentReferenceAndData[] = participantsDocs.map((document: DocumentData) => ({ uid: document.id, data: document.data() })); @@ -116,7 +146,7 @@ export const ProjectPageProvider: React.FC = ({ childr return ( - + {children} ); diff --git a/web/src/helpers/firebase.ts b/web/src/helpers/firebase.ts index 182523b..969801c 100644 --- a/web/src/helpers/firebase.ts +++ b/web/src/helpers/firebase.ts @@ -19,7 +19,7 @@ import { Functions, getFunctions } from "firebase/functions" import { getContributionsCollectionPath, getParticipantsCollectionPath, getTimeoutsCollectionPath, processItems } from "./utils" import { Auth, getAuth } from "firebase/auth" import { FirebaseDocumentInfo, WaitingQueue } from "./interfaces" -import { apiKey, appId, authDomain, commonTerms, messagingSenderId, projectId } from "./constants" +import { apiKey, appId, authDomain, commonTerms, finalContributionIndex, messagingSenderId, projectId } from "./constants" // we init this here so we can use it throughout the functions below export let firestoreDatabase: Firestore @@ -340,4 +340,28 @@ export const getCeremonyCircuitsWaitingQueue = async ( } return waiting +} + + +/** + * Get the final beacon used for finalizing a ceremony + * @param ceremonyId + */ +export const getFinalBeacon = async (ceremonyId: string, coordinatorId: string, circuitId: string) => { + const contributions = await getCircuitContributionsFromContributor(ceremonyId, circuitId, coordinatorId) + + const filtered = contributions + .filter((contributionDocument: any) => contributionDocument.data.zkeyIndex === finalContributionIndex) + .at(0) + + if (!filtered) + return { + beacon: "", + beaconHash: "" + } + + return { + beacon: filtered.data.beacon.value, + beaconHash: filtered.data.beacon.hash + } } \ No newline at end of file diff --git a/web/src/helpers/interfaces.ts b/web/src/helpers/interfaces.ts index 42404ca..e116d32 100644 --- a/web/src/helpers/interfaces.ts +++ b/web/src/helpers/interfaces.ts @@ -499,11 +499,21 @@ export interface WaitingQueue { waitingQueue: number } +/** + * Define the data structure for a project. + * @typedef {Object} Project + * @property {CeremonyDocumentReferenceAndData} ceremony - the reference and data of the ceremony. + * @property {Array} [circuits] - the list of references and data of the circuits. + * @property {Array} [participants] - the list of references and data of the participants. + * @property {Array} [contributions] - the list of references and data of the contributions. + * @property {string} [coordinatorId] - the unique identifier of the coordinator. + */ export interface Project { ceremony: CeremonyDocumentReferenceAndData circuits?: CircuitDocumentReferenceAndData[] | null participants?: ParticipantDocumentReferenceAndData[] | null contributions?: ContributionDocumentReferenceAndData[] | null + coordinatorId?: string } export interface State { @@ -522,18 +532,52 @@ export interface State { waitingQueue: WaitingQueue[]; } +/** + * Define the data structure for the project page context. + * @typedef {Object} ProjectData + * @property {string} ceremonyName - the name of the ceremony. + * @property {string} ceremonyDescription - the description of the ceremony. + * @property {string} ceremonyState - the state of the ceremony. + * @property {string} ceremonyType - the type of the ceremony. + */ export type ProjectData = z.infer; +/** + * Define the data structure for the project page context. + * @typedef {Object} ProjectPageContextProps + * @property {boolean} hasUserContributed - true if the user has contributed to the project; otherwise false. + * @property {ProjectData} projectData - the data about the project. + * @property {boolean} isLoading - true if the data is being loaded; otherwise false. + * @property {boolean} runTutorial - true if the tutorial should be run; otherwise false. + * @property {string[]} [avatars] - the list of avatars for the participants. + * @property {number} largestCircuitConstraints - the number of constraints of the largest circuit in the project. + * @property {ZkeyDownloadLink[]} [finalZkeys] - the list of final zKeys for the project. + * @property {FinalBeacon} [finalBeacon] - the beacon info for the final contribution. + * @property {ZkeyDownloadLink[]} [latestZkeys] - the list of latest zKeys for the project. + */ export type ProjectPageContextProps = { - hasUserContributed: boolean; - projectData: ProjectData | null; - isLoading: boolean; - runTutorial: boolean; - avatars?: string[]; - largestCircuitConstraints: number, + hasUserContributed: boolean + projectData: ProjectData | null + isLoading: boolean + runTutorial: boolean + avatars?: string[] + largestCircuitConstraints: number finalZkeys?: ZkeyDownloadLink[] + finalBeacon?: FinalBeacon + latestZkeys?: ZkeyDownloadLink[] }; export type StateProviderProps = { children: React.ReactNode; -}; \ No newline at end of file +}; + +/** + * Define the data structure for the beacon info. + * @typedef {Object} BeaconInfo + * @property {string} value - the value of the beacon. + * @property {string} hash - the hash of the beacon. + */ +export interface FinalBeacon { + beacon: string + beaconHash: string +} \ No newline at end of file diff --git a/web/src/pages/ProjectPage.tsx b/web/src/pages/ProjectPage.tsx index 0a17184..a10c9d9 100644 --- a/web/src/pages/ProjectPage.tsx +++ b/web/src/pages/ProjectPage.tsx @@ -64,7 +64,7 @@ type RouteParams = { const ProjectPage: React.FC = () => { const { ceremonyName } = useParams(); const { user, projects, setRunTutorial, runTutorial } = useContext(StateContext); - const { finalZkeys, hasUserContributed, projectData, isLoading, avatars, largestCircuitConstraints } = useProjectPageContext(); + const { latestZkeys, finalBeacon, finalZkeys, hasUserContributed, projectData, isLoading, avatars, largestCircuitConstraints } = useProjectPageContext(); // handle the callback from joyride const handleJoyrideCallback = (data: any) => { const { status } = data; @@ -131,11 +131,16 @@ const ProjectPage: React.FC = () => { : `phase2cli auth && phase2cli contribute -c ${project?.ceremony.data.prefix}`; const installCommand = `npm install -g @p0tion/phase2cli`; const authCommand = `phase2cli auth`; + const beaconValue = finalBeacon?.beacon + const beaconHash = finalBeacon?.beaconHash // Hook for clipboard const { onCopy: copyContribute, hasCopied: copiedContribute } = useClipboard(contributeCommand); const { onCopy: copyInstall, hasCopied: copiedInstall } = useClipboard(installCommand); const { onCopy: copyAuth, hasCopied: copiedAuth } = useClipboard(authCommand); + const { onCopy: copyBeaconValue, hasCopied: copiedBeaconValue } = useClipboard(beaconValue || "") + const { onCopy: copyBeaconHash, hasCopied: copiedBeaconHash } = useClipboard(beaconHash || "") + // Download a file from AWS S3 bucket. const downloadFileFromS3 = (index: number, name: string) => { @@ -505,8 +510,44 @@ const ProjectPage: React.FC = () => { - - Download Final ZKey: + { + project?.ceremony.data.state === CeremonyState.FINALIZED && beaconHash && beaconValue && +
+ + Final contribution beacon + + + +
+ } + + Download Final ZKey Press the button below to download the final ZKey files from the S3 bucket. @@ -531,6 +572,37 @@ const ProjectPage: React.FC = () => { ) }) } + { + project?.ceremony.data.state === CeremonyState.FINALIZED && + <> + + Download Last ZKey + + + You can use this zKey with the beacon value to verify that the final zKey was computed correctly. + + { + latestZkeys?.map((zkey, index) => { + return ( + + ) + }) + } + + }
From 34bb23450130677ea5ab7d9516c85be7921037ae Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Thu, 31 Aug 2023 15:25:56 +0100 Subject: [PATCH 04/14] feat(contribution) add warning about changin tabs --- web/src/components/Contribution.tsx | 1 + web/src/pages/ProjectPage.tsx | 11 ++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/web/src/components/Contribution.tsx b/web/src/components/Contribution.tsx index b5d3e03..14e7a0e 100644 --- a/web/src/components/Contribution.tsx +++ b/web/src/components/Contribution.tsx @@ -31,6 +31,7 @@ export const Contribution = (props: any): React.JSX.Element => { status === "" && Press contribute to join the ceremony } + If contributing on your phone, please do not leave the current browser tab {status} diff --git a/web/src/pages/ProjectPage.tsx b/web/src/pages/ProjectPage.tsx index a10c9d9..b48a044 100644 --- a/web/src/pages/ProjectPage.tsx +++ b/web/src/pages/ProjectPage.tsx @@ -242,14 +242,14 @@ const ProjectPage: React.FC = () => { { project.ceremony.data.state === CeremonyState.OPENED && user && !hasUserContributed && largestCircuitConstraints < maxConstraintsForBrowser ? : - hasUserContributed ? - - You have already contributed to this ceremony. Thank you for your participation. - : project.ceremony.data.state !== CeremonyState.OPENED ? This ceremony is {project.ceremony.data.state.toLocaleLowerCase()}. : + hasUserContributed ? + + You have already contributed to this ceremony. Thank you for your participation. + : <> You can contribute to this project by running the CLI commands below. @@ -579,7 +579,8 @@ const ProjectPage: React.FC = () => { Download Last ZKey - You can use this zKey with the beacon value to verify that the final zKey was computed correctly. + You can + use this zKey with the beacon value to verify that the final zKey was computed correctly. { latestZkeys?.map((zkey, index) => { From 521906b1d494f25496a87dab37b983628a6c74a6 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Thu, 31 Aug 2023 16:39:43 +0100 Subject: [PATCH 05/14] feat(cleanup) add login on tutorial and circuit details --- web/src/components/Login.tsx | 2 +- web/src/helpers/utils.ts | 6 +- web/src/pages/LandingPage/Banner.tsx | 1 - web/src/pages/ProjectPage.tsx | 90 ++++++++++++++++------------ 4 files changed, 57 insertions(+), 42 deletions(-) diff --git a/web/src/components/Login.tsx b/web/src/components/Login.tsx index 726dceb..809c5fe 100644 --- a/web/src/components/Login.tsx +++ b/web/src/components/Login.tsx @@ -21,7 +21,7 @@ export const Login = () => { return ( <> - diff --git a/web/src/helpers/utils.ts b/web/src/helpers/utils.ts index 0795b86..4156a58 100644 --- a/web/src/helpers/utils.ts +++ b/web/src/helpers/utils.ts @@ -76,6 +76,10 @@ export const projectsPageSteps = [ // steps for the tutorial on the single project details page export const singleProjectPageSteps = [ + { + target: ".loginButton", + content: "Click Login here to be able to contribute via your Browser" + }, { target: ".contributeCopyButton", content: "Here you can copy the command needed to contribute to this ceremony", @@ -93,7 +97,7 @@ export const singleProjectPageSteps = [ content: "Click here to view the completed contributions", }, { - target: ".detailsButton", + target: ".linksButton", content: "Click here to view the details of this circuit", }, { diff --git a/web/src/pages/LandingPage/Banner.tsx b/web/src/pages/LandingPage/Banner.tsx index c630c8e..aaa1fd9 100644 --- a/web/src/pages/LandingPage/Banner.tsx +++ b/web/src/pages/LandingPage/Banner.tsx @@ -43,7 +43,6 @@ const ScrollBanner: FC = ({ imageArray }) => { { // Validate the project data against the schema const validatedProjectData: ProjectData = ProjectDataSchema.parse(projectData); - /// @todo work on multiple circuits. - /// @todo uncomplete info for mocked fallback circuit data. - const circuitsClean = validatedProjectData.circuits?.map((circuit) => ({ + template: circuit.data.template, name: circuit.data.name, description: circuit.data.description, constraints: circuit.data.metadata?.constraints, @@ -97,7 +95,6 @@ const ProjectPage: React.FC = () => { currentContributor: circuit.data.waitingQueue?.currentContributor, memoryRequirement: bytesToMegabytes(circuit.data.zKeySizeInBytes ?? Math.pow(1024, 2)) .toString() - .slice(0, 5), avgTimingContribution: Math.round(Number(circuit.data.avgTimings?.fullContribution) / 1000), maxTiming: Math.round((Number(circuit.data.avgTimings?.fullContribution) * 1.618) / 1000) @@ -348,8 +345,8 @@ const ProjectPage: React.FC = () => { Contributions - - Details + + About Download ZKey @@ -471,44 +468,60 @@ const ProjectPage: React.FC = () => { - - - {" "} - How it works - - + - {" "} - DefinitelySetup is a product designed to run Trusted Setup ceremonies for GROTH16 - based snarks - powered by p0tion. Thanks to p0tion, PSE can setup and manage trusted - setups for the community (subject to approval). - - - {" "} - Search for ceremonies, contribute your entropy to the system. - - - {" "} - In this website you will be able to browse all ceremonies created with p0tion, as well - as understand how to contribute to it and retrieve the final artifacts. Let's secure - GROTH16 protocols together.
- Please note that when circuits have a large number of constraints (you can usually see that when the memory requirements - are greater than 100mb), the contribution might take a long time. -
+ {circuitsClean.map((circuit, index) => ( + + + {circuit.name} - {circuit.description} + + + + + Parameters + + { + circuit.template.paramConfiguration.length > 0 ? + circuit.template.paramConfiguration.join(" ") : + "No parameters" + } + + + + + Commit Hash + + {truncateString(circuit.template.commitHash, 6)} + + + + Template Link + + + {truncateString(circuit.template.source, 16)} + + + + + + ))} + + +
- { project?.ceremony.data.state === CeremonyState.FINALIZED && beaconHash && beaconValue && @@ -547,7 +560,7 @@ const ProjectPage: React.FC = () => { } - Download Final ZKey + Download Final ZKey(s) Press the button below to download the final ZKey files from the S3 bucket. @@ -576,11 +589,10 @@ const ProjectPage: React.FC = () => { project?.ceremony.data.state === CeremonyState.FINALIZED && <> - Download Last ZKey + Download Last ZKey(s) - You can - use this zKey with the beacon value to verify that the final zKey was computed correctly. + You can use this zKey(s) with the beacon value to verify that the final zKey(s) was computed correctly. { latestZkeys?.map((zkey, index) => { From 3b582badb36c31833c2704e0b23748f1d73a9557 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Thu, 31 Aug 2023 16:40:44 +0100 Subject: [PATCH 06/14] chore(syntax)- fix syntax --- web/src/helpers/utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/helpers/utils.ts b/web/src/helpers/utils.ts index 4156a58..436aa4f 100644 --- a/web/src/helpers/utils.ts +++ b/web/src/helpers/utils.ts @@ -90,7 +90,7 @@ export const singleProjectPageSteps = [ }, { target: ".circuitsView", - content: "Here you can see the circuits for this ceremony and their live statistics", + content: "Click here to view the circuits for this ceremony and their live statistics", }, { target: ".contributionsButton", @@ -98,7 +98,7 @@ export const singleProjectPageSteps = [ }, { target: ".linksButton", - content: "Click here to view the details of this circuit", + content: "Click here to view the details of the circuits", }, { target: ".zKeyNavigationButton", From 657e2c64b25f7def6e5d0b779bc5a967b1366db3 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Thu, 31 Aug 2023 16:48:34 +0100 Subject: [PATCH 07/14] fix(project) remove .length --- web/src/pages/ProjectPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/pages/ProjectPage.tsx b/web/src/pages/ProjectPage.tsx index f3cf24a..e2f7bd4 100644 --- a/web/src/pages/ProjectPage.tsx +++ b/web/src/pages/ProjectPage.tsx @@ -493,7 +493,7 @@ const ProjectPage: React.FC = () => { Parameters { - circuit.template.paramConfiguration.length > 0 ? + circuit.template.paramConfiguration ? circuit.template.paramConfiguration.join(" ") : "No parameters" } From 2b6c4b873e3e9e06d2935bbe45b1fd05c1219760 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Thu, 31 Aug 2023 16:58:08 +0100 Subject: [PATCH 08/14] fix(firebase) - replace .at with [] --- web/src/helpers/firebase.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/src/helpers/firebase.ts b/web/src/helpers/firebase.ts index 969801c..ddce9d0 100644 --- a/web/src/helpers/firebase.ts +++ b/web/src/helpers/firebase.ts @@ -351,8 +351,7 @@ export const getFinalBeacon = async (ceremonyId: string, coordinatorId: string, const contributions = await getCircuitContributionsFromContributor(ceremonyId, circuitId, coordinatorId) const filtered = contributions - .filter((contributionDocument: any) => contributionDocument.data.zkeyIndex === finalContributionIndex) - .at(0) + .filter((contributionDocument: any) => contributionDocument.data.zkeyIndex === finalContributionIndex)[0] if (!filtered) return { From 8bc1eba739024e58586cfda92639efdc9da8d9db Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Thu, 31 Aug 2023 17:05:41 +0100 Subject: [PATCH 09/14] fix(contribute) - stop listener upon timeout --- web/src/helpers/p0tion.ts | 5 ++++- web/tsconfig.json | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/web/src/helpers/p0tion.ts b/web/src/helpers/p0tion.ts index 7beed5e..ff95fe0 100644 --- a/web/src/helpers/p0tion.ts +++ b/web/src/helpers/p0tion.ts @@ -576,7 +576,10 @@ export const listenToParticipantDocumentChanges = async ( setStatus(`You are timed out. Timeout will end in ${convertToDoubleDigits(days)}:${convertToDoubleDigits(hours)}:${convertToDoubleDigits( minutes - )}:${convertToDoubleDigits(seconds)} (dd:hh:mm:ss)`, false) + )}:${convertToDoubleDigits(seconds)} (dd:hh:mm:ss). + Please reload the page and try again once the timeout expires`, false) + + unsubscribe() } if (completedContribution || timeoutExpired) { diff --git a/web/tsconfig.json b/web/tsconfig.json index a7fc6fb..d4aba32 100644 --- a/web/tsconfig.json +++ b/web/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { - "target": "ES2020", + "target": "ES2022", "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], + "lib": ["ES2022", "DOM", "DOM.Iterable"], "module": "ESNext", "skipLibCheck": true, From 52812b07bed87659c9957e7fd4daef0ff5184f00 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Thu, 31 Aug 2023 17:21:57 +0100 Subject: [PATCH 10/14] fix(params) fix wrong param name --- web/src/pages/ProjectPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/pages/ProjectPage.tsx b/web/src/pages/ProjectPage.tsx index e2f7bd4..767016c 100644 --- a/web/src/pages/ProjectPage.tsx +++ b/web/src/pages/ProjectPage.tsx @@ -493,8 +493,8 @@ const ProjectPage: React.FC = () => { Parameters { - circuit.template.paramConfiguration ? - circuit.template.paramConfiguration.join(" ") : + circuit.template.paramsConfiguration ? + circuit.template.paramsConfiguration.join(" ") : "No parameters" } From a67cb304ed104238ec21ba137262a65867eba2a9 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Thu, 31 Aug 2023 17:26:17 +0100 Subject: [PATCH 11/14] fix(typo) - fix typo --- .../pull_request_template.md | 4 ++-- .github/pull_request_template.md | 4 ++-- ceremonies/README.md | 4 ++-- .../p0tionConfig.json | 22 +++++++++---------- ceremonies/setup_ceremony_config.sh | 4 ++-- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md index c5f5794..642c8ce 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -62,7 +62,7 @@ Failing to follow the above instructions, will result in the CI checks failing. "template": { "source": "", "commitHash": "", - "paramConfiguration": [""] + "paramsConfiguration": [""] }, "verification": { "cfOrVm": "" @@ -98,7 +98,7 @@ Failing to follow the above instructions, will result in the CI checks failing. - template - an object made of: - source - a string with the URL of the circom file - commitHash - a string with the commit id (needs to be a GitHub commit hash) - - paramConfiguration - an array of numbers with the parameters of the circuit template + - paramsConfiguration - an array of numbers with the parameters of the circuit template - verification - an object detailing how the circuit's zKeys will be verified - cfOrVm - a string with either "CF" or "VM". If "VM" the following must be added: - vmConfigurationType - a string with the VM type - options: diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 2d828ab..288c010 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -57,7 +57,7 @@ Failing to follow the above instructions, will result in the CI checks failing. "template": { "source": "", "commitHash": "", - "paramConfiguration": [6,8,3,2] + "paramsConfiguration": [6,8,3,2] }, "verification": { "cfOrVm": "CF" @@ -91,7 +91,7 @@ Failing to follow the above instructions, will result in the CI checks failing. - template - an object made of: - source - a string with the URL of the circom file - commitHash - a string with the commit id (needs to be a GitHub commit hash) - - paramConfiguration - an array of numbers with the parameters of the circuit template + - paramsConfiguration - an array of numbers with the parameters of the circuit template - verification - an object detailing how the circuit's zKeys will be verified - cfOrVm - a string with either "CF" or "VM". If "VM" the following must be added: - vmConfigurationType - a string with the VM type - options: diff --git a/ceremonies/README.md b/ceremonies/README.md index e8c0bac..198f819 100644 --- a/ceremonies/README.md +++ b/ceremonies/README.md @@ -65,7 +65,7 @@ The script will upload your artifacts to a S3 bucket of your choice (must be own "template": { "source": "", "commitHash": "", - "paramConfiguration": [""] + "paramsConfiguration": [""] }, "verification": { "cfOrVm": "" @@ -99,7 +99,7 @@ The script will upload your artifacts to a S3 bucket of your choice (must be own - template - an object made of: - source - a string with the URL of the circom file - commitHash - a string with the commit id (needs to be a GitHub commit hash) - - paramConfiguration - an array of numbers with the parameters of the circuit template + - paramsConfiguration - an array of numbers with the parameters of the circuit template - verification - an object detailing how the circuit's zKeys will be verified - cfOrVm - a string with either "CF" or "VM". If "VM" the following must be added: - vmConfigurationType - a string with the VM type - options: diff --git a/ceremonies/rln-trusted-setup-ceremony/p0tionConfig.json b/ceremonies/rln-trusted-setup-ceremony/p0tionConfig.json index 6dcfee6..9e64047 100644 --- a/ceremonies/rln-trusted-setup-ceremony/p0tionConfig.json +++ b/ceremonies/rln-trusted-setup-ceremony/p0tionConfig.json @@ -15,7 +15,7 @@ "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", - "paramConfiguration": [] + "paramsConfiguration": [] }, "verification": { "cfOrVm": "CF" @@ -37,7 +37,7 @@ "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", - "paramConfiguration": [16, 16] + "paramsConfiguration": [16, 16] }, "verification": { "cfOrVm": "CF" @@ -61,7 +61,7 @@ "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", - "paramConfiguration": [17, 16] + "paramsConfiguration": [17, 16] }, "verification": { "cfOrVm": "CF" @@ -85,7 +85,7 @@ "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", - "paramConfiguration": [18, 16] + "paramsConfiguration": [18, 16] }, "verification": { "cfOrVm": "CF" @@ -109,7 +109,7 @@ "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", - "paramConfiguration": [19, 16] + "paramsConfiguration": [19, 16] }, "verification": { "cfOrVm": "CF" @@ -133,7 +133,7 @@ "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", - "paramConfiguration": [20, 16] + "paramsConfiguration": [20, 16] }, "verification": { "cfOrVm": "CF" @@ -157,7 +157,7 @@ "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", - "paramConfiguration": [21, 16] + "paramsConfiguration": [21, 16] }, "verification": { "cfOrVm": "CF" @@ -181,7 +181,7 @@ "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", - "paramConfiguration": [22, 16] + "paramsConfiguration": [22, 16] }, "verification": { "cfOrVm": "CF" @@ -205,7 +205,7 @@ "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", - "paramConfiguration": [23, 16] + "paramsConfiguration": [23, 16] }, "verification": { "cfOrVm": "CF" @@ -229,7 +229,7 @@ "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", - "paramConfiguration": [24, 16] + "paramsConfiguration": [24, 16] }, "verification": { "cfOrVm": "CF" @@ -253,7 +253,7 @@ "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", - "paramConfiguration": [25, 16] + "paramsConfiguration": [25, 16] }, "verification": { "cfOrVm": "CF" diff --git a/ceremonies/setup_ceremony_config.sh b/ceremonies/setup_ceremony_config.sh index 32a4f17..597eb7d 100644 --- a/ceremonies/setup_ceremony_config.sh +++ b/ceremonies/setup_ceremony_config.sh @@ -263,7 +263,7 @@ do echo -e "\nEnter circuit description:" read circuit_description - echo -e "\nEnter paramConfiguration values as a comma-separated list (e.g. 6,8,3,2):" + echo -e "\nEnter paramsConfiguration values as a comma-separated list (e.g. 6,8,3,2):" read param_str params=$(jq -nR '[(input | split(",")[] | tonumber)]' <<< "$param_str") @@ -286,7 +286,7 @@ do '{ "description": $circuit_description, "compiler": {"version": $compiler_version, "commitHash": $compiler_commit_hash}, - "template": {"source": $template_source, "commitHash": $template_commit_hash, "paramConfiguration": $params}, + "template": {"source": $template_source, "commitHash": $template_commit_hash, "paramsConfiguration": $params}, "verification": ($verification_method | if . == "CF" then {"cfOrVm": "CF"} else {"cfOrVm": "VM", "vmConfigurationType": $vm_configuration_type, "vmDiskSize": $vm_disk_size|tonumber, "vmDiskType": $vm_disk_type} end), "artifacts": {"r1csStoragePath": ("https://" + $bucket + ".s3." + $region + ".amazonaws.com/" + $base_name + ".r1cs"), "wasmStoragePath": ("https://" + $bucket + ".s3." + $region + ".amazonaws.com/" + $base_name + ".wasm")}, "name": $base_name, From 1aa9edcc96a617676f1ddb6e9ce641911b1ace5a Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Thu, 31 Aug 2023 17:53:16 +0100 Subject: [PATCH 12/14] fix(circuit params) - support legacy firestore field --- web/src/pages/ProjectPage.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/src/pages/ProjectPage.tsx b/web/src/pages/ProjectPage.tsx index 767016c..8537129 100644 --- a/web/src/pages/ProjectPage.tsx +++ b/web/src/pages/ProjectPage.tsx @@ -493,8 +493,10 @@ const ProjectPage: React.FC = () => { Parameters { - circuit.template.paramsConfiguration ? + circuit.template.paramsConfiguration && circuit.template.paramsConfiguration.length > 0 ? circuit.template.paramsConfiguration.join(" ") : + circuit.template.paramConfiguration && circuit.template.paramConfiguration.length > 0 ? + circuit.template.paramConfiguration.join(" ") : "No parameters" } From 11eed2886c206b08e722a4bf2a7b637636196dff Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Tue, 3 Oct 2023 14:23:11 +0100 Subject: [PATCH 13/14] feat(setup) - fix missing params on rln config file --- .../p0tionConfig.json | 55 +++++-------------- 1 file changed, 14 insertions(+), 41 deletions(-) diff --git a/ceremonies/rln-trusted-setup-ceremony/p0tionConfig.json b/ceremonies/rln-trusted-setup-ceremony/p0tionConfig.json index 9e64047..94805f1 100644 --- a/ceremonies/rln-trusted-setup-ceremony/p0tionConfig.json +++ b/ceremonies/rln-trusted-setup-ceremony/p0tionConfig.json @@ -43,8 +43,6 @@ "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln16.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln16.wasm" }, @@ -67,8 +65,6 @@ "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln17.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln17.wasm" }, @@ -91,8 +87,6 @@ "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln18.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln18.wasm" }, @@ -115,8 +109,6 @@ "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln19.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln19.wasm" }, @@ -139,8 +131,6 @@ "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln20.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln20.wasm" }, @@ -163,8 +153,6 @@ "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln21.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln21.wasm" }, @@ -187,8 +175,6 @@ "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln22.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln22.wasm" }, @@ -211,8 +197,6 @@ "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln23.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln23.wasm" }, @@ -235,8 +219,6 @@ "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln24.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln24.wasm" }, @@ -259,8 +241,6 @@ "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln25.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln25.wasm" }, @@ -276,14 +256,13 @@ }, "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", - "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d" + "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", + "paramsConfiguration": [26, 16] }, "verification": { "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln26.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln26.wasm" }, @@ -300,14 +279,13 @@ }, "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", - "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d" + "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", + "paramsConfiguration": [27, 16] }, "verification": { "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln27.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln27.wasm" }, @@ -324,14 +302,13 @@ }, "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", - "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d" + "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", + "paramsConfiguration": [28, 16] }, "verification": { "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln28.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln28.wasm" }, @@ -348,14 +325,13 @@ }, "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", - "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d" + "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", + "paramsConfiguration": [29, 16] }, "verification": { "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln29.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln29.wasm" }, @@ -372,14 +348,13 @@ }, "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", - "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d" + "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", + "paramsConfiguration": [30, 16] }, "verification": { "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln30.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln30.wasm" }, @@ -396,14 +371,13 @@ }, "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", - "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d" + "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", + "paramsConfiguration": [31, 16] }, "verification": { "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln31.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln31.wasm" }, @@ -420,14 +394,13 @@ }, "template": { "source": "https://github.com/Rate-Limiting-Nullifier/circom-rln", - "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d" + "commitHash": "17f0fed7d8d19e8b127fd0b3e5295a4831193a0d", + "paramsConfiguration": [32, 16] }, "verification": { "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln32.r1cs", "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/rln32.wasm" }, From 5be52e5a689001116189b44497fa8cc7c154fe0f Mon Sep 17 00:00:00 2001 From: 0xSachinK <0xsachink@gmail.com> Date: Wed, 17 Jan 2024 01:11:16 +0530 Subject: [PATCH 14/14] Add p0tion config file --- .../p0tionConfig.json | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 ceremonies/zkp2p-trusted-setup-ceremony-v2.1/p0tionConfig.json diff --git a/ceremonies/zkp2p-trusted-setup-ceremony-v2.1/p0tionConfig.json b/ceremonies/zkp2p-trusted-setup-ceremony-v2.1/p0tionConfig.json new file mode 100644 index 0000000..80c1b53 --- /dev/null +++ b/ceremonies/zkp2p-trusted-setup-ceremony-v2.1/p0tionConfig.json @@ -0,0 +1,32 @@ +{ + "title": "ZKP2P Trusted Setup Ceremony V2.1", + "description": "This is a trusted setup ceremony for the ZKP2P protocol", + "startDate": "2024-01-17T10:30:00", + "endDate": "2024-01-19T10:30:00", + "timeoutMechanismType": "FIXED", + "penalty": 3, + "circuits": [ + { + "description": "ZKP2P HDFC Send circuit", + "compiler": { + "version": "2.1.5", + "commitHash": "127414e9088cc017a357233f30f3fd7d91a8906c" + }, + "template": { + "source": "https://github.com/zkp2p/zk-p2p", + "commitHash": "7293bce5633b5bda8aa379451efe1860a7c5081e", + "paramsConfiguration": [1024, 4352, 121, 17, 7] + }, + "verification": { + "cfOrVm": "VM" + }, + "artifacts": { + "r1csStoragePath": "https://zk-p2p.s3.amazonaws.com/v2.5/v0.2.1/hdfc_send/hdfc_send.r1cs", + "wasmStoragePath": "https://zk-p2p.s3.amazonaws.com/v2.5/v0.2.1/hdfc_send/hdfc_send.wasm" + }, + "name": "ZKP2P-HDFC-Send", + "fixedTimeWindow": 3, + "sequencePosition": 1 + } + ] + } \ No newline at end of file