circom/c/calcwit.cpp
c/calcwit.cppRaw
1#include <string>
2#include <stdexcept>
3#include <sstream>
4#include <iostream>
5#include <iomanip>
6#include <stdlib.h>
7#include <gmp.h>
8#include <assert.h>
9#include "calcwit.h"
10#include "utils.h"
11
12Circom_CalcWit::Circom_CalcWit(Circom_Circuit *aCircuit) {
13 circuit = aCircuit;
14
15#ifdef SANITY_CHECK
16 signalAssigned = new bool[circuit->NSignals];
17 signalAssigned[0] = true;
18#endif
19
20 inputSignalsToTrigger = new int[circuit->NComponents];
21 signalValues = new BigInt[circuit->NSignals];
22
23 // Set one signal
24 mpz_init_set_ui(signalValues[0], 1);
25
26 // Initialize remaining signals
27 for (int i=1; i<circuit->NSignals; i++) mpz_init2(signalValues[i], 256);
28
29 BigInt p;
30 mpz_init_set_str(p, circuit->P, 10);
31 field = new ZqField(&p);
32 mpz_clear(p);
33
34 reset();
35}
36
37void Circom_CalcWit::reset() {
38
39#ifdef SANITY_CHECK
40 for (int i=1; i<circuit->NComponents; i++) signalAssigned[i] = false;
41#endif
42
43 for (int i=0; i<circuit->NComponents; i++) {
44 inputSignalsToTrigger[i] = circuit->components[i].inputSignals;
45 if (inputSignalsToTrigger[i] == 0) triggerComponent(i);
46 }
47}
48
49
50Circom_CalcWit::~Circom_CalcWit() {
51 delete field;
52
53#ifdef SANITY_CHECK
54 delete signalAssigned;
55#endif
56
57 for (int i=0; i<circuit->NSignals; i++) mpz_clear(signalValues[i]);
58
59 delete[] signalValues;
60 delete inputSignalsToTrigger;
61
62}
63
64int Circom_CalcWit::getSubComponentOffset(int cIdx, u64 hash) {
65 int hIdx;
66 for(hIdx = int(hash & 0xFF); hash!=circuit->components[cIdx].hashTable[hIdx].hash; hIdx++) {
67 if (!circuit->components[cIdx].hashTable[hIdx].hash) throw std::runtime_error("hash not found: " + int_to_hex(hash));
68 }
69 int entryPos = circuit->components[cIdx].hashTable[hIdx].pos;
70 if (circuit->components[cIdx].entries[entryPos].type != _typeComponent) {
71 throw std::runtime_error("invalid type");
72 }
73 return circuit->components[cIdx].entries[entryPos].offset;
74}
75
76
77Circom_Sizes Circom_CalcWit::getSubComponentSizes(int cIdx, u64 hash) {
78 int hIdx;
79 for(hIdx = int(hash & 0xFF); hash!=circuit->components[cIdx].hashTable[hIdx].hash; hIdx++) {
80 if (!circuit->components[cIdx].hashTable[hIdx].hash) throw std::runtime_error("hash not found: " + int_to_hex(hash));
81 }
82 int entryPos = circuit->components[cIdx].hashTable[hIdx].pos;
83 if (circuit->components[cIdx].entries[entryPos].type != _typeComponent) {
84 throw std::runtime_error("invalid type");
85 }
86 return circuit->components[cIdx].entries[entryPos].sizes;
87}
88
89int Circom_CalcWit::getSignalOffset(int cIdx, u64 hash) {
90 int hIdx;
91 for(hIdx = int(hash & 0xFF); hash!=circuit->components[cIdx].hashTable[hIdx].hash; hIdx++) {
92 if (!circuit->components[cIdx].hashTable[hIdx].hash) throw std::runtime_error("hash not found: " + int_to_hex(hash));
93 }
94 int entryPos = circuit->components[cIdx].hashTable[hIdx].pos;
95 if (circuit->components[cIdx].entries[entryPos].type != _typeSignal) {
96 throw std::runtime_error("invalid type");
97 }
98 return circuit->components[cIdx].entries[entryPos].offset;
99}
100
101Circom_Sizes Circom_CalcWit::getSignalSizes(int cIdx, u64 hash) {
102 int hIdx;
103 for(hIdx = int(hash & 0xFF); hash!=circuit->components[cIdx].hashTable[hIdx].hash; hIdx++) {
104 if (!circuit->components[cIdx].hashTable[hIdx].hash) throw std::runtime_error("hash not found: " + int_to_hex(hash));
105 }
106 int entryPos = circuit->components[cIdx].hashTable[hIdx].pos;
107 if (circuit->components[cIdx].entries[entryPos].type != _typeSignal) {
108 throw std::runtime_error("invalid type");
109 }
110 return circuit->components[cIdx].entries[entryPos].sizes;
111}
112
113PBigInt Circom_CalcWit::allocBigInts(int n) {
114 PBigInt res = new BigInt[n];
115 for (int i=0; i<n; i++) mpz_init2(res[i], 256);
116 return res;
117}
118
119void Circom_CalcWit::freeBigInts(PBigInt bi, int n) {
120 for (int i=0; i<n; i++) mpz_clear(bi[i]);
121 delete[] bi;
122}
123
124void Circom_CalcWit::getSignal(int cIdx, int sIdx, PBigInt value) {
125#ifdef SANITY_CHECK
126 if (signalAssigned[sIdx] == false) {
127 fprintf(stderr, "Accessing a not assigned signal: %d\n", sIdx);
128 assert(false);
129 }
130#endif
131 mpz_set(*value, signalValues[sIdx]);
132}
133
134void Circom_CalcWit::setSignal(int cIdx, int sIdx, PBigInt value) {
135#ifdef SANITY_CHECK
136 if (signalAssigned[sIdx] == true) {
137 fprintf(stderr, "Signal assigned twice: %d\n", sIdx);
138 assert(false);
139 }
140 signalAssigned[sIdx] = true;
141#endif
142 /*
143 // Log assignement
144 char *valueStr = mpz_get_str(0, 10, *value);
145 printf("%d --> %s\n", sIdx, valueStr);
146 free(valueStr);
147 */
148 mpz_set(signalValues[sIdx], *value);
149 if ( BITMAP_ISSET(circuit->mapIsInput, sIdx) ) {
150 inputSignalsToTrigger[cIdx]--;
151 if (inputSignalsToTrigger[cIdx] == 0) triggerComponent(cIdx);
152 }
153
154}
155
156void Circom_CalcWit::checkConstraint(PBigInt value1, PBigInt value2, char const *err) {
157#ifdef SANITY_CHECK
158 if (mpz_cmp(*value1, *value2) != 0) {
159 char *pcV1 = mpz_get_str(0, 10, *value1);
160 char *pcV2 = mpz_get_str(0, 10, *value2);
161 std::string sV1 = std::string(pcV1);
162 std::string sV2 = std::string(pcV2);
163 free(pcV1);
164 free(pcV2);
165 throw std::runtime_error(std::string("Constraint doesn't match, ") + err + ". " + sV1 + " != " + sV2 );
166 }
167#endif
168}
169
170
171void Circom_CalcWit::triggerComponent(int newCIdx) {
172 int oldCIdx = cIdx;
173 cIdx = newCIdx;
174 (*(circuit->components[newCIdx].fn))(this);
175 cIdx = oldCIdx;
176}
177
178void Circom_CalcWit::log(PBigInt value) {
179 char *pcV = mpz_get_str(0, 10, *value);
180 printf("Log: %s\n", pcV);
181 free(pcV);
182}
183
184