Browse Source

Merge with libsnarks used for HUSH 1.0.12 (4015f558bb)

pull/94/head
FireMartZ 6 years ago
parent
commit
62d1e78a19
  1. 8
      src/snark/src/algebra/curves/alt_bn128/alt_bn128_g1.cpp
  2. 8
      src/snark/src/algebra/curves/alt_bn128/alt_bn128_g1.hpp
  3. 8
      src/snark/src/algebra/curves/alt_bn128/alt_bn128_g2.cpp
  4. 8
      src/snark/src/algebra/curves/alt_bn128/alt_bn128_g2.hpp
  5. 6
      src/snark/src/algebra/curves/alt_bn128/alt_bn128_pairing.cpp
  6. 2
      src/snark/src/algebra/curves/curve_utils.tcc
  7. 42
      src/snark/src/algebra/curves/tests/test_bilinearity.cpp
  8. 101
      src/snark/src/algebra/curves/tests/test_groups.cpp
  9. 10
      src/snark/src/algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc
  10. 48
      src/snark/src/algebra/evaluation_domain/domains/extended_radix2_domain.hpp
  11. 180
      src/snark/src/algebra/evaluation_domain/domains/extended_radix2_domain.tcc
  12. 50
      src/snark/src/algebra/evaluation_domain/domains/step_radix2_domain.hpp
  13. 247
      src/snark/src/algebra/evaluation_domain/domains/step_radix2_domain.tcc
  14. 12
      src/snark/src/algebra/evaluation_domain/evaluation_domain.tcc
  15. 2
      src/snark/src/algebra/exponentiation/exponentiation.hpp
  16. 4
      src/snark/src/algebra/exponentiation/exponentiation.tcc
  17. 4
      src/snark/src/algebra/fields/bigint.hpp
  18. 13
      src/snark/src/algebra/fields/bigint.tcc
  19. 8
      src/snark/src/algebra/fields/field_utils.hpp
  20. 32
      src/snark/src/algebra/fields/field_utils.tcc
  21. 28
      src/snark/src/algebra/fields/fp.hpp
  22. 22
      src/snark/src/algebra/fields/fp.tcc
  23. 4
      src/snark/src/algebra/fields/fp12_2over3over2.hpp
  24. 10
      src/snark/src/algebra/fields/fp12_2over3over2.tcc
  25. 8
      src/snark/src/algebra/fields/fp2.hpp
  26. 8
      src/snark/src/algebra/fields/fp2.tcc
  27. 6
      src/snark/src/algebra/fields/fp3.hpp
  28. 6
      src/snark/src/algebra/fields/fp3.tcc
  29. 4
      src/snark/src/algebra/fields/fp6_3over2.hpp
  30. 4
      src/snark/src/algebra/fields/fp6_3over2.tcc
  31. 90
      src/snark/src/algebra/fields/tests/test_bigint.cpp
  32. 108
      src/snark/src/algebra/fields/tests/test_fields.cpp
  33. 1
      src/snark/src/algebra/scalar_multiplication/kc_multiexp.tcc
  34. 16
      src/snark/src/algebra/scalar_multiplication/multiexp.tcc
  35. 2
      src/snark/src/algebra/scalar_multiplication/wnaf.hpp
  36. 18
      src/snark/src/algebra/scalar_multiplication/wnaf.tcc
  37. 8
      src/snark/src/common/assert_except.hpp
  38. 18
      src/snark/src/common/data_structures/merkle_tree.tcc
  39. 14
      src/snark/src/common/data_structures/sparse_vector.hpp
  40. 36
      src/snark/src/common/data_structures/sparse_vector.tcc
  41. 67
      src/snark/src/common/profiling.cpp
  42. 10
      src/snark/src/common/profiling.hpp
  43. 28
      src/snark/src/common/utils.cpp
  44. 10
      src/snark/src/common/utils.hpp
  45. 40
      src/snark/src/gadgetlib1/gadgets/basic_gadgets.tcc
  46. 2
      src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_aux.tcc
  47. 4
      src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp
  48. 6
      src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc
  49. 6
      src/snark/src/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp
  50. 4
      src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.tcc
  51. 4
      src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.tcc
  52. 1
      src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp
  53. 4
      src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.tcc
  54. 22
      src/snark/src/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp
  55. 4
      src/snark/src/gadgetlib1/pb_variable.hpp
  56. 4
      src/snark/src/gadgetlib1/pb_variable.tcc
  57. 31
      src/snark/src/relations/arithmetic_programs/qap/tests/test_qap.cpp
  58. 2
      src/snark/src/relations/variable.hpp
  59. 2
      src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc
  60. 14
      src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp

8
src/snark/src/algebra/curves/alt_bn128/alt_bn128_g1.cpp

