mirror of
https://github.com/erhant/circomkit.git
synced 2026-05-05 03:00:37 -04:00
smol fixes
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
"extends": "./node_modules/gts/",
|
||||
"rules": {
|
||||
"node/no-unpublished-import": ["off"],
|
||||
"node/no-unpublished-require": ["off"],
|
||||
"@typescript-eslint/no-explicit-any": ["off"]
|
||||
"node/no-unpublished-require": ["off"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"ol-prefix": false,
|
||||
"line-length": false
|
||||
}
|
||||
41
README.md
41
README.md
@@ -44,27 +44,27 @@ Using Circomkit is easy:
|
||||
|
||||
1. Install [Circom](https://docs.circom.io/getting-started/installation/).
|
||||
2. Clone this repo (or use it as a template) and install packages (`yarn` or `npm install`).
|
||||
3. Write your circuit templates under the `circuits` folder. Your circuit code itself should be templates only; Circomkit programmatically generates the `main` component
|
||||
4. Write your tests under the `tests` folder.
|
||||
5. Once you are ready, write the circuit config in [`circuit.config.ts`](./circuit.config.ts).
|
||||
3. Write your circuit templates under the [circuits](./circuits/) folder. Your circuit code itself should be templates only; Circomkit programmatically generates the `main` component
|
||||
4. Write your tests under the [tests](./tests/) folder.
|
||||
5. Once you are ready, write the circuit configurations at [circuits.json](./circuits.json).
|
||||
6. Use NPM scripts (`yarn <script>` or `npm run <script>`) to compile your circuit, build keys, generate & verify proofs and much more!
|
||||
|
||||
A circuit config looks like this:
|
||||
|
||||
```js
|
||||
sudoku_4x4: { // the key is <circuit-name>
|
||||
file: 'sudoku', // file name (circuits/sudoku.circom)
|
||||
template: 'Sudoku', // template name
|
||||
pubs: ['puzzle'], // public signals
|
||||
params: [Math.sqrt(4)], // template parameters
|
||||
dir: "main" // output directory for main component
|
||||
// the key is <circuit-name>
|
||||
sudoku_4x4: {
|
||||
file: 'sudoku', // file name (circuits/sudoku.circom)
|
||||
template: 'Sudoku', // template name
|
||||
pubs: ['puzzle'], // public signals
|
||||
params: [Math.sqrt(4)], // template parameters
|
||||
},
|
||||
```
|
||||
|
||||
You can omit `pubs`, `params` and `dir` options, they have defaults. Afterwards, you can use the following commands:
|
||||
You can omit `pubs` and `params` options, they default to `[]`. Afterwards, you can use the following commands:
|
||||
|
||||
```bash
|
||||
# Compile the circuit (generates the main component too)
|
||||
# Compile the circuit (generates the main component & compiles it)
|
||||
yarn compile circuit-name
|
||||
|
||||
# Circuit setup
|
||||
@@ -83,7 +83,7 @@ yarn clean circuit-name
|
||||
yarn instantiate circuit-name
|
||||
```
|
||||
|
||||
You can change some general settings such as the configured proof system or the prime field under [`.cli.env`](./.cli.env).
|
||||
You can change some general settings such as the configured proof system or the prime field under [circomkit.env](./circomkit.env).
|
||||
|
||||
### Working with Input Signals
|
||||
|
||||
@@ -166,7 +166,7 @@ With the circuit object, we can do the following:
|
||||
- `circuit.expectCorrectAssert(input)` to test whether the circuit assertions pass for some given input
|
||||
- `circuit.expectFailedAssert(input)` to test whether the circuit assertions pass for some given input
|
||||
|
||||
#### Witnes
|
||||
#### Witness
|
||||
|
||||
What if we would just like to see what the output is, instead of comparing it to some witness? Well, that would be a trouble because we would have to parse the witness array (which is huge for some circuits) with respect to which signals the output signals correspond to. Thankfully, Circomkit has a function for that:
|
||||
|
||||
@@ -180,6 +180,17 @@ const output = await circuit.compute(INPUT, ['foo', 'bar']);
|
||||
|
||||
Note that this operation requires parsing the symbols file (`.sym`) and reading the witness array, which may be costly for large circuits. Most of the time, you won't need this for testing; instead, you will likely use it to see what the circuit actually does for debugging.
|
||||
|
||||
On top of these, you can create a fake witness by overriding symbols in the witness. This is useful in case you think there is a soundness error and would like to try and generate an adversarial witness.
|
||||
|
||||
```ts
|
||||
// correct witness
|
||||
const witness = await circuit.calculateWitness(INPUT);
|
||||
// faked witness
|
||||
const fakeWitness = await circuit.fakeWitness(witness, {
|
||||
'symbol-names-here': 42n,
|
||||
});
|
||||
```
|
||||
|
||||
#### Multiple templates
|
||||
|
||||
You will often have multiple templates in your circuit code, and you might want to test them in the same test file of your main circuit too. Well, you can!
|
||||
@@ -241,8 +252,8 @@ The repository follows an _opinionated file structure_ shown below, abstracting
|
||||
|
||||
```sh
|
||||
circomkit
|
||||
├── circuit.config.cjs # configs for circuit main components
|
||||
├── .cli.env # environment variables for cli
|
||||
├── circuits.json # configs for circuit main components
|
||||
├── circomkit.env # environment variables for cli
|
||||
├── circuits # where you write templates
|
||||
│ ├── main # auto-generated main components
|
||||
│ │ │── sudoku_9x9.circom # e.g. a 9x9 sudoku board
|
||||
|
||||
@@ -17,7 +17,7 @@ export default class ProofTester<IN extends string[] = []> {
|
||||
private readonly wasmPath: string;
|
||||
private readonly proverKeyPath: string;
|
||||
private readonly verificationKeyPath: string;
|
||||
private readonly verificationKey: any;
|
||||
private readonly verificationKey: unknown & {protocol: ProofSystem};
|
||||
|
||||
/**
|
||||
* Sets the paths & loads the verification key. The underlying proof system is checked by looking
|
||||
@@ -42,10 +42,11 @@ export default class ProofTester<IN extends string[] = []> {
|
||||
) as typeof this.verificationKey;
|
||||
|
||||
// check proof system
|
||||
if (!PROOF_SYSTEMS.includes(this.verificationKey.protocol)) {
|
||||
throw new Error('Unknown protocol in verification key: ' + this.verificationKey.protocol);
|
||||
const protocol = this.verificationKey.protocol;
|
||||
if (!PROOF_SYSTEMS.includes(protocol)) {
|
||||
throw new Error('Unknown protocol in verification key: ' + protocol);
|
||||
}
|
||||
this.protocol = this.verificationKey.protocol;
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,7 @@ export type CircomWasmTester = {
|
||||
assertOut: (actualOut: WitnessType, expectedOut: CircuitSignals) => Promise<void>;
|
||||
calculateWitness: (input: CircuitSignals, sanityCheck: boolean) => Promise<WitnessType>;
|
||||
loadConstraints: () => Promise<void>;
|
||||
constraints: any[] | undefined;
|
||||
constraints: unknown[] | undefined;
|
||||
loadSymbols: () => Promise<void>;
|
||||
symbols: SymbolsType | undefined;
|
||||
getDecoratedOutput: (witness: WitnessType) => Promise<string>;
|
||||
|
||||
@@ -21,7 +21,7 @@ export default class WasmTester<IN extends readonly string[] = [], OUT extends r
|
||||
/**
|
||||
* List of constraints, must call `loadConstraints` before accessing this key
|
||||
*/
|
||||
constraints: any[] | undefined;
|
||||
constraints: unknown[] | undefined;
|
||||
|
||||
constructor(circomWasmTester: CircomWasmTester) {
|
||||
this.circomWasmTester = circomWasmTester;
|
||||
@@ -46,10 +46,10 @@ export default class WasmTester<IN extends readonly string[] = [], OUT extends r
|
||||
|
||||
/**
|
||||
* Compute witness given the input signals.
|
||||
* @param input all signals, private and public.
|
||||
* @param sanityCheck check if input signals are sanitized
|
||||
* @param input all signals, private and public
|
||||
* @param sanityCheck check if input signals are sanitized, defaults to `true`
|
||||
*/
|
||||
calculateWitness(input: CircuitSignals<IN>, sanityCheck: boolean): Promise<WitnessType> {
|
||||
calculateWitness(input: CircuitSignals<IN>, sanityCheck = true): Promise<WitnessType> {
|
||||
return this.circomWasmTester.calculateWitness(input, sanityCheck);
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ export default class WasmTester<IN extends readonly string[] = [], OUT extends r
|
||||
* @param input bad input
|
||||
*/
|
||||
async expectFailedAssert(input: CircuitSignals<IN>) {
|
||||
await this.calculateWitness(input, true).then(
|
||||
await this.calculateWitness(input).then(
|
||||
() => assert.fail(),
|
||||
err => expect(err.message.slice(0, 21)).to.eq('Error: Assert Failed.')
|
||||
);
|
||||
@@ -137,7 +137,7 @@ export default class WasmTester<IN extends readonly string[] = [], OUT extends r
|
||||
* @param output expected output, if `undefined` it will only check constraints
|
||||
*/
|
||||
async expectCorrectAssert(input: CircuitSignals<IN>, output?: CircuitSignals<OUT>) {
|
||||
const witness = await this.calculateWitness(input, true);
|
||||
const witness = await this.calculateWitness(input);
|
||||
await this.checkConstraints(witness);
|
||||
if (output) {
|
||||
await this.assertOut(witness, output);
|
||||
@@ -161,7 +161,7 @@ export default class WasmTester<IN extends readonly string[] = [], OUT extends r
|
||||
*/
|
||||
async compute(input: CircuitSignals<IN>, outputSignals: OUT): Promise<CircuitSignals<typeof outputSignals>> {
|
||||
// compute witness & check constraints
|
||||
const witness = await this.calculateWitness(input, true);
|
||||
const witness = await this.calculateWitness(input);
|
||||
await this.checkConstraints(witness);
|
||||
|
||||
// get symbols of main component
|
||||
|
||||
Reference in New Issue
Block a user