Skip to content

Commit

Permalink
Minor fixes (#69)
Browse files Browse the repository at this point in the history
* add more tests for error catching

* calldata fixes as well

* bump version
  • Loading branch information
erhant authored Feb 17, 2024
1 parent 1a787a4 commit 0af1603
Show file tree
Hide file tree
Showing 10 changed files with 75 additions and 23 deletions.
6 changes: 3 additions & 3 deletions circuits.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
"template": "Multiplier",
"params": [3]
},
"someArrays_2_3": {
"file": "someArrays",
"template": "SomeArrays",
"arrays_2_3": {
"file": "arrays",
"template": "Arrays",
"params": [2, 3],
"pubs": ["in1D", "in2D"]
}
Expand Down
2 changes: 1 addition & 1 deletion circuits/someArrays.circom → circuits/arrays.circom
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pragma circom 2.0.0;

template SomeArrays(N, M) {
template Arrays(N, M) {
signal input in;
signal input in1D[N];
signal input in2D[N][M];
Expand Down
18 changes: 18 additions & 0 deletions circuits/errors.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
pragma circom 2.0.0;

// Run-time errors:
// - An input signal has more elements than expected
// - An input signal has less elements than expected
// - A signal is missing
// - A signal is extra
// - A run-time assertion error occurs.
// - Division-by-zero

template Errors() {
signal input in;
signal input inin[2];
signal output out;

assert(in != 1);
out <== in + (inin[0] * inin[1]);
}
File renamed without changes.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "circomkit",
"version": "0.0.23",
"version": "0.0.24",
"description": "A Circom development environment",
"author": "erhant",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion src/circomkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ export class Circomkit {
circuit: string,
circuitConfig: CircuitConfig & {recompile?: boolean}
) {
circuitConfig.dir ||= 'test'; // defaults to test directory
circuitConfig.dir ??= 'test'; // defaults to test directory

const targetPath = this.instantiate(circuit, circuitConfig);
const circomWasmTester: CircomWasmTester = await wasm_tester(targetPath, {
Expand Down
7 changes: 6 additions & 1 deletion src/testers/witnessTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ export class WitnessTester<IN extends readonly string[] = [], OUT extends readon
}
}

/** Expect an input to fail an assertion in the circuit. */
/** Expect a witness computation to fail in the circuit.
*
* See [here](https://github.com/iden3/circom/blob/master/code_producers/src/wasm_elements/common/witness_calculator.js#L21)
* for the list of errors that may occur during witness calculation.
* Most of the time, you will be expecting an assertion error.
*/
async expectFail(input: CircuitSignals<IN>) {
await this.calculateWitness(input).then(
() => assert.fail('Expected witness calculation to fail.'),
Expand Down
19 changes: 11 additions & 8 deletions src/utils/calldata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export function getCalldata(
function publicSignalsCalldata(pubs: PublicSignals, pretty: boolean): string {
const pubs256 = valuesToPaddedUint256s(pubs);
if (pretty) {
return `uint[${pubs.length}] pubs = [\n ${pubs256.join(',\n ')}\n];`;
return `uint[${pubs.length}] memory pubs = [\n ${pubs256.join(',\n ')}\n];`;
} else {
return `[${pubs256.map(s => `"${s}"`).join(',')}]`;
}
Expand All @@ -67,7 +67,7 @@ function fflonkCalldata(proof: FflonkProof, pretty: boolean): string {
]);

if (pretty) {
return `uint256[24] proof = [\n ${vals.join(',\n ')}\n];`;
return `uint256[24] memory proof = [\n ${vals.join(',\n ')}\n];`;
} else {
return `[${withQuotes(vals).join(',')}]`;
}
Expand All @@ -87,23 +87,26 @@ function plonkCalldata(proof: PlonkProof, pretty: boolean = false) {
]);

if (pretty) {
return `uint[24] proof = [\n ${vals.join(',\n ')}\n];`;
return `uint[24] memory proof = [\n ${vals.join(',\n ')}\n];`;
} else {
return `[${withQuotes(vals).join(',')}]`;
}
}

function groth16Calldata(proof: Groth16Proof, pretty: boolean) {
const pA = valuesToPaddedUint256s([proof.pi_a[0], proof.pi_a[1]]);
const pB0 = valuesToPaddedUint256s([proof.pi_b[0][1], proof.pi_b[0][1]]);
const pB1 = valuesToPaddedUint256s([proof.pi_b[1][1], proof.pi_b[1][1]]);
const pC = valuesToPaddedUint256s([proof.pi_c[0], proof.pi_c[1]]);

// note that pB are reversed, notice the indexing is [1] and [0] instead of [0] and [1].
const pB0 = valuesToPaddedUint256s([proof.pi_b[0][1], proof.pi_b[0][0]]);
const pB1 = valuesToPaddedUint256s([proof.pi_b[1][1], proof.pi_b[1][0]]);

if (pretty) {
// the eternal struggle between "should i use a template literal" or "join with \n"
return [
`uint[2] pA = [${pA.join(', ')}];`,
`uint[2][2] pB = [[${pB0.join(', ')}], [${pB1.join(', ')}]];`,
`uint[2] pC = [${pC.join(', ')}];`,
`uint[2] memory pA = [\n ${pA.join(',\n ')}\n];`,
`uint[2][2] memory pB = [\n [\n ${pB0.join(',\n ')}\n ],\n [\n ${pB1.join(',\n ')}\n ]\n];`,
`uint[2] memory pC = [\n ${pC.join(',\n ')}\n];`,
].join('\n');
} else {
return [
Expand Down
34 changes: 34 additions & 0 deletions tests/errors.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {Circomkit, WitnessTester} from '../src';

describe('error catching', () => {
let circuit: WitnessTester<['in', 'inin'], ['out']>;

before(async () => {
const circomkit = new Circomkit({verbose: false, logLevel: 'silent'});
circuit = await circomkit.WitnessTester('error_rt', {file: 'errors', template: 'Errors'});
});

it('should fail for fewer inputs than expected', async () => {
await circuit.expectFail({in: 0, inin: [1]});
});

it('should fail for more inputs than expected', async () => {
await circuit.expectFail({in: 0, inin: [1, 2, 3]});
});

it('should fail due to false-assert', async () => {
await circuit.expectFail({in: 1, inin: [1, 2]});
});

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]});
});

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});
});
});
8 changes: 0 additions & 8 deletions tests/witnessTester.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,6 @@ describe('witness tester', () => {
await circuit.expectPass(signals.input, signals.output);
});

it('should fail for fewer inputs than expected', async () => {
await circuit.expectFail({in: signals.input.in.slice(1)});
});

it('should fail for more inputs than expected', async () => {
await circuit.expectFail({in: [0, ...signals.input.in]});
});

it('should fail for bad witness', async () => {
await circuit.expectFail(signals.badInput);
});
Expand Down

0 comments on commit 0af1603

Please sign in to comment.