Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

circomkit install and multiplier example #28

Merged
merged 9 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
target
build
node_modules
/.vscode


node_modules/*

build/*
ptau/*
circuits/test/*.circom
circuits/main/*
7 changes: 7 additions & 0 deletions .mocharc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extension": ["ts"],
"require": "ts-node/register",
"spec": "circuits/test/**/*.test.ts",
"timeout": 100000,
"exit": true
}
6 changes: 4 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ ark-poly = { version = "0.4.1", default-features = false, features = ["parallel"
ark-relations = { version = "=0.4.0", default-features = false }
ark-serialize = { version = "0.4.1", default-features = false }
anyhow = "1.0.86"
serde = "1.0.204"
serde_json = "1.0.122"

[profile.release]
lto = true
Expand Down
32 changes: 27 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,44 @@
# AES-GCM circom circuits
A (WIP) implementation of [AES-GCM](https://web.cs.ucdavis.edu/~rogaway/ocb/gcm.pdf) in Circom.

## Design documents
- [Miro board](https://miro.com/app/board/uXjVKs-YCfM=/)
- [AES-GCM deep dive](https://gist.github.com/thor314/53cdab54aaf16bdafd5ac936d5447eb8)

## Generate AES witnsess values
Generate witnesses and an AES proof:
Generate json witnesses and an AES proof to populate the `inputs` dir:
`cargo run --release`

## Design documents
- [Miro board](https://miro.com/app/board/uXjVKs-YCfM=/)
- [AES-GCM deep dive](https://gist.github.com/thor314/53cdab54aaf16bdafd5ac936d5447eb8)
## Testing

### end-2-end testing
You can test that the witnesses in `inputs` are valid by using the `build/**/generate_witness.js` circom artifact. Run the `generate_witness.js` script:

```sh
cd build
# generate the `wtns` file from the json witnesses generated in rust
# also checks that the json witness has the right number of bytes
# and the json keys match the circom `signal` inputs
node gcm_siv_dec_2_keys_test_js/generate_witness.js gcm_siv_dec_2_keys_test_js/gcm_siv_dec_2_keys_test.wasm ../inputs/witness.json witness.wtns
```

### unit testing with circomkit
Alternatively, you can test witnesses are valid by writing tests in circomkit by running:

```sh
yarn install
yarn test
```

The tests run by `circomkit` are are specified in `circuits.json` and `.mocharc.json`.

## Browser Execution Demo
To prove an AES execution with the witness files generated above:

Install node, circom, and set up the directory:

```sh
# install node

# setup js
cd client && npm install
cd client && npm start
Expand Down
7 changes: 7 additions & 0 deletions circuits.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"multiplier_3": {
"file": "multiplier",
"template": "Multiplier",
"params": [3]
}
}
2 changes: 2 additions & 0 deletions circuits/aes/tiny.circom
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pragma circom 2.0.0;
thor314 marked this conversation as resolved.
Show resolved Hide resolved

template Multiplier() {
signal input a[3];
signal input b;
Expand Down
53 changes: 53 additions & 0 deletions circuits/multiplier.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
pragma circom 2.0.0;

template MultiplicationGate() {
signal input in[2];
signal output out <== in[0] * in[1];
}

template Multiplier(N) {
assert(N > 1);
signal input in[N];
signal output out;
component gate[N-1];

// instantiate gates
for (var i = 0; i < N-1; i++) {
gate[i] = MultiplicationGate();
}

// multiply
gate[0].in <== [in[0], in[1]];
for (var i = 0; i < N-2; i++) {
gate[i+1].in <== [gate[i].out, in[i+2]];
}
out <== gate[N-2].out;
}

// Alternative way using anonymous components
template MultiplierAnonymous(N) {
assert(N > 1);
signal input in[N];
signal output out;

signal inner[N-1];
inner[0] <== MultiplicationGate()([in[0], in[1]]);
for(var i = 0; i < N-2; i++) {
inner[i+1] <== MultiplicationGate()([inner[i], in[i+2]]);
}
out <== inner[N-2];
}

// Alternative way without the gate component
template MultiplierSimple(N) {
assert(N > 1);
signal input in[N];
signal output out;

signal inner[N-1];
inner[0] <== in[0] * in[1];
for(var i = 2; i < N; i++) {
inner[i-1] <== inner[i-2] * in[i];
}
out <== inner[N-2];
}
8 changes: 8 additions & 0 deletions circuits/test/common/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Circomkit, WitnessTester } from "circomkit";
import 'mocha';

export const circomkit = new Circomkit({
verbose: false,
});

export { WitnessTester };
6 changes: 6 additions & 0 deletions circuits/test/multiplier/mulgate.circom
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// auto-generated by circomkit
pragma circom 2.0.0;

include "../../multiplier.circom";

component main = MultiplicationGate();
42 changes: 42 additions & 0 deletions circuits/test/multiplier/mulitplier.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { WitnessTester } from "circomkit";
import { circomkit } from "../common";

describe("multiplier", () => {
const N = 3;
let circuit: WitnessTester<["in"], ["out"]>;

before(async () => {
circuit = await circomkit.WitnessTester(`multiplier_${N}`, {
file: "multiplier",
template: "Multiplier",
params: [N],
});
});

it("should have correct number of constraints", async () => {
await circuit.expectConstraintCount(N - 1);
});

it("should multiply correctly", async () => {
const randomNumbers = Array.from({ length: N }, () => Math.floor(Math.random() * 100 * N));
await circuit.expectPass({ in: randomNumbers }, { out: randomNumbers.reduce((prev, acc) => acc * prev) });
});
});

describe("multiplier utilities", () => {
describe("multiplication gate", () => {
let circuit: WitnessTester<["in"], ["out"]>;

before(async () => {
circuit = await circomkit.WitnessTester("mulgate", {
file: "multiplier",
template: "MultiplicationGate",
dir: "test/multiplier",
});
});

it("should multiply correctly", async () => {
await circuit.expectPass({ in: [7, 5] }, { out: 7 * 5 });
});
});
});
3 changes: 3 additions & 0 deletions inputs/multiplier_3/default.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"in": [2, 4, 10]
}
Loading