Update Python version requirements and fix compatibility issues

- Bump minimum Python version from 3.11 to 3.13 across all apps
- Add Python 3.11-3.13 test matrix to CLI workflow
- Document Python 3.11+ requirement in .env.example
- Fix Starlette Broadcast removal with in-process fallback implementation
- Add _InProcessBroadcast class for tests when Starlette Broadcast is unavailable
- Refactor API key validators to read live settings instead of cached values
- Update database models with explicit
This commit is contained in:
oib
2026-02-24 18:41:08 +01:00
parent 24b3a37733
commit 825f157749
270 changed files with 66674 additions and 2027 deletions

View File

@@ -0,0 +1,153 @@
1,1,4,main.final_parameters[0]
2,2,4,main.final_parameters[1]
3,3,4,main.final_parameters[2]
4,4,4,main.final_parameters[3]
5,5,4,main.training_complete
6,6,4,main.initial_parameters[0]
7,7,4,main.initial_parameters[1]
8,8,4,main.initial_parameters[2]
9,9,4,main.initial_parameters[3]
10,10,4,main.learning_rate
11,-1,4,main.current_params[0][0]
12,-1,4,main.current_params[0][1]
13,-1,4,main.current_params[0][2]
14,-1,4,main.current_params[0][3]
15,11,4,main.current_params[1][0]
16,12,4,main.current_params[1][1]
17,13,4,main.current_params[1][2]
18,14,4,main.current_params[1][3]
19,15,4,main.current_params[2][0]
20,16,4,main.current_params[2][1]
21,17,4,main.current_params[2][2]
22,18,4,main.current_params[2][3]
23,-1,4,main.current_params[3][0]
24,-1,4,main.current_params[3][1]
25,-1,4,main.current_params[3][2]
26,-1,4,main.current_params[3][3]
27,-1,3,main.epochs[0].next_epoch_params[0]
28,-1,3,main.epochs[0].next_epoch_params[1]
29,-1,3,main.epochs[0].next_epoch_params[2]
30,-1,3,main.epochs[0].next_epoch_params[3]
31,-1,3,main.epochs[0].epoch_params[0]
32,-1,3,main.epochs[0].epoch_params[1]
33,-1,3,main.epochs[0].epoch_params[2]
34,-1,3,main.epochs[0].epoch_params[3]
35,-1,3,main.epochs[0].epoch_gradients[0]
36,-1,3,main.epochs[0].epoch_gradients[1]
37,-1,3,main.epochs[0].epoch_gradients[2]
38,-1,3,main.epochs[0].epoch_gradients[3]
39,-1,3,main.epochs[0].learning_rate
40,-1,2,main.epochs[0].param_update.new_params[0]
41,-1,2,main.epochs[0].param_update.new_params[1]
42,-1,2,main.epochs[0].param_update.new_params[2]
43,-1,2,main.epochs[0].param_update.new_params[3]
44,-1,2,main.epochs[0].param_update.current_params[0]
45,-1,2,main.epochs[0].param_update.current_params[1]
46,-1,2,main.epochs[0].param_update.current_params[2]
47,-1,2,main.epochs[0].param_update.current_params[3]
48,-1,2,main.epochs[0].param_update.gradients[0]
49,-1,2,main.epochs[0].param_update.gradients[1]
50,-1,2,main.epochs[0].param_update.gradients[2]
51,-1,2,main.epochs[0].param_update.gradients[3]
52,-1,2,main.epochs[0].param_update.learning_rate
53,-1,1,main.epochs[0].param_update.updates[0].new_param
54,-1,1,main.epochs[0].param_update.updates[0].current_param
55,-1,1,main.epochs[0].param_update.updates[0].gradient
56,-1,1,main.epochs[0].param_update.updates[0].learning_rate
57,-1,1,main.epochs[0].param_update.updates[1].new_param
58,-1,1,main.epochs[0].param_update.updates[1].current_param
59,-1,1,main.epochs[0].param_update.updates[1].gradient
60,-1,1,main.epochs[0].param_update.updates[1].learning_rate
61,-1,1,main.epochs[0].param_update.updates[2].new_param
62,-1,1,main.epochs[0].param_update.updates[2].current_param
63,-1,1,main.epochs[0].param_update.updates[2].gradient
64,-1,1,main.epochs[0].param_update.updates[2].learning_rate
65,-1,1,main.epochs[0].param_update.updates[3].new_param
66,-1,1,main.epochs[0].param_update.updates[3].current_param
67,-1,1,main.epochs[0].param_update.updates[3].gradient
68,-1,1,main.epochs[0].param_update.updates[3].learning_rate
69,-1,3,main.epochs[1].next_epoch_params[0]
70,-1,3,main.epochs[1].next_epoch_params[1]
71,-1,3,main.epochs[1].next_epoch_params[2]
72,-1,3,main.epochs[1].next_epoch_params[3]
73,-1,3,main.epochs[1].epoch_params[0]
74,-1,3,main.epochs[1].epoch_params[1]
75,-1,3,main.epochs[1].epoch_params[2]
76,-1,3,main.epochs[1].epoch_params[3]
77,-1,3,main.epochs[1].epoch_gradients[0]
78,-1,3,main.epochs[1].epoch_gradients[1]
79,-1,3,main.epochs[1].epoch_gradients[2]
80,-1,3,main.epochs[1].epoch_gradients[3]
81,-1,3,main.epochs[1].learning_rate
82,-1,2,main.epochs[1].param_update.new_params[0]
83,-1,2,main.epochs[1].param_update.new_params[1]
84,-1,2,main.epochs[1].param_update.new_params[2]
85,-1,2,main.epochs[1].param_update.new_params[3]
86,-1,2,main.epochs[1].param_update.current_params[0]
87,-1,2,main.epochs[1].param_update.current_params[1]
88,-1,2,main.epochs[1].param_update.current_params[2]
89,-1,2,main.epochs[1].param_update.current_params[3]
90,-1,2,main.epochs[1].param_update.gradients[0]
91,-1,2,main.epochs[1].param_update.gradients[1]
92,-1,2,main.epochs[1].param_update.gradients[2]
93,-1,2,main.epochs[1].param_update.gradients[3]
94,-1,2,main.epochs[1].param_update.learning_rate
95,-1,1,main.epochs[1].param_update.updates[0].new_param
96,-1,1,main.epochs[1].param_update.updates[0].current_param
97,-1,1,main.epochs[1].param_update.updates[0].gradient
98,-1,1,main.epochs[1].param_update.updates[0].learning_rate
99,-1,1,main.epochs[1].param_update.updates[1].new_param
100,-1,1,main.epochs[1].param_update.updates[1].current_param
101,-1,1,main.epochs[1].param_update.updates[1].gradient
102,-1,1,main.epochs[1].param_update.updates[1].learning_rate
103,-1,1,main.epochs[1].param_update.updates[2].new_param
104,-1,1,main.epochs[1].param_update.updates[2].current_param
105,-1,1,main.epochs[1].param_update.updates[2].gradient
106,-1,1,main.epochs[1].param_update.updates[2].learning_rate
107,-1,1,main.epochs[1].param_update.updates[3].new_param
108,-1,1,main.epochs[1].param_update.updates[3].current_param
109,-1,1,main.epochs[1].param_update.updates[3].gradient
110,-1,1,main.epochs[1].param_update.updates[3].learning_rate
111,-1,3,main.epochs[2].next_epoch_params[0]
112,-1,3,main.epochs[2].next_epoch_params[1]
113,-1,3,main.epochs[2].next_epoch_params[2]
114,-1,3,main.epochs[2].next_epoch_params[3]
115,-1,3,main.epochs[2].epoch_params[0]
116,-1,3,main.epochs[2].epoch_params[1]
117,-1,3,main.epochs[2].epoch_params[2]
118,-1,3,main.epochs[2].epoch_params[3]
119,-1,3,main.epochs[2].epoch_gradients[0]
120,-1,3,main.epochs[2].epoch_gradients[1]
121,-1,3,main.epochs[2].epoch_gradients[2]
122,-1,3,main.epochs[2].epoch_gradients[3]
123,-1,3,main.epochs[2].learning_rate
124,-1,2,main.epochs[2].param_update.new_params[0]
125,-1,2,main.epochs[2].param_update.new_params[1]
126,-1,2,main.epochs[2].param_update.new_params[2]
127,-1,2,main.epochs[2].param_update.new_params[3]
128,-1,2,main.epochs[2].param_update.current_params[0]
129,-1,2,main.epochs[2].param_update.current_params[1]
130,-1,2,main.epochs[2].param_update.current_params[2]
131,-1,2,main.epochs[2].param_update.current_params[3]
132,-1,2,main.epochs[2].param_update.gradients[0]
133,-1,2,main.epochs[2].param_update.gradients[1]
134,-1,2,main.epochs[2].param_update.gradients[2]
135,-1,2,main.epochs[2].param_update.gradients[3]
136,-1,2,main.epochs[2].param_update.learning_rate
137,-1,1,main.epochs[2].param_update.updates[0].new_param
138,-1,1,main.epochs[2].param_update.updates[0].current_param
139,-1,1,main.epochs[2].param_update.updates[0].gradient
140,-1,1,main.epochs[2].param_update.updates[0].learning_rate
141,-1,1,main.epochs[2].param_update.updates[1].new_param
142,-1,1,main.epochs[2].param_update.updates[1].current_param
143,-1,1,main.epochs[2].param_update.updates[1].gradient
144,-1,1,main.epochs[2].param_update.updates[1].learning_rate
145,-1,1,main.epochs[2].param_update.updates[2].new_param
146,-1,1,main.epochs[2].param_update.updates[2].current_param
147,-1,1,main.epochs[2].param_update.updates[2].gradient
148,-1,1,main.epochs[2].param_update.updates[2].learning_rate
149,-1,1,main.epochs[2].param_update.updates[3].new_param
150,-1,1,main.epochs[2].param_update.updates[3].current_param
151,-1,1,main.epochs[2].param_update.updates[3].gradient
152,-1,1,main.epochs[2].param_update.updates[3].learning_rate
153,-1,0,main.lr_validator.learning_rate

View File

