arnaucube
arnaucube/circomPublic Self-hosted repository
circom/src/c_tester.js
src/c_tester.jsRaw
  1const chai = require("chai");
  2const assert = chai.assert;
  3
  4const fs = require("fs");
  5var tmp = require("tmp-promise");
  6const path = require("path");
  7const compiler = require("./compiler");
  8const util = require("util");
  9const exec = util.promisify(require("child_process").exec);
 10
 11const stringifyBigInts = require("snarkjs").stringifyBigInts;
 12const unstringifyBigInts = require("snarkjs").unstringifyBigInts;
 13const bigInt = require("snarkjs").bigInt;
 14
 15module.exports = c_tester;
 16
 17
 18async function  c_tester(circomFile, mainComponent, _options) {
 19    tmp.setGracefulCleanup();
 20    mainComponent = mainComponent || "main";
 21
 22    const dir = await tmp.dir({prefix: "circom_", unsafeCleanup: true });
 23
 24    const baseName = path.basename(circomFile, ".circom");
 25    const options = Object.assign({}, _options);
 26
 27    options.cSourceWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".cpp"));
 28    options.symWriteStream = fs.createWriteStream(path.join(dir.path, baseName + ".sym"));
 29    options.mainComponent = mainComponent;
 30    await compiler(circomFile, options);
 31
 32    const cdir = path.join(__dirname, "..", "c");
 33    await exec("g++" +
 34               ` ${path.join(dir.path, baseName + ".cpp")} ` +
 35               ` ${path.join(cdir,  "main.cpp")}` +
 36               ` ${path.join(cdir,  "calcwit.cpp")}` +
 37               ` ${path.join(cdir,  "utils.cpp")}` +
 38               ` -o ${path.join(dir.path, baseName)}` +
 39               ` -I ${cdir}` +
 40               " -lgmp -std=c++11 -DSANITY_CHECK"
 41    );
 42
 43    console.log(dir.path);
 44    return new CTester(dir, baseName, mainComponent);
 45}
 46
 47class CTester {
 48
 49    constructor(dir, baseName, mainComponent) {
 50        this.dir=dir;
 51        this.baseName = baseName;
 52        this.mainComponent = mainComponent;
 53    }
 54
 55    async release() {
 56        await this.dir.cleanup();
 57    }
 58
 59    async calculateWitness(input) {
 60        await fs.promises.writeFile(
 61            path.join(this.dir.path, "in.json"),
 62            JSON.stringify(stringifyBigInts(input), null, 1)
 63        );
 64        await exec(`${path.join(this.dir.path, this.baseName)}` +
 65                   ` ${path.join(this.dir.path, "in.json")}` +
 66                   ` ${path.join(this.dir.path, "out.json")}`
 67        );
 68        const resStr = await fs.promises.readFile(
 69            path.join(this.dir.path, "out.json")
 70        );
 71
 72        const res = unstringifyBigInts(JSON.parse(resStr));
 73        return res;
 74    }
 75
 76    async _loadSymbols() {
 77        this.symbols = {};
 78        const symsStr = await fs.promises.readFile(
 79            path.join(this.dir.path, this.baseName + ".sym"),
 80            "utf8"
 81        );
 82        const lines = symsStr.split("\n");
 83        for (let i=0; i<lines.length; i++) {
 84            const arr = lines[i].split(",");
 85            if (arr.length!=3) continue;
 86            this.symbols[arr[2]] = {
 87                idx: Number(arr[0]),
 88                idxWit: Number(arr[1])
 89            };
 90        }
 91    }
 92
 93    async assertOut(actualOut, expectedOut) {
 94        const self = this;
 95        if (!self.symbols) await self._loadSymbols();
 96
 97        checkObject("main", expectedOut);
 98
 99        function checkObject(prefix, eOut) {
100
101            if (Array.isArray(eOut)) {
102                for (let i=0; i<eOut.length; i++) {
103                    checkObject(prefix + "["+i+"]", eOut[i]);
104                }
105            } else if (typeof eOut == "object") {
106                for (let k in eOut) {
107                    checkObject(prefix + "."+k, eOut[k]);
108                }
109            } else {
110                const ba = bigInt(actualOut[self.symbols[prefix].idxWit]).toString();
111                const be = bigInt(eOut).toString();
112                assert.strictEqual(ba, be, prefix);
113            }
114        }
115    }
116
117}
118
119