todo: compile should take dirname

This commit is contained in:
Erhan Tezcan
2023-03-31 00:10:49 +03:00
parent 29bc8f834f
commit d46b5fae90
15 changed files with 126 additions and 40 deletions

View File

@@ -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": {

View File

@@ -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.

View 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',
},
};

View File

@@ -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 ?

View File

@@ -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++) {

View File

@@ -0,0 +1,6 @@
// auto-generated by instantiate.js
pragma circom 2.0.0;
include "../../circuits/fibonacci.circom";
component main = Fibonacci(11);

View File

@@ -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];

View File

@@ -0,0 +1,6 @@
// auto-generated by instantiate.js
pragma circom 2.0.0;
include "../float_add.circom";
component main = CheckBitLength(3);

View File

@@ -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",

View File

@@ -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
View 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);
});
});
});

View File

@@ -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 () => {

View File

@@ -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 () => {

View File

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