Skip to content

Commit

Permalink
feat: add wasm support at setup time
Browse files Browse the repository at this point in the history
  • Loading branch information
0xjei committed Mar 21, 2023
1 parent fb7cfd3 commit 53eeddd
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 7 deletions.
1 change: 1 addition & 0 deletions packages/actions/src/helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ export const commonTerms = {
finalize: `finalize`,
pot: `pot`,
zkeys: `zkeys`,
wasm: `wasm`,
vkeys: `vkeys`,
metadata: `metadata`,
transcripts: `transcripts`,
Expand Down
11 changes: 11 additions & 0 deletions packages/actions/src/helpers/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,17 @@ export const downloadCeremonyArtifact = async (
export const getR1csStorageFilePath = (circuitPrefix: string, completeR1csFilename: string): string =>
`${commonTerms.collections.circuits.name}/${circuitPrefix}/${completeR1csFilename}`

/**
* Get WASM file path tied to a particular circuit of a ceremony in the storage.
* @notice each WASM file in the storage must be stored in the following path: `circuits/<circuitPrefix>/<completeWasmFilename>`.
* nb. This is a rule that must be satisfied. This is NOT an optional convention.
* @param circuitPrefix <string> - the prefix of the circuit.
* @param completeWasmFilename <string> - the complete WASM filename (name + ext).
* @returns <string> - the storage path of the WASM file.
*/
export const getWasmStorageFilePath = (circuitPrefix: string, completeWasmFilename: string): string =>
`${commonTerms.collections.circuits.name}/${circuitPrefix}/${completeWasmFilename}`

/**
* Get PoT file path in the storage.
* @notice each PoT file in the storage must be stored in the following path: `pot/<completePotFilename>`.
Expand Down
3 changes: 2 additions & 1 deletion packages/actions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export {
getZkeyStorageFilePath,
getVerificationKeyStorageFilePath,
getVerifierContractStorageFilePath,
getTranscriptStorageFilePath
getTranscriptStorageFilePath,
getWasmStorageFilePath
} from "./helpers/storage"
export {
queryCollection,
Expand Down
19 changes: 19 additions & 0 deletions packages/actions/src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,25 @@ export type SourceTemplateData = {
paramsConfiguration: Array<string>
}

/**
* The references about the artifacts produced during the compilation of the ceremony circuit.
* @typedef {Object} CompilationArtifacts
* @property {string} r1csFilename - the name of the R1CS file.
* @property {string} wasmFilename - the name of the WASM file.
*/
export type CompilationArtifacts = {
r1csFilename: string
wasmFilename: string
}

/**
* Group input data for defining a ceremony circuit.
* @dev The data is both entered by the coordinator and derived.
* @typedef {Object} CircuitInputData
* @property {string} description - a short description for the circuit.
* @property {CircomCompilerData} compiler - the info about the Circom compiler used to compile the circuit template.
* @property {SourceTemplateData} template - the info about the circuit template.
* @property {CompilationArtifacts} compilationArtifacts - the references about the circuit compilation artifacts.
* @property {CircuitMetadata} [metadata] - the info about the R1CS file.
* @property {string} [name] - the name of the circuit.
* @property {number} [dynamicThreshold] - the dynamic timeout threshold expressed in percentage.
Expand All @@ -159,6 +171,7 @@ export type CircuitInputData = {
description: string
compiler: CircomCompilerData
template: SourceTemplateData
compilationArtifacts: CompilationArtifacts
metadata?: CircuitMetadata
name?: string
dynamicThreshold?: number
Expand Down Expand Up @@ -269,23 +282,29 @@ export type CircuitMetadata = {
* @typedef {Object} CircuitArtifacts
* @property {string} potFilename - the name of the Powers of Tau file.
* @property {string} r1csFilename - the name of the R1CS file.
* @property {string} wasmFilename - the name of the WASM file.
* @property {string} initialZkeyFilename - the name of the initial (= genesis) zKey file.
* @property {string} potStoragePath - the storage path of the Powers of Tau file.
* @property {string} r1csStoragePath - the storage path of the R1CS file.
* @property {string} wasmStoragePath - the storage path of the WASM file.
* @property {string} initialZkeyStoragePath - the storage path of the initial (= genesis) zKey file.
* @property {string} potBlake2bHash - the blake2b hash of the Powers of Tau file.
* @property {string} r1csBlake2bHash - the blake2b hash of the R1CS file.
* @property {string} wasmBlake2bHash - the blake2b hash of the WASM file.
* @property {string} initialZkeyBlake2bHash - the blake2b hash of the initial (= genesis) zKey file.
*/
export type CircuitArtifacts = {
potFilename: string
r1csFilename: string
wasmFilename: string
initialZkeyFilename: string
potStoragePath: string
r1csStoragePath: string
wasmStoragePath: string
initialZkeyStoragePath: string
potBlake2bHash: string
r1csBlake2bHash: string
wasmBlake2bHash: string
initialZkeyBlake2bHash: string
}

Expand Down
51 changes: 46 additions & 5 deletions packages/phase2cli/src/commands/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ import {
multiPartUpload,
checkIfObjectExist,
setupCeremony,
getR1CSInfo
getR1CSInfo,
commonTerms,
getWasmStorageFilePath
} from "@zkmpc/actions/src"
import { CeremonyTimeoutType } from "@zkmpc/actions/src/types/enums"
import {
Expand Down Expand Up @@ -63,6 +65,7 @@ import {
/**
* Handle whatever is needed to obtain the input data for a circuit that the coordinator would like to add to the ceremony.
* @param choosenCircuitFilename <string> - the name of the circuit to add.
* @param matchingWasmFilename <string> - the name of the circuit wasm file.
* @param ceremonyTimeoutMechanismType <CeremonyTimeoutType> - the type of ceremony timeout mechanism.
* @param sameCircomCompiler <boolean> - true, if this circuit shares with the others the <CircomCompilerData>; otherwise false.
* @param circuitSequencePosition <number> - the position of the circuit in the contribution queue.
Expand All @@ -71,6 +74,7 @@ import {
*/
const getInputDataToAddCircuitToCeremony = async (
choosenCircuitFilename: string,
matchingWasmFilename: string,
ceremonyTimeoutMechanismType: CeremonyTimeoutType,
sameCircomCompiler: boolean,
circuitSequencePosition: number,
Expand Down Expand Up @@ -111,6 +115,10 @@ const getInputDataToAddCircuitToCeremony = async (
? sharedCircomCompilerData.version
: circuitInputData.compiler.version
},
compilationArtifacts: {
r1csFilename: choosenCircuitFilename,
wasmFilename: matchingWasmFilename
},
name: circuitName,
prefix: circuitPrefix,
sequencePosition: circuitSequencePosition
Expand All @@ -124,7 +132,8 @@ const getInputDataToAddCircuitToCeremony = async (
* @returns <Promise<Array<CircuitInputData>>> - the input data for each circuit that has been added to the ceremony.
*/
const handleAdditionOfCircuitsToCeremony = async (
options: Array<string>,
r1csOptions: Array<string>,
wasmOptions: Array<string>,
ceremonyTimeoutMechanismType: CeremonyTimeoutType
): Promise<Array<CircuitInputData>> => {
// Prepare data.
Expand All @@ -151,14 +160,24 @@ const handleAdditionOfCircuitsToCeremony = async (
console.log(theme.text.bold(`\n- Circuit # ${theme.colors.magenta(`${circuitSequencePosition}`)}\n`))

// Select one circuit among cwd circuits identified by R1CS files.
const choosenCircuitFilename = await promptCircuitSelector(options)
const choosenCircuitFilename = await promptCircuitSelector(r1csOptions)

// Update list of possible options for next selection (if, any).
options = options.filter((circuitFilename: string) => circuitFilename !== choosenCircuitFilename)
r1csOptions = r1csOptions.filter((circuitFilename: string) => circuitFilename !== choosenCircuitFilename)

// Select the wasm file accordingly to circuit R1CS filename.
const matchingWasms = wasmOptions.filter(
(wasmFilename: string) =>
choosenCircuitFilename.split(`.r1cs`)[0] ===
wasmFilename.split(`.${commonTerms.foldersAndPathsTerms.wasm}`)[0]
)

if (matchingWasms.length !== 1) showError(COMMAND_ERRORS.COMMAND_SETUP_MISMATCH_R1CS_WASM, true)

// Get input data for choosen circuit.
const circuitInputData = await getInputDataToAddCircuitToCeremony(
choosenCircuitFilename,
matchingWasms[0],
ceremonyTimeoutMechanismType,
sameCircomCompiler,
circuitSequencePosition,
Expand All @@ -169,7 +188,7 @@ const handleAdditionOfCircuitsToCeremony = async (
inputDataForCircuits.push(circuitInputData)

// Check if any circuit is left for potentially addition to ceremony.
if (options.length !== 0) {
if (r1csOptions.length !== 0) {
// Prompt for selection.
const wannaAddNewCircuit = await promptCircuitAddition()

Expand Down Expand Up @@ -454,16 +473,21 @@ const setup = async () => {

// Look for R1CS files.
const r1csFilePaths = await filterDirectoryFilesByExtension(cwd, `.r1cs`)
// Look for WASM files.
const wasmFilePaths = await filterDirectoryFilesByExtension(cwd, `.wasm`)
// Look for pre-computed zKeys references (if any).
const localPreComputedZkeysFilenames = await filterDirectoryFilesByExtension(cwd, `.zkey`)

if (!r1csFilePaths.length) showError(COMMAND_ERRORS.COMMAND_SETUP_NO_R1CS, true)
if (!wasmFilePaths.length) showError(COMMAND_ERRORS.COMMAND_SETUP_NO_WASM, true)
if (wasmFilePaths.length !== r1csFilePaths.length) showError(COMMAND_ERRORS.COMMAND_SETUP_MISMATCH_R1CS_WASM, true)

// Prepare local directories.
checkAndMakeNewDirectoryIfNonexistent(localPaths.output)
cleanDir(localPaths.setup)
cleanDir(localPaths.pot)
cleanDir(localPaths.zkeys)
cleanDir(localPaths.wasm)

// Prompt the coordinator for gather ceremony input data.
const ceremonyInputData = await promptCeremonyInputData(firestoreDatabase)
Expand All @@ -472,6 +496,7 @@ const setup = async () => {
// Add circuits to ceremony.
const circuitsInputData: Array<CircuitInputData> = await handleAdditionOfCircuitsToCeremony(
r1csFilePaths.map((dirent: Dirent) => dirent.name),
wasmFilePaths.map((dirent: Dirent) => dirent.name),
ceremonyInputData.timeoutMechanismType
)

Expand Down Expand Up @@ -509,16 +534,19 @@ const setup = async () => {

// Rename R1Cs and zKey based on circuit name and prefix.
const r1csCompleteFilename = `${circuit.name}.r1cs`
const wasmCompleteFilename = `${circuit.name}.wasm`
const firstZkeyCompleteFilename = `${circuit.prefix}_${genesisZkeyIndex}.zkey`
let preComputedZkeyCompleteFilename = ``

// Local paths.
const r1csLocalPathAndFileName = getCWDFilePath(cwd, r1csCompleteFilename)
const wasmLocalPathAndFileName = getCWDFilePath(cwd, wasmCompleteFilename)
let potLocalPathAndFileName = getPotLocalFilePath(smallestPowersOfTauCompleteFilenameForCircuit)
let zkeyLocalPathAndFileName = getZkeyLocalFilePath(firstZkeyCompleteFilename)

// Storage paths.
const r1csStorageFilePath = getR1csStorageFilePath(circuit.prefix!, r1csCompleteFilename)
const wasmStorageFilePath = getWasmStorageFilePath(circuit.prefix!, wasmCompleteFilename)
let potStorageFilePath = getPotStorageFilePath(smallestPowersOfTauCompleteFilenameForCircuit)
const zkeyStorageFilePath = getZkeyStorageFilePath(circuit.prefix!, firstZkeyCompleteFilename)

Expand Down Expand Up @@ -633,13 +661,23 @@ const setup = async () => {
r1csCompleteFilename
)

// Upload WASM to Storage.
await handleCircuitArtifactUploadToStorage(
firebaseFunctions,
bucketName,
wasmStorageFilePath,
wasmLocalPathAndFileName,
wasmCompleteFilename
)

process.stdout.write(`\n`)

const spinner = customSpinner(`Preparing the ceremony data (this may take a while)...`, `clock`)
spinner.start()

// Computing file hash (this may take a while).
const r1csBlake2bHash = await blake512FromPath(r1csLocalPathAndFileName)
const wasmBlake2bHash = await blake512FromPath(wasmLocalPathAndFileName)
const potBlake2bHash = await blake512FromPath(potLocalPathAndFileName)
const initialZkeyBlake2bHash = await blake512FromPath(zkeyLocalPathAndFileName)

Expand All @@ -648,12 +686,15 @@ const setup = async () => {
// Prepare circuit data for writing to the DB.
const circuitFiles: CircuitArtifacts = {
r1csFilename: r1csCompleteFilename,
wasmFilename: wasmCompleteFilename,
potFilename: smallestPowersOfTauCompleteFilenameForCircuit,
initialZkeyFilename: firstZkeyCompleteFilename,
r1csStoragePath: r1csStorageFilePath,
wasmStoragePath: wasmStorageFilePath,
potStoragePath: potStorageFilePath,
initialZkeyStoragePath: zkeyStorageFilePath,
r1csBlake2bHash,
wasmBlake2bHash,
potBlake2bHash,
initialZkeyBlake2bHash
}
Expand Down
4 changes: 3 additions & 1 deletion packages/phase2cli/src/lib/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ export const COMMAND_ERRORS = {
COMMAND_NOT_COORDINATOR: `Unable to execute the command. In order to perform coordinator functionality you must authenticate with an account having adeguate permissions.`,
COMMAND_ABORT_PROMPT: `The data submission process was suddenly interrupted. Your previous data has not been saved. We are sorry, you will have to repeat the process again from the beginning.`,
COMMAND_ABORT_SELECTION: `The data selection process was suddenly interrupted. Your previous data has not been saved. We are sorry, you will have to repeat the process again from the beginning.`,
COMMAND_SETUP_NO_R1CS: `Unable to retrieve R1CS files from current working directory. Please, run this command from a working directory where the R1CS files are located to continue with the setup process. We kindly ask you to run the command from an empty directory containing only the R1CS files.`,
COMMAND_SETUP_NO_R1CS: `Unable to retrieve R1CS files from current working directory. Please, run this command from a working directory where the R1CS files are located to continue with the setup process. We kindly ask you to run the command from an empty directory containing only the R1CS and WASM files.`,
COMMAND_SETUP_NO_WASM: `Unable to retrieve WASM files from current working directory. Please, run this command from a working directory where the WASM files are located to continue with the setup process. We kindly ask you to run the command from an empty directory containing only the WASM and R1CS files.`,
COMMAND_SETUP_MISMATCH_R1CS_WASM: `The folder contains more R1CS files than WASM files (or vice versa). Please, run this command from a working directory where each R1CS is paired with its corresponding file WASM.`,
COMMAND_SETUP_DOWNLOAD_PTAU: `Unable to download Powers of Tau file from Hermez Cryptography Phase 1 Trusted Setup. Possible causes may involve an error while making the request (be sure to have a stable internet connection). Please, we kindly ask you to terminate the current session and repeat the process.`,
COMMAND_SETUP_ABORT: `You chose to abort the setup process.`,
COMMAND_CONTRIBUTE_NO_OPENED_CEREMONIES: `Unfortunately, there is no ceremony for which you can make a contribution at this time. Please, try again later.`,
Expand Down
2 changes: 2 additions & 0 deletions packages/phase2cli/src/lib/localConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const contributeLocalFolderPath = `${outputLocalFolderPath}/${commonTerms.folder
const finalizeLocalFolderPath = `${outputLocalFolderPath}/${commonTerms.foldersAndPathsTerms.finalize}`
const potLocalFolderPath = `${setupLocalFolderPath}/${commonTerms.foldersAndPathsTerms.pot}`
const zkeysLocalFolderPath = `${setupLocalFolderPath}/${commonTerms.foldersAndPathsTerms.zkeys}`
const wasmLocalFolderPath = `${setupLocalFolderPath}/${commonTerms.foldersAndPathsTerms.wasm}`
const contributionsLocalFolderPath = `${contributeLocalFolderPath}/${commonTerms.foldersAndPathsTerms.zkeys}`
const contributionTranscriptsLocalFolderPath = `${contributeLocalFolderPath}/${commonTerms.foldersAndPathsTerms.transcripts}`
const attestationLocalFolderPath = `${contributeLocalFolderPath}/${commonTerms.foldersAndPathsTerms.attestation}`
Expand All @@ -47,6 +48,7 @@ export const localPaths = {
finalize: finalizeLocalFolderPath,
pot: potLocalFolderPath,
zkeys: zkeysLocalFolderPath,
wasm: wasmLocalFolderPath,
contributions: contributionsLocalFolderPath,
transcripts: contributionTranscriptsLocalFolderPath,
attestations: attestationLocalFolderPath,
Expand Down

0 comments on commit 53eeddd

Please sign in to comment.