arnaucube
arnaucube/circomPublic Self-hosted repository
circom/c/main.cpp
c/main.cppRaw
  1#include <iostream>
  2#include <fstream>
  3#include <sstream>
  4#include <string>
  5#include <sys/types.h>
  6#include <sys/stat.h>
  7#include <sys/mman.h>
  8#include <fcntl.h>
  9#include <gmp.h>
 10#include <unistd.h>
 11#include <nlohmann/json.hpp>
 12using json = nlohmann::json;
 13
 14#include "calcwit.h"
 15#include "circom.h"
 16#include "utils.h"
 17
 18#define handle_error(msg) \
 19           do { perror(msg); exit(EXIT_FAILURE); } while (0)
 20
 21void loadBin(Circom_CalcWit *ctx, std::string filename) {
 22    int fd;
 23    struct stat sb;
 24
 25    // map input
 26    fd = open(filename.c_str(), O_RDONLY);
 27    if (fd == -1)
 28        handle_error("open");
 29
 30    if (fstat(fd, &sb) == -1)           /* To obtain file size */
 31        handle_error("fstat");
 32
 33
 34    u8 *in;
 35
 36    in = (u8 *)mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
 37    if (in == MAP_FAILED)
 38        handle_error("mmap");
 39
 40    close(fd);
 41
 42    BigInt v;
 43    mpz_init2(v, 256);
 44    u8 *p = in;
 45    for (int i=0; i<_circuit.NInputs; i++) {
 46        int len = *(u8 *)p;
 47        p++;
 48        mpz_import(v,len , -1 , 1, 0, 0, p);
 49        p+=len;
 50        ctx->setSignal(0, _circuit.wit2sig[1 + _circuit.NOutputs + i], &v);
 51    }
 52}
 53
 54
 55typedef void (*ItFunc)(Circom_CalcWit *ctx, int idx, json val);
 56
 57void iterateArr(Circom_CalcWit *ctx, int o, Circom_Sizes sizes, json jarr, ItFunc f) {
 58  if (!jarr.is_array()) {
 59    assert((sizes[0] == 1)&&(sizes[1] == 0));
 60    f(ctx, o, jarr);
 61  } else {
 62    int n = sizes[0] / sizes[1];
 63    for (int i=0; i<n; i++) {
 64      iterateArr(ctx, o + i*sizes[1], sizes+1, jarr[i], f);
 65    }
 66  }
 67}
 68
 69void itFunc(Circom_CalcWit *ctx, int o, json val) {
 70
 71    BigInt v;
 72    mpz_init2(v, 256);
 73
 74    std::string s;
 75
 76    if (val.is_string()) {
 77        s = val.get<std::string>();
 78    } else if (val.is_number()) {
 79
 80        double vd = val.get<double>();
 81        std::stringstream stream;
 82        stream << std::fixed << std::setprecision(0) << vd;
 83        s = stream.str();
 84    } else {
 85        handle_error("Invalid JSON type");
 86    }
 87
 88    mpz_set_str (v, s.c_str(), 10);
 89
 90    ctx->setSignal(0, o, &v);
 91}
 92
 93
 94void loadJson(Circom_CalcWit *ctx, std::string filename) {
 95    std::ifstream inStream(filename);
 96    json j;
 97    inStream >> j;
 98
 99    for (json::iterator it = j.begin(); it != j.end(); ++it) {
100//      std::cout << it.key() << " => " << it.value() << '\n';
101      u64 h = fnv1a(it.key());
102      int o = ctx->getSignalOffset(0, h);
103      Circom_Sizes sizes = ctx->getSignalSizes(0, h);
104      iterateArr(ctx, o, sizes, it.value(), itFunc);
105    }
106
107}
108
109
110void writeOutBin(Circom_CalcWit *ctx, std::string filename) {
111    FILE *write_ptr;
112
113    write_ptr = fopen(filename.c_str(),"wb");
114
115    BigInt v;
116    mpz_init2(v, 256);
117
118    u8 buffOut[256];
119    for (int i=0;i<_circuit.NVars;i++) {
120        size_t  size=256;
121        ctx->getWitness(i, &v);
122        mpz_export(buffOut+1, &size,  -1, 1, -1, 0, v);
123        *buffOut = (u8)size;
124        fwrite(buffOut, size+1, 1, write_ptr);
125    }
126    fclose(write_ptr);
127
128}
129
130
131void writeOutJson(Circom_CalcWit *ctx, std::string filename) {
132
133    std::ofstream outFile;
134    outFile.open (filename);
135
136    outFile << "[\n";
137
138    BigInt v;
139    mpz_init2(v, 256);
140
141    char pcV[256];
142
143    for (int i=0;i<_circuit.NVars;i++) {
144        ctx->getWitness(i, &v);
145        mpz_get_str(pcV, 10, v);
146        std::string sV = std::string(pcV);
147        outFile << (i ? "," : " ") << "\"" << sV << "\"\n";
148    }
149
150    outFile << "]\n";
151    outFile.close();
152}
153
154bool hasEnding (std::string const &fullString, std::string const &ending) {
155    if (fullString.length() >= ending.length()) {
156        return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
157    } else {
158        return false;
159    }
160}
161
162int main(int argc, char *argv[]) {
163    if (argc!=3) {
164        std::string cl = argv[0];
165        std::string base_filename = cl.substr(cl.find_last_of("/\\") + 1);
166        std::cout << "Usage: " << base_filename << " <input.<bin|json>> <output.<bin|json>>\n";
167    } else {
168
169        // open output
170        Circom_CalcWit *ctx = new Circom_CalcWit(&_circuit);
171
172        std::string infilename = argv[1];
173
174        if (hasEnding(infilename, std::string(".bin"))) {
175            loadBin(ctx, infilename);
176        } else if (hasEnding(infilename, std::string(".json"))) {
177            loadJson(ctx, infilename);
178        } else {
179            handle_error("Invalid input extension (.bin / .json)");
180        }
181
182
183        std::string outfilename = argv[2];
184
185        if (hasEnding(outfilename, std::string(".bin"))) {
186            writeOutBin(ctx, outfilename);
187        } else if (hasEnding(outfilename, std::string(".json"))) {
188            writeOutJson(ctx, outfilename);
189        } else {
190            handle_error("Invalid output extension (.bin / .json)");
191        }
192
193        delete ctx;
194        exit(EXIT_SUCCESS);
195    }
196}