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