add fr support files

This commit is contained in:
Jaremy Creechley 2023-11-20 21:15:41 -07:00
parent 7379bc04ae
commit d882610744
No known key found for this signature in database
GPG Key ID: 4E66FB67B21D3300
12 changed files with 13927 additions and 0 deletions

129
example/support/calcwit.cpp Normal file
View File

@ -0,0 +1,129 @@
#include <iomanip>
#include <sstream>
#include <assert.h>
#include "calcwit.hpp"
namespace CIRCUIT_NAME {
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;
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++;
while (pos != inipos) {
if (circuit->InputHashMap[pos].hash==h) return pos;
if (circuit->InputHashMap[pos].hash==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;
}
} //namespace

View File

@ -0,0 +1,73 @@
#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 12 //512
namespace CIRCUIT_NAME {
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,IODefPair> templateInsId2IOSignalInfo;
std::string* listOfTemplateMessages;
// parallelism
std::mutex numThreadMutex;
std::condition_variable ntcvs;
uint numThread;
uint 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);
} //namespace
#endif // CIRCOM_CALCWIT_H

8799
example/support/fr.asm Normal file

File diff suppressed because it is too large Load Diff

322
example/support/fr.cpp Normal file
View File

@ -0,0 +1,322 @@
#include "fr.hpp"
#include <stdio.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);
}
void Fr_longErr()
{
Fr_fail();
}
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_R3.longVal);
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;

287
example/support/fr.hpp Normal file
View File