@@ -0,0 +1,22 @@
CC=g++
CFLAGS=-std=c++11 -O3 -I.
DEPS_HPP = circom.hpp calcwit.hpp fr.hpp
DEPS_O = main.o calcwit.o fr.o fr_asm.o
ifeq ($(shell uname),Darwin)
NASM=nasm -fmacho64 --prefix _
endif
ifeq ($(shell uname),Linux)
NASM=nasm -felf64
endif
all: modular_ml_components
%.o: %.cpp $(DEPS_HPP)
$(CC) -c $< $(CFLAGS)
fr_asm.o: fr.asm
$(NASM) fr.asm -o fr_asm.o
modular_ml_components: $(DEPS_O) modular_ml_components.o
$(CC) -o modular_ml_components *.o -lgmp

View File

@@ -0,0 +1,127 @@
#include <iomanip>
#include <sstream>
#include <assert.h>
#include "calcwit.hpp"
extern void run(Circom_CalcWit* ctx);
std::string int_to_hex( u64 i )
{
std::stringstream stream;
stream << "0x"
<< std::setfill ('0') << std::setw(16)
<< std::hex << i;
return stream.str();
}
u64 fnv1a(std::string s) {
u64 hash = 0xCBF29CE484222325LL;
for(char& c : s) {
hash ^= u64(c);
hash *= 0x100000001B3LL;
}
return hash;
}
Circom_CalcWit::Circom_CalcWit (Circom_Circuit *aCircuit, uint maxTh) {
circuit = aCircuit;
inputSignalAssignedCounter = get_main_input_signal_no();
inputSignalAssigned = new bool[inputSignalAssignedCounter];
for (int i = 0; i< inputSignalAssignedCounter; i++) {
inputSignalAssigned[i] = false;
}
signalValues = new FrElement[get_total_signal_no()];
Fr_str2element(&signalValues[0], "1", 10);
componentMemory = new Circom_Component[get_number_of_components()];
circuitConstants = circuit ->circuitConstants;
templateInsId2IOSignalInfo = circuit -> templateInsId2IOSignalInfo;
busInsId2FieldInfo = circuit -> busInsId2FieldInfo;
maxThread = maxTh;
// parallelism
numThread = 0;
}
Circom_CalcWit::~Circom_CalcWit() {
// ...
}
uint Circom_CalcWit::getInputSignalHashPosition(u64 h) {
uint n = get_size_of_input_hashmap();
uint pos = (uint)(h % (u64)n);
if (circuit->InputHashMap[pos].hash!=h){
uint inipos = pos;
pos = (pos+1)%n;
while (pos != inipos) {
if (circuit->InputHashMap[pos].hash == h) return pos;
if (circuit->InputHashMap[pos].signalid == 0) {
fprintf(stderr, "Signal not found\n");
assert(false);
}
pos = (pos+1)%n;
}
fprintf(stderr, "Signals not found\n");
assert(false);
}
return pos;
}
void Circom_CalcWit::tryRunCircuit(){
if (inputSignalAssignedCounter == 0) {
run(this);
}
}
void Circom_CalcWit::setInputSignal(u64 h, uint i, FrElement & val){
if (inputSignalAssignedCounter == 0) {
fprintf(stderr, "No more signals to be assigned\n");
assert(false);
}
uint pos = getInputSignalHashPosition(h);
if (i >= circuit->InputHashMap[pos].signalsize) {
fprintf(stderr, "Input signal array access exceeds the size\n");
assert(false);
}
uint si = circuit->InputHashMap[pos].signalid+i;
if (inputSignalAssigned[si-get_main_input_signal_start()]) {
fprintf(stderr, "Signal assigned twice: %d\n", si);
assert(false);
}
signalValues[si] = val;
inputSignalAssigned[si-get_main_input_signal_start()] = true;
inputSignalAssignedCounter--;
tryRunCircuit();
}
u64 Circom_CalcWit::getInputSignalSize(u64 h) {
uint pos = getInputSignalHashPosition(h);
return circuit->InputHashMap[pos].signalsize;
}
std::string Circom_CalcWit::getTrace(u64 id_cmp){
if (id_cmp == 0) return componentMemory[id_cmp].componentName;
else{
u64 id_father = componentMemory[id_cmp].idFather;
std::string my_name = componentMemory[id_cmp].componentName;
return Circom_CalcWit::getTrace(id_father) + "." + my_name;
}
}
std::string Circom_CalcWit::generate_position_array(uint* dimensions, uint size_dimensions, uint index){
std::string positions = "";
for (uint i = 0 ; i < size_dimensions; i++){
uint last_pos = index % dimensions[size_dimensions -1 - i];
index = index / dimensions[size_dimensions -1 - i];
std::string new_pos = "[" + std::to_string(last_pos) + "]";
positions = new_pos + positions;
}
return positions;
}

View File

@@ -0,0 +1,70 @@
#ifndef CIRCOM_CALCWIT_H
#define CIRCOM_CALCWIT_H
#include <mutex>
#include <condition_variable>
#include <functional>
#include <atomic>
#include <memory>
#include "circom.hpp"
#include "fr.hpp"
#define NMUTEXES 32 //512
u64 fnv1a(std::string s);
class Circom_CalcWit {
bool *inputSignalAssigned;
uint inputSignalAssignedCounter;
Circom_Circuit *circuit;
public:
FrElement *signalValues;
Circom_Component* componentMemory;
FrElement* circuitConstants;
std::map<u32,IOFieldDefPair> templateInsId2IOSignalInfo;
IOFieldDefPair* busInsId2FieldInfo;
std::string* listOfTemplateMessages;
// parallelism
std::mutex numThreadMutex;
std::condition_variable ntcvs;
int numThread;
int maxThread;
// Functions called by the circuit
Circom_CalcWit(Circom_Circuit *aCircuit, uint numTh = NMUTEXES);
~Circom_CalcWit();
// Public functions
void setInputSignal(u64 h, uint i, FrElement &val);
void tryRunCircuit();
u64 getInputSignalSize(u64 h);
inline uint getRemaingInputsToBeSet() {
return inputSignalAssignedCounter;
}
inline void getWitness(uint idx, PFrElement val) {
Fr_copy(val, &signalValues[circuit->witness2SignalList[idx]]);
}
std::string getTrace(u64 id_cmp);
std::string generate_position_array(uint* dimensions, uint size_dimensions, uint index);
private:
uint getInputSignalHashPosition(u64 h);
};
typedef void (*Circom_TemplateFunction)(uint __cIdx, Circom_CalcWit* __ctx);
#endif // CIRCOM_CALCWIT_H

View File

