From 00fa5f227204a1bf225859e63a7fa0c3a861d70c Mon Sep 17 00:00:00 2001 From: "Michael Bradley, Jr" Date: Thu, 12 Sep 2019 18:55:36 -0500 Subject: [PATCH] refactor(@embark/plugins/snark): add embark-snark package to the monorepo --- packages/plugins/snark/.npmrc | 4 + packages/plugins/snark/README.md | 47 ++ packages/plugins/snark/babel.config.js | 42 ++ packages/plugins/snark/package.json | 96 +++++ packages/plugins/snark/src/index.js | 211 +++++++++ packages/plugins/snark/test/index.js | 574 +++++++++++++++++++++++++ yarn.lock | 317 ++++++++++++-- 7 files changed, 1259 insertions(+), 32 deletions(-) create mode 100644 packages/plugins/snark/.npmrc create mode 100644 packages/plugins/snark/README.md create mode 100644 packages/plugins/snark/babel.config.js create mode 100644 packages/plugins/snark/package.json create mode 100644 packages/plugins/snark/src/index.js create mode 100644 packages/plugins/snark/test/index.js diff --git a/packages/plugins/snark/.npmrc b/packages/plugins/snark/.npmrc new file mode 100644 index 000000000..e031d3432 --- /dev/null +++ b/packages/plugins/snark/.npmrc @@ -0,0 +1,4 @@ +engine-strict = true +package-lock = false +save-exact = true +scripts-prepend-node-path = true diff --git a/packages/plugins/snark/README.md b/packages/plugins/snark/README.md new file mode 100644 index 000000000..c0770dc4e --- /dev/null +++ b/packages/plugins/snark/README.md @@ -0,0 +1,47 @@ +Embark-Snark +====== + +Plugin for [Embark](https://github.com/embark-framework/embark) to compile circom circuits and generate solidity proof + +Installation +====== + +In your embark dapp directory: +```npm install embark-snark --save``` + +then add embark-snark to the plugins section in ```embark.json```: + +```Json + "plugins": { + "embark-snark": { + "circuits": ["app/circuits/**"], + "inputs": { + "multiplier": { + "a": 3, + "b": 11 + } + } + } + } +``` + +You can defined where your circuits will be and what are the inputs. + +Now you can create your first circuits, for example, ```app/circuits/multiplier.circom```: + +``` + template Multiplier() { + signal private input a; + signal private input b; + signal output c; c <== a*b; + } + + component main = Multiplier(); +``` + +Embark will now compile the circuits and generate a solidity contracts to verify the proof as well as deploy it. + +Requirements +====== + +- Embark 5.0.0-alpha.0 or later diff --git a/packages/plugins/snark/babel.config.js b/packages/plugins/snark/babel.config.js new file mode 100644 index 000000000..8591034d0 --- /dev/null +++ b/packages/plugins/snark/babel.config.js @@ -0,0 +1,42 @@ +const cloneDeep = require('lodash.clonedeep'); + +module.exports = api => { + const env = api.env(); + + const base = { + plugins: [ + '@babel/plugin-proposal-class-properties', + [ + '@babel/plugin-transform-runtime', + { + corejs: 2 + } + ] + ], + presets: ['@babel/preset-env'] + }; + + if (env === 'base' || env.startsWith('base:')) { + return base; + } + + const node = cloneDeep(base); + node.presets[0] = [ + node.presets[0], + { + targets: { node: '8.11.3' } + } + ]; + + if (env === 'node' || env.startsWith('node:')) { + return node; + } + + const test = cloneDeep(node); + + if (env === 'test') { + return test; + } + + return {}; +}; diff --git a/packages/plugins/snark/package.json b/packages/plugins/snark/package.json new file mode 100644 index 000000000..bfecb86e4 --- /dev/null +++ b/packages/plugins/snark/package.json @@ -0,0 +1,96 @@ +{ + "name": "embark-snark", + "version": "4.1.1", + "author": "Anthony Laibe", + "contributors": [ + "Michael Bradley (https://github.com/michaelsbradleyjr/)" + ], + "description": "Snark plugin for Embark", + "homepage": "https://github.com/embark-framework/embark/tree/master/packages/plugins/snark#readme", + "bugs": "https://github.com/embark-framework/embark/issues", + "keywords": [ + "blockchain", + "circom", + "dapps", + "embark", + "ethereum", + "ipfs", + "serverless", + "snark", + "snarkjs", + "solc", + "solidity", + "zksnark" + ], + "license": "MIT", + "repository": { + "directory": "packages/plugins/snark", + "type": "git", + "url": "https://github.com/embark-framework/embark.git" + }, + "main": "dist/index.js", + "files": [ + "dist" + ], + "scripts": { + "build": "cross-env BABEL_ENV=node babel src --extensions \".js\" --out-dir dist --source-maps", + "ci": "npm run qa", + "clean": "npm run reset", + "lint": "eslint babel.config.js src/ test/", + "package": "npm pack", + "qa": "npm-run-all lint build test package", + "reset": "npx rimraf coverage dist embark-*.tgz package", + "start": "npm run watch", + "test": "jest", + "watch": "npm run build -- --verbose --watch" + }, + "dependencies": { + "@babel/runtime-corejs2": "7.6.0", + "circom": "0.0.31", + "find-up": "4.1.0", + "glob": "7.1.4", + "snarkjs": "0.1.19" + }, + "devDependencies": { + "@babel/cli": "7.5.5", + "@babel/core": "7.5.5", + "@babel/plugin-proposal-class-properties": "7.5.5", + "@babel/plugin-transform-runtime": "7.5.5", + "@babel/preset-env": "7.5.5", + "babel-eslint": "10.0.3", + "babel-jest": "24.9.0", + "cross-env": "5.2.0", + "eslint": "6.2.2", + "eslint-config-prettier": "6.1.0", + "eslint-plugin-jest": "22.5.1", + "eslint-plugin-prettier": "3.1.0", + "jest": "24.9.0", + "lodash.clonedeep": "4.5.0", + "npm-run-all": "4.1.5", + "prettier": "1.18.2", + "rimraf": "3.0.0" + }, + "eslintConfig": { + "env": { + "es6": true, + "node": true + }, + "extends": [ + "eslint:recommended", + "plugin:jest/recommended", + "plugin:jest/style", + "plugin:prettier/recommended" + ], + "parser": "babel-eslint" + }, + "jest": { + "collectCoverage": true, + "testEnvironment": "node", + "testMatch": [ + "**/test/**/*.js" + ] + }, + "prettier": { + "singleQuote": true + } +} diff --git a/packages/plugins/snark/src/index.js b/packages/plugins/snark/src/index.js new file mode 100644 index 000000000..387663a73 --- /dev/null +++ b/packages/plugins/snark/src/index.js @@ -0,0 +1,211 @@ +import { exec } from 'child_process'; +import { sync as findUp } from 'find-up'; +import globCb from 'glob'; +import * as path from 'path'; +import * as zkSnark from 'snarkjs'; +import { promisify } from 'util'; + +const glob = promisify(globCb); + +zkSnark.bigInt.prototype.toJSON = function() { + return this.toString(); +}; + +export class Snarks { + constructor(embark) { + this.embark = embark; + this.circuitsConfig = embark.pluginConfig; + this.compiledCircuitsPath = embark.config.dappPath('.embark', 'snarks'); + this.fs = embark.fs; + this.logger = embark.logger; + + if (this.circuitsConfig) { + this.registerEvents(); + } + } + + static Extensions = { + Json: '.json', + Circom: '.circom', + VkProof: '.vk_proof', + VkVerifier: '.vk_verifier', + Solidity: '.sol' + }; + + static circomBinary = findUp('node_modules/.bin/circom', { cwd: __dirname }); + static snarkjsBinary = findUp('node_modules/.bin/snarkjs', { + cwd: __dirname + }); + + registerEvents() { + this.embark.registerActionForEvent( + 'compiler:contracts:compile:before', + this.compileAndGenerateContracts.bind(this) + ); + } + + verifierFilepath(basename) { + return path.join( + this.compiledCircuitsPath, + `${basename}${Snarks.Extensions.VkVerifier}` + ); + } + + verifierContractPath(basename) { + return path.join( + this.compiledCircuitsPath, + `${basename}${Snarks.Extensions.Solidity}` + ); + } + + proofFilepath(basename) { + return path.join( + this.compiledCircuitsPath, + `${basename}${Snarks.Extensions.VkProof}` + ); + } + + async compileCircuits() { + await this.fs.ensureDir(this.compiledCircuitsPath); + + const patterns = this.circuitsConfig.circuits; + if (!patterns || !patterns.length) { + return; + } + + this.logger.info('Compiling circuits...'); + + await Promise.all( + patterns.map(async pattern => { + const filepaths = await glob(pattern); + await Promise.all( + filepaths + .filter( + filename => path.extname(filename) === Snarks.Extensions.Circom + ) + .map(filepath => this.compileCircuit(filepath)) + ); + }) + ); + } + + compileCircuit(filepath) { + return new Promise((resolve, reject) => { + const output = path.join( + this.compiledCircuitsPath, + `${path.basename(filepath, Snarks.Extensions.Circom)}${ + Snarks.Extensions.Json + }` + ); + exec(`${Snarks.circomBinary} ${filepath} -o ${output}`, error => { + if (error) { + return reject(error); + } + + resolve(); + }); + }); + } + + async generateProofs() { + this.logger.info('Generating proofs...'); + + await Promise.all( + (await this.fs.readdir(this.compiledCircuitsPath)) + .filter(filename => path.extname(filename) === Snarks.Extensions.Json) + .map(filename => this.generateProof(filename)) + ); + } + + async generateProof(filename) { + const filepath = path.join(this.compiledCircuitsPath, filename); + const basename = path.basename(filename, Snarks.Extensions.Json); + + const circuit = await this.getCircuit(filepath); + const setup = await this.generateSetup(circuit, basename); + + const input = this.circuitsConfig.inputs[basename]; + if (!input) { + return; + } + + const witness = circuit.calculateWitness(input); + const { proof, publicSignals } = zkSnark.original.genProof( + setup.vk_proof, + witness + ); + if (!zkSnark.original.isValid(setup.vk_verifier, proof, publicSignals)) { + throw new Error( + `The proof is not valid for ${basename} with inputs: ${JSON.stringify( + input + )}` + ); + } + + return this.generateVerifier(basename); + } + + async getCircuit(filepath) { + const definition = JSON.parse(await this.fs.readFile(filepath, 'utf8')); + return new zkSnark.Circuit(definition); + } + + async generateSetup(circuit, basename) { + const setup = zkSnark.original.setup(circuit); + await Promise.all([ + this.fs.writeFile( + this.proofFilepath(basename), + JSON.stringify(setup.vk_proof), + 'utf8' + ), + this.fs.writeFile( + this.verifierFilepath(basename), + JSON.stringify(setup.vk_verifier), + 'utf8' + ) + ]); + + return setup; + } + + generateVerifier(basename) { + return new Promise((resolve, reject) => { + const source = this.verifierFilepath(basename); + const output = this.verifierContractPath(basename); + exec( + `${Snarks.snarkjsBinary} generateverifier --vk ${source} -v ${output}`, + error => { + if (error) { + return reject(error); + } + + resolve(); + } + ); + }); + } + + async addVerifiersToContracts(contractFiles) { + (await this.fs.readdir(this.compiledCircuitsPath)) + .filter(filename => path.extname(filename) === Snarks.Extensions.Solidity) + .map(filename => this.addVerifierToContracts(filename, contractFiles)); + } + + addVerifierToContracts(filename, contractFiles) { + filename = path.join(this.compiledCircuitsPath, filename); + contractFiles.push({ path: filename }); + } + + async compileAndGenerateContracts(contractFiles, callback) { + try { + await this.compileCircuits(); + await this.generateProofs(); + await this.addVerifiersToContracts(contractFiles); + } catch (error) { + return callback(error); + } + callback(null, contractFiles); + } +} + +export default embark => new Snarks(embark); diff --git a/packages/plugins/snark/test/index.js b/packages/plugins/snark/test/index.js new file mode 100644 index 000000000..af70dd25b --- /dev/null +++ b/packages/plugins/snark/test/index.js @@ -0,0 +1,574 @@ +jest.mock('child_process'); +jest.mock('find-up'); +jest.mock('glob'); +jest.mock('snarkjs'); + +const { exec } = require('child_process'); + +const findUp = require('find-up'); +const path = require('path'); +const somePath = path.normalize('/some/path'); +findUp.sync.mockImplementation(() => somePath); + +const glob = require('glob'); + +const snarkjs = require('snarkjs'); +const someString = 'someString'; +snarkjs.bigInt = class { + toString() { + return someString; + } +}; + +describe('embark-snark', () => { + let Snarks, plugin; + + describe('side effects', () => { + describe('bigInt patching', () => { + it("should patch the prototype of snarkjs' bigInt constructor with a toJSON method", () => { + expect(snarkjs.bigInt.prototype.toJSON).toBeUndefined(); + ({ Snarks, default: plugin } = require('../src/index.js')); + expect(new snarkjs.bigInt().toJSON()).toBe(someString); + }); + }); + }); + + describe('plugin', () => { + let dappPath, embark; + + beforeAll(() => { + dappPath = jest.fn(() => {}); + embark = { config: { dappPath } }; + }); + + it('should call the implementation (Snarks class) with its argument', () => { + plugin(embark); + expect(dappPath).toHaveBeenCalled(); + }); + }); + + describe('Snarks class', () => { + describe('static properties', () => { + it('should have the expected static properties', () => { + expect(Snarks.circomBinary).toBe(somePath); + expect(Snarks.snarkjsBinary).toBe(somePath); + }); + }); + + describe('constructor', () => { + let dappPath, fs, logger, pluginConfig, embark, embarkNoPluginConfig; + + beforeAll(() => { + dappPath = jest.fn(() => somePath); + fs = {}; + logger = {}; + pluginConfig = {}; + + embark = { + config: { dappPath }, + fs, + logger, + pluginConfig + }; + + embarkNoPluginConfig = { + config: { dappPath }, + fs, + logger + }; + + jest.spyOn(Snarks.prototype, 'registerEvents'); + Snarks.prototype.registerEvents.mockImplementation(() => {}); + }); + + afterAll(() => { + Snarks.prototype.registerEvents.mockRestore(); + }); + + it('should setup the expected instance properties', () => { + const snarks = new Snarks(embark); + expect(snarks.embark).toBe(embark); + expect(snarks.circuitsConfig).toBe(pluginConfig); + expect(snarks.compiledCircuitsPath).toBe(somePath); + expect(snarks.fs).toBe(fs); + expect(snarks.logger).toBe(logger); + }); + + it('should call Snarks#registerEvents only when there is a plugin config', () => { + let snarks = new Snarks(embark); + expect(snarks.registerEvents).toHaveBeenCalled(); + + Snarks.prototype.registerEvents.mockClear(); + + snarks = new Snarks(embarkNoPluginConfig); + expect(snarks.registerEvents).not.toHaveBeenCalled(); + }); + }); + + describe('instance methods', () => { + let errorLogger, infoLogger, snarks; + + beforeAll(() => { + errorLogger = jest.fn(() => {}); + infoLogger = jest.fn(() => {}); + }); + + beforeEach(() => { + snarks = Object.create(Snarks.prototype); + snarks.compiledCircuitsPath = somePath; + snarks.logger = { error: errorLogger, info: infoLogger }; + }); + + describe('registerEvents', () => { + let bind, bound, registerActionForEvent; + + beforeAll(() => { + bound = () => {}; + bind = jest.fn(() => bound); + + registerActionForEvent = jest.fn(() => {}); + }); + + beforeEach(() => { + snarks.compileAndGenerateContracts = { bind }; + snarks.embark = { registerActionForEvent }; + }); + + it("should call embark's registerActionForEvent with instance-bound Snarks#compileAndGenerateContracts", () => { + snarks.registerEvents(); + expect(registerActionForEvent).toHaveBeenCalledWith( + expect.any(String), + bound + ); + expect(bind).toHaveBeenCalledWith(snarks); + }); + }); + + describe('verifierFilepath', () => { + it('should combine a path, basename, and extension', () => { + const basename = 'foo'; + + const combined = snarks.verifierFilepath(basename); + expect(combined).toBe( + path.join(somePath, `${basename}${Snarks.Extensions.VkVerifier}`) + ); + }); + }); + + describe('verifierContractPath', () => { + it('should combine a path, basename, and extension', () => { + const basename = 'foo'; + + const combined = snarks.verifierContractPath(basename); + expect(combined).toBe( + path.join(somePath, `${basename}${Snarks.Extensions.Solidity}`) + ); + }); + }); + + describe('proofFilepath', () => { + it('should combine a path, basename, and extension', () => { + const basename = 'foo'; + + const combined = snarks.proofFilepath(basename); + expect(combined).toBe( + path.join(somePath, `${basename}${Snarks.Extensions.VkProof}`) + ); + }); + }); + + describe('compileCircuits', () => { + let bar, foo, ensureDir; + + beforeAll(() => { + foo = `foo${Snarks.Extensions.Circom}`; + bar = `bar${Snarks.Extensions.Circom}`; + ensureDir = jest.fn(() => {}); + + glob.mockImplementation((_, cb) => + cb(null, [foo, 'A.aaa', bar, 'B.bbb']) + ); + }); + + beforeEach(() => { + snarks.compileCircuit = jest.fn(() => {}); + snarks.fs = { ensureDir }; + }); + + afterAll(() => { + glob.mockReset(); + }); + + it('should not compile if no matching circuits are found', async () => { + const circuits = []; + snarks.circuitsConfig = { circuits }; + + await snarks.compileCircuits(); + expect(snarks.compileCircuit).not.toHaveBeenCalled(); + }); + + it('should compile the configured circuits', async () => { + const circuits = ['whatever']; + snarks.circuitsConfig = { circuits }; + + await snarks.compileCircuits(); + expect(snarks.compileCircuit).toHaveBeenNthCalledWith(1, foo); + expect(snarks.compileCircuit).toHaveBeenNthCalledWith(2, bar); + expect(snarks.compileCircuit).toHaveBeenCalledTimes(2); + }); + }); + + describe('compileCircuit', () => { + let basename, filepath; + + beforeAll(() => { + basename = 'foo'; + filepath = path.join( + somePath, + `${basename}${Snarks.Extensions.Circom}` + ); + }); + + afterEach(() => { + exec.mockReset(); + }); + + it('should compile the ciruict', async () => { + exec.mockImplementation((_, cb) => cb()); + + await snarks.compileCircuit(filepath); + expect(exec).toHaveBeenCalledWith( + expect.stringContaining(filepath), + expect.any(Function) + ); + expect(exec).toHaveBeenCalledWith( + expect.stringContaining( + path.join(somePath, `${basename}${Snarks.Extensions.Json}`) + ), + expect.any(Function) + ); + }); + + it('should reject if the compiler has an error', async () => { + const message = 'error'; + exec.mockImplementation((_, cb) => cb(new Error(message))); + + await expect(snarks.compileCircuit(filepath)).rejects.toThrow( + message + ); + }); + }); + + describe('generateProofs', () => { + let bar, foo, readdir; + + beforeAll(() => { + foo = `foo${Snarks.Extensions.Json}`; + bar = `bar${Snarks.Extensions.Json}`; + readdir = jest.fn(async () => [foo, 'A.aaa', bar, 'B.bbb']); + }); + + beforeEach(() => { + snarks.generateProof = jest.fn(() => {}); + snarks.fs = { readdir }; + }); + + it('should generate proofs for the compiled circuits', async () => { + await snarks.generateProofs(); + expect(snarks.generateProof).toHaveBeenNthCalledWith(1, foo); + expect(snarks.generateProof).toHaveBeenNthCalledWith(2, bar); + expect(snarks.generateProof).toHaveBeenCalledTimes(2); + }); + }); + + describe('generateProof', () => { + let basename, + calculateWitness, + filename, + foo, + inputs, + proof, + publicSignals, + setup, + vk_verifier; + + beforeAll(() => { + basename = 'foo'; + calculateWitness = jest.fn(() => {}); + filename = `${basename}${Snarks.Extensions.Json}`; + foo = {}; + inputs = { foo }; + proof = {}; + publicSignals = {}; + + vk_verifier = {}; + setup = { vk_verifier }; + + snarkjs.original.genProof.mockImplementation(() => ({ + proof, + publicSignals + })); + }); + + beforeEach(() => { + snarks.circuitsConfig = { inputs }; + snarks.getCircuit = jest.fn(() => ({ calculateWitness })); + snarks.generateSetup = jest.fn(() => setup); + snarks.generateVerifier = jest.fn(() => {}); + }); + + afterEach(() => { + snarkjs.original.isValid.mockReset(); + }); + + afterAll(() => { + snarkjs.original.genProof.mockReset(); + }); + + it('should not generate if there is no matching input', async () => { + snarks.circuitsConfig = { inputs: {} }; + + await snarks.generateProof(filename); + expect(snarkjs.original.isValid).not.toHaveBeenCalled(); + }); + + it('should generate the proof for a circuit', async () => { + snarkjs.original.isValid.mockImplementation(() => true); + + await snarks.generateProof(filename); + expect(snarkjs.original.isValid).toHaveBeenCalledWith( + vk_verifier, + proof, + publicSignals + ); + expect(snarks.generateVerifier).toHaveBeenCalledWith( + path.basename(filename, Snarks.Extensions.Json) + ); + }); + + it('should reject if the proof is not valid', async () => { + snarkjs.original.isValid.mockImplementation(() => false); + + await expect(snarks.generateProof(filename)).rejects.toThrow( + /^The proof is not valid/ + ); + expect(snarks.generateVerifier).not.toHaveBeenCalled(); + }); + }); + + describe('getCircuit', () => { + let circuit, filepath, readFile; + + beforeAll(() => { + circuit = {}; + filepath = 'whatever'; + readFile = jest.fn(async () => '{}'); + + snarkjs.Circuit.mockImplementation(function() { + return circuit; + }); + }); + + beforeEach(() => { + snarks.fs = { readFile }; + }); + + afterAll(() => { + snarkjs.Circuit.mockReset(); + }); + + it("should return a circuit object given a compiled-circuit's path", async () => { + await expect(snarks.getCircuit(filepath)).resolves.toBe(circuit); + }); + }); + + describe('generateSetup', () => { + let basename, + circuit, + filepath, + setup, + vk_proof, + vk_verifier, + writeFile; + + beforeAll(() => { + basename = 'foo'; + circuit = {}; + filepath = path.join(somePath, basename); + + vk_proof = {}; + vk_verifier = {}; + setup = { vk_proof, vk_verifier }; + + writeFile = jest.fn(async () => {}); + + snarkjs.original.setup.mockImplementation(() => setup); + }); + + beforeEach(() => { + snarks.fs = { writeFile }; + snarks.proofFilepath = jest.fn(() => filepath); + snarks.verifierFilepath = jest.fn(() => filepath); + }); + + afterAll(() => { + snarkjs.original.setup.mockReset(); + }); + + it('should write proof and verifier files for a circuit', async () => { + await snarks.generateSetup(circuit, basename); + expect(writeFile).toHaveBeenNthCalledWith(1, filepath, '{}', 'utf8'); + expect(writeFile).toHaveBeenNthCalledWith(2, filepath, '{}', 'utf8'); + expect(writeFile).toHaveBeenCalledTimes(2); + }); + + it('should return the snarkjs setup', async () => { + await expect(snarks.generateSetup(circuit, basename)).resolves.toBe( + setup + ); + }); + }); + + describe('generateVerifier', () => { + let basename, contractPath, vkVerifierPath; + + beforeAll(() => { + basename = 'foo'; + contractPath = path.join( + somePath, + `${basename}${Snarks.Extensions.Solidity}` + ); + vkVerifierPath = contractPath = path.join( + somePath, + `${basename}${Snarks.Extensions.VkVerifier}` + ); + }); + + beforeEach(() => { + snarks.verifierFilepath = jest.fn(() => vkVerifierPath); + snarks.verifierContractPath = jest.fn(() => contractPath); + }); + + afterEach(() => { + exec.mockReset(); + }); + + it('should generate the verifier-contracts', async () => { + exec.mockImplementation((_, cb) => cb()); + + await snarks.generateVerifier(basename); + expect(exec).toHaveBeenCalledWith( + expect.stringContaining(vkVerifierPath), + expect.any(Function) + ); + expect(exec).toHaveBeenCalledWith( + expect.stringContaining(contractPath), + expect.any(Function) + ); + }); + + it('should reject if there is an error during generation', async () => { + const message = 'error'; + exec.mockImplementation((_, cb) => cb(new Error(message))); + + await expect(snarks.generateVerifier(basename)).rejects.toThrow( + message + ); + }); + }); + + describe('addVerifiersToContracts', () => { + let bar, contractFiles, foo, readdir; + + beforeAll(() => { + foo = `foo${Snarks.Extensions.Solidity}`; + bar = `bar${Snarks.Extensions.Solidity}`; + + contractFiles = []; + readdir = jest.fn(async () => [foo, 'A.aaa', bar, 'B.bbb']); + }); + + beforeEach(() => { + snarks.addVerifierToContracts = jest.fn(() => {}); + snarks.fs = { readdir }; + }); + + it('should add all verifier-contracts', async () => { + await snarks.addVerifiersToContracts(contractFiles); + expect(snarks.addVerifierToContracts).toHaveBeenNthCalledWith( + 1, + foo, + contractFiles + ); + expect(snarks.addVerifierToContracts).toHaveBeenNthCalledWith( + 2, + bar, + contractFiles + ); + expect(snarks.addVerifierToContracts).toHaveBeenCalledTimes(2); + }); + }); + + describe('addVerifierToContracts', () => { + let contractFiles, + events, + existingContract, + filename, + filepath, + request; + + beforeAll(() => { + existingContract = { + path: path.join('/path/to', `whatever${Snarks.Extensions.Solidity}`) + }; + contractFiles = [existingContract]; + + filename = 'foo${Snarks.Extensions.Solidity}'; + filepath = path.join(somePath, filename); + + request = jest.fn(() => {}); + events = { request }; + }); + + beforeEach(() => { + snarks.embark = { events }; + }); + + it('should add a verifier-contract to the array of contract files', () => { + snarks.addVerifierToContracts(filename, contractFiles); + expect(contractFiles).toEqual([existingContract, { path: filepath }]); + }); + }); + + describe('compileAndGenerateContracts', () => { + let callback, contractFiles, error; + + beforeAll(() => { + callback = jest.fn(() => {}); + contractFiles = []; + error = new Error('error'); + }); + + beforeEach(() => { + snarks.compileCircuits = jest.fn(() => {}); + snarks.generateProofs = jest.fn(() => {}); + snarks.addVerifiersToContracts = jest.fn(() => {}); + }); + + it('should call back without error and with the array of contract files after successfully compiling and generating', async () => { + await snarks.compileAndGenerateContracts(contractFiles, callback); + expect(callback).toHaveBeenCalledWith(null, contractFiles); + }); + + it('should call back with an error if a step fails', async () => { + snarks.generateProofs = jest.fn(() => { + throw error; + }); + + await snarks.compileAndGenerateContracts(contractFiles, callback); + expect(callback).toHaveBeenCalledWith(error); + }); + }); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index ecc90b359..31cb0a7d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3549,7 +3549,7 @@ acorn-jsx@^3.0.0: dependencies: acorn "^3.0.4" -acorn-jsx@^5.0.0: +acorn-jsx@^5.0.0, acorn-jsx@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f" integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw== @@ -3569,11 +3569,16 @@ acorn@^3.0.4: resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= -acorn@^6.0.1, acorn@^6.0.2, acorn@^6.1.1, acorn@^6.2.1: +acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.7, acorn@^6.1.1, acorn@^6.2.1: version "6.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.3.0.tgz#0087509119ffa4fc0a0041d1e93a417e68cb856e" integrity sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA== +acorn@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a" + integrity sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ== + address@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" @@ -3658,7 +3663,7 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== -ajv@6.10.2, ajv@^6.1.0, ajv@^6.10.2, ajv@^6.5.3, ajv@^6.5.5: +ajv@6.10.2, ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.3, ajv@^6.5.5, ajv@^6.9.1: version "6.10.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== @@ -4248,6 +4253,18 @@ babel-core@^6.0.0, babel-core@^6.26.0: slash "^1.0.0" source-map "^0.5.7" +babel-eslint@10.0.3: + version "10.0.3" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" + integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" + babel-eslint@9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-9.0.0.tgz#7d9445f81ed9f60aff38115f838970df9f2b6220" @@ -4903,6 +4920,11 @@ bfj@6.1.1: hoopy "^0.1.2" tryer "^1.0.0" +big-integer@^1.6.32, big-integer@^1.6.43: + version "1.6.44" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.44.tgz#4ee9ae5f5839fc11ade338fea216b4513454a539" + integrity sha512-7MzElZPTyJ2fNvBkPxtFQ2fWIkVmuzw41+BZHSzpEq3ymB2MfeKp1+yXl/tS75xCx+WnyV+yb0kp+K1C3UNwmQ== + big.js@^3.1.3: version "3.2.0" resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e" @@ -5597,7 +5619,7 @@ chai@4.1.2: pathval "^1.0.0" type-detect "^4.0.0" -chai@4.2.0: +chai@4.2.0, chai@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== @@ -5782,6 +5804,15 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: inherits "^2.0.1" safe-buffer "^5.0.1" +circom@0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/circom/-/circom-0.0.31.tgz#c4cd5ab6a82611bb5753e635173c1ff52cbea6c7" + integrity sha512-KtMgJ3fkUGelR9SijMBJUjLAkPC1/dAmaLUdunKaYZEVks5hupLwQ8dtdCbpwOGfiwvBnPLYqM2wyWrgmIAbbw== + dependencies: + big-integer "^1.6.32" + optimist "^0.6.1" + yargs "^12.0.2" + circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" @@ -7935,6 +7966,13 @@ escope@^3.6.0: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-config-prettier@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.1.0.tgz#e6f678ba367fbd1273998d5510f76f004e9dce7b" + integrity sha512-k9fny9sPjIBQ2ftFTesJV21Rg4R/7a7t7LCtZVrYQiHEp8Nnuk3EGaDmsKSAnsPj0BYcgB2zxzHa2NTkIxcOLg== + dependencies: + get-stdin "^6.0.0" + eslint-config-react-app@3.0.8: version "3.0.8" resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-3.0.8.tgz#6f606828ba30bafee7d744c41cd07a3fea8f3035" @@ -8026,6 +8064,11 @@ eslint-plugin-import@~2.2.0: minimatch "^3.0.3" pkg-up "^1.0.0" +eslint-plugin-jest@22.5.1: + version "22.5.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-22.5.1.tgz#a31dfe9f9513c6af7c17ece4c65535a1370f060b" + integrity sha512-c3WjZR/HBoi4GedJRwo2OGHa8Pzo1EbSVwQ2HFzJ+4t2OoYM7Alx646EH/aaxZ+9eGcPiq0FT0UGkRuFFx2FHg== + eslint-plugin-jsx-a11y@6.1.2: version "6.1.2" resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.1.2.tgz#69bca4890b36dcf0fe16dd2129d2d88b98f33f88" @@ -8051,6 +8094,13 @@ eslint-plugin-node@~4.2.2: resolve "^1.1.7" semver "5.3.0" +eslint-plugin-prettier@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.0.tgz#8695188f95daa93b0dc54b249347ca3b79c4686d" + integrity sha512-XWX2yVuwVNLOUhQijAkXz+rMPPoCr7WFiAl8ig6I7Xn+pPVhDhzg4DxHpmbeb0iqjO9UronEA3Tb09ChnFVHHA== + dependencies: + prettier-linter-helpers "^1.0.0" + eslint-plugin-promise@~3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca" @@ -8103,14 +8153,22 @@ eslint-scope@^4.0.0, eslint-scope@^4.0.3: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^1.3.1: +eslint-scope@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" + integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-utils@^1.3.1, eslint-utils@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.2.tgz#166a5180ef6ab7eb462f162fd0e6f2463d7309ab" integrity sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q== dependencies: eslint-visitor-keys "^1.0.0" -eslint-visitor-keys@^1.0.0: +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== @@ -8159,6 +8217,91 @@ eslint@5.7.0: table "^5.0.2" text-table "^0.2.0" +eslint@6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.2.2.tgz#03298280e7750d81fcd31431f3d333e43d93f24f" + integrity sha512-mf0elOkxHbdyGX1IJEUsNBzCDdyoUgljF3rRlgfyYh0pwGnreLc0jjD6ZuleOibjmnUWZLY2eXwSooeOgGJ2jw== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^5.0.0" + eslint-utils "^1.4.2" + eslint-visitor-keys "^1.1.0" + espree "^6.1.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.4.1" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.14" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +eslint@^5.16.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" + integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.9.1" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^4.0.3" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^5.0.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.2.2" + js-yaml "^3.13.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.11" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^5.5.1" + strip-ansi "^4.0.0" + strip-json-comments "^2.0.1" + table "^5.2.3" + text-table "^0.2.0" + eslint@~3.19.0: version "3.19.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc" @@ -8217,6 +8360,24 @@ espree@^4.0.0: acorn-jsx "^5.0.0" eslint-visitor-keys "^1.0.0" +espree@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" + integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== + dependencies: + acorn "^6.0.7" + acorn-jsx "^5.0.0" + eslint-visitor-keys "^1.0.0" + +espree@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.1.tgz#7f80e5f7257fc47db450022d723e356daeb1e5de" + integrity sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ== + dependencies: + acorn "^7.0.0" + acorn-jsx "^5.0.2" + eslint-visitor-keys "^1.1.0" + esprima-extract-comments@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/esprima-extract-comments/-/esprima-extract-comments-1.1.0.tgz#0dacab567a5900240de6d344cf18c33617becbc9" @@ -8971,6 +9132,11 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + fast-glob@^2.0.2, fast-glob@^2.2.6: version "2.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" @@ -9091,6 +9257,13 @@ file-entry-cache@^2.0.0: flat-cache "^1.2.1" object-assign "^4.0.1" +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + file-loader@4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-4.2.0.tgz#5fb124d2369d7075d70a9a5abecd12e60a95215e" @@ -9264,6 +9437,14 @@ find-up@3.0.0, find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@4.1.0, find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -9272,14 +9453,6 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - flat-cache@^1.2.1: version "1.3.4" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" @@ -9290,6 +9463,15 @@ flat-cache@^1.2.1: rimraf "~2.6.2" write "^0.2.1" +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + flat@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" @@ -9307,6 +9489,11 @@ flatted@0.2.3: resolved "https://registry.yarnpkg.com/flatted/-/flatted-0.2.3.tgz#2373f329b476e4362ed4a69a7233b42d6f93365b" integrity sha512-C4B5UtK3kOrLAyZ1ftqEWprxCfLmCIqEcNufZrtsJhiZ/fcI5mvCgtAtC3pu7BC9KE7aUIrPXwTgcT1fiI7QhA== +flatted@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== + flatten@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782" @@ -9725,6 +9912,11 @@ get-stdin@^5.0.1: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" integrity sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g= +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + get-stream@^2.2.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" @@ -9865,18 +10057,7 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^5.0.15: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: +glob@7.1.4, glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: version "7.1.4" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.4.tgz#aa608a2f6c577ad357e1ae5a5c26d9a8d1969255" integrity sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A== @@ -9888,6 +10069,17 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, gl once "^1.3.0" path-is-absolute "^1.0.0" +glob@^5.0.15: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@~6.0.4: version "6.0.4" resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" @@ -10865,6 +11057,14 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" +import-fresh@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" + integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + import-from@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" @@ -11024,7 +11224,7 @@ inquirer@^0.12.0: strip-ansi "^3.0.0" through "^2.3.6" -inquirer@^6.1.0, inquirer@^6.2.0: +inquirer@^6.1.0, inquirer@^6.2.0, inquirer@^6.2.2, inquirer@^6.4.1: version "6.5.2" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== @@ -12823,6 +13023,16 @@ keccak@^1.0.2: nan "^2.2.1" safe-buffer "^5.1.0" +keccak@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/keccak/-/keccak-2.0.0.tgz#7456ea5023284271e6f362b4397e8df4d2bb994c" + integrity sha512-rKe/lRr0KGhjoz97cwg+oeT1Rj/Y4cjae6glArioUC8JBF9ROGZctwIaaruM7d7naovME4Q8WcQSO908A8qcyQ== + dependencies: + bindings "^1.2.1" + inherits "^2.0.3" + nan "^2.2.1" + safe-buffer "^5.1.0" + keccakjs@0.2.3, keccakjs@^0.2.0, keccakjs@^0.2.1, keccakjs@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.3.tgz#5e4e969ce39689a3861f445d7752ee3477f9fe72" @@ -15325,6 +15535,13 @@ param-case@^2.1.0, param-case@^2.1.1: dependencies: no-case "^2.2.0" +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + parse-asn1@^5.0.0: version "5.1.4" resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.4.tgz#37f6628f823fbdeb2273b4d540434a22f3ef1fcc" @@ -16444,6 +16661,13 @@ preserve@^0.2.0: resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" integrity sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks= +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + prettier-plugin-solidity@1.0.0-alpha.25: version "1.0.0-alpha.25" resolved "https://registry.yarnpkg.com/prettier-plugin-solidity/-/prettier-plugin-solidity-1.0.0-alpha.25.tgz#45b5c7aa68f69f2aa160cd1d2590c459cd89e6d4" @@ -16458,7 +16682,7 @@ prettier-plugin-solidity@1.0.0-alpha.25: solidity-parser-antlr "^0.4.4" string-width "^3.0.0" -prettier@^1.14.2, prettier@^1.15.3: +prettier@1.18.2, prettier@^1.14.2, prettier@^1.15.3: version "1.18.2" resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== @@ -18286,7 +18510,7 @@ resolve@1.8.1: dependencies: path-parse "^1.0.5" -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.8.1: +resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.12.0, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.5.0, resolve@^1.6.0, resolve@^1.8.1: version "1.12.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" integrity sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w== @@ -18724,7 +18948,7 @@ semver@6.2.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db" integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A== -semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -19181,6 +19405,18 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +snarkjs@0.1.19: + version "0.1.19" + resolved "https://registry.yarnpkg.com/snarkjs/-/snarkjs-0.1.19.tgz#1c89215cc7cf2844c887348b3208d3e170a80813" + integrity sha512-HcrLUWTSX8XEzIdbfZS/GABGaTsa+fN2nuniUku/voCfuAEu5kFgDTIbw879zwD2Uxqy56wiWwzUzwifCfi8mA== + dependencies: + big-integer "^1.6.43" + chai "^4.2.0" + escape-string-regexp "^1.0.5" + eslint "^5.16.0" + keccak "^2.0.0" + yargs "^12.0.5" + sockjs-client@1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.1.5.tgz#1bb7c0f7222c40f42adf14f4442cbd1269771a83" @@ -19822,6 +20058,11 @@ strip-json-comments@2.0.1, strip-json-comments@^2.0.1, strip-json-comments@~2.0. resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strip-json-comments@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + strong-log-transformer@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" @@ -20019,7 +20260,7 @@ table@^3.7.8: slice-ansi "0.0.4" string-width "^2.0.0" -table@^5.0.2: +table@^5.0.2, table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== @@ -20946,6 +21187,11 @@ uuid@^3.0.1, uuid@^3.1.0, uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== +v8-compile-cache@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" + integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== + validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.3: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -22307,6 +22553,13 @@ write-pkg@^3.1.0: sort-keys "^2.0.0" write-json-file "^2.2.0" +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + write@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" @@ -22566,7 +22819,7 @@ yargs@13.2.2: y18n "^4.0.0" yargs-parser "^13.0.0" -yargs@^12.0.0, yargs@^12.0.1, yargs@^12.0.5: +yargs@^12.0.0, yargs@^12.0.1, yargs@^12.0.2, yargs@^12.0.5: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==