@ -0,0 +1,287 @@
#ifndef __FR_H
#define __FR_H
#include "fr_element.hpp"
#include <cstdint>
#include <string>
#include <gmp.h>
#ifdef __APPLE__
#include <sys/types.h> // typedef unsigned int uint;
#endif // __APPLE__
extern FrElement Fr_q;
extern FrElement Fr_R2;
extern FrElement Fr_R3;
extern FrRawElement Fr_rawq;
extern FrRawElement Fr_rawR3;
#ifdef USE_ASM
#if defined(ARCH_X86_64)
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_rawShl(FrRawElement r, FrRawElement a, uint64_t b);
extern "C" void Fr_rawShr(FrRawElement r, FrRawElement a, uint64_t b);
extern "C" void Fr_fail();
#elif defined(ARCH_ARM64)
void Fr_copy(PFrElement r, PFrElement a);
void Fr_mul(PFrElement r, PFrElement a, PFrElement b);
void Fr_toNormal(PFrElement r, PFrElement a);
void Fr_toLongNormal(PFrElement r, PFrElement a);
int Fr_isTrue(PFrElement pE);
void Fr_copyn(PFrElement r, PFrElement a, int n);
void Fr_lt(PFrElement r, PFrElement a, PFrElement b);
int Fr_toInt(PFrElement pE);
void Fr_shr(PFrElement r, PFrElement a, PFrElement b);
void Fr_shl(PFrElement r, PFrElement a, PFrElement b);
void Fr_band(PFrElement r, PFrElement a, PFrElement b);
void Fr_bor(PFrElement r, PFrElement a, PFrElement b);
void Fr_bxor(PFrElement r, PFrElement a, PFrElement b);
void Fr_bnot(PFrElement r, PFrElement a);
void Fr_sub(PFrElement r, PFrElement a, PFrElement b);
void Fr_eq(PFrElement r, PFrElement a, PFrElement b);
void Fr_neq(PFrElement r, PFrElement a, PFrElement b);
void Fr_add(PFrElement r, PFrElement a, PFrElement b);
void Fr_gt(PFrElement r, PFrElement a, PFrElement b);
void Fr_leq(PFrElement r, PFrElement a, PFrElement b);
void Fr_geq(PFrElement r, PFrElement a, PFrElement b);
void Fr_lor(PFrElement r, PFrElement a, PFrElement b);
void Fr_lnot(PFrElement r, PFrElement a);
void Fr_land(PFrElement r, PFrElement a, PFrElement b);
void Fr_neg(PFrElement r, PFrElement a);
void Fr_toMontgomery(PFrElement r, PFrElement a);
void Fr_square(PFrElement r, PFrElement a);
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);
void Fr_rawMSquare(FrRawElement pRawResult, const FrRawElement pRawA);
extern "C" void Fr_rawMMul1(FrRawElement pRawResult, const FrRawElement pRawA, uint64_t pRawB);
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);
void Fr_rawZero(FrRawElement pRawResult);
extern "C" void Fr_rawCopyS2L(FrRawElement pRawResult, int64_t val);
extern "C" void Fr_rawAddLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB);
extern "C" void Fr_rawSubSL(FrRawElement pRawResult, uint64_t rawA, FrRawElement pRawB);
extern "C" void Fr_rawSubLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB);
extern "C" void Fr_rawNegLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB);
extern "C" int Fr_rawCmp(FrRawElement pRawA, FrRawElement pRawB);
extern "C" void Fr_rawAnd(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB);
extern "C" void Fr_rawOr(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB);
extern "C" void Fr_rawXor(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB);
extern "C" void Fr_rawShl(FrRawElement r, FrRawElement a, uint64_t b);
extern "C" void Fr_rawShr(FrRawElement r, FrRawElement a, uint64_t b);
extern "C" void Fr_rawNot(FrRawElement pRawResult, FrRawElement pRawA);
extern "C" void Fr_rawSubRegular(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB);
void Fr_fail();
void Fr_longErr();
#endif
#else
void Fr_copy(PFrElement r, PFrElement a);
void Fr_mul(PFrElement r, PFrElement a, PFrElement b);
void Fr_toNormal(PFrElement r, PFrElement a);
void Fr_toLongNormal(PFrElement r, PFrElement a);
int Fr_isTrue(PFrElement pE);
void Fr_copyn(PFrElement r, PFrElement a, int n);
void Fr_lt(PFrElement r, PFrElement a, PFrElement b);
int Fr_toInt(PFrElement pE);
void Fr_shl(PFrElement r, PFrElement a, PFrElement b);
void Fr_shr(PFrElement r, PFrElement a, PFrElement b);
void Fr_band(PFrElement r, PFrElement a, PFrElement b);
void Fr_bor(PFrElement r, PFrElement a, PFrElement b);
void Fr_bxor(PFrElement r, PFrElement a, PFrElement b);
void Fr_bnot(PFrElement r, PFrElement a);
void Fr_sub(PFrElement r, PFrElement a, PFrElement b);
void Fr_eq(PFrElement r, PFrElement a, PFrElement b);
void Fr_neq(PFrElement r, PFrElement a, PFrElement b);
void Fr_add(PFrElement r, PFrElement a, PFrElement b);
void Fr_gt(PFrElement r, PFrElement a, PFrElement b);
void Fr_leq(PFrElement r, PFrElement a, PFrElement b);
void Fr_geq(PFrElement r, PFrElement a, PFrElement b);
void Fr_lor(PFrElement r, PFrElement a, PFrElement b);
void Fr_lnot(PFrElement r, PFrElement a);
void Fr_land(PFrElement r, PFrElement a, PFrElement b);
void Fr_neg(PFrElement r, PFrElement a);
void Fr_toMontgomery(PFrElement r, PFrElement a);
void Fr_square(PFrElement r, PFrElement a);
void Fr_rawCopy(FrRawElement pRawResult, const FrRawElement pRawA);
void Fr_rawSwap(FrRawElement pRawResult, FrRawElement pRawA);
void Fr_rawAdd(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB);
void Fr_rawSub(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB);
void Fr_rawNeg(FrRawElement pRawResult, const FrRawElement pRawA);
void Fr_rawMMul(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB);
void Fr_rawMSquare(FrRawElement pRawResult, const FrRawElement pRawA);
void Fr_rawMMul1(FrRawElement pRawResult, const FrRawElement pRawA, uint64_t pRawB);
void Fr_rawToMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA);
void Fr_rawFromMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA);
int Fr_rawIsEq(const FrRawElement pRawA, const FrRawElement pRawB);
int Fr_rawIsZero(const FrRawElement pRawB);
void Fr_rawZero(FrRawElement pRawResult);
void Fr_rawCopyS2L(FrRawElement pRawResult, int64_t val);
void Fr_rawAddLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB);
void Fr_rawSubSL(FrRawElement pRawResult, uint64_t rawA, FrRawElement pRawB);
void Fr_rawSubLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB);
void Fr_rawNegLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB);
int Fr_rawCmp(FrRawElement pRawA, FrRawElement pRawB);
void Fr_rawAnd(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB);
void Fr_rawOr(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB);
void Fr_rawXor(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB);
void Fr_rawShl(FrRawElement r, FrRawElement a, uint64_t b);
void Fr_rawShr(FrRawElement r, FrRawElement a, uint64_t b);
void Fr_rawNot(FrRawElement pRawResult, FrRawElement pRawA);
void Fr_rawSubRegular(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB);
void Fr_fail();
void Fr_longErr();
#endif
// 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,23 @@
#ifndef FR_ELEMENT_HPP
#define FR_ELEMENT_HPP
#include <cstdint>
#define Fr_N64 4
#define Fr_SHORT 0x00000000
#define Fr_MONTGOMERY 0x40000000
#define Fr_SHORTMONTGOMERY 0x40000000
#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;
#endif // FR_ELEMENT_HPP

