Skip to content

Commit

Permalink
fix(verification): fixed hardhat task
Browse files Browse the repository at this point in the history
refactored hardhat task to include authentication, and cleanup
  • Loading branch information
ctrlc03 committed Mar 20, 2023
1 parent 86f54b2 commit eeb6214
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 37 deletions.
3 changes: 1 addition & 2 deletions packages/actions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"pre:publish": "yarn build",
"compile:contracts": "hardhat compile",
"test:contracts": "export GOOGLE_APPLICATION_CREDENTIALS=\"../backend/serviceAccountKey.json\" && NODE_ENV=prod hardhat test test/unit/contract.test.ts",
"verify:ceremony": "export GOOGLE_APPLICATION_CREDENTIALS=\"../backend/serviceAccountKey.json\" && hardhat verifyCeremony"
"verify:ceremony": "export GOOGLE_APPLICATION_CREDENTIALS=\"../backend/serviceAccountKey.json\" && NODE_ENV=prod hardhat verifyCeremony"
},
"dependencies": {
"@octokit/auth-oauth-device": "^4.0.3",
Expand Down Expand Up @@ -68,7 +68,6 @@
"rollup-plugin-auto-external": "^2.0.0",
"rollup-plugin-cleanup": "^3.2.1",
"rollup-plugin-typescript2": "^0.34.1",
"solc": "^0.8.19",
"ts-node": "^10.9.1",
"typescript": "^4.9.3",
"winston": "^3.8.2"
Expand Down
22 changes: 17 additions & 5 deletions packages/actions/src/helpers/contracts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Contract, ContractFactory, Signer } from "ethers"
import { utils as ffUtils } from "ffjavascript"
import { Firestore } from "firebase/firestore"
import { Firestore, where } from "firebase/firestore"
import { Functions } from "firebase/functions"
import fs from "fs"
import solc from "solc"
Expand All @@ -14,7 +14,8 @@ import {
verifyZKey
} from "./verification"
import { compareHashes } from "./crypto"
import { finalContributionIndex, verificationKeyAcronym, verifierSmartContractAcronym } from "./constants"
import { commonTerms, finalContributionIndex, verificationKeyAcronym, verifierSmartContractAcronym } from "./constants"
import { fromQueryToFirebaseDocumentInfo, queryCollection } from "./database"

