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