Skip to content

Commit

Permalink
feat(setup): add a cli command to validate the ceremony setup file an…
Browse files Browse the repository at this point in the history
…d the constraints
  • Loading branch information
ctrlc03 committed Jul 11, 2023
1 parent 7e007e2 commit 66f8837
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 17 deletions.
32 changes: 16 additions & 16 deletions packages/actions/src/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ 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
const data: CeremonySetupTemplate = JSON.parse(fs.readFileSync(path).toString())

// 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
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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)

Expand Down Expand Up @@ -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") {}
Expand All @@ -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
}

Expand Down Expand Up @@ -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}`)
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/phase2cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions packages/phase2cli/src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
29 changes: 29 additions & 0 deletions packages/phase2cli/src/commands/validate.ts
Original file line number Diff line number Diff line change
@@ -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
8 changes: 7 additions & 1 deletion packages/phase2cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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))}/..`
Expand All @@ -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 <path>", "The path to the ceremony setup template", "")
.option("-c, --constraints <number>", "The number of constraints to check against")
.action(validate)

// Only coordinator commands.
const ceremony = program.command("coordinate").description("commands for coordinating a ceremony")
Expand Down

0 comments on commit 66f8837

Please sign in to comment.