From c9f951a89512df9dc12147f915e9220b034f42ab Mon Sep 17 00:00:00 2001 From: Erhan Date: Fri, 26 Apr 2024 22:19:10 +0300 Subject: [PATCH] fixes & new version (#77) * fixes & new version * comments --- package.json | 4 ++-- src/circomkit.ts | 20 +++++++++++--------- src/testers/witnessTester.ts | 26 ++++++++++++++++---------- src/utils/r1cs.ts | 3 +-- tests/errors.test.ts | 9 +++++++-- 5 files changed, 37 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 5eae79d..2f4d6aa 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "circomkit", - "version": "0.0.25", - "description": "A Circom development environment", + "version": "0.1.0", + "description": "A Circom testing & development environment", "author": "erhant", "license": "MIT", "engines": { diff --git a/src/circomkit.ts b/src/circomkit.ts index d9e6449..4ef5f66 100644 --- a/src/circomkit.ts +++ b/src/circomkit.ts @@ -92,7 +92,7 @@ export class Circomkit { } /** Computes a path that requires a circuit name. */ - private path(circuit: string, type: CircuitPathBuilders): string { + path(circuit: string, type: CircuitPathBuilders): string { const dir = `${this.config.dirBuild}/${circuit}`; switch (type) { case 'dir': @@ -117,17 +117,17 @@ export class Circomkit { } /** Computes a path that requires a circuit and an input name. */ - private pathWithInput(circuit: string, input: string, type: CircuitInputPathBuilders): string { + pathWithInput(circuit: string, input: string, type: CircuitInputPathBuilders): string { const dir = `${this.config.dirBuild}/${circuit}/${input}`; switch (type) { case 'dir': return dir; + case 'wtns': + return `${dir}/witness.wtns`; case 'pubs': return `${dir}/public.json`; case 'proof': - return `${dir}/proof.json`; - case 'wtns': - return `${dir}/witness.wtns`; + return `${dir}/${this.config.protocol}_proof.json`; case 'in': return `${this.config.dirInputs}/${circuit}/${input}.json`; default: @@ -136,13 +136,13 @@ export class Circomkit { } /** Given a PTAU name, returns the relative path. */ - private pathPtau(ptauName: string): string { + pathPtau(ptauName: string): string { return `${this.config.dirPtau}/${ptauName}`; } /** Given a circuit & id name, returns the relative path of the phase-2 PTAU. * This is used in particular by Groth16's circuit-specific setup phase. */ - private pathZkey(circuit: string, id: number): string { + pathZkey(circuit: string, id: number): string { return `${this.config.dirBuild}/${circuit}/${circuit}_${id}.zkey`; } @@ -185,8 +185,10 @@ export class Circomkit { } /** Read the information about the circuit by extracting it from the R1CS file. - * This implementation follows the specs at - * https://github.com/iden3/r1csfile/blob/master/doc/r1cs_bin_format.md. + * + * This implementation follows the specs at [iden3/r1csfile](https://github.com/iden3/r1csfile/blob/master/doc/r1cs_bin_format.md) + * and is inspired from the work by [PSE's `p0tion`](https://github.com/privacy-scaling-explorations/p0tion/blob/f88bcee5d499dce975d0592ed10b21aa8d73bbd2/packages/actions/src/helpers/utils.ts#L413) + * and by [Weijiekoh's `circom-helper`](https://github.com/weijiekoh/circom-helper/blob/master/ts/read_num_inputs.ts#L5). */ async info(circuit: string): Promise { let pointer = 0; diff --git a/src/testers/witnessTester.ts b/src/testers/witnessTester.ts index cb64d0f..f884b34 100644 --- a/src/testers/witnessTester.ts +++ b/src/testers/witnessTester.ts @@ -72,23 +72,29 @@ export class WitnessTester) { - await this.calculateWitness(input).then( + async expectFail(input: CircuitSignals): Promise { + return await this.calculateWitness(input).then( () => assert.fail('Expected witness calculation to fail.'), err => { + const errorMessage = (err as Error).message; + const isExpectedError = [ 'Error: Assert Failed.', // a constraint failure (most common) 'Not enough values for input signal', // few inputs than expected for a signal 'Too many values for input signal', // more inputs than expected for a signal - ].some(msg => (err as Error).message.startsWith(msg)); - if (isExpectedError) { - // we expected this failure, register it as an expect call - expect(isExpectedError).to.be.true; - } else { - // we did not expect this failure, throw it anyways - throw err; - } + 'Not all inputs have been set.', // few inputs than expected for many signals + ].some(msg => errorMessage.startsWith(msg)); + + // we did not expect this failure, throw it anyways + if (!isExpectedError) throw err; + + // we expected this failure, register it as an expect call + expect(isExpectedError).to.be.true; + + return errorMessage; } ); } diff --git a/src/utils/r1cs.ts b/src/utils/r1cs.ts index a1c2550..fc39865 100644 --- a/src/utils/r1cs.ts +++ b/src/utils/r1cs.ts @@ -1,7 +1,6 @@ import {readSync, ReadPosition} from 'fs'; -/** Reads a specified number of bytes from a file and converts them to a BigInt. - */ +/** Reads a specified number of bytes from a file and converts them to a `BigInt`. */ export function readBytesFromFile(fd: number, offset: number, length: number, position: ReadPosition): BigInt { const buffer = Buffer.alloc(length); diff --git a/tests/errors.test.ts b/tests/errors.test.ts index 81ab44d..22f6d42 100644 --- a/tests/errors.test.ts +++ b/tests/errors.test.ts @@ -1,6 +1,6 @@ import {Circomkit, WitnessTester} from '../src'; -describe('error catching', () => { +describe('errors', () => { let circuit: WitnessTester<['in', 'inin'], ['out']>; before(async () => { @@ -10,25 +10,30 @@ describe('error catching', () => { it('should fail for fewer inputs than expected', async () => { await circuit.expectFail({in: 0, inin: [1]}); + // Not enough values for input signal inin }); it('should fail for more inputs than expected', async () => { await circuit.expectFail({in: 0, inin: [1, 2, 3]}); + // Too many values for input signal inin }); it('should fail due to false-assert', async () => { await circuit.expectFail({in: 1, inin: [1, 2]}); + // Error: Assert Failed. }); it('should fail due to missing signal', async () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error - await circuit.expectFail({inin: [1, 2, 3]}); + await circuit.expectFail({inin: [1, 2]}); + // Not all inputs have been set. Only 2 out of 3. }); it('should fail due to extra signal', async () => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error await circuit.expectFail({inin: [1, 2, 3], idontexist: 1}); + // Too many values for input signal inin }); });