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}