@@ -0,0 +1,89 @@
#ifndef __CIRCOM_H
#define __CIRCOM_H
#include <map>
#include <gmp.h>
#include <mutex>
#include <condition_variable>
#include <thread>
#include "fr.hpp"
typedef unsigned long long u64;
typedef uint32_t u32;
typedef uint8_t u8;
//only for the main inputs
struct __attribute__((__packed__)) HashSignalInfo {
u64 hash;
u64 signalid;
u64 signalsize;
};
struct IOFieldDef {
u32 offset;
u32 len;
u32 *lengths;
u32 size;
u32 busId;
};
struct IOFieldDefPair {
u32 len;
IOFieldDef* defs;
};
struct Circom_Circuit {
// const char *P;
HashSignalInfo* InputHashMap;
u64* witness2SignalList;
FrElement* circuitConstants;
std::map<u32,IOFieldDefPair> templateInsId2IOSignalInfo;
IOFieldDefPair* busInsId2FieldInfo;
};
struct Circom_Component {
u32 templateId;
u64 signalStart;
u32 inputCounter;
std::string templateName;
std::string componentName;
u64 idFather;
u32* subcomponents = NULL;
bool* subcomponentsParallel = NULL;
bool *outputIsSet = NULL; //one for each output
std::mutex *mutexes = NULL; //one for each output
std::condition_variable *cvs = NULL;
std::thread *sbct = NULL;//subcomponent threads
};
/*
For every template instantiation create two functions:
- name_create
- name_run
//PFrElement: pointer to FrElement
Every name_run or circom_function has:
=====================================
//array of PFrElements for auxiliars in expression computation (known size);
PFrElements expaux[];
//array of PFrElements for local vars (known size)
PFrElements lvar[];
*/
uint get_main_input_signal_start();
uint get_main_input_signal_no();
uint get_total_signal_no();
uint get_number_of_components();
uint get_size_of_input_hashmap();
uint get_size_of_witness();
uint get_size_of_constants();
uint get_size_of_io_map();
uint get_size_of_bus_field_map();
#endif // __CIRCOM_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,321 @@
#include "fr.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <gmp.h>
#include <assert.h>
#include <string>
static mpz_t q;
static mpz_t zero;
static mpz_t one;
static mpz_t mask;
static size_t nBits;
static bool initialized = false;
void Fr_toMpz(mpz_t r, PFrElement pE) {
FrElement tmp;
Fr_toNormal(&tmp, pE);
if (!(tmp.type & Fr_LONG)) {
mpz_set_si(r, tmp.shortVal);
if (tmp.shortVal<0) {
mpz_add(r, r, q);
}
} else {
mpz_import(r, Fr_N64, -1, 8, -1, 0, (const void *)tmp.longVal);
}
}
void Fr_fromMpz(PFrElement pE, mpz_t v) {
if (mpz_fits_sint_p(v)) {
pE->type = Fr_SHORT;
pE->shortVal = mpz_get_si(v);
} else {
pE->type = Fr_LONG;
for (int i=0; i<Fr_N64; i++) pE->longVal[i] = 0;
mpz_export((void *)(pE->longVal), NULL, -1, 8, -1, 0, v);
}
}
bool Fr_init() {
if (initialized) return false;
initialized = true;
mpz_init(q);
mpz_import(q, Fr_N64, -1, 8, -1, 0, (const void *)Fr_q.longVal);
mpz_init_set_ui(zero, 0);
mpz_init_set_ui(one, 1);
nBits = mpz_sizeinbase (q, 2);
mpz_init(mask);
mpz_mul_2exp(mask, one, nBits);
mpz_sub(mask, mask, one);
return true;
}
void Fr_str2element(PFrElement pE, char const *s, uint base) {
mpz_t mr;
mpz_init_set_str(mr, s, base);
mpz_fdiv_r(mr, mr, q);
Fr_fromMpz(pE, mr);
mpz_clear(mr);
}
char *Fr_element2str(PFrElement pE) {
FrElement tmp;
mpz_t r;
if (!(pE->type & Fr_LONG)) {
if (pE->shortVal>=0) {
char *r = new char[32];
sprintf(r, "%d", pE->shortVal);
return r;
} else {
mpz_init_set_si(r, pE->shortVal);
mpz_add(r, r, q);
}
} else {
Fr_toNormal(&tmp, pE);
mpz_init(r);
mpz_import(r, Fr_N64, -1, 8, -1, 0, (const void *)tmp.longVal);
}
char *res = mpz_get_str (0, 10, r);
mpz_clear(r);
return res;
}
void Fr_idiv(PFrElement r, PFrElement a, PFrElement b) {
mpz_t ma;
mpz_t mb;
mpz_t mr;
mpz_init(ma);
mpz_init(mb);
mpz_init(mr);
Fr_toMpz(ma, a);
// char *s1 = mpz_get_str (0, 10, ma);
// printf("s1 %s\n", s1);
Fr_toMpz(mb, b);
// char *s2 = mpz_get_str (0, 10, mb);
// printf("s2 %s\n", s2);
mpz_fdiv_q(mr, ma, mb);
// char *sr = mpz_get_str (0, 10, mr);
// printf("r %s\n", sr);
Fr_fromMpz(r, mr);
mpz_clear(ma);
mpz_clear(mb);
mpz_clear(mr);
}
void Fr_mod(PFrElement r, PFrElement a, PFrElement b) {
mpz_t ma;
mpz_t mb;
mpz_t mr;
mpz_init(ma);
mpz_init(mb);
mpz_init(mr);
Fr_toMpz(ma, a);
Fr_toMpz(mb, b);
mpz_fdiv_r(mr, ma, mb);
Fr_fromMpz(r, mr);
mpz_clear(ma);
mpz_clear(mb);
mpz_clear(mr);
}
void Fr_pow(PFrElement r, PFrElement a, PFrElement b) {
mpz_t ma;
mpz_t mb;
mpz_t mr;
mpz_init(ma);
mpz_init(mb);
mpz_init(mr);
Fr_toMpz(ma, a);
Fr_toMpz(mb, b);
mpz_powm(mr, ma, mb, q);
Fr_fromMpz(r, mr);
mpz_clear(ma);
mpz_clear(mb);
mpz_clear(mr);
}
void Fr_inv(PFrElement r, PFrElement a) {
mpz_t ma;
mpz_t mr;
mpz_init(ma);
mpz_init(mr);
Fr_toMpz(ma, a);
mpz_invert(mr, ma, q);
Fr_fromMpz(r, mr);
mpz_clear(ma);
mpz_clear(mr);
}
void Fr_div(PFrElement r, PFrElement a, PFrElement b) {
FrElement tmp;
Fr_inv(&tmp, b);
Fr_mul(r, a, &tmp);
}
void Fr_fail() {
assert(false);
}
RawFr::RawFr() {
Fr_init();
set(fZero, 0);
set(fOne, 1);
neg(fNegOne, fOne);
}
RawFr::~RawFr() {
}
void RawFr::fromString(Element &r, const std::string &s, uint32_t radix) {
mpz_t mr;
mpz_init_set_str(mr, s.c_str(), radix);
mpz_fdiv_r(mr, mr, q);
for (int i=0; i<Fr_N64; i++) r.v[i] = 0;
mpz_export((void *)(r.v), NULL, -1, 8, -1, 0, mr);
Fr_rawToMontgomery(r.v,r.v);
mpz_clear(mr);
}
void RawFr::fromUI(Element &r, unsigned long int v) {
mpz_t mr;
mpz_init(mr);
mpz_set_ui(mr, v);
for (int i=0; i<Fr_N64; i++) r.v[i] = 0;
mpz_export((void *)(r.v), NULL, -1, 8, -1, 0, mr);
Fr_rawToMontgomery(r.v,r.v);
mpz_clear(mr);
}
RawFr::Element RawFr::set(int value) {
Element r;
set(r, value);
return r;
}
void RawFr::set(Element &r, int value) {
mpz_t mr;
mpz_init(mr);
mpz_set_si(mr, value);
if (value < 0) {
mpz_add(mr, mr, q);
}
mpz_export((void *)(r.v), NULL, -1, 8, -1, 0, mr);
for (int i=0; i<Fr_N64; i++) r.v[i] = 0;
mpz_export((void *)(r.v), NULL, -1, 8, -1, 0, mr);
Fr_rawToMontgomery(r.v,r.v);
mpz_clear(mr);
}
std::string RawFr::toString(const Element &a, uint32_t radix) {
Element tmp;
mpz_t r;
Fr_rawFromMontgomery(tmp.v, a.v);
mpz_init(r);
mpz_import(r, Fr_N64, -1, 8, -1, 0, (const void *)(tmp.v));
char *res = mpz_get_str (0, radix, r);
mpz_clear(r);
std::string resS(res);
free(res);
return resS;
}
void RawFr::inv(Element &r, const Element &a) {
mpz_t mr;
mpz_init(mr);
mpz_import(mr, Fr_N64, -1, 8, -1, 0, (const void *)(a.v));
mpz_invert(mr, mr, q);
for (int i=0; i<Fr_N64; i++) r.v[i] = 0;
mpz_export((void *)(r.v), NULL, -1, 8, -1, 0, mr);
Fr_rawMMul(r.v, r.v,Fr_rawR3);
mpz_clear(mr);
}
void RawFr::div(Element &r, const Element &a, const Element &b) {
Element tmp;
inv(tmp, b);
mul(r, a, tmp);
}
#define BIT_IS_SET(s, p) (s[p>>3] & (1 << (p & 0x7)))
void RawFr::exp(Element &r, const Element &base, uint8_t* scalar, unsigned int scalarSize) {
bool oneFound = false;
Element copyBase;
copy(copyBase, base);
for (int i=scalarSize*8-1; i>=0; i--) {
if (!oneFound) {
if ( !BIT_IS_SET(scalar, i) ) continue;
copy(r, copyBase);
oneFound = true;
continue;
}
square(r, r);
if ( BIT_IS_SET(scalar, i) ) {
mul(r, r, copyBase);
}
}
if (!oneFound) {
copy(r, fOne);
}
}
void RawFr::toMpz(mpz_t r, const Element &a) {
Element tmp;
Fr_rawFromMontgomery(tmp.v, a.v);
mpz_import(r, Fr_N64, -1, 8, -1, 0, (const void *)tmp.v);
}
void RawFr::fromMpz(Element &r, const mpz_t a) {
for (int i=0; i<Fr_N64; i++) r.v[i] = 0;
mpz_export((void *)(r.v), NULL, -1, 8, -1, 0, a);
Fr_rawToMontgomery(r.v, r.v);
}
int RawFr::toRprBE(const Element &element, uint8_t *data, int bytes)
{
if (bytes < Fr_N64 * 8) {
return -(Fr_N64 * 8);
}
mpz_t r;
mpz_init(r);
toMpz(r, element);
mpz_export(data, NULL, 1, 8, 1, 0, r);
return Fr_N64 * 8;
}
int RawFr::fromRprBE(Element &element, const uint8_t *data, int bytes)
{
if (bytes < Fr_N64 * 8) {
return -(Fr_N64* 8);
}
mpz_t r;
mpz_init(r);
mpz_import(r, Fr_N64 * 8, 0, 1, 0, 0, data);
fromMpz(element, r);
return Fr_N64 * 8;
}
static bool init = Fr_init();
RawFr RawFr::field;

View File

