arnaucube
arnaucube/circomPublic Self-hosted repository
circom/ports/c/calcwit.cpp
ports/c/calcwit.cppRaw
  1#include <string>
  2#include <stdexcept>
  3#include <sstream>
  4#include <iostream>
  5#include <iomanip>
  6#include <stdlib.h>
  7#include <assert.h>
  8#include <stdarg.h>
  9#include <thread>
 10#include "calcwit.h"
 11#include "utils.h"
 12
 13Circom_CalcWit::Circom_CalcWit(Circom_Circuit *aCircuit) {
 14    circuit = aCircuit;
 15
 16#ifdef SANITY_CHECK
 17    signalAssigned = new bool[circuit->NSignals];
 18    signalAssigned[0] = true;
 19#endif
 20
 21    mutexes = new std::mutex[NMUTEXES];
 22    cvs = new std::condition_variable[NMUTEXES];
 23    inputSignalsToTrigger = new int[circuit->NComponents];
 24    signalValues = new FrElement[circuit->NSignals];
 25
 26    // Set one signal
 27    Fr_copy(&signalValues[0], circuit->constants + 1);
 28
 29    reset();
 30}
 31
 32
 33Circom_CalcWit::~Circom_CalcWit() {
 34
 35#ifdef SANITY_CHECK
 36    delete signalAssigned;
 37#endif
 38
 39    delete[] cvs;
 40    delete[] mutexes;
 41
 42    delete[] signalValues;
 43    delete[] inputSignalsToTrigger;
 44
 45}
 46
 47void Circom_CalcWit::syncPrintf(const char *format, ...) {
 48    va_list args;
 49    va_start(args, format);
 50
 51    printf_mutex.lock();
 52    vprintf(format, args);
 53    printf_mutex.unlock();
 54
 55    va_end(args);
 56}
 57
 58void Circom_CalcWit::reset() {
 59
 60#ifdef SANITY_CHECK
 61    for (int i=1; i<circuit->NComponents; i++) signalAssigned[i] = false;
 62#endif
 63
 64    for (int i=0; i<circuit->NComponents; i++) {
 65        inputSignalsToTrigger[i] = circuit->components[i].inputSignals;
 66    }
 67    for (int i=0; i<circuit->NComponents; i++) {
 68        if (inputSignalsToTrigger[i] == 0) triggerComponent(i);
 69    }
 70}
 71
 72
 73int Circom_CalcWit::getSubComponentOffset(int cIdx, u64 hash) {
 74    int hIdx;
 75    for(hIdx = int(hash & 0xFF); hash!=circuit->components[cIdx].hashTable[hIdx].hash; hIdx++) {
 76        if (!circuit->components[cIdx].hashTable[hIdx].hash) throw std::runtime_error("hash not found: " + int_to_hex(hash));
 77    }
 78    int entryPos = circuit->components[cIdx].hashTable[hIdx].pos;
 79    if (circuit->components[cIdx].entries[entryPos].type != _typeComponent) {
 80        throw std::runtime_error("invalid type");
 81    }
 82    return circuit->components[cIdx].entries[entryPos].offset;
 83}
 84
 85
 86Circom_Sizes Circom_CalcWit::getSubComponentSizes(int cIdx, u64 hash) {
 87    int hIdx;
 88    for(hIdx = int(hash & 0xFF); hash!=circuit->components[cIdx].hashTable[hIdx].hash; hIdx++) {
 89        if (!circuit->components[cIdx].hashTable[hIdx].hash) throw std::runtime_error("hash not found: " + int_to_hex(hash));
 90    }
 91    int entryPos = circuit->components[cIdx].hashTable[hIdx].pos;
 92    if (circuit->components[cIdx].entries[entryPos].type != _typeComponent) {
 93        throw std::runtime_error("invalid type");
 94    }
 95    return circuit->components[cIdx].entries[entryPos].sizes;
 96}
 97
 98int Circom_CalcWit::getSignalOffset(int cIdx, u64 hash) {
 99    int hIdx;
100    for(hIdx = int(hash & 0xFF); hash!=circuit->components[cIdx].hashTable[hIdx].hash; hIdx++) {
101        if (!circuit->components[cIdx].hashTable[hIdx].hash) throw std::runtime_error("hash not found: " + int_to_hex(hash));
102    }
103    int entryPos = circuit->components[cIdx].hashTable[hIdx].pos;
104    if (circuit->components[cIdx].entries[entryPos].type != _typeSignal) {
105        throw std::runtime_error("invalid type");
106    }
107    return circuit->components[cIdx].entries[entryPos].offset;
108}
109
110Circom_Sizes Circom_CalcWit::getSignalSizes(int cIdx, u64 hash) {
111    int hIdx;
112    for(hIdx = int(hash & 0xFF); hash!=circuit->components[cIdx].hashTable[hIdx].hash; hIdx++) {
113        if (!circuit->components[cIdx].hashTable[hIdx].hash) throw std::runtime_error("hash not found: " + int_to_hex(hash));
114    }
115    int entryPos = circuit->components[cIdx].hashTable[hIdx].pos;
116    if (circuit->components[cIdx].entries[entryPos].type != _typeSignal) {
117        throw std::runtime_error("invalid type");
118    }
119    return circuit->components[cIdx].entries[entryPos].sizes;
120}
121
122void Circom_CalcWit::getSignal(int currentComponentIdx, int cIdx, int sIdx, PFrElement value) {
123    // syncPrintf("getSignal: %d\n", sIdx);
124    if ((circuit->components[cIdx].newThread)&&(currentComponentIdx != cIdx)) {
125        std::unique_lock<std::mutex> lk(mutexes[cIdx % NMUTEXES]);
126        while (inputSignalsToTrigger[cIdx] != -1) {
127            cvs[cIdx % NMUTEXES].wait(lk);
128        }
129        // cvs[cIdx % NMUTEXES].wait(lk, [&]{return inputSignalsToTrigger[cIdx] == -1;});
130        lk.unlock();
131    }
132#ifdef SANITY_CHECK
133    if (signalAssigned[sIdx] == false) {
134        fprintf(stderr, "Accessing a not assigned signal: %d\n", sIdx);
135        assert(false);
136    }
137#endif
138    Fr_copy(value, signalValues + sIdx);
139    /*
140    char *valueStr = mpz_get_str(0, 10, *value);
141    syncPrintf("%d, Get %d --> %s\n", currentComponentIdx, sIdx, valueStr);
142    free(valueStr);
143    */
144}
145
146void Circom_CalcWit::finished(int cIdx) {
147    {
148        std::lock_guard<std::mutex> lk(mutexes[cIdx % NMUTEXES]);
149        inputSignalsToTrigger[cIdx] = -1;
150    }
151    // syncPrintf("Finished: %d\n", cIdx);
152    cvs[cIdx % NMUTEXES].notify_all();
153}
154
155void Circom_CalcWit::setSignal(int currentComponentIdx, int cIdx, int sIdx, PFrElement value) {
156    // syncPrintf("setSignal: %d\n", sIdx);
157
158#ifdef SANITY_CHECK
159    if (signalAssigned[sIdx] == true) {
160        fprintf(stderr, "Signal assigned twice: %d\n", sIdx);
161        assert(false);
162    }
163    signalAssigned[sIdx] = true;
164#endif
165    // Log assignement
166    /*
167    char *valueStr = mpz_get_str(0, 10, *value);
168    syncPrintf("%d, Set %d --> %s\n", currentComponentIdx, sIdx, valueStr);
169    free(valueStr);
170    */
171    Fr_copy(signalValues + sIdx, value);
172    if ( BITMAP_ISSET(circuit->mapIsInput, sIdx) ) {
173        if (inputSignalsToTrigger[cIdx]>0) {
174            inputSignalsToTrigger[cIdx]--;
175            if (inputSignalsToTrigger[cIdx] == 0) triggerComponent(cIdx);
176        } else {
177            fprintf(stderr, "Input signals does not match with map: %d\n", sIdx);
178            assert(false);
179        }
180    }
181
182}
183
184void Circom_CalcWit::checkConstraint(int currentComponentIdx, PFrElement value1, PFrElement value2, char const *err) {
185#ifdef SANITY_CHECK
186    FrElement tmp;
187    Fr_eq(&tmp, value1, value2);
188    if (!Fr_isTrue(&tmp)) {
189        char *pcV1 = Fr_element2str(value1);
190        char *pcV2 = Fr_element2str(value2);
191        // throw std::runtime_error(std::to_string(currentComponentIdx) + std::string(", Constraint doesn't match, ") + err + ". " + sV1 + " != " + sV2 );
192        fprintf(stderr, "Constraint doesn't match, %s: %s != %s", err, pcV1, pcV2);
193        free(pcV1);
194        free(pcV2);
195        assert(false);
196    }
197#endif
198}
199
200
201void Circom_CalcWit::triggerComponent(int newCIdx) {
202    //int oldCIdx = cIdx;
203    // cIdx = newCIdx;
204    if (circuit->components[newCIdx].newThread) {
205        // syncPrintf("Triggered: %d\n", newCIdx);
206        std::thread t(circuit->components[newCIdx].fn, this, newCIdx);
207        // t.join();
208        t.detach();
209    } else {
210        (*(circuit->components[newCIdx].fn))(this, newCIdx);
211    }
212    // cIdx = oldCIdx;
213}
214
215void Circom_CalcWit::log(PFrElement value) {
216    char *pcV = Fr_element2str(value);
217    syncPrintf("Log: %s\n", pcV);
218    free(pcV);
219}
220
221void Circom_CalcWit::join() {
222    for (int i=0; i<circuit->NComponents; i++) {
223        std::unique_lock<std::mutex> lk(mutexes[i % NMUTEXES]);
224        while (inputSignalsToTrigger[i] != -1) {
225            cvs[i % NMUTEXES].wait(lk);
226        }
227        // cvs[i % NMUTEXES].wait(lk, [&]{return inputSignalsToTrigger[i] == -1;});
228        lk.unlock();
229        // syncPrintf("Joined: %d\n", i);
230    }
231
232}
233
234