Skip to content

Commit fa4cada

Browse files
authored
Fix bugs in field utils to work for libsnark (#103)
* Fix bugs in field utils to work for libsnark * Add more tests for common and field utils * Update changelog
1 parent c47bd61 commit fa4cada

File tree

6 files changed

+118
-9
lines changed

6 files changed

+118
-9
lines changed

CHANGELOG.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ This update introduces new field and curve API's, and enforces they are used con
1919
- #75 Get rid of warning for unused constant PI, in complex field
2020
- #78 Reduce prints when inhibit_profiling_info is set
2121
- #79 & #87 Use std::size_t for all code, fix bugs introduced by #58
22-
- #94 & #96 Fix bugs that make libff incompatible with libfqfft and libiop
22+
- #94 & #96 Fix bugs that make libff incompatible with
23+
[libfqfft](https://github.com/scipr-lab/libfqfft) and [libiop](https://github.com/scipr-lab/libiop)
24+
- #103 Fix bugs that make libff incompatible with [libsnark](https://github.com/scipr-lab/libsnark)
25+
and add more tests for the field utils
2326

2427
## v0.2.0
2528

libff/algebra/field_utils/field_utils.tcc

+3-3
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ get_root_of_unity(const size_t n)
116116
template<typename FieldT>
117117
std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<size_t> &v, const size_t w)
118118
{
119-
const size_t chunk_bits = FieldT::capacity();
119+
const size_t chunk_bits = FieldT::floor_size_in_bits();
120120
const size_t repacked_size = div_ceil(v.size() * w, chunk_bits);
121121
std::vector<FieldT> result(repacked_size);
122122

@@ -141,7 +141,7 @@ std::vector<FieldT> pack_int_vector_into_field_element_vector(const std::vector<
141141
template<typename FieldT>
142142
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v, const size_t chunk_bits)
143143
{
144-
assert(chunk_bits <= FieldT::capacity());
144+
assert(chunk_bits <= FieldT::floor_size_in_bits());
145145

146146
const size_t repacked_size = div_ceil(v.size(), chunk_bits);
147147
std::vector<FieldT> result(repacked_size);
@@ -162,7 +162,7 @@ std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &
162162
template<typename FieldT>
163163
std::vector<FieldT> pack_bit_vector_into_field_element_vector(const bit_vector &v)
164164
{
165-
return pack_bit_vector_into_field_element_vector<FieldT>(v, FieldT::capacity());
165+
return pack_bit_vector_into_field_element_vector<FieldT>(v, FieldT::floor_size_in_bits());
166166
}
167167

168168
template<typename FieldT>

libff/algebra/field_utils/tests/test_field_utils.cpp

+57
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,16 @@
88
* @copyright MIT license (see LICENSE file)
99
*****************************************************************************/
1010
#include "libff/algebra/field_utils/bigint.hpp"
11+
#include "libff/algebra/field_utils/field_utils.hpp"
1112
#include "libff/algebra/field_utils/algorithms.hpp"
1213
#include "libff/algebra/fields/binary/gf64.hpp"
14+
#include "libff/algebra/curves/edwards/edwards_fields.hpp"
1315
#include <gtest/gtest.h>
1416

1517
using namespace libff;
1618

19+
using std::size_t;
20+
1721
template<typename FieldT>
1822
FieldT power_naive(const FieldT &base, const std::size_t exponent)
1923
{
@@ -98,3 +102,56 @@ TEST(FieldUtilsTest, BigintTest)
98102
x.clear();
99103
EXPECT_EQ(x, zero);
100104
}
105+
106+
TEST(FieldUtilsTest, FieldVectorConversionTest)
107+
{
108+
init_edwards_fields();
109+
110+
// pack_bit_vector_into_field_element_vector
111+
112+
bit_vector vec;
113+
for (size_t i = 0; i < 12 + edwards_Fq::ceil_size_in_bits(); i++)
114+
vec.push_back(0);
115+
vec.push_back(1);
116+
vec.push_back(0);
117+
vec.push_back(1);
118+
119+
std::vector<edwards_Fq> field_vec = pack_bit_vector_into_field_element_vector<edwards_Fq>(vec);
120+
121+
EXPECT_EQ(field_vec.size(), 2);
122+
EXPECT_EQ(field_vec[0], edwards_Fq::zero());
123+
EXPECT_EQ(field_vec[1], edwards_Fq(40960)); // 5 * 2**13
124+
125+
// convert_bit_vector_to_field_element_vector
126+
127+
bit_vector vec2;
128+
vec2.push_back(0);
129+
vec2.push_back(0);
130+
vec2.push_back(1);
131+
vec2.push_back(0);
132+
vec2.push_back(1);
133+
134+
field_vec = convert_bit_vector_to_field_element_vector<edwards_Fq>(vec2);
135+
136+
EXPECT_EQ(field_vec.size(), 5);
137+
EXPECT_EQ(field_vec[0], edwards_Fq::zero());
138+
EXPECT_EQ(field_vec[1], edwards_Fq::zero());
139+
EXPECT_EQ(field_vec[2], edwards_Fq::one());
140+
EXPECT_EQ(field_vec[3], edwards_Fq::zero());
141+
EXPECT_EQ(field_vec[4], edwards_Fq::one());
142+
143+
// convert_field_element_vector_to_bit_vector
144+
145+
std::vector<edwards_Fq> field_vec2;
146+
field_vec2.push_back(edwards_Fq(edwards_Fq(5)));
147+
field_vec2.push_back(edwards_Fq::zero());
148+
149+
bit_vector vec3 = convert_field_element_vector_to_bit_vector(field_vec2);
150+
151+
EXPECT_EQ(vec3.size(), edwards_Fq::ceil_size_in_bits() * 2);
152+
EXPECT_EQ(vec3[0], 1);
153+
EXPECT_EQ(vec3[1], 0);
154+
EXPECT_EQ(vec3[2], 1);
155+
for (size_t i = 3; i < vec3.size(); i++)
156+
EXPECT_EQ(vec3[i], 0);
157+
}

libff/common/tests/test_common.cpp

+48
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include <gtest/gtest.h>
1212

1313
#include "libff/common/utils.hpp"
14+
#include "libff/algebra/fields/binary/gf32.hpp"
15+
#include "libff/algebra/curves/edwards/edwards_pp.hpp"
16+
#include "libff/algebra/curves/mnt/mnt6/mnt6_pp.hpp"
1417

1518
using namespace libff;
1619

@@ -37,3 +40,48 @@ TEST(Log2Test, PowersOfTwo) {
3740
EXPECT_EQ(libff::log2(k+1), i+1);
3841
}
3942
}
43+
44+
template<typename FieldT>
45+
void test_random_element()
46+
{
47+
FieldT x = random_element_non_zero_one<FieldT>();
48+
EXPECT_NE(x, FieldT::zero());
49+
EXPECT_NE(x, FieldT::one());
50+
51+
x = random_element_non_zero<FieldT>();
52+
EXPECT_NE(x, FieldT::zero());
53+
54+
FieldT y = random_element_exclude(x);
55+
EXPECT_NE(x, y);
56+
}
57+
58+
TEST(UtilsTest, RandomElementTest)
59+
{
60+
init_edwards_fields();
61+
test_random_element<edwards_Fq3>();
62+
test_random_element<gf32>();
63+
}
64+
65+
TEST(UtilsTest, CurveVectorSizeTest)
66+
{
67+
init_edwards_params();
68+
init_mnt6_params();
69+
70+
std::vector<edwards_G1> vec;
71+
72+
vec.push_back(edwards_G1::G1_one);
73+
vec.push_back(edwards_G1::G1_zero);
74+
vec.push_back(edwards_G1::G1_one);
75+
76+
EXPECT_EQ(curve_size_in_bits(vec), 552);
77+
78+
std::vector<mnt6_G2> vec2;
79+
80+
vec2.push_back(mnt6_G2::G2_zero);
81+
vec2.push_back(mnt6_G2::G2_one);
82+
vec2.push_back(mnt6_G2::G2_one);
83+
vec2.push_back(mnt6_G2::G2_zero);
84+
vec2.push_back(mnt6_G2::G2_zero);
85+
86+
EXPECT_EQ(curve_size_in_bits(vec2), 4475);
87+
}

libff/common/utils.hpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,9 @@ void UNUSED(Types&&...) {}
6161
void serialize_bit_vector(std::ostream &out, const bit_vector &v);
6262
void deserialize_bit_vector(std::istream &in, bit_vector &v);
6363

64-
template<typename T>
65-
std::size_t ceil_size_in_bits(const std::vector<T> &v);
64+
/** Should not be used for fields, because the field function is named ceil_size_in_bits instead. */
65+
template<typename CurveT>
66+
std::size_t curve_size_in_bits(const std::vector<CurveT> &v);
6667

6768
/* Print a vector in the form { elem0 elem1 elem2 ... }, with a newline at the end
6869
template<typename T>

libff/common/utils.tcc

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ namespace libff {
1313

1414
using std::size_t;
1515

16-
template<typename T>
17-
size_t ceil_size_in_bits(const std::vector<T> &v)
16+
template<typename CurveT>
17+
size_t curve_size_in_bits(const std::vector<CurveT> &v)
1818
{
19-
return v.size() * T::ceil_size_in_bits();
19+
return v.size() * CurveT::size_in_bits();
2020
}
2121

2222
template<typename T>

0 commit comments

Comments
 (0)