2389
example/support/fr_generic.cpp Executable file

File diff suppressed because it is too large Load Diff

Binary file not shown.

1199
example/support/fr_raw_arm64.s Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,364 @@
#include "fr_element.hpp"
#include <gmp.h>
#include <cstring>
static uint64_t Fr_rawq[] = {0x43e1f593f0000001,0x2833e84879b97091,0xb85045b68181585d,0x30644e72e131a029, 0};
static FrRawElement Fr_rawR2 = {0x1bb8e645ae216da7,0x53fe3ab1e35c59e3,0x8c49833d53bb8085,0x0216d0b17f4e44a5};
static uint64_t Fr_np = {0xc2e1f593efffffff};
static uint64_t lboMask = 0x3fffffffffffffff;
void Fr_rawAdd(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB)
{
uint64_t carry = mpn_add_n(pRawResult, pRawA, pRawB, Fr_N64);
if(carry || mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0)
{
mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
}
}
void Fr_rawAddLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB)
{
uint64_t carry = mpn_add_1(pRawResult, pRawA, Fr_N64, rawB);
if(carry || mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0)
{
mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
}
}
void Fr_rawSub(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB)
{
uint64_t carry = mpn_sub_n(pRawResult, pRawA, pRawB, Fr_N64);
if(carry)
{
mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
}
}
void Fr_rawSubRegular(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB)
{
mpn_sub_n(pRawResult, pRawA, pRawB, Fr_N64);
}
void Fr_rawSubSL(FrRawElement pRawResult, uint64_t rawA, FrRawElement pRawB)
{
FrRawElement pRawA = {rawA, 0, 0, 0};
uint64_t carry = mpn_sub_n(pRawResult, pRawA, pRawB, Fr_N64);
if(carry)
{
mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
}
}
void Fr_rawSubLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB)
{
uint64_t carry = mpn_sub_1(pRawResult, pRawA, Fr_N64, rawB);
if(carry)
{
mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
}
}
void Fr_rawNeg(FrRawElement pRawResult, const FrRawElement pRawA)
{
const uint64_t zero[Fr_N64] = {0, 0, 0, 0};
if (mpn_cmp(pRawA, zero, Fr_N64) != 0)
{
mpn_sub_n(pRawResult, Fr_rawq, pRawA, Fr_N64);
}
else
{
mpn_copyi(pRawResult, zero, Fr_N64);
}
}
// Substracts a long element and a short element form 0
void Fr_rawNegLS(FrRawElement pRawResult, FrRawElement pRawA, uint64_t rawB)
{
uint64_t carry1 = mpn_sub_1(pRawResult, Fr_rawq, Fr_N64, rawB);
uint64_t carry2 = mpn_sub_n(pRawResult, pRawResult, pRawA, Fr_N64);
if (carry1 || carry2)
{
mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
}
}
void Fr_rawCopy(FrRawElement pRawResult, const FrRawElement pRawA)
{
pRawResult[0] = pRawA[0];
pRawResult[1] = pRawA[1];
pRawResult[2] = pRawA[2];
pRawResult[3] = pRawA[3];
}
int Fr_rawIsEq(const FrRawElement pRawA, const FrRawElement pRawB)
{
return mpn_cmp(pRawA, pRawB, Fr_N64) == 0;
}
void Fr_rawMMul(FrRawElement pRawResult, const FrRawElement pRawA, const FrRawElement pRawB)
{
const mp_size_t N = Fr_N64+1;
const uint64_t *mq = Fr_rawq;
uint64_t np0;
uint64_t product0[N] = {0};
uint64_t product1[N] = {0};
uint64_t product2[N] = {0};
uint64_t product3[N] = {0};
product0[4] = mpn_mul_1(product0, pRawB, Fr_N64, pRawA[0]);
np0 = Fr_np * product0[0];
product1[1] = mpn_addmul_1(product0, mq, N, np0);
product1[4] = mpn_addmul_1(product1, pRawB, Fr_N64, pRawA[1]);
mpn_add(product1, product1, N, product0+1, N-1);
np0 = Fr_np * product1[0];
product2[1] = mpn_addmul_1(product1, mq, N, np0);
product2[4] = mpn_addmul_1(product2, pRawB, Fr_N64, pRawA[2]);
mpn_add(product2, product2, N, product1+1, N-1);
np0 = Fr_np * product2[0];
product3[1] = mpn_addmul_1(product2, mq, N, np0);
product3[4] = mpn_addmul_1(product3, pRawB, Fr_N64, pRawA[3]);
mpn_add(product3, product3, N, product2+1, N-1);
np0 = Fr_np * product3[0];
mpn_addmul_1(product3, mq, N, np0);
mpn_copyi(pRawResult, product3+1, Fr_N64);
if (mpn_cmp(pRawResult, mq, Fr_N64) >= 0)
{
mpn_sub_n(pRawResult, pRawResult, mq, Fr_N64);
}
}
void Fr_rawMSquare(FrRawElement pRawResult, const FrRawElement pRawA)
{
Fr_rawMMul(pRawResult, pRawA, pRawA);
}
void Fr_rawMMul1(FrRawElement pRawResult, const FrRawElement pRawA, uint64_t pRawB)
{
const mp_size_t N = Fr_N64+1;
const uint64_t *mq = Fr_rawq;
uint64_t np0;
uint64_t product0[N] = {0};
uint64_t product1[N] = {0};
uint64_t product2[N] = {0};
uint64_t product3[N] = {0};
product0[4] = mpn_mul_1(product0, pRawA, Fr_N64, pRawB);
np0 = Fr_np * product0[0];
product1[1] = mpn_addmul_1(product0, mq, N, np0);
mpn_add(product1, product1, N, product0+1, N-1);
np0 = Fr_np * product1[0];
product2[1] = mpn_addmul_1(product1, mq, N, np0);
mpn_add(product2, product2, N, product1+1, N-1);
np0 = Fr_np * product2[0];
product3[1] = mpn_addmul_1(product2, mq, N, np0);
mpn_add(product3, product3, N, product2+1, N-1);
np0 = Fr_np * product3[0];
mpn_addmul_1(product3, mq, N, np0);
mpn_copyi(pRawResult, product3+1, Fr_N64);
if (mpn_cmp(pRawResult, mq, Fr_N64) >= 0)
{
mpn_sub_n(pRawResult, pRawResult, mq, Fr_N64);
}
}
void Fr_rawToMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA)
{
Fr_rawMMul(pRawResult, pRawA, Fr_rawR2);
}
void Fr_rawFromMontgomery(FrRawElement pRawResult, const FrRawElement &pRawA)
{
const mp_size_t N = Fr_N64+1;
const uint64_t *mq = Fr_rawq;
uint64_t np0;
uint64_t product0[N];
uint64_t product1[N] = {0};
uint64_t product2[N] = {0};
uint64_t product3[N] = {0};
mpn_copyi(product0, pRawA, Fr_N64); product0[4] = 0;
np0 = Fr_np * product0[0];
product1[1] = mpn_addmul_1(product0, mq, N, np0);
mpn_add(product1, product1, N, product0+1, N-1);
np0 = Fr_np * product1[0];
product2[1] = mpn_addmul_1(product1, mq, N, np0);
mpn_add(product2, product2, N, product1+1, N-1);
np0 = Fr_np * product2[0];
product3[1] = mpn_addmul_1(product2, mq, N, np0);
mpn_add(product3, product3, N, product2+1, N-1);
np0 = Fr_np * product3[0];
mpn_addmul_1(product3, mq, N, np0);
mpn_copyi(pRawResult, product3+1, Fr_N64);
if (mpn_cmp(pRawResult, mq, Fr_N64) >= 0)
{
mpn_sub_n(pRawResult, pRawResult, mq, Fr_N64);
}
}
int Fr_rawIsZero(const FrRawElement rawA)
{
return mpn_zero_p(rawA, Fr_N64) ? 1 : 0;
}
int Fr_rawCmp(FrRawElement pRawA, FrRawElement pRawB)
{
return mpn_cmp(pRawA, pRawB, Fr_N64);
}
void Fr_rawSwap(FrRawElement pRawResult, FrRawElement pRawA)
{
FrRawElement temp;
temp[0] = pRawResult[0];
temp[1] = pRawResult[1];
temp[2] = pRawResult[2];
temp[3] = pRawResult[3];
pRawResult[0] = pRawA[0];
pRawResult[1] = pRawA[1];
pRawResult[2] = pRawA[2];
pRawResult[3] = pRawA[3];
pRawA[0] = temp[0];
pRawA[1] = temp[1];
pRawA[2] = temp[2];
pRawA[3] = temp[3];
}
void Fr_rawCopyS2L(FrRawElement pRawResult, int64_t val)
{
pRawResult[0] = val;
pRawResult[1] = 0;
pRawResult[2] = 0;
pRawResult[3] = 0;
if (val < 0)
{
pRawResult[1] = -1;
pRawResult[2] = -1;
pRawResult[3] = -1;
mpn_add_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
}
}
void Fr_rawAnd(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB)
{
mpn_and_n(pRawResult, pRawA, pRawB, Fr_N64);
pRawResult[3] &= lboMask;
if (mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0)
{
mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
}
}
void Fr_rawOr(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB)
{
mpn_ior_n(pRawResult, pRawA, pRawB, Fr_N64);
pRawResult[3] &= lboMask;
if (mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0)
{
mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
}
}
void Fr_rawXor(FrRawElement pRawResult, FrRawElement pRawA, FrRawElement pRawB)
{
mpn_xor_n(pRawResult, pRawA, pRawB, Fr_N64);
pRawResult[3] &= lboMask;
if (mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0)
{
mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
}
}
void Fr_rawShl(FrRawElement r, FrRawElement a, uint64_t b)
{
uint64_t bit_shift = b % 64;
uint64_t word_shift = b / 64;
uint64_t word_count = Fr_N64 - word_shift;
mpn_copyi(r + word_shift, a, word_count);
std::memset(r, 0, word_shift * sizeof(uint64_t));
if (bit_shift)
{
mpn_lshift(r, r, Fr_N64, bit_shift);
}
r[3] &= lboMask;
if (mpn_cmp(r, Fr_rawq, Fr_N64) >= 0)
{
mpn_sub_n(r, r, Fr_rawq, Fr_N64);
}
}
void Fr_rawShr(FrRawElement r, FrRawElement a, uint64_t b)
{
const uint64_t bit_shift = b % 64;
const uint64_t word_shift = b / 64;
const uint64_t word_count = Fr_N64 - word_shift;
mpn_copyi(r, a + word_shift, word_count);
std::memset(r + word_count, 0, word_shift * sizeof(uint64_t));
if (bit_shift)
{
mpn_rshift(r, r, Fr_N64, bit_shift);
}
}
void Fr_rawNot(FrRawElement pRawResult, FrRawElement pRawA)
{
mpn_com(pRawResult, pRawA, Fr_N64);
pRawResult[3] &= lboMask;
if (mpn_cmp(pRawResult, Fr_rawq, Fr_N64) >= 0)
{
mpn_sub_n(pRawResult, pRawResult, Fr_rawq, Fr_N64);
}
}