@@ -0,0 +1,164 @@
#ifndef __FR_H
#define __FR_H
#include <stdint.h>
#include <string>
#include <gmp.h>
#ifdef __APPLE__
#include <sys/types.h> // typedef unsigned int uint;
#endif // __APPLE__
#define Fr_N64 4
#define Fr_SHORT 0x00000000
#define Fr_LONG 0x80000000
#define Fr_LONGMONTGOMERY 0xC0000000
typedef uint64_t FrRawElement[Fr_N64];
typedef struct __attribute__((__packed__)) {
int32_t shortVal;
uint32_t type;
FrRawElement longVal;
} FrElement;
typedef FrElement *PFrElement;
extern FrElement Fr_q;
extern FrElement Fr_R3;
extern FrRawElement Fr_rawq;
extern FrRawElement Fr_rawR3;
extern "C" void Fr_copy(PFrElement r, PFrElement a);
extern "C" void Fr_copyn(PFrElement r, PFrElement a, int n);
extern "C" void Fr_add(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_sub(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_neg(PFrElement r, PFrElement a);
extern "C" void Fr_mul(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_square(PFrElement r, PFrElement a);
extern "C" void Fr_band(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_bor(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_bxor(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_bnot(PFrElement r, PFrElement a);
extern "C" void Fr_shl(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_shr(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_eq(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_neq(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_lt(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_gt(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_leq(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_geq(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_land(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_lor(PFrElement r, PFrElement a, PFrElement b);
extern "C" void Fr_lnot(PFrElement r, PFrElement a);
extern "C" void Fr_toNormal(PFrElement r, PFrElement a);
extern "C" void Fr_toLongNormal(PFrElement r, PFrElement a);
extern "C" void Fr_toMontgomery(PFrElement r, PFrElement a);
extern "C" int Fr_isTrue(PFrElement pE);
extern "C" int Fr_toInt(PFrElement pE);
extern "C" void Fr_rawCopy(FrRawElement pRawResult, const FrRawElement pRawA);
extern "C" void Fr_rawSwap(FrRawElement pRawResult, FrRawElement pRawA);
extern "C" void Fr_rawAdd(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB);
extern "C" void Fr_rawSub(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB);
extern "C" void Fr_rawNeg(FrRawElement pRawResult, const FrRawElement pRawA);
extern "C" void Fr_rawMMul(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB);
extern "C" void Fr_rawMSquare(FrRawElement pRawResult, const FrRawElement pRawA);
extern "C" void Fr_rawMMul1(FrRawElement pRawResult, const FrRawElement pRawA, uint64_t pRawB);
extern "C" void Fr_rawToMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA);
extern "C" void Fr_rawFromMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA);
extern "C" int Fr_rawIsEq(const FrRawElement pRawA, const FrRawElement pRawB);
extern "C" int Fr_rawIsZero(const FrRawElement pRawB);
extern "C" void Fr_fail();
// Pending functions to convert
void Fr_str2element(PFrElement pE, char const*s, uint base);
char *Fr_element2str(PFrElement pE);
void Fr_idiv(PFrElement r, PFrElement a, PFrElement b);
void Fr_mod(PFrElement r, PFrElement a, PFrElement b);
void Fr_inv(PFrElement r, PFrElement a);
void Fr_div(PFrElement r, PFrElement a, PFrElement b);
void Fr_pow(PFrElement r, PFrElement a, PFrElement b);
class RawFr {
public:
const static int N64 = Fr_N64;
const static int MaxBits = 254;
struct Element {
FrRawElement v;
};
private:
Element fZero;
Element fOne;
Element fNegOne;
public:
RawFr();
~RawFr();
const Element &zero() { return fZero; };
const Element &one() { return fOne; };
const Element &negOne() { return fNegOne; };
Element set(int value);
void set(Element &r, int value);
void fromString(Element &r, const std::string &n, uint32_t radix = 10);
std::string toString(const Element &a, uint32_t radix = 10);
void inline copy(Element &r, const Element &a) { Fr_rawCopy(r.v, a.v); };
void inline swap(Element &a, Element &b) { Fr_rawSwap(a.v, b.v); };
void inline add(Element &r, const Element &a, const Element &b) { Fr_rawAdd(r.v, a.v, b.v); };
void inline sub(Element &r, const Element &a, const Element &b) { Fr_rawSub(r.v, a.v, b.v); };
void inline mul(Element &r, const Element &a, const Element &b) { Fr_rawMMul(r.v, a.v, b.v); };
Element inline add(const Element &a, const Element &b) { Element r; Fr_rawAdd(r.v, a.v, b.v); return r;};
Element inline sub(const Element &a, const Element &b) { Element r; Fr_rawSub(r.v, a.v, b.v); return r;};
Element inline mul(const Element &a, const Element &b) { Element r; Fr_rawMMul(r.v, a.v, b.v); return r;};
Element inline neg(const Element &a) { Element r; Fr_rawNeg(r.v, a.v); return r; };
Element inline square(const Element &a) { Element r; Fr_rawMSquare(r.v, a.v); return r; };
Element inline add(int a, const Element &b) { return add(set(a), b);};
Element inline sub(int a, const Element &b) { return sub(set(a), b);};
Element inline mul(int a, const Element &b) { return mul(set(a), b);};
Element inline add(const Element &a, int b) { return add(a, set(b));};
Element inline sub(const Element &a, int b) { return sub(a, set(b));};
Element inline mul(const Element &a, int b) { return mul(a, set(b));};
void inline mul1(Element &r, const Element &a, uint64_t b) { Fr_rawMMul1(r.v, a.v, b); };
void inline neg(Element &r, const Element &a) { Fr_rawNeg(r.v, a.v); };
void inline square(Element &r, const Element &a) { Fr_rawMSquare(r.v, a.v); };
void inv(Element &r, const Element &a);
void div(Element &r, const Element &a, const Element &b);
void exp(Element &r, const Element &base, uint8_t* scalar, unsigned int scalarSize);
void inline toMontgomery(Element &r, const Element &a) { Fr_rawToMontgomery(r.v, a.v); };
void inline fromMontgomery(Element &r, const Element &a) { Fr_rawFromMontgomery(r.v, a.v); };
int inline eq(const Element &a, const Element &b) { return Fr_rawIsEq(a.v, b.v); };
int inline isZero(const Element &a) { return Fr_rawIsZero(a.v); };
void toMpz(mpz_t r, const Element &a);
void fromMpz(Element &a, const mpz_t r);
int toRprBE(const Element &element, uint8_t *data, int bytes);
int fromRprBE(Element &element, const uint8_t *data, int bytes);
int bytes ( void ) { return Fr_N64 * 8; };
void fromUI(Element &r, unsigned long int v);
static RawFr field;
};
#endif // __FR_H

View File

@@ -0,0 +1,374 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <nlohmann/json.hpp>
#include <vector>
#include <chrono>
using json = nlohmann::json;
#include "calcwit.hpp"
#include "circom.hpp"
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while (0)
Circom_Circuit* loadCircuit(std::string const &datFileName) {
Circom_Circuit *circuit = new Circom_Circuit;
int fd;
struct stat sb;
fd = open(datFileName.c_str(), O_RDONLY);
if (fd == -1) {
std::cout << ".dat file not found: " << datFileName << "\n";
throw std::system_error(errno, std::generic_category(), "open");
}
if (fstat(fd, &sb) == -1) { /* To obtain file size */
throw std::system_error(errno, std::generic_category(), "fstat");
}
u8* bdata = (u8*)mmap(NULL, sb.st_size, PROT_READ , MAP_PRIVATE, fd, 0);
close(fd);
circuit->InputHashMap = new HashSignalInfo[get_size_of_input_hashmap()];
uint dsize = get_size_of_input_hashmap()*sizeof(HashSignalInfo);
memcpy((void *)(circuit->InputHashMap), (void *)bdata, dsize);
circuit->witness2SignalList = new u64[get_size_of_witness()];
uint inisize = dsize;
dsize = get_size_of_witness()*sizeof(u64);
memcpy((void *)(circuit->witness2SignalList), (void *)(bdata+inisize), dsize);
circuit->circuitConstants = new FrElement[get_size_of_constants()];
if (get_size_of_constants()>0) {
inisize += dsize;
dsize = get_size_of_constants()*sizeof(FrElement);
memcpy((void *)(circuit->circuitConstants), (void *)(bdata+inisize), dsize);
}
std::map<u32,IOFieldDefPair> templateInsId2IOSignalInfo1;
IOFieldDefPair* busInsId2FieldInfo1;
if (get_size_of_io_map()>0) {
u32 index[get_size_of_io_map()];
inisize += dsize;
dsize = get_size_of_io_map()*sizeof(u32);
memcpy((void *)index, (void *)(bdata+inisize), dsize);
inisize += dsize;
assert(inisize % sizeof(u32) == 0);
assert(sb.st_size % sizeof(u32) == 0);
u32 dataiomap[(sb.st_size-inisize)/sizeof(u32)];
memcpy((void *)dataiomap, (void *)(bdata+inisize), sb.st_size-inisize);
u32* pu32 = dataiomap;
for (int i = 0; i < get_size_of_io_map(); i++) {
u32 n = *pu32;
IOFieldDefPair p;
p.len = n;
IOFieldDef defs[n];
pu32 += 1;
for (u32 j = 0; j <n; j++){
defs[j].offset=*pu32;
u32 len = *(pu32+1);
defs[j].len = len;
defs[j].lengths = new u32[len];
memcpy((void *)defs[j].lengths,(void *)(pu32+2),len*sizeof(u32));
pu32 += len + 2;
defs[j].size=*pu32;
defs[j].busId=*(pu32+1);
pu32 += 2;
}
p.defs = (IOFieldDef*)calloc(p.len, sizeof(IOFieldDef));
for (u32 j = 0; j < p.len; j++){
p.defs[j] = defs[j];
}
templateInsId2IOSignalInfo1[index[i]] = p;
}
busInsId2FieldInfo1 = (IOFieldDefPair*)calloc(get_size_of_bus_field_map(), sizeof(IOFieldDefPair));
for (int i = 0; i < get_size_of_bus_field_map(); i++) {
u32 n = *pu32;
IOFieldDefPair p;
p.len = n;
IOFieldDef defs[n];
pu32 += 1;
for (u32 j = 0; j <n; j++){
defs[j].offset=*pu32;
u32 len = *(pu32+1);
defs[j].len = len;
defs[j].lengths = new u32[len];
memcpy((void *)defs[j].lengths,(void *)(pu32+2),len*sizeof(u32));
pu32 += len + 2;
defs[j].size=*pu32;
defs[j].busId=*(pu32+1);
pu32 += 2;
}
p.defs = (IOFieldDef*)calloc(10, sizeof(IOFieldDef));
for (u32 j = 0; j < p.len; j++){
p.defs[j] = defs[j];
}
busInsId2FieldInfo1[i] = p;
}
}
circuit->templateInsId2IOSignalInfo = move(templateInsId2IOSignalInfo1);
circuit->busInsId2FieldInfo = busInsId2FieldInfo1;
munmap(bdata, sb.st_size);
return circuit;
}
bool check_valid_number(std::string & s, uint base){
bool is_valid = true;
if (base == 16){
for (uint i = 0; i < s.size(); i++){
is_valid &= (
('0' <= s[i] && s[i] <= '9') ||
('a' <= s[i] && s[i] <= 'f') ||
('A' <= s[i] && s[i] <= 'F')
);
}
} else{
for (uint i = 0; i < s.size(); i++){
is_valid &= ('0' <= s[i] && s[i] < char(int('0') + base));
}
}
return is_valid;
}
void json2FrElements (json val, std::vector<FrElement> & vval){
if (!val.is_array()) {
FrElement v;
std::string s_aux, s;
uint base;
if (val.is_string()) {
s_aux = val.get<std::string>();
std::string possible_prefix = s_aux.substr(0, 2);
if (possible_prefix == "0b" || possible_prefix == "0B"){
s = s_aux.substr(2, s_aux.size() - 2);
base = 2;
} else if (possible_prefix == "0o" || possible_prefix == "0O"){
s = s_aux.substr(2, s_aux.size() - 2);
base = 8;
} else if (possible_prefix == "0x" || possible_prefix == "0X"){
s = s_aux.substr(2, s_aux.size() - 2);
base = 16;
} else{
s = s_aux;
base = 10;
}
if (!check_valid_number(s, base)){
std::ostringstream errStrStream;
errStrStream << "Invalid number in JSON input: " << s_aux << "\n";
throw std::runtime_error(errStrStream.str() );
}
} else if (val.is_number()) {
double vd = val.get<double>();
std::stringstream stream;
stream << std::fixed << std::setprecision(0) << vd;
s = stream.str();
base = 10;
} else {
std::ostringstream errStrStream;
errStrStream << "Invalid JSON type\n";
throw std::runtime_error(errStrStream.str() );
}
Fr_str2element (&v, s.c_str(), base);
vval.push_back(v);
} else {
for (uint i = 0; i < val.size(); i++) {
json2FrElements (val[i], vval);
}
}
}
json::value_t check_type(std::string prefix, json in){
if (not in.is_array()) {
if (in.is_number_integer() || in.is_number_unsigned() || in.is_string())
return json::value_t::number_integer;
else return in.type();
} else {
if (in.size() == 0) return json::value_t::null;
json::value_t t = check_type(prefix, in[0]);
for (uint i = 1; i < in.size(); i++) {
if (t != check_type(prefix, in[i])) {
fprintf(stderr, "Types are not the same in the key %s\n",prefix.c_str());
assert(false);
}
}
return t;
}
}
void qualify_input(std::string prefix, json &in, json &in1);
void qualify_input_list(std::string prefix, json &in, json &in1){
if (in.is_array()) {
for (uint i = 0; i<in.size(); i++) {
std::string new_prefix = prefix + "[" + std::to_string(i) + "]";
qualify_input_list(new_prefix,in[i],in1);
}
} else {
qualify_input(prefix,in,in1);
}
}
void qualify_input(std::string prefix, json &in, json &in1) {
if (in.is_array()) {
if (in.size() > 0) {
json::value_t t = check_type(prefix,in);
if (t == json::value_t::object) {
qualify_input_list(prefix,in,in1);
} else {
in1[prefix] = in;
}
} else {
in1[prefix] = in;
}
} else if (in.is_object()) {
for (json::iterator it = in.begin(); it != in.end(); ++it) {
std::string new_prefix = prefix.length() == 0 ? it.key() : prefix + "." + it.key();
qualify_input(new_prefix,it.value(),in1);
}
} else {
in1[prefix] = in;
}
}
void loadJson(Circom_CalcWit *ctx, std::string filename) {
std::ifstream inStream(filename);
json jin;
inStream >> jin;
json j;
//std::cout << jin << std::endl;
std::string prefix = "";
qualify_input(prefix, jin, j);
//std::cout << j << std::endl;
u64 nItems = j.size();
// printf("Items : %llu\n",nItems);
if (nItems == 0){
ctx->tryRunCircuit();
}
for (json::iterator it = j.begin(); it != j.end(); ++it) {
// std::cout << it.key() << " => " << it.value() << '\n';
u64 h = fnv1a(it.key());
std::vector<FrElement> v;
json2FrElements(it.value(),v);
uint signalSize = ctx->getInputSignalSize(h);
if (v.size() < signalSize) {
std::ostringstream errStrStream;
errStrStream << "Error loading signal " << it.key() << ": Not enough values\n";
throw std::runtime_error(errStrStream.str() );
}
if (v.size() > signalSize) {
std::ostringstream errStrStream;
errStrStream << "Error loading signal " << it.key() << ": Too many values\n";
throw std::runtime_error(errStrStream.str() );
}
for (uint i = 0; i<v.size(); i++){
try {
// std::cout << it.key() << "," << i << " => " << Fr_element2str(&(v[i])) << '\n';
ctx->setInputSignal(h,i,v[i]);
} catch (std::runtime_error e) {
std::ostringstream errStrStream;
errStrStream << "Error setting signal: " << it.key() << "\n" << e.what();
throw std::runtime_error(errStrStream.str() );
}
}
}
}
void writeBinWitness(Circom_CalcWit *ctx, std::string wtnsFileName) {
FILE *write_ptr;
write_ptr = fopen(wtnsFileName.c_str(),"wb");
fwrite("wtns", 4, 1, write_ptr);
u32 version = 2;
fwrite(&version, 4, 1, write_ptr);
u32 nSections = 2;
fwrite(&nSections, 4, 1, write_ptr);
// Header
u32 idSection1 = 1;
fwrite(&idSection1, 4, 1, write_ptr);
u32 n8 = Fr_N64*8;
u64 idSection1length = 8 + n8;
fwrite(&idSection1length, 8, 1, write_ptr);
fwrite(&n8, 4, 1, write_ptr);
fwrite(Fr_q.longVal, Fr_N64*8, 1, write_ptr);
uint Nwtns = get_size_of_witness();
u32 nVars = (u32)Nwtns;
fwrite(&nVars, 4, 1, write_ptr);
// Data
u32 idSection2 = 2;
fwrite(&idSection2, 4, 1, write_ptr);
u64 idSection2length = (u64)n8*(u64)Nwtns;
fwrite(&idSection2length, 8, 1, write_ptr);
FrElement v;
for (int i=0;i<Nwtns;i++) {
ctx->getWitness(i, &v);
Fr_toLongNormal(&v, &v);
fwrite(v.longVal, Fr_N64*8, 1, write_ptr);
}
fclose(write_ptr);
}
int main (int argc, char *argv[]) {
std::string cl(argv[0]);
if (argc!=3) {
std::cout << "Usage: " << cl << " <input.json> <output.wtns>\n";
} else {
std::string datfile = cl + ".dat";
std::string jsonfile(argv[1]);
std::string wtnsfile(argv[2]);
// auto t_start = std::chrono::high_resolution_clock::now();
Circom_Circuit *circuit = loadCircuit(datfile);
Circom_CalcWit *ctx = new Circom_CalcWit(circuit);
loadJson(ctx, jsonfile);
if (ctx->getRemaingInputsToBeSet()!=0) {
std::cerr << "Not all inputs have been set. Only " << get_main_input_signal_no()-ctx->getRemaingInputsToBeSet() << " out of " << get_main_input_signal_no() << std::endl;
assert(false);
}
/*
for (uint i = 0; i<get_size_of_witness(); i++){
FrElement x;
ctx->getWitness(i, &x);
std::cout << i << ": " << Fr_element2str(&x) << std::endl;
}
*/
//auto t_mid = std::chrono::high_resolution_clock::now();
//std::cout << std::chrono::duration<double, std::milli>(t_mid-t_start).count()<<std::endl;
writeBinWitness(ctx,wtnsfile);
//auto t_end = std::chrono::high_resolution_clock::now();
//std::cout << std::chrono::duration<double, std::milli>(t_end-t_mid).count()<<std::endl;
}
}

View File

@@ -0,0 +1,618 @@
#include <stdio.h>
#include <iostream>
#include <assert.h>
#include "circom.hpp"
#include "calcwit.hpp"
void LearningRateValidation_0_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather);
void LearningRateValidation_0_run(uint ctx_index,Circom_CalcWit* ctx);
void ParameterUpdate_1_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather);
void ParameterUpdate_1_run(uint ctx_index,Circom_CalcWit* ctx);
void VectorParameterUpdate_2_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather);
void VectorParameterUpdate_2_run(uint ctx_index,Circom_CalcWit* ctx);
void TrainingEpoch_3_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather);
void TrainingEpoch_3_run(uint ctx_index,Circom_CalcWit* ctx);
void ModularTrainingVerification_4_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather);
void ModularTrainingVerification_4_run(uint ctx_index,Circom_CalcWit* ctx);
Circom_TemplateFunction _functionTable[5] = {
LearningRateValidation_0_run,
ParameterUpdate_1_run,
VectorParameterUpdate_2_run,
TrainingEpoch_3_run,
ModularTrainingVerification_4_run };
Circom_TemplateFunction _functionTableParallel[5] = {
NULL,
NULL,
NULL,
NULL,
NULL };
uint get_main_input_signal_start() {return 6;}
uint get_main_input_signal_no() {return 5;}
uint get_total_signal_no() {return 154;}
uint get_number_of_components() {return 20;}
uint get_size_of_input_hashmap() {return 256;}
uint get_size_of_witness() {return 19;}
uint get_size_of_constants() {return 4;}
uint get_size_of_io_map() {return 0;}
uint get_size_of_bus_field_map() {return 0;}
void release_memory_component(Circom_CalcWit* ctx, uint pos) {{
if (pos != 0){{
if(ctx->componentMemory[pos].subcomponents)
delete []ctx->componentMemory[pos].subcomponents;
if(ctx->componentMemory[pos].subcomponentsParallel)
delete []ctx->componentMemory[pos].subcomponentsParallel;
if(ctx->componentMemory[pos].outputIsSet)
delete []ctx->componentMemory[pos].outputIsSet;
if(ctx->componentMemory[pos].mutexes)
delete []ctx->componentMemory[pos].mutexes;
if(ctx->componentMemory[pos].cvs)
delete []ctx->componentMemory[pos].cvs;
if(ctx->componentMemory[pos].sbct)
delete []ctx->componentMemory[pos].sbct;
}}
}}
// function declarations
// template declarations
void LearningRateValidation_0_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather){
ctx->componentMemory[coffset].templateId = 0;
ctx->componentMemory[coffset].templateName = "LearningRateValidation";
ctx->componentMemory[coffset].signalStart = soffset;
ctx->componentMemory[coffset].inputCounter = 1;
ctx->componentMemory[coffset].componentName = componentName;
ctx->componentMemory[coffset].idFather = componentFather;
ctx->componentMemory[coffset].subcomponents = new uint[0];
}
void LearningRateValidation_0_run(uint ctx_index,Circom_CalcWit* ctx){
FrElement* circuitConstants = ctx->circuitConstants;
FrElement* signalValues = ctx->signalValues;
FrElement expaux[0];
FrElement lvar[0];
u64 mySignalStart = ctx->componentMemory[ctx_index].signalStart;
std::string myTemplateName = ctx->componentMemory[ctx_index].templateName;
std::string myComponentName = ctx->componentMemory[ctx_index].componentName;
u64 myFather = ctx->componentMemory[ctx_index].idFather;
u64 myId = ctx_index;
u32* mySubcomponents = ctx->componentMemory[ctx_index].subcomponents;
bool* mySubcomponentsParallel = ctx->componentMemory[ctx_index].subcomponentsParallel;
std::string* listOfTemplateMessages = ctx->listOfTemplateMessages;
uint sub_component_aux;
uint index_multiple_eq;
int cmp_index_ref_load = -1;
for (uint i = 0; i < 0; i++){
uint index_subc = ctx->componentMemory[ctx_index].subcomponents[i];
if (index_subc != 0){
assert(!(ctx->componentMemory[index_subc].inputCounter));
release_memory_component(ctx,index_subc);
}
}
}
void ParameterUpdate_1_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather){
ctx->componentMemory[coffset].templateId = 1;
ctx->componentMemory[coffset].templateName = "ParameterUpdate";
ctx->componentMemory[coffset].signalStart = soffset;
ctx->componentMemory[coffset].inputCounter = 3;
ctx->componentMemory[coffset].componentName = componentName;
ctx->componentMemory[coffset].idFather = componentFather;
ctx->componentMemory[coffset].subcomponents = new uint[0];
}
void ParameterUpdate_1_run(uint ctx_index,Circom_CalcWit* ctx){
FrElement* circuitConstants = ctx->circuitConstants;
FrElement* signalValues = ctx->signalValues;
FrElement expaux[2];
FrElement lvar[0];
u64 mySignalStart = ctx->componentMemory[ctx_index].signalStart;
std::string myTemplateName = ctx->componentMemory[ctx_index].templateName;
std::string myComponentName = ctx->componentMemory[ctx_index].componentName;
u64 myFather = ctx->componentMemory[ctx_index].idFather;
u64 myId = ctx_index;
u32* mySubcomponents = ctx->componentMemory[ctx_index].subcomponents;
bool* mySubcomponentsParallel = ctx->componentMemory[ctx_index].subcomponentsParallel;
std::string* listOfTemplateMessages = ctx->listOfTemplateMessages;
uint sub_component_aux;
uint index_multiple_eq;
int cmp_index_ref_load = -1;
{
PFrElement aux_dest = &signalValues[mySignalStart + 0];
// load src
Fr_mul(&expaux[1],&signalValues[mySignalStart + 3],&signalValues[mySignalStart + 2]); // line circom 18
Fr_sub(&expaux[0],&signalValues[mySignalStart + 1],&expaux[1]); // line circom 18
// end load src
Fr_copy(aux_dest,&expaux[0]);
}
for (uint i = 0; i < 0; i++){
uint index_subc = ctx->componentMemory[ctx_index].subcomponents[i];
if (index_subc != 0){
assert(!(ctx->componentMemory[index_subc].inputCounter));
release_memory_component(ctx,index_subc);
}
}
}
void VectorParameterUpdate_2_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather){
ctx->componentMemory[coffset].templateId = 2;
ctx->componentMemory[coffset].templateName = "VectorParameterUpdate";
ctx->componentMemory[coffset].signalStart = soffset;
ctx->componentMemory[coffset].inputCounter = 9;
ctx->componentMemory[coffset].componentName = componentName;
ctx->componentMemory[coffset].idFather = componentFather;
ctx->componentMemory[coffset].subcomponents = new uint[4]{0};
}
void VectorParameterUpdate_2_run(uint ctx_index,Circom_CalcWit* ctx){
FrElement* circuitConstants = ctx->circuitConstants;
FrElement* signalValues = ctx->signalValues;
FrElement expaux[2];
FrElement lvar[2];
u64 mySignalStart = ctx->componentMemory[ctx_index].signalStart;
std::string myTemplateName = ctx->componentMemory[ctx_index].templateName;
std::string myComponentName = ctx->componentMemory[ctx_index].componentName;
u64 myFather = ctx->componentMemory[ctx_index].idFather;
u64 myId = ctx_index;
u32* mySubcomponents = ctx->componentMemory[ctx_index].subcomponents;
bool* mySubcomponentsParallel = ctx->componentMemory[ctx_index].subcomponentsParallel;
std::string* listOfTemplateMessages = ctx->listOfTemplateMessages;
uint sub_component_aux;
uint index_multiple_eq;
int cmp_index_ref_load = -1;
{
PFrElement aux_dest = &lvar[0];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[0]);
}
{
uint aux_create = 0;
int aux_cmp_num = 0+ctx_index+1;
uint csoffset = mySignalStart+13;
uint aux_dimensions[1] = {4};
for (uint i = 0; i < 4; i++) {
std::string new_cmp_name = "updates"+ctx->generate_position_array(aux_dimensions, 1, i);
ParameterUpdate_1_create(csoffset,aux_cmp_num,ctx,new_cmp_name,myId);
mySubcomponents[aux_create+ i] = aux_cmp_num;
csoffset += 4 ;
aux_cmp_num += 1;
}
}
{
PFrElement aux_dest = &lvar[1];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[1]);
}
Fr_lt(&expaux[0],&lvar[1],&circuitConstants[0]); // line circom 31
while(Fr_isTrue(&expaux[0])){
{
uint cmp_index_ref = ((1 * Fr_toInt(&lvar[1])) + 0);
{
PFrElement aux_dest = &ctx->signalValues[ctx->componentMemory[mySubcomponents[cmp_index_ref]].signalStart + 1];
// load src
// end load src
Fr_copy(aux_dest,&signalValues[mySignalStart + ((1 * Fr_toInt(&lvar[1])) + 4)]);
}
// run sub component if needed
if(!(ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter -= 1)){
ParameterUpdate_1_run(mySubcomponents[cmp_index_ref],ctx);
}
}
{
uint cmp_index_ref = ((1 * Fr_toInt(&lvar[1])) + 0);
{
PFrElement aux_dest = &ctx->signalValues[ctx->componentMemory[mySubcomponents[cmp_index_ref]].signalStart + 2];
// load src
// end load src
Fr_copy(aux_dest,&signalValues[mySignalStart + ((1 * Fr_toInt(&lvar[1])) + 8)]);
}
// run sub component if needed
if(!(ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter -= 1)){
ParameterUpdate_1_run(mySubcomponents[cmp_index_ref],ctx);
}
}
{
uint cmp_index_ref = ((1 * Fr_toInt(&lvar[1])) + 0);
{
PFrElement aux_dest = &ctx->signalValues[ctx->componentMemory[mySubcomponents[cmp_index_ref]].signalStart + 3];
// load src
// end load src
Fr_copy(aux_dest,&signalValues[mySignalStart + 12]);
}
// run sub component if needed
if(!(ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter -= 1)){
ParameterUpdate_1_run(mySubcomponents[cmp_index_ref],ctx);
}
}
{
PFrElement aux_dest = &signalValues[mySignalStart + ((1 * Fr_toInt(&lvar[1])) + 0)];
// load src
cmp_index_ref_load = ((1 * Fr_toInt(&lvar[1])) + 0);
cmp_index_ref_load = ((1 * Fr_toInt(&lvar[1])) + 0);
// end load src
Fr_copy(aux_dest,&ctx->signalValues[ctx->componentMemory[mySubcomponents[((1 * Fr_toInt(&lvar[1])) + 0)]].signalStart + 0]);
}
{
PFrElement aux_dest = &lvar[1];
// load src
Fr_add(&expaux[0],&lvar[1],&circuitConstants[2]); // line circom 31
// end load src
Fr_copy(aux_dest,&expaux[0]);
}
Fr_lt(&expaux[0],&lvar[1],&circuitConstants[0]); // line circom 31
}
for (uint i = 0; i < 4; i++){
uint index_subc = ctx->componentMemory[ctx_index].subcomponents[i];
if (index_subc != 0){
assert(!(ctx->componentMemory[index_subc].inputCounter));
release_memory_component(ctx,index_subc);
}
}
}
void TrainingEpoch_3_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather){
ctx->componentMemory[coffset].templateId = 3;
ctx->componentMemory[coffset].templateName = "TrainingEpoch";
ctx->componentMemory[coffset].signalStart = soffset;
ctx->componentMemory[coffset].inputCounter = 9;
ctx->componentMemory[coffset].componentName = componentName;
ctx->componentMemory[coffset].idFather = componentFather;
ctx->componentMemory[coffset].subcomponents = new uint[1]{0};
}
void TrainingEpoch_3_run(uint ctx_index,Circom_CalcWit* ctx){
FrElement* circuitConstants = ctx->circuitConstants;
FrElement* signalValues = ctx->signalValues;
FrElement expaux[1];
FrElement lvar[1];
u64 mySignalStart = ctx->componentMemory[ctx_index].signalStart;
std::string myTemplateName = ctx->componentMemory[ctx_index].templateName;
std::string myComponentName = ctx->componentMemory[ctx_index].componentName;
u64 myFather = ctx->componentMemory[ctx_index].idFather;
u64 myId = ctx_index;
u32* mySubcomponents = ctx->componentMemory[ctx_index].subcomponents;
bool* mySubcomponentsParallel = ctx->componentMemory[ctx_index].subcomponentsParallel;
std::string* listOfTemplateMessages = ctx->listOfTemplateMessages;
uint sub_component_aux;
uint index_multiple_eq;
int cmp_index_ref_load = -1;
{
PFrElement aux_dest = &lvar[0];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[0]);
}
{
std::string new_cmp_name = "param_update";
VectorParameterUpdate_2_create(mySignalStart+13,0+ctx_index+1,ctx,new_cmp_name,myId);
mySubcomponents[0] = 0+ctx_index+1;
}
{
uint cmp_index_ref = 0;
{
PFrElement aux_dest = &ctx->signalValues[ctx->componentMemory[mySubcomponents[cmp_index_ref]].signalStart + 4];
// load src
// end load src
Fr_copyn(aux_dest,&signalValues[mySignalStart + 4],4);
}
// no need to run sub component
ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter -= 4;
assert(ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter > 0);
}
{
uint cmp_index_ref = 0;
{
PFrElement aux_dest = &ctx->signalValues[ctx->componentMemory[mySubcomponents[cmp_index_ref]].signalStart + 8];
// load src
// end load src
Fr_copyn(aux_dest,&signalValues[mySignalStart + 8],4);
}
// no need to run sub component
ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter -= 4;
assert(ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter > 0);
}
{
uint cmp_index_ref = 0;
{
PFrElement aux_dest = &ctx->signalValues[ctx->componentMemory[mySubcomponents[cmp_index_ref]].signalStart + 12];
// load src
// end load src
Fr_copy(aux_dest,&signalValues[mySignalStart + 12]);
}
// need to run sub component
ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter -= 1;
assert(!(ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter));
VectorParameterUpdate_2_run(mySubcomponents[cmp_index_ref],ctx);
}
{
PFrElement aux_dest = &signalValues[mySignalStart + 0];
// load src
cmp_index_ref_load = 0;
cmp_index_ref_load = 0;
// end load src
Fr_copyn(aux_dest,&ctx->signalValues[ctx->componentMemory[mySubcomponents[0]].signalStart + 0],4);
}
for (uint i = 0; i < 1; i++){
uint index_subc = ctx->componentMemory[ctx_index].subcomponents[i];
if (index_subc != 0){
assert(!(ctx->componentMemory[index_subc].inputCounter));
release_memory_component(ctx,index_subc);
}
}
}
void ModularTrainingVerification_4_create(uint soffset,uint coffset,Circom_CalcWit* ctx,std::string componentName,uint componentFather){
ctx->componentMemory[coffset].templateId = 4;
ctx->componentMemory[coffset].templateName = "ModularTrainingVerification";
ctx->componentMemory[coffset].signalStart = soffset;
ctx->componentMemory[coffset].inputCounter = 5;
ctx->componentMemory[coffset].componentName = componentName;
ctx->componentMemory[coffset].idFather = componentFather;
ctx->componentMemory[coffset].subcomponents = new uint[4]{0};
}
void ModularTrainingVerification_4_run(uint ctx_index,Circom_CalcWit* ctx){
FrElement* circuitConstants = ctx->circuitConstants;
FrElement* signalValues = ctx->signalValues;
FrElement expaux[2];
FrElement lvar[4];
u64 mySignalStart = ctx->componentMemory[ctx_index].signalStart;
std::string myTemplateName = ctx->componentMemory[ctx_index].templateName;
std::string myComponentName = ctx->componentMemory[ctx_index].componentName;
u64 myFather = ctx->componentMemory[ctx_index].idFather;
u64 myId = ctx_index;
u32* mySubcomponents = ctx->componentMemory[ctx_index].subcomponents;
bool* mySubcomponentsParallel = ctx->componentMemory[ctx_index].subcomponentsParallel;
std::string* listOfTemplateMessages = ctx->listOfTemplateMessages;
uint sub_component_aux;
uint index_multiple_eq;
int cmp_index_ref_load = -1;
{
PFrElement aux_dest = &lvar[0];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[3]);
}
{
PFrElement aux_dest = &lvar[1];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[0]);
}
{
std::string new_cmp_name = "lr_validator";
LearningRateValidation_0_create(mySignalStart+152,18+ctx_index+1,ctx,new_cmp_name,myId);
mySubcomponents[0] = 18+ctx_index+1;
}
{
uint aux_create = 1;
int aux_cmp_num = 0+ctx_index+1;
uint csoffset = mySignalStart+26;
uint aux_dimensions[1] = {3};
for (uint i = 0; i < 3; i++) {
std::string new_cmp_name = "epochs"+ctx->generate_position_array(aux_dimensions, 1, i);
TrainingEpoch_3_create(csoffset,aux_cmp_num,ctx,new_cmp_name,myId);
mySubcomponents[aux_create+ i] = aux_cmp_num;
csoffset += 42 ;
aux_cmp_num += 6;
}
}
{
uint cmp_index_ref = 0;
{
PFrElement aux_dest = &ctx->signalValues[ctx->componentMemory[mySubcomponents[cmp_index_ref]].signalStart + 0];
// load src
// end load src
Fr_copy(aux_dest,&signalValues[mySignalStart + 9]);
}
// need to run sub component
ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter -= 1;
assert(!(ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter));
LearningRateValidation_0_run(mySubcomponents[cmp_index_ref],ctx);
}
{
PFrElement aux_dest = &lvar[2];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[1]);
}
Fr_lt(&expaux[0],&lvar[2],&circuitConstants[0]); // line circom 100
while(Fr_isTrue(&expaux[0])){
{
PFrElement aux_dest = &signalValues[mySignalStart + ((0 + (1 * Fr_toInt(&lvar[2]))) + 10)];
// load src
// end load src
Fr_copy(aux_dest,&signalValues[mySignalStart + ((1 * Fr_toInt(&lvar[2])) + 5)]);
}
{
PFrElement aux_dest = &lvar[2];
// load src
Fr_add(&expaux[0],&lvar[2],&circuitConstants[2]); // line circom 100
// end load src
Fr_copy(aux_dest,&expaux[0]);
}
Fr_lt(&expaux[0],&lvar[2],&circuitConstants[0]); // line circom 100
}
{
PFrElement aux_dest = &lvar[2];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[1]);
}
Fr_lt(&expaux[0],&lvar[2],&circuitConstants[3]); // line circom 106
while(Fr_isTrue(&expaux[0])){
{
PFrElement aux_dest = &lvar[3];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[1]);
}
Fr_lt(&expaux[0],&lvar[3],&circuitConstants[0]); // line circom 110
while(Fr_isTrue(&expaux[0])){
{
uint cmp_index_ref = ((1 * Fr_toInt(&lvar[2])) + 1);
{
PFrElement aux_dest = &ctx->signalValues[ctx->componentMemory[mySubcomponents[cmp_index_ref]].signalStart + ((1 * Fr_toInt(&lvar[3])) + 4)];
// load src
// end load src
Fr_copy(aux_dest,&signalValues[mySignalStart + (((4 * Fr_toInt(&lvar[2])) + (1 * Fr_toInt(&lvar[3]))) + 10)]);
}
// run sub component if needed
if(!(ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter -= 1)){
TrainingEpoch_3_run(mySubcomponents[cmp_index_ref],ctx);
}
}
{
PFrElement aux_dest = &lvar[3];
// load src
Fr_add(&expaux[0],&lvar[3],&circuitConstants[2]); // line circom 110
// end load src
Fr_copy(aux_dest,&expaux[0]);
}
Fr_lt(&expaux[0],&lvar[3],&circuitConstants[0]); // line circom 110
}
{
PFrElement aux_dest = &lvar[3];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[1]);
}
Fr_lt(&expaux[0],&lvar[3],&circuitConstants[0]); // line circom 115
while(Fr_isTrue(&expaux[0])){
{
uint cmp_index_ref = ((1 * Fr_toInt(&lvar[2])) + 1);
{
PFrElement aux_dest = &ctx->signalValues[ctx->componentMemory[mySubcomponents[cmp_index_ref]].signalStart + ((1 * Fr_toInt(&lvar[3])) + 8)];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[2]);
}
// run sub component if needed
if(!(ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter -= 1)){
TrainingEpoch_3_run(mySubcomponents[cmp_index_ref],ctx);
}
}
{
PFrElement aux_dest = &lvar[3];
// load src
Fr_add(&expaux[0],&lvar[3],&circuitConstants[2]); // line circom 115
// end load src
Fr_copy(aux_dest,&expaux[0]);
}
Fr_lt(&expaux[0],&lvar[3],&circuitConstants[0]); // line circom 115
}
{
uint cmp_index_ref = ((1 * Fr_toInt(&lvar[2])) + 1);
{
PFrElement aux_dest = &ctx->signalValues[ctx->componentMemory[mySubcomponents[cmp_index_ref]].signalStart + 12];
// load src
// end load src
Fr_copy(aux_dest,&signalValues[mySignalStart + 9]);
}
// run sub component if needed
if(!(ctx->componentMemory[mySubcomponents[cmp_index_ref]].inputCounter -= 1)){
TrainingEpoch_3_run(mySubcomponents[cmp_index_ref],ctx);
}
}
{
PFrElement aux_dest = &lvar[3];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[1]);
}
Fr_lt(&expaux[0],&lvar[3],&circuitConstants[0]); // line circom 122
while(Fr_isTrue(&expaux[0])){
{
PFrElement aux_dest = &signalValues[mySignalStart + (((4 * (Fr_toInt(&lvar[2]) + 1)) + (1 * Fr_toInt(&lvar[3]))) + 10)];
// load src
cmp_index_ref_load = ((1 * Fr_toInt(&lvar[2])) + 1);
cmp_index_ref_load = ((1 * Fr_toInt(&lvar[2])) + 1);
// end load src
Fr_copy(aux_dest,&ctx->signalValues[ctx->componentMemory[mySubcomponents[((1 * Fr_toInt(&lvar[2])) + 1)]].signalStart + ((1 * Fr_toInt(&lvar[3])) + 0)]);
}
{
PFrElement aux_dest = &lvar[3];
// load src
Fr_add(&expaux[0],&lvar[3],&circuitConstants[2]); // line circom 122
// end load src
Fr_copy(aux_dest,&expaux[0]);
}
Fr_lt(&expaux[0],&lvar[3],&circuitConstants[0]); // line circom 122
}
{
PFrElement aux_dest = &lvar[2];
// load src
Fr_add(&expaux[0],&lvar[2],&circuitConstants[2]); // line circom 106
// end load src
Fr_copy(aux_dest,&expaux[0]);
}
Fr_lt(&expaux[0],&lvar[2],&circuitConstants[3]); // line circom 106
}
{
PFrElement aux_dest = &lvar[2];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[1]);
}
Fr_lt(&expaux[0],&lvar[2],&circuitConstants[0]); // line circom 128
while(Fr_isTrue(&expaux[0])){
{
PFrElement aux_dest = &signalValues[mySignalStart + ((1 * Fr_toInt(&lvar[2])) + 0)];
// load src
// end load src
Fr_copy(aux_dest,&signalValues[mySignalStart + ((12 + (1 * Fr_toInt(&lvar[2]))) + 10)]);
}
{
PFrElement aux_dest = &lvar[2];
// load src
Fr_add(&expaux[0],&lvar[2],&circuitConstants[2]); // line circom 128
// end load src
Fr_copy(aux_dest,&expaux[0]);
}
Fr_lt(&expaux[0],&lvar[2],&circuitConstants[0]); // line circom 128
}
{
PFrElement aux_dest = &signalValues[mySignalStart + 4];
// load src
// end load src
Fr_copy(aux_dest,&circuitConstants[2]);
}
for (uint i = 0; i < 4; i++){
uint index_subc = ctx->componentMemory[ctx_index].subcomponents[i];
if (index_subc != 0){
assert(!(ctx->componentMemory[index_subc].inputCounter));
release_memory_component(ctx,index_subc);
}
}
}
void run(Circom_CalcWit* ctx){
ModularTrainingVerification_4_create(1,0,ctx,"main",0);
ModularTrainingVerification_4_run(0,ctx);
}