@ -10,12 +10,12 @@
namespace libsnark {
#ifdef PROFILE_OP_COUNTS
long long alt_bn128_G1::add_cnt = 0;
long long alt_bn128_G1::dbl_cnt = 0;
int64_t alt_bn128_G1::add_cnt = 0;
int64_t alt_bn128_G1::dbl_cnt = 0;
#endif
std::vector<size_t> alt_bn128_G1::wnaf_window_table;
std::vector<size_t> alt_bn128_G1::fixed_base_exp_window_table;
std::vector<uint64_t> alt_bn128_G1::wnaf_window_table;
std::vector<uint64_t> alt_bn128_G1::fixed_base_exp_window_table;
alt_bn128_G1 alt_bn128_G1::G1_zero;
alt_bn128_G1 alt_bn128_G1::G1_one;

8
src/snark/src/algebra/curves/alt_bn128/alt_bn128_g1.hpp

@ -20,11 +20,11 @@ std::istream& operator>>(std::istream &, alt_bn128_G1&);
class alt_bn128_G1 {
public:
#ifdef PROFILE_OP_COUNTS
static long long add_cnt;
static long long dbl_cnt;
static int64_t add_cnt;
static int64_t dbl_cnt;
#endif
static std::vector<size_t> wnaf_window_table;
static std::vector<size_t> fixed_base_exp_window_table;
static std::vector<uint64_t> wnaf_window_table;
static std::vector<uint64_t> fixed_base_exp_window_table;
static alt_bn128_G1 G1_zero;
static alt_bn128_G1 G1_one;

8
src/snark/src/algebra/curves/alt_bn128/alt_bn128_g2.cpp

@ -10,12 +10,12 @@
namespace libsnark {
#ifdef PROFILE_OP_COUNTS
long long alt_bn128_G2::add_cnt = 0;
long long alt_bn128_G2::dbl_cnt = 0;
int64_t alt_bn128_G2::add_cnt = 0;
int64_t alt_bn128_G2::dbl_cnt = 0;
#endif
std::vector<size_t> alt_bn128_G2::wnaf_window_table;
std::vector<size_t> alt_bn128_G2::fixed_base_exp_window_table;
std::vector<uint64_t> alt_bn128_G2::wnaf_window_table;
std::vector<uint64_t> alt_bn128_G2::fixed_base_exp_window_table;
alt_bn128_G2 alt_bn128_G2::G2_zero;
alt_bn128_G2 alt_bn128_G2::G2_one;

8
src/snark/src/algebra/curves/alt_bn128/alt_bn128_g2.hpp

@ -20,11 +20,11 @@ std::istream& operator>>(std::istream &, alt_bn128_G2&);
class alt_bn128_G2 {
public:
#ifdef PROFILE_OP_COUNTS
static long long add_cnt;
static long long dbl_cnt;
static int64_t add_cnt;
static int64_t dbl_cnt;
#endif
static std::vector<size_t> wnaf_window_table;
static std::vector<size_t> fixed_base_exp_window_table;
static std::vector<uint64_t> wnaf_window_table;
static std::vector<uint64_t> fixed_base_exp_window_table;
static alt_bn128_G2 G2_zero;
static alt_bn128_G2 G2_one;

6
src/snark/src/algebra/curves/alt_bn128/alt_bn128_pairing.cpp

@ -324,7 +324,7 @@ alt_bn128_ate_G2_precomp alt_bn128_ate_precompute_G2(const alt_bn128_G2& Q)
bool found_one = false;
alt_bn128_ate_ell_coeffs c;
for (long i = loop_count.max_bits(); i >= 0; --i)
for (int64_t i = loop_count.max_bits(); i >= 0; --i)
{
const bool bit = loop_count.test_bit(i);
if (!found_one)
@ -378,7 +378,7 @@ alt_bn128_Fq12 alt_bn128_ate_miller_loop(const alt_bn128_ate_G1_precomp &prec_P,
const bigint<alt_bn128_Fr::num_limbs> &loop_count = alt_bn128_ate_loop_count;
alt_bn128_ate_ell_coeffs c;
for (long i = loop_count.max_bits(); i >= 0; --i)
for (int64_t i = loop_count.max_bits(); i >= 0; --i)
{
const bool bit = loop_count.test_bit(i);
if (!found_one)
@ -432,7 +432,7 @@ alt_bn128_Fq12 alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp &
size_t idx = 0;
const bigint<alt_bn128_Fr::num_limbs> &loop_count = alt_bn128_ate_loop_count;
for (long i = loop_count.max_bits(); i >= 0; --i)
for (int64_t i = loop_count.max_bits(); i >= 0; --i)
{
const bool bit = loop_count.test_bit(i);
if (!found_one)

2
src/snark/src/algebra/curves/curve_utils.tcc

@ -16,7 +16,7 @@ GroupT scalar_mul(const GroupT &base, const bigint<m> &scalar)
GroupT result = GroupT::zero();
bool found_one = false;
for (long i = scalar.max_bits() - 1; i >= 0; --i)
for (int64_t i = scalar.max_bits() - 1; i >= 0; --i)
{
if (found_one)
{

42
src/snark/src/algebra/curves/tests/test_bilinearity.cpp

@ -4,13 +4,17 @@
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#include <iostream>
#include "common/profiling.hpp"
//#include "algebra/curves/edwards/edwards_pp.hpp"
#ifdef CURVE_BN128
#include "algebra/curves/bn128/bn128_pp.hpp"
#endif
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
#include <gtest/gtest.h>
//#include "algebra/curves/mnt/mnt4/mnt4_pp.hpp"
//#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
#include "algebra/curves/alt_bn128/alt_bn128_pairing.hpp"
#include "algebra/curves/alt_bn128/alt_bn128_pairing.cpp"
using namespace libsnark;
@ -45,11 +49,11 @@ void pairing_test()
ans1.print();
ans2.print();
ans3.print();
EXPECT_EQ(ans1, ans2);
EXPECT_EQ(ans2, ans3);
assert(ans1 == ans2);
assert(ans2 == ans3);
EXPECT_NE(ans1, GT_one);
EXPECT_EQ((ans1^Fr<ppT>::field_char()), GT_one);
assert(ans1 != GT_one);
assert((ans1^Fr<ppT>::field_char()) == GT_one);
printf("\n\n");
}
@ -69,7 +73,7 @@ void double_miller_loop_test()
const Fqk<ppT> ans_1 = ppT::miller_loop(prec_P1, prec_Q1);
const Fqk<ppT> ans_2 = ppT::miller_loop(prec_P2, prec_Q2);
const Fqk<ppT> ans_12 = ppT::double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2);
EXPECT_EQ(ans_1 * ans_2, ans_12);
assert(ans_1 * ans_2 == ans_12);
}
template<typename ppT>
@ -98,17 +102,31 @@ void affine_pairing_test()
ans1.print();
ans2.print();
ans3.print();
EXPECT_EQ(ans1, ans2);
EXPECT_EQ(ans2, ans3);
assert(ans1 == ans2);
assert(ans2 == ans3);
EXPECT_NE(ans1, GT_one);
EXPECT_EQ((ans1^Fr<ppT>::field_char()), GT_one);
assert(ans1 != GT_one);
assert((ans1^Fr<ppT>::field_char()) == GT_one);
printf("\n\n");
}
TEST(algebra, bilinearity)
int main(void)
{
start_profiling();
edwards_pp::init_public_params();
pairing_test<edwards_pp>();
double_miller_loop_test<edwards_pp>();
mnt6_pp::init_public_params();
pairing_test<mnt6_pp>();
double_miller_loop_test<mnt6_pp>();
affine_pairing_test<mnt6_pp>();
mnt4_pp::init_public_params();
pairing_test<mnt4_pp>();
double_miller_loop_test<mnt4_pp>();
affine_pairing_test<mnt4_pp>();
alt_bn128_pp::init_public_params();
pairing_test<alt_bn128_pp>();
double_miller_loop_test<alt_bn128_pp>();

101
src/snark/src/algebra/curves/tests/test_groups.cpp

@ -5,14 +5,15 @@
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#include "common/profiling.hpp"
//#include "algebra/curves/edwards/edwards_pp.hpp"
//#include "algebra/curves/mnt/mnt4/mnt4_pp.hpp"
//#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
#ifdef CURVE_BN128
#include "algebra/curves/bn128/bn128_pp.hpp"
#endif
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
#include <sstream>
#include <gtest/gtest.h>
using namespace libsnark;
template<typename GroupT>
@ -24,31 +25,31 @@ void test_mixed_add()
el = GroupT::zero();
el.to_special();
result = base.mixed_add(el);
EXPECT_EQ(result, base + el);
assert(result == base + el);
base = GroupT::zero();
el = GroupT::random_element();
el.to_special();
result = base.mixed_add(el);
EXPECT_EQ(result, base + el);
assert(result == base + el);
base = GroupT::random_element();
el = GroupT::zero();
el.to_special();
result = base.mixed_add(el);
EXPECT_EQ(result, base + el);
assert(result == base + el);
base = GroupT::random_element();
el = GroupT::random_element();
el.to_special();
result = base.mixed_add(el);
EXPECT_EQ(result, base + el);
assert(result == base + el);
base = GroupT::random_element();
el = base;
el.to_special();
result = base.mixed_add(el);
EXPECT_EQ(result, base.dbl());
assert(result == base.dbl());
}
template<typename GroupT>
@ -59,53 +60,53 @@ void test_group()
bigint<1> randsum = bigint<1>("121160274");
GroupT zero = GroupT::zero();
EXPECT_EQ(zero, zero);
assert(zero == zero);
GroupT one = GroupT::one();
EXPECT_EQ(one, one);
assert(one == one);
GroupT two = bigint<1>(2l) * GroupT::one();
EXPECT_EQ(two, two);
assert(two == two);
GroupT five = bigint<1>(5l) * GroupT::one();
GroupT three = bigint<1>(3l) * GroupT::one();
GroupT four = bigint<1>(4l) * GroupT::one();
EXPECT_EQ(two+five, three+four);
assert(two+five == three+four);
GroupT a = GroupT::random_element();
GroupT b = GroupT::random_element();
EXPECT_NE(one, zero);
EXPECT_NE(a, zero);
EXPECT_NE(a, one);
assert(one != zero);
assert(a != zero);
assert(a != one);
EXPECT_NE(b, zero);
EXPECT_NE(b, one);
assert(b != zero);
assert(b != one);
EXPECT_EQ(a.dbl(), a + a);
EXPECT_EQ(b.dbl(), b + b);
EXPECT_EQ(one.add(two), three);
EXPECT_EQ(two.add(one), three);
EXPECT_EQ(a + b, b + a);
EXPECT_EQ(a - a, zero);
EXPECT_EQ(a - b, a + (-b));
EXPECT_EQ(a - b, (-b) + a);
assert(a.dbl() == a + a);
assert(b.dbl() == b + b);
assert(one.add(two) == three);
assert(two.add(one) == three);
assert(a + b == b + a);
assert(a - a == zero);
assert(a - b == a + (-b));
assert(a - b == (-b) + a);
// handle special cases
EXPECT_EQ(zero + (-a), -a);
EXPECT_EQ(zero - a, -a);
EXPECT_EQ(a - zero, a);
EXPECT_EQ(a + zero, a);
EXPECT_EQ(zero + a, a);
assert(zero + (-a) == -a);
assert(zero - a == -a);
assert(a - zero == a);
assert(a + zero == a);
assert(zero + a == a);
EXPECT_EQ((a + b).dbl(), (a + b) + (b + a));
EXPECT_EQ(bigint<1>("2") * (a + b), (a + b) + (b + a));
assert((a + b).dbl() == (a + b) + (b + a));
assert(bigint<1>("2") * (a + b) == (a + b) + (b + a));
EXPECT_EQ((rand1 * a) + (rand2 * a), (randsum * a));
assert((rand1 * a) + (rand2 * a) == (randsum * a));
EXPECT_EQ(GroupT::order() * a, zero);
EXPECT_EQ(GroupT::order() * one, zero);
EXPECT_NE((GroupT::order() * a) - a, zero);
EXPECT_NE((GroupT::order() * one) - one, zero);
assert(GroupT::order() * a == zero);
assert(GroupT::order() * one == zero);
assert((GroupT::order() * a) - a != zero);
assert((GroupT::order() * one) - one != zero);
test_mixed_add<GroupT>();
}
@ -114,7 +115,7 @@ template<typename GroupT>
void test_mul_by_q()
{
GroupT a = GroupT::random_element();
EXPECT_EQ((GroupT::base_field_char()*a), a.mul_by_q());
assert((GroupT::base_field_char()*a) == a.mul_by_q());
}
template<typename GroupT>
@ -128,14 +129,36 @@ void test_output()
ss << g;
GroupT gg;
ss >> gg;
EXPECT_EQ(g, gg);
assert(g == gg);
/* use a random point in next iteration */
g = GroupT::random_element();
}
}
TEST(algebra, groups)
int main(void)
{
/*
edwards_pp::init_public_params();
test_group<G1<edwards_pp> >();
test_output<G1<edwards_pp> >();
test_group<G2<edwards_pp> >();
test_output<G2<edwards_pp> >();
test_mul_by_q<G2<edwards_pp> >();
mnt4_pp::init_public_params();
test_group<G1<mnt4_pp> >();
test_output<G1<mnt4_pp> >();
test_group<G2<mnt4_pp> >();
test_output<G2<mnt4_pp> >();
test_mul_by_q<G2<mnt4_pp> >();
mnt6_pp::init_public_params();
test_group<G1<mnt6_pp> >();
test_output<G1<mnt6_pp> >();
test_group<G2<mnt6_pp> >();
test_output<G2<mnt6_pp> >();
test_mul_by_q<G2<mnt6_pp> >();
*/
alt_bn128_pp::init_public_params();
test_group<G1<alt_bn128_pp> >();
test_output<G1<alt_bn128_pp> >();

10
src/snark/src/algebra/evaluation_domain/domains/basic_radix2_domain_aux.tcc

@ -74,11 +74,11 @@ void _basic_serial_radix2_FFT(std::vector<FieldT> &a, const FieldT &omega)
template<typename FieldT>
void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omega, const size_t log_cpus)
{
const size_t num_cpus = 1ul<<log_cpus;
const size_t num_cpus = UINT64_C(1)<<log_cpus;
const size_t m = a.size();
const size_t log_m = log2(m);
assert(m == 1ul<<log_m);
assert(m == UINT64_C(1)<<log_m);
if (log_m < log_cpus)
{
@ -90,7 +90,7 @@ void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omeg
std::vector<std::vector<FieldT> > tmp(num_cpus);
for (size_t j = 0; j < num_cpus; ++j)
{
tmp[j].resize(1ul<<(log_m-log_cpus), FieldT::zero());
tmp[j].resize(UINT64_C(1)<<(log_m-log_cpus), FieldT::zero());
}
#ifdef MULTICORE
@ -102,7 +102,7 @@ void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omeg
const FieldT omega_step = omega^(j<<(log_m - log_cpus));
FieldT elt = FieldT::one();
for (size_t i = 0; i < 1ul<<(log_m - log_cpus); ++i)
for (size_t i = 0; i < UINT64_C(1)<<(log_m - log_cpus); ++i)
{
for (size_t s = 0; s < num_cpus; ++s)
{
@ -135,7 +135,7 @@ void _basic_parallel_radix2_FFT_inner(std::vector<FieldT> &a, const FieldT &omeg
#endif
for (size_t i = 0; i < num_cpus; ++i)
{
for (size_t j = 0; j < 1ul<<(log_m - log_cpus); ++j)
for (size_t j = 0; j < UINT64_C(1)<<(log_m - log_cpus); ++j)
{
// now: i = idx >> (log_m - log_cpus) and j = idx % (1u << (log_m - log_cpus)), for idx = ((i<<(log_m-log_cpus))+j) % (1u << log_m)
a[(j<<log_cpus) + i] = tmp[i][j];

48
src/snark/src/algebra/evaluation_domain/domains/extended_radix2_domain.hpp

@ -0,0 +1,48 @@
/** @file
*****************************************************************************
Declaration of interfaces for the "extended radix-2" evaluation domain.
Roughly, the domain has size m = 2^{k+1} and consists of
"the m-th roots of unity" union "a coset of these roots".
*****************************************************************************
* @author This file is part of libsnark, developed by SCIPR Lab
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#ifndef EXTENDED_RADIX2_DOMAIN_HPP_
#define EXTENDED_RADIX2_DOMAIN_HPP_
#include "algebra/evaluation_domain/evaluation_domain.hpp"
namespace libsnark {
template<typename FieldT>
class extended_radix2_domain : public evaluation_domain<FieldT> {
public:
size_t small_m;
FieldT omega;
FieldT shift;
extended_radix2_domain(const size_t m);
void FFT(std::vector<FieldT> &a);
void iFFT(std::vector<FieldT> &a);
void cosetFFT(std::vector<FieldT> &a, const FieldT &g);
void icosetFFT(std::vector<FieldT> &a, const FieldT &g);
std::vector<FieldT> lagrange_coeffs(const FieldT &t);
FieldT get_element(const size_t idx);
FieldT compute_Z(const FieldT &t);
void add_poly_Z(const FieldT &coeff, std::vector<FieldT> &H);
void divide_by_Z_on_coset(std::vector<FieldT> &P);
};
} // libsnark
#include "algebra/evaluation_domain/domains/extended_radix2_domain.tcc"
#endif // EXTENDED_RADIX2_DOMAIN_HPP_

180
src/snark/src/algebra/evaluation_domain/domains/extended_radix2_domain.tcc

@ -0,0 +1,180 @@
/** @file
*****************************************************************************
Implementation of interfaces for the "extended radix-2" evaluation domain.
See extended_radix2_domain.hpp .
*****************************************************************************
* @author This file is part of libsnark, developed by SCIPR Lab
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#ifndef EXTENDED_RADIX2_DOMAIN_TCC_
#include "algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp"
namespace libsnark {
template<typename FieldT>
extended_radix2_domain<FieldT>::extended_radix2_domain(const size_t m) : evaluation_domain<FieldT>(m)
{
assert(m > 1);
const size_t logm = log2(m);
assert(logm == FieldT::s + 1);
small_m = m/2;
omega = get_root_of_unity<FieldT>(small_m);
shift = coset_shift<FieldT>();
}
template<typename FieldT>
void extended_radix2_domain<FieldT>::FFT(std::vector<FieldT> &a)
{
assert(a.size() == this->m);
std::vector<FieldT> a0(small_m, FieldT::zero());
std::vector<FieldT> a1(small_m, FieldT::zero());
const FieldT shift_to_small_m = shift^bigint<1>(small_m);
FieldT shift_i = FieldT::one();
for (size_t i = 0; i < small_m; ++i)
{
a0[i] = a[i] + a[small_m + i];
a1[i] = shift_i * (a[i] + shift_to_small_m * a[small_m + i]);
shift_i *= shift;
}
_basic_radix2_FFT(a0, omega);
_basic_radix2_FFT(a1, omega);
for (size_t i = 0; i < small_m; ++i)
{
a[i] = a0[i];
a[i+small_m] = a1[i];
}
}
template<typename FieldT>
void extended_radix2_domain<FieldT>::iFFT(std::vector<FieldT> &a)
{
assert(a.size() == this->m);
// note: this is not in-place
std::vector<FieldT> a0(a.begin(), a.begin() + small_m);
std::vector<FieldT> a1(a.begin() + small_m, a.end());
const FieldT omega_inverse = omega.inverse();
_basic_radix2_FFT(a0, omega_inverse);
_basic_radix2_FFT(a1, omega_inverse);
const FieldT shift_to_small_m = shift^bigint<1>(small_m);
const FieldT sconst = (FieldT(small_m) * (FieldT::one()-shift_to_small_m)).inverse();
const FieldT shift_inverse = shift.inverse();
FieldT shift_inverse_i = FieldT::one();
for (size_t i = 0; i < small_m; ++i)
{
a[i] = sconst * (-shift_to_small_m * a0[i] + shift_inverse_i * a1[i]);
a[i+small_m] = sconst * (a0[i] - shift_inverse_i * a1[i]);
shift_inverse_i *= shift_inverse;
}
}
template<typename FieldT>
void extended_radix2_domain<FieldT>::cosetFFT(std::vector<FieldT> &a, const FieldT &g)
{
_multiply_by_coset(a, g);
FFT(a);
}
template<typename FieldT>
void extended_radix2_domain<FieldT>::icosetFFT(std::vector<FieldT> &a, const FieldT &g)
{
iFFT(a);
_multiply_by_coset(a, g.inverse());
}
template<typename FieldT>
std::vector<FieldT> extended_radix2_domain<FieldT>::lagrange_coeffs(const FieldT &t)
{
const std::vector<FieldT> T0 = _basic_radix2_lagrange_coeffs(small_m, t);
const std::vector<FieldT> T1 = _basic_radix2_lagrange_coeffs(small_m, t * shift.inverse());
std::vector<FieldT> result(this->m, FieldT::zero());
const FieldT t_to_small_m = t ^ bigint<1>(small_m);
const FieldT shift_to_small_m = shift ^ bigint<1>(small_m);
const FieldT one_over_denom = (shift_to_small_m - FieldT::one()).inverse();
const FieldT T0_coeff = (t_to_small_m - shift_to_small_m) * (-one_over_denom);
const FieldT T1_coeff = (t_to_small_m - FieldT::one()) * one_over_denom;
for (size_t i = 0; i < small_m; ++i)
{
result[i] = T0[i] * T0_coeff;
result[i+small_m] = T1[i] * T1_coeff;
}
return result;
}
template<typename FieldT>
FieldT extended_radix2_domain<FieldT>::get_element(const size_t idx)
{
if (idx < small_m)
{
return omega^idx;
}
else
{
return shift*(omega^(idx-small_m));
}
}
template<typename FieldT>
FieldT extended_radix2_domain<FieldT>::compute_Z(const FieldT &t)
{
return ((t^small_m) - FieldT::one()) * ((t^small_m) - (shift^small_m));
}
template<typename FieldT>
void extended_radix2_domain<FieldT>::add_poly_Z(const FieldT &coeff, std::vector<FieldT> &H)
{
assert(H.size() == this->m+1);
const FieldT shift_to_small_m = shift^small_m;
H[this->m] += coeff;
H[small_m] -= coeff * (shift_to_small_m + FieldT::one());
H[0] += coeff * shift_to_small_m;
}
template<typename FieldT>
void extended_radix2_domain<FieldT>::divide_by_Z_on_coset(std::vector<FieldT> &P)
{
const FieldT coset = FieldT::multiplicative_generator;
const FieldT coset_to_small_m = coset^small_m;
const FieldT shift_to_small_m = shift^small_m;
const FieldT Z0 = (coset_to_small_m - FieldT::one()) * (coset_to_small_m - shift_to_small_m);
const FieldT Z1 = (coset_to_small_m*shift_to_small_m - FieldT::one()) * (coset_to_small_m * shift_to_small_m - shift_to_small_m);
const FieldT Z0_inverse = Z0.inverse();
const FieldT Z1_inverse = Z1.inverse();
for (size_t i = 0; i < small_m; ++i)
{
P[i] *= Z0_inverse;
P[i+small_m] *= Z1_inverse;
}
}
} // libsnark
#endif // EXTENDED_RADIX2_DOMAIN_TCC_

50
src/snark/src/algebra/evaluation_domain/domains/step_radix2_domain.hpp

@ -0,0 +1,50 @@
/** @file
*****************************************************************************
Declaration of interfaces for the "step radix-2" evaluation domain.
Roughly, the domain has size m = 2^k + 2^r and consists of
"the 2^k-th roots of unity" union "a coset of 2^r-th roots of unity".
*****************************************************************************
* @author This file is part of libsnark, developed by SCIPR Lab
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#ifndef STEP_RADIX2_DOMAIN_HPP_
#define STEP_RADIX2_DOMAIN_HPP_
#include "algebra/evaluation_domain/evaluation_domain.hpp"
namespace libsnark {
template<typename FieldT>
class step_radix2_domain : public evaluation_domain<FieldT> {
public:
size_t big_m;
size_t small_m;
FieldT omega;
FieldT big_omega;
FieldT small_omega;
step_radix2_domain(const size_t m);
void FFT(std::vector<FieldT> &a);
void iFFT(std::vector<FieldT> &a);
void cosetFFT(std::vector<FieldT> &a, const FieldT &g);
void icosetFFT(std::vector<FieldT> &a, const FieldT &g);
std::vector<FieldT> lagrange_coeffs(const FieldT &t);
FieldT get_element(const size_t idx);
FieldT compute_Z(const FieldT &t);
void add_poly_Z(const FieldT &coeff, std::vector<FieldT> &H);
void divide_by_Z_on_coset(std::vector<FieldT> &P);
};
} // libsnark
#include "algebra/evaluation_domain/domains/step_radix2_domain.tcc"
#endif // STEP_RADIX2_DOMAIN_HPP_

247
src/snark/src/algebra/evaluation_domain/domains/step_radix2_domain.tcc

@ -0,0 +1,247 @@
/** @file
*****************************************************************************
Implementation of interfaces for the "step radix-2" evaluation domain.
See step_radix2_domain.hpp .
*****************************************************************************
* @author This file is part of libsnark, developed by SCIPR Lab
* and contributors (see AUTHORS).
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#ifndef STEP_RADIX2_DOMAIN_TCC_
#include "algebra/evaluation_domain/domains/basic_radix2_domain_aux.hpp"
namespace libsnark {
template<typename FieldT>
step_radix2_domain<FieldT>::step_radix2_domain(const size_t m) : evaluation_domain<FieldT>(m)
{
assert(m > 1);
big_m = UINT64_C(1)<<(log2(m)-1);
small_m = m - big_m;
assert(small_m == UINT64_C(1)<<log2(small_m));
omega = get_root_of_unity<FieldT>(UINT64_C(1)<<log2(m)); // rounded!
big_omega = omega.squared();
small_omega = get_root_of_unity<FieldT>(small_m);
}
template<typename FieldT>
void step_radix2_domain<FieldT>::FFT(std::vector<FieldT> &a)
{
assert(a.size() == this->m);
std::vector<FieldT> c(big_m, FieldT::zero());
std::vector<FieldT> d(big_m, FieldT::zero());
FieldT omega_i = FieldT::one();
for (size_t i = 0; i < big_m; ++i)
{
c[i] = (i < small_m ? a[i] + a[i+big_m] : a[i]);
d[i] = omega_i * (i < small_m ? a[i] - a[i+big_m] : a[i]);
omega_i *= omega;
}
std::vector<FieldT> e(small_m, FieldT::zero());
const size_t compr = UINT64_C(1)<<(log2(big_m) - log2(small_m));
for (size_t i = 0; i < small_m; ++i)
{
for (size_t j = 0; j < compr; ++j)
{
e[i] += d[i + j * small_m];
}
}
_basic_radix2_FFT(c, omega.squared());
_basic_radix2_FFT(e, get_root_of_unity<FieldT>(small_m));
for (size_t i = 0; i < big_m; ++i)
{
a[i] = c[i];
}
for (size_t i = 0; i < small_m; ++i)
{
a[i+big_m] = e[i];
}
}
template<typename FieldT>
void step_radix2_domain<FieldT>::iFFT(std::vector<FieldT> &a)
{
assert(a.size() == this->m);
std::vector<FieldT> U0(a.begin(), a.begin() + big_m);
std::vector<FieldT> U1(a.begin() + big_m, a.end());
_basic_radix2_FFT(U0, omega.squared().inverse());
_basic_radix2_FFT(U1, get_root_of_unity<FieldT>(small_m).inverse());
const FieldT U0_size_inv = FieldT(big_m).inverse();
for (size_t i = 0; i < big_m; ++i)
{
U0[i] *= U0_size_inv;
}
const FieldT U1_size_inv = FieldT(small_m).inverse();
for (size_t i = 0; i < small_m; ++i)
{
U1[i] *= U1_size_inv;
}
std::vector<FieldT> tmp = U0;
FieldT omega_i = FieldT::one();
for (size_t i = 0; i < big_m; ++i)
{
tmp[i] *= omega_i;
omega_i *= omega;
}
// save A_suffix
for (size_t i = small_m; i < big_m; ++i)
{
a[i] = U0[i];
}
const size_t compr = UINT64_C(1)<<(log2(big_m) - log2(small_m));
for (size_t i = 0; i < small_m; ++i)
{
for (size_t j = 1; j < compr; ++j)
{
U1[i] -= tmp[i + j * small_m];
}
}
const FieldT omega_inv = omega.inverse();
FieldT omega_inv_i = FieldT::one();
for (size_t i = 0; i < small_m; ++i)
{
U1[i] *= omega_inv_i;
omega_inv_i *= omega_inv;
}
// compute A_prefix
const FieldT over_two = FieldT(2).inverse();
for (size_t i = 0; i < small_m; ++i)
{
a[i] = (U0[i]+U1[i]) * over_two;
}
// compute B2
for (size_t i = 0; i < small_m; ++i)
{
a[big_m + i] = (U0[i]-U1[i]) * over_two;
}
}
template<typename FieldT>
void step_radix2_domain<FieldT>::cosetFFT(std::vector<FieldT> &a, const FieldT &g)
{
_multiply_by_coset(a, g);
FFT(a);
}
template<typename FieldT>
void step_radix2_domain<FieldT>::icosetFFT(std::vector<FieldT> &a, const FieldT &g)
{
iFFT(a);
_multiply_by_coset(a, g.inverse());
}
template<typename FieldT>
std::vector<FieldT> step_radix2_domain<FieldT>::lagrange_coeffs(const FieldT &t)
{
std::vector<FieldT> inner_big = _basic_radix2_lagrange_coeffs(big_m, t);
std::vector<FieldT> inner_small = _basic_radix2_lagrange_coeffs(small_m, t * omega.inverse());
std::vector<FieldT> result(this->m, FieldT::zero());
const FieldT L0 = (t^small_m)-(omega^small_m);
const FieldT omega_to_small_m = omega^small_m;
const FieldT big_omega_to_small_m = big_omega ^ small_m;
FieldT elt = FieldT::one();
for (size_t i = 0; i < big_m; ++i)
{
result[i] = inner_big[i] * L0 * (elt - omega_to_small_m).inverse();
elt *= big_omega_to_small_m;
}
const FieldT L1 = ((t^big_m)-FieldT::one()) * ((omega^big_m) - FieldT::one()).inverse();
for (size_t i = 0; i < small_m; ++i)
{
result[big_m + i] = L1 * inner_small[i];
}
return result;
}
template<typename FieldT>
FieldT step_radix2_domain<FieldT>::get_element(const size_t idx)
{
if (idx < big_m)
{
return big_omega^idx;
}
else
{
return omega * (small_omega^(idx-big_m));
}
}
template<typename FieldT>
FieldT step_radix2_domain<FieldT>::compute_Z(const FieldT &t)
{
return ((t^big_m) - FieldT::one()) * ((t^small_m) - (omega^small_m));
}
template<typename FieldT>
void step_radix2_domain<FieldT>::add_poly_Z(const FieldT &coeff, std::vector<FieldT> &H)
{
assert(H.size() == this->m+1);
const FieldT omega_to_small_m = omega^small_m;
H[this->m] += coeff;
H[big_m] -= coeff * omega_to_small_m;
H[small_m] -= coeff;
H[0] += coeff * omega_to_small_m;
}
template<typename FieldT>
void step_radix2_domain<FieldT>::divide_by_Z_on_coset(std::vector<FieldT> &P)
{
// (c^{2^k}-1) * (c^{2^r} * w^{2^{r+1}*i) - w^{2^r})
const FieldT coset = FieldT::multiplicative_generator;
const FieldT Z0 = (coset^big_m) - FieldT::one();
const FieldT coset_to_small_m_times_Z0 = (coset^small_m) * Z0;
const FieldT omega_to_small_m_times_Z0 = (omega^small_m) * Z0;
const FieldT omega_to_2small_m = omega^(2*small_m);
FieldT elt = FieldT::one();
for (size_t i = 0; i < big_m; ++i)
{
P[i] *= (coset_to_small_m_times_Z0 * elt - omega_to_small_m_times_Z0).inverse();
elt *= omega_to_2small_m;
}
// (c^{2^k}*w^{2^k}-1) * (c^{2^k} * w^{2^r} - w^{2^r})
const FieldT Z1 = ((((coset*omega)^big_m) - FieldT::one()) * (((coset * omega)^small_m) - (omega^small_m)));
const FieldT Z1_inverse = Z1.inverse();
for (size_t i = 0; i < small_m; ++i)
{
P[big_m + i] *= Z1_inverse;
}
}
} // libsnark
#endif // STEP_RADIX2_DOMAIN_TCC_

12
src/snark/src/algebra/evaluation_domain/evaluation_domain.tcc

@ -22,6 +22,8 @@
#include <cassert>
#include "algebra/fields/field_utils.hpp"
#include "algebra/evaluation_domain/domains/basic_radix2_domain.hpp"
#include "algebra/evaluation_domain/domains/extended_radix2_domain.hpp"
#include "algebra/evaluation_domain/domains/step_radix2_domain.hpp"
namespace libsnark {
@ -41,7 +43,7 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
{
print_indent(); printf("* Selected domain: extended_radix2\n");
}
assert(0);
result.reset(new extended_radix2_domain<FieldT>(min_size));
}
else
{
@ -54,9 +56,9 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
}
else
{
const size_t big = 1ul<<(log2(min_size)-1);
const size_t big = UINT64_C(1)<<(log2(min_size)-1);
const size_t small = min_size - big;
const size_t rounded_small = (1ul<<log2(small));
const size_t rounded_small = (UINT64_C(1)<<log2(small));
if (big == rounded_small)
{
if (log2(big + rounded_small) < FieldT::s+1)
@ -73,7 +75,7 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
{
print_indent(); printf("* Selected domain: extended_radix2\n");
}
assert(0);
result.reset(new extended_radix2_domain<FieldT>(big + rounded_small));
}
}
else
@ -82,7 +84,7 @@ std::shared_ptr<evaluation_domain<FieldT> > get_evaluation_domain(const size_t m
{
print_indent(); printf("* Selected domain: step_radix2\n");
}
assert(0);
result.reset(new step_radix2_domain<FieldT>(big + rounded_small));
}
}

2
src/snark/src/algebra/exponentiation/exponentiation.hpp

@ -22,7 +22,7 @@ template<typename FieldT, mp_size_t m>
FieldT power(const FieldT &base, const bigint<m> &exponent);
template<typename FieldT>
FieldT power(const FieldT &base, const unsigned long exponent);
FieldT power(const FieldT &base, const uint64_t exponent);
} // libsnark

4
src/snark/src/algebra/exponentiation/exponentiation.tcc

@ -25,7 +25,7 @@ FieldT power(const FieldT &base, const bigint<m> &exponent)
bool found_one = false;
for (long i = exponent.max_bits() - 1; i >= 0; --i)
for (int64_t i = exponent.max_bits() - 1; i >= 0; --i)
{
if (found_one)
{
@ -43,7 +43,7 @@ FieldT power(const FieldT &base, const bigint<m> &exponent)
}
template<typename FieldT>
FieldT power(const FieldT &base, const unsigned long exponent)
FieldT power(const FieldT &base, const uint64_t exponent)
{
return power<FieldT>(base, bigint<1>(exponent));
}

4
src/snark/src/algebra/fields/bigint.hpp

@ -33,7 +33,7 @@ public:
mp_limb_t data[n] = {0};
bigint() = default;
bigint(const unsigned long x); /// Initalize from a small integer
bigint(const uint64_t x); /// Initalize from a small integer
bigint(const char* s); /// Initialize from a string containing an integer in decimal notation
bigint(const mpz_t r); /// Initialize from MPZ element
@ -46,7 +46,7 @@ public:
size_t max_bits() const { return n * GMP_NUMB_BITS; }
size_t num_bits() const;
unsigned long as_ulong() const; /* return the last limb of the integer */
uint64_t as_ulong() const; /* return the last limb of the integer */
void to_mpz(mpz_t r) const;
bool test_bit(const std::size_t bitno) const;

13
src/snark/src/algebra/fields/bigint.tcc

@ -9,6 +9,7 @@
#ifndef BIGINT_TCC_
#define BIGINT_TCC_
#include <iostream>
#include <cassert>
#include <climits>
#include <cstring>
@ -17,9 +18,9 @@
namespace libsnark {
template<mp_size_t n>
bigint<n>::bigint(const unsigned long x) /// Initalize from a small integer
bigint<n>::bigint(const uint64_t x) /// Initalize from a small integer
{
static_assert(ULONG_MAX <= GMP_NUMB_MAX, "unsigned long does not fit in a GMP limb");
static_assert(UINT64_MAX <= GMP_NUMB_MAX, "uint64_t does not fit in a GMP limb");
this->data[0] = x;
}
@ -105,7 +106,7 @@ template<mp_size_t n>
size_t bigint<n>::num_bits() const
{
/*
for (long i = max_bits(); i >= 0; --i)
for (int64_t i = max_bits(); i >= 0; --i)
{
if (this->test_bit(i))
{
@ -115,7 +116,7 @@ size_t bigint<n>::num_bits() const
return 0;
*/
for (long i = n-1; i >= 0; --i)
for (int64_t i = n-1; i >= 0; --i)
{
mp_limb_t x = this->data[i];
if (x == 0)
@ -124,14 +125,14 @@ size_t bigint<n>::num_bits() const
}
else
{
return ((i+1) * GMP_NUMB_BITS) - __builtin_clzl(x);
return (((i+1) * GMP_NUMB_BITS) - __builtin_clzl(x)) / 2;
}
}
return 0;
}
template<mp_size_t n>
unsigned long bigint<n>::as_ulong() const
uint64_t bigint<n>::as_ulong() const
{
return this->data[0];
}

8
src/snark/src/algebra/fields/field_utils.hpp

@ -16,13 +16,13 @@ namespace libsnark {
// returns root of unity of order n (for n a power of 2), if one exists
template<typename FieldT>
FieldT get_root_of_unity(const size_t n);
FieldT get_root_of_unity(const unsigned long long n);
template<typename FieldT>
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<size_t> &v, const size_t w);
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<unsigned long long> &v, const unsigned long long w);
template<typename FieldT>
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const size_t chunk_bits);
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const unsigned long long chunk_bits);
template<typename FieldT>
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v);
@ -37,7 +37,7 @@ template<typename FieldT>
bit_vector convert_field_element_to_bit_vector(const FieldT &el);
template<typename FieldT>
bit_vector convert_field_element_to_bit_vector(const FieldT &el, const size_t bitcount);
bit_vector convert_field_element_to_bit_vector(const FieldT &el, const unsigned long long bitcount);
template<typename FieldT>
FieldT convert_bit_vector_to_field_element(const bit_vector &v);

32
src/snark/src/algebra/fields/field_utils.tcc

@ -21,14 +21,14 @@ FieldT coset_shift()
}
template<typename FieldT>
FieldT get_root_of_unity(const size_t n)
FieldT get_root_of_unity(const unsigned long long n)
{
const size_t logn = log2(n);
const unsigned long long logn = log2(n);
assert(n == (1u << logn));
assert(logn <= FieldT::s);
FieldT omega = FieldT::root_of_unity;
for (size_t i = FieldT::s; i > logn; --i)
for (unsigned long long i = FieldT::s; i > logn; --i)
{
omega *= omega;
}
@ -37,21 +37,21 @@ FieldT get_root_of_unity(const size_t n)
}
template<typename FieldT>
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<size_t> &v, const size_t w)
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<unsigned long long> &v, const unsigned long long w)
{
const size_t chunk_bits = FieldT::capacity();
const size_t repacked_size = div_ceil(v.size() * w, chunk_bits);
const unsigned long long chunk_bits = FieldT::capacity();
const unsigned long long repacked_size = div_ceil(v.size() * w, chunk_bits);
std::vector<FieldT> result(repacked_size);
for (size_t i = 0; i < repacked_size; ++i)
for (unsigned long long i = 0; i < repacked_size; ++i)
{
bigint<FieldT::num_limbs> b;
for (size_t j = 0; j < chunk_bits; ++j)
for (unsigned long long j = 0; j < chunk_bits; ++j)
{
const size_t word_index = (i * chunk_bits + j) / w;
const size_t pos_in_word = (i * chunk_bits + j) % w;
const size_t word_or_0 = (word_index < v.size() ? v[word_index] : 0);
const size_t bit = (word_or_0 >> pos_in_word) & 1;
const unsigned long long word_index = (i * chunk_bits + j) / w;
const unsigned long long pos_in_word = (i * chunk_bits + j) % w;
const unsigned long long word_or_0 = (word_index < v.size() ? v[word_index] : 0);
const unsigned long long bit = (word_or_0 >> pos_in_word) & 1;
b.data[j / GMP_NUMB_BITS] |= bit << (j % GMP_NUMB_BITS);
}
@ -62,11 +62,11 @@ std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<
}
template<typename FieldT>
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const size_t chunk_bits)
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const unsigned long long chunk_bits)
{
assert(chunk_bits <= FieldT::capacity());
const size_t repacked_size = div_ceil(v.size(), chunk_bits);
const unsigned long long repacked_size = div_ceil(v.size(), chunk_bits);
std::vector<FieldT> result(repacked_size);
for (size_t i = 0; i < repacked_size; ++i)
@ -131,7 +131,7 @@ bit_vector convert_field_element_to_bit_vector(const FieldT &el)
}
template<typename FieldT>
bit_vector convert_field_element_to_bit_vector(const FieldT &el, const size_t bitcount)
bit_vector convert_field_element_to_bit_vector(const FieldT &el, const unsigned long long bitcount)
{
bit_vector result = convert_field_element_to_bit_vector(el);
result.resize(bitcount);
@ -171,7 +171,7 @@ void batch_invert(std::vector<FieldT> &vec)
FieldT acc_inverse = acc.inverse();
for (long i = vec.size()-1; i >= 0; --i)
for (int64_t i = vec.size()-1; i >= 0; --i)
{
const FieldT old_el = vec[i];
vec[i] = acc_inverse * prod[i];

28
src/snark/src/algebra/fields/fp.hpp

@ -44,11 +44,11 @@ public:
static const mp_size_t num_limbs = n;
static const constexpr bigint<n>& mod = modulus;
#ifdef PROFILE_OP_COUNTS
static long long add_cnt;
static long long sub_cnt;
static long long mul_cnt;
static long long sqr_cnt;
static long long inv_cnt;
static int64_t add_cnt;
static int64_t sub_cnt;
static int64_t mul_cnt;
static int64_t sqr_cnt;
static int64_t inv_cnt;
#endif
static size_t num_bits;
static bigint<n> euler; // (modulus-1)/2
@ -67,9 +67,9 @@ public:
Fp_model() {};
Fp_model(const bigint<n> &b);
Fp_model(const long x, const bool is_unsigned=false);
Fp_model(const int64_t x, const bool is_unsigned=false);
void set_ulong(const unsigned long x);
void set_ulong(const uint64_t x);
void mul_reduce(const bigint<n> &other);
@ -82,7 +82,7 @@ public:
/* Return the last limb of the standard representation of the
field element. E.g. on 64-bit architectures Fp(123).as_ulong()
and Fp(2^64+123).as_ulong() would both return 123. */
unsigned long as_ulong() const;
uint64_t as_ulong() const;
bool operator==(const Fp_model& other) const;
bool operator!=(const Fp_model& other) const;
@ -93,7 +93,7 @@ public:
Fp_model& operator+=(const Fp_model& other);
Fp_model& operator-=(const Fp_model& other);
Fp_model& operator*=(const Fp_model& other);
Fp_model& operator^=(const unsigned long pow);
Fp_model& operator^=(const uint64_t pow);
template<mp_size_t m>
Fp_model& operator^=(const bigint<m> &pow);
@ -107,12 +107,12 @@ public:
Fp_model inverse() const;
Fp_model sqrt() const; // HAS TO BE A SQUARE (else does not terminate)
Fp_model operator^(const unsigned long pow) const;
Fp_model operator^(const unsigned long long pow) const;
template<mp_size_t m>
Fp_model operator^(const bigint<m> &pow) const;
static size_t size_in_bits() { return num_bits; }
static size_t capacity() { return num_bits - 1; }
static unsigned long long size_in_bits() { return num_bits; }
static unsigned long long capacity() { return num_bits - 1; }
static bigint<n> field_char() { return modulus; }
static Fp_model<n, modulus> zero();
@ -141,13 +141,13 @@ long long Fp_model<n, modulus>::inv_cnt = 0;
#endif
template<mp_size_t n, const bigint<n>& modulus>
size_t Fp_model<n, modulus>::num_bits;
unsigned long long Fp_model<n, modulus>::num_bits;
template<mp_size_t n, const bigint<n>& modulus>
bigint<n> Fp_model<n, modulus>::euler;
template<mp_size_t n, const bigint<n>& modulus>
size_t Fp_model<n, modulus>::s;
unsigned long long Fp_model<n, modulus>::s;
template<mp_size_t n, const bigint<n>& modulus>
bigint<n> Fp_model<n, modulus>::t;

22
src/snark/src/algebra/fields/fp.tcc

@ -194,7 +194,7 @@ Fp_model<n,modulus>::Fp_model(const bigint<n> &b)
}
template<mp_size_t n, const bigint<n>& modulus>
Fp_model<n,modulus>::Fp_model(const long x, const bool is_unsigned)
Fp_model<n,modulus>::Fp_model(const int64_t x, const bool is_unsigned)
{
if (is_unsigned || x >= 0)
{
@ -210,7 +210,7 @@ Fp_model<n,modulus>::Fp_model(const long x, const bool is_unsigned)
}
template<mp_size_t n, const bigint<n>& modulus>
void Fp_model<n,modulus>::set_ulong(const unsigned long x)
void Fp_model<n,modulus>::set_ulong(const uint64_t x)
{
this->mont_repr.clear();
this->mont_repr.data[0] = x;
@ -237,7 +237,7 @@ bigint<n> Fp_model<n,modulus>::as_bigint() const
}
template<mp_size_t n, const bigint<n>& modulus>
unsigned long Fp_model<n,modulus>::as_ulong() const
uint64_t Fp_model<n,modulus>::as_ulong() const
{
return this->as_bigint().as_ulong();
}
@ -502,7 +502,7 @@ Fp_model<n,modulus>& Fp_model<n,modulus>::operator*=(const Fp_model<n,modulus>&
}
template<mp_size_t n, const bigint<n>& modulus>
Fp_model<n,modulus>& Fp_model<n,modulus>::operator^=(const unsigned long pow)
Fp_model<n,modulus>& Fp_model<n,modulus>::operator^=(const uint64_t pow)
{
(*this) = power<Fp_model<n, modulus> >(*this, pow);
return (*this);
@ -538,7 +538,7 @@ Fp_model<n,modulus> Fp_model<n,modulus>::operator*(const Fp_model<n,modulus>& ot
}
template<mp_size_t n, const bigint<n>& modulus>
Fp_model<n,modulus> Fp_model<n,modulus>::operator^(const unsigned long pow) const
Fp_model<n,modulus> Fp_model<n,modulus>::operator^(const uint64_t pow) const
{
Fp_model<n, modulus> r(*this);
return (r ^= pow);
@ -684,13 +684,13 @@ Fp_model<n, modulus> Fp_model<n,modulus>::random_element() /// returns random el
r.mont_repr.randomize();
/* clear all bits higher than MSB of modulus */
size_t bitno = GMP_NUMB_BITS * n - 1;
unsigned long long bitno = GMP_NUMB_BITS * n - 1;
while (modulus.test_bit(bitno) == false)
{
const std::size_t part = bitno/GMP_NUMB_BITS;
const std::size_t bit = bitno - (GMP_NUMB_BITS*part);
const unsigned long long part = bitno/GMP_NUMB_BITS;
const unsigned long long bit = bitno - (GMP_NUMB_BITS*part);
r.mont_repr.data[part] &= ~(1ul<<bit);
r.mont_repr.data[part] &= ~(1ull<<bit);
bitno--;
}
@ -710,7 +710,7 @@ Fp_model<n,modulus> Fp_model<n,modulus>::sqrt() const
Fp_model<n,modulus> one = Fp_model<n,modulus>::one();
size_t v = Fp_model<n,modulus>::s;
unsigned long long v = Fp_model<n,modulus>::s;
Fp_model<n,modulus> z = Fp_model<n,modulus>::nqr_to_t;
Fp_model<n,modulus> w = (*this)^Fp_model<n,modulus>::t_minus_1_over_2;
Fp_model<n,modulus> x = (*this) * w;
@ -734,7 +734,7 @@ Fp_model<n,modulus> Fp_model<n,modulus>::sqrt() const
while (b != one)
{
size_t m = 0;
unsigned long long m = 0;
Fp_model<n,modulus> b2m = b;
while (b2m != one)
{

4
src/snark/src/algebra/fields/fp12_2over3over2.hpp

@ -66,7 +66,7 @@ public:
Fp12_2over3over2_model squared_karatsuba() const;
Fp12_2over3over2_model squared_complex() const;
Fp12_2over3over2_model inverse() const;
Fp12_2over3over2_model Frobenius_map(unsigned long power) const;
Fp12_2over3over2_model Frobenius_map(uint64_t power) const;
Fp12_2over3over2_model unitary_inverse() const;
Fp12_2over3over2_model cyclotomic_squared() const;
@ -78,7 +78,7 @@ public:
Fp12_2over3over2_model cyclotomic_exp(const bigint<m> &exponent) const;
static bigint<n> base_field_char() { return modulus; }
static size_t extension_degree() { return 12; }
static unsigned long long extension_degree() { return 12; }
friend std::ostream& operator<< <n, modulus>(std::ostream &out, const Fp12_2over3over2_model<n, modulus> &el);
friend std::istream& operator>> <n, modulus>(std::istream &in, Fp12_2over3over2_model<n, modulus> &el);

10
src/snark/src/algebra/fields/fp12_2over3over2.tcc

@ -156,7 +156,7 @@ Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::inverse() c
}
template<mp_size_t n, const bigint<n>& modulus>
Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::Frobenius_map(unsigned long power) const
Fp12_2over3over2_model<n,modulus> Fp12_2over3over2_model<n,modulus>::Frobenius_map(uint64_t power) const
{
return Fp12_2over3over2_model<n,modulus>(c0.Frobenius_map(power),
Frobenius_coeffs_c1[power % 12] * c1.Frobenius_map(power));
@ -339,16 +339,16 @@ Fp12_2over3over2_model<n, modulus> Fp12_2over3over2_model<n,modulus>::cyclotomic
Fp12_2over3over2_model<n,modulus> res = Fp12_2over3over2_model<n,modulus>::one();
bool found_one = false;
for (long i = m-1; i >= 0; --i)
for (int64_t i = m-1; i >= 0; --i)
{
for (long j = GMP_NUMB_BITS - 1; j >= 0; --j)
for (int64_t j = GMP_NUMB_BITS - 1; j >= 0; --j)
{
if (found_one)
{
res = res.cyclotomic_squared();
}
if (exponent.data[i] & (1ul<<j))
if (exponent.data[i] & (UINT64_C(1)<<j))
{
found_one = true;
res = res * (*this);
@ -390,7 +390,7 @@ std::istream& operator>>(std::istream& in, std::vector<Fp12_2over3over2_model<n,
{
v.clear();
size_t s;
unsigned long long s;
in >> s;
char b;

8
src/snark/src/algebra/fields/fp2.hpp

@ -37,7 +37,7 @@ public:
typedef Fp_model<n, modulus> my_Fp;
static bigint<2*n> euler; // (modulus^2-1)/2
static size_t s; // modulus^2 = 2^s * t + 1
static unsigned long long s; // modulus^2 = 2^s * t + 1
static bigint<2*n> t; // with t odd
static bigint<2*n> t_minus_1_over_2; // (t-1)/2
static my_Fp non_residue; // X^4-non_residue irreducible over Fp; used for constructing Fp2 = Fp[X] / (X^2 - non_residue)
@ -66,7 +66,7 @@ public:
Fp2_model operator-() const;
Fp2_model squared() const; // default is squared_complex
Fp2_model inverse() const;
Fp2_model Frobenius_map(unsigned long power) const;
Fp2_model Frobenius_map(uint64_t power) const;
Fp2_model sqrt() const; // HAS TO BE A SQUARE (else does not terminate)
Fp2_model squared_karatsuba() const;
Fp2_model squared_complex() const;
@ -74,7 +74,7 @@ public:
template<mp_size_t m>
Fp2_model operator^(const bigint<m> &other) const;
static size_t size_in_bits() { return 2*my_Fp::size_in_bits(); }
static unsigned long long size_in_bits() { return 2*my_Fp::size_in_bits(); }
static bigint<n> base_field_char() { return modulus; }
friend std::ostream& operator<< <n, modulus>(std::ostream &out, const Fp2_model<n, modulus> &el);
@ -94,7 +94,7 @@ template<mp_size_t n, const bigint<n>& modulus>
bigint<2*n> Fp2_model<n, modulus>::euler;
template<mp_size_t n, const bigint<n>& modulus>
size_t Fp2_model<n, modulus>::s;
unsigned long long Fp2_model<n, modulus>::s;
template<mp_size_t n, const bigint<n>& modulus>
bigint<2*n> Fp2_model<n, modulus>::t;

8
src/snark/src/algebra/fields/fp2.tcc

@ -136,7 +136,7 @@ Fp2_model<n,modulus> Fp2_model<n,modulus>::inverse() const
}
template<mp_size_t n, const bigint<n>& modulus>
Fp2_model<n,modulus> Fp2_model<n,modulus>::Frobenius_map(unsigned long power) const
Fp2_model<n,modulus> Fp2_model<n,modulus>::Frobenius_map(uint64_t power) const
{
return Fp2_model<n,modulus>(c0,
Frobenius_coeffs_c1[power % 2] * c1);
@ -151,7 +151,7 @@ Fp2_model<n,modulus> Fp2_model<n,modulus>::sqrt() const
Fp2_model<n,modulus> one = Fp2_model<n,modulus>::one();
size_t v = Fp2_model<n,modulus>::s;
unsigned long long v = Fp2_model<n,modulus>::s;
Fp2_model<n,modulus> z = Fp2_model<n,modulus>::nqr_to_t;
Fp2_model<n,modulus> w = (*this)^Fp2_model<n,modulus>::t_minus_1_over_2;
Fp2_model<n,modulus> x = (*this) * w;
@ -175,7 +175,7 @@ Fp2_model<n,modulus> Fp2_model<n,modulus>::sqrt() const
while (b != one)
{
size_t m = 0;
unsigned long long m = 0;
Fp2_model<n,modulus> b2m = b;
while (b2m != one)
{
@ -239,7 +239,7 @@ std::istream& operator>>(std::istream& in, std::vector<Fp2_model<n, modulus> > &
{
v.clear();
size_t s;
unsigned long long s;
in >> s;
char b;

6
src/snark/src/algebra/fields/fp3.hpp

@ -37,7 +37,7 @@ public:
typedef Fp_model<n, modulus> my_Fp;
static bigint<3*n> euler; // (modulus^3-1)/2
static size_t s; // modulus^3 = 2^s * t + 1
static unsigned long long s; // modulus^3 = 2^s * t + 1
static bigint<3*n> t; // with t odd
static bigint<3*n> t_minus_1_over_2; // (t-1)/2
static my_Fp non_residue; // X^6-non_residue irreducible over Fp; used for constructing Fp3 = Fp[X] / (X^3 - non_residue)
@ -73,7 +73,7 @@ public:
template<mp_size_t m>
Fp3_model operator^(const bigint<m> &other) const;
static size_t size_in_bits() { return 3*my_Fp::size_in_bits(); }
static unsigned long long size_in_bits() { return 3*my_Fp::size_in_bits(); }
static bigint<n> base_field_char() { return modulus; }
friend std::ostream& operator<< <n, modulus>(std::ostream &out, const Fp3_model<n, modulus> &el);
@ -93,7 +93,7 @@ template<mp_size_t n, const bigint<n>& modulus>
bigint<3*n> Fp3_model<n, modulus>::euler;
template<mp_size_t n, const bigint<n>& modulus>
size_t Fp3_model<n, modulus>::s;
unsigned long long Fp3_model<n, modulus>::s;
template<mp_size_t n, const bigint<n>& modulus>
bigint<3*n> Fp3_model<n, modulus>::t;

6
src/snark/src/algebra/fields/fp3.tcc

@ -149,7 +149,7 @@ Fp3_model<n,modulus> Fp3_model<n,modulus>::sqrt() const
{
Fp3_model<n,modulus> one = Fp3_model<n,modulus>::one();
size_t v = Fp3_model<n,modulus>::s;
unsigned long long v = Fp3_model<n,modulus>::s;
Fp3_model<n,modulus> z = Fp3_model<n,modulus>::nqr_to_t;
Fp3_model<n,modulus> w = (*this)^Fp3_model<n,modulus>::t_minus_1_over_2;
Fp3_model<n,modulus> x = (*this) * w;
@ -173,7 +173,7 @@ Fp3_model<n,modulus> Fp3_model<n,modulus>::sqrt() const
while (b != one)
{
size_t m = 0;
unsigned long long m = 0;
Fp3_model<n,modulus> b2m = b;
while (b2m != one)
{
@ -237,7 +237,7 @@ std::istream& operator>>(std::istream& in, std::vector<Fp3_model<n, modulus> > &
{
v.clear();
size_t s;
unsigned long long s;
in >> s;
char b;

4
src/snark/src/algebra/fields/fp6_3over2.hpp

@ -63,7 +63,7 @@ public:
Fp6_3over2_model operator-() const;
Fp6_3over2_model squared() const;
Fp6_3over2_model inverse() const;
Fp6_3over2_model Frobenius_map(unsigned long power) const;
Fp6_3over2_model Frobenius_map(uint64_t power) const;
static my_Fp2 mul_by_non_residue(const my_Fp2 &elt);
@ -71,7 +71,7 @@ public:
Fp6_3over2_model operator^(const bigint<m> &other) const;
static bigint<n> base_field_char() { return modulus; }
static size_t extension_degree() { return 6; }
static unsigned long long extension_degree() { return 6; }
friend std::ostream& operator<< <n, modulus>(std::ostream &out, const Fp6_3over2_model<n, modulus> &el);
friend std::istream& operator>> <n, modulus>(std::istream &in, Fp6_3over2_model<n, modulus> &el);

4
src/snark/src/algebra/fields/fp6_3over2.tcc

@ -149,7 +149,7 @@ Fp6_3over2_model<n,modulus> Fp6_3over2_model<n,modulus>::inverse() const
}
template<mp_size_t n, const bigint<n>& modulus>
Fp6_3over2_model<n,modulus> Fp6_3over2_model<n,modulus>::Frobenius_map(unsigned long power) const
Fp6_3over2_model<n,modulus> Fp6_3over2_model<n,modulus>::Frobenius_map(uint64_t power) const
{
return Fp6_3over2_model<n,modulus>(c0.Frobenius_map(power),
Frobenius_coeffs_c1[power % 6] * c1.Frobenius_map(power),
@ -194,7 +194,7 @@ std::istream& operator>>(std::istream& in, std::vector<Fp6_3over2_model<n, modul
{
v.clear();
size_t s;
uint64_t s;
in >> s;
char b;

90
src/snark/src/algebra/fields/tests/test_bigint.cpp

@ -7,13 +7,11 @@
#include "algebra/fields/bigint.hpp"
#include <gtest/gtest.h>
using namespace libsnark;
TEST(algebra, bigint)
void test_bigint()
{
static_assert(ULONG_MAX == 0xFFFFFFFFFFFFFFFFul, "unsigned long not 64-bit");
static_assert(UINT64_MAX == 0xFFFFFFFFFFFFFFFFul, "uint64_t not 64-bit");
static_assert(GMP_NUMB_BITS == 64, "GMP limb not 64-bit");
const char *b1_decimal = "76749407";
@ -22,76 +20,88 @@ TEST(algebra, bigint)
const char *b2_binary = "0000000000000000000000000000010101111101101000000110100001011010"
"1101101010001001000001101000101000100110011001110001111110100010";
bigint<1> b0 = bigint<1>(0ul);
bigint<1> b0 = bigint<1>(UINT64_C(0));
bigint<1> b1 = bigint<1>(b1_decimal);
bigint<2> b2 = bigint<2>(b2_decimal);
EXPECT_EQ(b0.as_ulong(), 0ul);
EXPECT_TRUE(b0.is_zero());
EXPECT_EQ(b1.as_ulong(), 76749407ul);
EXPECT_FALSE(b1.is_zero());
EXPECT_EQ(b2.as_ulong(), 15747124762497195938ul);
EXPECT_FALSE(b2.is_zero());
EXPECT_NE(b0, b1);
EXPECT_FALSE(b0 == b1);
EXPECT_EQ(b2.max_bits(), 128);
EXPECT_EQ(b2.num_bits(), 99);
assert(b0.as_ulong() == UINT64_C(0));
assert(b0.is_zero());
assert(b1.as_ulong() == UINT64_C(76749407));
assert(!(b1.is_zero()));
assert(b2.as_ulong() == UINT64_C(15747124762497195938));
assert(!(b2.is_zero()));
assert(b0 != b1);
assert(!(b0 == b1));
assert(b2.max_bits() == 128);
assert(b2.num_bits() == 99);
for (size_t i = 0; i < 128; i++) {
EXPECT_EQ(b2.test_bit(i), (b2_binary[127-i] == '1'));
assert(b2.test_bit(i) == (b2_binary[127-i] == '1'));
}
bigint<3> b3 = b2 * b1;
EXPECT_EQ(b3, bigint<3>(b3_decimal));
EXPECT_FALSE(b3.is_zero());
assert(b3 == bigint<3>(b3_decimal));
assert(!(b3.is_zero()));
bigint<3> b3a { b3 };
EXPECT_EQ(b3a, bigint<3>(b3_decimal));
EXPECT_EQ(b3a, b3);
EXPECT_FALSE(b3a.is_zero());
assert(b3a == bigint<3>(b3_decimal));
assert(b3a == b3);
assert(!(b3a.is_zero()));
mpz_t m3;
mpz_init(m3);
b3.to_mpz(m3);
bigint<3> b3b { m3 };
EXPECT_EQ(b3b, b3);
assert(b3b == b3);
bigint<2> quotient;
bigint<2> remainder;
bigint<3>::div_qr(quotient, remainder, b3, b2);
EXPECT_LT(quotient.num_bits(), GMP_NUMB_BITS);
EXPECT_EQ(quotient.as_ulong(), b1.as_ulong());
assert(quotient.num_bits() < GMP_NUMB_BITS);
assert(quotient.as_ulong() == b1.as_ulong());
bigint<1> b1inc = bigint<1>("76749408");
bigint<1> b1a = quotient.shorten(b1inc, "test");
EXPECT_EQ(b1a, b1);
EXPECT_TRUE(remainder.is_zero());
assert(b1a == b1);
assert(remainder.is_zero());
remainder.limit(b2, "test");
EXPECT_THROW((void)(quotient.shorten(b1, "test")), std::domain_error);
EXPECT_THROW(remainder.limit(remainder, "test"), std::domain_error);
try {
(void)(quotient.shorten(b1, "test"));
assert(false);
} catch (std::domain_error) {}
try {
remainder.limit(remainder, "test");
assert(false);
} catch (std::domain_error) {}
bigint<1> br = bigint<1>("42");
b3 += br;
EXPECT_NE(b3, b3a);
EXPECT_GT(b3, b3a);
EXPECT_FALSE(b3a > b3);
assert(b3 != b3a);
assert(b3 > b3a);
assert(!(b3a > b3));
bigint<3>::div_qr(quotient, remainder, b3, b2);
EXPECT_LT(quotient.num_bits(), GMP_NUMB_BITS);
EXPECT_EQ(quotient.as_ulong(), b1.as_ulong());
EXPECT_LT(remainder.num_bits(), GMP_NUMB_BITS);
EXPECT_EQ(remainder.as_ulong(), 42);
assert(quotient.num_bits() < GMP_NUMB_BITS);
assert(quotient.as_ulong() == b1.as_ulong());
assert(remainder.num_bits() < GMP_NUMB_BITS);
assert(remainder.as_ulong() == 42);
b3a.clear();
EXPECT_TRUE(b3a.is_zero());
EXPECT_EQ(b3a.num_bits(), 0);
EXPECT_FALSE(b3.is_zero());
assert(b3a.is_zero());
assert(b3a.num_bits() == 0);
assert(!(b3.is_zero()));
bigint<4> bx = bigint<4>().randomize();
bigint<4> by = bigint<4>().randomize();
EXPECT_FALSE(bx == by);
assert(!(bx == by));
// TODO: test serialization
}
int main(void)
{
test_bigint();
return 0;
}

108
src/snark/src/algebra/fields/tests/test_fields.cpp

@ -5,6 +5,9 @@
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#include "common/profiling.hpp"
#include "algebra/curves/edwards/edwards_pp.hpp"
#include "algebra/curves/mnt/mnt4/mnt4_pp.hpp"
#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
#ifdef CURVE_BN128
#include "algebra/curves/bn128/bn128_pp.hpp"
#endif
@ -12,8 +15,6 @@
#include "algebra/fields/fp6_3over2.hpp"
#include "algebra/fields/fp12_2over3over2.hpp"
#include <gtest/gtest.h>
using namespace libsnark;
template<typename FieldT>
@ -28,25 +29,25 @@ void test_field()
FieldT a = FieldT::random_element();
FieldT a_ser;
a_ser = reserialize<FieldT>(a);
EXPECT_EQ(a_ser, a);
assert(a_ser == a);
FieldT b = FieldT::random_element();
FieldT c = FieldT::random_element();
FieldT d = FieldT::random_element();
EXPECT_NE(a, zero);
EXPECT_NE(a, one);
assert(a != zero);
assert(a != one);
EXPECT_EQ(a * a, a.squared());
EXPECT_EQ((a + b).squared(), a.squared() + a*b + b*a + b.squared());
EXPECT_EQ((a + b)*(c + d), a*c + a*d + b*c + b*d);
EXPECT_EQ(a - b, a + (-b));
EXPECT_EQ(a - b, (-b) + a);
assert(a * a == a.squared());
assert((a + b).squared() == a.squared() + a*b + b*a + b.squared());
assert((a + b)*(c + d) == a*c + a*d + b*c + b*d);
assert(a - b == a + (-b));
assert(a - b == (-b) + a);
EXPECT_EQ((a ^ rand1) * (a ^ rand2), (a^randsum));
assert((a ^ rand1) * (a ^ rand2) == (a^randsum));
EXPECT_EQ(a * a.inverse(), one);
EXPECT_EQ((a + b) * c.inverse(), a * c.inverse() + (b.inverse() * c).inverse());
assert(a * a.inverse() == one);
assert((a + b) * c.inverse() == a * c.inverse() + (b.inverse() * c).inverse());
}
@ -57,7 +58,7 @@ void test_sqrt()
{
FieldT a = FieldT::random_element();
FieldT asq = a.squared();
EXPECT_TRUE(asq.sqrt() == a || asq.sqrt() == -a);
assert(asq.sqrt() == a || asq.sqrt() == -a);
}
}
@ -65,21 +66,21 @@ template<typename FieldT>
void test_two_squarings()
{
FieldT a = FieldT::random_element();
EXPECT_EQ(a.squared(), a * a);
EXPECT_EQ(a.squared(), a.squared_complex());
EXPECT_EQ(a.squared(), a.squared_karatsuba());
assert(a.squared() == a * a);
assert(a.squared() == a.squared_complex());
assert(a.squared() == a.squared_karatsuba());
}
template<typename FieldT>
void test_Frobenius()
{
FieldT a = FieldT::random_element();
EXPECT_EQ(a.Frobenius_map(0), a);
assert(a.Frobenius_map(0) == a);
FieldT a_q = a ^ FieldT::base_field_char();
for (size_t power = 1; power < 10; ++power)
{
const FieldT a_qi = a.Frobenius_map(power);
EXPECT_EQ(a_qi, a_q);
assert(a_qi == a_q);
a_q = a_q ^ FieldT::base_field_char();
}
@ -88,10 +89,49 @@ void test_Frobenius()
template<typename FieldT>
void test_unitary_inverse()
{
EXPECT_EQ(FieldT::extension_degree() % 2, 0);
assert(FieldT::extension_degree() % 2 == 0);
FieldT a = FieldT::random_element();
FieldT aqcubed_minus1 = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse();
EXPECT_EQ(aqcubed_minus1.inverse(), aqcubed_minus1.unitary_inverse());
assert(aqcubed_minus1.inverse() == aqcubed_minus1.unitary_inverse());
}
template<typename FieldT>
void test_cyclotomic_squaring();
template<>
void test_cyclotomic_squaring<Fqk<edwards_pp> >()
{
typedef Fqk<edwards_pp> FieldT;
assert(FieldT::extension_degree() % 2 == 0);
FieldT a = FieldT::random_element();
FieldT a_unitary = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse();
// beta = a^((q^(k/2)-1)*(q+1))
FieldT beta = a_unitary.Frobenius_map(1) * a_unitary;
assert(beta.cyclotomic_squared() == beta.squared());
}
template<>
void test_cyclotomic_squaring<Fqk<mnt4_pp> >()
{
typedef Fqk<mnt4_pp> FieldT;
assert(FieldT::extension_degree() % 2 == 0);
FieldT a = FieldT::random_element();
FieldT a_unitary = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse();
// beta = a^(q^(k/2)-1)
FieldT beta = a_unitary;
assert(beta.cyclotomic_squared() == beta.squared());
}
template<>
void test_cyclotomic_squaring<Fqk<mnt6_pp> >()
{
typedef Fqk<mnt6_pp> FieldT;
assert(FieldT::extension_degree() % 2 == 0);
FieldT a = FieldT::random_element();
FieldT a_unitary = a.Frobenius_map(FieldT::extension_degree()/2) * a.inverse();
// beta = a^((q^(k/2)-1)*(q+1))
FieldT beta = a_unitary.Frobenius_map(1) * a_unitary;
assert(beta.cyclotomic_squared() == beta.squared());
}
template<typename ppT>
@ -157,16 +197,16 @@ void test_Fp4_tom_cook()
c2 = - (FieldT(5)*(FieldT(4).inverse()))* v0 + (FieldT(2)*(FieldT(3).inverse()))*(v1 + v2) - FieldT(24).inverse()*(v3 + v4) + FieldT(4)*v6 + beta*v6;
c3 = FieldT(12).inverse() * (FieldT(5)*v0 - FieldT(7)*v1) - FieldT(24).inverse()*(v2 - FieldT(7)*v3 + v4 + v5) + FieldT(15)*v6;
EXPECT_EQ(res, correct_res);
assert(res == correct_res);
// {v0, v3, v4, v5}
const FieldT u = (FieldT::one() - beta).inverse();
EXPECT_EQ(v0, u * c0 + beta * u * c2 - beta * u * FieldT(2).inverse() * v1 - beta * u * FieldT(2).inverse() * v2 + beta * v6);
EXPECT_EQ(v3, - FieldT(15) * u * c0 - FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 - FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v1 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v2
assert(v0 == u * c0 + beta * u * c2 - beta * u * FieldT(2).inverse() * v1 - beta * u * FieldT(2).inverse() * v2 + beta * v6);
assert(v3 == - FieldT(15) * u * c0 - FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 - FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v1 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v2
- FieldT(3) * (-FieldT(16) + beta) * v6);
EXPECT_EQ(v4, - FieldT(15) * u * c0 + FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 + FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v2 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v1
assert(v4 == - FieldT(15) * u * c0 + FieldT(30) * u * c1 - FieldT(3) * (FieldT(4) + beta) * u * c2 + FieldT(6) * (FieldT(4) + beta) * u * c3 + (FieldT(24) - FieldT(3) * beta * FieldT(2).inverse()) * u * v2 + (-FieldT(8) + beta * FieldT(2).inverse()) * u * v1
- FieldT(3) * (-FieldT(16) + beta) * v6);
EXPECT_EQ(v5, - FieldT(80) * u * c0 - FieldT(240) * u * c1 - FieldT(8) * (FieldT(9) + beta) * u * c2 - FieldT(24) * (FieldT(9) + beta) * u * c3 - FieldT(2) * (-FieldT(81) + beta) * u * v1 + (-FieldT(81) + beta) * u * v2
assert(v5 == - FieldT(80) * u * c0 - FieldT(240) * u * c1 - FieldT(8) * (FieldT(9) + beta) * u * c2 - FieldT(24) * (FieldT(9) + beta) * u * c3 - FieldT(2) * (-FieldT(81) + beta) * u * v1 + (-FieldT(81) + beta) * u * v2
- FieldT(8) * (-FieldT(81) + beta) * v6);
// c0 + beta c2 - (beta v1)/2 - (beta v2)/ 2 - (-1 + beta) beta v6,
@ -176,8 +216,22 @@ void test_Fp4_tom_cook()
}
}
TEST(algebra, fields)
int main(void)
{
edwards_pp::init_public_params();
test_all_fields<edwards_pp>();
test_cyclotomic_squaring<Fqk<edwards_pp> >();
mnt4_pp::init_public_params();
test_all_fields<mnt4_pp>();
test_Fp4_tom_cook<mnt4_Fq4>();
test_two_squarings<Fqe<mnt4_pp> >();
test_cyclotomic_squaring<Fqk<mnt4_pp> >();
mnt6_pp::init_public_params();
test_all_fields<mnt6_pp>();
test_cyclotomic_squaring<Fqk<mnt6_pp> >();
alt_bn128_pp::init_public_params();
test_field<alt_bn128_Fq6>();
test_Frobenius<alt_bn128_Fq6>();

1
src/snark/src/algebra/scalar_multiplication/kc_multiexp.tcc

@ -8,6 +8,7 @@
#ifndef KC_MULTIEXP_TCC_
#define KC_MULTIEXP_TCC_
namespace libsnark {
template<typename T1, typename T2, mp_size_t n>

16
src/snark/src/algebra/scalar_multiplication/multiexp.tcc

@ -40,7 +40,7 @@ public:
#if defined(__x86_64__) && defined(USE_ASM)
if (n == 3)
{
long res;
int64_t res;
__asm__
("// check for overflow \n\t"
"mov $0, %[res] \n\t"
@ -58,7 +58,7 @@ public:
}
else if (n == 4)
{
long res;
int64_t res;
__asm__
("// check for overflow \n\t"
"mov $0, %[res] \n\t"
@ -77,7 +77,7 @@ public:
}
else if (n == 5)
{
long res;
int64_t res;
__asm__
("// check for overflow \n\t"
"mov $0, %[res] \n\t"
@ -190,7 +190,7 @@ T multi_exp_inner(typename std::vector<T>::const_iterator vec_start,
if (vec_len != odd_vec_len)
{
g.emplace_back(T::zero());
opt_q.emplace_back(ordered_exponent<n>(odd_vec_len - 1, bigint<n>(0ul)));
opt_q.emplace_back(ordered_exponent<n>(odd_vec_len - 1, bigint<n>(UINT64_C(0))));
}
assert(g.size() % 2 == 1);
assert(opt_q.size() == g.size());
@ -214,7 +214,7 @@ T multi_exp_inner(typename std::vector<T>::const_iterator vec_start,
const size_t bbits = b.r.num_bits();
const size_t limit = (abits-bbits >= 20 ? 20 : abits-bbits);
if (bbits < 1ul<<limit)
if (bbits < UINT64_C(1)<<limit)
{
/*
In this case, exponentiating to the power of a is cheaper than
@ -389,7 +389,7 @@ size_t get_exp_window_size(const size_t num_scalars)
#endif
}
size_t window = 1;
for (long i = T::fixed_base_exp_window_table.size()-1; i >= 0; --i)
for (int64_t i = T::fixed_base_exp_window_table.size()-1; i >= 0; --i)
{
#ifdef DEBUG
if (!inhibit_profiling_info)
@ -420,9 +420,9 @@ window_table<T> get_window_table(const size_t scalar_size,
const size_t window,
const T &g)
{
const size_t in_window = 1ul<<window;
const size_t in_window = UINT64_C(1)<<window;
const size_t outerc = (scalar_size+window-1)/window;
const size_t last_in_window = 1ul<<(scalar_size - (outerc-1)*window);
const size_t last_in_window = UINT64_C(1)<<(scalar_size - (outerc-1)*window);
#ifdef DEBUG
if (!inhibit_profiling_info)
{

2
src/snark/src/algebra/scalar_multiplication/wnaf.hpp

@ -18,7 +18,7 @@ namespace libsnark {
* Find the wNAF representation of the given scalar relative to the given window size.
*/
template<mp_size_t n>
std::vector<long> find_wnaf(const size_t window_size, const bigint<n> &scalar);
std::vector<int64_t> find_wnaf(const size_t window_size, const bigint<n> &scalar);
/**
* In additive notation, use wNAF exponentiation (with the given window size) to compute scalar * base.

18
src/snark/src/algebra/scalar_multiplication/wnaf.tcc

@ -17,15 +17,15 @@
namespace libsnark {
template<mp_size_t n>
std::vector<long> find_wnaf(const size_t window_size, const bigint<n> &scalar)
std::vector<int64_t> find_wnaf(const size_t window_size, const bigint<n> &scalar)
{
const size_t length = scalar.max_bits(); // upper bound
std::vector<long> res(length+1);
std::vector<int64_t> res(length+1);
bigint<n> c = scalar;
long j = 0;
int64_t j = 0;
while (!c.is_zero())
{
long u;
int64_t u;
if ((c.data[0] & 1) == 1)
{
u = c.data[0] % (1u << (window_size+1));
@ -59,11 +59,11 @@ std::vector<long> find_wnaf(const size_t window_size, const bigint<n> &scalar)
template<typename T, mp_size_t n>
T fixed_window_wnaf_exp(const size_t window_size, const T &base, const bigint<n> &scalar)
{
std::vector<long> naf = find_wnaf(window_size, scalar);
std::vector<T> table(1ul<<(window_size-1));
std::vector<int64_t> naf = find_wnaf(window_size, scalar);
std::vector<T> table(UINT64_C(1)<<(window_size-1));
T tmp = base;
T dbl = base.dbl();
for (size_t i = 0; i < 1ul<<(window_size-1); ++i)
for (size_t i = 0; i < UINT64_C(1)<<(window_size-1); ++i)
{
table[i] = tmp;
tmp = tmp + dbl;
@ -71,7 +71,7 @@ T fixed_window_wnaf_exp(const size_t window_size, const T &base, const bigint<n>
T res = T::zero();
bool found_nonzero = false;
for (long i = naf.size()-1; i >= 0; --i)
for (int64_t i = naf.size()-1; i >= 0; --i)
{
if (found_nonzero)
{
@ -99,7 +99,7 @@ template<typename T, mp_size_t n>
T opt_window_wnaf_exp(const T &base, const bigint<n> &scalar, const size_t scalar_bits)
{
size_t best = 0;
for (long i = T::wnaf_window_table.size() - 1; i >= 0; --i)
for (int64_t i = T::wnaf_window_table.size() - 1; i >= 0; --i)
{
if (scalar_bits >= T::wnaf_window_table[i])
{

8
src/snark/src/common/assert_except.hpp

@ -3,10 +3,10 @@
#include <exception>
inline void assert_except(bool condition) {
if (!condition) {
throw std::runtime_error("Assertion failed.");
}
inline void assert_except (bool condition) {
if (! condition) {
throw std :: runtime_error ("Assertion failed.");
}
}
#endif

18
src/snark/src/common/data_structures/merkle_tree.tcc

@ -66,14 +66,14 @@ merkle_tree<HashT>::merkle_tree(const size_t depth,
assert(log2(contents_as_vector.size()) <= depth);
for (size_t address = 0; address < contents_as_vector.size(); ++address)
{
const size_t idx = address + (1ul<<depth) - 1;
const size_t idx = address + (UINT64_C(1)<<depth) - 1;
values[idx] = contents_as_vector[address];
hashes[idx] = contents_as_vector[address];
hashes[idx].resize(digest_size);
}
size_t idx_begin = (1ul<<depth) - 1;
size_t idx_end = contents_as_vector.size() + ((1ul<<depth) - 1);
size_t idx_begin = (UINT64_C(1)<<depth) - 1;
size_t idx_end = contents_as_vector.size() + ((UINT64_C(1)<<depth) - 1);
for (int layer = depth; layer > 0; --layer)
{
@ -100,13 +100,13 @@ merkle_tree<HashT>::merkle_tree(const size_t depth,
if (!contents.empty())
{
assert(contents.rbegin()->first < 1ul<<depth);
assert(contents.rbegin()->first < UINT64_C(1)<<depth);
for (auto it = contents.begin(); it != contents.end(); ++it)
{
const size_t address = it->first;
const bit_vector value = it->second;
const size_t idx = address + (1ul<<depth) - 1;
const size_t idx = address + (UINT64_C(1)<<depth) - 1;
values[address] = value;
hashes[idx] = value;
@ -167,7 +167,7 @@ void merkle_tree<HashT>::set_value(const size_t address,
const bit_vector &value)
{
assert(log2(address) <= depth);
size_t idx = address + (1ul<<depth) - 1;
size_t idx = address + (UINT64_C(1)<<depth) - 1;
assert(value.size() == value_size);
values[address] = value;
@ -201,7 +201,7 @@ typename HashT::merkle_authentication_path_type merkle_tree<HashT>::get_path(con
{
typename HashT::merkle_authentication_path_type result(depth);
assert(log2(address) <= depth);
size_t idx = address + (1ul<<depth) - 1;
size_t idx = address + (UINT64_C(1)<<depth) - 1;
for (size_t layer = depth; layer > 0; --layer)
{
@ -209,7 +209,7 @@ typename HashT::merkle_authentication_path_type merkle_tree<HashT>::get_path(con
auto it = hashes.find(sibling_idx);
if (layer == depth)
{
auto it2 = values.find(sibling_idx - ((1ul<<depth) - 1));
auto it2 = values.find(sibling_idx - ((UINT64_C(1)<<depth) - 1));
result[layer-1] = (it2 == values.end() ? bit_vector(value_size, false) : it2->second);
result[layer-1].resize(digest_size);
}
@ -227,7 +227,7 @@ typename HashT::merkle_authentication_path_type merkle_tree<HashT>::get_path(con
template<typename HashT>
void merkle_tree<HashT>::dump() const
{
for (size_t i = 0; i < 1ul<<depth; ++i)
for (size_t i = 0; i < UINT64_C(1)<<depth; ++i)
{
auto it = values.find(i);
printf("[%zu] -> ", i);

14
src/snark/src/common/data_structures/sparse_vector.hpp

@ -32,9 +32,9 @@ std::istream& operator>>(std::istream &in, sparse_vector<T> &v);
template<typename T>
struct sparse_vector {
std::vector<size_t> indices;
std::vector<unsigned long long> indices;
std::vector<T> values;
size_t domain_size_ = 0;
unsigned long long domain_size_ = 0;
sparse_vector() = default;
sparse_vector(const sparse_vector<T> &other) = default;
@ -44,7 +44,7 @@ struct sparse_vector {
sparse_vector<T>& operator=(const sparse_vector<T> &other) = default;
sparse_vector<T>& operator=(sparse_vector<T> &&other) = default;
T operator[](const size_t idx) const;
T operator[](const unsigned long long idx) const;
bool operator==(const sparse_vector<T> &other) const;
bool operator==(const std::vector<T> &other) const;
@ -52,15 +52,15 @@ struct sparse_vector {
bool is_valid() const;
bool empty() const;
size_t domain_size() const; // return domain_size_
size_t size() const; // return the number of indices (representing the number of non-zero entries)
size_t size_in_bits() const; // return the number bits needed to store the sparse vector
unsigned long long domain_size() const; // return domain_size_
unsigned long long size() const; // return the number of indices (representing the number of non-zero entries)
unsigned long long size_in_bits() const; // return the number bits needed to store the sparse vector
/* return a pair consisting of the accumulated value and the sparse vector of non-accumuated values */
template<typename FieldT>
std::pair<T, sparse_vector<T> > accumulate(const typename std::vector<FieldT>::const_iterator &it_begin,
const typename std::vector<FieldT>::const_iterator &it_end,
const size_t offset) const;
const unsigned long long offset) const;
friend std::ostream& operator<< <T>(std::ostream &out, const sparse_vector<T> &v);
friend std::istream& operator>> <T>(std::istream &in, sparse_vector<T> &v);

36
src/snark/src/common/data_structures/sparse_vector.tcc

@ -29,7 +29,7 @@ sparse_vector<T>::sparse_vector(std::vector<T> &&v) :
}
template<typename T>
T sparse_vector<T>::operator[](const size_t idx) const
T sparse_vector<T>::operator[](const unsigned long long idx) const
{
auto it = std::lower_bound(indices.begin(), indices.end(), idx);
return (it != indices.end() && *it == idx) ? values[it - indices.begin()] : T();
@ -43,7 +43,7 @@ bool sparse_vector<T>::operator==(const sparse_vector<T> &other) const
return false;
}
size_t this_pos = 0, other_pos = 0;
unsigned long long this_pos = 0, other_pos = 0;
while (this_pos < this->indices.size() && other_pos < other.indices.size())
{
if (this->indices[this_pos] == other.indices[other_pos])
@ -103,8 +103,8 @@ bool sparse_vector<T>::operator==(const std::vector<T> &other) const
return false;
}
size_t j = 0;
for (size_t i = 0; i < other.size(); ++i)
unsigned long long j = 0;
for (unsigned long long i = 0; i < other.size(); ++i)
{
if (this->indices[j] == i)
{
@ -134,7 +134,7 @@ bool sparse_vector<T>::is_valid() const
return false;
}
for (size_t i = 0; i + 1 < indices.size(); ++i)
for (unsigned long long i = 0; i + 1 < indices.size(); ++i)
{
if (indices[i] >= indices[i+1])
{
@ -157,42 +157,42 @@ bool sparse_vector<T>::empty() const
}
template<typename T>
size_t sparse_vector<T>::domain_size() const
unsigned long long sparse_vector<T>::domain_size() const
{
return domain_size_;
}
template<typename T>
size_t sparse_vector<T>::size() const
unsigned long long sparse_vector<T>::size() const
{
return indices.size();
}
template<typename T>
size_t sparse_vector<T>::size_in_bits() const
unsigned long long sparse_vector<T>::size_in_bits() const
{
return indices.size() * (sizeof(size_t) * 8 + T::size_in_bits());
return indices.size() * (sizeof(unsigned long long) * 8 + T::size_in_bits());
}
template<typename T>
template<typename FieldT>
std::pair<T, sparse_vector<T> > sparse_vector<T>::accumulate(const typename std::vector<FieldT>::const_iterator &it_begin,
const typename std::vector<FieldT>::const_iterator &it_end,
const size_t offset) const
const unsigned long long offset) const
{
// TODO: does not really belong here.
const size_t chunks = 1;
const unsigned long long chunks = 1;
const bool use_multiexp = true;
T accumulated_value = T::zero();
sparse_vector<T> resulting_vector;
resulting_vector.domain_size_ = domain_size_;
const size_t range_len = it_end - it_begin;
const unsigned long long range_len = it_end - it_begin;
bool in_block = false;
size_t first_pos = -1, last_pos = -1; // g++ -flto emits unitialized warning, even though in_block guards for such cases.
unsigned long long first_pos = -1, last_pos = -1; // g++ -flto emits unitialized warning, even though in_block guards for such cases.
for (size_t i = 0; i < indices.size(); ++i)
for (unsigned long long i = 0; i < indices.size(); ++i)
{
const bool matching_pos = (offset <= indices[i] && indices[i] < offset + range_len);
// printf("i = %zu, pos[i] = %zu, offset = %zu, w_size = %zu\n", i, indices[i], offset, w_size);
@ -265,7 +265,7 @@ std::ostream& operator<<(std::ostream& out, const sparse_vector<T> &v)
{
out << v.domain_size_ << "\n";
out << v.indices.size() << "\n";
for (const size_t& i : v.indices)
for (const unsigned long long& i : v.indices)
{
out << i << "\n";
}
@ -285,11 +285,11 @@ std::istream& operator>>(std::istream& in, sparse_vector<T> &v)
in >> v.domain_size_;
consume_newline(in);
size_t s;
unsigned long long s;
in >> s;
consume_newline(in);
v.indices.resize(s);
for (size_t i = 0; i < s; ++i)
for (unsigned long long i = 0; i < s; ++i)
{
in >> v.indices[i];
consume_newline(in);
@ -300,7 +300,7 @@ std::istream& operator>>(std::istream& in, sparse_vector<T> &v)
consume_newline(in);
v.values.reserve(s);
for (size_t i = 0; i < s; ++i)
for (unsigned long long i = 0; i < s; ++i)
{
T t;
in >> t;

67
src/snark/src/common/profiling.cpp

@ -26,6 +26,13 @@
#include <proc/readproc.h>
#endif
#ifdef __MACH__ // required to build on MacOS
#include <time.h>
#include <sys/time.h>
#include <mach/clock.h>
#include <mach/mach.h>
#endif
namespace libsnark {
long long get_nsec_time()
@ -38,10 +45,20 @@ long long get_nsec_time()
long long get_nsec_cpu_time()
{
::timespec ts;
#ifdef __MACH__
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts.tv_sec = mts.tv_sec;
ts.tv_nsec = mts.tv_nsec;
#else
if ( ::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts) )
throw ::std::runtime_error("clock_gettime(CLOCK_PROCESS_CPUTIME_ID) failed");
// If we expected this to work, don't silently ignore failures, because that would hide the problem and incur an unnecessarily system-call overhead. So if we ever observe this exception, we should probably add a suitable #ifdef .
//TODO: clock_gettime(CLOCK_PROCESS_CPUTIME_ID) is not supported by native Windows. What about Cygwin? Should we #ifdef on CLOCK_PROCESS_CPUTIME_ID or on __linux__?
#endif
return ts.tv_sec * 1000000000ll + ts.tv_nsec;
}
@ -57,20 +74,20 @@ void start_profiling()
}
std::map<std::string, size_t> invocation_counts;
std::map<std::string, long long> enter_times;
std::map<std::string, long long> last_times;
std::map<std::string, long long> cumulative_times;
std::map<std::string, int64_t> enter_times;
std::map<std::string, int64_t> last_times;
std::map<std::string, int64_t> cumulative_times;
//TODO: Instead of analogous maps for time and cpu_time, use a single struct-valued map
std::map<std::string, long long> enter_cpu_times;
std::map<std::string, long long> last_cpu_times;
std::map<std::pair<std::string, std::string>, long long> op_counts;
std::map<std::pair<std::string, std::string>, long long> cumulative_op_counts; // ((msg, data_point), value)
std::map<std::string, int64_t> enter_cpu_times;
std::map<std::string, int64_t> last_cpu_times;
std::map<std::pair<std::string, std::string>, int64_t> op_counts;
std::map<std::pair<std::string, std::string>, int64_t> cumulative_op_counts; // ((msg, data_point), value)
// TODO: Convert op_counts and cumulative_op_counts from pair to structs
size_t indentation = 0;
std::vector<std::string> block_names;
std::list<std::pair<std::string, long long*> > op_data_points = {
std::list<std::pair<std::string, int64_t*> > op_data_points = {
#ifdef PROFILE_OP_COUNTS
std::make_pair("Fradd", &Fr<default_ec_pp>::add_cnt),
std::make_pair("Frsub", &Fr<default_ec_pp>::sub_cnt),
@ -98,7 +115,7 @@ void clear_profiling_counters()
cumulative_times.clear();
}
void print_cumulative_time_entry(const std::string &key, const long long factor)
void print_cumulative_time_entry(const std::string &key, const int64_t factor)
{
const double total_ms = (cumulative_times.at(key) * 1e-6);
const size_t cnt = invocation_counts.at(key);
@ -106,7 +123,7 @@ void print_cumulative_time_entry(const std::string &key, const long long factor)
printf(" %-45s: %12.5fms = %lld * %0.5fms (%zu invocations, %0.5fms = %lld * %0.5fms per invocation)\n", key.c_str(), total_ms, factor, total_ms/factor, cnt, avg_ms, factor, avg_ms/factor);
}
void print_cumulative_times(const long long factor)
void print_cumulative_times(const int64_t factor)
{
printf("Dumping times:\n");
for (auto& kv : cumulative_times)
@ -155,7 +172,7 @@ void print_op_profiling(const std::string &msg)
printf("(opcounts) = (");
bool first = true;
for (std::pair<std::string, long long*> p : op_data_points)
for (std::pair<std::string, int64_t*> p : op_data_points)
{
if (!first)
{
@ -171,14 +188,14 @@ void print_op_profiling(const std::string &msg)
#endif
}
static void print_times_from_last_and_start(long long now, long long last,
long long cpu_now, long long cpu_last)
static void print_times_from_last_and_start(int64_t now, int64_t last,
int64_t cpu_now, int64_t cpu_last)
{
long long time_from_start = now - start_time;
long long time_from_last = now - last;
int64_t time_from_start = now - start_time;
int64_t time_from_last = now - last;
long long cpu_time_from_start = cpu_now - start_cpu_time;
long long cpu_time_from_last = cpu_now - cpu_last;
int64_t cpu_time_from_start = cpu_now - start_cpu_time;
int64_t cpu_time_from_last = cpu_now - cpu_last;
if (time_from_last != 0) {
double parallelism_from_last = 1.0 * cpu_time_from_last / time_from_last;
@ -199,8 +216,8 @@ void print_time(const char* msg)
return;
}
long long now = get_nsec_time();
long long cpu_now = get_nsec_cpu_time();
int64_t now = get_nsec_time();
int64_t cpu_now = get_nsec_cpu_time();
printf("%-35s\t", msg);
print_times_from_last_and_start(now, last_time, cpu_now, last_cpu_time);
@ -231,7 +248,7 @@ void print_indent()
void op_profiling_enter(const std::string &msg)
{
for (std::pair<std::string, long long*> p : op_data_points)
for (std::pair<std::string, int64_t*> p : op_data_points)
{
op_counts[std::make_pair(msg, p.first)] = *(p.second);
}
@ -245,9 +262,9 @@ void enter_block(const std::string &msg, const bool indent)
}
block_names.emplace_back(msg);
long long t = get_nsec_time();
int64_t t = get_nsec_time();
enter_times[msg] = t;
long long cpu_t = get_nsec_cpu_time();
int64_t cpu_t = get_nsec_cpu_time();
enter_cpu_times[msg] = cpu_t;
if (inhibit_profiling_info)
@ -288,15 +305,15 @@ void leave_block(const std::string &msg, const bool indent)
++invocation_counts[msg];
long long t = get_nsec_time();
int64_t t = get_nsec_time();
last_times[msg] = (t - enter_times[msg]);
cumulative_times[msg] += (t - enter_times[msg]);
long long cpu_t = get_nsec_cpu_time();
int64_t cpu_t = get_nsec_cpu_time();
last_cpu_times[msg] = (cpu_t - enter_cpu_times[msg]);
#ifdef PROFILE_OP_COUNTS
for (std::pair<std::string, long long*> p : op_data_points)
for (std::pair<std::string, int64_t*> p : op_data_points)
{
cumulative_op_counts[std::make_pair(msg, p.first)] += *(p.second)-op_counts[std::make_pair(msg, p.first)];
}

10
src/snark/src/common/profiling.hpp

@ -22,7 +22,7 @@
namespace libsnark {
void start_profiling();
long long get_nsec_time();
int64_t get_nsec_time();
void print_time(const char* msg);
void print_header(const char* msg);
@ -31,13 +31,13 @@ void print_indent();
extern bool inhibit_profiling_info;
extern bool inhibit_profiling_counters;
extern std::map<std::string, size_t> invocation_counts;
extern std::map<std::string, long long> last_times;
extern std::map<std::string, long long> cumulative_times;
extern std::map<std::string, int64_t> last_times;
extern std::map<std::string, int64_t> cumulative_times;
void clear_profiling_counters();
void print_cumulative_time_entry(const std::string &key, const long long factor=1);
void print_cumulative_times(const long long factor=1);
void print_cumulative_time_entry(const std::string &key, const int64_t factor=1);
void print_cumulative_times(const int64_t factor=1);
void print_cumulative_op_counts(const bool only_fq=false);
void enter_block(const std::string &msg, const bool indent=true);

28
src/snark/src/common/utils.cpp

@ -15,11 +15,11 @@
namespace libsnark {
size_t log2(size_t n)
unsigned long long log2(unsigned long long n)
/* returns ceil(log2(n)), so 1ul<<log2(n) is the smallest power of 2,
that is not less than n. */
{
size_t r = ((n & (n-1)) == 0 ? 0 : 1); // add 1 if n is not power of 2
unsigned long long r = ((n & (n-1)) == 0 ? 0 : 1); // add 1 if n is not power of 2
while (n > 1)
{
@ -30,10 +30,10 @@ size_t log2(size_t n)
return r;
}
size_t bitreverse(size_t n, const size_t l)
unsigned long long bitreverse(unsigned long long n, const unsigned long long l)
{
size_t r = 0;
for (size_t k = 0; k < l; ++k)
unsigned long long r = 0;
for (unsigned long long k = 0; k < l; ++k)
{
r = (r << 1) | (n & 1);
n >>= 1;
@ -41,20 +41,20 @@ size_t bitreverse(size_t n, const size_t l)
return r;
}
bit_vector int_list_to_bits(const std::initializer_list<unsigned long> &l, const size_t wordsize)
bit_vector int_list_to_bits(const std::initializer_list<uint64_t> &l, const size_t wordsize)
{
bit_vector res(wordsize*l.size());
for (size_t i = 0; i < l.size(); ++i)
for (uint64_t i = 0; i < l.size(); ++i)
{
for (size_t j = 0; j < wordsize; ++j)
for (uint64_t j = 0; j < wordsize; ++j)
{
res[i*wordsize + j] = (*(l.begin()+i) & (1ul<<(wordsize-1-j)));
res[i*wordsize + j] = (*(l.begin()+i) & (UINT64_C(1)<<(wordsize-1-j)));
}
}
return res;
}
long long div_ceil(long long x, long long y)
int64_t div_ceil(int64_t x, int64_t y)
{
return (x + (y-1)) / y;
}
@ -68,7 +68,7 @@ bool is_little_endian()
std::string FORMAT(const std::string &prefix, const char* format, ...)
{
const static size_t MAX_FMT = 256;
const static unsigned long long MAX_FMT = 256;
char buf[MAX_FMT];
va_list args;
va_start(args, format);
@ -81,7 +81,7 @@ std::string FORMAT(const std::string &prefix, const char* format, ...)
void serialize_bit_vector(std::ostream &out, const bit_vector &v)
{
out << v.size() << "\n";
for (size_t i = 0; i < v.size(); ++i)
for (unsigned long long i = 0; i < v.size(); ++i)
{
out << v[i] << "\n";
}
@ -89,10 +89,10 @@ void serialize_bit_vector(std::ostream &out, const bit_vector &v)
void deserialize_bit_vector(std::istream &in, bit_vector &v)
{
size_t size;
unsigned long long size;
in >> size;
v.resize(size);
for (size_t i = 0; i < size; ++i)
for (unsigned long long i = 0; i < size; ++i)
{
bool b;
in >> b;

10
src/snark/src/common/utils.hpp

@ -21,12 +21,12 @@ namespace libsnark {
typedef std::vector<bool> bit_vector;
/// returns ceil(log2(n)), so 1ul<<log2(n) is the smallest power of 2, that is not less than n
size_t log2(size_t n);
unsigned long long log2(unsigned long long n);
inline size_t exp2(size_t k) { return 1ul << k; }
inline unsigned long long exp2(unsigned long long k) { return 1ull << k; }
size_t bitreverse(size_t n, const size_t l);
bit_vector int_list_to_bits(const std::initializer_list<unsigned long> &l, const size_t wordsize);
unsigned long long bitreverse(unsigned long long n, const unsigned long long l);
bit_vector int_list_to_bits(const std::initializer_list<unsigned long long> &l, const unsigned long long wordsize);
long long div_ceil(long long x, long long y);
bool is_little_endian();
@ -47,7 +47,7 @@ void serialize_bit_vector(std::ostream &out, const bit_vector &v);
void deserialize_bit_vector(std::istream &in, bit_vector &v);
template<typename T>
size_t size_in_bits(const std::vector<T> &v);
unsigned long long size_in_bits(const std::vector<T> &v);
#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))

40
src/snark/src/gadgetlib1/gadgets/basic_gadgets.tcc

@ -275,11 +275,11 @@ void test_disjunction_gadget(const size_t n)
disjunction_gadget<FieldT> d(pb, inputs, output, "d");
d.generate_r1cs_constraints();
for (size_t w = 0; w < 1ul<<n; ++w)
for (size_t w = 0; w < UINT64_C(1)<<n; ++w)
{
for (size_t j = 0; j < n; ++j)
{
pb.val(inputs[j]) = FieldT((w & (1ul<<j)) ? 1 : 0);
pb.val(inputs[j]) = FieldT((w & (UINT64_C(1)<<j)) ? 1 : 0);
}
d.generate_r1cs_witness();
@ -366,11 +366,11 @@ void test_conjunction_gadget(const size_t n)
conjunction_gadget<FieldT> c(pb, inputs, output, "c");
c.generate_r1cs_constraints();
for (size_t w = 0; w < 1ul<<n; ++w)
for (size_t w = 0; w < UINT64_C(1)<<n; ++w)
{
for (size_t j = 0; j < n; ++j)
{
pb.val(inputs[j]) = (w & (1ul<<j)) ? FieldT::one() : FieldT::zero();
pb.val(inputs[j]) = (w & (UINT64_C(1)<<j)) ? FieldT::one() : FieldT::zero();
}
c.generate_r1cs_witness();
@ -378,13 +378,13 @@ void test_conjunction_gadget(const size_t n)
#ifdef DEBUG
printf("positive test for %zu\n", w);
#endif
assert(pb.val(output) == (w == (1ul<<n) - 1 ? FieldT::one() : FieldT::zero()));
assert(pb.val(output) == (w == (UINT64_C(1)<<n) - 1 ? FieldT::one() : FieldT::zero()));
assert(pb.is_satisfied());
#ifdef DEBUG
printf("negative test for %zu\n", w);
#endif
pb.val(output) = (w == (1ul<<n) - 1 ? FieldT::zero() : FieldT::one());
pb.val(output) = (w == (UINT64_C(1)<<n) - 1 ? FieldT::zero() : FieldT::one());
assert(!pb.is_satisfied());
}
@ -454,9 +454,9 @@ void test_comparison_gadget(const size_t n)
comparison_gadget<FieldT> cmp(pb, n, A, B, less, less_or_eq, "cmp");
cmp.generate_r1cs_constraints();
for (size_t a = 0; a < 1ul<<n; ++a)
for (size_t a = 0; a < UINT64_C(1)<<n; ++a)
{
for (size_t b = 0; b < 1ul<<n; ++b)
for (size_t b = 0; b < UINT64_C(1)<<n; ++b)
{
pb.val(A) = FieldT(a);
pb.val(B) = FieldT(b);
@ -523,16 +523,16 @@ void test_inner_product_gadget(const size_t n)
inner_product_gadget<FieldT> g(pb, A, B, result, "g");
g.generate_r1cs_constraints();
for (size_t i = 0; i < 1ul<<n; ++i)
for (size_t i = 0; i < UINT64_C(1)<<n; ++i)
{
for (size_t j = 0; j < 1ul<<n; ++j)
for (size_t j = 0; j < UINT64_C(1)<<n; ++j)
{
size_t correct = 0;
for (size_t k = 0; k < n; ++k)
{
pb.val(A[k]) = (i & (1ul<<k) ? FieldT::one() : FieldT::zero());
pb.val(B[k]) = (j & (1ul<<k) ? FieldT::one() : FieldT::zero());
correct += ((i & (1ul<<k)) && (j & (1ul<<k)) ? 1 : 0);
pb.val(A[k]) = (i & (UINT64_C(1)<<k) ? FieldT::one() : FieldT::zero());
pb.val(B[k]) = (j & (UINT64_C(1)<<k) ? FieldT::one() : FieldT::zero());
correct += ((i & (UINT64_C(1)<<k)) && (j & (UINT64_C(1)<<k)) ? 1 : 0);
}
g.generate_r1cs_witness();
@ -587,7 +587,7 @@ void loose_multiplexing_gadget<FieldT>::generate_r1cs_witness()
{
/* assumes that idx can be fit in ulong; true for our purposes for now */
const bigint<FieldT::num_limbs> valint = this->pb.val(index).as_bigint();
unsigned long idx = valint.as_ulong();
uint64_t idx = valint.as_ulong();
const bigint<FieldT::num_limbs> arrsize(arr.size());
if (idx >= arr.size() || mpn_cmp(valint.data, arrsize.data, FieldT::num_limbs) >= 0)
@ -619,7 +619,7 @@ void test_loose_multiplexing_gadget(const size_t n)
protoboard<FieldT> pb;
pb_variable_array<FieldT> arr;
arr.allocate(pb, 1ul<<n, "arr");
arr.allocate(pb, UINT64_C(1)<<n, "arr");
pb_variable<FieldT> index, result, success_flag;
index.allocate(pb, "index");
result.allocate(pb, "result");
@ -628,20 +628,20 @@ void test_loose_multiplexing_gadget(const size_t n)
loose_multiplexing_gadget<FieldT> g(pb, arr, index, result, success_flag, "g");
g.generate_r1cs_constraints();
for (size_t i = 0; i < 1ul<<n; ++i)
for (size_t i = 0; i < UINT64_C(1)<<n; ++i)
{
pb.val(arr[i]) = FieldT((19*i) % (1ul<<n));
pb.val(arr[i]) = FieldT((19*i) % (UINT64_C(1)<<n));
}
for (int idx = -1; idx <= (int)(1ul<<n); ++idx)
for (int idx = -1; idx <= (int)(UINT64_C(1)<<n); ++idx)
{
pb.val(index) = FieldT(idx);
g.generate_r1cs_witness();
if (0 <= idx && idx <= (int)(1ul<<n) - 1)
if (0 <= idx && idx <= (int)(UINT64_C(1)<<n) - 1)
{
printf("demuxing element %d (in bounds)\n", idx);
assert(pb.val(result) == FieldT((19*idx) % (1ul<<n)));
assert(pb.val(result) == FieldT((19*idx) % (UINT64_C(1)<<n)));
assert(pb.val(success_flag) == FieldT::one());
assert(pb.is_satisfied());
pb.val(result) -= FieldT::one();

2
src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_aux.tcc

@ -285,7 +285,7 @@ void majority_gadget<FieldT>::generate_r1cs_witness()
{
for (size_t i = 0; i < 32; ++i)
{
const long v = (this->pb.lc_val(X[i]) + this->pb.lc_val(Y[i]) + this->pb.lc_val(Z[i])).as_ulong();
const int64_t v = (this->pb.lc_val(X[i]) + this->pb.lc_val(Y[i]) + this->pb.lc_val(Z[i])).as_ulong();
this->pb.val(result_bits[i]) = FieldT(v / 2);
}

4
src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_components.hpp

@ -78,7 +78,7 @@ public:
pb_linear_combination_array<FieldT> g;
pb_linear_combination_array<FieldT> h;
pb_variable<FieldT> W;
long K;
int64_t K;
pb_linear_combination_array<FieldT> new_a;
pb_linear_combination_array<FieldT> new_e;
@ -92,7 +92,7 @@ public:
const pb_linear_combination_array<FieldT> &g,
const pb_linear_combination_array<FieldT> &h,
const pb_variable<FieldT> &W,
const long &K,
const int64_t &K,
const pb_linear_combination_array<FieldT> &new_a,
const pb_linear_combination_array<FieldT> &new_e,
const std::string &annotation_prefix);

6
src/snark/src/gadgetlib1/gadgets/hashes/sha256/sha256_components.tcc

@ -16,7 +16,7 @@
namespace libsnark {
const unsigned long SHA256_K[64] = {
const uint64_t SHA256_K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
@ -27,7 +27,7 @@ const unsigned long SHA256_K[64] = {
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
};
const unsigned long SHA256_H[8] = {
const uint64_t SHA256_H[8] = {
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
};
@ -149,7 +149,7 @@ sha256_round_function_gadget<FieldT>::sha256_round_function_gadget(protoboard<Fi
const pb_linear_combination_array<FieldT> &g,
const pb_linear_combination_array<FieldT> &h,
const pb_variable<FieldT> &W,
const long &K,
const int64_t &K,
const pb_linear_combination_array<FieldT> &new_a,
const pb_linear_combination_array<FieldT> &new_e,
const std::string &annotation_prefix) :

6
src/snark/src/gadgetlib1/gadgets/hashes/sha256/tests/test_sha256_gadget.cpp

@ -10,8 +10,6 @@
#include "common/profiling.hpp"
#include "gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp"
#include <gtest/gtest.h>
using namespace libsnark;
template<typename FieldT>
@ -37,10 +35,10 @@ void test_two_to_one()
f.generate_r1cs_witness();
output.generate_r1cs_witness(hash_bv);
EXPECT_TRUE(pb.is_satisfied());
assert(pb.is_satisfied());
}
TEST(gadgetlib1, sha256)
int main(void)
{
start_profiling();
default_ec_pp::init_public_params();

4
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.tcc

@ -41,7 +41,7 @@ void merkle_authentication_path_variable<FieldT, HashT>::generate_r1cs_witness(c
for (size_t i = 0; i < tree_depth; ++i)
{
if (address & (1ul << (tree_depth-1-i)))
if (address & (UINT64_C(1) << (tree_depth-1-i)))
{
left_digests[i].generate_r1cs_witness(path[i]);
}
@ -58,7 +58,7 @@ merkle_authentication_path merkle_authentication_path_variable<FieldT, HashT>::g
merkle_authentication_path result;
for (size_t i = 0; i < tree_depth; ++i)
{
if (address & (1ul << (tree_depth-1-i)))
if (address & (UINT64_C(1) << (tree_depth-1-i)))
{
result.emplace_back(left_digests[i].get_digest());
}

4
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.tcc

@ -144,10 +144,10 @@ void test_merkle_tree_check_read_gadget()
bit_vector address_bits;
size_t address = 0;
for (long level = tree_depth-1; level >= 0; --level)
for (int64_t level = tree_depth-1; level >= 0; --level)
{
const bool computed_is_right = (std::rand() % 2);
address |= (computed_is_right ? 1ul << (tree_depth-1-level) : 0);
address |= (computed_is_right ? UINT64_C(1) << (tree_depth-1-level) : 0);
address_bits.push_back(computed_is_right);
bit_vector other(digest_len);
std::generate(other.begin(), other.end(), [&]() { return std::rand() % 2; });

1
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp

@ -19,6 +19,7 @@
#include "common/data_structures/merkle_tree.hpp"
#include "gadgetlib1/gadget.hpp"
#include "gadgetlib1/gadgets/hashes/crh_gadget.hpp"
#include "gadgetlib1/gadgets/hashes/hash_io.hpp"
#include "gadgetlib1/gadgets/hashes/digest_selector_gadget.hpp"
#include "gadgetlib1/gadgets/merkle_tree/merkle_authentication_path_variable.hpp"

4
src/snark/src/gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.tcc

@ -197,10 +197,10 @@ void test_merkle_tree_check_update_gadget()
bit_vector address_bits;
size_t address = 0;
for (long level = tree_depth-1; level >= 0; --level)
for (int64_t level = tree_depth-1; level >= 0; --level)
{
const bool computed_is_right = (std::rand() % 2);
address |= (computed_is_right ? 1ul << (tree_depth-1-level) : 0);
address |= (computed_is_right ? UINT64_C(1) << (tree_depth-1-level) : 0);
address_bits.push_back(computed_is_right);
bit_vector other(digest_len);
std::generate(other.begin(), other.end(), [&]() { return std::rand() % 2; });

22
src/snark/src/gadgetlib1/gadgets/merkle_tree/tests/test_merkle_tree_gadgets.cpp

@ -5,36 +5,44 @@
* @copyright MIT license (see LICENSE file)
*****************************************************************************/
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
#ifdef CURVE_BN128
#include "algebra/curves/bn128/bn128_pp.hpp"
#endif
#include "algebra/curves/edwards/edwards_pp.hpp"
#include "algebra/curves/mnt/mnt4/mnt4_pp.hpp"
#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
#include "gadgetlib1/gadgets/merkle_tree/merkle_tree_check_read_gadget.hpp"
#include "gadgetlib1/gadgets/merkle_tree/merkle_tree_check_update_gadget.hpp"
#include "gadgetlib1/gadgets/hashes/sha256/sha256_gadget.hpp"
#include <gtest/gtest.h>
using namespace libsnark;
template<typename ppT>
void test_all_merkle_tree_gadgets()
{
typedef Fr<ppT> FieldT;
test_merkle_tree_check_read_gadget<FieldT, CRH_with_bit_out_gadget<FieldT> >();
test_merkle_tree_check_read_gadget<FieldT, sha256_two_to_one_hash_gadget<FieldT> >();
test_merkle_tree_check_update_gadget<FieldT, CRH_with_bit_out_gadget<FieldT> >();
test_merkle_tree_check_update_gadget<FieldT, sha256_two_to_one_hash_gadget<FieldT> >();
}
TEST(gadgetlib1, merkle_tree)
int main(void)
{
start_profiling();
alt_bn128_pp::init_public_params();
test_all_merkle_tree_gadgets<alt_bn128_pp>();
#ifdef CURVE_BN128 // BN128 has fancy dependencies so it may be disabled
bn128_pp::init_public_params();
test_all_merkle_tree_gadgets<bn128_pp>();
#endif
edwards_pp::init_public_params();
test_all_merkle_tree_gadgets<edwards_pp>();
mnt4_pp::init_public_params();
test_all_merkle_tree_gadgets<mnt4_pp>();
mnt6_pp::init_public_params();
test_all_merkle_tree_gadgets<mnt6_pp>();
}

4
src/snark/src/gadgetlib1/pb_variable.hpp

@ -59,7 +59,7 @@ public:
void fill_with_field_elements(protoboard<FieldT> &pb, const std::vector<FieldT>& vals) const;
void fill_with_bits(protoboard<FieldT> &pb, const bit_vector& bits) const;
void fill_with_bits_of_ulong(protoboard<FieldT> &pb, const unsigned long i) const;
void fill_with_bits_of_ulong(protoboard<FieldT> &pb, const uint64_t i) const;
void fill_with_bits_of_field_element(protoboard<FieldT> &pb, const FieldT &r) const;
std::vector<FieldT> get_vals(const protoboard<FieldT> &pb) const;
@ -120,7 +120,7 @@ public:
void fill_with_field_elements(protoboard<FieldT> &pb, const std::vector<FieldT>& vals) const;
void fill_with_bits(protoboard<FieldT> &pb, const bit_vector& bits) const;
void fill_with_bits_of_ulong(protoboard<FieldT> &pb, const unsigned long i) const;
void fill_with_bits_of_ulong(protoboard<FieldT> &pb, const uint64_t i) const;
void fill_with_bits_of_field_element(protoboard<FieldT> &pb, const FieldT &r) const;
std::vector<FieldT> get_vals(const protoboard<FieldT> &pb) const;

4
src/snark/src/gadgetlib1/pb_variable.tcc

@ -65,7 +65,7 @@ void pb_variable_array<FieldT>::fill_with_bits_of_field_element(protoboard<Field
}
template<typename FieldT>
void pb_variable_array<FieldT>::fill_with_bits_of_ulong(protoboard<FieldT> &pb, const unsigned long i) const
void pb_variable_array<FieldT>::fill_with_bits_of_ulong(protoboard<FieldT> &pb, const uint64_t i) const
{
this->fill_with_bits_of_field_element(pb, FieldT(i, true));
}
@ -232,7 +232,7 @@ void pb_linear_combination_array<FieldT>::fill_with_bits_of_field_element(protob
}
template<typename FieldT>
void pb_linear_combination_array<FieldT>::fill_with_bits_of_ulong(protoboard<FieldT> &pb, const unsigned long i) const
void pb_linear_combination_array<FieldT>::fill_with_bits_of_ulong(protoboard<FieldT> &pb, const uint64_t i) const
{
this->fill_with_bits_of_field_element(pb, FieldT(i));
}

31
src/snark/src/relations/arithmetic_programs/qap/tests/test_qap.cpp

@ -10,15 +10,13 @@
#include <cstring>
#include <vector>
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
#include "algebra/curves/mnt/mnt6/mnt6_pp.hpp"
#include "algebra/fields/field_utils.hpp"
#include "common/profiling.hpp"
#include "common/utils.hpp"
#include "reductions/r1cs_to_qap/r1cs_to_qap.hpp"
#include "relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp"
#include <gtest/gtest.h>
using namespace libsnark;
template<typename FieldT>
@ -30,7 +28,7 @@ void test_qap(const size_t qap_degree, const size_t num_inputs, const bool binar
See the transformation from R1CS to QAP for why this is the case.
So we need that qap_degree >= num_inputs + 1.
*/
ASSERT_LE(num_inputs + 1, qap_degree);
assert(num_inputs + 1 <= qap_degree);
enter_block("Call to test_qap");
const size_t num_constraints = qap_degree - num_inputs - 1;
@ -53,7 +51,7 @@ void test_qap(const size_t qap_degree, const size_t num_inputs, const bool binar
leave_block("Generate constraint system and assignment");
enter_block("Check satisfiability of constraint system");
EXPECT_TRUE(example.constraint_system.is_satisfied(example.primary_input, example.auxiliary_input));
assert(example.constraint_system.is_satisfied(example.primary_input, example.auxiliary_input));
leave_block("Check satisfiability of constraint system");
const FieldT t = FieldT::random_element(),
@ -74,31 +72,44 @@ void test_qap(const size_t qap_degree, const size_t num_inputs, const bool binar
leave_block("Compute QAP witness");
enter_block("Check satisfiability of QAP instance 1");
EXPECT_TRUE(qap_inst_1.is_satisfied(qap_wit));
assert(qap_inst_1.is_satisfied(qap_wit));
leave_block("Check satisfiability of QAP instance 1");
enter_block("Check satisfiability of QAP instance 2");
EXPECT_TRUE(qap_inst_2.is_satisfied(qap_wit));
assert(qap_inst_2.is_satisfied(qap_wit));
leave_block("Check satisfiability of QAP instance 2");
leave_block("Call to test_qap");
}
TEST(relations, qap)
int main()
{
start_profiling();
mnt6_pp::init_public_params();
const size_t num_inputs = 10;
const size_t basic_domain_size = UINT64_C(1)<<mnt6_Fr::s;
const size_t step_domain_size = (UINT64_C(1)<<10) + (UINT64_C(1)<<8);
const size_t extended_domain_size = UINT64_C(1)<<(mnt6_Fr::s+1);
const size_t extended_domain_size_special = extended_domain_size-1;
enter_block("Test QAP with binary input");
test_qap<Fr<alt_bn128_pp> >(1ul << 21, num_inputs, true);
test_qap<Fr<mnt6_pp> >(basic_domain_size, num_inputs, true);
test_qap<Fr<mnt6_pp> >(step_domain_size, num_inputs, true);
test_qap<Fr<mnt6_pp> >(extended_domain_size, num_inputs, true);
test_qap<Fr<mnt6_pp> >(extended_domain_size_special, num_inputs, true);
leave_block("Test QAP with binary input");
enter_block("Test QAP with field input");
test_qap<Fr<alt_bn128_pp> >(1ul << 21, num_inputs, false);
test_qap<Fr<mnt6_pp> >(basic_domain_size, num_inputs, false);
test_qap<Fr<mnt6_pp> >(step_domain_size, num_inputs, false);
test_qap<Fr<mnt6_pp> >(extended_domain_size, num_inputs, false);
test_qap<Fr<mnt6_pp> >(extended_domain_size_special, num_inputs, false);
leave_block("Test QAP with field input");
}

2
src/snark/src/relations/variable.hpp

@ -26,7 +26,7 @@ namespace libsnark {
* Mnemonic typedefs.
*/
typedef size_t var_index_t;
typedef long integer_coeff_t;
typedef int64_t integer_coeff_t;
/**
* Forward declaration.

2
src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.tcc

@ -83,7 +83,7 @@ bool run_r1cs_ppzksnark(const r1cs_example<Fr<ppT> > &example,
}
print_header("R1CS ppzkSNARK Prover");
r1cs_ppzksnark_proof<ppT> proof = r1cs_ppzksnark_prover<ppT>(keypair.pk, example.primary_input, example.auxiliary_input, example.constraint_system);
r1cs_ppzksnark_proof<ppT> proof = r1cs_ppzksnark_prover<ppT>(keypair.pk, example.primary_input, example.auxiliary_input);
printf("\n"); print_indent(); print_mem("after prover");
if (test_serialization)

14
src/snark/src/zk_proof_systems/ppzksnark/r1cs_ppzksnark/tests/test_r1cs_ppzksnark.cpp

@ -11,14 +11,14 @@
#include <cassert>
#include <cstdio>
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
#include "zk_proof_systems/ppzksnark/r1cs_ppzksnark/r1cs_ppzksnark_params.hpp"
#include "common/default_types/ec_pp.hpp"
#include "common/default_types/r1cs_ppzksnark_pp.hpp"
#include "common/profiling.hpp"
#include "common/utils.hpp"
#include "relations/constraint_satisfaction_problems/r1cs/examples/r1cs_examples.hpp"
#include "zk_proof_systems/ppzksnark/r1cs_ppzksnark/examples/run_r1cs_ppzksnark.hpp"
#include <gtest/gtest.h>
using namespace libsnark;
template<typename ppT>
@ -29,16 +29,16 @@ void test_r1cs_ppzksnark(size_t num_constraints,
const bool test_serialization = true;
r1cs_example<Fr<ppT> > example = generate_r1cs_example_with_binary_input<Fr<ppT> >(num_constraints, input_size);
example.constraint_system.swap_AB_if_beneficial();
const bool bit = run_r1cs_ppzksnark<ppT>(example, test_serialization);
EXPECT_TRUE(bit);
assert(bit);
print_header("(leave) Test R1CS ppzkSNARK");
}
TEST(zk_proof_systems, r1cs_ppzksnark)
int main()
{
default_r1cs_ppzksnark_pp::init_public_params();
start_profiling();
test_r1cs_ppzksnark<alt_bn128_pp>(1000, 20);
test_r1cs_ppzksnark<default_r1cs_ppzksnark_pp>(1000, 100);
}

Loading…
Cancel
Save