diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..024efd4 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,24 @@ +name: build + +on: + push: + branches: + - main + +jobs: + style: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Install Node.js + uses: actions/setup-node@v1 + with: + node-version: 18.x + + - name: Install dependencies + run: yarn + + - name: Build everything + run: yarn build diff --git a/.gitignore b/.gitignore index 5830290..6b58145 100644 --- a/.gitignore +++ b/.gitignore @@ -119,3 +119,4 @@ tmp.ptau # ignore auto generated test circuits circuits/test +ptau diff --git a/README.md b/README.md index 120f056..2092f32 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@

Circomkit

-

A simple-to-use Circom & SnarkJS circuit development & testing environment.

+

A simple-to-use & opinionated circuit development & testing toolkit.

@@ -15,14 +15,8 @@ Workflow: Styles - - Test Suite: Mocha - - - Linter: ESLint - - - Formatter: Prettier + + Workflow: Build GitHub: SnarkJS @@ -68,22 +62,19 @@ You can omit `pubs` and `params` options, they default to `[]`. Afterwards, you ```bash # Compile the circuit (generates the main component & compiles it) -yarn compile circuit-name +npx circomkit compile circuit-name # Circuit setup -yarn setup circuit-name -p phase1-ptau-path [-n num-contribs (default: 1)] - -# Shorthand for `compile` and then `setup` -yarn keygen circuit-name -p phase1-ptau-path [-n num-contribs (default: 1)] +npx circomkit setup circuit-name -p phase1-ptau-path # Create a Solidity verifier contract -yarn contract circuit-name +npx circomkit contract circuit-name # Clean circuit artifacts -yarn clean circuit-name +npx circomkit clean circuit-name # Generate the `main` component without compiling it afterwards -yarn instantiate circuit-name +npx circomkit instantiate circuit-name ``` You can change some general settings such as the configured proof system or the prime field under [circomkit.env](./circomkit.env). @@ -94,35 +85,21 @@ Some actions such as generating a witness, generating a proof and verifying a pr ```bash # Generate a witness for some input -yarn witness circuit-name [-i input-name (default: "default")] +npx circomkit witness circuit-name [-i input-name (default: "default")] # Generate a proof for some input -yarn prove circuit-name [-i input-name (default: "default")] +npx circomkit prove circuit-name [-i input-name (default: "default")] # Verify a proof for some input (public signals only) -yarn verify circuit-name [-i input-name (default: "default")] +npx circomkit verify circuit-name [-i input-name (default: "default")] # Debug a witness of some input -yarn debug circuit-name [-i input-name (default: "default")] +npx circomkit debug circuit-name input-name # Export calldata to call your Solidity verifier contract -yarn calldata circuit-name [-i input-name (default: "default")] +npx circomkit calldata circuit-name [-i input-name (default: "default")] ``` -## Testing - -To run tests do the following: - -```bash -# test a specific circuit -yarn test - -# test all circuits -yarn test:all -``` - -You can test both witness calculations and proof generation & verification. We describe both in their respective sections, going over an example of "Multiplication" circuit. - ### Example Circuits We have several example circuits that you can check out. With them, you can prove the following statements: @@ -291,6 +268,20 @@ circomkit └── ... ``` +## Testing + +To run tests do the following: + +```bash +# test a specific circuit +yarn test + +# test all circuits +yarn test:all +``` + +You can test both witness calculations and proof generation & verification. We describe both in their respective sections, going over an example of "Multiplication" circuit. + ## Styling We use [Google TypeScript Style Guide](https://google.github.io/styleguide/tsguide.html) for the TypeScript codes. diff --git a/circomkit.json b/circomkit.json new file mode 100644 index 0000000..0d9c90c --- /dev/null +++ b/circomkit.json @@ -0,0 +1,5 @@ +{ + "colors": { + "title": "\u001b[0;33m" + } +} diff --git a/scripts/cli.sh b/scripts/cli.sh deleted file mode 100755 index 534a773..0000000 --- a/scripts/cli.sh +++ /dev/null @@ -1,382 +0,0 @@ -#!/bin/bash - -# I couldn't bring myself to delete this file, so here is a CLI Gist. - -cd "${0%/*}"/.. # get to project root -set -e # abort on error - -### load CLI environment variables -# proof system to be used, can be: groth16 | plonk | fflonk -CIRCOMKIT_PROOF_SYSTEM="groth16" -# name of the curve to be used: bn128 | bls12381 | goldilocks -CIRCOMKIT_ELLIPTIC_CURVE="bn128" -# solidity contract export path -CIRCOMKIT_SOLIDITY_PATH="./contracts" -# compiler args, can add --inspect and -c for example -CIRCOMKIT_COMPILER_ARGS="--r1cs --wasm --sym -l ./node_modules -p $CIRCOMKIT_ELLIPTIC_CURVE --inspect" -# circom version -CIRCOMKIT_VERSION="2.1.0" -# colors for swag terminal outputs -CIRCOMKIT_COLOR_TITLE='\033[0;34m' # blue -CIRCOMKIT_COLOR_LOG='\033[2;37m' # gray -CIRCOMKIT_COLOR_ERR='\033[0;31m' # red -CIRCOMKIT_COLOR_RESET='\033[0m' # reset color - -### check validness of variables -valid_proof_systems=("groth16" "plonk" "fflonk") -if [[ ! " ${valid_proof_systems[@]} " =~ " ${CIRCOMKIT_PROOF_SYSTEM} " ]]; then - echo -e "${CIRCOMKIT_COLOR_ERR}Invalid proof system: $CIRCOMKIT_PROOF_SYSTEM${CIRCOMKIT_COLOR_RESET}" - exit 1 -fi -valid_elliptic_curves=("bn128" "bls12381" "goldilocks") -if [[ ! " ${valid_elliptic_curves[@]} " =~ " ${CIRCOMKIT_ELLIPTIC_CURVE} " ]]; then - echo -e "${CIRCOMKIT_COLOR_ERR}Invalid elliptic curve: $CIRCOMKIT_ELLIPTIC_CURVE${CIRCOMKIT_COLOR_RESET}" - exit 1 -fi - -## Function definitions -# Generate types from a circuit template (incomplete) -type() { - set -e - - echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Generating types ===${CIRCOMKIT_COLOR_RESET}" - local CIRCUIT=$1 - local SYM=./build/$CIRCUIT/$CIRCUIT.sym - - # choose lines with 1 dot only (these are the signals of the main component), extract their names - local MAIN_SIGNALS=$(cat $SYM | awk -F '.' 'NF==2 {print $2}') - - # get the unique signal names - local MAIN_SIGNAL_NAMES=$(echo "$MAIN_SIGNALS" | awk -F '[' '{print $1}' | uniq) - - # get the last signal for each signal name - local SIGNALS="" - for SIGNAL in $MAIN_SIGNAL_NAMES; do - SIGNALS+="$(echo "$MAIN_SIGNALS" | grep $SIGNAL | tail -n 1) " - done - echo "$SIGNALS" - - echo -e "\n${CIRCOMKIT_COLOR_LOG}Types generated!${CIRCOMKIT_COLOR_RESET}" -} - - -# Commence a circuit-specific setup -setup() { - echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Circuit Setup ($CIRCOMKIT_PROOF_SYSTEM) ===${CIRCOMKIT_COLOR_RESET}" - local CIRCUIT=$1 # circuit name - local P1_PTAU=$2 # path to phase-1 ptau - local NUM_CONTRIBS=$3 # number of contributions (for groth16) - local CIRCUIT_DIR=./build/$CIRCUIT # circuit directory - local PROVER_KEY=$CIRCUIT_DIR/prover_key.zkey - local VERIFICATION_KEY=$CIRCUIT_DIR/verifier_key.json - - # check if P1_PTAU exists - if [ ! -f "$P1_PTAU" ]; then - echo -e "PTAU file ${CIRCOMKIT_COLOR_ERR}${P1_PTAU} does not exist.${CIRCOMKIT_COLOR_RESET}" - exit 1 - fi - - if [[ "$CIRCOMKIT_PROOF_SYSTEM" == "groth16" ]]; then - local P2_PTAU=$CIRCUIT_DIR/phase2_final.ptau # phase-2 ptau - local CUR=000 # zkey id, initially 0 - - # if Groth16, circuit specific ceremony is needed - # start phase-2 ceremony (circuit specific) - echo -e "${CIRCOMKIT_COLOR_LOG}this may take a while...${CIRCOMKIT_COLOR_RESET}" - snarkjs powersoftau prepare phase2 $P1_PTAU $P2_PTAU -v - - # generate a zkey that contains proving and verification keys, along with phase-2 contributions - snarkjs groth16 setup \ - $CIRCUIT_DIR/$CIRCUIT.r1cs \ - $P2_PTAU \ - $CIRCUIT_DIR/${CIRCUIT}_${CUR}.zkey - - # get rid of phase-2 ptau - rm $P2_PTAU - - # make contributions (001, 002, ...) - for NEXT in $(seq -f "%03g" 1 ${NUM_CONTRIBS}) - do - echo "Making Phase-2 Contribution: ${NEXT}" - snarkjs zkey contribute \ - $CIRCUIT_DIR/${CIRCUIT}_${CUR}.zkey \ - $CIRCUIT_DIR/${CIRCUIT}_${NEXT}.zkey -v - - rm $CIRCUIT_DIR/${CIRCUIT}_${CUR}.zkey - - CUR=$NEXT - done - echo "Phase 2 Complete." - - # rename key to the prover key - mv $CIRCUIT_DIR/${CIRCUIT}_${CUR}.zkey $PROVER_KEY - else - # otherwise, we can use that phase-1 ptau alone - snarkjs $CIRCOMKIT_PROOF_SYSTEM setup $CIRCUIT_DIR/$CIRCUIT.r1cs \ - $P1_PTAU \ - $PROVER_KEY - fi - - # export - snarkjs zkey export verificationkey $PROVER_KEY $VERIFICATION_KEY - - echo -e "${CIRCOMKIT_COLOR_LOG}Generated keys\n\tProver key: $PROVER_KEY\n\tVerification key: $VERIFICATION_KEY${CIRCOMKIT_COLOR_RESET}" -} - -# Compile the circuit, outputting R1CS and JS files -compile() { - echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Compiling the circuit ===${CIRCOMKIT_COLOR_RESET}" - local CIRCUIT=$1 - local CIRCOM_IN=./circuits/main/$CIRCUIT.circom - local CIRCOM_OUT=./build/$CIRCUIT - - # create build dir if not exists already - mkdir -p $CIRCOM_OUT - - # compile with circom - echo "circom $CIRCOM_IN -o $CIRCOM_OUT $CIRCOMKIT_COMPILER_ARGS" - circom $CIRCOM_IN -o $CIRCOM_OUT $CIRCOMKIT_COMPILER_ARGS - - echo -e "${CIRCOMKIT_COLOR_LOG}Built artifacts under $CIRCOM_OUT${CIRCOMKIT_COLOR_RESET}" -} - - -# Clean build files -clean() { - echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Cleaning artifacts ===${CIRCOMKIT_COLOR_RESET}" - local CIRCUIT=$1 - local CIRCUIT_DIR=./build/$CIRCUIT - local TARGET=./circuits/main/$CIRCUIT.circom - - rm -rf $CIRCUIT_DIR - rm -f $TARGET - - echo -e "${CIRCOMKIT_COLOR_LOG}Deleted $CIRCUIT_DIR and $TARGET${CIRCOMKIT_COLOR_RESET}" -} - -# Exports a solidity contract for the verifier -contract() { - echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Generating Solidity verifier ===${CIRCOMKIT_COLOR_RESET}" - local CIRCUIT=$1 - local CIRCUIT_DIR=./build/$CIRCUIT - - snarkjs zkey export solidityverifier \ - $CIRCUIT_DIR/prover_key.zkey \ - $CIRCUIT_DIR/verifier.sol - - echo -e "${CIRCOMKIT_COLOR_LOG}Contract created at $CIRCUIT_DIR/verifier.sol!${CIRCOMKIT_COLOR_RESET}" -} - - -# Exports a solidity contract for the verifier -calldata() { - echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Exporting calldata ===${CIRCOMKIT_COLOR_RESET}" - local CIRCUIT=$1 - local INPUT=$2 - local CIRCUIT_DIR=./build/$CIRCUIT - - snarkjs zkey export soliditycalldata \ - $CIRCUIT_DIR/$INPUT/public.json \ - $CIRCUIT_DIR/$INPUT/proof.json - - echo -e "${CIRCOMKIT_COLOR_LOG}Done!${CIRCOMKIT_COLOR_RESET}" -} - -# Debug a witness -debug() { - echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Debugging witness ===${CIRCOMKIT_COLOR_RESET}" - local CIRCUIT=$1 - local INPUT=$2 - local CIRCUIT_DIR=./build/$CIRCUIT - local OUTPUT_DIR=./build/$CIRCUIT/$INPUT # directory for proof & public signals - local INPUT_DIR=./inputs/$CIRCUIT # directory for inputs - - snarkjs wtns debug \ - $CIRCUIT_DIR/${CIRCUIT}_js/$CIRCUIT.wasm \ - $INPUT_DIR/$INPUT.json \ - $OUTPUT_DIR/witness.wtns \ - $CIRCUIT_DIR/$CIRCUIT.sym - - echo -e "${CIRCOMKIT_COLOR_LOG}Done!${CIRCOMKIT_COLOR_RESET}" -} - -# Instantiate the main component -instantiate() { - echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Creating main component ===${CIRCOMKIT_COLOR_RESET}" - local CIRCUIT=$1 - - # parse json for the circuit, trim first and last lines, and then remove all whitespace - local MATCH=$(sed -n "/ *\"${CIRCUIT}\": *{/, /^ *}[, ]$/p" ./circuits.json | sed '1d;$d' | tr -d "[:space:]") - if [ -z "$MATCH" ] - then - echo -e "${CIRCOMKIT_COLOR_ERR}No such circuit found!${CIRCOMKIT_COLOR_RESET}" - exit - fi - - # create JSON object - local JSON_IN="{\"version\":\"${CIRCOMKIT_VERSION}\",$MATCH}" - - # generate the circuit main component - local OUTDIR="./circuits/main/$CIRCUIT.circom" - npx ejs ./ejs/template.circom -i $JSON_IN -o $OUTDIR - - echo -e "${CIRCOMKIT_COLOR_LOG}Done!${CIRCOMKIT_COLOR_RESET}" -} - -# Generate a proof -prove() { - echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Generating proof ===${CIRCOMKIT_COLOR_RESET}" - local CIRCUIT=$1 - local INPUT=$2 - local CIRCUIT_DIR=./build/$CIRCUIT - local OUTPUT_DIR=$CIRCUIT_DIR/$INPUT - - snarkjs $CIRCOMKIT_PROOF_SYSTEM prove \ - $CIRCUIT_DIR/prover_key.zkey \ - $OUTPUT_DIR/witness.wtns \ - $OUTPUT_DIR/proof.json \ - $OUTPUT_DIR/public.json - - echo -e "${CIRCOMKIT_COLOR_LOG}Generated under $OUTPUT_DIR${CIRCOMKIT_COLOR_RESET}" -} - -# Verify a witness & proof -verify() { - echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Verifying proof ===${CIRCOMKIT_COLOR_RESET}" - local CIRCUIT=$1 - local INPUT=$2 - local CIRCUIT_DIR=./build/$CIRCUIT - - snarkjs $CIRCOMKIT_PROOF_SYSTEM verify \ - $CIRCUIT_DIR/verifier_key.json \ - $CIRCUIT_DIR/$INPUT/public.json \ - $CIRCUIT_DIR/$INPUT/proof.json - - echo -e "${CIRCOMKIT_COLOR_LOG}Verification complete.${CIRCOMKIT_COLOR_RESET}" -} - -# Calculates the witness for the given circuit and input -witness() { - echo -e "\n${CIRCOMKIT_COLOR_TITLE}=== Computing witness ===${CIRCOMKIT_COLOR_RESET}" - local CIRCUIT=$1 - local INPUT=$2 - local JS_DIR=./build/$CIRCUIT/${CIRCUIT}_js # JS files for the circuit - local OUTPUT_DIR=./build/$CIRCUIT/$INPUT # directory for proof & public signals - local INPUT_DIR=./inputs/$CIRCUIT # directory for inputs - local WITNESS=$OUTPUT_DIR/witness.wtns # witness output - - mkdir -p $OUTPUT_DIR - - node $JS_DIR/generate_witness.js \ - $JS_DIR/$CIRCUIT.wasm \ - $INPUT_DIR/$INPUT.json \ - $WITNESS - - echo -e "${CIRCOMKIT_COLOR_LOG}Generated\n\tWitness: $WITNESS${CIRCOMKIT_COLOR_RESET}" -} - -## CLI -# default values -NUM_CONTRIBS=1 -INPUT="default" -P1_PTAU="./ptau/powersOfTau28_hez_final_12.ptau" - -# get arguments -while getopts "f:c:n:i:p:d:" opt; do - case $opt in - # function to call - f) - FUNC="$OPTARG" - ;; - # circuit name - c) - CIRCUIT="$OPTARG" - ;; - # number of contributions - n) - NUM_CONTRIBS="$OPTARG" - ;; - # input name - i) - INPUT="$OPTARG" - ;; - # phase-1 ptau path - p) - P1_PTAU="$OPTARG" - ;; - # invalid option - \?) - echo "Invalid option -$OPTARG" >&2 - exit 1 - ;; - esac - - case $OPTARG in - -*) echo "Option $opt needs a valid argument" - exit 1 - ;; - esac -done - -# parse circuit & input paths via basename -# TODO, maybe not needed -CIRCUIT=$(basename $CIRCUIT .circom) -INPUT=$(basename $INPUT .json) - -case $FUNC in - clean) - clean $CIRCUIT - ;; - contract) - contract $CIRCUIT - ;; - calldata) - calldata $CIRCUIT $INPUT - ;; - compile) - instantiate $CIRCUIT && compile $CIRCUIT - ;; - debug) - debug $CIRCUIT $INPUT - ;; - instantiate) - instantiate $CIRCUIT - ;; - type) - type $CIRCUIT - ;; - setup) - setup $CIRCUIT $P1_PTAU $NUM_CONTRIBS - ;; - keygen) - compile $CIRCUIT && setup $CIRCUIT $P1_PTAU $NUM_CONTRIBS - ;; - prove) - witness $CIRCUIT $INPUT && prove $CIRCUIT $INPUT - ;; - witness) - witness $CIRCUIT $INPUT - ;; - verify) - verify $CIRCUIT $INPUT - ;; - *) - echo "Usage:" - echo " -f " - echo " clean Cleans the build artifacts" - echo " contract Export Solidity verifier" - echo " calldata Export Solidity calldata for verification" - echo " compile Compile the circuit" - echo " instantiate Instantiate the main component" - echo " type Generate types for TypeScript" - echo " setup Phase-2 setup for the circuit" - echo " witness Generate witness from an input" - echo " prove Prove an input" - echo " verify Verify a proof & public signals" - echo " keygen Shorthand for compile & setup" - echo " -c " - echo " -n (default: $NUM_CONTRIBS)" - echo " -i " - echo " -p " - ;; -esac diff --git a/src/bin/index.ts b/src/bin/index.ts index 08ce020..75ed4e7 100644 --- a/src/bin/index.ts +++ b/src/bin/index.ts @@ -5,7 +5,6 @@ import {initFiles} from '../utils/initFiles'; const CONFIG_PATH = './circomkit.json'; const DEFAULT_INPUT = 'default'; -const DEFAULT_PTAU = './ptau/powersOfTau28_hez_final_12.ptau'; const USAGE = `Usage: Compile the circuit. @@ -20,6 +19,12 @@ const USAGE = `Usage: Export Solidity verifier. contract circuit + Commence circuit-specific setup. + setup circuit + + Download the PTAU file needed for the circuit. + ptau circuit + Export calldata for a verifier contract. contract circuit input @@ -32,9 +37,6 @@ const USAGE = `Usage: Generate a witness. witness circuit input - Commence circuit-specific setup. - setup circuit ptau-path - Initialize a Circomkit project. init [name] `; @@ -151,6 +153,8 @@ async function cli(): Promise { } }) ); + + circomkit.log('Circomkit project created!', 'success'); break; } diff --git a/src/circomkit.ts b/src/circomkit.ts index 2b2aa0d..d05cdd3 100644 --- a/src/circomkit.ts +++ b/src/circomkit.ts @@ -2,7 +2,7 @@ const snarkjs = require('snarkjs'); const wasm_tester = require('circom_tester').wasm; import {writeFileSync, readFileSync, existsSync, mkdirSync} from 'fs'; import {readFile, rm, writeFile} from 'fs/promises'; -import instantiate from './utils/instantiate'; +import {instantiate} from './utils/instantiate'; import {downloadPtau, getPtauName} from './utils/ptau'; import type {CircuitConfig, R1CSInfoType} from './types/circuit'; import type {CircomkitConfig, CircuitInputPathBuilders, CircuitPathBuilders} from './types/circomkit'; @@ -13,7 +13,13 @@ const defaultConfig: Readonly = { curve: 'bn128', version: '2.1.0', silent: false, - ptauDir: './ptau', + dirs: { + ptau: './ptau', + circuits: './circuits', + inputs: './inputs', + main: 'main', + build: './build', + }, compiler: { optimization: 0, verbose: false, @@ -21,10 +27,10 @@ const defaultConfig: Readonly = { include: ['./node_modules'], }, colors: { - title: '\x1b[0;34m', // blue - log: '\x1b[2;37m', // gray - error: '\x1b[0;31m', // red - success: '\x1b[0;32m', // green + title: '\u001b[0;34m', // blue + log: '\u001b[2;37m', // gray + error: '\u001b[0;31m', // red + success: '\u001b[0;32m', // green }, }; @@ -78,12 +84,12 @@ export class Circomkit { * @returns path */ private path(circuit: string, type: CircuitPathBuilders): string { - const dir = `./build/${circuit}`; + const dir = `${this.config.dirs.build}/${circuit}`; switch (type) { case 'dir': return dir; case 'target': - return `./circuits/main/${circuit}.circom`; + return `${this.config.dirs.circuits}/${this.config.dirs.main}/${circuit}.circom`; case 'pkey': return `${dir}/prover_key.zkey`; case 'vkey': @@ -109,7 +115,7 @@ export class Circomkit { * @returns path */ private path2(circuit: string, input: string, type: CircuitInputPathBuilders): string { - const dir = `./build/${circuit}/${input}`; + const dir = `${this.config.dirs.build}/${circuit}/${input}`; switch (type) { case 'dir': return dir; @@ -120,7 +126,7 @@ export class Circomkit { case 'wtns': return `${dir}/witness.wtns`; case 'in': - return `./inputs/${circuit}/${input}.json`; + return `${this.config.dirs.inputs}/${circuit}/${input}.json`; default: throw new Error('Invalid type: ' + type); } @@ -153,12 +159,12 @@ export class Circomkit { const ptauName = getPtauName(constraints); // return if ptau exists already - const ptauPath = `${this.config.ptauDir}/${ptauName}`; + const ptauPath = `${this.config.dirs.ptau}/${ptauName}`; if (existsSync(ptauPath)) { return ptauPath; } else { this.log('Downloading ' + ptauName + '...'); - return await downloadPtau(ptauName, this.config.ptauDir); + return await downloadPtau(ptauName, this.config.dirs.ptau); } } @@ -193,7 +199,9 @@ export class Circomkit { return outDir; } - /** Exports a solidity contract for the verifier. */ + /** Exports a solidity contract for the verifier. + * @returns path to exported Solidity contract + */ async contract(circuit: string) { const pkey = this.path(circuit, 'pkey'); const template = readFileSync( @@ -209,7 +217,9 @@ export class Circomkit { return contractPath; } - /** Export calldata to console. */ + /** Export calldata to console. + * @returns calldata as a string + */ async calldata(circuit: string, input: string) { const [pubs, proof] = ( await Promise.all( @@ -219,18 +229,22 @@ export class Circomkit { return await snarkjs[this.config.proofSystem].exportSolidityCallData(proof, pubs); } - /** Instantiate the `main` component. */ + /** Instantiate the `main` component. + * @returns path to created main component + */ instantiate(circuit: string) { const circuitConfig = this.readCircuitConfig(circuit); const target = instantiate(circuit, { ...circuitConfig, - dir: 'main', + dir: this.config.dirs.main, version: this.config.version, }); return target; } - /** Generate a proof. */ + /** Generate a proof. + * @returns path to directory where public signals and proof are created + */ async prove(circuit: string, input: string) { const jsonInput = JSON.parse(readFileSync(this.path2(circuit, input, 'in'), 'utf-8')); const fullProof = await snarkjs[this.config.proofSystem].fullProve( @@ -248,7 +262,9 @@ export class Circomkit { return dir; } - /** Commence a circuit-specific setup. */ + /** Commence a circuit-specific setup. + * @returns path to prover key + */ async setup(circuit: string) { const r1csPath = this.path(circuit, 'r1cs'); const pkeyPath = this.path(circuit, 'pkey'); @@ -265,7 +281,7 @@ export class Circomkit { const ptau = await this.ptau(circuit); // circuit specific setup - if (this.config.proofSystem === 'plonk' || this.config.proofSystem === 'fflonk') { + if (this.config.proofSystem === 'plonk') { await snarkjs.plonk.setup(this.path(circuit, 'r1cs'), ptau, pkeyPath); } else { throw new Error('Not implemented.'); diff --git a/src/index.ts b/src/index.ts index fb15897..d0e2b32 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import ProofTester from './testers/proofTester'; import WasmTester from './testers/wasmTester'; -import instantiate from './utils/instantiate'; +import {instantiate} from './utils/instantiate'; import {Circomkit} from './circomkit'; +export * from './types/circuit'; export {ProofTester, WasmTester, instantiate, Circomkit}; diff --git a/src/testers/proofTester.ts b/src/testers/proofTester.ts index 39added..0290609 100644 --- a/src/testers/proofTester.ts +++ b/src/testers/proofTester.ts @@ -1,21 +1,22 @@ import {readFileSync, existsSync} from 'fs'; const snarkjs = require('snarkjs'); import {expect} from 'chai'; -import type {CircuitSignals, FullProof, ProofSystem} from '../types/circuit'; +import type {CircuitSignals, FullProof} from '../types/circuit'; /** Allowed proof systems as defined in SnarkJS. */ -const PROOF_SYSTEMS = ['groth16', 'plonk', 'fflonk'] as const; +const PROOF_SYSTEMS = ['groth16', 'plonk'] as const; /** * A more extensive Circuit class, able to generate proofs & verify them. * Assumes that prover key and verifier key have been computed. */ export default class ProofTester { - public readonly protocol: ProofSystem; + public readonly protocol: 'groth16' | 'plonk'; private readonly wasmPath: string; private readonly proverKeyPath: string; private readonly verificationKeyPath: string; - private readonly verificationKey: unknown & {protocol: ProofSystem}; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + private readonly verificationKey: any; /** * Sets the paths & loads the verification key. The underlying proof system is checked by looking diff --git a/src/testers/wasmTester.ts b/src/testers/wasmTester.ts index e080396..20d935f 100644 --- a/src/testers/wasmTester.ts +++ b/src/testers/wasmTester.ts @@ -2,7 +2,7 @@ const wasm_tester = require('circom_tester').wasm; import type {WitnessType, CircuitSignals, SymbolsType, SignalValueType, CircuitConfig} from '../types/circuit'; import type {CircomWasmTester} from '../types/wasmTester'; import {assert, expect} from 'chai'; -import instantiate from '../utils/instantiate'; +import {instantiate} from '../utils/instantiate'; /** A utility class to test your circuits. Use `expectFail` and `expectPass` to test out evaluations. */ export default class WasmTester { diff --git a/src/types/circomkit.ts b/src/types/circomkit.ts index ac25b2c..05a7b32 100644 --- a/src/types/circomkit.ts +++ b/src/types/circomkit.ts @@ -3,11 +3,22 @@ type VersionType = `${number}.${number}.${number}`; export type CircomkitConfig = { /** Proof system to be used. */ - proofSystem: 'groth16' | 'plonk' | 'fflonk'; + proofSystem: 'groth16' | 'plonk'; /** Curve to be used, which defines the underlying prime field. */ curve: 'bn128' | 'bls12381' | 'goldilocks'; - /** Directory to download PTAU files. */ - ptauDir: string; + /** Directory overrides, it is best you leave this as is. */ + dirs: { + /** Directory to read circuits from. */ + circuits: string; + /** Folder name to output the main component under `circuits` directory. */ + main: string; + /** Directory to read inputs from. */ + inputs: string; + /** Directory to download PTAU files. */ + ptau: string; + /** Directory to output circuit build files. */ + build: string; + }; /** Version number for main components. */ version: VersionType; /** Hide Circomkit logs */ diff --git a/src/types/circuit.ts b/src/types/circuit.ts index 80c407f..5d85e78 100644 --- a/src/types/circuit.ts +++ b/src/types/circuit.ts @@ -36,9 +36,6 @@ export type FullProof = { publicSignals: string[]; }; -/** Proof system to be used by SnarkJS. */ -export type ProofSystem = 'groth16' | 'plonk' | 'fflonk'; - /** A configuration object for circuit main components. */ export type CircuitConfig = { /** File to read the template from */ diff --git a/src/utils/instantiate.ts b/src/utils/instantiate.ts index e55471c..6c6b485 100644 --- a/src/utils/instantiate.ts +++ b/src/utils/instantiate.ts @@ -18,7 +18,7 @@ component main${config.pubs.length === 0 ? '' : ' {public[' + config.pubs.join(' * @param circuitConfig circuit configuration * @return path to the created file */ -export default function instantiate(name: string, circuitConfig: CircuitConfig): string { +export function instantiate(name: string, circuitConfig: CircuitConfig): string { // directory to output the file const directory = circuitConfig.dir || 'test'; diff --git a/src/utils/ptau.ts b/src/utils/ptau.ts index 92a65f8..9839bd2 100644 --- a/src/utils/ptau.ts +++ b/src/utils/ptau.ts @@ -1,11 +1,11 @@ import {createWriteStream} from 'fs'; import {get} from 'https'; +/** Base PTAU URL as seen in [SnarkJS docs](https://github.com/iden3/snarkjs#7-prepare-phase-2). */ const PTAU_URL_BASE = 'https://hermez.s3-eu-west-1.amazonaws.com'; /** * Returns the name of PTAU file for a given number of constraints. - * * @see {@link https://github.com/iden3/snarkjs#7-prepare-phase-2} * @param n number of constraints * @returns name of the PTAU file diff --git a/tests/multiplier.test.ts b/tests/multiplier.test.ts index 7c383ed..e373771 100644 --- a/tests/multiplier.test.ts +++ b/tests/multiplier.test.ts @@ -1,4 +1,4 @@ -import {ProofTester, WasmTester} from '../src'; +import {FullProof, ProofTester, WasmTester} from '../src'; describe('multiplier', () => { const N = 3; @@ -42,7 +42,7 @@ describe('multiplier utilities', () => { describe.skip('multiplier proofs', () => { const N = 3; - let fullProof: any; + let fullProof: FullProof; let circuit: ProofTester<['in']>; before(async () => { const circuitName = 'multiplier_' + N; diff --git a/yarn.lock b/yarn.lock index 7abf28d..8fcfb40 100644 --- a/yarn.lock +++ b/yarn.lock @@ -160,11 +160,6 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== -"@types/ejs@^3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@types/ejs/-/ejs-3.1.2.tgz#75d277b030bc11b3be38c807e10071f45ebc78d9" - integrity sha512-ZmiaE3wglXVWBM9fyVC17aGPkLo/UgaOjEiI2FXQfyczrCefORPxIe+2dVmnmk3zkVIbizjrlQzmPGhSYGXG5g== - "@types/json-schema@^7.0.7": version "7.0.11" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" @@ -646,24 +641,6 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== -copyfiles@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/copyfiles/-/copyfiles-2.4.1.tgz#d2dcff60aaad1015f09d0b66e7f0f1c5cd3c5da5" - integrity sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg== - dependencies: - glob "^7.0.5" - minimatch "^3.0.3" - mkdirp "^1.0.4" - noms "0.0.0" - through2 "^2.0.1" - untildify "^4.0.0" - yargs "^16.1.0" - -core-util-is@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" @@ -1194,7 +1171,7 @@ glob@^10.2.5: minipass "^5.0.0 || ^6.0.2" path-scurry "^1.7.0" -glob@^7.0.5, glob@^7.1.3: +glob@^7.1.3: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -1362,7 +1339,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -1483,16 +1460,6 @@ is-unicode-supported@^0.1.0: resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -1714,7 +1681,7 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^3.0.3, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -1749,11 +1716,6 @@ minimist-options@4.1.0: resolved "https://registry.yarnpkg.com/minipass/-/minipass-6.0.2.tgz#542844b6c4ce95b202c0995b0a471f1229de4c81" integrity sha512-MzWSV5nYVT7mVyWCwn2o7JH13w2TBRmmSqSRCKzTw+lmft9X4z+3wjvs06Tzijo5z4W/kahUCDpRXTF+ZrmF/w== -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - mocha@^10.2.0: version "10.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" @@ -1816,14 +1778,6 @@ ncp@^2.0.0: resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" integrity sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA== -noms@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/noms/-/noms-0.0.0.tgz#da8ebd9f3af9d6760919b27d9cdc8092a7332859" - integrity sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow== - dependencies: - inherits "^2.0.1" - readable-stream "~1.0.31" - normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -1997,11 +1951,6 @@ prettier@^2.1.2: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.3.tgz#ab697b1d3dd46fb4626fbe2f543afe0cc98d8632" integrity sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw== -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - progress@^2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -2068,29 +2017,6 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -readable-stream@~1.0.31: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@~2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" - integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -2186,11 +2112,6 @@ safe-buffer@^5.1.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -2337,18 +2258,6 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ== - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - "strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -2422,14 +2331,6 @@ text-table@^0.2.0: resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== -through2@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -2553,11 +2454,6 @@ typescript@^4.9.5: resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== -untildify@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b" - integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw== - uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -2565,11 +2461,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== - util@^0.12.4: version "0.12.5" resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" @@ -2685,11 +2576,6 @@ write-file-atomic@^3.0.3: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -2720,7 +2606,7 @@ yargs-unparser@2.0.0: flat "^5.0.2" is-plain-obj "^2.1.0" -yargs@16.2.0, yargs@^16.1.0: +yargs@16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==