diff --git a/.gitignore b/.gitignore index 4516389..5830290 100644 --- a/.gitignore +++ b/.gitignore @@ -116,3 +116,6 @@ tmp.ptau # is this still a thing lol .DS_Store + +# ignore auto generated test circuits +circuits/test diff --git a/README.md b/README.md index a40b6b3..135d056 100644 --- a/README.md +++ b/README.md @@ -81,24 +81,27 @@ To run Mocha tests do the following: ```bash # run all tests -yarn test +yarn test:all # run a specific test -yarn --grep "circuit name" +yarn test "circuit name" ``` -Within each test, there are two sub-tests: +### Witness Computation -- **Witness Computation** will test whether witness computations are matching the expectations & the constraints hold. -- **Proof Validation** will test whether proof generation & verification works correctly. This requires the **WASM file**, **prover key**, and **verification key** to be calculated beforehand. +TODO + +### Proof Verification + +TODO ## Examples We have several example circuits to help guide you: -- **Multiplier**: Prove that you know the factors of a number. -- **Floating Point Addition**: A floating-point addition circuit, as written in [Berkeley ZKP MOOC 2023 - Lab 1](https://github.com/rdi-berkeley/zkp-mooc-lab). -- **Fibonacci**: Calculate N'th Fibonacci number, has both recursive & iterative implementations. -- **Sudoku**: Prove that you know the solution to a sudoku puzzle where the board size is a perfect square. +- **Multiplier**: A circuit to prove that you know the factors of a number. +- **Floating Point Addition**: A circuit to compute the sum of two floating-point numbers, as written in [Berkeley ZKP MOOC 2023 - Lab 1](https://github.com/rdi-berkeley/zkp-mooc-lab). +- **Fibonacci**: A circuit to compute Fibonacci numbers. +- **Sudoku**: A circuit to prove that you know the solution to a Sudoku puzzle. ## Styling diff --git a/circuits/float_add.circom b/circuits/float_add.circom index 87fcf52..4b63a1f 100644 --- a/circuits/float_add.circom +++ b/circuits/float_add.circom @@ -7,7 +7,17 @@ include "circomlib/circuits/switcher.circom"; include "circomlib/circuits/gates.circom"; include "circomlib/circuits/bitify.circom"; -include "functions/bits.circom"; +/* + * Finds Math.floor(log2(n)) + */ +function log2(n) { + var tmp = 1, ans = 1; + while (tmp < n) { + ans++; + tmp *= 2; + } + return ans; +} /* * Basically `out = cond ? ifTrue : ifFalse` @@ -199,7 +209,7 @@ template LeftShift(shift_bound) { signal output y; // find number of bits in shift_bound - var n = numOfBits(shift_bound); + var n = log2(shift_bound) + 1; // convert "shift" to bits component shift_bits = Num2BitsWithSkipChecks(n); diff --git a/circuits/functions/bits.circom b/circuits/functions/bits.circom deleted file mode 100644 index 2ea28e6..0000000 --- a/circuits/functions/bits.circom +++ /dev/null @@ -1,10 +0,0 @@ -pragma circom 2.0.0; - -include "./math.circom"; - -/* - * Get number of bits - */ -function numOfBits(n) { - return log2(n) + 1; -} diff --git a/circuits/functions/math.circom b/circuits/functions/math.circom deleted file mode 100644 index d62a071..0000000 --- a/circuits/functions/math.circom +++ /dev/null @@ -1,13 +0,0 @@ -pragma circom 2.0.0; - -/* - * Computes Math.floor(log2(n)) - */ -function log2(n) { - var tmp = 1, ans = 1; - while (tmp < n) { - ans++; - tmp *= 2; - } - return ans; -} diff --git a/circuits/sudoku.circom b/circuits/sudoku.circom index 1039cdc..c30ff67 100644 --- a/circuits/sudoku.circom +++ b/circuits/sudoku.circom @@ -1,7 +1,6 @@ pragma circom 2.0.0; include "circomlib/circuits/bitify.circom"; -include "functions/bits.circom"; // Assert that two elements are not equal template NonEqual() { diff --git a/tests/float_add.test.ts b/tests/float_add.test.ts index 26f3108..714b2d2 100644 --- a/tests/float_add.test.ts +++ b/tests/float_add.test.ts @@ -2,7 +2,7 @@ import {instantiate} from '../utils/instantiate'; import {createWasmTester} from '../utils/wasmTester'; // tests adapted from https://github.com/rdi-berkeley/zkp-mooc-lab -describe('fp32', () => { +describe('float_add 32-bit', () => { let circuit: Awaited>; before(async () => { @@ -105,7 +105,7 @@ describe('fp32', () => { }); }); -describe('fp64', () => { +describe('float_add 64-bit', () => { let circuit: Awaited>; before(async () => { @@ -193,3 +193,42 @@ describe('fp64', () => { }); }); }); + +describe('float_add utilities', () => { + describe('check bit length', () => { + const b = 23; // bit count + const circuitName = 'cbl_' + b; + let circuit: Awaited>; + + before(async () => { + instantiate(circuitName, 'float_add/test', { + file: 'float_add', + template: 'CheckBitLength', + publicInputs: [], + templateParams: [b], + }); + circuit = await createWasmTester(circuitName, 'test/float_add'); + await circuit.printConstraintCount(b + 2); + }); + + it('bitlength of `in` <= `b`', async () => { + await circuit.expectCorrectAssert( + { + in: '4903265', + }, + {out: '1'} + ); + }); + + it('bitlength of `in` > `b`', async () => { + await circuit.expectCorrectAssert( + { + in: '13291873', + }, + {out: '0'} + ); + }); + }); + + describe('right shift', () => {}); +}); diff --git a/utils/instantiate.ts b/utils/instantiate.ts index 58fcd79..f41d9a9 100644 --- a/utils/instantiate.ts +++ b/utils/instantiate.ts @@ -1,5 +1,5 @@ import ejs from 'ejs'; -import {writeFileSync, readFileSync} from 'fs'; +import {writeFileSync, readFileSync, existsSync, mkdirSync} from 'fs'; import config from '../circuit.config'; import {CircuitConfig} from '../types/circuit'; @@ -16,11 +16,19 @@ export function instantiate(name: string, directory: string, circuitConfig?: Cir // generate the main component code const ejsPath = './circuits/ejs/template.circom'; - let circuit = ejs.render(readFileSync(ejsPath).toString(), circuitConfig); + let circuit = ejs.render(readFileSync(ejsPath).toString(), { + ...circuitConfig, + file: circuitConfig.file, // TODO: add ../'s based on dir + }); // output to file - const targetDir = directory || 'main'; - const targetPath = `./circuits/${targetDir}/${name}.circom`; + const targetDir = `./circuits/${directory || 'main'}`; + if (!existsSync(targetDir)) { + mkdirSync(targetDir, { + recursive: true, + }); + } + const targetPath = `${targetDir}/${name}.circom`; writeFileSync(targetPath, circuit); console.log(`Main component created at: ${targetPath}\n`); }