You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
4.9 KiB

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