@devtion/devcli 0.0.0-7140596 → 0.0.0-7cfaa5d
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/.env +40 -39
- package/dist/index.js +67 -58
- package/dist/types/commands/contribute.d.ts +1 -1
- package/dist/types/commands/finalize.d.ts +4 -3
- package/dist/types/commands/observe.d.ts +1 -1
- package/dist/types/commands/setup.d.ts +1 -1
- package/dist/types/lib/prompts.d.ts +1 -1
- package/dist/types/lib/utils.d.ts +3 -2
- package/package.json +2 -2
- package/src/commands/auth.ts +5 -5
- package/src/commands/contribute.ts +12 -8
- package/src/commands/finalize.ts +19 -10
- package/src/commands/index.ts +1 -1
- package/src/commands/listCeremonies.ts +2 -3
- package/src/commands/observe.ts +2 -2
- package/src/commands/setup.ts +39 -41
- package/src/commands/validate.ts +2 -3
- package/src/index.ts +17 -8
- package/src/lib/localConfigs.ts +1 -1
- package/src/lib/prompts.ts +13 -12
- package/src/lib/services.ts +1 -3
- package/src/lib/utils.ts +24 -6
package/dist/.env
CHANGED
|
@@ -1,40 +1,41 @@
|
|
|
1
|
-
### FIREBASE ###
|
|
2
|
-
### These configs are related to the configuration of the Firebase services.
|
|
1
|
+
### FIREBASE ###
|
|
2
|
+
### These configs are related to the configuration of the Firebase services.
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# The Firebase Application API key for making request against the services.
|
|
6
|
+
# nb. this is going to be auto-generated when creating a new application.
|
|
7
|
+
FIREBASE_API_KEY=AIzaSyDVAu8U4zBpM3FFLPyktSjZnCmg1IR73Cg
|
|
8
|
+
# The URL to Firebase Authentication service (should point to default).
|
|
9
|
+
# nb. this is going to be auto-generated when creating a new application.
|
|
10
|
+
FIREBASE_AUTH_DOMAIN=p0tion-ci-environment.firebaseapp.com
|
|
11
|
+
# The Firebase Application project id (should match with application name).
|
|
12
|
+
FIREBASE_PROJECT_ID=p0tion-ci-environment
|
|
13
|
+
# The Firebase unique message sender identifier (to recognize the application user).
|
|
14
|
+
# nb. this is going to be auto-generated when creating a new application.
|
|
15
|
+
FIREBASE_MESSAGING_SENDER_ID=22680510841
|
|
16
|
+
# The Firebase unique identifier for your application.
|
|
17
|
+
# nb. this is going to be auto-generated when creating a new application.
|
|
18
|
+
FIREBASE_APP_ID=1:22680510841:web:529a664e73dbabd1c7cfa8
|
|
19
|
+
FIREBASE_CF_URL_VERIFY_CONTRIBUTION=https://verifycontribution-mq4aqokliq-ew.a.run.app
|
|
20
|
+
|
|
21
|
+
### AUTHENTICATION ###
|
|
22
|
+
### These configs are related to the authentication of users.
|
|
23
|
+
|
|
24
|
+
# The unique identifier for the Github client associated to the OAuth Application.
|
|
25
|
+
AUTH_GITHUB_CLIENT_ID=e9f8a5fabdfe0d95618c
|
|
26
|
+
|
|
27
|
+
### AWS S3 STORAGE ###
|
|
28
|
+
### These configs are related to the configuration of the interaction with the
|
|
29
|
+
### AWS S3 bucket used as storage for ceremony artifacts.
|
|
30
|
+
|
|
31
|
+
# The chunk size to be used when executing multi-part upload or downloads.
|
|
32
|
+
# default 25 MBs.
|
|
33
|
+
# (e.g. a 200 MB file setting a stream chunk size of 25 MB is going to be splitted and uploaded/downloaded in 4 chunks).
|
|
34
|
+
CONFIG_STREAM_CHUNK_SIZE_IN_MB=25
|
|
35
|
+
# The postfix string for each ceremony bucket.
|
|
36
|
+
# default -ph2-ceremony
|
|
37
|
+
CONFIG_CEREMONY_BUCKET_POSTFIX=-p0tion-development-environment
|
|
38
|
+
# The amount of time in seconds which indicates the duration about the validity of a pre-signed URL.
|
|
39
|
+
# default: 7200 seconds = 2 hours.
|
|
40
|
+
CONFIG_PRESIGNED_URL_EXPIRATION_IN_SECONDS=7200
|
|
3
41
|
|
|
4
|
-
|
|
5
|
-
# The Firebase Application API key for making request against the services.
|
|
6
|
-
# nb. this is going to be auto-generated when creating a new application.
|
|
7
|
-
FIREBASE_API_KEY="AIzaSyDVAu8U4zBpM3FFLPyktSjZnCmg1IR73Cg"
|
|
8
|
-
# The URL to Firebase Authentication service (should point to default).
|
|
9
|
-
# nb. this is going to be auto-generated when creating a new application.
|
|
10
|
-
FIREBASE_AUTH_DOMAIN="p0tion-ci-environment.firebaseapp.com"
|
|
11
|
-
# The Firebase Application project id (should match with application name).
|
|
12
|
-
FIREBASE_PROJECT_ID="p0tion-ci-environment"
|
|
13
|
-
# The Firebase unique message sender identifier (to recognize the application user).
|
|
14
|
-
# nb. this is going to be auto-generated when creating a new application.
|
|
15
|
-
FIREBASE_MESSAGING_SENDER_ID="22680510841"
|
|
16
|
-
# The Firebase unique identifier for your application.
|
|
17
|
-
# nb. this is going to be auto-generated when creating a new application.
|
|
18
|
-
FIREBASE_APP_ID="1:22680510841:web:529a664e73dbabd1c7cfa8"
|
|
19
|
-
FIREBASE_CF_URL_VERIFY_CONTRIBUTION="https://verifycontribution-mq4aqokliq-ew.a.run.app"
|
|
20
|
-
|
|
21
|
-
### AUTHENTICATION ###
|
|
22
|
-
### These configs are related to the authentication of users.
|
|
23
|
-
|
|
24
|
-
# The unique identifier for the Github client associated to the OAuth Application.
|
|
25
|
-
AUTH_GITHUB_CLIENT_ID="e9f8a5fabdfe0d95618c"
|
|
26
|
-
|
|
27
|
-
### AWS S3 STORAGE ###
|
|
28
|
-
### These configs are related to the configuration of the interaction with the
|
|
29
|
-
### AWS S3 bucket used as storage for ceremony artifacts.
|
|
30
|
-
|
|
31
|
-
# The chunk size to be used when executing multi-part upload or downloads.
|
|
32
|
-
# default 50 MBs.
|
|
33
|
-
# (e.g. a 200 MB file setting a stream chunk size of 50 MB is going to be splitted and uploaded/downloaded in 4 chunks).
|
|
34
|
-
CONFIG_STREAM_CHUNK_SIZE_IN_MB=50
|
|
35
|
-
# The postfix string for each ceremony bucket.
|
|
36
|
-
# default "-ph2-ceremony"
|
|
37
|
-
CONFIG_CEREMONY_BUCKET_POSTFIX="-p0tion-development-environment"
|
|
38
|
-
# The amount of time in seconds which indicates the duration about the validity of a pre-signed URL.
|
|
39
|
-
# default: 7200 seconds = 2 hours.
|
|
40
|
-
CONFIG_PRESIGNED_URL_EXPIRATION_IN_SECONDS=7200
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* @module @
|
|
5
|
-
* @version 1.0.
|
|
4
|
+
* @module @devtion/devcli
|
|
5
|
+
* @version 1.0.8
|
|
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
|
|
@@ -17,8 +17,7 @@ import boxen from 'boxen';
|
|
|
17
17
|
import { pipeline } from 'node:stream';
|
|
18
18
|
import { promisify } from 'node:util';
|
|
19
19
|
import fetch$1 from 'node-fetch';
|
|
20
|
-
import {
|
|
21
|
-
import { commonTerms, formatZkeyIndex, getZkeyStorageFilePath, finalContributionIndex, createCustomLoggerForFile, getBucketName, progressToNextContributionStep, permanentlyStoreCurrentContributionTimeAndHash, convertToDoubleDigits, multiPartUpload, verifyContribution, generateGetObjectPreSignedUrl, convertBytesOrKbToGb, numExpIterations, getDocumentById, getParticipantsCollectionPath, fromQueryToFirebaseDocumentInfo, getAllCollectionDocs, extractPrefix, autoGenerateEntropy, vmConfigurationTypes, initializeFirebaseCoreServices, signInToFirebaseWithCredentials, getCurrentFirebaseAuthUser, isCoordinator, parseCeremonyFile, blake512FromPath, checkIfObjectExist, setupCeremony, genesisZkeyIndex, getR1csStorageFilePath, getWasmStorageFilePath, getPotStorageFilePath, extractPoTFromFilename, potFileDownloadMainUrl, createS3Bucket, potFilenameTemplate, getR1CSInfo, getOpenedCeremonies, getCeremonyCircuits, checkParticipantForCeremony, getCurrentActiveParticipantTimeout, getCircuitBySequencePosition, getCircuitContributionsFromContributor, progressToNextCircuitForContribution, resumeContributionAfterTimeoutExpiration, generateValidContributionsAttestation, getContributionsValidityForContributor, getClosedCeremonies, checkAndPrepareCoordinatorForFinalization, computeSHA256ToHex, finalizeCeremony, getVerificationKeyStorageFilePath, verificationKeyAcronym, getVerifierContractStorageFilePath, verifierSmartContractAcronym, finalizeCircuit, exportVkey, exportVerifierContract } from '@p0tion/actions';
|
|
20
|
+
import { commonTerms, formatZkeyIndex, getZkeyStorageFilePath, finalContributionIndex, createCustomLoggerForFile, getBucketName, progressToNextContributionStep, permanentlyStoreCurrentContributionTimeAndHash, convertToDoubleDigits, multiPartUpload, verifyContribution, generateGetObjectPreSignedUrl, convertBytesOrKbToGb, numExpIterations, getDocumentById, getParticipantsCollectionPath, fromQueryToFirebaseDocumentInfo, getAllCollectionDocs, extractPrefix, autoGenerateEntropy, vmConfigurationTypes, initializeFirebaseCoreServices, signInToFirebaseWithCredentials, getCurrentFirebaseAuthUser, isCoordinator, parseCeremonyFile, blake512FromPath, checkIfObjectExist, setupCeremony, genesisZkeyIndex, getR1csStorageFilePath, getWasmStorageFilePath, getPotStorageFilePath, extractPoTFromFilename, potFileDownloadMainUrl, createS3Bucket, potFilenameTemplate, getR1CSInfo, getOpenedCeremonies, getCeremonyCircuits, checkParticipantForCeremony, getCurrentActiveParticipantTimeout, getCircuitBySequencePosition, getCircuitContributionsFromContributor, progressToNextCircuitForContribution, resumeContributionAfterTimeoutExpiration, generateValidContributionsAttestation, getContributionsValidityForContributor, getClosedCeremonies, checkAndPrepareCoordinatorForFinalization, computeSHA256ToHex, finalizeCeremony, getVerificationKeyStorageFilePath, verificationKeyAcronym, getVerifierContractStorageFilePath, verifierSmartContractAcronym, finalizeCircuit, exportVkey, exportVerifierContract } from '@devtion/actions';
|
|
22
21
|
import fetch from '@adobe/node-fetch-retry';
|
|
23
22
|
import { request } from '@octokit/request';
|
|
24
23
|
import { SingleBar, Presets } from 'cli-progress';
|
|
@@ -34,7 +33,6 @@ import Conf from 'conf';
|
|
|
34
33
|
import prompts from 'prompts';
|
|
35
34
|
import clear from 'clear';
|
|
36
35
|
import figlet from 'figlet';
|
|
37
|
-
import { Readable } from 'stream';
|
|
38
36
|
import { createOAuthDeviceAuth } from '@octokit/auth-oauth-device';
|
|
39
37
|
import clipboard from 'clipboardy';
|
|
40
38
|
import open from 'open';
|
|
@@ -367,6 +365,12 @@ const getVerificationKeyLocalFilePath = (completeFilename) => `${verificationKey
|
|
|
367
365
|
* @returns <string> - the complete final verifier contract path to the file.
|
|
368
366
|
*/
|
|
369
367
|
const getVerifierContractLocalFilePath = (completeFilename) => `${verifierContractsLocalFolderPath}/${completeFilename}`;
|
|
368
|
+
/**
|
|
369
|
+
* Get the complete final attestation file path.
|
|
370
|
+
* @param completeFilename <string> - the complete filename of the file (name.ext).
|
|
371
|
+
* @returns <string> - the complete final final attestation path to the file.
|
|
372
|
+
*/
|
|
373
|
+
const getFinalAttestationLocalFilePath = (completeFilename) => `${finalAttestationsLocalFolderPath}/${completeFilename}`;
|
|
370
374
|
/**
|
|
371
375
|
* Get the final transcript file path.
|
|
372
376
|
* @param completeFilename <string> - the complete filename of the file (name.ext).
|
|
@@ -581,8 +585,18 @@ const publishGist = async (token, content, ceremonyTitle, ceremonyPrefix) => {
|
|
|
581
585
|
* @returns <string> - the ready to share tweet url.
|
|
582
586
|
*/
|
|
583
587
|
const generateCustomUrlToTweetAboutParticipation = (ceremonyName, gistUrl, isFinalizing) => isFinalizing
|
|
584
|
-
? `https://twitter.com/intent/tweet?text=I%20have%20finalized%20the%20${ceremonyName}
|
|
585
|
-
|
|
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`;
|
|
586
600
|
/**
|
|
587
601
|
* Return a custom progress bar.
|
|
588
602
|
* @param type <ProgressBarType> - the type of the progress bar.
|
|
@@ -710,13 +724,14 @@ const getLatestUpdatesFromParticipant = async (firestoreDatabase, ceremonyId, pa
|
|
|
710
724
|
* @param entropyOrBeaconHash <string> - the entropy or beacon hash (only when finalizing) for the contribution.
|
|
711
725
|
* @param contributorOrCoordinatorIdentifier <string> - the identifier of the contributor or coordinator (only when finalizing).
|
|
712
726
|
* @param isFinalizing <boolean> - flag to discriminate between ceremony finalization (true) and contribution (false).
|
|
727
|
+
* @param circuitsLength <number> - the total number of circuits in the ceremony.
|
|
713
728
|
*/
|
|
714
|
-
const handleStartOrResumeContribution = async (cloudFunctions, firestoreDatabase, ceremony, circuit, participant, entropyOrBeaconHash, contributorOrCoordinatorIdentifier, isFinalizing) => {
|
|
729
|
+
const handleStartOrResumeContribution = async (cloudFunctions, firestoreDatabase, ceremony, circuit, participant, entropyOrBeaconHash, contributorOrCoordinatorIdentifier, isFinalizing, circuitsLength) => {
|
|
715
730
|
// Extract data.
|
|
716
731
|
const { prefix: ceremonyPrefix } = ceremony.data;
|
|
717
732
|
const { waitingQueue, avgTimings, prefix: circuitPrefix, sequencePosition } = circuit.data;
|
|
718
733
|
const { completedContributions } = waitingQueue; // = current progress.
|
|
719
|
-
console.log(`${theme.text.bold(`\n- Circuit # ${theme.colors.magenta(`${sequencePosition}`)}`)} (Contribution Steps)`);
|
|
734
|
+
console.log(`${theme.text.bold(`\n- Circuit # ${theme.colors.magenta(`${sequencePosition}/${circuitsLength}`)}`)} (Contribution Steps)`);
|
|
720
735
|
// Get most up-to-date data from the participant document.
|
|
721
736
|
let participantData = await getLatestUpdatesFromParticipant(firestoreDatabase, ceremony.id, participant.id);
|
|
722
737
|
const spinner = customSpinner(`${participantData.contributionStep === "DOWNLOADING" /* ParticipantContributionStep.DOWNLOADING */
|
|
@@ -809,7 +824,7 @@ const handleStartOrResumeContribution = async (cloudFunctions, firestoreDatabase
|
|
|
809
824
|
console.log(`${theme.symbols.success} Contribution ${theme.text.bold(`#${nextZkeyIndex}`)} already computed`);
|
|
810
825
|
// Contribution step = UPLOADING.
|
|
811
826
|
if (isFinalizing || participantData.contributionStep === "UPLOADING" /* ParticipantContributionStep.UPLOADING */) {
|
|
812
|
-
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
|
|
827
|
+
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.`;
|
|
813
828
|
spinner.start();
|
|
814
829
|
if (!isFinalizing)
|
|
815
830
|
await multiPartUpload(cloudFunctions, bucketName, nextZkeyStorageFilePath, nextZkeyLocalFilePath, Number(process.env.CONFIG_STREAM_CHUNK_SIZE_IN_MB), ceremony.id, participantData.tempContributionData);
|
|
@@ -1120,7 +1135,7 @@ const promptCircuitInputData = async (constraintSize, timeoutMechanismType, same
|
|
|
1120
1135
|
let circomVersion = "";
|
|
1121
1136
|
let circomCommitHash = "";
|
|
1122
1137
|
let circuitInputData;
|
|
1123
|
-
let
|
|
1138
|
+
let cfOrVm;
|
|
1124
1139
|
let vmDiskType;
|
|
1125
1140
|
let vmConfigurationType = "";
|
|
1126
1141
|
const questions = [
|
|
@@ -1180,13 +1195,16 @@ const promptCircuitInputData = async (constraintSize, timeoutMechanismType, same
|
|
|
1180
1195
|
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.
|
|
1181
1196
|
`VM` // eq. false.
|
|
1182
1197
|
);
|
|
1183
|
-
|
|
1198
|
+
cfOrVm = confirmation
|
|
1199
|
+
? "CF" /* CircuitContributionVerificationMechanism.CF */
|
|
1200
|
+
: "VM" /* CircuitContributionVerificationMechanism.VM */;
|
|
1184
1201
|
}
|
|
1185
|
-
else
|
|
1186
|
-
|
|
1187
|
-
|
|
1202
|
+
else {
|
|
1203
|
+
cfOrVm = "VM" /* CircuitContributionVerificationMechanism.VM */;
|
|
1204
|
+
}
|
|
1205
|
+
if (cfOrVm === undefined)
|
|
1188
1206
|
showError(COMMAND_ERRORS.COMMAND_ABORT_PROMPT, true);
|
|
1189
|
-
if (
|
|
1207
|
+
if (cfOrVm === "VM" /* CircuitContributionVerificationMechanism.VM */) {
|
|
1190
1208
|
// Ask for selecting the specific VM configuration type.
|
|
1191
1209
|
vmConfigurationType = await promptVMTypeSelector(constraintSize);
|
|
1192
1210
|
// Ask for selecting the specific VM disk (volume) type.
|
|
@@ -1220,9 +1238,7 @@ const promptCircuitInputData = async (constraintSize, timeoutMechanismType, same
|
|
|
1220
1238
|
paramsConfiguration: circuitConfigurationValues
|
|
1221
1239
|
},
|
|
1222
1240
|
verification: {
|
|
1223
|
-
cfOrVm
|
|
1224
|
-
? "CF" /* CircuitContributionVerificationMechanism.CF */
|
|
1225
|
-
: "VM" /* CircuitContributionVerificationMechanism.VM */,
|
|
1241
|
+
cfOrVm,
|
|
1226
1242
|
vm: {
|
|
1227
1243
|
vmConfigurationType,
|
|
1228
1244
|
vmDiskType
|
|
@@ -1258,9 +1274,7 @@ const promptCircuitInputData = async (constraintSize, timeoutMechanismType, same
|
|
|
1258
1274
|
paramsConfiguration: circuitConfigurationValues
|
|
1259
1275
|
},
|
|
1260
1276
|
verification: {
|
|
1261
|
-
cfOrVm
|
|
1262
|
-
? "CF" /* CircuitContributionVerificationMechanism.CF */
|
|
1263
|
-
: "VM" /* CircuitContributionVerificationMechanism.VM */,
|
|
1277
|
+
cfOrVm,
|
|
1264
1278
|
vm: {
|
|
1265
1279
|
vmConfigurationType,
|
|
1266
1280
|
vmDiskType
|
|
@@ -1826,7 +1840,9 @@ const setup = async (cmd) => {
|
|
|
1826
1840
|
let ceremonyId = ""; // The unique identifier of the ceremony.
|
|
1827
1841
|
const { firebaseApp, firebaseFunctions, firestoreDatabase } = await bootstrapCommandExecutionAndServices();
|
|
1828
1842
|
// Check for authentication.
|
|
1829
|
-
const { user, providerUserId } = cmd.auth
|
|
1843
|
+
const { user, providerUserId } = cmd.auth
|
|
1844
|
+
? await authWithToken(firebaseApp, cmd.auth)
|
|
1845
|
+
: await checkAuth(firebaseApp);
|
|
1830
1846
|
// Preserve command execution only for coordinators.
|
|
1831
1847
|
if (!(await isCoordinator(user)))
|
|
1832
1848
|
showError(COMMAND_ERRORS.COMMAND_NOT_COORDINATOR, true);
|
|
@@ -1843,7 +1859,7 @@ const setup = async (cmd) => {
|
|
|
1843
1859
|
// if there is the file option, then set up the non interactively
|
|
1844
1860
|
if (cmd.template) {
|
|
1845
1861
|
// 1. parse the file
|
|
1846
|
-
// tmp data - do not cleanup files as we need them
|
|
1862
|
+
// tmp data - do not cleanup files as we need them
|
|
1847
1863
|
const spinner = customSpinner(`Parsing ${theme.text.bold(cmd.template)} setup configuration file...`, `clock`);
|
|
1848
1864
|
spinner.start();
|
|
1849
1865
|
const setupCeremonyData = await parseCeremonyFile(cmd.template);
|
|
@@ -1853,8 +1869,6 @@ const setup = async (cmd) => {
|
|
|
1853
1869
|
// create a new bucket
|
|
1854
1870
|
const bucketName = await handleCeremonyBucketCreation(firebaseFunctions, ceremonySetupData.ceremonyPrefix);
|
|
1855
1871
|
console.log(`\n${theme.symbols.success} Ceremony bucket name: ${theme.text.bold(bucketName)}`);
|
|
1856
|
-
// create S3 clienbt
|
|
1857
|
-
const s3 = new S3Client({ region: 'us-east-1' });
|
|
1858
1872
|
// loop through each circuit
|
|
1859
1873
|
for await (const circuit of setupCeremonyData.circuits) {
|
|
1860
1874
|
// Local paths.
|
|
@@ -1864,21 +1878,12 @@ const setup = async (cmd) => {
|
|
|
1864
1878
|
const potLocalPathAndFileName = getPotLocalFilePath(circuit.files.potFilename);
|
|
1865
1879
|
const zkeyLocalPathAndFileName = getZkeyLocalFilePath(circuit.files.initialZkeyFilename);
|
|
1866
1880
|
// 2. download the pot and wasm files
|
|
1867
|
-
const streamPipeline = promisify(pipeline);
|
|
1868
1881
|
await checkAndDownloadSmallestPowersOfTau(convertToDoubleDigits(circuit.metadata?.pot), circuit.files.potFilename);
|
|
1869
|
-
// download the wasm to calculate the hash
|
|
1870
|
-
const spinner = customSpinner(`Downloading the ${theme.text.bold(`#${circuit.name}`)} WASM file from the project's bucket...`, `clock`);
|
|
1871
|
-
spinner.start();
|
|
1872
|
-
const command = new GetObjectCommand({ Bucket: ceremonySetupData.circuitArtifacts[index].artifacts.bucket, Key: ceremonySetupData.circuitArtifacts[index].artifacts.wasmStoragePath });
|
|
1873
|
-
const response = await s3.send(command);
|
|
1874
|
-
if (response.$metadata.httpStatusCode !== 200) {
|
|
1875
|
-
throw new Error("There was an error while trying to download the wasm file. Please check that the file has the correct permissions (public) set.");
|
|
1876
|
-
}
|
|
1877
|
-
if (response.Body instanceof Readable)
|
|
1878
|
-
await streamPipeline(response.Body, createWriteStream(wasmLocalPathAndFileName));
|
|
1879
|
-
spinner.stop();
|
|
1880
1882
|
// 3. generate the zKey
|
|
1883
|
+
const spinner = customSpinner(`Generating genesis zKey for circuit ${theme.text.bold(circuit.name)}...`, `clock`);
|
|
1884
|
+
spinner.start();
|
|
1881
1885
|
await zKey.newZKey(r1csLocalPathAndFileName, getPotLocalFilePath(circuit.files.potFilename), zkeyLocalPathAndFileName, undefined);
|
|
1886
|
+
spinner.succeed(`Generation of the genesis zKey for citcui ${theme.text.bold(circuit.name)} completed successfully`);
|
|
1882
1887
|
// 4. calculate the hashes
|
|
1883
1888
|
const wasmBlake2bHash = await blake512FromPath(wasmLocalPathAndFileName);
|
|
1884
1889
|
const potBlake2bHash = await blake512FromPath(getPotLocalFilePath(circuit.files.potFilename));
|
|
@@ -2114,7 +2119,7 @@ const onVerification = async (verification) => {
|
|
|
2114
2119
|
clipboard.readSync();
|
|
2115
2120
|
// Display data.
|
|
2116
2121
|
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`);
|
|
2117
|
-
console.log(theme.colors.magenta(figlet.textSync("Code is Below", { font: "ANSI Shadow" })),
|
|
2122
|
+
console.log(theme.colors.magenta(figlet.textSync("Code is Below", { font: "ANSI Shadow" })), "\n");
|
|
2118
2123
|
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`);
|
|
2119
2124
|
const spinner = customSpinner(`Redirecting to Github...`, `clock`);
|
|
2120
2125
|
spinner.start();
|
|
@@ -2566,8 +2571,8 @@ const listenToParticipantDocumentChanges = async (firestoreDatabase, cloudFuncti
|
|
|
2566
2571
|
// Communicate resume / start of the contribution to participant.
|
|
2567
2572
|
await simpleLoader(`${changedContributionStep === "DOWNLOADING" /* ParticipantContributionStep.DOWNLOADING */ ? `Starting` : `Resuming`} your contribution...`, `clock`, 3000);
|
|
2568
2573
|
// Start / Resume the contribution for the participant.
|
|
2569
|
-
await handleStartOrResumeContribution(cloudFunctions, firestoreDatabase, ceremony, circuit, participant, entropy, providerUserId, false // not finalizing.
|
|
2570
|
-
);
|
|
2574
|
+
await handleStartOrResumeContribution(cloudFunctions, firestoreDatabase, ceremony, circuit, participant, entropy, providerUserId, false, // not finalizing.
|
|
2575
|
+
circuits.length);
|
|
2571
2576
|
}
|
|
2572
2577
|
// Scenario (3.A).
|
|
2573
2578
|
else if (isWaitingForContribution)
|
|
@@ -2616,7 +2621,9 @@ const listenToParticipantDocumentChanges = async (firestoreDatabase, cloudFuncti
|
|
|
2616
2621
|
// Get latest contribution verification result.
|
|
2617
2622
|
await getLatestVerificationResult(firestoreDatabase, ceremony.id, circuit.id, participant.id);
|
|
2618
2623
|
// Get next circuit for contribution.
|
|
2619
|
-
const nextCircuit = timeoutExpired
|
|
2624
|
+
const nextCircuit = timeoutExpired
|
|
2625
|
+
? getCircuitBySequencePosition(circuits, changedContributionProgress)
|
|
2626
|
+
: getCircuitBySequencePosition(circuits, changedContributionProgress + 1);
|
|
2620
2627
|
// Check disk space requirements for participant.
|
|
2621
2628
|
const wannaGenerateAttestation = await handleDiskSpaceRequirementForNextContribution(cloudFunctions, ceremony.id, nextCircuit.data.sequencePosition, nextCircuit.data.zKeySizeInBytes, timeoutExpired, providerUserId);
|
|
2622
2629
|
// Check if the participant would like to generate a new attestation.
|
|
@@ -2654,11 +2661,12 @@ const listenToParticipantDocumentChanges = async (firestoreDatabase, cloudFuncti
|
|
|
2654
2661
|
*/
|
|
2655
2662
|
const contribute = async (opt) => {
|
|
2656
2663
|
const { firebaseApp, firebaseFunctions, firestoreDatabase } = await bootstrapCommandExecutionAndServices();
|
|
2657
|
-
// Check for authentication.
|
|
2658
|
-
const { user, providerUserId, token } = await checkAuth(firebaseApp);
|
|
2659
2664
|
// Get options.
|
|
2660
2665
|
const ceremonyOpt = opt.ceremony;
|
|
2661
2666
|
const entropyOpt = opt.entropy;
|
|
2667
|
+
const auth = opt.auth;
|
|
2668
|
+
// Check for authentication.
|
|
2669
|
+
const { user, providerUserId, token } = auth ? await authWithToken(firebaseApp, auth) : await checkAuth(firebaseApp);
|
|
2662
2670
|
// Prepare data.
|
|
2663
2671
|
let selectedCeremony;
|
|
2664
2672
|
// Retrieve the opened ceremonies.
|
|
@@ -2694,7 +2702,7 @@ const contribute = async (opt) => {
|
|
|
2694
2702
|
const userDoc = await getDocumentById(firestoreDatabase, commonTerms.collections.users.name, user.uid);
|
|
2695
2703
|
const userData = userDoc.data();
|
|
2696
2704
|
if (!userData) {
|
|
2697
|
-
spinner.fail(`Unfortunately we could not find a user document with your information. This likely means that you did not pass the GitHub reputation checks and therefore are not elegible to contribute to any ceremony. Please contact the coordinator if you believe this to be an error.`);
|
|
2705
|
+
spinner.fail(`Unfortunately we could not find a user document with your information. This likely means that you did not pass the GitHub reputation checks and therefore are not elegible to contribute to any ceremony. If you believe you pass the requirements, it might be possible that your profile is private and we were not able to fetch your real statistics, in this case please consider making your profile public for the duration of the contribution. Please contact the coordinator if you believe this to be an error.`);
|
|
2698
2706
|
process.exit(0);
|
|
2699
2707
|
}
|
|
2700
2708
|
// Check the user's current participant readiness for contribution status (eligible, already contributed, timed out).
|
|
@@ -2914,7 +2922,7 @@ const handleVerifierSmartContract = async (cloudFunctions, bucketName, finalZkey
|
|
|
2914
2922
|
const packagePath = `${dirname(fileURLToPath(import.meta.url))}`;
|
|
2915
2923
|
const verifierPath = packagePath.includes(`src/commands`)
|
|
2916
2924
|
? `${dirname(fileURLToPath(import.meta.url))}/../../../../node_modules/snarkjs/templates/verifier_groth16.sol.ejs`
|
|
2917
|
-
: `${dirname(fileURLToPath(import.meta.url))}
|
|
2925
|
+
: `${dirname(fileURLToPath(import.meta.url))}/../node_modules/snarkjs/templates/verifier_groth16.sol.ejs`;
|
|
2918
2926
|
// Export the Solidity verifier smart contract.
|
|
2919
2927
|
const verifierCode = await exportVerifierContract(finalZkeyLocalFilePath, verifierPath);
|
|
2920
2928
|
spinner.text = `Writing verifier smart contract...`;
|
|
@@ -2941,10 +2949,11 @@ const handleVerifierSmartContract = async (cloudFunctions, bucketName, finalZkey
|
|
|
2941
2949
|
* @param participant <FirebaseDocumentInfo> - the Firestore document of the participant (coordinator).
|
|
2942
2950
|
* @param beacon <string> - the value used to compute the final contribution while finalizing the ceremony.
|
|
2943
2951
|
* @param coordinatorIdentifier <string> - the identifier of the coordinator.
|
|
2952
|
+
* @param circuitsLength <number> - the number of circuits in the ceremony.
|
|
2944
2953
|
*/
|
|
2945
|
-
const handleCircuitFinalization = async (cloudFunctions, firestoreDatabase, ceremony, circuit, participant, beacon, coordinatorIdentifier) => {
|
|
2954
|
+
const handleCircuitFinalization = async (cloudFunctions, firestoreDatabase, ceremony, circuit, participant, beacon, coordinatorIdentifier, circuitsLength) => {
|
|
2946
2955
|
// Step (1).
|
|
2947
|
-
await handleStartOrResumeContribution(cloudFunctions, firestoreDatabase, ceremony, circuit, participant, computeSHA256ToHex(beacon), coordinatorIdentifier, true);
|
|
2956
|
+
await handleStartOrResumeContribution(cloudFunctions, firestoreDatabase, ceremony, circuit, participant, computeSHA256ToHex(beacon), coordinatorIdentifier, true, circuitsLength);
|
|
2948
2957
|
await sleep(2000); // workaound for descriptors.
|
|
2949
2958
|
// Extract data.
|
|
2950
2959
|
const { prefix: circuitPrefix } = circuit.data;
|
|
@@ -2979,10 +2988,11 @@ const handleCircuitFinalization = async (cloudFunctions, firestoreDatabase, cere
|
|
|
2979
2988
|
* @dev For proper execution, the command requires the coordinator to be authenticated with a GitHub account (run auth command first) in order to
|
|
2980
2989
|
* handle sybil-resistance and connect to GitHub APIs to publish the gist containing the final public attestation.
|
|
2981
2990
|
*/
|
|
2982
|
-
const finalize = async () => {
|
|
2991
|
+
const finalize = async (opt) => {
|
|
2983
2992
|
const { firebaseApp, firebaseFunctions, firestoreDatabase } = await bootstrapCommandExecutionAndServices();
|
|
2984
2993
|
// Check for authentication.
|
|
2985
|
-
const
|
|
2994
|
+
const auth = opt.auth;
|
|
2995
|
+
const { user, providerUserId, token: coordinatorAccessToken } = auth ? await authWithToken(firebaseApp, auth) : await checkAuth(firebaseApp);
|
|
2986
2996
|
// Preserve command execution only for coordinators.
|
|
2987
2997
|
if (!(await isCoordinator(user)))
|
|
2988
2998
|
showError(COMMAND_ERRORS.COMMAND_NOT_COORDINATOR, true);
|
|
@@ -3017,7 +3027,7 @@ const finalize = async () => {
|
|
|
3017
3027
|
const circuits = await getCeremonyCircuits(firestoreDatabase, selectedCeremony.id);
|
|
3018
3028
|
// Handle finalization for each ceremony circuit.
|
|
3019
3029
|
for await (const circuit of circuits)
|
|
3020
|
-
await handleCircuitFinalization(firebaseFunctions, firestoreDatabase, selectedCeremony, circuit, participant, beacon, providerUserId);
|
|
3030
|
+
await handleCircuitFinalization(firebaseFunctions, firestoreDatabase, selectedCeremony, circuit, participant, beacon, providerUserId, circuits.length);
|
|
3021
3031
|
process.stdout.write(`\n`);
|
|
3022
3032
|
const spinner = customSpinner(`Wrapping up the finalization of the ceremony...`, "clock");
|
|
3023
3033
|
spinner.start();
|
|
@@ -3032,7 +3042,7 @@ const finalize = async () => {
|
|
|
3032
3042
|
// Generate attestation with final contributions.
|
|
3033
3043
|
const publicAttestation = await generateValidContributionsAttestation(firestoreDatabase, circuits, selectedCeremony.id, participant.id, contributions, providerUserId, ceremonyName, true);
|
|
3034
3044
|
// Write public attestation locally.
|
|
3035
|
-
writeFile(
|
|
3045
|
+
writeFile(getFinalAttestationLocalFilePath(`${prefix}_${finalContributionIndex}_${commonTerms.foldersAndPathsTerms.attestation}.log`), Buffer.from(publicAttestation));
|
|
3036
3046
|
await sleep(3000); // workaround for file descriptor unexpected close.
|
|
3037
3047
|
const gistUrl = await publishGist(coordinatorAccessToken, publicAttestation, ceremonyName, prefix);
|
|
3038
3048
|
console.log(`\n${theme.symbols.info} Your public final attestation has been successfully posted as Github Gist (${theme.text.bold(theme.text.underlined(gistUrl))})`);
|
|
@@ -3168,15 +3178,13 @@ program
|
|
|
3168
3178
|
.description("compute contributions for a Phase2 Trusted Setup ceremony circuits")
|
|
3169
3179
|
.option("-c, --ceremony <string>", "the prefix of the ceremony you want to contribute for", "")
|
|
3170
3180
|
.option("-e, --entropy <string>", "the entropy (aka toxic waste) of your contribution", "")
|
|
3181
|
+
.option("-a, --auth <string>", "the Github OAuth 2.0 token", "")
|
|
3171
3182
|
.action(contribute);
|
|
3172
3183
|
program
|
|
3173
3184
|
.command("clean")
|
|
3174
3185
|
.description("clean up output generated by commands from the current working directory")
|
|
3175
3186
|
.action(clean);
|
|
3176
|
-
program
|
|
3177
|
-
.command("list")
|
|
3178
|
-
.description("List all ceremonies prefixes")
|
|
3179
|
-
.action(listCeremonies);
|
|
3187
|
+
program.command("list").description("List all ceremonies prefixes").action(listCeremonies);
|
|
3180
3188
|
program
|
|
3181
3189
|
.command("logout")
|
|
3182
3190
|
.description("sign out from Firebae Auth service and delete Github OAuth 2.0 token from local storage")
|
|
@@ -3192,8 +3200,8 @@ const ceremony = program.command("coordinate").description("commands for coordin
|
|
|
3192
3200
|
ceremony
|
|
3193
3201
|
.command("setup")
|
|
3194
3202
|
.description("setup a Groth16 Phase 2 Trusted Setup ceremony for zk-SNARK circuits")
|
|
3195
|
-
.option(
|
|
3196
|
-
.option(
|
|
3203
|
+
.option("-t, --template <path>", "The path to the ceremony setup template", "")
|
|
3204
|
+
.option("-a, --auth <string>", "The Github OAuth 2.0 token", "")
|
|
3197
3205
|
.action(setup);
|
|
3198
3206
|
ceremony
|
|
3199
3207
|
.command("observe")
|
|
@@ -3202,5 +3210,6 @@ ceremony
|
|
|
3202
3210
|
ceremony
|
|
3203
3211
|
.command("finalize")
|
|
3204
3212
|
.description("finalize a Phase2 Trusted Setup ceremony by applying a beacon, exporting verification key and verifier contract")
|
|
3213
|
+
.option("-a, --auth <string>", "the Github OAuth 2.0 token", "")
|
|
3205
3214
|
.action(finalize);
|
|
3206
3215
|
program.parseAsync(process.argv);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { Contribution, ContributionValidity, FirebaseDocumentInfo } from "@
|
|
2
|
+
import { Contribution, ContributionValidity, FirebaseDocumentInfo } from "@devtion/actions";
|
|
3
3
|
import { DocumentSnapshot, DocumentData, Firestore } from "firebase/firestore";
|
|
4
4
|
import { Functions } from "firebase/functions";
|
|
5
5
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { FirebaseDocumentInfo } from "@
|
|
2
|
+
import { FirebaseDocumentInfo } from "@devtion/actions";
|
|
3
3
|
import { Functions } from "firebase/functions";
|
|
4
4
|
import { Firestore } from "firebase/firestore";
|
|
5
5
|
/**
|
|
@@ -36,8 +36,9 @@ export declare const handleVerifierSmartContract: (cloudFunctions: Functions, bu
|
|
|
36
36
|
* @param participant <FirebaseDocumentInfo> - the Firestore document of the participant (coordinator).
|
|
37
37
|
* @param beacon <string> - the value used to compute the final contribution while finalizing the ceremony.
|
|
38
38
|
* @param coordinatorIdentifier <string> - the identifier of the coordinator.
|
|
39
|
+
* @param circuitsLength <number> - the number of circuits in the ceremony.
|
|
39
40
|
*/
|
|
40
|
-
export declare const handleCircuitFinalization: (cloudFunctions: Functions, firestoreDatabase: Firestore, ceremony: FirebaseDocumentInfo, circuit: FirebaseDocumentInfo, participant: FirebaseDocumentInfo, beacon: string, coordinatorIdentifier: string) => Promise<void>;
|
|
41
|
+
export declare const handleCircuitFinalization: (cloudFunctions: Functions, firestoreDatabase: Firestore, ceremony: FirebaseDocumentInfo, circuit: FirebaseDocumentInfo, participant: FirebaseDocumentInfo, beacon: string, coordinatorIdentifier: string, circuitsLength: number) => Promise<void>;
|
|
41
42
|
/**
|
|
42
43
|
* Finalize command.
|
|
43
44
|
* @notice The finalize command allows a coordinator to finalize a Trusted Setup Phase 2 ceremony by providing the final beacon,
|
|
@@ -47,5 +48,5 @@ export declare const handleCircuitFinalization: (cloudFunctions: Functions, fire
|
|
|
47
48
|
* @dev For proper execution, the command requires the coordinator to be authenticated with a GitHub account (run auth command first) in order to
|
|
48
49
|
* handle sybil-resistance and connect to GitHub APIs to publish the gist containing the final public attestation.
|
|
49
50
|
*/
|
|
50
|
-
declare const finalize: () => Promise<void>;
|
|
51
|
+
declare const finalize: (opt: any) => Promise<void>;
|
|
51
52
|
export default finalize;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Functions } from "firebase/functions";
|
|
3
|
-
import { CeremonyTimeoutType, CircomCompilerData, CircuitInputData, CeremonyInputData, CircuitDocument } from "@
|
|
3
|
+
import { CeremonyTimeoutType, CircomCompilerData, CircuitInputData, CeremonyInputData, CircuitDocument } from "@devtion/actions";
|
|
4
4
|
/**
|
|
5
5
|
* Handle whatever is needed to obtain the input data for a circuit that the coordinator would like to add to the ceremony.
|
|
6
6
|
* @param choosenCircuitFilename <string> - the name of the circuit to add.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Answers } from "prompts";
|
|
2
2
|
import { Firestore } from "firebase/firestore";
|
|
3
|
-
import { CeremonyInputData, FirebaseDocumentInfo, CircomCompilerData, CircuitInputData, CeremonyTimeoutType, DiskTypeForVM } from "@
|
|
3
|
+
import { CeremonyInputData, FirebaseDocumentInfo, CircomCompilerData, CircuitInputData, CeremonyTimeoutType, DiskTypeForVM } from "@devtion/actions";
|
|
4
4
|
/**
|
|
5
5
|
* Ask a binary (yes/no or true/false) customizable question.
|
|
6
6
|
* @param question <string> - the question to be answered.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FirebaseDocumentInfo } from "@
|
|
1
|
+
import { FirebaseDocumentInfo } from "@devtion/actions";
|
|
2
2
|
import { OAuthCredential } from "firebase/auth";
|
|
3
3
|
import { DocumentData, Firestore } from "firebase/firestore";
|
|
4
4
|
import { Functions } from "firebase/functions";
|
|
@@ -154,5 +154,6 @@ export declare const getLatestUpdatesFromParticipant: (firestoreDatabase: Firest
|
|
|
154
154
|
* @param entropyOrBeaconHash <string> - the entropy or beacon hash (only when finalizing) for the contribution.
|
|
155
155
|
* @param contributorOrCoordinatorIdentifier <string> - the identifier of the contributor or coordinator (only when finalizing).
|
|
156
156
|
* @param isFinalizing <boolean> - flag to discriminate between ceremony finalization (true) and contribution (false).
|
|
157
|
+
* @param circuitsLength <number> - the total number of circuits in the ceremony.
|
|
157
158
|
*/
|
|
158
|
-
export declare const handleStartOrResumeContribution: (cloudFunctions: Functions, firestoreDatabase: Firestore, ceremony: FirebaseDocumentInfo, circuit: FirebaseDocumentInfo, participant: FirebaseDocumentInfo, entropyOrBeaconHash: any, contributorOrCoordinatorIdentifier: string, isFinalizing: boolean) => Promise<void>;
|
|
159
|
+
export declare const handleStartOrResumeContribution: (cloudFunctions: Functions, firestoreDatabase: Firestore, ceremony: FirebaseDocumentInfo, circuit: FirebaseDocumentInfo, participant: FirebaseDocumentInfo, entropyOrBeaconHash: any, contributorOrCoordinatorIdentifier: string, isFinalizing: boolean, circuitsLength: number) => Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devtion/devcli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.0-
|
|
4
|
+
"version": "0.0.0-7cfaa5d",
|
|
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": "
|
|
100
|
+
"gitHead": "53164d43af65410911da5fa33f1ac0cade724872"
|
|
101
101
|
}
|
package/src/commands/auth.ts
CHANGED
|
@@ -73,12 +73,12 @@ export const onVerification = async (verification: Verification): Promise<void>
|
|
|
73
73
|
)} on this device to generate a new token and authenticate\n`
|
|
74
74
|
)
|
|
75
75
|
|
|
76
|
-
console.log(theme.colors.magenta(figlet.textSync("Code is Below", { font: "ANSI Shadow" })),
|
|
77
|
-
|
|
76
|
+
console.log(theme.colors.magenta(figlet.textSync("Code is Below", { font: "ANSI Shadow" })), "\n")
|
|
77
|
+
|
|
78
78
|
console.log(
|
|
79
|
-
`${theme.symbols.info} Your auth code: ${theme.text.bold(
|
|
80
|
-
|
|
81
|
-
})\n`
|
|
79
|
+
`${theme.symbols.info} Your auth code: ${theme.text.bold(
|
|
80
|
+
verification.user_code
|
|
81
|
+
)} has been copied to your clipboard (${theme.emojis.clipboard} ${theme.symbols.success})\n`
|
|
82
82
|
)
|
|
83
83
|
|
|
84
84
|
const spinner = customSpinner(`Redirecting to Github...`, `clock`)
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
generateValidContributionsAttestation,
|
|
23
23
|
commonTerms,
|
|
24
24
|
convertToDoubleDigits
|
|
25
|
-
} from "@
|
|
25
|
+
} from "@devtion/actions"
|
|
26
26
|
import { DocumentSnapshot, DocumentData, Firestore, onSnapshot, Timestamp } from "firebase/firestore"
|
|
27
27
|
import { Functions } from "firebase/functions"
|
|
28
28
|
import open from "open"
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
estimateParticipantFreeGlobalDiskSpace
|
|
41
41
|
} from "../lib/utils.js"
|
|
42
42
|
import { COMMAND_ERRORS, showError } from "../lib/errors.js"
|
|
43
|
-
import { bootstrapCommandExecutionAndServices, checkAuth } from "../lib/services.js"
|
|
43
|
+
import { authWithToken, bootstrapCommandExecutionAndServices, checkAuth } from "../lib/services.js"
|
|
44
44
|
import { getAttestationLocalFilePath, localPaths } from "../lib/localConfigs.js"
|
|
45
45
|
import theme from "../lib/theme.js"
|
|
46
46
|
import { checkAndMakeNewDirectoryIfNonexistent, writeFile } from "../lib/files.js"
|
|
@@ -724,7 +724,8 @@ export const listenToParticipantDocumentChanges = async (
|
|
|
724
724
|
participant,
|
|
725
725
|
entropy,
|
|
726
726
|
providerUserId,
|
|
727
|
-
false // not finalizing.
|
|
727
|
+
false, // not finalizing.
|
|
728
|
+
circuits.length
|
|
728
729
|
)
|
|
729
730
|
}
|
|
730
731
|
// Scenario (3.A).
|
|
@@ -810,7 +811,9 @@ export const listenToParticipantDocumentChanges = async (
|
|
|
810
811
|
await getLatestVerificationResult(firestoreDatabase, ceremony.id, circuit.id, participant.id)
|
|
811
812
|
|
|
812
813
|
// Get next circuit for contribution.
|
|
813
|
-
const nextCircuit = timeoutExpired
|
|
814
|
+
const nextCircuit = timeoutExpired
|
|
815
|
+
? getCircuitBySequencePosition(circuits, changedContributionProgress)
|
|
816
|
+
: getCircuitBySequencePosition(circuits, changedContributionProgress + 1)
|
|
814
817
|
|
|
815
818
|
// Check disk space requirements for participant.
|
|
816
819
|
const wannaGenerateAttestation = await handleDiskSpaceRequirementForNextContribution(
|
|
@@ -891,12 +894,13 @@ export const listenToParticipantDocumentChanges = async (
|
|
|
891
894
|
const contribute = async (opt: any) => {
|
|
892
895
|
const { firebaseApp, firebaseFunctions, firestoreDatabase } = await bootstrapCommandExecutionAndServices()
|
|
893
896
|
|
|
894
|
-
// Check for authentication.
|
|
895
|
-
const { user, providerUserId, token } = await checkAuth(firebaseApp)
|
|
896
|
-
|
|
897
897
|
// Get options.
|
|
898
898
|
const ceremonyOpt = opt.ceremony
|
|
899
899
|
const entropyOpt = opt.entropy
|
|
900
|
+
const auth = opt.auth
|
|
901
|
+
|
|
902
|
+
// Check for authentication.
|
|
903
|
+
const { user, providerUserId, token } = auth ? await authWithToken(firebaseApp, auth) : await checkAuth(firebaseApp)
|
|
900
904
|
|
|
901
905
|
// Prepare data.
|
|
902
906
|
let selectedCeremony: FirebaseDocumentInfo
|
|
@@ -948,7 +952,7 @@ const contribute = async (opt: any) => {
|
|
|
948
952
|
const userData = userDoc.data()
|
|
949
953
|
if (!userData) {
|
|
950
954
|
spinner.fail(
|
|
951
|
-
`Unfortunately we could not find a user document with your information. This likely means that you did not pass the GitHub reputation checks and therefore are not elegible to contribute to any ceremony. Please contact the coordinator if you believe this to be an error.`
|
|
955
|
+
`Unfortunately we could not find a user document with your information. This likely means that you did not pass the GitHub reputation checks and therefore are not elegible to contribute to any ceremony. If you believe you pass the requirements, it might be possible that your profile is private and we were not able to fetch your real statistics, in this case please consider making your profile public for the duration of the contribution. Please contact the coordinator if you believe this to be an error.`
|
|
952
956
|
)
|
|
953
957
|
process.exit(0)
|
|
954
958
|
}
|
package/src/commands/finalize.ts
CHANGED
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
exportVerifierContract,
|
|
23
23
|
FirebaseDocumentInfo,
|
|
24
24
|
exportVkey
|
|
25
|
-
} from "@
|
|
25
|
+
} from "@devtion/actions"
|
|
26
26
|
import { Functions } from "firebase/functions"
|
|
27
27
|
import { Firestore } from "firebase/firestore"
|
|
28
28
|
import { dirname } from "path"
|
|
@@ -36,9 +36,9 @@ import {
|
|
|
36
36
|
sleep,
|
|
37
37
|
terminate
|
|
38
38
|
} from "../lib/utils.js"
|
|
39
|
-
import { bootstrapCommandExecutionAndServices, checkAuth } from "../lib/services.js"
|
|
39
|
+
import { authWithToken, bootstrapCommandExecutionAndServices, checkAuth } from "../lib/services.js"
|
|
40
40
|
import {
|
|
41
|
-
|
|
41
|
+
getFinalAttestationLocalFilePath,
|
|
42
42
|
getFinalZkeyLocalFilePath,
|
|
43
43
|
getVerificationKeyLocalFilePath,
|
|
44
44
|
getVerifierContractLocalFilePath,
|
|
@@ -112,7 +112,7 @@ export const handleVerifierSmartContract = async (
|
|
|
112
112
|
? `${dirname(
|
|
113
113
|
fileURLToPath(import.meta.url)
|
|
114
114
|
)}/../../../../node_modules/snarkjs/templates/verifier_groth16.sol.ejs`
|
|
115
|
-
: `${dirname(fileURLToPath(import.meta.url))}
|
|
115
|
+
: `${dirname(fileURLToPath(import.meta.url))}/../node_modules/snarkjs/templates/verifier_groth16.sol.ejs`
|
|
116
116
|
|
|
117
117
|
// Export the Solidity verifier smart contract.
|
|
118
118
|
const verifierCode = await exportVerifierContract(finalZkeyLocalFilePath, verifierPath)
|
|
@@ -152,6 +152,7 @@ export const handleVerifierSmartContract = async (
|
|
|
152
152
|
* @param participant <FirebaseDocumentInfo> - the Firestore document of the participant (coordinator).
|
|
153
153
|
* @param beacon <string> - the value used to compute the final contribution while finalizing the ceremony.
|
|
154
154
|
* @param coordinatorIdentifier <string> - the identifier of the coordinator.
|
|
155
|
+
* @param circuitsLength <number> - the number of circuits in the ceremony.
|
|
155
156
|
*/
|
|
156
157
|
export const handleCircuitFinalization = async (
|
|
157
158
|
cloudFunctions: Functions,
|
|
@@ -160,7 +161,8 @@ export const handleCircuitFinalization = async (
|
|
|
160
161
|
circuit: FirebaseDocumentInfo,
|
|
161
162
|
participant: FirebaseDocumentInfo,
|
|
162
163
|
beacon: string,
|
|
163
|
-
coordinatorIdentifier: string
|
|
164
|
+
coordinatorIdentifier: string,
|
|
165
|
+
circuitsLength: number
|
|
164
166
|
) => {
|
|
165
167
|
// Step (1).
|
|
166
168
|
await handleStartOrResumeContribution(
|
|
@@ -171,7 +173,8 @@ export const handleCircuitFinalization = async (
|
|
|
171
173
|
participant,
|
|
172
174
|
computeSHA256ToHex(beacon),
|
|
173
175
|
coordinatorIdentifier,
|
|
174
|
-
true
|
|
176
|
+
true,
|
|
177
|
+
circuitsLength
|
|
175
178
|
)
|
|
176
179
|
|
|
177
180
|
await sleep(2000) // workaound for descriptors.
|
|
@@ -241,11 +244,16 @@ export const handleCircuitFinalization = async (
|
|
|
241
244
|
* @dev For proper execution, the command requires the coordinator to be authenticated with a GitHub account (run auth command first) in order to
|
|
242
245
|
* handle sybil-resistance and connect to GitHub APIs to publish the gist containing the final public attestation.
|
|
243
246
|
*/
|
|
244
|
-
const finalize = async () => {
|
|
247
|
+
const finalize = async (opt: any) => {
|
|
245
248
|
const { firebaseApp, firebaseFunctions, firestoreDatabase } = await bootstrapCommandExecutionAndServices()
|
|
246
249
|
|
|
247
250
|
// Check for authentication.
|
|
248
|
-
const
|
|
251
|
+
const auth = opt.auth
|
|
252
|
+
const {
|
|
253
|
+
user,
|
|
254
|
+
providerUserId,
|
|
255
|
+
token: coordinatorAccessToken
|
|
256
|
+
} = auth ? await authWithToken(firebaseApp, auth) : await checkAuth(firebaseApp)
|
|
249
257
|
|
|
250
258
|
// Preserve command execution only for coordinators.
|
|
251
259
|
if (!(await isCoordinator(user))) showError(COMMAND_ERRORS.COMMAND_NOT_COORDINATOR, true)
|
|
@@ -306,7 +314,8 @@ const finalize = async () => {
|
|
|
306
314
|
circuit,
|
|
307
315
|
participant,
|
|
308
316
|
beacon,
|
|
309
|
-
providerUserId
|
|
317
|
+
providerUserId,
|
|
318
|
+
circuits.length
|
|
310
319
|
)
|
|
311
320
|
|
|
312
321
|
process.stdout.write(`\n`)
|
|
@@ -344,7 +353,7 @@ const finalize = async () => {
|
|
|
344
353
|
|
|
345
354
|
// Write public attestation locally.
|
|
346
355
|
writeFile(
|
|
347
|
-
|
|
356
|
+
getFinalAttestationLocalFilePath(
|
|
348
357
|
`${prefix}_${finalContributionIndex}_${commonTerms.foldersAndPathsTerms.attestation}.log`
|
|
349
358
|
),
|
|
350
359
|
Buffer.from(publicAttestation)
|
package/src/commands/index.ts
CHANGED
|
@@ -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"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { commonTerms, getAllCollectionDocs } from "@
|
|
1
|
+
import { commonTerms, getAllCollectionDocs } from "@devtion/actions"
|
|
2
2
|
import { showError } from "../lib/errors.js"
|
|
3
3
|
import { bootstrapCommandExecutionAndServices } from "../lib/services.js"
|
|
4
4
|
|
|
@@ -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
|
package/src/commands/observe.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
getOpenedCeremonies,
|
|
8
8
|
isCoordinator,
|
|
9
9
|
convertToDoubleDigits
|
|
10
|
-
} from "@
|
|
10
|
+
} from "@devtion/actions"
|
|
11
11
|
import { Firestore } from "firebase/firestore"
|
|
12
12
|
import logSymbols from "log-symbols"
|
|
13
13
|
import readline from "readline"
|
|
@@ -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).
|
package/src/commands/setup.ts
CHANGED
|
@@ -7,7 +7,6 @@ import { pipeline } from "node:stream"
|
|
|
7
7
|
import { promisify } from "node:util"
|
|
8
8
|
import fetch from "node-fetch"
|
|
9
9
|
import { Functions } from "firebase/functions"
|
|
10
|
-
import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3"
|
|
11
10
|
import {
|
|
12
11
|
CeremonyTimeoutType,
|
|
13
12
|
CircomCompilerData,
|
|
@@ -37,7 +36,7 @@ import {
|
|
|
37
36
|
setupCeremony,
|
|
38
37
|
parseCeremonyFile,
|
|
39
38
|
CircuitContributionVerificationMechanism
|
|
40
|
-
} from "@
|
|
39
|
+
} from "@devtion/actions"
|
|
41
40
|
import { customSpinner, simpleLoader, sleep, terminate } from "../lib/utils.js"
|
|
42
41
|
import {
|
|
43
42
|
promptCeremonyInputData,
|
|
@@ -63,7 +62,6 @@ import {
|
|
|
63
62
|
getFileStats,
|
|
64
63
|
checkAndMakeNewDirectoryIfNonexistent
|
|
65
64
|
} from "../lib/files.js"
|
|
66
|
-
import { Readable } from "stream"
|
|
67
65
|
|
|
68
66
|
/**
|
|
69
67
|
* Handle whatever is needed to obtain the input data for a circuit that the coordinator would like to add to the ceremony.
|
|
@@ -468,7 +466,7 @@ export const handleCircuitArtifactUploadToStorage = async (
|
|
|
468
466
|
* from Hermez's ceremony Phase 1 Reliable Setup Ceremony.
|
|
469
467
|
* @param cmd? <any> - the path to the ceremony setup file.
|
|
470
468
|
*/
|
|
471
|
-
const setup = async (cmd: { template?: string
|
|
469
|
+
const setup = async (cmd: { template?: string; auth?: string }) => {
|
|
472
470
|
// Setup command state.
|
|
473
471
|
const circuits: Array<CircuitDocument> = [] // Circuits.
|
|
474
472
|
let ceremonyId: string = "" // The unique identifier of the ceremony.
|
|
@@ -476,8 +474,10 @@ const setup = async (cmd: { template?: string, auth?: string}) => {
|
|
|
476
474
|
const { firebaseApp, firebaseFunctions, firestoreDatabase } = await bootstrapCommandExecutionAndServices()
|
|
477
475
|
|
|
478
476
|
// Check for authentication.
|
|
479
|
-
const { user, providerUserId } = cmd.auth
|
|
480
|
-
|
|
477
|
+
const { user, providerUserId } = cmd.auth
|
|
478
|
+
? await authWithToken(firebaseApp, cmd.auth)
|
|
479
|
+
: await checkAuth(firebaseApp)
|
|
480
|
+
|
|
481
481
|
// Preserve command execution only for coordinators.
|
|
482
482
|
if (!(await isCoordinator(user))) showError(COMMAND_ERRORS.COMMAND_NOT_COORDINATOR, true)
|
|
483
483
|
|
|
@@ -503,7 +503,7 @@ const setup = async (cmd: { template?: string, auth?: string}) => {
|
|
|
503
503
|
// if there is the file option, then set up the non interactively
|
|
504
504
|
if (cmd.template) {
|
|
505
505
|
// 1. parse the file
|
|
506
|
-
// tmp data - do not cleanup files as we need them
|
|
506
|
+
// tmp data - do not cleanup files as we need them
|
|
507
507
|
const spinner = customSpinner(`Parsing ${theme.text.bold(cmd.template!)} setup configuration file...`, `clock`)
|
|
508
508
|
spinner.start()
|
|
509
509
|
const setupCeremonyData = await parseCeremonyFile(cmd.template!)
|
|
@@ -516,9 +516,6 @@ const setup = async (cmd: { template?: string, auth?: string}) => {
|
|
|
516
516
|
const bucketName = await handleCeremonyBucketCreation(firebaseFunctions, ceremonySetupData.ceremonyPrefix)
|
|
517
517
|
console.log(`\n${theme.symbols.success} Ceremony bucket name: ${theme.text.bold(bucketName)}`)
|
|
518
518
|
|
|
519
|
-
// create S3 clienbt
|
|
520
|
-
const s3 = new S3Client({region: 'us-east-1'})
|
|
521
|
-
|
|
522
519
|
// loop through each circuit
|
|
523
520
|
for await (const circuit of setupCeremonyData.circuits) {
|
|
524
521
|
// Local paths.
|
|
@@ -529,32 +526,27 @@ const setup = async (cmd: { template?: string, auth?: string}) => {
|
|
|
529
526
|
const zkeyLocalPathAndFileName = getZkeyLocalFilePath(circuit.files.initialZkeyFilename)
|
|
530
527
|
|
|
531
528
|
// 2. download the pot and wasm files
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
529
|
+
await checkAndDownloadSmallestPowersOfTau(
|
|
530
|
+
convertToDoubleDigits(circuit.metadata?.pot!),
|
|
531
|
+
circuit.files.potFilename
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
// 3. generate the zKey
|
|
536
535
|
const spinner = customSpinner(
|
|
537
|
-
`
|
|
538
|
-
`#${circuit.name}`
|
|
539
|
-
)} WASM file from the project's bucket...`,
|
|
536
|
+
`Generating genesis zKey for circuit ${theme.text.bold(circuit.name)}...`,
|
|
540
537
|
`clock`
|
|
541
538
|
)
|
|
542
539
|
spinner.start()
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
await streamPipeline(response.Body, createWriteStream(wasmLocalPathAndFileName))
|
|
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
|
+
)
|
|
553
549
|
|
|
554
|
-
spinner.stop()
|
|
555
|
-
// 3. generate the zKey
|
|
556
|
-
await zKey.newZKey(r1csLocalPathAndFileName, getPotLocalFilePath(circuit.files.potFilename), zkeyLocalPathAndFileName, undefined)
|
|
557
|
-
|
|
558
550
|
// 4. calculate the hashes
|
|
559
551
|
const wasmBlake2bHash = await blake512FromPath(wasmLocalPathAndFileName)
|
|
560
552
|
const potBlake2bHash = await blake512FromPath(getPotLocalFilePath(circuit.files.potFilename))
|
|
@@ -570,7 +562,7 @@ const setup = async (cmd: { template?: string, auth?: string}) => {
|
|
|
570
562
|
zkeyLocalPathAndFileName,
|
|
571
563
|
circuit.files.initialZkeyFilename
|
|
572
564
|
)
|
|
573
|
-
|
|
565
|
+
|
|
574
566
|
// Check if PoT file has been already uploaded to storage.
|
|
575
567
|
const alreadyUploadedPot = await checkIfObjectExist(
|
|
576
568
|
firebaseFunctions,
|
|
@@ -618,18 +610,24 @@ const setup = async (cmd: { template?: string, auth?: string}) => {
|
|
|
618
610
|
|
|
619
611
|
ceremonySetupData.circuits[index].zKeySizeInBytes = getFileStats(zkeyLocalPathAndFileName).size
|
|
620
612
|
}
|
|
621
|
-
|
|
622
613
|
|
|
623
614
|
// 7. setup the ceremony
|
|
624
|
-
const ceremonyId = await setupCeremony(
|
|
625
|
-
|
|
626
|
-
ceremonySetupData.ceremonyInputData
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
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
|
+
|
|
631
629
|
terminate(providerUserId)
|
|
632
|
-
}
|
|
630
|
+
}
|
|
633
631
|
|
|
634
632
|
// Look for R1CS files.
|
|
635
633
|
const r1csFilePaths = await filterDirectoryFilesByExtension(cwd, `.r1cs`)
|
package/src/commands/validate.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { parseCeremonyFile } from "@
|
|
1
|
+
import { parseCeremonyFile } from "@devtion/actions"
|
|
2
2
|
import { showError } from "../lib/errors.js"
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Validate ceremony setup command.
|
|
6
6
|
*/
|
|
7
|
-
const validate = async (cmd: { template: string
|
|
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 {
|
|
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))}/..`
|
|
@@ -21,15 +31,13 @@ program
|
|
|
21
31
|
.description("compute contributions for a Phase2 Trusted Setup ceremony circuits")
|
|
22
32
|
.option("-c, --ceremony <string>", "the prefix of the ceremony you want to contribute for", "")
|
|
23
33
|
.option("-e, --entropy <string>", "the entropy (aka toxic waste) of your contribution", "")
|
|
34
|
+
.option("-a, --auth <string>", "the Github OAuth 2.0 token", "")
|
|
24
35
|
.action(contribute)
|
|
25
36
|
program
|
|
26
37
|
.command("clean")
|
|
27
38
|
.description("clean up output generated by commands from the current working directory")
|
|
28
39
|
.action(clean)
|
|
29
|
-
program
|
|
30
|
-
.command("list")
|
|
31
|
-
.description("List all ceremonies prefixes")
|
|
32
|
-
.action(listCeremonies)
|
|
40
|
+
program.command("list").description("List all ceremonies prefixes").action(listCeremonies)
|
|
33
41
|
program
|
|
34
42
|
.command("logout")
|
|
35
43
|
.description("sign out from Firebae Auth service and delete Github OAuth 2.0 token from local storage")
|
|
@@ -47,10 +55,10 @@ const ceremony = program.command("coordinate").description("commands for coordin
|
|
|
47
55
|
ceremony
|
|
48
56
|
.command("setup")
|
|
49
57
|
.description("setup a Groth16 Phase 2 Trusted Setup ceremony for zk-SNARK circuits")
|
|
50
|
-
.option(
|
|
51
|
-
.option(
|
|
58
|
+
.option("-t, --template <path>", "The path to the ceremony setup template", "")
|
|
59
|
+
.option("-a, --auth <string>", "The Github OAuth 2.0 token", "")
|
|
52
60
|
.action(setup)
|
|
53
|
-
|
|
61
|
+
|
|
54
62
|
ceremony
|
|
55
63
|
.command("observe")
|
|
56
64
|
.description("observe in real-time the waiting queue of each ceremony circuit")
|
|
@@ -61,6 +69,7 @@ ceremony
|
|
|
61
69
|
.description(
|
|
62
70
|
"finalize a Phase2 Trusted Setup ceremony by applying a beacon, exporting verification key and verifier contract"
|
|
63
71
|
)
|
|
72
|
+
.option("-a, --auth <string>", "the Github OAuth 2.0 token", "")
|
|
64
73
|
.action(finalize)
|
|
65
74
|
|
|
66
75
|
program.parseAsync(process.argv)
|
package/src/lib/localConfigs.ts
CHANGED
package/src/lib/prompts.ts
CHANGED
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
CircuitContributionVerificationMechanism,
|
|
15
15
|
vmConfigurationTypes,
|
|
16
16
|
DiskTypeForVM
|
|
17
|
-
} from "@
|
|
17
|
+
} from "@devtion/actions"
|
|
18
18
|
import theme from "./theme.js"
|
|
19
19
|
import { COMMAND_ERRORS, showError } from "./errors.js"
|
|
20
20
|
|
|
@@ -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
|
|
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
|
-
|
|
433
|
-
|
|
432
|
+
cfOrVm = confirmation
|
|
433
|
+
? CircuitContributionVerificationMechanism.CF
|
|
434
|
+
: CircuitContributionVerificationMechanism.VM
|
|
434
435
|
|
|
435
|
-
|
|
436
|
+
} else {
|
|
437
|
+
cfOrVm = CircuitContributionVerificationMechanism.VM
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (cfOrVm === undefined) showError(COMMAND_ERRORS.COMMAND_ABORT_PROMPT, true)
|
|
436
441
|
|
|
437
|
-
if (
|
|
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
|
|
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
|
|
524
|
-
? CircuitContributionVerificationMechanism.CF
|
|
525
|
-
: CircuitContributionVerificationMechanism.VM,
|
|
526
|
+
cfOrVm,
|
|
526
527
|
vm: {
|
|
527
528
|
vmConfigurationType,
|
|
528
529
|
vmDiskType
|
package/src/lib/services.ts
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
getCurrentFirebaseAuthUser,
|
|
3
3
|
initializeFirebaseCoreServices,
|
|
4
4
|
signInToFirebaseWithCredentials
|
|
5
|
-
} from "@
|
|
5
|
+
} from "@devtion/actions"
|
|
6
6
|
import clear from "clear"
|
|
7
7
|
import figlet from "figlet"
|
|
8
8
|
import { FirebaseApp } from "firebase/app"
|
|
@@ -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
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
permanentlyStoreCurrentContributionTimeAndHash,
|
|
20
20
|
progressToNextContributionStep,
|
|
21
21
|
verifyContribution
|
|
22
|
-
} from "@
|
|
22
|
+
} from "@devtion/actions"
|
|
23
23
|
import { Presets, SingleBar } from "cli-progress"
|
|
24
24
|
import dotenv from "dotenv"
|
|
25
25
|
import { GithubAuthProvider, OAuthCredential } from "firebase/auth"
|
|
@@ -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}
|
|
315
|
-
|
|
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.
|
|
@@ -521,6 +535,7 @@ export const getLatestUpdatesFromParticipant = async (
|
|
|
521
535
|
* @param entropyOrBeaconHash <string> - the entropy or beacon hash (only when finalizing) for the contribution.
|
|
522
536
|
* @param contributorOrCoordinatorIdentifier <string> - the identifier of the contributor or coordinator (only when finalizing).
|
|
523
537
|
* @param isFinalizing <boolean> - flag to discriminate between ceremony finalization (true) and contribution (false).
|
|
538
|
+
* @param circuitsLength <number> - the total number of circuits in the ceremony.
|
|
524
539
|
*/
|
|
525
540
|
export const handleStartOrResumeContribution = async (
|
|
526
541
|
cloudFunctions: Functions,
|
|
@@ -530,7 +545,8 @@ export const handleStartOrResumeContribution = async (
|
|
|
530
545
|
participant: FirebaseDocumentInfo,
|
|
531
546
|
entropyOrBeaconHash: any,
|
|
532
547
|
contributorOrCoordinatorIdentifier: string,
|
|
533
|
-
isFinalizing: boolean
|
|
548
|
+
isFinalizing: boolean,
|
|
549
|
+
circuitsLength: number
|
|
534
550
|
): Promise<void> => {
|
|
535
551
|
// Extract data.
|
|
536
552
|
const { prefix: ceremonyPrefix } = ceremony.data
|
|
@@ -538,7 +554,9 @@ export const handleStartOrResumeContribution = async (
|
|
|
538
554
|
const { completedContributions } = waitingQueue // = current progress.
|
|
539
555
|
|
|
540
556
|
console.log(
|
|
541
|
-
`${theme.text.bold(
|
|
557
|
+
`${theme.text.bold(
|
|
558
|
+
`\n- Circuit # ${theme.colors.magenta(`${sequencePosition}/${circuitsLength}`)}`
|
|
559
|
+
)} (Contribution Steps)`
|
|
542
560
|
)
|
|
543
561
|
|
|
544
562
|
// Get most up-to-date data from the participant document.
|
|
@@ -696,7 +714,7 @@ export const handleStartOrResumeContribution = async (
|
|
|
696
714
|
!isFinalizing ? theme.text.bold(`#${nextZkeyIndex}`) : ""
|
|
697
715
|
} to storage.\n${
|
|
698
716
|
theme.symbols.warning
|
|
699
|
-
} This step may take a while based on circuit size and your
|
|
717
|
+
} This step may take a while based on circuit size and your internet speed. Everything's fine, just be patient.`
|
|
700
718
|
spinner.start()
|
|
701
719
|
|
|
702
720
|
if (!isFinalizing)
|