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 <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    FrElement v;
 43    u8 *p = in;
 44    for (int i=0; i<_circuit.NInputs; i++) {
 45        v.type = Fr_LONG;
 46        for (int j=0; j<Fr_N64; j++) {
 47            v.longVal[j] = *(u64 *)p;
 48        }
 49        p += 8;
 50        ctx->setSignal(0, 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    FrElement v;
 72
 73    std::string s;
 74
 75    if (val.is_string()) {
 76        s = val.get<std::string>();
 77    } else if (val.is_number()) {
 78
 79        double vd = val.get<double>();
 80        std::stringstream stream;
 81        stream << std::fixed << std::setprecision(0) << vd;
 82        s = stream.str();
 83    } else {
 84        handle_error("Invalid JSON type");
 85    }
 86
 87    Fr_str2element (&v, s.c_str());
 88
 89    ctx->setSignal(0, 0, o, &v);
 90}
 91
 92
 93void loadJson(Circom_CalcWit *ctx, std::string filename) {
 94    std::ifstream inStream(filename);
 95    json j;
 96    inStream >> j;
 97
 98    for (json::iterator it = j.begin(); it != j.end(); ++it) {
 99//      std::cout << it.key() << " => " << it.value() << '\n';
100      u64 h = fnv1a(it.key());
101      int o;
102      try {
103        o = ctx->getSignalOffset(0, h);
104      } catch (std::runtime_error e) {
105        std::ostringstream errStrStream;
106        errStrStream << "Error loadin variable: " << it.key() << "\n" << e.what();
107        throw std::runtime_error(errStrStream.str() );
108      }
109      Circom_Sizes sizes = ctx->getSignalSizes(0, h);
110      iterateArr(ctx, o, sizes, it.value(), itFunc);
111    }
112
113}
114
115
116void writeOutBin(Circom_CalcWit *ctx, std::string filename) {
117    FILE *write_ptr;
118
119    write_ptr = fopen(filename.c_str(),"wb");
120
121    FrElement v;
122
123    u8 buffOut[256];
124    for (int i=0;i<_circuit.NVars;i++) {
125        size_t  size=256;
126        ctx->getWitness(i, &v);
127        Fr_toLongNormal(&v);
128        fwrite(v.longVal, Fr_N64*8, 1, write_ptr);
129    }
130    fclose(write_ptr);
131
132}
133
134
135void writeOutJson(Circom_CalcWit *ctx, std::string filename) {
136
137    std::ofstream outFile;
138    outFile.open (filename);
139
140    outFile << "[\n";
141
142    FrElement v;
143
144    for (int i=0;i<_circuit.NVars;i++) {
145        ctx->getWitness(i, &v);
146        char *pcV = Fr_element2str(&v);
147        std::string sV = std::string(pcV);
148        outFile << (i ? "," : " ") << "\"" << sV << "\"\n";
149        free(pcV);
150    }
151
152    outFile << "]\n";
153    outFile.close();
154}
155
156bool hasEnding (std::string const &fullString, std::string const &ending) {
157    if (fullString.length() >= ending.length()) {
158        return (0 == fullString.compare (fullString.length() - ending.length(), ending.length(), ending));
159    } else {
160        return false;
161    }
162}
163
164int main(int argc, char *argv[]) {
165    Fr_init();
166    if (argc!=3) {
167        std::string cl = argv[0];
168        std::string base_filename = cl.substr(cl.find_last_of("/\\") + 1);
169        std::cout << "Usage: " << base_filename << " <input.<bin|json>> <output.<bin|json>>\n";
170    } else {
171
172        // open output
173        Circom_CalcWit *ctx = new Circom_CalcWit(&_circuit);
174
175        std::string infilename = argv[1];
176
177        if (hasEnding(infilename, std::string(".bin"))) {
178            loadBin(ctx, infilename);
179        } else if (hasEnding(infilename, std::string(".json"))) {
180            loadJson(ctx, infilename);
181        } else {
182            handle_error("Invalid input extension (.bin / .json)");
183        }
184
185        ctx->join();
186
187        printf("Finished!\n");
188
189        std::string outfilename = argv[2];
190
191        if (hasEnding(outfilename, std::string(".bin"))) {
192            writeOutBin(ctx, outfilename);
193        } else if (hasEnding(outfilename, std::string(".json"))) {
194            writeOutJson(ctx, outfilename);
195        } else {
196            handle_error("Invalid output extension (.bin / .json)");
197        }
198
199        delete ctx;
200        exit(EXIT_SUCCESS);
201    }
202}