View File

@ -0,0 +1,309 @@
#include "witnesscalc.h"
#include "calcwit.hpp"
#include "circom.hpp"
#include "fr.hpp"
#include <nlohmann/json.hpp>
#include <sstream>
#include <memory>
namespace CIRCUIT_NAME {
using json = nlohmann::json;
Circom_Circuit* loadCircuit(const void *buffer, unsigned long buffer_size) {
if (buffer_size % sizeof(u32) != 0) {
throw std::runtime_error("Invalid circuit file: wrong buffer_size");
}
Circom_Circuit *circuit = new Circom_Circuit;
u8* bdata = (u8*)buffer;
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,IODefPair> templateInsId2IOSignalInfo1;
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;
if (inisize % sizeof(u32) != 0) {
throw std::runtime_error("Invalid circuit file: wrong inisize");
}
u32 dataiomap[(buffer_size-inisize)/sizeof(u32)];
memcpy((void *)dataiomap, (void *)(bdata+inisize), buffer_size-inisize);
u32* pu32 = dataiomap;
for (int i = 0; i < get_size_of_io_map(); i++) {
u32 n = *pu32;
IODefPair p;
p.len = n;
IODef 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;
}
p.defs = (IODef*)calloc(10, sizeof(IODef));
for (u32 j = 0; j < p.len; j++){
p.defs[j] = defs[j];
}
templateInsId2IOSignalInfo1[index[i]] = p;
}
}
circuit->templateInsId2IOSignalInfo = move(templateInsId2IOSignalInfo1);
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 {
throw std::runtime_error("Invalid JSON type");
}
Fr_str2element (&v, s.c_str(), base);
vval.push_back(v);
} else {
for (uint i = 0; i < val.size(); i++) {
json2FrElements (val[i], vval);
}
}
}
void loadJson(Circom_CalcWit *ctx, const char *json_buffer, unsigned long buffer_size) {
json j = json::parse(json_buffer, json_buffer + buffer_size);
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() );
}
}
}
}
unsigned long getBinWitnessSize() {
uint Nwtns = get_size_of_witness();
return 44 + Fr_N64*8 * (Nwtns + 1);
}
char *appendBuffer(char *buffer, const void *src, unsigned long src_size) {
memcpy(buffer, src, src_size);
return buffer + src_size;
}
char *appendBuffer(char *buffer, const u32 src) {
return appendBuffer(buffer, &src, 4);
}
char *appendBuffer(char *buffer, const u64 src) {
return appendBuffer(buffer, &src, 8);
}
char *appendBuffer(char *buffer, const FrRawElement src) {
return appendBuffer(buffer, src, Fr_N64*8);
}
void storeBinWitness(Circom_CalcWit *ctx, char *buffer) {
buffer = appendBuffer(buffer, "wtns", 4);
u32 version = 2;
buffer = appendBuffer(buffer, version);
u32 nSections = 2;
buffer = appendBuffer(buffer, nSections);
// Header
u32 idSection1 = 1;
buffer = appendBuffer(buffer, idSection1);
u32 n8 = Fr_N64*8;
u64 idSection1length = 8 + n8;
buffer = appendBuffer(buffer, idSection1length);
buffer = appendBuffer(buffer, n8);
buffer = appendBuffer(buffer, Fr_q.longVal);
uint Nwtns = get_size_of_witness();
u32 nVars = (u32)Nwtns;
buffer = appendBuffer(buffer, nVars);
// Data
u32 idSection2 = 2;
buffer = appendBuffer(buffer, idSection2);
u64 idSection2length = (u64)n8*(u64)Nwtns;
buffer = appendBuffer(buffer, idSection2length);
FrElement v;
for (int i=0;i<Nwtns;i++) {
ctx->getWitness(i, &v);
Fr_toLongNormal(&v, &v);
buffer = appendBuffer(buffer, v.longVal);
}
}
int witnesscalc(
const char *circuit_buffer, unsigned long circuit_size,
const char *json_buffer, unsigned long json_size,
char *wtns_buffer, unsigned long *wtns_size,
char *error_msg, unsigned long error_msg_maxsize)
{
unsigned long witnessSize = getBinWitnessSize();
if (*wtns_size < witnessSize) {
*wtns_size = witnessSize;
return WITNESSCALC_ERROR_SHORT_BUFFER;
}
try {
std::unique_ptr<Circom_Circuit> circuit(loadCircuit(circuit_buffer, circuit_size));
std::unique_ptr<Circom_CalcWit> ctx(new Circom_CalcWit(circuit.get()));
loadJson(ctx.get(), json_buffer, json_size);
if (ctx.get()->getRemaingInputsToBeSet() != 0) {
std::stringstream stream;
stream << "Not all inputs have been set. Only "
<< get_main_input_signal_no()-ctx.get()->getRemaingInputsToBeSet()
<< " out of " << get_main_input_signal_no();
strncpy(error_msg, stream.str().c_str(), error_msg_maxsize);
return WITNESSCALC_ERROR;
}
storeBinWitness(ctx.get(), wtns_buffer);
*wtns_size = witnessSize;
} catch (std::exception& e) {
if (error_msg) {
strncpy(error_msg, e.what(), error_msg_maxsize);
}
return WITNESSCALC_ERROR;
} catch (std::exception *e) {
if (error_msg) {
strncpy(error_msg, e->what(), error_msg_maxsize);
}
delete e;
return WITNESSCALC_ERROR;
} catch (...) {
if (error_msg) {
strncpy(error_msg, "unknown error", error_msg_maxsize);
}
return WITNESSCALC_ERROR;
}
return WITNESSCALC_OK;
}
} // namespace

View File

@ -0,0 +1,33 @@
#ifndef WITNESSCALC_H
#define WITNESSCALC_H
namespace CIRCUIT_NAME {
#define WITNESSCALC_OK 0x0
#define WITNESSCALC_ERROR 0x1
#define WITNESSCALC_ERROR_SHORT_BUFFER 0x2
/**
*
* @return error code:
* WITNESSCALC_OK - in case of success.
* WITNESSCALC_ERROR - in case of an error.
*
* On success wtns_buffer is filled with witness data and
* wtns_size contains the number bytes copied to wtns_buffer.
*
* If wtns_buffer is too small then the function returns WITNESSCALC_ERROR_SHORT_BUFFER
* and the minimum size for wtns_buffer in wtns_size.
*
*/
int
witnesscalc(
const char *circuit_buffer, unsigned long circuit_size,
const char *json_buffer, unsigned long json_size,
char *wtns_buffer, unsigned long *wtns_size,
char *error_msg, unsigned long error_msg_maxsize);
} // namespace
#endif // WITNESSCALC_H