1
0
Fork 0
mirror of synced 2025-09-24 04:40:05 +00:00
ZoKrates/zokrates_libsnark/lib/util.tcc
2022-05-13 12:34:05 +02:00

187 lines
No EOL
5 KiB
C++

#pragma once
#include "ffi.hpp"
#include <cassert>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
// conversion byte[N] -> libsnark bigint
template <mp_size_t N>
libff::bigint<N> to_libff_bigint(const uint8_t* input)
{
libff::bigint<N> x;
for (unsigned i = 0; i < N; i++) {
for (unsigned j = 0; j < 8; j++) {
x.data[N - 1 - i] |= uint64_t(input[i * 8 + j]) << (8 * (7 - j));
}
}
return x;
}
// conversion libsnark bigint -> byte[N]
template <mp_size_t N>
void from_libff_bigint(libff::bigint<N> x, uint8_t* out)
{
for (unsigned i = 0; i < N; i++) {
for (unsigned j = 0; j < 8; j++) {
out[i * 8 + j] = uint8_t(uint64_t(x.data[N - 1 - i]) >> (8 * (7 - j)));
}
}
}
template <mp_size_t Q, typename G1>
void serialize_g1_affine(G1 point, uint8_t*& buffer)
{
const size_t ELEMENT_SIZE = Q * sizeof(mp_limb_t);
G1 aff = point;
aff.to_affine_coordinates();
auto x = aff.X.as_bigint();
auto y = aff.Y.as_bigint();
from_libff_bigint<Q>(x, buffer);
buffer += ELEMENT_SIZE;
from_libff_bigint<Q>(y, buffer);
buffer += ELEMENT_SIZE;
}
template <mp_size_t Q, typename G2>
void serialize_g2_affine(G2 point, uint8_t*& buffer)
{
const size_t ELEMENT_SIZE = Q * sizeof(mp_limb_t);
G2 aff = point;
aff.to_affine_coordinates();
auto x0 = aff.X.c0.as_bigint();
auto x1 = aff.X.c1.as_bigint();
auto y0 = aff.Y.c0.as_bigint();
auto y1 = aff.Y.c1.as_bigint();
from_libff_bigint<Q>(x0, buffer);
buffer += ELEMENT_SIZE;
from_libff_bigint<Q>(x1, buffer);
buffer += ELEMENT_SIZE;
from_libff_bigint<Q>(y0, buffer);
buffer += ELEMENT_SIZE;
from_libff_bigint<Q>(y1, buffer);
buffer += ELEMENT_SIZE;
}
template <mp_size_t Q, typename Fq, typename G1>
G1 deserialize_g1_affine(uint8_t*& buffer)
{
const size_t ELEMENT_SIZE = Q * sizeof(mp_limb_t);
auto x = to_libff_bigint<Q>(buffer);
buffer += ELEMENT_SIZE;
auto y = to_libff_bigint<Q>(buffer);
buffer += ELEMENT_SIZE;
return G1(Fq(x), Fq(y), Fq::one());
}
template <mp_size_t Q, typename Fq2, typename G2>
G2 deserialize_g2_affine(uint8_t*& buffer)
{
const size_t ELEMENT_SIZE = Q * sizeof(mp_limb_t);
auto x0 = to_libff_bigint<Q>(buffer);
buffer += ELEMENT_SIZE;
auto x1 = to_libff_bigint<Q>(buffer);
buffer += ELEMENT_SIZE;
auto y0 = to_libff_bigint<Q>(buffer);
buffer += ELEMENT_SIZE;
auto y1 = to_libff_bigint<Q>(buffer);
buffer += ELEMENT_SIZE;
auto x = Fq2(x0, x1);
auto y = Fq2(y0, y1);
return G2(x, y, Fq2::one());
}
template <template <typename ppT> class ConstraintSystem, mp_size_t R, typename ppT>
ConstraintSystem<ppT> create_constraint_system(const uint8_t* a,
const uint8_t* b,
const uint8_t* c,
int32_t a_len,
int32_t b_len,
int32_t c_len,
int32_t constraints,
int32_t variables,
int32_t inputs)
{
ConstraintSystem<ppT> cs;
cs.primary_input_size = inputs;
cs.auxiliary_input_size = variables - inputs - 1; // ~one not included
struct vvmap_t {
int constraint_id;
int variable_id;
uint8_t variable_value[R * sizeof(mp_limb_t)];
};
const vvmap_t* a_vvmap = (vvmap_t*)a;
const vvmap_t* b_vvmap = (vvmap_t*)b;
const vvmap_t* c_vvmap = (vvmap_t*)c;
int a_id = 0;
int b_id = 0;
int c_id = 0;
for (int row = 0; row < constraints; row++) {
linear_combination<libff::Fr<ppT>> lin_comb_a, lin_comb_b, lin_comb_c;
while (a_id < a_len && a_vvmap[a_id].constraint_id == row) {
libff::bigint<R> value = to_libff_bigint<R>(a_vvmap[a_id].variable_value);
if (!value.is_zero()) {
lin_comb_a.add_term(a_vvmap[a_id].variable_id, value);
}
a_id++;
}
while (b_id < b_len && b_vvmap[b_id].constraint_id == row) {
libff::bigint<R> value = to_libff_bigint<R>(b_vvmap[b_id].variable_value);
if (!value.is_zero()) {
lin_comb_b.add_term(b_vvmap[b_id].variable_id, value);
}
b_id++;
}
while (c_id < c_len && c_vvmap[c_id].constraint_id == row) {
libff::bigint<R> value = to_libff_bigint<R>(c_vvmap[c_id].variable_value);
if (!value.is_zero()) {
lin_comb_c.add_term(c_vvmap[c_id].variable_id, value);
}
c_id++;
}
cs.add_constraint(r1cs_constraint<libff::Fr<ppT>>(lin_comb_a, lin_comb_b, lin_comb_c));
}
return cs;
}
template <typename T>
inline void from_buffer(buffer_t* buffer, T& t)
{
std::string tmp((char*)buffer->data, buffer->length);
std::stringstream ss(tmp);
ss >> t;
}
template <typename T>
inline buffer_t create_buffer(T& t)
{
std::stringstream ss;
ss << t;
std::string tmp = ss.str();
size_t length = tmp.length();
buffer_t buffer;
buffer.data = (uint8_t*)malloc(length);
buffer.length = length;
tmp.copy(reinterpret_cast<char*>(buffer.data), buffer.length);
return buffer;
}