/**
* Formats part of a GROTH16 SNARK proof
Expand Down Expand Up @@ -140,7 +141,6 @@ export const deployVerifierContract = async (contractPath: string, signer: Signe
* @param circuitInputsPath <string> path to the circuit inputs file
* @param verifierTemplatePath <string> path to the verifier template file
* @param signer <Signer> signer for contract interaction
* @param coordinatorId <string> coordinator id
* @param logger <any> logger for printing snarkjs output
*/
export const verifyCeremony = async (
Expand All @@ -152,7 +152,6 @@ export const verifyCeremony = async (
circuitInputsPath: string,
verifierTemplatePath: string,
signer: Signer,
coordinatorId: string,
logger?: any
): Promise<void> => {
// 1. download all ceremony artifacts
Expand All @@ -168,6 +167,19 @@ export const verifyCeremony = async (
throw new Error("The circuit inputs file does not exist. Please check the path and try again.")
const circuitsInputs = JSON.parse(fs.readFileSync(circuitInputsPath).toString())

// find the ceremony given the prefix
const ceremonyQuery = await queryCollection(firestore, commonTerms.collections.ceremonies.name, [
where(commonTerms.collections.ceremonies.fields.prefix, "==", ceremonyPrefix)
])

// get the ceremony data - no need to do an existence check as
// we already checked that the ceremony exists in downloafAllCeremonyArtifacts
const ceremonyData = fromQueryToFirebaseDocumentInfo(ceremonyQuery.docs)
const ceremony = ceremonyData.at(0)
// this is required to re-generate the final zKey
const {coordinatorId} = ceremony!.data
const ceremonyId = ceremony!.id

// we verify each circuit separately
for (const ceremonyArtifact of ceremonyArtifacts) {
// get the index of the circuit in the list of circuits
Expand All @@ -189,7 +201,7 @@ export const verifyCeremony = async (
// 3. get the final contribution beacon
const contributionBeacon = await getFinalContributionBeacon(
firestore,
ceremonyArtifact.ceremonyId,
ceremonyId,
ceremonyArtifact.circuitId,
coordinatorId
)
Expand Down
67 changes: 44 additions & 23 deletions packages/actions/src/helpers/tasks.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,57 @@
import { task } from "hardhat/config"
import { cwd } from "process"
import { verifyCeremony } from "./contracts"
import { initializeUserServices } from "../../test/utils"
import {
createMockUser,
deleteAdminApp,
generatePseudoRandomStringOfNumbers,
initializeAdminServices,
initializeUserServices
} from "../../test/utils"

task("verifyCeremony", "A task that can be used to verify a ceremony finalization validity")
.addPositionalParam("ceremonyPrefix")
.addPositionalParam("outputDirectory")
.addPositionalParam("solidityVersion")
.addPositionalParam("wasmPath")
.addPositionalParam("circuitInputs")
.addPositionalParam("verifierTemplatePath")
.addPositionalParam("coordinatorUID")
.addPositionalParam("circuitInputsPath")
.setAction(async (taskArgs, hre) => {
// get a signer
const [deployer] = await hre.ethers.getSigners()

// init user app
const { userFirestore, userFunctions } = initializeUserServices()
// init user and admin app
const { adminAuth, adminFirestore } = initializeAdminServices()
const { userApp, userFirestore, userFunctions } = initializeUserServices()

// verify ceremony
await verifyCeremony(
userFunctions,
userFirestore,
taskArgs.ceremonyPrefix,
taskArgs.outputDirectory,
taskArgs.solidityVersion,
taskArgs.wasmPath,
taskArgs.circuitInputs,
taskArgs.verifierTemplatePath,
deployer,
taskArgs.coordinatorUID
)
const outputDirectory = `${cwd()}/test/data/artifacts/verification/`
const verifierTemplatePath = `${cwd()}/../../node_modules/snarkjs/templates/verifier_groth16.sol.ejs`

// if we are here it is because it didn't throw so we can safely assume that it all was veriifer
console.log(`[+] The artifacts generated by the ceremony ${taskArgs.ceremonyPrefix} are valid`)
// create user
const coordinatorEmail = "coordinator@email.com"
const coordinatorPassword = generatePseudoRandomStringOfNumbers(20)
const coordinatorUID = await createMockUser(userApp, coordinatorEmail, coordinatorPassword, true, adminAuth)

try {
// verify ceremony
await verifyCeremony(
userFunctions,
userFirestore,
taskArgs.ceremonyPrefix,
outputDirectory,
taskArgs.wasmPath,
taskArgs.circuitInputs,
verifierTemplatePath,
deployer
)

// if we are here it is because it didn't throw so we can safely assume that it all was veriifer
console.log(`[+] The artifacts generated by the ceremony ${taskArgs.ceremonyPrefix} are valid\n`)
} catch (err: any) {
console.log(`[-] Could not verify the ceremony validity. ${err.toString()}\n`)
} finally {
// Clean ceremony and user from DB.
await adminFirestore.collection("users").doc(coordinatorUID).delete()
// Remove Auth user.
await adminAuth.deleteUser(coordinatorUID)
// Delete admin app.
await deleteAdminApp()
}
})
1 change: 0 additions & 1 deletion packages/actions/src/helpers/verification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,6 @@ export const downloadAllCeremonyArtifacts = async (
await downloadCeremonyArtifact(functions, bucketName, vKeyStoragePath, vKeyLocalPath)

ceremonyArtifacts.push({
ceremonyId: ceremony.id,
circuitPrefix: circuit.data.prefix,
circuitId: circuit.id,
directoryRoot: circuitDir,
Expand Down
2 changes: 0 additions & 2 deletions packages/actions/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,6 @@ export type ParticipantDocumentReferenceAndData = {
/**
* Define a ceremony artifacts with their local paths.
* @typedef {Object} CeremonyArtifacts
* @property {string} ceremonyId - the unique identifier of the ceremony.
* @property {string} circuitPrefix - the prefix of the circuit.
* @property {string} circuitId - the unique identifier of the circuit.
* @property {string} directoryRoot - the root directory of the ceremony.
Expand All @@ -496,7 +495,6 @@ export type ParticipantDocumentReferenceAndData = {
* @dev must be used for generating fake/mock documents when testing.
*/
export type CeremonyArtifacts = {
ceremonyId: string
circuitPrefix: string
circuitId: string
directoryRoot: string
Expand Down
9 changes: 5 additions & 4 deletions packages/actions/test/unit/contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ describe("Smart Contract", () => {
hash: computeSHA256ToHex(finalizationBeacon)
}
}

// update this here so it can be used to generate the final zKey
ceremony.data.coordinatorId = coordinatorIdentifier
await createMockCeremony(adminFirestore, ceremony, circuit)

await createMockParticipant(adminFirestore, ceremony.uid, users[0].uid, coordinatorParticipant)
Expand Down Expand Up @@ -272,8 +275,7 @@ describe("Smart Contract", () => {
wasmPath,
inputsPath,
verifierTemplatePath,
signer,
coordinatorIdentifier
signer
)
).to.be.fulfilled
})
Expand All @@ -287,8 +289,7 @@ describe("Smart Contract", () => {
wasmPath,
inputsPath,
verifierTemplatePath,
signer,
coordinatorIdentifier
signer
)
).to.be.rejected
})
Expand Down

0 comments on commit eeb6214

Please sign in to comment.