diff --git a/circuits/multiplier.circom b/circuits/multiplier.circom index ee13cad..64b8413 100644 --- a/circuits/multiplier.circom +++ b/circuits/multiplier.circom @@ -1,14 +1,33 @@ pragma circom 2.0.0; +template IsZero() { + signal input in; + signal output out; + + signal inv; + inv <-- in != 0 ? (1 / in) : 0; + + out <== (-in * inv) + 1; + in * out === 0; +} + template Multiplier(n) { assert(n > 1); signal input in[n]; signal output out; - signal inner[n-1]; + // assert that all numbers are != 1 + component isZero[n]; + for (var i = 0; i < n; i++) { + isZero[i] = IsZero(); + isZero[i].in <== in[i] - 1; + isZero[i].out === 0; + } + // multiply + signal inner[n-1]; inner[0] <== in[0] * in[1]; - for(var i = 2; i < n; i++) { + for (var i = 2; i < n; i++) { inner[i-1] <== inner[i-2] * in[i]; } diff --git a/src/testers/witnessTester.ts b/src/testers/witnessTester.ts index 7c15094..3b1d07b 100644 --- a/src/testers/witnessTester.ts +++ b/src/testers/witnessTester.ts @@ -15,9 +15,7 @@ export default class WitnessTester { return this.circomWasmTester.checkConstraints(witness); } @@ -27,18 +25,18 @@ export default class WitnessTester { await this.expectConstraintPass(witness).then( () => assert.fail('Expected constraints to not match.'), - err => expect(err).to.be.instanceOf(AssertionError) + err => { + // console.log(err.message); + expect(err.message).to.eq("Constraint doesn't match"); + } ); } - /** Compute witness given the input signals. - * @param input all signals, private and public - */ + /** Compute witness given the input signals. */ async calculateWitness(input: CircuitSignals): Promise { return this.circomWasmTester.calculateWitness(input, true); } @@ -74,7 +72,10 @@ export default class WitnessTester) { await this.calculateWitness(input).then( () => assert.fail('Expected witness calculation to fail.'), - err => expect(err).to.be.instanceOf(AssertionError) + err => { + // console.log(err.message); + expect(err.message.startsWith('Error: Assert Failed.')).to.be.true; + } ); } diff --git a/tests/common/index.ts b/tests/common/index.ts index df0ceb0..a863f7d 100644 --- a/tests/common/index.ts +++ b/tests/common/index.ts @@ -3,6 +3,8 @@ export const N = 3; const numbers = Array.from({length: N}, () => Math.floor(Math.random() * 100 * N)); const product = numbers.reduce((prev, acc) => acc * prev); +const malicious = Array.from({length: N}, () => 1); +malicious[0] = product; export const CIRCUIT_NAME = `multiplier_${N}`; export const CIRCUIT_CONFIG = { @@ -16,6 +18,9 @@ export const PTAU_PATH = './ptau/powersOfTau28_hez_final_08.ptau'; export const INPUT = { in: numbers, }; +export const BAD_INPUT = { + in: malicious, +}; export const OUTPUT = { out: product, }; diff --git a/tests/testers.test.ts b/tests/testers.test.ts index 9335483..d6ded8b 100644 --- a/tests/testers.test.ts +++ b/tests/testers.test.ts @@ -1,5 +1,5 @@ import {Circomkit, ProofTester, WitnessTester} from '../src'; -import {CIRCUIT_CONFIG, CIRCUIT_NAME, INPUT, N, OUTPUT} from './common'; +import {BAD_INPUT, CIRCUIT_CONFIG, CIRCUIT_NAME, INPUT, N, OUTPUT} from './common'; import {expect} from 'chai'; describe('witness tester', () => { @@ -14,13 +14,21 @@ describe('witness tester', () => { }); it('should have correct number of constraints', async () => { - await circuit.expectConstraintCount(N, true); + // N - 1 constraints for each multiplication + // 1 constraint for the output + // 4 * N constraints to check if each input is different than 1 + // TOTAL: 5 * N + await circuit.expectConstraintCount(5 * N, true); }); it('should assert correctly', async () => { await circuit.expectPass(INPUT, OUTPUT); }); + it('should fail for bad inupt', async () => { + await circuit.expectFail(BAD_INPUT); + }); + it('should compute correctly', async () => { const output = await circuit.compute(INPUT, ['out']); expect(output).to.haveOwnProperty('out'); @@ -35,7 +43,7 @@ describe('witness tester', () => { it('should NOT assert for bad witness', async () => { const witness = await circuit.calculateWitness(INPUT); const badWitness = await circuit.editWitness(witness, { - 'main.inner[0]': 99999n, + 'main.inner[0]': 1n, }); await circuit.expectConstraintFail(badWitness); });