refactors and typed config

This commit is contained in:
Erhan Tezcan
2023-03-31 15:00:57 +03:00
parent d46b5fae90
commit ddb2e296fa
19 changed files with 84 additions and 51 deletions

View File

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

View File

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

View File

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

32
circuit.config.d.ts vendored Normal file
View File

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

View File

@@ -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(", ") %>);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,5 +1,5 @@
{
"name": "circom-typescript-starter",
"name": "circomkit",
"version": "0.0.1",
"description": "A Circom development environment",
"license": "MIT",

View File

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

View File

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

View File

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

View File

@@ -16,5 +16,5 @@
"outDir": "dist"
},
"include": ["src/**/*.ts", "tests/**/*.ts", "types/**/*.ts"],
"exclude": ["node_modules", "build", "dist"]
"exclude": ["node_modules", "build", "dist", "ptau"]
}