diff --git a/.cli.env b/.cli.env index 7b6c0e5..5c8af4e 100644 --- a/.cli.env +++ b/.cli.env @@ -2,6 +2,6 @@ CLIENV_COMPILER_ARGS="-l ./node_modules" # colors for swag -CLIENV_COLOR_TITLE='\033[0;34m' # blue color -CLIENV_COLOR_LOG='\033[2;37m' # gray color -CLIENV_COLOR_RESET='\033[0m' # reset color settings +CLIENV_COLOR_TITLE='\033[0;34m' # blue +CLIENV_COLOR_LOG='\033[2;37m' # gray +CLIENV_COLOR_RESET='\033[0m' # reset color diff --git a/README.md b/README.md index 54b11fb..2ba646d 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ -# Circom Starter +# Circomkit > An opinionated Circom circuit development environment. ## Usage -Clone the repository or create a new one with this as the template! You need [Circom](https://docs.circom.io/getting-started/installation/) to compile circuits. Other than that, just `yarn` or `npm install` to get started. +Clone the repository or create a new one with this as the template! You need [Circom](https://docs.circom.io/getting-started/installation/) to compile circuits. Other than that, just `yarn` or `npm install` to get started. It will also install [Circomlib](https://github.com/iden3/circomlib/tree/master/circuits) which has many utility circuits. The repository follows an _opinionated file structure_ shown below, abstracting away the pathing and orientation behind the scenes. Shell scripts handle most of the work, and they are exposed through a [CLI](./scripts/main.sh). ```sh -circom-ts-starter +circomkit ├── circuit.config.cjs # configs for circuit main components ├── .cli.env # environment variables for cli ├── circuits # where you write templates @@ -20,7 +20,7 @@ circom-ts-starter │ └── ... ├── inputs # where you write JSON inputs per circuit │ ├── sudoku_9x9 # each main template has its own folder -│ │ ├── input-1.json # e.g. a solution & its puzzle +│ │ ├── example-input.json # e.g. a solution & its puzzle │ │ └── ... │ └── ... ├── ptau # universal phase-1 setups @@ -32,7 +32,7 @@ circom-ts-starter │ │ │── generate_witness.js │ │ │── witness_calculator.js │ │ └── sudoku_9x9.wasm - │ │── input-name # artifacts of witness & proof generation + │ │── example-input # artifacts of witness & proof generation │ │ │── proof.json # proof object │ │ │── public.json # public signals │ │ └── witness.wtns @@ -44,14 +44,14 @@ circom-ts-starter └── ... ``` -Write your circuits under `circuits` folder; the circuit code itself should be templates only. The main component itself is created automatically via a [script](./scripts/instantiate.js) which uses a simple EJS [template](./circuits/main/_template.circom) to create the main component. The target circuits are defined under the [circuit configs](./circuit.config.cjs) file, such as: +Write your circuits under `circuits` folder; the circuit code itself should be templates only. The main component itself is created automatically via a [script](./scripts/instantiate.js) which uses a simple EJS [template](./circuits/ejs/_template.circom) to create the main component. The target circuits are defined under the [circuit configs](./circuit.config.cjs) file, such as: ```js multiplier3: { template: 'Multiplier', // template to instantiate the main component file: 'multiplier', // file to include for the template publicInputs: [], // array of public inputs - templateInputs: [3], // template parameters, order is important + templateParams: [3], // template parameters, order is important } ``` @@ -88,4 +88,4 @@ Within each test, there are two sub-tests: ## Styling -The code uses Google TypeScript Style guide. It also has some folder & file icon overrides for several Material UI icons to make things look better. +The code uses Google TypeScript Style guide. It also has some folder & file icon overrides for several Material UI icons to make things look better in VSCode. diff --git a/circuit.config.cjs b/circuit.config.cjs index 41404d6..dc9612a 100644 --- a/circuit.config.cjs +++ b/circuit.config.cjs @@ -1,45 +1,49 @@ -module.exports = { +/** + * @type {import("./circuit.config").Config} + */ +const config = { // multiplication of 3 numbers multiplier3: { file: 'multiplier', template: 'Multiplier', publicInputs: [], - templateInputs: [3], + templateParams: [3], }, // A 9x9 sudoku board sudoku_9x9: { file: 'sudoku', template: 'Sudoku', publicInputs: ['puzzle'], - templateInputs: [Math.sqrt(9)], + templateParams: [Math.sqrt(9)], }, // 64-bit floating point, 11-bit exponent and 52-bit mantissa fp64: { file: 'float_add', template: 'FloatAdd', publicInputs: [], - templateInputs: [11, 52], + templateParams: [11, 52], }, // 32-bit floating point, 8-bit exponent and 23-bit mantissa fp32: { file: 'float_add', template: 'FloatAdd', publicInputs: [], - templateInputs: [8, 23], + templateParams: [8, 23], }, // 11-th Fibonacci number fibonacci_11: { file: 'fibonacci', template: 'Fibonacci', publicInputs: [], - templateInputs: [11], + templateParams: [11], }, // checks that a number fits to given bit count checkBitLength: { file: 'float_add', template: 'CheckBitLength', publicInputs: [], - templateInputs: [3], - dir: 'util', + templateParams: [3], }, }; + +module.exports = config; diff --git a/circuit.config.d.ts b/circuit.config.d.ts new file mode 100644 index 0000000..d77afd3 --- /dev/null +++ b/circuit.config.d.ts @@ -0,0 +1,32 @@ +/** + * Configuration file for your circuits. + */ +export type Config = { + [circuitName: string]: { + /** + * File to read the template from + */ + file: string; + + /** + * The template name to instantiate + */ + template: string; + + /** + * An array of public input signal names + */ + publicInputs: string[]; + + /** + * An array of template parameters + */ + templateParams: (number | bigint)[]; + + /** + * Directory to output under `circuits`, defaults to `main` + * @depracated work in progress, use `main` for now (leave empty) + */ + dir?: string; + }; +}; diff --git a/circuits/ejs/template.circom b/circuits/ejs/template.circom index a136764..1bf9519 100644 --- a/circuits/ejs/template.circom +++ b/circuits/ejs/template.circom @@ -1,5 +1,6 @@ <%#'this file is an EJS template to generate main component for circuits'-%> <%#'configuration is read from config.js in the project root directory'-%> +<%#'do not edit this file!'-%> // auto-generated by instantiate.js pragma circom 2.0.0; @@ -9,4 +10,4 @@ component main<%= publicInputs.length == 0 ? '' : ' {public[' + publicInputs.join(", ") + ']}' - %> = <%= template %>(<%= templateInputs.join(", ") %>); + %> = <%= template %>(<%= templateParams.join(", ") %>); diff --git a/circuits/main/fibonacci_11.circom b/circuits/main/fibonacci_11.circom index 5ae5949..6c71a4f 100644 --- a/circuits/main/fibonacci_11.circom +++ b/circuits/main/fibonacci_11.circom @@ -1,6 +1,6 @@ // auto-generated by instantiate.js pragma circom 2.0.0; -include "../../circuits/fibonacci.circom"; +include "../fibonacci.circom"; component main = Fibonacci(11); diff --git a/circuits/main/fp32.circom b/circuits/main/fp32.circom index bd56a09..2f5dbb7 100644 --- a/circuits/main/fp32.circom +++ b/circuits/main/fp32.circom @@ -1,6 +1,6 @@ // auto-generated by instantiate.js pragma circom 2.0.0; -include "../../circuits/float_add.circom"; +include "../float_add.circom"; component main = FloatAdd(8, 23); diff --git a/circuits/main/fp64.circom b/circuits/main/fp64.circom index b256872..ad755fd 100644 --- a/circuits/main/fp64.circom +++ b/circuits/main/fp64.circom @@ -1,6 +1,6 @@ // auto-generated by instantiate.js pragma circom 2.0.0; -include "../../circuits/float_add.circom"; +include "../float_add.circom"; component main = FloatAdd(11, 52); diff --git a/circuits/main/multiplier3.circom b/circuits/main/multiplier3.circom index ba67f1c..a8559aa 100644 --- a/circuits/main/multiplier3.circom +++ b/circuits/main/multiplier3.circom @@ -1,6 +1,6 @@ // auto-generated by instantiate.js pragma circom 2.0.0; -include "../../circuits/multiplier.circom"; +include "../multiplier.circom"; component main = Multiplier(3); diff --git a/circuits/main/sudoku_9x9.circom b/circuits/main/sudoku_9x9.circom index b2136ed..747745f 100644 --- a/circuits/main/sudoku_9x9.circom +++ b/circuits/main/sudoku_9x9.circom @@ -1,6 +1,6 @@ // auto-generated by instantiate.js pragma circom 2.0.0; -include "../../circuits/sudoku.circom"; +include "../sudoku.circom"; component main {public[puzzle]} = Sudoku(3); diff --git a/circuits/multiplier.circom b/circuits/multiplier.circom index d2f0f8a..9b8c488 100644 --- a/circuits/multiplier.circom +++ b/circuits/multiplier.circom @@ -1,12 +1,9 @@ pragma circom 2.0.0; // Multiplication of two numbers -template Multiplier2() { - signal input in1; - signal input in2; - signal output out; - - out <== in1 * in2; +template MultiplicationGate() { + signal input in[2]; + signal output out <== in[0] * in[1]; } // Multiplication of N numbers @@ -15,17 +12,15 @@ template Multiplier(N) { signal output out; component comp[N-1]; - // instantiate multiplier2 gates + // instantiate gates for (var i = 0; i < N-1; i++) { - comp[i] = Multiplier2(); + comp[i] = MultiplicationGate(); } // multiply - comp[0].in1 <== in[0]; - comp[0].in2 <== in[1]; - for(var i = 0; i < N-2; i++){ - comp[i+1].in1 <== comp[i].out; - comp[i+1].in2 <== in[i+2]; + comp[0].in <== [in[0], in[1]]; + for(var i = 0; i < N-2; i++) { + comp[i+1].in <== [comp[i].out, in[i+2]]; } out <== comp[N-2].out; } diff --git a/circuits/sudoku.circom b/circuits/sudoku.circom index c0693fe..cdc666f 100644 --- a/circuits/sudoku.circom +++ b/circuits/sudoku.circom @@ -1,5 +1,7 @@ pragma circom 2.0.0; +// include "circomlib/circuits/" TODO TODO + // Assert that two elements are not equal. // Done via the check if in0 - in1 is non-zero. template NonEqual() { diff --git a/circuits/util/checkBitLength.circom b/circuits/util/checkBitLength.circom deleted file mode 100644 index 5743c1a..0000000 --- a/circuits/util/checkBitLength.circom +++ /dev/null @@ -1,6 +0,0 @@ -// auto-generated by instantiate.js -pragma circom 2.0.0; - -include "../float_add.circom"; - -component main = CheckBitLength(3); diff --git a/inputs/sudoku9/foo.json b/inputs/sudoku_9x9/example.json similarity index 100% rename from inputs/sudoku9/foo.json rename to inputs/sudoku_9x9/example.json diff --git a/package.json b/package.json index b8a9ba6..1736a91 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "circom-typescript-starter", + "name": "circomkit", "version": "0.0.1", "description": "A Circom development environment", "license": "MIT", diff --git a/scripts/functions/compile.sh b/scripts/functions/compile.sh index 3a0cd28..ffc1592 100755 --- a/scripts/functions/compile.sh +++ b/scripts/functions/compile.sh @@ -2,12 +2,12 @@ compile() { echo -e "\n${CLIENV_COLOR_TITLE}=== Compiling the circuit ===${CLIENV_COLOR_RESET}" local CIRCUIT=$1 - local CIRCOM_IN=./circuits/main/$CIRCUIT.circom - local CIRCOM_OUT=./build/$CIRCUIT # generate the circuit main component node ./scripts/instantiate.js $CIRCUIT - + local CIRCOM_IN=./circuits/main/$CIRCUIT.circom + local CIRCOM_OUT=./build/$CIRCUIT + # create build dir if not exists already mkdir -p $CIRCOM_OUT diff --git a/tests/fibonacci.test.ts b/tests/fibonacci.test.ts index cdfc555..311d334 100644 --- a/tests/fibonacci.test.ts +++ b/tests/fibonacci.test.ts @@ -1,13 +1,18 @@ import {createWasmTester} from '../utils/wasmTester'; import type {CircuitSignals} from '../types/circuit'; +// simple fibonacci with 2 variables function fibonacci(init: [number, number], n: number): number { + if (n < 0) { + throw new Error('N must be positive'); + } + let [a, b] = init; for (let i = 2; i <= n; i++) { b = a + b; a = b - a; } - return b; + return n == 0 ? a : b; } const CIRCUIT_NAME = 'fibonacci_11'; diff --git a/tests/sudoku.test.ts b/tests/sudoku.test.ts index 7ad1439..3846985 100644 --- a/tests/sudoku.test.ts +++ b/tests/sudoku.test.ts @@ -2,7 +2,7 @@ import {createWasmTester} from '../utils/wasmTester'; import type {CircuitSignals, FullProof} from '../types/circuit'; import {assert, expect} from 'chai'; // read inputs from file -import inputfoo from '../inputs/sudoku9/foo.json'; +import inputfoo from '../inputs/sudoku_9x9/example.json'; const CIRCUIT_NAME = 'sudoku9'; describe(CIRCUIT_NAME, () => { diff --git a/tsconfig.json b/tsconfig.json index c25f501..f6ece09 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,5 +16,5 @@ "outDir": "dist" }, "include": ["src/**/*.ts", "tests/**/*.ts", "types/**/*.ts"], - "exclude": ["node_modules", "build", "dist"] + "exclude": ["node_modules", "build", "dist", "ptau"] }