@devtion/devcli 0.0.0-3c7b092 → 0.0.0-3df1645

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  /**
4
- * @module @devtion/devcli
5
- * @version 1.0.8
4
+ * @module @p0tion/phase2cli
5
+ * @version 1.0.9
6
6
  * @file All-in-one interactive command-line for interfacing with zkSNARK Phase 2 Trusted Setup ceremonies
7
7
  * @copyright Ethereum Foundation 2022
8
8
  * @license MIT
@@ -585,8 +585,18 @@ const publishGist = async (token, content, ceremonyTitle, ceremonyPrefix) => {
585
585
  * @returns <string> - the ready to share tweet url.
586
586
  */
587
587
  const generateCustomUrlToTweetAboutParticipation = (ceremonyName, gistUrl, isFinalizing) => isFinalizing
588
- ? `https://twitter.com/intent/tweet?text=I%20have%20finalized%20the%20${ceremonyName}${ceremonyName.toLowerCase().includes("trusted") || ceremonyName.toLowerCase().includes("setup") || ceremonyName.toLowerCase().includes("phase2") || ceremonyName.toLowerCase().includes("ceremony") ? "!" : "%20Phase%202%20Trusted%20Setup%20ceremony!"}%20You%20can%20view%20my%20final%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP%20#PSE`
589
- : `https://twitter.com/intent/tweet?text=I%20contributed%20to%20the%20${ceremonyName}${ceremonyName.toLowerCase().includes("trusted") || ceremonyName.toLowerCase().includes("setup") || ceremonyName.toLowerCase().includes("phase2") || ceremonyName.toLowerCase().includes("ceremony") ? "!" : "%20Phase%202%20Trusted%20Setup%20ceremony!"}%20You%20can%20view%20the%20steps%20to%20contribute%20here:%20https://ceremony.pse.dev%20You%20can%20view%20my%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP`;
588
+ ? `https://twitter.com/intent/tweet?text=I%20have%20finalized%20the%20${ceremonyName}${ceremonyName.toLowerCase().includes("trusted") ||
589
+ ceremonyName.toLowerCase().includes("setup") ||
590
+ ceremonyName.toLowerCase().includes("phase2") ||
591
+ ceremonyName.toLowerCase().includes("ceremony")
592
+ ? "!"
593
+ : "%20Phase%202%20Trusted%20Setup%20ceremony!"}%20You%20can%20view%20my%20final%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP%20#PSE`
594
+ : `https://twitter.com/intent/tweet?text=I%20contributed%20to%20the%20${ceremonyName}${ceremonyName.toLowerCase().includes("trusted") ||
595
+ ceremonyName.toLowerCase().includes("setup") ||
596
+ ceremonyName.toLowerCase().includes("phase2") ||
597
+ ceremonyName.toLowerCase().includes("ceremony")
598
+ ? "!"
599
+ : "%20Phase%202%20Trusted%20Setup%20ceremony!"}%20You%20can%20view%20the%20steps%20to%20contribute%20here:%20https://ceremony.pse.dev%20You%20can%20view%20my%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP`;
590
600
  /**
591
601
  * Return a custom progress bar.
592
602
  * @param type <ProgressBarType> - the type of the progress bar.
@@ -767,6 +777,7 @@ const handleStartOrResumeContribution = async (cloudFunctions, firestoreDatabase
767
777
  // Download the latest contribution from bucket.
768
778
  await downloadCeremonyArtifact(cloudFunctions, bucketName, lastZkeyStorageFilePath, lastZkeyLocalFilePath);
769
779
  console.log(`${theme.symbols.success} Contribution ${theme.text.bold(`#${lastZkeyIndex}`)} correctly downloaded`);
780
+ await sleep(3000);
770
781
  // Advance to next contribution step (COMPUTING) if not finalizing.
771
782
  if (!isFinalizing) {
772
783
  spinner.text = `Preparing for contribution computation...`;
@@ -794,11 +805,14 @@ const handleStartOrResumeContribution = async (cloudFunctions, firestoreDatabase
794
805
  showError(COMMAND_ERRORS.COMMAND_CONTRIBUTE_FINALIZE_NO_TRANSCRIPT_CONTRIBUTION_HASH_MATCH, true);
795
806
  // Format contribution hash.
796
807
  const contributionHash = matchContributionHash?.at(0)?.replace("\n\t\t", "");
808
+ await sleep(500);
797
809
  // Make request to cloud functions to permanently store the information.
798
810
  await permanentlyStoreCurrentContributionTimeAndHash(cloudFunctions, ceremony.id, computingTime, contributionHash);
799
811
  // Format computing time.
800
812
  const { seconds: computationSeconds, minutes: computationMinutes, hours: computationHours } = getSecondsMinutesHoursFromMillis(computingTime);
801
813
  spinner.succeed(`${isFinalizing ? "Contribution" : `Contribution ${theme.text.bold(`#${nextZkeyIndex}`)}`} computation took ${theme.text.bold(`${convertToDoubleDigits(computationHours)}:${convertToDoubleDigits(computationMinutes)}:${convertToDoubleDigits(computationSeconds)}`)}`);
814
+ // ensure the previous step is completed
815
+ await sleep(5000);
802
816
  // Advance to next contribution step (UPLOADING) if not finalizing.
803
817
  if (!isFinalizing) {
804
818
  spinner.text = `Preparing for uploading the contribution...`;
@@ -816,10 +830,15 @@ const handleStartOrResumeContribution = async (cloudFunctions, firestoreDatabase
816
830
  if (isFinalizing || participantData.contributionStep === "UPLOADING" /* ParticipantContributionStep.UPLOADING */) {
817
831
  spinner.text = `Uploading ${isFinalizing ? "final" : "your"} contribution ${!isFinalizing ? theme.text.bold(`#${nextZkeyIndex}`) : ""} to storage.\n${theme.symbols.warning} This step may take a while based on circuit size and your internet speed. Everything's fine, just be patient.`;
818
832
  spinner.start();
819
- if (!isFinalizing)
820
- await multiPartUpload(cloudFunctions, bucketName, nextZkeyStorageFilePath, nextZkeyLocalFilePath, Number(process.env.CONFIG_STREAM_CHUNK_SIZE_IN_MB), ceremony.id, participantData.tempContributionData);
833
+ const progressBar = customProgressBar(ProgressBarType.UPLOAD, `your contribution`);
834
+ if (!isFinalizing) {
835
+ await multiPartUpload(cloudFunctions, bucketName, nextZkeyStorageFilePath, nextZkeyLocalFilePath, Number(process.env.CONFIG_STREAM_CHUNK_SIZE_IN_MB), ceremony.id, participantData.tempContributionData, progressBar);
836
+ progressBar.stop();
837
+ }
821
838
  else
822
839
  await multiPartUpload(cloudFunctions, bucketName, nextZkeyStorageFilePath, nextZkeyLocalFilePath, Number(process.env.CONFIG_STREAM_CHUNK_SIZE_IN_MB));
840
+ // small sleep to ensure the previous step is completed
841
+ await sleep(5000);
823
842
  spinner.succeed(`${isFinalizing ? `Contribution` : `Contribution ${theme.text.bold(`#${nextZkeyIndex}`)}`} correctly saved to storage`);
824
843
  // Advance to next contribution step (VERIFYING) if not finalizing.
825
844
  if (!isFinalizing) {
@@ -1125,7 +1144,7 @@ const promptCircuitInputData = async (constraintSize, timeoutMechanismType, same
1125
1144
  let circomVersion = "";
1126
1145
  let circomCommitHash = "";
1127
1146
  let circuitInputData;
1128
- let useCfOrVm;
1147
+ let cfOrVm;
1129
1148
  let vmDiskType;
1130
1149
  let vmConfigurationType = "";
1131
1150
  const questions = [
@@ -1185,13 +1204,16 @@ const promptCircuitInputData = async (constraintSize, timeoutMechanismType, same
1185
1204
  const { confirmation } = await askForConfirmation(`The contribution verification can be performed using Cloud Functions (CF, cheaper for small contributions but limited to 1M constraints) or custom virtual machines (expensive but could scale up to 30M constraints). Be aware about VM costs and if you wanna learn more, please visit the documentation to have a complete overview about cost estimation of the two mechanisms.\nChoose the contribution verification mechanism`, `CF`, // eq. true.
1186
1205
  `VM` // eq. false.
1187
1206
  );
1188
- useCfOrVm = confirmation;
1207
+ cfOrVm = confirmation
1208
+ ? "CF" /* CircuitContributionVerificationMechanism.CF */
1209
+ : "VM" /* CircuitContributionVerificationMechanism.VM */;
1189
1210
  }
1190
- else
1191
- useCfOrVm = "VM" /* CircuitContributionVerificationMechanism.VM */;
1192
- if (useCfOrVm === undefined)
1211
+ else {
1212
+ cfOrVm = "VM" /* CircuitContributionVerificationMechanism.VM */;
1213
+ }
1214
+ if (cfOrVm === undefined)
1193
1215
  showError(COMMAND_ERRORS.COMMAND_ABORT_PROMPT, true);
1194
- if (!useCfOrVm) {
1216
+ if (cfOrVm === "VM" /* CircuitContributionVerificationMechanism.VM */) {
1195
1217
  // Ask for selecting the specific VM configuration type.
1196
1218
  vmConfigurationType = await promptVMTypeSelector(constraintSize);
1197
1219
  // Ask for selecting the specific VM disk (volume) type.
@@ -1225,9 +1247,7 @@ const promptCircuitInputData = async (constraintSize, timeoutMechanismType, same
1225
1247
  paramsConfiguration: circuitConfigurationValues
1226
1248
  },
1227
1249
  verification: {
1228
- cfOrVm: useCfOrVm
1229
- ? "CF" /* CircuitContributionVerificationMechanism.CF */
1230
- : "VM" /* CircuitContributionVerificationMechanism.VM */,
1250
+ cfOrVm,
1231
1251
  vm: {
1232
1252
  vmConfigurationType,
1233
1253
  vmDiskType
@@ -1263,9 +1283,7 @@ const promptCircuitInputData = async (constraintSize, timeoutMechanismType, same
1263
1283
  paramsConfiguration: circuitConfigurationValues
1264
1284
  },
1265
1285
  verification: {
1266
- cfOrVm: useCfOrVm
1267
- ? "CF" /* CircuitContributionVerificationMechanism.CF */
1268
- : "VM" /* CircuitContributionVerificationMechanism.VM */,
1286
+ cfOrVm,
1269
1287
  vm: {
1270
1288
  vmConfigurationType,
1271
1289
  vmDiskType
@@ -1831,7 +1849,9 @@ const setup = async (cmd) => {
1831
1849
  let ceremonyId = ""; // The unique identifier of the ceremony.
1832
1850
  const { firebaseApp, firebaseFunctions, firestoreDatabase } = await bootstrapCommandExecutionAndServices();
1833
1851
  // Check for authentication.
1834
- const { user, providerUserId } = cmd.auth ? await authWithToken(firebaseApp, cmd.auth) : await checkAuth(firebaseApp);
1852
+ const { user, providerUserId } = cmd.auth
1853
+ ? await authWithToken(firebaseApp, cmd.auth)
1854
+ : await checkAuth(firebaseApp);
1835
1855
  // Preserve command execution only for coordinators.
1836
1856
  if (!(await isCoordinator(user)))
1837
1857
  showError(COMMAND_ERRORS.COMMAND_NOT_COORDINATOR, true);
@@ -1848,7 +1868,7 @@ const setup = async (cmd) => {
1848
1868
  // if there is the file option, then set up the non interactively
1849
1869
  if (cmd.template) {
1850
1870
  // 1. parse the file
1851
- // tmp data - do not cleanup files as we need them
1871
+ // tmp data - do not cleanup files as we need them
1852
1872
  const spinner = customSpinner(`Parsing ${theme.text.bold(cmd.template)} setup configuration file...`, `clock`);
1853
1873
  spinner.start();
1854
1874
  const setupCeremonyData = await parseCeremonyFile(cmd.template);
@@ -2104,17 +2124,29 @@ const expirationCountdownForGithubOAuth = (expirationInSeconds) => {
2104
2124
  */
2105
2125
  const onVerification = async (verification) => {
2106
2126
  // Copy code to clipboard.
2107
- clipboard.writeSync(verification.user_code);
2108
- clipboard.readSync();
2127
+ let noClipboard = false;
2128
+ try {
2129
+ clipboard.writeSync(verification.user_code);
2130
+ clipboard.readSync();
2131
+ }
2132
+ catch (error) {
2133
+ noClipboard = true;
2134
+ }
2109
2135
  // Display data.
2110
2136
  console.log(`${theme.symbols.warning} Visit ${theme.text.bold(theme.text.underlined(verification.verification_uri))} on this device to generate a new token and authenticate\n`);
2111
- console.log(theme.colors.magenta(figlet.textSync("Code is Below", { font: "ANSI Shadow" })), '\n');
2112
- console.log(`${theme.symbols.info} Your auth code: ${theme.text.bold(verification.user_code)} has been copied to your clipboard (${theme.emojis.clipboard} ${theme.symbols.success})\n`);
2137
+ console.log(theme.colors.magenta(figlet.textSync("Code is Below", { font: "ANSI Shadow" })), "\n");
2138
+ const message = !noClipboard ? `has been copied to your clipboard (${theme.emojis.clipboard})` : ``;
2139
+ console.log(`${theme.symbols.info} Your auth code: ${theme.text.bold(verification.user_code)} ${message} ${theme.symbols.success})\n`);
2113
2140
  const spinner = customSpinner(`Redirecting to Github...`, `clock`);
2114
2141
  spinner.start();
2115
2142
  await sleep(10000); // ~10s to make users able to read the CLI.
2116
- // Automatically open the page (# Step 2).
2117
- await open(verification.verification_uri);
2143
+ try {
2144
+ // Automatically open the page (# Step 2).
2145
+ await open(verification.verification_uri);
2146
+ }
2147
+ catch (error) {
2148
+ console.log(`${theme.symbols.info} Please authenticate via GitHub at ${verification.verification_uri}`);
2149
+ }
2118
2150
  spinner.stop();
2119
2151
  // Countdown for time expiration.
2120
2152
  expirationCountdownForGithubOAuth(verification.expires_in);
@@ -2610,7 +2642,9 @@ const listenToParticipantDocumentChanges = async (firestoreDatabase, cloudFuncti
2610
2642
  // Get latest contribution verification result.
2611
2643
  await getLatestVerificationResult(firestoreDatabase, ceremony.id, circuit.id, participant.id);
2612
2644
  // Get next circuit for contribution.
2613
- const nextCircuit = timeoutExpired ? getCircuitBySequencePosition(circuits, changedContributionProgress) : getCircuitBySequencePosition(circuits, changedContributionProgress + 1);
2645
+ const nextCircuit = timeoutExpired
2646
+ ? getCircuitBySequencePosition(circuits, changedContributionProgress)
2647
+ : getCircuitBySequencePosition(circuits, changedContributionProgress + 1);
2614
2648
  // Check disk space requirements for participant.
2615
2649
  const wannaGenerateAttestation = await handleDiskSpaceRequirementForNextContribution(cloudFunctions, ceremony.id, nextCircuit.data.sequencePosition, nextCircuit.data.zKeySizeInBytes, timeoutExpired, providerUserId);
2616
2650
  // Check if the participant would like to generate a new attestation.
@@ -3171,10 +3205,7 @@ program
3171
3205
  .command("clean")
3172
3206
  .description("clean up output generated by commands from the current working directory")
3173
3207
  .action(clean);
3174
- program
3175
- .command("list")
3176
- .description("List all ceremonies prefixes")
3177
- .action(listCeremonies);
3208
+ program.command("list").description("List all ceremonies prefixes").action(listCeremonies);
3178
3209
  program
3179
3210
  .command("logout")
3180
3211
  .description("sign out from Firebae Auth service and delete Github OAuth 2.0 token from local storage")
@@ -3190,8 +3221,8 @@ const ceremony = program.command("coordinate").description("commands for coordin
3190
3221
  ceremony
3191
3222
  .command("setup")
3192
3223
  .description("setup a Groth16 Phase 2 Trusted Setup ceremony for zk-SNARK circuits")
3193
- .option('-t, --template <path>', 'The path to the ceremony setup template', '')
3194
- .option('-a, --auth <string>', 'The Github OAuth 2.0 token', '')
3224
+ .option("-t, --template <path>", "The path to the ceremony setup template", "")
3225
+ .option("-a, --auth <string>", "The Github OAuth 2.0 token", "")
3195
3226
  .action(setup);
3196
3227
  ceremony
3197
3228
  .command("observe")
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@devtion/devcli",
3
3
  "type": "module",
4
- "version": "0.0.0-3c7b092",
4
+ "version": "0.0.0-3df1645",
5
5
  "description": "All-in-one interactive command-line for interfacing with zkSNARK Phase 2 Trusted Setup ceremonies",
6
6
  "repository": "git@github.com:privacy-scaling-explorations/p0tion.git",
7
7
  "homepage": "https://github.com/privacy-scaling-explorations/p0tion",
@@ -97,5 +97,5 @@
97
97
  "publishConfig": {
98
98
  "access": "public"
99
99
  },
100
- "gitHead": "04a0a07eddaf6db530ae3ff3c4c61f8a12b98f91"
100
+ "gitHead": "6f9aa8c0097076db64ca825e5714f4e149012f03"
101
101
  }
@@ -63,8 +63,14 @@ export const expirationCountdownForGithubOAuth = (expirationInSeconds: number) =
63
63
  */
64
64
  export const onVerification = async (verification: Verification): Promise<void> => {
65
65
  // Copy code to clipboard.
66
- clipboard.writeSync(verification.user_code)
67
- clipboard.readSync()
66
+ let noClipboard = false
67
+ try {
68
+ clipboard.writeSync(verification.user_code)
69
+ clipboard.readSync()
70
+ } catch (error) {
71
+ noClipboard = true
72
+ }
73
+
68
74
 
69
75
  // Display data.
70
76
  console.log(
@@ -73,12 +79,13 @@ export const onVerification = async (verification: Verification): Promise<void>
73
79
  )} on this device to generate a new token and authenticate\n`
74
80
  )
75
81
 
76
- console.log(theme.colors.magenta(figlet.textSync("Code is Below", { font: "ANSI Shadow" })), '\n')
77
-
82
+ console.log(theme.colors.magenta(figlet.textSync("Code is Below", { font: "ANSI Shadow" })), "\n")
83
+
84
+ const message = !noClipboard ? `has been copied to your clipboard (${theme.emojis.clipboard})` : ``
78
85
  console.log(
79
- `${theme.symbols.info} Your auth code: ${theme.text.bold(verification.user_code)} has been copied to your clipboard (${theme.emojis.clipboard} ${
80
- theme.symbols.success
81
- })\n`
86
+ `${theme.symbols.info} Your auth code: ${theme.text.bold(
87
+ verification.user_code
88
+ )} ${message} ${theme.symbols.success})\n`
82
89
  )
83
90
 
84
91
  const spinner = customSpinner(`Redirecting to Github...`, `clock`)
@@ -86,8 +93,12 @@ export const onVerification = async (verification: Verification): Promise<void>
86
93
 
87
94
  await sleep(10000) // ~10s to make users able to read the CLI.
88
95
 
89
- // Automatically open the page (# Step 2).
90
- await open(verification.verification_uri)
96
+ try {
97
+ // Automatically open the page (# Step 2).
98
+ await open(verification.verification_uri)
99
+ } catch (error: any) {
100
+ console.log(`${theme.symbols.info} Please authenticate via GitHub at ${verification.verification_uri}`)
101
+ }
91
102
 
92
103
  spinner.stop()
93
104
 
@@ -811,7 +811,9 @@ export const listenToParticipantDocumentChanges = async (
811
811
  await getLatestVerificationResult(firestoreDatabase, ceremony.id, circuit.id, participant.id)
812
812
 
813
813
  // Get next circuit for contribution.
814
- const nextCircuit = timeoutExpired ? getCircuitBySequencePosition(circuits, changedContributionProgress) : getCircuitBySequencePosition(circuits, changedContributionProgress + 1)
814
+ const nextCircuit = timeoutExpired
815
+ ? getCircuitBySequencePosition(circuits, changedContributionProgress)
816
+ : getCircuitBySequencePosition(circuits, changedContributionProgress + 1)
815
817
 
816
818
  // Check disk space requirements for participant.
817
819
  const wannaGenerateAttestation = await handleDiskSpaceRequirementForNextContribution(
@@ -895,7 +897,7 @@ const contribute = async (opt: any) => {
895
897
  // Get options.
896
898
  const ceremonyOpt = opt.ceremony
897
899
  const entropyOpt = opt.entropy
898
- const auth = opt.auth
900
+ const auth = opt.auth
899
901
 
900
902
  // Check for authentication.
901
903
  const { user, providerUserId, token } = auth ? await authWithToken(firebaseApp, auth) : await checkAuth(firebaseApp)
@@ -249,7 +249,11 @@ const finalize = async (opt: any) => {
249
249
 
250
250
  // Check for authentication.
251
251
  const auth = opt.auth
252
- const { user, providerUserId, token: coordinatorAccessToken } = auth ? await authWithToken(firebaseApp, auth) : await checkAuth(firebaseApp)
252
+ const {
253
+ user,
254
+ providerUserId,
255
+ token: coordinatorAccessToken
256
+ } = auth ? await authWithToken(firebaseApp, auth) : await checkAuth(firebaseApp)
253
257
 
254
258
  // Preserve command execution only for coordinators.
255
259
  if (!(await isCoordinator(user))) showError(COMMAND_ERRORS.COMMAND_NOT_COORDINATOR, true)
@@ -6,4 +6,4 @@ export { default as finalize } from "./finalize.js"
6
6
  export { default as clean } from "./clean.js"
7
7
  export { default as logout } from "./logout.js"
8
8
  export { default as validate } from "./validate.js"
9
- export { default as listCeremonies} from "./listCeremonies.js"
9
+ export { default as listCeremonies } from "./listCeremonies.js"
@@ -17,11 +17,10 @@ const listCeremonies = async () => {
17
17
 
18
18
  // loop through all ceremonies
19
19
  for (const ceremony of ceremonies) names.push(ceremony.data().prefix)
20
-
20
+
21
21
  // print them to the console
22
22
  console.log(names.join(", "))
23
23
  process.exit(0)
24
-
25
24
  } catch (err: any) {
26
25
  showError(`${err.toString()}`, false)
27
26
  // we want to exit with a non-zero exit code
@@ -15,7 +15,7 @@ import { COMMAND_ERRORS, GENERIC_ERRORS, showError } from "../lib/errors.js"
15
15
  import { promptForCeremonySelection } from "../lib/prompts.js"
16
16
  import { bootstrapCommandExecutionAndServices, checkAuth } from "../lib/services.js"
17
17
  import theme from "../lib/theme.js"
18
- import {customSpinner, getSecondsMinutesHoursFromMillis, sleep } from "../lib/utils.js"
18
+ import { customSpinner, getSecondsMinutesHoursFromMillis, sleep } from "../lib/utils.js"
19
19
 
20
20
  /**
21
21
  * Clean cursor lines from current position back to root (default: zero).
@@ -466,7 +466,7 @@ export const handleCircuitArtifactUploadToStorage = async (
466
466
  * from Hermez's ceremony Phase 1 Reliable Setup Ceremony.
467
467
  * @param cmd? <any> - the path to the ceremony setup file.
468
468
  */
469
- const setup = async (cmd: { template?: string, auth?: string}) => {
469
+ const setup = async (cmd: { template?: string; auth?: string }) => {
470
470
  // Setup command state.
471
471
  const circuits: Array<CircuitDocument> = [] // Circuits.
472
472
  let ceremonyId: string = "" // The unique identifier of the ceremony.
@@ -474,8 +474,10 @@ const setup = async (cmd: { template?: string, auth?: string}) => {
474
474
  const { firebaseApp, firebaseFunctions, firestoreDatabase } = await bootstrapCommandExecutionAndServices()
475
475
 
476
476
  // Check for authentication.
477
- const { user, providerUserId } = cmd.auth ? await authWithToken(firebaseApp, cmd.auth) : await checkAuth(firebaseApp)
478
-
477
+ const { user, providerUserId } = cmd.auth
478
+ ? await authWithToken(firebaseApp, cmd.auth)
479
+ : await checkAuth(firebaseApp)
480
+
479
481
  // Preserve command execution only for coordinators.
480
482
  if (!(await isCoordinator(user))) showError(COMMAND_ERRORS.COMMAND_NOT_COORDINATOR, true)
481
483
 
@@ -501,7 +503,7 @@ const setup = async (cmd: { template?: string, auth?: string}) => {
501
503
  // if there is the file option, then set up the non interactively
502
504
  if (cmd.template) {
503
505
  // 1. parse the file
504
- // tmp data - do not cleanup files as we need them
506
+ // tmp data - do not cleanup files as we need them
505
507
  const spinner = customSpinner(`Parsing ${theme.text.bold(cmd.template!)} setup configuration file...`, `clock`)
506
508
  spinner.start()
507
509
  const setupCeremonyData = await parseCeremonyFile(cmd.template!)
@@ -524,13 +526,26 @@ const setup = async (cmd: { template?: string, auth?: string}) => {
524
526
  const zkeyLocalPathAndFileName = getZkeyLocalFilePath(circuit.files.initialZkeyFilename)
525
527
 
526
528
  // 2. download the pot and wasm files
527
- await checkAndDownloadSmallestPowersOfTau(convertToDoubleDigits(circuit.metadata?.pot!), circuit.files.potFilename)
528
-
529
+ await checkAndDownloadSmallestPowersOfTau(
530
+ convertToDoubleDigits(circuit.metadata?.pot!),
531
+ circuit.files.potFilename
532
+ )
533
+
529
534
  // 3. generate the zKey
530
- const spinner = customSpinner(`Generating genesis zKey for circuit ${theme.text.bold(circuit.name)}...`, `clock`)
535
+ const spinner = customSpinner(
536
+ `Generating genesis zKey for circuit ${theme.text.bold(circuit.name)}...`,
537
+ `clock`
538
+ )
531
539
  spinner.start()
532
- await zKey.newZKey(r1csLocalPathAndFileName, getPotLocalFilePath(circuit.files.potFilename), zkeyLocalPathAndFileName, undefined)
533
- spinner.succeed(`Generation of the genesis zKey for citcui ${theme.text.bold(circuit.name)} completed successfully`)
540
+ await zKey.newZKey(
541
+ r1csLocalPathAndFileName,
542
+ getPotLocalFilePath(circuit.files.potFilename),
543
+ zkeyLocalPathAndFileName,
544
+ undefined
545
+ )
546
+ spinner.succeed(
547
+ `Generation of the genesis zKey for citcui ${theme.text.bold(circuit.name)} completed successfully`
548
+ )
534
549
 
535
550
  // 4. calculate the hashes
536
551
  const wasmBlake2bHash = await blake512FromPath(wasmLocalPathAndFileName)
@@ -547,7 +562,7 @@ const setup = async (cmd: { template?: string, auth?: string}) => {
547
562
  zkeyLocalPathAndFileName,
548
563
  circuit.files.initialZkeyFilename
549
564
  )
550
-
565
+
551
566
  // Check if PoT file has been already uploaded to storage.
552
567
  const alreadyUploadedPot = await checkIfObjectExist(
553
568
  firebaseFunctions,
@@ -595,18 +610,24 @@ const setup = async (cmd: { template?: string, auth?: string}) => {
595
610
 
596
611
  ceremonySetupData.circuits[index].zKeySizeInBytes = getFileStats(zkeyLocalPathAndFileName).size
597
612
  }
598
-
599
613
 
600
614
  // 7. setup the ceremony
601
- const ceremonyId = await setupCeremony(firebaseFunctions, ceremonySetupData.ceremonyInputData, ceremonySetupData.ceremonyPrefix, ceremonySetupData.circuits)
602
- console.log( `Congratulations, the setup of ceremony ${theme.text.bold(
603
- ceremonySetupData.ceremonyInputData.title
604
- )} (${`UID: ${theme.text.bold(ceremonyId)}`}) has been successfully completed ${
605
- theme.emojis.tada
606
- }. You will be able to find all the files and info respectively in the ceremony bucket and database document.`)
607
-
615
+ const ceremonyId = await setupCeremony(
616
+ firebaseFunctions,
617
+ ceremonySetupData.ceremonyInputData,
618
+ ceremonySetupData.ceremonyPrefix,
619
+ ceremonySetupData.circuits
620
+ )
621
+ console.log(
622
+ `Congratulations, the setup of ceremony ${theme.text.bold(
623
+ ceremonySetupData.ceremonyInputData.title
624
+ )} (${`UID: ${theme.text.bold(ceremonyId)}`}) has been successfully completed ${
625
+ theme.emojis.tada
626
+ }. You will be able to find all the files and info respectively in the ceremony bucket and database document.`
627
+ )
628
+
608
629
  terminate(providerUserId)
609
- }
630
+ }
610
631
 
611
632
  // Look for R1CS files.
612
633
  const r1csFilePaths = await filterDirectoryFilesByExtension(cwd, `.r1cs`)
@@ -4,7 +4,7 @@ import { showError } from "../lib/errors.js"
4
4
  /**
5
5
  * Validate ceremony setup command.
6
6
  */
7
- const validate = async (cmd: { template: string, constraints?: number }) => {
7
+ const validate = async (cmd: { template: string; constraints?: number }) => {
8
8
  try {
9
9
  // parse the file and cleanup after
10
10
  const parsedFile = await parseCeremonyFile(cmd.template, true)
@@ -18,7 +18,6 @@ const validate = async (cmd: { template: string, constraints?: number }) => {
18
18
  }
19
19
 
20
20
  console.log(true)
21
-
22
21
  } catch (err: any) {
23
22
  showError(`${err.toString()}`, false)
24
23
  // we want to exit with a non-zero exit code
package/src/index.ts CHANGED
@@ -4,7 +4,17 @@ import { createCommand } from "commander"
4
4
  import { readFileSync } from "fs"
5
5
  import { dirname } from "path"
6
6
  import { fileURLToPath } from "url"
7
- import { setup, auth, contribute, observe, finalize, clean, logout, validate, listCeremonies } from "./commands/index.js"
7
+ import {
8
+ setup,
9
+ auth,
10
+ contribute,
11
+ observe,
12
+ finalize,
13
+ clean,
14
+ logout,
15
+ validate,
16
+ listCeremonies
17
+ } from "./commands/index.js"
8
18
 
9
19
  // Get pkg info (e.g., name, version).
10
20
  const packagePath = `${dirname(fileURLToPath(import.meta.url))}/..`
@@ -27,10 +37,7 @@ program
27
37
  .command("clean")
28
38
  .description("clean up output generated by commands from the current working directory")
29
39
  .action(clean)
30
- program
31
- .command("list")
32
- .description("List all ceremonies prefixes")
33
- .action(listCeremonies)
40
+ program.command("list").description("List all ceremonies prefixes").action(listCeremonies)
34
41
  program
35
42
  .command("logout")
36
43
  .description("sign out from Firebae Auth service and delete Github OAuth 2.0 token from local storage")
@@ -48,10 +55,10 @@ const ceremony = program.command("coordinate").description("commands for coordin
48
55
  ceremony
49
56
  .command("setup")
50
57
  .description("setup a Groth16 Phase 2 Trusted Setup ceremony for zk-SNARK circuits")
51
- .option('-t, --template <path>', 'The path to the ceremony setup template', '')
52
- .option('-a, --auth <string>', 'The Github OAuth 2.0 token', '')
58
+ .option("-t, --template <path>", "The path to the ceremony setup template", "")
59
+ .option("-a, --auth <string>", "The Github OAuth 2.0 token", "")
53
60
  .action(setup)
54
-
61
+
55
62
  ceremony
56
63
  .command("observe")
57
64
  .description("observe in real-time the waiting queue of each ceremony circuit")
@@ -343,7 +343,7 @@ export const promptCircuitInputData = async (
343
343
  let circomVersion: string = ""
344
344
  let circomCommitHash: string = ""
345
345
  let circuitInputData: CircuitInputData
346
- let useCfOrVm: CircuitContributionVerificationMechanism
346
+ let cfOrVm: CircuitContributionVerificationMechanism
347
347
  let vmDiskType: DiskTypeForVM
348
348
  let vmConfigurationType: string = ""
349
349
 
@@ -429,12 +429,17 @@ export const promptCircuitInputData = async (
429
429
  `CF`, // eq. true.
430
430
  `VM` // eq. false.
431
431
  )
432
- useCfOrVm = confirmation
433
- } else useCfOrVm = CircuitContributionVerificationMechanism.VM
432
+ cfOrVm = confirmation
433
+ ? CircuitContributionVerificationMechanism.CF
434
+ : CircuitContributionVerificationMechanism.VM
434
435
 
435
- if (useCfOrVm === undefined) showError(COMMAND_ERRORS.COMMAND_ABORT_PROMPT, true)
436
+ } else {
437
+ cfOrVm = CircuitContributionVerificationMechanism.VM
438
+ }
439
+
440
+ if (cfOrVm === undefined) showError(COMMAND_ERRORS.COMMAND_ABORT_PROMPT, true)
436
441
 
437
- if (!useCfOrVm) {
442
+ if (cfOrVm === CircuitContributionVerificationMechanism.VM) {
438
443
  // Ask for selecting the specific VM configuration type.
439
444
  vmConfigurationType = await promptVMTypeSelector(constraintSize)
440
445
 
@@ -478,9 +483,7 @@ export const promptCircuitInputData = async (
478
483
  paramsConfiguration: circuitConfigurationValues
479
484
  },
480
485
  verification: {
481
- cfOrVm: useCfOrVm
482
- ? CircuitContributionVerificationMechanism.CF
483
- : CircuitContributionVerificationMechanism.VM,
486
+ cfOrVm,
484
487
  vm: {
485
488
  vmConfigurationType,
486
489
  vmDiskType
@@ -520,9 +523,7 @@ export const promptCircuitInputData = async (
520
523
  paramsConfiguration: circuitConfigurationValues
521
524
  },
522
525
  verification: {
523
- cfOrVm: useCfOrVm
524
- ? CircuitContributionVerificationMechanism.CF
525
- : CircuitContributionVerificationMechanism.VM,
526
+ cfOrVm,
526
527
  vm: {
527
528
  vmConfigurationType,
528
529
  vmDiskType
@@ -117,8 +117,6 @@ export const signInToFirebase = async (firebaseApp: FirebaseApp, credentials: OA
117
117
  }
118
118
  }
119
119
 
120
-
121
-
122
120
  /**
123
121
  * Ensure that the callee is an authenticated user.
124
122
  * @notice The token will be passed as parameter.
package/src/lib/utils.ts CHANGED
@@ -311,8 +311,22 @@ export const generateCustomUrlToTweetAboutParticipation = (
311
311
  isFinalizing: boolean
312
312
  ) =>
313
313
  isFinalizing
314
- ? `https://twitter.com/intent/tweet?text=I%20have%20finalized%20the%20${ceremonyName}${ceremonyName.toLowerCase().includes("trusted") || ceremonyName.toLowerCase().includes("setup") || ceremonyName.toLowerCase().includes("phase2") || ceremonyName.toLowerCase().includes("ceremony") ? "!" : "%20Phase%202%20Trusted%20Setup%20ceremony!"}%20You%20can%20view%20my%20final%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP%20#PSE`
315
- : `https://twitter.com/intent/tweet?text=I%20contributed%20to%20the%20${ceremonyName}${ceremonyName.toLowerCase().includes("trusted") || ceremonyName.toLowerCase().includes("setup") || ceremonyName.toLowerCase().includes("phase2") || ceremonyName.toLowerCase().includes("ceremony") ? "!" : "%20Phase%202%20Trusted%20Setup%20ceremony!"}%20You%20can%20view%20the%20steps%20to%20contribute%20here:%20https://ceremony.pse.dev%20You%20can%20view%20my%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP`
314
+ ? `https://twitter.com/intent/tweet?text=I%20have%20finalized%20the%20${ceremonyName}${
315
+ ceremonyName.toLowerCase().includes("trusted") ||
316
+ ceremonyName.toLowerCase().includes("setup") ||
317
+ ceremonyName.toLowerCase().includes("phase2") ||
318
+ ceremonyName.toLowerCase().includes("ceremony")
319
+ ? "!"
320
+ : "%20Phase%202%20Trusted%20Setup%20ceremony!"
321
+ }%20You%20can%20view%20my%20final%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP%20#PSE`
322
+ : `https://twitter.com/intent/tweet?text=I%20contributed%20to%20the%20${ceremonyName}${
323
+ ceremonyName.toLowerCase().includes("trusted") ||
324
+ ceremonyName.toLowerCase().includes("setup") ||
325
+ ceremonyName.toLowerCase().includes("phase2") ||
326
+ ceremonyName.toLowerCase().includes("ceremony")
327
+ ? "!"
328
+ : "%20Phase%202%20Trusted%20Setup%20ceremony!"
329
+ }%20You%20can%20view%20the%20steps%20to%20contribute%20here:%20https://ceremony.pse.dev%20You%20can%20view%20my%20attestation%20here:%20${gistUrl}%20#Ethereum%20#ZKP`
316
330
 
317
331
  /**
318
332
  * Return a custom progress bar.
@@ -540,7 +554,9 @@ export const handleStartOrResumeContribution = async (
540
554
  const { completedContributions } = waitingQueue // = current progress.
541
555
 
542
556
  console.log(
543
- `${theme.text.bold(`\n- Circuit # ${theme.colors.magenta(`${sequencePosition}/${circuitsLength}`)}`)} (Contribution Steps)`
557
+ `${theme.text.bold(
558
+ `\n- Circuit # ${theme.colors.magenta(`${sequencePosition}/${circuitsLength}`)}`
559
+ )} (Contribution Steps)`
544
560
  )
545
561
 
546
562
  // Get most up-to-date data from the participant document.
@@ -609,6 +625,8 @@ export const handleStartOrResumeContribution = async (
609
625
  `${theme.symbols.success} Contribution ${theme.text.bold(`#${lastZkeyIndex}`)} correctly downloaded`
610
626
  )
611
627
 
628
+ await sleep(3000)
629
+
612
630
  // Advance to next contribution step (COMPUTING) if not finalizing.
613
631
  if (!isFinalizing) {
614
632
  spinner.text = `Preparing for contribution computation...`
@@ -652,6 +670,8 @@ export const handleStartOrResumeContribution = async (
652
670
  // Format contribution hash.
653
671
  const contributionHash = matchContributionHash?.at(0)?.replace("\n\t\t", "")!
654
672
 
673
+ await sleep(500)
674
+
655
675
  // Make request to cloud functions to permanently store the information.
656
676
  await permanentlyStoreCurrentContributionTimeAndHash(
657
677
  cloudFunctions,
@@ -677,6 +697,9 @@ export const handleStartOrResumeContribution = async (
677
697
  )}`
678
698
  )
679
699
 
700
+ // ensure the previous step is completed
701
+ await sleep(5000)
702
+
680
703
  // Advance to next contribution step (UPLOADING) if not finalizing.
681
704
  if (!isFinalizing) {
682
705
  spinner.text = `Preparing for uploading the contribution...`
@@ -701,7 +724,9 @@ export const handleStartOrResumeContribution = async (
701
724
  } This step may take a while based on circuit size and your internet speed. Everything's fine, just be patient.`
702
725
  spinner.start()
703
726
 
704
- if (!isFinalizing)
727
+ const progressBar = customProgressBar(ProgressBarType.UPLOAD, `your contribution`)
728
+
729
+ if (!isFinalizing) {
705
730
  await multiPartUpload(
706
731
  cloudFunctions,
707
732
  bucketName,
@@ -709,8 +734,12 @@ export const handleStartOrResumeContribution = async (
709
734
  nextZkeyLocalFilePath,
710
735
  Number(process.env.CONFIG_STREAM_CHUNK_SIZE_IN_MB),
711
736
  ceremony.id,
712
- participantData.tempContributionData
737
+ participantData.tempContributionData,
738
+ progressBar
713
739
  )
740
+
741
+ progressBar.stop()
742
+ }
714
743
  else
715
744
  await multiPartUpload(
716
745
  cloudFunctions,
@@ -720,6 +749,9 @@ export const handleStartOrResumeContribution = async (
720
749
  Number(process.env.CONFIG_STREAM_CHUNK_SIZE_IN_MB)
721
750
  )
722
751
 
752
+ // small sleep to ensure the previous step is completed
753
+ await sleep(5000)
754
+
723
755
  spinner.succeed(
724
756
  `${
725
757
  isFinalizing ? `Contribution` : `Contribution ${theme.text.bold(`#${nextZkeyIndex}`)}`