diff --git a/packages/actions/src/helpers/utils.ts b/packages/actions/src/helpers/utils.ts index d11e2466..c62d936d 100644 --- a/packages/actions/src/helpers/utils.ts +++ b/packages/actions/src/helpers/utils.ts @@ -36,7 +36,7 @@ import { */ export const parseCeremonyFile = (path: string): SetupCeremonyData => { // check that the path exists - if (!fs.existsSync(path)) throw new Error("Error while setting up the ceremony. The provided path to the configuration file does not exist. Please provide an absolute path and try again.") + if (!fs.existsSync(path)) throw new Error("The provided path to the configuration file does not exist. Please provide an absolute path and try again.") try { // read the data @@ -44,11 +44,11 @@ export const parseCeremonyFile = (path: string): SetupCeremonyData => { // verify that the data is correct if (data['timeoutMechanismType'] !== CeremonyTimeoutType.DYNAMIC && data['timeoutMechanismType'] !== CeremonyTimeoutType.FIXED) - throw new Error("Invalid timeout type. Please choose between") + throw new Error("Invalid timeout type. Please choose between DYNAMIC and FIXED.") // validate that we have at least 1 circuit input data if (!data.circuits || data.circuits.length === 0) - throw new Error("Error while setting up the ceremony. You need to provide the data for at least 1 circuit.") + throw new Error("You need to provide the data for at least 1 circuit.") // validate that the end date is in the future let endDate: Date @@ -57,18 +57,18 @@ export const parseCeremonyFile = (path: string): SetupCeremonyData => { endDate = new Date(data.endDate) startDate = new Date(data.startDate) } catch (error: any) { - throw new Error("Error while setting up the ceremony. The dates should follow this format: 2023-07-04T00:00:00.") + throw new Error("The dates should follow this format: 2023-07-04T00:00:00.") } - if (endDate <= startDate) throw new Error("Error while setting up the ceremony. The end date should be greater than the start date.") + if (endDate <= startDate) throw new Error("The end date should be greater than the start date.") const currentDate = new Date() if (endDate <= currentDate || startDate <= currentDate) - throw new Error("Error while setting up the ceremony. The start and end dates should be in the future.") + throw new Error("The start and end dates should be in the future.") // validate penalty - if (data.penalty <= 0) throw new Error("Error while setting up the ceremony. The penalty should be greater than zero.") + if (data.penalty <= 0) throw new Error("The penalty should be greater than zero.") const circuits: CircuitDocument[] = [] const urlPattern = /(https?:\/\/[^\s]+)/g @@ -86,8 +86,8 @@ export const parseCeremonyFile = (path: string): SetupCeremonyData => { const wasmPath = artifacts.wasmLocalFilePath // ensure that the artifact exist locally - if (!fs.existsSync(r1csPath)) throw new Error("Error while setting up the ceremony. The path to the r1cs file does not exist. Please ensure this is correct and that an absolute path is provided.") - if (!fs.existsSync(wasmPath)) throw new Error("Error while setting up the ceremony. The path to the wasm file does not exist. Please ensure this is correct and that an absolute path is provided.") + if (!fs.existsSync(r1csPath)) throw new Error("The path to the r1cs file does not exist. Please ensure this is correct and that an absolute path is provided.") + if (!fs.existsSync(wasmPath)) throw new Error("The path to the wasm file does not exist. Please ensure this is correct and that an absolute path is provided.") // extract the metadata from the r1cs const metadata = getR1CSInfo(r1csPath) @@ -96,10 +96,10 @@ export const parseCeremonyFile = (path: string): SetupCeremonyData => { const template = circuitData.template const URLMatch = template.source.match(urlPattern) - if (!URLMatch || URLMatch.length === 0 || URLMatch.length > 1) throw new Error("Error while setting up the ceremony. You should provide the URL to the circuits templates on GitHub.") + if (!URLMatch || URLMatch.length === 0 || URLMatch.length > 1) throw new Error("You should provide the URL to the circuits templates on GitHub.") const hashMatch = template.commitHash.match(commitHashPattern) - if (!hashMatch || hashMatch.length === 0 || hashMatch.length > 1) throw new Error("Error while setting up the ceremony. You should provide a valid commit hash of the circuit templates.") + if (!hashMatch || hashMatch.length === 0 || hashMatch.length > 1) throw new Error("You should provide a valid commit hash of the circuit templates.") const circuitPrefix = extractPrefix(circuitData.name) @@ -130,12 +130,12 @@ export const parseCeremonyFile = (path: string): SetupCeremonyData => { // validate that the compiler hash is a valid hash const compiler = circuitData.compiler const compilerHashMatch = compiler.commitHash.match(commitHashPattern) - if (!compilerHashMatch || compilerHashMatch.length === 0 || compilerHashMatch.length > 1) throw new Error("Error while setting up the ceremony. You should provide a valid commit hash of the circuit compiler.") + if (!compilerHashMatch || compilerHashMatch.length === 0 || compilerHashMatch.length > 1) throw new Error("You should provide a valid commit hash of the circuit compiler.") // validate that the verification options are valid const verification = circuitData.verification if (verification.cfOrVm !== "CF" && verification.cfOrVm !== "VM") - throw new Error("Error while setting up the ceremony. Please enter a valid verification mechanism: either CF or VM") + throw new Error("Please enter a valid verification mechanism: either CF or VM") // @todo VM parameters verification // if (verification['cfOrVM'] === "VM") {} @@ -145,13 +145,13 @@ export const parseCeremonyFile = (path: string): SetupCeremonyData => { let fixedTimeWindow: number | undefined if (data.timeoutMechanismType === CeremonyTimeoutType.DYNAMIC) { if (circuitData.dynamicThreshold <= 0) - throw new Error("Error while setting up the ceremony. The dynamic threshold should be > 0.") + throw new Error("The dynamic threshold should be > 0.") dynamicThreshold = circuitData.dynamicThreshold } if (data.timeoutMechanismType === CeremonyTimeoutType.FIXED) { if (circuitData.fixedTimeWindow <= 0) - throw new Error("Error while setting up the ceremony. The fixed time window threshold should be > 0.") + throw new Error("The fixed time window threshold should be > 0.") fixedTimeWindow = circuitData.fixedTimeWindow } @@ -196,7 +196,7 @@ export const parseCeremonyFile = (path: string): SetupCeremonyData => { return setupData } catch (error: any) { - throw new Error(`Error while setting up the ceremony. ${error.message}`) + throw new Error(`Error while parsing up the ceremony setup file. ${error.message}`) } } diff --git a/packages/phase2cli/package.json b/packages/phase2cli/package.json index bdfbfd14..d66ff4b4 100644 --- a/packages/phase2cli/package.json +++ b/packages/phase2cli/package.json @@ -37,6 +37,7 @@ "contribute": "yarn start contribute", "clean": "yarn start clean", "logout": "yarn start logout", + "validate": "yarn start validate", "coordinate:setup": "yarn start coordinate setup", "coordinate:observe": "yarn start coordinate observe", "coordinate:finalize": "yarn start coordinate finalize", diff --git a/packages/phase2cli/src/commands/index.ts b/packages/phase2cli/src/commands/index.ts index 7adfdb46..56a679f2 100644 --- a/packages/phase2cli/src/commands/index.ts +++ b/packages/phase2cli/src/commands/index.ts @@ -5,3 +5,4 @@ export { default as observe } from "./observe.js" export { default as finalize } from "./finalize.js" export { default as clean } from "./clean.js" export { default as logout } from "./logout.js" +export { default as validate } from "./validate.js" \ No newline at end of file diff --git a/packages/phase2cli/src/commands/validate.ts b/packages/phase2cli/src/commands/validate.ts new file mode 100644 index 00000000..73e0992c --- /dev/null +++ b/packages/phase2cli/src/commands/validate.ts @@ -0,0 +1,29 @@ +import { parseCeremonyFile } from "@p0tion/actions" +import { showError } from "../lib/errors.js" + +/** + * Validate ceremony setup command. + */ +const validate = async (cmd: { template: string, constraints?: number }) => { + try { + // parse the file + const parsedFile = parseCeremonyFile(cmd.template) + // check whether we have a constraints option otherwise default to 1M + const constraints = cmd.constraints || 1000000 + for (const circuit of parsedFile.circuits) { + if (circuit.metadata.constraints > constraints) { + console.log(false) + process.exit(0) + } + } + + console.log(true) + + } catch (err: any) { + showError(`${err.toString()}`, false) + // we want to exit with a non-zero exit code + process.exit(1) + } +} + +export default validate diff --git a/packages/phase2cli/src/index.ts b/packages/phase2cli/src/index.ts index d55a78d7..aca8ed99 100755 --- a/packages/phase2cli/src/index.ts +++ b/packages/phase2cli/src/index.ts @@ -4,7 +4,7 @@ import { createCommand } from "commander" import { readFileSync } from "fs" import { dirname } from "path" import { fileURLToPath } from "url" -import { setup, auth, contribute, observe, finalize, clean, logout } from "./commands/index.js" +import { setup, auth, contribute, observe, finalize, clean, logout, validate } from "./commands/index.js" // Get pkg info (e.g., name, version). const packagePath = `${dirname(fileURLToPath(import.meta.url))}/..` @@ -30,6 +30,12 @@ program .command("logout") .description("sign out from Firebae Auth service and delete Github OAuth 2.0 token from local storage") .action(logout) +program + .command("validate") + .description("Validate that a Ceremony Setup file is correct") + .requiredOption("-t, --template ", "The path to the ceremony setup template", "") + .option("-c, --constraints ", "The number of constraints to check against") + .action(validate) // Only coordinator commands. const ceremony = program.command("coordinate").description("commands for coordinating a ceremony")