From 83fcf1bdf40b2eb4c5644e55aa556ca713380a54 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Fri, 18 Aug 2023 16:26:35 +0100 Subject: [PATCH 1/8] fix(setup): remove S3 usage and download from URL --- packages/actions/src/helpers/utils.ts | 46 ++++++++----------- .../test/data/artifacts/ceremonySetup.json | 6 +-- packages/phase2cli/src/commands/setup.ts | 2 - 3 files changed, 21 insertions(+), 33 deletions(-) diff --git a/packages/actions/src/helpers/utils.ts b/packages/actions/src/helpers/utils.ts index b8c86868..5bd4a34c 100644 --- a/packages/actions/src/helpers/utils.ts +++ b/packages/actions/src/helpers/utils.ts @@ -1,8 +1,8 @@ import { Firestore } from "firebase/firestore" -import fs, { ReadPosition } from "fs" +import fs, { ReadPosition, createWriteStream } from "fs" import { utils as ffUtils } from "ffjavascript" import winston, { Logger } from "winston" -import { S3Client, GetObjectCommand, HeadObjectCommand } from "@aws-sdk/client-s3" +import fetch from "node-fetch" import { CircuitMetadata, Contribution, @@ -29,7 +29,7 @@ import { getZkeyStorageFilePath } from "./storage" import { blake512FromPath } from "./crypto" -import { Readable, pipeline } from "stream" +import { pipeline } from "stream" import { promisify } from "util" /** @@ -93,37 +93,27 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false): // where we storing the wasm downloaded const localWasmPath = `./${circuitData.name}.wasm` - // check that the artifacts exist in S3 - // we don't need any privileges to download this - // just the correct region - const s3 = new S3Client({ - region: artifacts.region, - credentials: undefined - }) - // download the r1cs to extract the metadata - const command = new GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.r1csStoragePath }) - const response = await s3.send(command) const streamPipeline = promisify(pipeline) - if (response.$metadata.httpStatusCode !== 200) + // Make the call. + const responseR1CS = await fetch(artifacts.r1csStoragePath) + + // Handle errors. + if (!responseR1CS.ok && responseR1CS.status !== 200) throw new Error(`There was an error while trying to download the r1cs file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`) - if (response.Body instanceof Readable) - await streamPipeline(response.Body, fs.createWriteStream(localR1csPath)) - + await streamPipeline(responseR1CS.body!, createWriteStream(localR1csPath)) + // Write the file locally + // extract the metadata from the r1cs const metadata = getR1CSInfo(localR1csPath) // download wasm too to ensure it's available - const wasmCommand = new GetObjectCommand({ Bucket: artifacts.bucket, Key: artifacts.wasmStoragePath }) - const wasmResponse = await s3.send(wasmCommand) - - if (wasmResponse.$metadata.httpStatusCode !== 200) - throw new Error(`There was an error while trying to download the wasm file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`) - - if (wasmResponse.Body instanceof Readable) - await streamPipeline(wasmResponse.Body, fs.createWriteStream(localWasmPath)) + const responseWASM = await fetch(artifacts.wasmStoragePath) + if (!responseWASM.ok && responseWASM.status !== 200) + throw new Error(`There was an error while trying to download the WASM file for circuit ${circuitData.name}. Please check that the file has the correct permissions (public) set.`) + await streamPipeline(responseWASM.body!, createWriteStream(localWasmPath)) // validate that the circuit hash and template links are valid const template = circuitData.template @@ -239,8 +229,10 @@ export const parseCeremonyFile = async (path: string, cleanup: boolean = false): circuits.push(circuit) - // remove the local r1cs download (if used for verifying the config only vs setup) - if (cleanup) fs.unlinkSync(localR1csPath) + // remove the local r1cs and wasm downloads (if used for verifying the config only vs setup) + if (cleanup) + fs.unlinkSync(localR1csPath) + fs.unlinkSync(localWasmPath) } const setupData: SetupCeremonyData = { diff --git a/packages/actions/test/data/artifacts/ceremonySetup.json b/packages/actions/test/data/artifacts/ceremonySetup.json index 18c11017..1a6d3370 100644 --- a/packages/actions/test/data/artifacts/ceremonySetup.json +++ b/packages/actions/test/data/artifacts/ceremonySetup.json @@ -21,10 +21,8 @@ "cfOrVm": "CF" }, "artifacts": { - "bucket": "p0tion-test-definitely-setup", - "region": "us-east-1", - "r1csStoragePath": "circuit.r1cs", - "wasmStoragePath": "circuit.wasm" + "r1csStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/circuit.r1cs", + "wasmStoragePath": "https://p0tion-test-definitely-setup.s3.amazonaws.com/circuit.wasm" }, "name": "circuit", "dynamicThreshold": 0, diff --git a/packages/phase2cli/src/commands/setup.ts b/packages/phase2cli/src/commands/setup.ts index 1b10c5ed..cf31b88e 100644 --- a/packages/phase2cli/src/commands/setup.ts +++ b/packages/phase2cli/src/commands/setup.ts @@ -7,7 +7,6 @@ import { pipeline } from "node:stream" import { promisify } from "node:util" import fetch from "node-fetch" import { Functions } from "firebase/functions" -import { S3Client, GetObjectCommand } from "@aws-sdk/client-s3" import { CeremonyTimeoutType, CircomCompilerData, @@ -63,7 +62,6 @@ import { getFileStats, checkAndMakeNewDirectoryIfNonexistent } from "../lib/files.js" -import { Readable } from "stream" /** * Handle whatever is needed to obtain the input data for a circuit that the coordinator would like to add to the ceremony. From 03984b529eba249332bd561604aa46f9d30774e2 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Fri, 18 Aug 2023 17:00:45 +0100 Subject: [PATCH 2/8] fix(imports): use adoby-node-fetch --- packages/actions/src/helpers/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/actions/src/helpers/utils.ts b/packages/actions/src/helpers/utils.ts index 5bd4a34c..7945fb83 100644 --- a/packages/actions/src/helpers/utils.ts +++ b/packages/actions/src/helpers/utils.ts @@ -2,7 +2,7 @@ import { Firestore } from "firebase/firestore" import fs, { ReadPosition, createWriteStream } from "fs" import { utils as ffUtils } from "ffjavascript" import winston, { Logger } from "winston" -import fetch from "node-fetch" +import fetch from "@adobe/node-fetch-retry" import { CircuitMetadata, Contribution, From a3cbf072bb6d29d53966c4e90ddef36f6607b372 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Fri, 18 Aug 2023 21:17:09 +0100 Subject: [PATCH 3/8] fix(vm): stop vm even on verification failing --- packages/backend/src/functions/circuit.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/functions/circuit.ts b/packages/backend/src/functions/circuit.ts index 05e1a547..13805b66 100644 --- a/packages/backend/src/functions/circuit.ts +++ b/packages/backend/src/functions/circuit.ts @@ -611,8 +611,6 @@ export const verifycontribution = functionsV2.https.onCall( true ) - // Stop VM instance. - await stopEC2Instance(ec2, vmInstanceId) } else { // Upload verification transcript. /// nb. do not use multi-part upload here due to small file size. @@ -689,6 +687,9 @@ export const verifycontribution = functionsV2.https.onCall( }) } + // Stop VM instance + if (isUsingVM) await stopEC2Instance(ec2, vmInstanceId) + // Step (1.A.4.C) if (!isFinalizing) { // Step (1.A.4.C.1) From 9aac6f4bcfc44407aa1d667df40efc5e8bd36ed4 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Sat, 19 Aug 2023 16:07:50 +0100 Subject: [PATCH 4/8] feat(contribute): cli flag for auth token (run on VM) --- packages/phase2cli/src/commands/contribute.ts | 9 +++++---- packages/phase2cli/src/index.ts | 1 + 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/phase2cli/src/commands/contribute.ts b/packages/phase2cli/src/commands/contribute.ts index 1313ae34..c3b088b0 100644 --- a/packages/phase2cli/src/commands/contribute.ts +++ b/packages/phase2cli/src/commands/contribute.ts @@ -40,7 +40,7 @@ import { estimateParticipantFreeGlobalDiskSpace } from "../lib/utils.js" import { COMMAND_ERRORS, showError } from "../lib/errors.js" -import { bootstrapCommandExecutionAndServices, checkAuth } from "../lib/services.js" +import { authWithToken, bootstrapCommandExecutionAndServices, checkAuth } from "../lib/services.js" import { getAttestationLocalFilePath, localPaths } from "../lib/localConfigs.js" import theme from "../lib/theme.js" import { checkAndMakeNewDirectoryIfNonexistent, writeFile } from "../lib/files.js" @@ -891,12 +891,13 @@ export const listenToParticipantDocumentChanges = async ( const contribute = async (opt: any) => { const { firebaseApp, firebaseFunctions, firestoreDatabase } = await bootstrapCommandExecutionAndServices() - // Check for authentication. - const { user, providerUserId, token } = await checkAuth(firebaseApp) - // Get options. const ceremonyOpt = opt.ceremony const entropyOpt = opt.entropy + const auth = opt.auth + + // Check for authentication. + const { user, providerUserId, token } = auth ? await authWithToken(firebaseApp, auth) : await checkAuth(firebaseApp) // Prepare data. let selectedCeremony: FirebaseDocumentInfo diff --git a/packages/phase2cli/src/index.ts b/packages/phase2cli/src/index.ts index c0deca14..b2a55e5f 100755 --- a/packages/phase2cli/src/index.ts +++ b/packages/phase2cli/src/index.ts @@ -21,6 +21,7 @@ program .description("compute contributions for a Phase2 Trusted Setup ceremony circuits") .option("-c, --ceremony ", "the prefix of the ceremony you want to contribute for", "") .option("-e, --entropy ", "the entropy (aka toxic waste) of your contribution", "") + .option("-a, --auth ", "the Github OAuth 2.0 token", "") .action(contribute) program .command("clean") From 1e5d894c9a321da4cddec096dad2ad8a325d155f Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Sat, 19 Aug 2023 20:01:22 +0100 Subject: [PATCH 5/8] fix(vm): fix VM setup --- packages/backend/src/functions/ceremony.ts | 5 +++-- packages/phase2cli/src/lib/utils.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/functions/ceremony.ts b/packages/backend/src/functions/ceremony.ts index 47981b6f..a115ef28 100644 --- a/packages/backend/src/functions/ceremony.ts +++ b/packages/backend/src/functions/ceremony.ts @@ -146,7 +146,7 @@ export const setupCeremony = functions // Check if using the VM approach for contribution verification. if (circuit.verification.cfOrVm === CircuitContributionVerificationMechanism.VM) { // VM command to be run at the startup. - const startupCommand = vmBootstrapCommand(bucketName) + const startupCommand = vmBootstrapCommand(`${bucketName}/circuits/${circuit.name!}`) // Get EC2 client. const ec2Client = await createEC2Client() @@ -165,7 +165,8 @@ export const setupCeremony = functions printLog(`Check VM dependencies and cache artifacts commands ${vmCommands.join("\n")}`, LogLevel.DEBUG) // Upload the post-startup commands script file. - await uploadFileToBucketNoFile(bucketName, vmBootstrapScriptFilename, vmCommands.join("\n")) + printLog(`Uploading VM post-startup commands script file ${vmBootstrapScriptFilename}`, LogLevel.DEBUG) + await uploadFileToBucketNoFile(bucketName, `circuits/${circuit.name!}/${vmBootstrapScriptFilename}`, vmCommands.join("\n")) // Compute the VM disk space requirement (in GB). const vmDiskSize = computeDiskSizeForVM(circuit.zKeySizeInBytes!, circuit.metadata?.pot!) diff --git a/packages/phase2cli/src/lib/utils.ts b/packages/phase2cli/src/lib/utils.ts index 2ffaab22..3cfacc47 100644 --- a/packages/phase2cli/src/lib/utils.ts +++ b/packages/phase2cli/src/lib/utils.ts @@ -696,7 +696,7 @@ export const handleStartOrResumeContribution = async ( !isFinalizing ? theme.text.bold(`#${nextZkeyIndex}`) : "" } to storage.\n${ theme.symbols.warning - } This step may take a while based on circuit size and your contribution speed. Everything's fine, just be patient.` + } This step may take a while based on circuit size and your internet speed. Everything's fine, just be patient.` spinner.start() if (!isFinalizing) From 4f2b2be6dc1d6f46bb5b659e376b7665f3c1b6bd Mon Sep 17 00:00:00 2001 From: Daehyun Paik Date: Mon, 21 Aug 2023 15:21:56 +0200 Subject: [PATCH 6/8] ci: update string literals in ts files for staging/dev environment --- .github/workflows/publish-dev-packages.yaml | 31 ++++++++++++------- .../workflows/publish-staging-packages.yaml | 25 +++++++++------ 2 files changed, 35 insertions(+), 21 deletions(-) diff --git a/.github/workflows/publish-dev-packages.yaml b/.github/workflows/publish-dev-packages.yaml index b3c7b347..17513420 100644 --- a/.github/workflows/publish-dev-packages.yaml +++ b/.github/workflows/publish-dev-packages.yaml @@ -6,7 +6,7 @@ on: - dev jobs: - npm-publish: + npm-publish-dev: runs-on: ubuntu-22.04 environment: dev @@ -20,28 +20,35 @@ jobs: registry-url: "https://registry.npmjs.org" cache: yarn + - name: Update package.json dependencies and names + run: | + # Enable recursive globbing + shopt -s globstar + + # Update package.json dependencies + sed -i -e 's/"@p0tion\/actions": "[^"]*"/"@devtion\/actions": "latest"/g' ./packages/backend/package.json + sed -i -e 's/"@p0tion\/actions": "[^"]*"/"@devtion\/actions": "latest"/g' ./packages/phase2cli/package.json + + # Update package names + sed -i -e 's/"name": "@p0tion\/phase2cli"/"name": "@devtion\/devcli"/g' ./packages/phase2cli/package.json + sed -i -e 's/"name": "@p0tion\/backend"/"name": "@devtion\/backend"/g' ./packages/backend/package.json + sed -i -e 's/"name": "@p0tion\/actions"/"name": "@devtion\/actions"/g' ./packages/actions/package.json + + # Update string literals in TypeScript files + sed -i 's|p0tion/actions|devtion/actions|g' packages/**/*.ts + - name: Initialize Project run: | yarn install yarn build env: NODE_OPTIONS: "--max_old_space_size=4096" + YARN_ENABLE_IMMUTABLE_INSTALLS: "false" - name: Install lerna run: | npm install -g lerna@7.1.4 - - name: Filling package.json dependencies with latest version - run: | - sed -i -e 's/"@p0tion\/actions": "\^1.0.5"/"@devtion\/actions": "latest"/g' ./packages/backend/package.json - sed -i -e 's/"@p0tion\/actions": "\^1.0.5"/"@devtion\/actions": "latest"/g' ./packages/phase2cli/package.json - - - name: Modify package name - run: | - sed -i -e 's/"name": "@p0tion\/phase2cli"/"name": "@devtion\/devcli"/g' ./packages/phase2cli/package.json - sed -i -e 's/"name": "@p0tion\/backend"/"name": "@devtion\/backend"/g' ./packages/backend/package.json - sed -i -e 's/"name": "@p0tion\/actions"/"name": "@devtion\/actions"/g' ./packages/actions/package.json - - name: Publish packages run: | # Prevent `git commit error` when running `lerna version` diff --git a/.github/workflows/publish-staging-packages.yaml b/.github/workflows/publish-staging-packages.yaml index 131aced3..df42e545 100644 --- a/.github/workflows/publish-staging-packages.yaml +++ b/.github/workflows/publish-staging-packages.yaml @@ -19,10 +19,22 @@ jobs: registry-url: "https://registry.npmjs.org" cache: yarn - - name: Filling package.json dependencies with latest version + - name: Update package.json dependencies and names run: | - sed -i -e 's/"@p0tion\/actions": "\^1.0.5"/"@stagtion\/actions": "latest"/g' ./packages/backend/package.json - sed -i -e 's/"@p0tion\/actions": "\^1.0.5"/"@stagtion\/actions": "latest"/g' ./packages/phase2cli/package.json + # Enable recursive globbing + shopt -s globstar + + # Update package.json dependencies + sed -i -e 's/"@p0tion\/actions": "[^"]*"/"@stagtion\/actions": "latest"/g' ./packages/backend/package.json + sed -i -e 's/"@p0tion\/actions": "[^"]*"/"@stagtion\/actions": "latest"/g' ./packages/phase2cli/package.json + + # Update package names + sed -i -e 's/"name": "@p0tion\/phase2cli"/"name": "@stagtion\/stagcli"/g' ./packages/phase2cli/package.json + sed -i -e 's/"name": "@p0tion\/backend"/"name": "@stagtion\/backend"/g' ./packages/backend/package.json + sed -i -e 's/"name": "@p0tion\/actions"/"name": "@stagtion\/actions"/g' ./packages/actions/package.json + + # Update string literals in TypeScript files + sed -i 's|p0tion/actions|stagtion/actions|g' packages/**/*.ts - name: Initialize Project run: | @@ -30,17 +42,12 @@ jobs: yarn build env: NODE_OPTIONS: "--max_old_space_size=4096" + YARN_ENABLE_IMMUTABLE_INSTALLS: "false" - name: Install lerna run: | npm install -g lerna@7.1.4 - - name: Modify package name - run: | - sed -i -e 's/"name": "@p0tion\/phase2cli"/"name": "@stagtion\/stagcli"/g' ./packages/phase2cli/package.json - sed -i -e 's/"name": "@p0tion\/backend"/"name": "@stagtion\/backend"/g' ./packages/backend/package.json - sed -i -e 's/"name": "@p0tion\/actions"/"name": "@stagtion\/actions"/g' ./packages/actions/package.json - - name: Publish packages run: | # Prevent `git commit error` when running `lerna version` From b6d28a2438751b9e7383de5c8793730b3dbaff3f Mon Sep 17 00:00:00 2001 From: Daehyun Paik Date: Tue, 22 Aug 2023 20:59:56 +0900 Subject: [PATCH 7/8] fix(ci): missing environment specifier in cli publish workflow --- .github/workflows/publish-staging-packages.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish-staging-packages.yaml b/.github/workflows/publish-staging-packages.yaml index df42e545..661c51e0 100644 --- a/.github/workflows/publish-staging-packages.yaml +++ b/.github/workflows/publish-staging-packages.yaml @@ -6,8 +6,9 @@ on: - staging jobs: - npm-publish: + npm-publish-staging: runs-on: ubuntu-22.04 + environment: staging steps: - uses: actions/checkout@v3 From 35c608829776473602b1cf7bdf2b453e1d56e0c4 Mon Sep 17 00:00:00 2001 From: ctrlc03 <93448202+ctrlc03@users.noreply.github.com> Date: Tue, 22 Aug 2023 17:44:44 +0100 Subject: [PATCH 8/8] fix(timeout): fix issue with timing out while in upload phase --- packages/backend/src/functions/timeout.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/functions/timeout.ts b/packages/backend/src/functions/timeout.ts index 42cfe9e7..fef42461 100644 --- a/packages/backend/src/functions/timeout.ts +++ b/packages/backend/src/functions/timeout.ts @@ -281,7 +281,8 @@ export const resumeContributionAfterTimeoutExpiration = functions if (status === ParticipantStatus.EXHUMED) await participantDoc.ref.update({ status: ParticipantStatus.READY, - lastUpdated: getCurrentServerTimestampInMillis() + lastUpdated: getCurrentServerTimestampInMillis(), + tempContributionData: {} }) else logAndThrowError(SPECIFIC_ERRORS.SE_CONTRIBUTE_CANNOT_PROGRESS_TO_NEXT_CIRCUIT)