mirror of
https://github.com/erhant/circomkit.git
synced 2026-05-05 03:00:37 -04:00
todo: compile should take dirname
This commit is contained in:
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -5,7 +5,8 @@
|
||||
"main": "Controller",
|
||||
"inputs": "Json",
|
||||
"ptau": "Secure",
|
||||
"zkey": "Functions"
|
||||
"zkey": "Functions",
|
||||
"ejs": "JavaScript"
|
||||
},
|
||||
// https://raw.githubusercontent.com/PKief/vscode-material-icon-theme/main/images/fileIcons.png
|
||||
"material-icon-theme.files.associations": {
|
||||
|
||||
37
README.md
37
README.md
@@ -1,6 +1,6 @@
|
||||
# Circom Starter
|
||||
|
||||
> A template repository to write arithmetic circuits.
|
||||
> An opinionated Circom circuit development environment.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -13,32 +13,32 @@ circom-ts-starter
|
||||
├── circuit.config.cjs # configs for circuit main components
|
||||
├── .cli.env # environment variables for cli
|
||||
├── circuits # where you write templates
|
||||
│ ├── main # where you instantiate components
|
||||
│ │ │── foo-main.circom
|
||||
│ ├── main # auto-generated main components
|
||||
│ │ │── sudoku_9x9.circom # e.g. a 9x9 sudoku board
|
||||
│ │ └── ...
|
||||
│ │── foo.circom
|
||||
│ │── sudoku.circom # a generic sudoku template
|
||||
│ └── ...
|
||||
├── inputs # where you write JSON inputs per circuit
|
||||
│ ├── foo
|
||||
│ │ ├── input-name.json
|
||||
│ ├── sudoku_9x9 # each main template has its own folder
|
||||
│ │ ├── input-1.json # e.g. a solution & its puzzle
|
||||
│ │ └── ...
|
||||
│ └── ...
|
||||
├── ptau # universal phase-1 setups
|
||||
│ ├── powersOfTau28_hez_final_12.ptau
|
||||
│ └── ...
|
||||
└── build # artifacts, .gitignore'd
|
||||
│── foo-main
|
||||
│ │── foo-main_js # artifacts of compilation
|
||||
└── build # build artifacts, these are .gitignore'd
|
||||
│── sudoku_9x9 # each main template has its own folder
|
||||
│ │── sudoku_9x9_js # artifacts of compilation
|
||||
│ │ │── generate_witness.js
|
||||
│ │ │── witness_calculator.js
|
||||
│ │ └── foo-main.wasm
|
||||
│ │ └── sudoku_9x9.wasm
|
||||
│ │── input-name # artifacts of witness & proof generation
|
||||
│ │ │── proof.json # proof object
|
||||
│ │ │── public.json # public signals
|
||||
│ │ └── witness.wtns
|
||||
│ │── ... # folders for other inputs
|
||||
│ │── foo-main.r1cs
|
||||
│ │── foo-main.sym
|
||||
│ │── sudoku_9x9.r1cs
|
||||
│ │── sudoku_9x9.sym
|
||||
│ │── prover_key.zkey
|
||||
│ └── verification_key.json
|
||||
└── ...
|
||||
@@ -58,11 +58,14 @@ multiplier3: {
|
||||
Use the [CLI](./scripts/cli.sh), or its wrapper scripts in [package.json](./package.json) to do stuff with your circuits.
|
||||
|
||||
```bash
|
||||
yarn compile -c circuit-name
|
||||
yarn clean -c circuit-name
|
||||
yarn ptau -c circuit-name -n num-contribs -p phase1-ptau-path
|
||||
yarn prove -c circuit-name -i input-name
|
||||
yarn verify -c circuit-name -i input-name
|
||||
# first argument is ALWAYS the circuit name
|
||||
yarn compile circuit-name
|
||||
yarn clean circuit-name
|
||||
yarn ptau circuit-name -n num-contribs -p phase1-ptau-path
|
||||
yarn prove circuit-name -i input-name
|
||||
yarn verify circuit-name -i input-name
|
||||
yarn test circuit-name
|
||||
yarn test:all
|
||||
```
|
||||
|
||||
There are some environment variables that the CLI can make use of, they are written under [.cli.env](./.cli.env) file.
|
||||
|
||||
@@ -7,11 +7,11 @@ module.exports = {
|
||||
templateInputs: [3],
|
||||
},
|
||||
// A 9x9 sudoku board
|
||||
sudoku9: {
|
||||
sudoku_9x9: {
|
||||
file: 'sudoku',
|
||||
template: 'Sudoku',
|
||||
publicInputs: ['puzzle'],
|
||||
templateInputs: [3],
|
||||
templateInputs: [Math.sqrt(9)],
|
||||
},
|
||||
// 64-bit floating point, 11-bit exponent and 52-bit mantissa
|
||||
fp64: {
|
||||
@@ -27,4 +27,19 @@ module.exports = {
|
||||
publicInputs: [],
|
||||
templateInputs: [8, 23],
|
||||
},
|
||||
// 11-th Fibonacci number
|
||||
fibonacci_11: {
|
||||
file: 'fibonacci',
|
||||
template: 'Fibonacci',
|
||||
publicInputs: [],
|
||||
templateInputs: [11],
|
||||
},
|
||||
// checks that a number fits to given bit count
|
||||
checkBitLength: {
|
||||
file: 'float_add',
|
||||
template: 'CheckBitLength',
|
||||
publicInputs: [],
|
||||
templateInputs: [3],
|
||||
dir: 'util',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// auto-generated by instantiate.js
|
||||
pragma circom 2.0.0;
|
||||
|
||||
include "../../circuits/<%= file %>.circom";
|
||||
include "../<%= file %>.circom";
|
||||
|
||||
component main<%=
|
||||
publicInputs.length == 0 ?
|
||||
@@ -7,7 +7,7 @@ template Fibonacci(n) {
|
||||
signal output out;
|
||||
|
||||
// compute the sequence
|
||||
signal f[n+1];
|
||||
signal fib[n+1];
|
||||
fib[0] <== in[0];
|
||||
fib[1] <== in[1];
|
||||
for (var i = 2; i <= n; i++) {
|
||||
|
||||
6
circuits/main/fibonacci_11.circom
Normal file
6
circuits/main/fibonacci_11.circom
Normal file
@@ -0,0 +1,6 @@
|
||||
// auto-generated by instantiate.js
|
||||
pragma circom 2.0.0;
|
||||
|
||||
include "../../circuits/fibonacci.circom";
|
||||
|
||||
component main = Fibonacci(11);
|
||||
@@ -10,7 +10,7 @@ template Multiplier2() {
|
||||
}
|
||||
|
||||
// Multiplication of N numbers
|
||||
template Multiplier(N){
|
||||
template Multiplier(N) {
|
||||
signal input in[N];
|
||||
signal output out;
|
||||
component comp[N-1];
|
||||
|
||||
6
circuits/util/checkBitLength.circom
Normal file
6
circuits/util/checkBitLength.circom
Normal file
@@ -0,0 +1,6 @@
|
||||
// auto-generated by instantiate.js
|
||||
pragma circom 2.0.0;
|
||||
|
||||
include "../float_add.circom";
|
||||
|
||||
component main = CheckBitLength(3);
|
||||
15
package.json
15
package.json
@@ -4,13 +4,14 @@
|
||||
"description": "A Circom development environment",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "npx mocha",
|
||||
"type": "./scripts/cli.sh -f type",
|
||||
"compile": "./scripts/cli.sh -f compile",
|
||||
"clean": "./scripts/cli.sh -f clean",
|
||||
"ptau": "./scripts/cli.sh -f ptau",
|
||||
"prove": "./scripts/cli.sh -f prove",
|
||||
"verify": "./scripts/cli.sh -f verify",
|
||||
"test:all": "npx mocha",
|
||||
"test": "npx mocha --grep",
|
||||
"type": "./scripts/cli.sh -f type -c",
|
||||
"compile": "./scripts/cli.sh -f compile -c",
|
||||
"clean": "./scripts/cli.sh -f clean -c",
|
||||
"ptau": "./scripts/cli.sh -f ptau -c",
|
||||
"prove": "./scripts/cli.sh -f prove -c",
|
||||
"verify": "./scripts/cli.sh -f verify -c",
|
||||
"_help": "./scripts/cli.sh -f help"
|
||||
},
|
||||
"author": "erhant",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const ejs = require('ejs');
|
||||
const {writeFileSync, readFileSync} = require('fs');
|
||||
const {writeFileSync, readFileSync, existsSync, mkdirSync} = require('fs');
|
||||
const config = require('../circuit.config.cjs');
|
||||
|
||||
// read circuit from config
|
||||
@@ -9,9 +9,20 @@ if (!(target in config)) {
|
||||
}
|
||||
|
||||
// generate the main component code
|
||||
let circuit = ejs.render(readFileSync('./circuits/main/_template.circom').toString(), config[target]);
|
||||
const templatePath = './circuits/ejs/template.circom';
|
||||
let circuit = ejs.render(readFileSync(templatePath).toString(), config[target]);
|
||||
|
||||
// output to file
|
||||
const targetPath = `./circuits/main/${target}.circom`;
|
||||
const dirName = config[target].dir ? config[target].dir : 'main';
|
||||
if (typeof dirName !== 'string') {
|
||||
throw new Error(`Bad target type.`);
|
||||
}
|
||||
|
||||
const dir = `./circuits/${dirName}`;
|
||||
if (!existsSync(dir)) {
|
||||
mkdirSync(dir, {recursive: true});
|
||||
}
|
||||
|
||||
const targetPath = `${dir}/${target}.circom`;
|
||||
writeFileSync(targetPath, circuit);
|
||||
console.log(`Main component created at: ${targetPath}\n`);
|
||||
|
||||
40
tests/fibonacci.test.ts
Normal file
40
tests/fibonacci.test.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import {createWasmTester} from '../utils/wasmTester';
|
||||
import type {CircuitSignals} from '../types/circuit';
|
||||
|
||||
function fibonacci(init: [number, number], n: number): number {
|
||||
let [a, b] = init;
|
||||
for (let i = 2; i <= n; i++) {
|
||||
b = a + b;
|
||||
a = b - a;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
const CIRCUIT_NAME = 'fibonacci_11';
|
||||
describe(CIRCUIT_NAME, () => {
|
||||
const INPUT: CircuitSignals = {
|
||||
in: [1, 1],
|
||||
};
|
||||
|
||||
describe('witness computation', () => {
|
||||
let circuit: Awaited<ReturnType<typeof createWasmTester>>;
|
||||
|
||||
before(async () => {
|
||||
circuit = await createWasmTester(CIRCUIT_NAME);
|
||||
});
|
||||
|
||||
it('should compute correctly', async () => {
|
||||
// compute witness
|
||||
const witness = await circuit.calculateWitness(INPUT, true);
|
||||
|
||||
// witness should have valid constraints
|
||||
await circuit.checkConstraints(witness);
|
||||
|
||||
// witness should have correct output
|
||||
const output = {
|
||||
out: fibonacci(INPUT.in, 11),
|
||||
};
|
||||
await circuit.assertOut(witness, output);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -13,7 +13,7 @@ describe(CIRCUIT_NAME, () => {
|
||||
let circuit: Awaited<ReturnType<typeof createWasmTester>>;
|
||||
|
||||
before(async () => {
|
||||
circuit = await createWasmTester('./circuits/main/' + CIRCUIT_NAME + '.circom', true);
|
||||
circuit = await createWasmTester(CIRCUIT_NAME);
|
||||
});
|
||||
|
||||
it('should compute correctly', async () => {
|
||||
@@ -55,7 +55,6 @@ describe(CIRCUIT_NAME, () => {
|
||||
|
||||
describe('proof verification', () => {
|
||||
let fullProof: FullProof;
|
||||
|
||||
const circuit = new ProofTester(CIRCUIT_NAME);
|
||||
|
||||
before(async () => {
|
||||
|
||||
@@ -12,7 +12,7 @@ describe(CIRCUIT_NAME, () => {
|
||||
let circuit: Awaited<ReturnType<typeof createWasmTester>>;
|
||||
|
||||
before(async () => {
|
||||
circuit = await createWasmTester('./circuits/main/' + CIRCUIT_NAME + '.circom', true);
|
||||
circuit = await createWasmTester(CIRCUIT_NAME);
|
||||
});
|
||||
|
||||
it('should compute correctly', async () => {
|
||||
|
||||
@@ -38,8 +38,7 @@ type WasmTester = {
|
||||
loadConstraints(): Promise<void>;
|
||||
|
||||
/**
|
||||
* List of constraints, must call `loadConstraints` before
|
||||
* accessing this key
|
||||
* List of constraints, must call `loadConstraints` before accessing this key
|
||||
*/
|
||||
constraints: any[] | undefined;
|
||||
|
||||
@@ -68,11 +67,16 @@ type WasmTester = {
|
||||
/**
|
||||
* Compiles and reutrns a circuit via `circom_tester`'s `wasm_tester`.
|
||||
* @param circuit name of circuit
|
||||
* @param dir directory to read the circuit from, defaults to `main`
|
||||
* @param showNumConstraints print number of constraints, defualts to `false`
|
||||
* @returns a `wasm_tester` object
|
||||
*/
|
||||
export async function createWasmTester(path: string, showNumConstraints: boolean = false): Promise<WasmTester> {
|
||||
const circuit = await wasm_tester(path, {
|
||||
export async function createWasmTester(
|
||||
circuitName: string,
|
||||
dir: string = 'main',
|
||||
showNumConstraints: boolean = false
|
||||
): Promise<WasmTester> {
|
||||
const circuit = await wasm_tester(`./circuits/${dir}/${circuitName}.circom`, {
|
||||
include: 'node_modules', // will link circomlib circuits
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user