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}