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