View File

@@ -0,0 +1,21 @@
const wc = require("./witness_calculator.js");
const { readFileSync, writeFile } = require("fs");
if (process.argv.length != 5) {
console.log("Usage: node generate_witness.js <file.wasm> <input.json> <output.wtns>");
} else {
const input = JSON.parse(readFileSync(process.argv[3], "utf8"));
const buffer = readFileSync(process.argv[2]);
wc(buffer).then(async witnessCalculator => {
/*
const w= await witnessCalculator.calculateWitness(input,0);
for (let i=0; i< w.length; i++){
console.log(w[i]);
}*/
const buff= await witnessCalculator.calculateWTNSBin(input,0);
writeFile(process.argv[4], buff, function(err) {
if (err) throw err;
});
});
}

View File

@@ -0,0 +1,381 @@
module.exports = async function builder(code, options) {
options = options || {};
let wasmModule;
try {
wasmModule = await WebAssembly.compile(code);
} catch (err) {
console.log(err);
console.log("\nTry to run circom --c in order to generate c++ code instead\n");
throw new Error(err);
}
let wc;
let errStr = "";
let msgStr = "";
const instance = await WebAssembly.instantiate(wasmModule, {
runtime: {
exceptionHandler : function(code) {
let err;
if (code == 1) {
err = "Signal not found.\n";
} else if (code == 2) {
err = "Too many signals set.\n";
} else if (code == 3) {
err = "Signal already set.\n";
} else if (code == 4) {
err = "Assert Failed.\n";
} else if (code == 5) {
err = "Not enough memory.\n";
} else if (code == 6) {
err = "Input signal array access exceeds the size.\n";
} else {
err = "Unknown error.\n";
}
throw new Error(err + errStr);
},
printErrorMessage : function() {
errStr += getMessage() + "\n";
// console.error(getMessage());
},
writeBufferMessage : function() {
const msg = getMessage();
// Any calls to `log()` will always end with a `\n`, so that's when we print and reset
if (msg === "\n") {
console.log(msgStr);
msgStr = "";
} else {
// If we've buffered other content, put a space in between the items
if (msgStr !== "") {
msgStr += " "
}
// Then append the message to the message we are creating
msgStr += msg;
}
},
showSharedRWMemory : function() {
printSharedRWMemory ();
}
}
});
const sanityCheck =
options
// options &&
// (
// options.sanityCheck ||
// options.logGetSignal ||
// options.logSetSignal ||
// options.logStartComponent ||
// options.logFinishComponent
// );
wc = new WitnessCalculator(instance, sanityCheck);
return wc;
function getMessage() {
var message = "";
var c = instance.exports.getMessageChar();
while ( c != 0 ) {
message += String.fromCharCode(c);
c = instance.exports.getMessageChar();
}
return message;
}
function printSharedRWMemory () {
const shared_rw_memory_size = instance.exports.getFieldNumLen32();
const arr = new Uint32Array(shared_rw_memory_size);
for (let j=0; j<shared_rw_memory_size; j++) {
arr[shared_rw_memory_size-1-j] = instance.exports.readSharedRWMemory(j);
}
// If we've buffered other content, put a space in between the items
if (msgStr !== "") {
msgStr += " "
}
// Then append the value to the message we are creating
msgStr += (fromArray32(arr).toString());
}
};
class WitnessCalculator {
constructor(instance, sanityCheck) {
this.instance = instance;
this.version = this.instance.exports.getVersion();
this.n32 = this.instance.exports.getFieldNumLen32();
this.instance.exports.getRawPrime();
const arr = new Uint32Array(this.n32);
for (let i=0; i<this.n32; i++) {
arr[this.n32-1-i] = this.instance.exports.readSharedRWMemory(i);
}
this.prime = fromArray32(arr);
this.witnessSize = this.instance.exports.getWitnessSize();
this.sanityCheck = sanityCheck;
}
circom_version() {
return this.instance.exports.getVersion();
}
async _doCalculateWitness(input_orig, sanityCheck) {
//input is assumed to be a map from signals to arrays of bigints
this.instance.exports.init((this.sanityCheck || sanityCheck) ? 1 : 0);
let prefix = "";
var input = new Object();
//console.log("Input: ", input_orig);
qualify_input(prefix,input_orig,input);
//console.log("Input after: ",input);
const keys = Object.keys(input);
var input_counter = 0;
keys.forEach( (k) => {
const h = fnvHash(k);
const hMSB = parseInt(h.slice(0,8), 16);
const hLSB = parseInt(h.slice(8,16), 16);
const fArr = flatArray(input[k]);
let signalSize = this.instance.exports.getInputSignalSize(hMSB, hLSB);
if (signalSize < 0){
throw new Error(`Signal ${k} not found\n`);
}
if (fArr.length < signalSize) {
throw new Error(`Not enough values for input signal ${k}\n`);
}
if (fArr.length > signalSize) {
throw new Error(`Too many values for input signal ${k}\n`);
}
for (let i=0; i<fArr.length; i++) {
const arrFr = toArray32(normalize(fArr[i],this.prime),this.n32)
for (let j=0; j<this.n32; j++) {
this.instance.exports.writeSharedRWMemory(j,arrFr[this.n32-1-j]);
}
try {
this.instance.exports.setInputSignal(hMSB, hLSB,i);
input_counter++;
} catch (err) {
// console.log(`After adding signal ${i} of ${k}`)
throw new Error(err);
}
}
});
if (input_counter < this.instance.exports.getInputSize()) {
throw new Error(`Not all inputs have been set. Only ${input_counter} out of ${this.instance.exports.getInputSize()}`);
}
}
async calculateWitness(input, sanityCheck) {
const w = [];
await this._doCalculateWitness(input, sanityCheck);
for (let i=0; i<this.witnessSize; i++) {
this.instance.exports.getWitness(i);
const arr = new Uint32Array(this.n32);
for (let j=0; j<this.n32; j++) {
arr[this.n32-1-j] = this.instance.exports.readSharedRWMemory(j);
}
w.push(fromArray32(arr));
}
return w;
}
async calculateBinWitness(input, sanityCheck) {
const buff32 = new Uint32Array(this.witnessSize*this.n32);
const buff = new Uint8Array( buff32.buffer);
await this._doCalculateWitness(input, sanityCheck);
for (let i=0; i<this.witnessSize; i++) {
this.instance.exports.getWitness(i);
const pos = i*this.n32;
for (let j=0; j<this.n32; j++) {
buff32[pos+j] = this.instance.exports.readSharedRWMemory(j);
}
}
return buff;
}
async calculateWTNSBin(input, sanityCheck) {
const buff32 = new Uint32Array(this.witnessSize*this.n32+this.n32+11);
const buff = new Uint8Array( buff32.buffer);
await this._doCalculateWitness(input, sanityCheck);
//"wtns"
buff[0] = "w".charCodeAt(0)
buff[1] = "t".charCodeAt(0)
buff[2] = "n".charCodeAt(0)
buff[3] = "s".charCodeAt(0)
//version 2
buff32[1] = 2;
//number of sections: 2
buff32[2] = 2;
//id section 1
buff32[3] = 1;
const n8 = this.n32*4;
//id section 1 length in 64bytes
const idSection1length = 8 + n8;
const idSection1lengthHex = idSection1length.toString(16);
buff32[4] = parseInt(idSection1lengthHex.slice(0,8), 16);
buff32[5] = parseInt(idSection1lengthHex.slice(8,16), 16);
//this.n32
buff32[6] = n8;
//prime number
this.instance.exports.getRawPrime();
var pos = 7;
for (let j=0; j<this.n32; j++) {
buff32[pos+j] = this.instance.exports.readSharedRWMemory(j);
}
pos += this.n32;
// witness size
buff32[pos] = this.witnessSize;
pos++;
//id section 2
buff32[pos] = 2;
pos++;
// section 2 length
const idSection2length = n8*this.witnessSize;
const idSection2lengthHex = idSection2length.toString(16);
buff32[pos] = parseInt(idSection2lengthHex.slice(0,8), 16);
buff32[pos+1] = parseInt(idSection2lengthHex.slice(8,16), 16);
pos += 2;
for (let i=0; i<this.witnessSize; i++) {
this.instance.exports.getWitness(i);
for (let j=0; j<this.n32; j++) {
buff32[pos+j] = this.instance.exports.readSharedRWMemory(j);
}
pos += this.n32;
}
return buff;
}
}
function qualify_input_list(prefix,input,input1){
if (Array.isArray(input)) {
for (let i = 0; i<input.length; i++) {
let new_prefix = prefix + "[" + i + "]";
qualify_input_list(new_prefix,input[i],input1);
}
} else {
qualify_input(prefix,input,input1);
}
}
function qualify_input(prefix,input,input1) {
if (Array.isArray(input)) {
a = flatArray(input);
if (a.length > 0) {
let t = typeof a[0];
for (let i = 1; i<a.length; i++) {
if (typeof a[i] != t){
throw new Error(`Types are not the same in the key ${prefix}`);
}
}
if (t == "object") {
qualify_input_list(prefix,input,input1);
} else {
input1[prefix] = input;
}
} else {
input1[prefix] = input;
}
} else if (typeof input == "object") {
const keys = Object.keys(input);
keys.forEach( (k) => {
let new_prefix = prefix == ""? k : prefix + "." + k;
qualify_input(new_prefix,input[k],input1);
});
} else {
input1[prefix] = input;
}
}
function toArray32(rem,size) {
const res = []; //new Uint32Array(size); //has no unshift
const radix = BigInt(0x100000000);
while (rem) {
res.unshift( Number(rem % radix));
rem = rem / radix;
}
if (size) {
var i = size - res.length;
while (i>0) {
res.unshift(0);
i--;
}
}
return res;
}
function fromArray32(arr) { //returns a BigInt
var res = BigInt(0);
const radix = BigInt(0x100000000);
for (let i = 0; i<arr.length; i++) {
res = res*radix + BigInt(arr[i]);
}
return res;
}
function flatArray(a) {
var res = [];
fillArray(res, a);
return res;
function fillArray(res, a) {
if (Array.isArray(a)) {
for (let i=0; i<a.length; i++) {
fillArray(res, a[i]);
}
} else {
res.push(a);
}
}
}
function normalize(n, prime) {
let res = BigInt(n) % prime
if (res < 0) res += prime
return res
}
function fnvHash(str) {
const uint64_max = BigInt(2) ** BigInt(64);
let hash = BigInt("0xCBF29CE484222325");
for (var i = 0; i < str.length; i++) {
hash ^= BigInt(str[i].charCodeAt());
hash *= BigInt(0x100000001B3);
hash %= uint64_max;
}
let shash = hash.toString(16);
let n = 16 - shash.length;
shash = '0'.repeat(n).concat(shash);
return shash;
}