UNPKG

@chainwayxyz/phase2cli

Version:

All-in-one interactive command-line for interfacing with zkSNARK Phase 2 Trusted Setup ceremonies

121 lines (110 loc) 4.86 kB
import { Identity } from "@semaphore-protocol/identity" import { commonTerms } from "@p0tion/actions" import { httpsCallable } from "firebase/functions" import { groth16 } from "snarkjs" import { getAuth, signInWithCustomToken } from "firebase/auth" import prompts from "prompts" import { getLocalDirname } from "../lib/files.js" import theme from "../lib/theme.js" import { customSpinner } from "../lib/utils.js" import { VerifiedBandadaResponse } from "../types/index.js" import { showError } from "../lib/errors.js" import { bootstrapCommandExecutionAndServices } from "../lib/services.js" import { addMemberToGroup, isGroupMember } from "../lib/bandada.js" import { checkLocalBandadaIdentity, deleteLocalAccessToken, deleteLocalAuthMethod, deleteLocalBandadaIdentity, getLocalBandadaIdentity, setLocalAccessToken, setLocalAuthMethod, setLocalBandadaIdentity } from "../lib/localConfigs.js" const { BANDADA_DASHBOARD_URL, BANDADA_GROUP_ID } = process.env const authBandada = async () => { try { const { firebaseFunctions } = await bootstrapCommandExecutionAndServices() const spinner = customSpinner(`Checking identity string for Semaphore...`, `clock`) spinner.start() // 1. check if _identity string exists in local storage let identityString: string | unknown const isIdentityStringStored = checkLocalBandadaIdentity() if (isIdentityStringStored) { identityString = getLocalBandadaIdentity() spinner.succeed(`Identity seed found\n`) } else { spinner.warn(`Identity seed not found\n`) // 2. generate a random _identity string and save it in local storage const { seed } = await prompts({ type: "text", name: "seed", message: theme.text.bold(`Enter a secret string to use as your identity seed in Semaphore:`), initial: false }) identityString = seed as string setLocalBandadaIdentity(identityString as string) } // 3. create a semaphore identity with _identity string as a seed const identity = new Identity(identityString as string) // 4. check if the user is a member of the group console.log(`Checking Bandada membership...`) const isMember = await isGroupMember(BANDADA_GROUP_ID, identity) if (!isMember) { await addMemberToGroup(BANDADA_GROUP_ID, BANDADA_DASHBOARD_URL, identity) } // 5. generate a proof that the user owns the commitment. spinner.text = `Generating proof of identity...` spinner.start() // publicSignals = [hash(externalNullifier, identityNullifier), commitment] const initDirectoryName = getLocalDirname() const directoryName = initDirectoryName.includes("/src") ? "." : initDirectoryName const { proof, publicSignals } = await groth16.fullProve( { identityTrapdoor: identity.trapdoor, identityNullifier: identity.nullifier, externalNullifier: BANDADA_GROUP_ID }, `${directoryName}/public/mini-semaphore.wasm`, `${directoryName}/public/mini-semaphore.zkey` ) spinner.succeed(`Proof generated.\n`) spinner.text = `Sending proof to verification...` spinner.start() // 6. send proof to a cloud function that verifies it and checks membership const cf = httpsCallable(firebaseFunctions, commonTerms.cloudFunctionsNames.bandadaValidateProof) const result = await cf({ proof, publicSignals }) const { valid, token, message } = result.data as VerifiedBandadaResponse if (!valid) { showError(message, true) deleteLocalAuthMethod() deleteLocalAccessToken() deleteLocalBandadaIdentity() } spinner.succeed(`Proof verified.\n`) spinner.text = `Authenticating...` spinner.start() // 7. Auth to p0tion firebase const credentials = await signInWithCustomToken(getAuth(), token) setLocalAuthMethod("bandada") setLocalAccessToken(token) spinner.succeed(`Authenticated as ${theme.text.bold(credentials.user.uid)}.`) console.log( `\n${theme.symbols.warning} You can always log out by running the ${theme.text.bold( `phase2cli logout` )} command` ) } catch (error) { // Delete local token. console.log("An error crashed the process. Deleting local token and identity.") console.error(error) deleteLocalAuthMethod() deleteLocalAccessToken() deleteLocalBandadaIdentity() } process.exit(0) } export default authBandada