Skip to content
Open
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
14 changes: 7 additions & 7 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"ffjavascript": "^0.2.38",
"fnv-plus": "^1.3.1",
"r1csfile": "0.0.16",
"tmp-promise": "^3.0.2",
"tmp-promise": "^3.0.3",
"util": "^0.12.4"
}
}
24 changes: 24 additions & 0 deletions scripts/circom-docker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bash

set -o errexit

[[ $1 =~ (-h|--help) ]] && {
echo "usage: ${0##*/} <circom params>"
echo "e.g.: ${0##*/} circuits/hello.circom --r1cs --wasm --sym --c --output compiled/"
exit 1
}

path_this=$( cd $(dirname "$0"); pwd -L )
if [ -L "$0" ]; then
path_this=$(dirname $(readlink ${path_this}/$(basename "$0"))) # path relatively to the symlink file
[[ "$path_this" != /* ]] && path_this=$(cd $(dirname "$0")/${path_this}; pwd -L)
fi

test -t 1 && USE_TTY="-t" | USE_TTY=""

docker run -i ${USE_TTY} --rm \
-v "${path_this}/..":/data \
-v /etc/passwd:/etc/passwd:ro \
-v /etc/group:/etc/group:ro \
--user $(id -u) \
aspiers/circom circom $@
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully this can be replaced with iden3/circom or even just circom at some point :-)

33 changes: 33 additions & 0 deletions test/helpers/circomDocker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const { mkdtemp, rmdirSync } = require("fs");
const { tmpdir, userInfo } = require("os");
const { join, sep } = require("path");

module.exports = {
getOptions,
};

async function getOptions(projectRoot = "") {
const basedir = projectRoot || join(__dirname, "../../");
const options = {
basedir,
};
if (!!process.env.CIRCOM_DOCKER) {
const tmpDir = await new Promise((res, rej) =>
mkdtemp(`${tmpdir()}${sep}`, (err, folder) =>
err ? rej(err) : res(folder)
)
);
process.on("exit", () => rmdirSync(tmpDir, { recursive: true }));
options.tmpdir = tmpDir;

options.compiler = `docker run -i --rm -v ${basedir}:/data -v ${tmpDir}:${tmpDir} `;
const { uid } = userInfo();
if (!!uid) {
options.compiler += `-v /etc/passwd:/etc/passwd:ro `;
options.compiler += `-v /etc/group:/etc/group:ro `;
options.compiler += `--user ${uid} `;
}
options.compiler += "aspiers/circom circom";
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here - hopefully can be replaced with iden3/circom or circom.

}
return Promise.resolve(options);
}
4 changes: 3 additions & 1 deletion test/multiplier2.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ describe("Simple test", function () {

it("Checking the compilation of a simple circuit generating wasm", async () => {

const circuit = await wasm_tester(path.join(__dirname, "Multiplier2.circom"));
const input = path.join(__dirname, "Multiplier2.circom");
const opts = await getOptions(__dirname);
const circuit = await wasm_tester(input, opts);
const w = await circuit.calculateWitness({a: 2, b: 4});
await circuit.checkConstraints(w);
});
Expand Down
72 changes: 42 additions & 30 deletions wasm/tester.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ const fs = require("fs");
var tmp = require("tmp-promise");
const path = require("path");

const util = require("util");
const exec = util.promisify(require("child_process").exec);
const { exec } = require("child_process");

const loadR1cs = require("r1csfile").load;
const ZqField = require("ffjavascript").ZqField;
Expand All @@ -15,27 +14,30 @@ module.exports = wasm_tester;

async function wasm_tester(circomInput, _options) {

assert(await compiler_above_version("2.0.0"),"Wrong compiler version. Must be at least 2.0.0");

tmp.setGracefulCleanup();
const options = Object.assign(
// default
{ compiler: "circom", json: false },
// user-defined
_options,
// may not be redefined by user
{ wasm: true, sym: true, r1cs: true, circomVersion: "2.0.0" },
);

const dir = await tmp.dir({prefix: "circom_", unsafeCleanup: true });
assert(await compiler_above_version(options), "Wrong compiler version. Must be at least 2.0.0");

//console.log(dir.path);
tmp.setGracefulCleanup();

const baseName = path.basename(circomInput, ".circom");
const options = Object.assign({}, _options);
const dir = await tmp.dir({prefix: "circom_", unsafeCleanup: true, tmpdir: options.tmpdir});

options.wasm = true;
options.input = !!options.basedir ? path.relative(options.basedir, circomInput) : circomInput;
options.output = !!options.basedir ? path.relative(options.basedir, dir.path) : dir.path;

//console.log(dir.path);

options.sym = true;
options.json = options.json || false; // costraints in json format
options.r1cs = true;
options.output = dir.path;
const baseName = path.basename(options.input, ".circom");

await compile(circomInput, options);
await compile(options);

const utils = require("./utils");
const WitnessCalculator = require("./witness_calculator");

const wasm = await fs.promises.readFile(path.join(dir.path, baseName+"_js/"+ baseName + ".wasm"));
Expand All @@ -45,20 +47,19 @@ async function wasm_tester(circomInput, _options) {
return new WasmTester(dir, baseName, wc);
}

async function compile (fileName, options) {
var flags = "--wasm ";
async function compile (options) {
var flags = " --wasm ";
if (options.sym) flags += "--sym ";
if (options.r1cs) flags += "--r1cs ";
if (options.json) flags += "--json ";
if (options.output) flags += "--output " + options.output + " ";
if (options.O === 0) flags += "--O0 "
if (options.O === 1) flags += "--O1 "

b = await exec("circom " + flags + fileName);
assert(b.stderr == "",
"circom compiler error \n" + b.stderr);
b = await _exec(options.compiler + flags + options.input);
assert(b.err === null, "circom compiler error \n" + b.stderr || b.stdout);
}

class WasmTester {

constructor(dir, baseName, witnessCalculator) {
Expand Down Expand Up @@ -154,7 +155,7 @@ class WasmTester {
}

function checkConstraint(constraint) {

const F = self.F;
const a = evalLC(constraint[0]);
const b = evalLC(constraint[1]);
Expand All @@ -179,23 +180,34 @@ class WasmTester {

function version_to_list ( v ) {
return v.split(".").map(function(x) {
return parseInt(x, 10);
return parseInt(x, 10);
});
}

function check_versions ( v1, v2 ) {
//check if v1 is newer than or equal to v2
for (let i = 0; i < v2.length; i++) {
if (v1[i] > v2[i]) return true;
if (v1[i] < v2[i]) return false;
if (v1[i] > v2[i]) return true;
if (v1[i] < v2[i]) return false;
}
return true;
}

async function compiler_above_version(v) {
let output = await exec('circom --version').toString();
async function compiler_above_version(options) {
let output = (await _exec(options.compiler + ' --version')).stdout.toString();
let compiler_version = version_to_list(output.slice(output.search(/\d/),-1));
vlist = version_to_list(v);
return check_versions ( compiler_version, vlist );
vlist = version_to_list(options.circomVersion);
return check_versions(compiler_version, vlist);
}

async function _exec(cmd) {
return new Promise((resolve) => {
const res = {};
exec(cmd, (err, stdout, stderr) => {
res.err = err;
res.stdout = stdout;
res.stderr = stderr;
resolve(res);
});
});
}