mirror of
https://github.com/erhant/circomkit.git
synced 2026-05-05 03:00:37 -04:00
better proof system checker
This commit is contained in:
2
.cli.env
2
.cli.env
@@ -1,5 +1,5 @@
|
||||
# compiler args, can add --inspect and -c for example
|
||||
CIRCOMKIT_COMPILER_ARGS="-l ./node_modules --r1cs --wasm --sym"
|
||||
CIRCOMKIT_COMPILER_ARGS="-l ./node_modules --r1cs --wasm --sym -c"
|
||||
|
||||
# proof system to be used, can be: groth16 | plonk | fflonk
|
||||
CIRCOMKIT_PROOF_SYSTEM="groth16"
|
||||
|
||||
42
TODO.md
Normal file
42
TODO.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# TODOs
|
||||
|
||||
The two features in plan right now is the following:
|
||||
|
||||
- [ ] **Multiple Backends**: We only use WASM & SnarkJS right now, but we would like to export prover libraries for other backends such as mobile.
|
||||
- [ ] **Type Generation**: Generate input & output signal type declarations for a given circuit, [work in progress](./scripts/functions/type.sh).
|
||||
|
||||
## Multiple Backends
|
||||
|
||||
The default code generates a WASM circuit and does tests in NodeJS environment. We would like to have an easy guide to show how proof generation can be done on other backends for a given circuit too.
|
||||
|
||||
Some resources on this:
|
||||
|
||||
- [iden3 Rapidsnark](https://github.com/iden3/go-rapidsnark) computes witness, generates & verifies proofs in Go.
|
||||
- [polygonId witnesscalc](https://github.com/0xPolygonID/witnesscalc) has witness computation build files for many backends.
|
||||
|
||||
## Type Generation
|
||||
|
||||
We would like to generate types from input and output signals. For example,
|
||||
|
||||
```c
|
||||
template Multiplier(N) {
|
||||
signal input in[N];
|
||||
signal output out;
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
could have input and output signals as
|
||||
|
||||
```ts
|
||||
type inputs = {
|
||||
in: Array<bigint>;
|
||||
};
|
||||
type outputs = {
|
||||
out: bigint;
|
||||
};
|
||||
```
|
||||
|
||||
We could ignore the input size (`in` array should precisely have `N` elements for the example above) because the array size can be computed at runtime within Circom, which makes things a lot more complicated.
|
||||
|
||||
Our `type` script almost does the job, but so far I couldn't find a good way to determine the output signal itself, or ignore intermediate signals.
|
||||
@@ -57,7 +57,7 @@ describe('multiplier utilities', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe.skip('multiplier proofs', () => {
|
||||
describe('multiplier proofs', () => {
|
||||
const N = 3;
|
||||
|
||||
let fullProof: FullProof;
|
||||
|
||||
@@ -3,38 +3,50 @@ const snarkjs = require('snarkjs');
|
||||
import {expect} from 'chai';
|
||||
import type {CircuitSignals, FullProof, ProofSystem} from '../types/circuit';
|
||||
|
||||
// Make a const assertion
|
||||
// see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions
|
||||
const PROOF_SYSTEMS = ['groth16', 'plonk', 'fflonk'] as const;
|
||||
|
||||
/**
|
||||
* A more extensive Circuit class, able to generate proofs & verify them.
|
||||
* Assumes that prover key and verifier key have been computed.
|
||||
*/
|
||||
export class ProofTester {
|
||||
public readonly proofSystem: ProofSystem;
|
||||
public readonly protocol: (typeof PROOF_SYSTEMS)[number];
|
||||
private readonly wasmPath: string;
|
||||
private readonly proverKeyPath: string;
|
||||
private readonly verificationKey: object;
|
||||
private readonly verificationKeyPath: string;
|
||||
private readonly verificationKey: object & {
|
||||
protocol: ProofSystem;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the paths & loads the verification key
|
||||
* Sets the paths & loads the verification key. The underlying proof system is checked by looking
|
||||
* at `verificationKey.protocol`.
|
||||
* @param circuit a proof tester
|
||||
* @param proofSystem proof system to use, defaults to `groth16`
|
||||
*/
|
||||
constructor(circuit: string, proofSystem: ProofSystem = 'groth16') {
|
||||
constructor(circuit: string) {
|
||||
// find paths (computed w.r.t circuit name)
|
||||
this.wasmPath = `./build/${circuit}/${circuit}_js/${circuit}.wasm`;
|
||||
this.proverKeyPath = `./build/${circuit}/prover_key.zkey`;
|
||||
const verificationKeyPath = `./build/${circuit}/verification_key.json`;
|
||||
this.verificationKeyPath = `./build/${circuit}/verification_key.json`;
|
||||
|
||||
// ensure that paths exist
|
||||
const missing = [this.wasmPath, this.proverKeyPath, verificationKeyPath].filter(p => !fs.existsSync(p));
|
||||
const missing = [this.wasmPath, this.proverKeyPath, this.verificationKeyPath].filter(p => !fs.existsSync(p));
|
||||
if (missing.length !== 0) {
|
||||
throw new Error('Missing files for' + circuit + '\n' + missing);
|
||||
throw new Error('Missing files for' + circuit + ':\n' + missing.join('\n'));
|
||||
}
|
||||
|
||||
// load verification key
|
||||
this.verificationKey = JSON.parse(fs.readFileSync(verificationKeyPath).toString());
|
||||
this.verificationKey = JSON.parse(
|
||||
fs.readFileSync(this.verificationKeyPath).toString()
|
||||
) as typeof this.verificationKey;
|
||||
|
||||
// set proof system
|
||||
this.proofSystem = proofSystem;
|
||||
// check proof system
|
||||
if (!PROOF_SYSTEMS.includes(this.verificationKey.protocol)) {
|
||||
throw new Error('Unknown protocol in verification key: ' + this.verificationKey.protocol);
|
||||
}
|
||||
this.protocol = this.verificationKey.protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,7 +56,7 @@ export class ProofTester {
|
||||
* @returns a proof and public signals
|
||||
*/
|
||||
async prove(input: CircuitSignals): Promise<FullProof> {
|
||||
return await snarkjs[this.proofSystem].fullProve(input, this.wasmPath, this.proverKeyPath);
|
||||
return await snarkjs[this.protocol].fullProve(input, this.wasmPath, this.proverKeyPath);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,7 +66,7 @@ export class ProofTester {
|
||||
* @returns `true` if proof verifies, `false` otherwise
|
||||
*/
|
||||
async verify(proof: object, publicSignals: string[]): Promise<boolean> {
|
||||
return await snarkjs[this.proofSystem].verify(this.verificationKey, publicSignals, proof);
|
||||
return await snarkjs[this.protocol].verify(this.verificationKey, publicSignals, proof);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user