From e5cd50ebb9d8e9b5786c68b8ef79cf22b13768b4 Mon Sep 17 00:00:00 2001 From: Duncan Tebbs Date: Fri, 22 May 2020 10:45:54 +0100 Subject: [PATCH] Expose both compressed and uncompressed point serialization. Use generic vector serialization. --- .../algebra/curves/alt_bn128/alt_bn128_g1.cpp | 80 ++++++------ .../algebra/curves/alt_bn128/alt_bn128_g1.hpp | 9 +- .../algebra/curves/alt_bn128/alt_bn128_g2.cpp | 57 +++++++-- .../algebra/curves/alt_bn128/alt_bn128_g2.hpp | 6 +- libff/algebra/curves/bn128/bn128_g1.cpp | 119 +++++++++--------- libff/algebra/curves/bn128/bn128_g1.hpp | 10 +- libff/algebra/curves/bn128/bn128_g2.cpp | 61 ++++++--- libff/algebra/curves/bn128/bn128_g2.hpp | 6 +- libff/algebra/curves/edwards/edwards_g1.cpp | 73 ++++++----- libff/algebra/curves/edwards/edwards_g1.hpp | 9 +- libff/algebra/curves/edwards/edwards_g2.cpp | 52 ++++++-- libff/algebra/curves/edwards/edwards_g2.hpp | 6 +- libff/algebra/curves/mnt/mnt4/mnt4_g1.cpp | 81 ++++++------ libff/algebra/curves/mnt/mnt4/mnt4_g1.hpp | 9 +- libff/algebra/curves/mnt/mnt4/mnt4_g2.cpp | 64 +++++++--- libff/algebra/curves/mnt/mnt4/mnt4_g2.hpp | 6 +- libff/algebra/curves/mnt/mnt6/mnt6_g1.cpp | 96 +++++++------- libff/algebra/curves/mnt/mnt6/mnt6_g1.hpp | 9 +- libff/algebra/curves/mnt/mnt6/mnt6_g2.cpp | 64 ++++++++-- libff/algebra/curves/mnt/mnt6/mnt6_g2.hpp | 6 +- libff/algebra/curves/tests/test_groups.cpp | 10 ++ 21 files changed, 516 insertions(+), 317 deletions(-) diff --git a/libff/algebra/curves/alt_bn128/alt_bn128_g1.cpp b/libff/algebra/curves/alt_bn128/alt_bn128_g1.cpp index 8be6340a..49c84830 100755 --- a/libff/algebra/curves/alt_bn128/alt_bn128_g1.cpp +++ b/libff/algebra/curves/alt_bn128/alt_bn128_g1.cpp @@ -405,31 +405,51 @@ alt_bn128_G1 alt_bn128_G1::random_element() return (scalar_field::random_element().as_bigint()) * G1_one; } -std::ostream& operator<<(std::ostream &out, const alt_bn128_G1 &g) +void alt_bn128_G1::write_uncompressed(std::ostream &out) const { - alt_bn128_G1 copy(g); + alt_bn128_G1 copy(*this); copy.to_affine_coordinates(); out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; -#ifdef NO_PT_COMPRESSION out << copy.X << OUTPUT_SEPARATOR << copy.Y; -#else +} + +void alt_bn128_G1::write_compressed(std::ostream &out) const +{ + alt_bn128_G1 copy(*this); + copy.to_affine_coordinates(); + + out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; /* storing LSB of Y */ out << copy.X << OUTPUT_SEPARATOR << (copy.Y.as_bigint().data[0] & 1); -#endif - - return out; } -std::istream& operator>>(std::istream &in, alt_bn128_G1 &g) +void alt_bn128_G1::read_uncompressed(std::istream &in, alt_bn128_G1 &g) { char is_zero; alt_bn128_Fq tX, tY; -#ifdef NO_PT_COMPRESSION in >> is_zero >> tX >> tY; is_zero -= '0'; -#else + + // using Jacobian coordinates + if (!is_zero) + { + g.X = tX; + g.Y = tY; + g.Z = alt_bn128_Fq::one(); + } + else + { + g = alt_bn128_G1::zero(); + } +} + +void alt_bn128_G1::read_compressed(std::istream &in, alt_bn128_G1 &g) +{ + char is_zero; + alt_bn128_Fq tX, tY; + in.read((char*)&is_zero, 1); // this reads is_zero; is_zero -= '0'; consume_OUTPUT_SEPARATOR(in); @@ -452,7 +472,7 @@ std::istream& operator>>(std::istream &in, alt_bn128_G1 &g) tY = -tY; } } -#endif + // using Jacobian coordinates if (!is_zero) { @@ -464,39 +484,25 @@ std::istream& operator>>(std::istream &in, alt_bn128_G1 &g) { g = alt_bn128_G1::zero(); } - - return in; } -std::ostream& operator<<(std::ostream& out, const std::vector &v) +std::ostream& operator<<(std::ostream &out, const alt_bn128_G1 &g) { - out << v.size() << "\n"; - for (const alt_bn128_G1& t : v) - { - out << t << OUTPUT_NEWLINE; - } - +#ifdef NO_PT_COMPRESSION + g.write_uncompressed(out); +#else + g.write_compressed(out); +#endif return out; } -std::istream& operator>>(std::istream& in, std::vector &v) +std::istream& operator>>(std::istream &in, alt_bn128_G1 &g) { - v.clear(); - - size_t s; - in >> s; - consume_newline(in); - - v.reserve(s); - - for (size_t i = 0; i < s; ++i) - { - alt_bn128_G1 g; - in >> g; - consume_OUTPUT_NEWLINE(in); - v.emplace_back(g); - } - +#ifdef NO_PT_COMPRESSION + alt_bn128_G1::read_uncompressed(in, g); +#else + alt_bn128_G1::read_compressed(in, g); +#endif return in; } diff --git a/libff/algebra/curves/alt_bn128/alt_bn128_g1.hpp b/libff/algebra/curves/alt_bn128/alt_bn128_g1.hpp index 232513ce..aad9be48 100755 --- a/libff/algebra/curves/alt_bn128/alt_bn128_g1.hpp +++ b/libff/algebra/curves/alt_bn128/alt_bn128_g1.hpp @@ -69,8 +69,10 @@ class alt_bn128_G1 { static bigint base_field_char() { return base_field::field_char(); } static bigint order() { return scalar_field::field_char(); } - friend std::ostream& operator<<(std::ostream &out, const alt_bn128_G1 &g); - friend std::istream& operator>>(std::istream &in, alt_bn128_G1 &g); + void write_uncompressed(std::ostream &) const; + void write_compressed(std::ostream &) const; + static void read_uncompressed(std::istream &, alt_bn128_G1 &); + static void read_compressed(std::istream &, alt_bn128_G1 &); static void batch_to_special_all_non_zeros(std::vector &vec); }; @@ -87,8 +89,5 @@ alt_bn128_G1 operator*(const Fp_model &lhs, const alt_bn128_G1 &rhs return scalar_mul(rhs, lhs.as_bigint()); } -std::ostream& operator<<(std::ostream& out, const std::vector &v); -std::istream& operator>>(std::istream& in, std::vector &v); - } // libff #endif // ALT_BN128_G1_HPP_ diff --git a/libff/algebra/curves/alt_bn128/alt_bn128_g2.cpp b/libff/algebra/curves/alt_bn128/alt_bn128_g2.cpp index 333c3421..242644e6 100755 --- a/libff/algebra/curves/alt_bn128/alt_bn128_g2.cpp +++ b/libff/algebra/curves/alt_bn128/alt_bn128_g2.cpp @@ -419,30 +419,48 @@ alt_bn128_G2 alt_bn128_G2::random_element() return (alt_bn128_Fr::random_element().as_bigint()) * G2_one; } -std::ostream& operator<<(std::ostream &out, const alt_bn128_G2 &g) +void alt_bn128_G2::write_uncompressed(std::ostream &out) const { - alt_bn128_G2 copy(g); + alt_bn128_G2 copy(*this); copy.to_affine_coordinates(); out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; -#ifdef NO_PT_COMPRESSION out << copy.X << OUTPUT_SEPARATOR << copy.Y; -#else +} + +void alt_bn128_G2::write_compressed(std::ostream &out) const +{ + alt_bn128_G2 copy(*this); + copy.to_affine_coordinates(); + out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; /* storing LSB of Y */ out << copy.X << OUTPUT_SEPARATOR << (copy.Y.c0.as_bigint().data[0] & 1); -#endif - - return out; } -std::istream& operator>>(std::istream &in, alt_bn128_G2 &g) +void alt_bn128_G2::read_uncompressed(std::istream &in, alt_bn128_G2 &g) { char is_zero; alt_bn128_Fq2 tX, tY; -#ifdef NO_PT_COMPRESSION in >> is_zero >> tX >> tY; is_zero -= '0'; -#else + // using projective coordinates + if (!is_zero) + { + g.X = tX; + g.Y = tY; + g.Z = alt_bn128_Fq2::one(); + } + else + { + g = alt_bn128_G2::zero(); + } +} + +void alt_bn128_G2::read_compressed(std::istream &in, alt_bn128_G2 &g) +{ + char is_zero; + alt_bn128_Fq2 tX, tY; + in.read((char*)&is_zero, 1); // this reads is_zero; is_zero -= '0'; consume_OUTPUT_SEPARATOR(in); @@ -465,7 +483,6 @@ std::istream& operator>>(std::istream &in, alt_bn128_G2 &g) tY = -tY; } } -#endif // using projective coordinates if (!is_zero) { @@ -477,7 +494,25 @@ std::istream& operator>>(std::istream &in, alt_bn128_G2 &g) { g = alt_bn128_G2::zero(); } +} +std::ostream& operator<<(std::ostream &out, const alt_bn128_G2 &g) +{ +#ifdef NO_PT_COMPRESSION + g.write_uncompressed(out); +#else + g.write_compressed(out); +#endif + return out; +} + +std::istream& operator>>(std::istream &in, alt_bn128_G2 &g) +{ +#ifdef NO_PT_COMPRESSION + alt_bn128_G2::read_uncompressed(in, g); +#else + alt_bn128_G2::read_compressed(in, g); +#endif return in; } diff --git a/libff/algebra/curves/alt_bn128/alt_bn128_g2.hpp b/libff/algebra/curves/alt_bn128/alt_bn128_g2.hpp index a22c06f3..7cc1f840 100755 --- a/libff/algebra/curves/alt_bn128/alt_bn128_g2.hpp +++ b/libff/algebra/curves/alt_bn128/alt_bn128_g2.hpp @@ -73,8 +73,10 @@ class alt_bn128_G2 { static bigint base_field_char() { return base_field::field_char(); } static bigint order() { return scalar_field::field_char(); } - friend std::ostream& operator<<(std::ostream &out, const alt_bn128_G2 &g); - friend std::istream& operator>>(std::istream &in, alt_bn128_G2 &g); + void write_uncompressed(std::ostream &) const; + void write_compressed(std::ostream &) const; + static void read_uncompressed(std::istream &, alt_bn128_G2 &); + static void read_compressed(std::istream &, alt_bn128_G2 &); static void batch_to_special_all_non_zeros(std::vector &vec); }; diff --git a/libff/algebra/curves/bn128/bn128_g1.cpp b/libff/algebra/curves/bn128/bn128_g1.cpp index 6d1e8b2b..031cbc0c 100755 --- a/libff/algebra/curves/bn128/bn128_g1.cpp +++ b/libff/algebra/curves/bn128/bn128_g1.cpp @@ -352,35 +352,6 @@ bn128_G1 bn128_G1::random_element() return bn128_Fr::random_element().as_bigint() * G1_one; } -std::ostream& operator<<(std::ostream &out, const bn128_G1 &g) -{ - bn128_G1 gcopy(g); - gcopy.to_affine_coordinates(); - - out << (gcopy.is_zero() ? '1' : '0') << OUTPUT_SEPARATOR; - -#ifdef NO_PT_COMPRESSION - /* no point compression case */ -#ifndef BINARY_OUTPUT - out << gcopy.X << OUTPUT_SEPARATOR << gcopy.Y; -#else - out.write((char*) &gcopy.X, sizeof(gcopy.X)); - out.write((char*) &gcopy.Y, sizeof(gcopy.Y)); -#endif - -#else - /* point compression case */ -#ifndef BINARY_OUTPUT - out << gcopy.X; -#else - out.write((char*) &gcopy.X, sizeof(gcopy.X)); -#endif - out << OUTPUT_SEPARATOR << (((unsigned char*)&gcopy.Y)[0] & 1 ? '1' : '0'); -#endif - - return out; -} - bool bn128_G1::is_well_formed() const { if (this->is_zero()) @@ -412,15 +383,43 @@ bool bn128_G1::is_well_formed() const } } -std::istream& operator>>(std::istream &in, bn128_G1 &g) +void bn128_G1::write_uncompressed(std::ostream &out) const +{ + bn128_G1 gcopy(*this); + gcopy.to_affine_coordinates(); + + out << (gcopy.is_zero() ? '1' : '0') << OUTPUT_SEPARATOR; + +#ifndef BINARY_OUTPUT + out << gcopy.X << OUTPUT_SEPARATOR << gcopy.Y; +#else + out.write((char*) &gcopy.X, sizeof(gcopy.X)); + out.write((char*) &gcopy.Y, sizeof(gcopy.Y)); +#endif +} + +void bn128_G1::write_compressed(std::ostream &out) const +{ + bn128_G1 gcopy(*this); + gcopy.to_affine_coordinates(); + + out << (gcopy.is_zero() ? '1' : '0') << OUTPUT_SEPARATOR; + +#ifndef BINARY_OUTPUT + out << gcopy.X; +#else + out.write((char*) &gcopy.X, sizeof(gcopy.X)); +#endif + out << OUTPUT_SEPARATOR << (((unsigned char*)&gcopy.Y)[0] & 1 ? '1' : '0'); +} + +void bn128_G1::read_uncompressed(std::istream &in, bn128_G1 &g) { char is_zero; in.read((char*)&is_zero, 1); // this reads is_zero; is_zero -= '0'; consume_OUTPUT_SEPARATOR(in); -#ifdef NO_PT_COMPRESSION - /* no point compression case */ #ifndef BINARY_OUTPUT in >> g.X; consume_OUTPUT_SEPARATOR(in); @@ -430,8 +429,24 @@ std::istream& operator>>(std::istream &in, bn128_G1 &g) in.read((char*) &g.Y, sizeof(g.Y)); #endif -#else - /* point compression case */ + /* finalize */ + if (!is_zero) + { + g.Z = bn::Fp(1); + } + else + { + g = bn128_G1::zero(); + } +} + +void bn128_G1::read_compressed(std::istream &in, bn128_G1 &g) +{ + char is_zero; + in.read((char*)&is_zero, 1); // this reads is_zero; + is_zero -= '0'; + consume_OUTPUT_SEPARATOR(in); + bn::Fp tX; #ifndef BINARY_OUTPUT in >> tX; @@ -458,7 +473,6 @@ std::istream& operator>>(std::istream &in, bn128_G1 &g) bn::Fp::neg(g.Y, g.Y); } } -#endif /* finalize */ if (!is_zero) @@ -469,36 +483,25 @@ std::istream& operator>>(std::istream &in, bn128_G1 &g) { g = bn128_G1::zero(); } - - return in; } -std::ostream& operator<<(std::ostream& out, const std::vector &v) +std::ostream& operator<<(std::ostream &out, const bn128_G1 &g) { - out << v.size() << "\n"; - for (const bn128_G1& t : v) - { - out << t << OUTPUT_NEWLINE; - } +#ifdef NO_PT_COMPRESSION + g.write_uncompressed(out); +#else + g.write_compressed(out); +#endif return out; } -std::istream& operator>>(std::istream& in, std::vector &v) +std::istream& operator>>(std::istream &in, bn128_G1 &g) { - v.clear(); - - size_t s; - in >> s; - consume_newline(in); - v.reserve(s); - - for (size_t i = 0; i < s; ++i) - { - bn128_G1 g; - in >> g; - consume_OUTPUT_NEWLINE(in); - v.emplace_back(g); - } +#ifdef NO_PT_COMPRESSION + bn128_G1::read_uncompressed(in, g); +#else + bn128_G1::read_compressed(in, g); +#endif return in; } diff --git a/libff/algebra/curves/bn128/bn128_g1.hpp b/libff/algebra/curves/bn128/bn128_g1.hpp index 02a4ad0a..02bd263e 100755 --- a/libff/algebra/curves/bn128/bn128_g1.hpp +++ b/libff/algebra/curves/bn128/bn128_g1.hpp @@ -73,8 +73,10 @@ class bn128_G1 { static bigint base_field_char() { return base_field::field_char(); } static bigint order() { return scalar_field::field_char(); } - friend std::ostream& operator<<(std::ostream &out, const bn128_G1 &g); - friend std::istream& operator>>(std::istream &in, bn128_G1 &g); + void write_uncompressed(std::ostream &) const; + void write_compressed(std::ostream &) const; + static void read_uncompressed(std::istream &, bn128_G1 &); + static void read_compressed(std::istream &, bn128_G1 &); static void batch_to_special_all_non_zeros(std::vector &vec); }; @@ -91,9 +93,5 @@ bn128_G1 operator*(const Fp_model &lhs, const bn128_G1 &rhs) return scalar_mul(rhs, lhs.as_bigint()); } -std::ostream& operator<<(std::ostream& out, const std::vector &v); -std::istream& operator>>(std::istream& in, std::vector &v); - - } // libff #endif // BN128_G1_HPP_ diff --git a/libff/algebra/curves/bn128/bn128_g2.cpp b/libff/algebra/curves/bn128/bn128_g2.cpp index fa59d3ae..e98a0eaf 100755 --- a/libff/algebra/curves/bn128/bn128_g2.cpp +++ b/libff/algebra/curves/bn128/bn128_g2.cpp @@ -383,14 +383,13 @@ bn128_G2 bn128_G2::random_element() return bn128_Fr::random_element().as_bigint() * G2_one; } -std::ostream& operator<<(std::ostream &out, const bn128_G2 &g) +void bn128_G2::write_uncompressed(std::ostream &out) const { - bn128_G2 gcopy(g); + bn128_G2 gcopy(*this); gcopy.to_affine_coordinates(); out << (gcopy.is_zero() ? '1' : '0') << OUTPUT_SEPARATOR; -#ifdef NO_PT_COMPRESSION /* no point compression case */ #ifndef BINARY_OUTPUT out << gcopy.X.a_ << OUTPUT_SEPARATOR << gcopy.X.b_ << OUTPUT_SEPARATOR; @@ -401,9 +400,15 @@ std::ostream& operator<<(std::ostream &out, const bn128_G2 &g) out.write((char*) &gcopy.Y.a_, sizeof(gcopy.Y.a_)); out.write((char*) &gcopy.Y.b_, sizeof(gcopy.Y.b_)); #endif +} + +void bn128_G2::write_compressed(std::ostream &out) const +{ + bn128_G2 gcopy(*this); + gcopy.to_affine_coordinates(); + + out << (gcopy.is_zero() ? '1' : '0') << OUTPUT_SEPARATOR; -#else - /* point compression case */ #ifndef BINARY_OUTPUT out << gcopy.X.a_ << OUTPUT_SEPARATOR << gcopy.X.b_; #else @@ -411,20 +416,15 @@ std::ostream& operator<<(std::ostream &out, const bn128_G2 &g) out.write((char*) &gcopy.X.b_, sizeof(gcopy.X.b_)); #endif out << OUTPUT_SEPARATOR << (((unsigned char*)&gcopy.Y.a_)[0] & 1 ? '1' : '0'); -#endif - - return out; } -std::istream& operator>>(std::istream &in, bn128_G2 &g) +void bn128_G2::read_uncompressed(std::istream &in, bn128_G2 &g) { char is_zero; in.read((char*)&is_zero, 1); // this reads is_zero; is_zero -= '0'; consume_OUTPUT_SEPARATOR(in); -#ifdef NO_PT_COMPRESSION - /* no point compression case */ #ifndef BINARY_OUTPUT in >> g.X.a_; consume_OUTPUT_SEPARATOR(in); @@ -440,8 +440,24 @@ std::istream& operator>>(std::istream &in, bn128_G2 &g) in.read((char*) &g.Y.b_, sizeof(g.Y.b_)); #endif -#else - /* point compression case */ + /* finalize */ + if (!is_zero) + { + g.Z = bn::Fp2(bn::Fp(1), bn::Fp(0)); + } + else + { + g = bn128_G2::zero(); + } +} + +void bn128_G2::read_compressed(std::istream &in, bn128_G2 &g) +{ + char is_zero; + in.read((char*)&is_zero, 1); // this reads is_zero; + is_zero -= '0'; + consume_OUTPUT_SEPARATOR(in); + bn::Fp2 tX; #ifndef BINARY_OUTPUT in >> tX.a_; @@ -471,7 +487,6 @@ std::istream& operator>>(std::istream &in, bn128_G2 &g) bn::Fp2::neg(g.Y, g.Y); } } -#endif /* finalize */ if (!is_zero) @@ -482,7 +497,25 @@ std::istream& operator>>(std::istream &in, bn128_G2 &g) { g = bn128_G2::zero(); } +} + +std::ostream& operator<<(std::ostream &out, const bn128_G2 &g) +{ +#ifdef NO_PT_COMPRESSION + g.write_uncompressed(out); +#else + g.write_compressed(out); +#endif + return out; +} +std::istream& operator>>(std::istream &in, bn128_G2 &g) +{ +#ifdef NO_PT_COMPRESSION + bn128_G2::read_uncompressed(in, g); +#else + bn128_G2::read_compressed(in, g); +#endif return in; } diff --git a/libff/algebra/curves/bn128/bn128_g2.hpp b/libff/algebra/curves/bn128/bn128_g2.hpp index df06bf6d..459a3763 100755 --- a/libff/algebra/curves/bn128/bn128_g2.hpp +++ b/libff/algebra/curves/bn128/bn128_g2.hpp @@ -74,8 +74,10 @@ class bn128_G2 { static bigint base_field_char() { return base_field::field_char(); } static bigint order() { return scalar_field::field_char(); } - friend std::ostream& operator<<(std::ostream &out, const bn128_G2 &g); - friend std::istream& operator>>(std::istream &in, bn128_G2 &g); + void write_uncompressed(std::ostream &) const; + void write_compressed(std::ostream &) const; + static void read_uncompressed(std::istream &, bn128_G2 &); + static void read_compressed(std::istream &, bn128_G2 &); static void batch_to_special_all_non_zeros(std::vector &vec); }; diff --git a/libff/algebra/curves/edwards/edwards_g1.cpp b/libff/algebra/curves/edwards/edwards_g1.cpp index 3e30f345..d967bf7d 100755 --- a/libff/algebra/curves/edwards/edwards_g1.cpp +++ b/libff/algebra/curves/edwards/edwards_g1.cpp @@ -304,33 +304,44 @@ edwards_G1 edwards_G1::random_element() return edwards_Fr::random_element().as_bigint() * G1_one; } -std::ostream& operator<<(std::ostream &out, const edwards_G1 &g) +void edwards_G1::write_uncompressed(std::ostream &out) const { - edwards_G1 copy(g); + edwards_G1 copy(*this); copy.to_affine_coordinates(); -#ifdef NO_PT_COMPRESSION out << copy.X << OUTPUT_SEPARATOR << copy.Y; -#else - /* storing LSB of Y */ - out << copy.X << OUTPUT_SEPARATOR << (copy.Y.as_bigint().data[0] & 1); -#endif +} - return out; +void edwards_G1::write_compressed(std::ostream &out) const +{ + edwards_G1 copy(*this); + copy.to_affine_coordinates(); + out << copy.X << OUTPUT_SEPARATOR << (copy.Y.as_bigint().data[0] & 1); } -std::istream& operator>>(std::istream &in, edwards_G1 &g) +void edwards_G1::read_uncompressed(std::istream &in, edwards_G1 &g) { edwards_Fq tX, tY; - -#ifdef NO_PT_COMPRESSION in >> tX; consume_OUTPUT_SEPARATOR(in); in >> tY; -#else + + // using inverted coordinates + g.X = tY; + g.Y = tX; + g.Z = tX * tY; + +#ifdef USE_MIXED_ADDITION + g.to_special(); +#endif +} + +void edwards_G1::read_compressed(std::istream &in, edwards_G1 &g) +{ /* a x^2 + y^2 = 1 + d x^2 y^2 y = sqrt((1-ax^2)/(1-dx^2)) */ + edwards_Fq tX, tY; unsigned char Y_lsb; in >> tX; @@ -347,7 +358,6 @@ std::istream& operator>>(std::istream &in, edwards_G1 &g) { tY = -tY; } -#endif // using inverted coordinates g.X = tY; @@ -357,38 +367,25 @@ std::istream& operator>>(std::istream &in, edwards_G1 &g) #ifdef USE_MIXED_ADDITION g.to_special(); #endif - - return in; } -std::ostream& operator<<(std::ostream& out, const std::vector &v) +std::ostream& operator<<(std::ostream &out, const edwards_G1 &g) { - out << v.size() << "\n"; - for (const edwards_G1& t : v) - { - out << t << OUTPUT_NEWLINE; - } - +#ifdef NO_PT_COMPRESSION + g.write_uncompressed(out); +#else + g.write_compressed(out); +#endif return out; } -std::istream& operator>>(std::istream& in, std::vector &v) +std::istream& operator>>(std::istream &in, edwards_G1 &g) { - v.clear(); - - size_t s; - in >> s; - v.reserve(s); - consume_newline(in); - - for (size_t i = 0; i < s; ++i) - { - edwards_G1 g; - in >> g; - v.emplace_back(g); - consume_OUTPUT_NEWLINE(in); - } - +#ifdef NO_PT_COMPRESSION + edwards_G1::read_uncompressed(in, g); +#else + edwards_G1::read_compressed(in, g); +#endif return in; } diff --git a/libff/algebra/curves/edwards/edwards_g1.hpp b/libff/algebra/curves/edwards/edwards_g1.hpp index 29539fb5..4e41b6fa 100755 --- a/libff/algebra/curves/edwards/edwards_g1.hpp +++ b/libff/algebra/curves/edwards/edwards_g1.hpp @@ -71,8 +71,10 @@ class edwards_G1 { static bigint base_field_char() { return base_field::field_char(); } static bigint order() { return scalar_field::field_char(); } - friend std::ostream& operator<<(std::ostream &out, const edwards_G1 &g); - friend std::istream& operator>>(std::istream &in, edwards_G1 &g); + void write_uncompressed(std::ostream &) const; + void write_compressed(std::ostream &) const; + static void read_uncompressed(std::istream &, edwards_G1 &); + static void read_compressed(std::istream &, edwards_G1 &); static void batch_to_special_all_non_zeros(std::vector &vec); }; @@ -89,8 +91,5 @@ edwards_G1 operator*(const Fp_model &lhs, const edwards_G1 &rhs) return scalar_mul(rhs, lhs.as_bigint()); } -std::ostream& operator<<(std::ostream& out, const std::vector &v); -std::istream& operator>>(std::istream& in, std::vector &v); - } // libff #endif // EDWARDS_G1_HPP_ diff --git a/libff/algebra/curves/edwards/edwards_g2.cpp b/libff/algebra/curves/edwards/edwards_g2.cpp index feadd9f4..0e69dda7 100755 --- a/libff/algebra/curves/edwards/edwards_g2.cpp +++ b/libff/algebra/curves/edwards/edwards_g2.cpp @@ -336,32 +336,45 @@ edwards_G2 edwards_G2::random_element() return edwards_Fr::random_element().as_bigint() * G2_one; } -std::ostream& operator<<(std::ostream &out, const edwards_G2 &g) +void edwards_G2::write_uncompressed(std::ostream &out) const { - edwards_G2 copy(g); + edwards_G2 copy(*this); copy.to_affine_coordinates(); -#ifdef NO_PT_COMPRESSION out << copy.X << OUTPUT_SEPARATOR << copy.Y; -#else +} + +void edwards_G2::write_compressed(std::ostream &out) const +{ + edwards_G2 copy(*this); + copy.to_affine_coordinates(); /* storing LSB of Y */ out << copy.X << OUTPUT_SEPARATOR << (copy.Y.c0.as_bigint().data[0] & 1); -#endif - return out; } -std::istream& operator>>(std::istream &in, edwards_G2 &g) +void edwards_G2::read_uncompressed(std::istream &in, edwards_G2 &g) { edwards_Fq3 tX, tY; - -#ifdef NO_PT_COMPRESSION in >> tX; consume_OUTPUT_SEPARATOR(in); in >> tY; -#else + + // using inverted coordinates + g.X = tY; + g.Y = tX; + g.Z = tX * tY; + +#ifdef USE_MIXED_ADDITION + g.to_special(); +#endif +} + +void edwards_G2::read_compressed(std::istream &in, edwards_G2 &g) +{ /* a x^2 + y^2 = 1 + d x^2 y^2 y = sqrt((1-ax^2)/(1-dx^2)) */ + edwards_Fq3 tX, tY; unsigned char Y_lsb; in >> tX; consume_OUTPUT_SEPARATOR(in); @@ -379,7 +392,6 @@ std::istream& operator>>(std::istream &in, edwards_G2 &g) { tY = -tY; } -#endif // using inverted coordinates g.X = tY; @@ -389,7 +401,25 @@ std::istream& operator>>(std::istream &in, edwards_G2 &g) #ifdef USE_MIXED_ADDITION g.to_special(); #endif +} + +std::ostream& operator<<(std::ostream &out, const edwards_G2 &g) +{ +#ifdef NO_PT_COMPRESSION + g.write_uncompressed(out); +#else + g.write_compressed(out); +#endif + return out; +} +std::istream& operator>>(std::istream &in, edwards_G2 &g) +{ +#ifdef NO_PT_COMPRESSION + edwards_G2::read_uncompressed(in, g); +#else + edwards_G2::read_compressed(in, g); +#endif return in; } diff --git a/libff/algebra/curves/edwards/edwards_g2.hpp b/libff/algebra/curves/edwards/edwards_g2.hpp index afdc0883..9ce37af0 100755 --- a/libff/algebra/curves/edwards/edwards_g2.hpp +++ b/libff/algebra/curves/edwards/edwards_g2.hpp @@ -77,8 +77,10 @@ class edwards_G2 { static bigint base_field_char() { return base_field::field_char(); } static bigint order() { return scalar_field::field_char(); } - friend std::ostream& operator<<(std::ostream &out, const edwards_G2 &g); - friend std::istream& operator>>(std::istream &in, edwards_G2 &g); + void write_uncompressed(std::ostream &) const; + void write_compressed(std::ostream &) const; + static void read_uncompressed(std::istream &, edwards_G2 &); + static void read_compressed(std::istream &, edwards_G2 &); static void batch_to_special_all_non_zeros(std::vector &vec); }; diff --git a/libff/algebra/curves/mnt/mnt4/mnt4_g1.cpp b/libff/algebra/curves/mnt/mnt4/mnt4_g1.cpp index 0863c778..bcf93c3d 100755 --- a/libff/algebra/curves/mnt/mnt4/mnt4_g1.cpp +++ b/libff/algebra/curves/mnt/mnt4/mnt4_g1.cpp @@ -390,31 +390,49 @@ mnt4_G1 mnt4_G1::random_element() return (scalar_field::random_element().as_bigint()) * G1_one; } -std::ostream& operator<<(std::ostream &out, const mnt4_G1 &g) +void mnt4_G1::write_uncompressed(std::ostream &out) const { - mnt4_G1 copy(g); + mnt4_G1 copy(*this); copy.to_affine_coordinates(); out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; -#ifdef NO_PT_COMPRESSION out << copy.X << OUTPUT_SEPARATOR << copy.Y; -#else +} + +void mnt4_G1::write_compressed(std::ostream &out) const +{ + mnt4_G1 copy(*this); + copy.to_affine_coordinates(); + + out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; /* storing LSB of Y */ out << copy.X << OUTPUT_SEPARATOR << (copy.Y.as_bigint().data[0] & 1); -#endif - - return out; } -std::istream& operator>>(std::istream &in, mnt4_G1 &g) +void mnt4_G1::read_uncompressed(std::istream &in, mnt4_G1 &g) { char is_zero; mnt4_Fq tX, tY; - -#ifdef NO_PT_COMPRESSION in >> is_zero >> tX >> tY; is_zero -= '0'; -#else + + // using projective coordinates + if (!is_zero) + { + g.X = tX; + g.Y = tY; + g.Z = mnt4_Fq::one(); + } + else + { + g = mnt4_G1::zero(); + } +} + +void mnt4_G1::read_compressed(std::istream &in, mnt4_G1 &g) +{ + char is_zero; + mnt4_Fq tX, tY; in.read((char*)&is_zero, 1); is_zero -= '0'; consume_OUTPUT_SEPARATOR(in); @@ -437,7 +455,7 @@ std::istream& operator>>(std::istream &in, mnt4_G1 &g) tY = -tY; } } -#endif + // using projective coordinates if (!is_zero) { @@ -449,40 +467,25 @@ std::istream& operator>>(std::istream &in, mnt4_G1 &g) { g = mnt4_G1::zero(); } - - return in; } -std::ostream& operator<<(std::ostream& out, const std::vector &v) +std::ostream& operator<<(std::ostream &out, const mnt4_G1 &g) { - out << v.size() << "\n"; - for (const mnt4_G1& t : v) - { - out << t << OUTPUT_NEWLINE; - } - +#ifdef NO_PT_COMPRESSION + g.write_uncompressed(out); +#else + g.write_compressed(out); +#endif return out; } -std::istream& operator>>(std::istream& in, std::vector &v) +std::istream& operator>>(std::istream &in, mnt4_G1 &g) { - v.clear(); - - size_t s; - in >> s; - - consume_newline(in); - - v.reserve(s); - - for (size_t i = 0; i < s; ++i) - { - mnt4_G1 g; - in >> g; - consume_OUTPUT_NEWLINE(in); - v.emplace_back(g); - } - +#ifdef NO_PT_COMPRESSION + mnt4_G1::read_uncompressed(in, g); +#else + mnt4_G1::read_compressed(in, g); +#endif return in; } diff --git a/libff/algebra/curves/mnt/mnt4/mnt4_g1.hpp b/libff/algebra/curves/mnt/mnt4/mnt4_g1.hpp index 4297cbf2..bf3c4e44 100755 --- a/libff/algebra/curves/mnt/mnt4/mnt4_g1.hpp +++ b/libff/algebra/curves/mnt/mnt4/mnt4_g1.hpp @@ -77,8 +77,10 @@ class mnt4_G1 { static bigint base_field_char() { return mnt4_Fq::field_char(); } static bigint order() { return mnt4_Fr::field_char(); } - friend std::ostream& operator<<(std::ostream &out, const mnt4_G1 &g); - friend std::istream& operator>>(std::istream &in, mnt4_G1 &g); + void write_uncompressed(std::ostream &) const; + void write_compressed(std::ostream &) const; + static void read_uncompressed(std::istream &, mnt4_G1 &); + static void read_compressed(std::istream &, mnt4_G1 &); static void batch_to_special_all_non_zeros(std::vector &vec); }; @@ -95,9 +97,6 @@ mnt4_G1 operator*(const Fp_model &lhs, const mnt4_G1 &rhs) return scalar_mul(rhs, lhs.as_bigint()); } -std::ostream& operator<<(std::ostream& out, const std::vector &v); -std::istream& operator>>(std::istream& in, std::vector &v); - } // libff #endif // MNT4_G1_HPP_ diff --git a/libff/algebra/curves/mnt/mnt4/mnt4_g2.cpp b/libff/algebra/curves/mnt/mnt4/mnt4_g2.cpp index 1f627c6e..d6dea136 100755 --- a/libff/algebra/curves/mnt/mnt4/mnt4_g2.cpp +++ b/libff/algebra/curves/mnt/mnt4/mnt4_g2.cpp @@ -414,31 +414,49 @@ mnt4_G2 mnt4_G2::random_element() return (mnt4_Fr::random_element().as_bigint()) * G2_one; } -std::ostream& operator<<(std::ostream &out, const mnt4_G2 &g) +void mnt4_G2::write_uncompressed(std::ostream &out) const { - mnt4_G2 copy(g); + mnt4_G2 copy(*this); copy.to_affine_coordinates(); out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; -#ifdef NO_PT_COMPRESSION out << copy.X << OUTPUT_SEPARATOR << copy.Y; -#else +} + +void mnt4_G2::write_compressed(std::ostream &out) const +{ + mnt4_G2 copy(*this); + copy.to_affine_coordinates(); + + out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; /* storing LSB of Y */ out << copy.X << OUTPUT_SEPARATOR << (copy.Y.c0.as_bigint().data[0] & 1); -#endif - - return out; } -std::istream& operator>>(std::istream &in, mnt4_G2 &g) +void mnt4_G2::read_uncompressed(std::istream &in, mnt4_G2 &g) { char is_zero; mnt4_Fq2 tX, tY; - -#ifdef NO_PT_COMPRESSION in >> is_zero >> tX >> tY; is_zero -= '0'; -#else + + // using projective coordinates + if (!is_zero) + { + g.X = tX; + g.Y = tY; + g.Z = mnt4_Fq2::one(); + } + else + { + g = mnt4_G2::zero(); + } +} + +void mnt4_G2::read_compressed(std::istream &in, mnt4_G2 &g) +{ + char is_zero; + mnt4_Fq2 tX, tY; in.read((char*)&is_zero, 1); // this reads is_zero; is_zero -= '0'; consume_OUTPUT_SEPARATOR(in); @@ -461,7 +479,7 @@ std::istream& operator>>(std::istream &in, mnt4_G2 &g) tY = -tY; } } -#endif + // using projective coordinates if (!is_zero) { @@ -473,8 +491,6 @@ std::istream& operator>>(std::istream &in, mnt4_G2 &g) { g = mnt4_G2::zero(); } - - return in; } void mnt4_G2::batch_to_special_all_non_zeros(std::vector &vec) @@ -496,4 +512,24 @@ void mnt4_G2::batch_to_special_all_non_zeros(std::vector &vec) } } +std::ostream& operator<<(std::ostream &out, const mnt4_G2 &g) +{ +#ifdef NO_PT_COMPRESSION + g.write_uncompressed(out); +#else + g.write_compressed(out); +#endif + return out; +} + +std::istream& operator>>(std::istream &in, mnt4_G2 &g) +{ +#ifdef NO_PT_COMPRESSION + mnt4_G2::read_uncompressed(in, g); +#else + mnt4_G2::read_compressed(in, g); +#endif + return in; +} + } // libff diff --git a/libff/algebra/curves/mnt/mnt4/mnt4_g2.hpp b/libff/algebra/curves/mnt/mnt4/mnt4_g2.hpp index 24cb6a7a..d08ef73c 100755 --- a/libff/algebra/curves/mnt/mnt4/mnt4_g2.hpp +++ b/libff/algebra/curves/mnt/mnt4/mnt4_g2.hpp @@ -82,8 +82,10 @@ class mnt4_G2 { static bigint base_field_char() { return mnt4_Fq::field_char(); } static bigint order() { return mnt4_Fr::field_char(); } - friend std::ostream& operator<<(std::ostream &out, const mnt4_G2 &g); - friend std::istream& operator>>(std::istream &in, mnt4_G2 &g); + void write_uncompressed(std::ostream &) const; + void write_compressed(std::ostream &) const; + static void read_uncompressed(std::istream &, mnt4_G2 &); + static void read_compressed(std::istream &, mnt4_G2 &); static void batch_to_special_all_non_zeros(std::vector &vec); }; diff --git a/libff/algebra/curves/mnt/mnt6/mnt6_g1.cpp b/libff/algebra/curves/mnt/mnt6/mnt6_g1.cpp index 9b527e47..a4658273 100755 --- a/libff/algebra/curves/mnt/mnt6/mnt6_g1.cpp +++ b/libff/algebra/curves/mnt/mnt6/mnt6_g1.cpp @@ -390,31 +390,49 @@ mnt6_G1 mnt6_G1::random_element() return (scalar_field::random_element().as_bigint()) * G1_one; } -std::ostream& operator<<(std::ostream &out, const mnt6_G1 &g) +void mnt6_G1::write_uncompressed(std::ostream &out) const { - mnt6_G1 copy(g); + mnt6_G1 copy(*this); copy.to_affine_coordinates(); out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; -#ifdef NO_PT_COMPRESSION out << copy.X << OUTPUT_SEPARATOR << copy.Y; -#else +} + +void mnt6_G1::write_compressed(std::ostream &out) const +{ + mnt6_G1 copy(*this); + copy.to_affine_coordinates(); + + out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; /* storing LSB of Y */ out << copy.X << OUTPUT_SEPARATOR << (copy.Y.as_bigint().data[0] & 1); -#endif - - return out; } -std::istream& operator>>(std::istream &in, mnt6_G1 &g) +void mnt6_G1::read_uncompressed(std::istream &in, mnt6_G1 &g) { char is_zero; mnt6_Fq tX, tY; - -#ifdef NO_PT_COMPRESSION in >> is_zero >> tX >> tY; is_zero -= '0'; -#else + + // using projective coordinates + if (!is_zero) + { + g.X = tX; + g.Y = tY; + g.Z = mnt6_Fq::one(); + } + else + { + g = mnt6_G1::zero(); + } +} + +void mnt6_G1::read_compressed(std::istream &in, mnt6_G1 &g) +{ + char is_zero; + mnt6_Fq tX, tY; in.read((char*)&is_zero, 1); // this reads is_zero; is_zero -= '0'; consume_OUTPUT_SEPARATOR(in); @@ -437,7 +455,7 @@ std::istream& operator>>(std::istream &in, mnt6_G1 &g) tY = -tY; } } -#endif + // using projective coordinates if (!is_zero) { @@ -449,40 +467,6 @@ std::istream& operator>>(std::istream &in, mnt6_G1 &g) { g = mnt6_G1::zero(); } - - return in; -} - -std::ostream& operator<<(std::ostream& out, const std::vector &v) -{ - out << v.size() << "\n"; - for (const mnt6_G1& t : v) - { - out << t << OUTPUT_NEWLINE; - } - - return out; -} - -std::istream& operator>>(std::istream& in, std::vector &v) -{ - v.clear(); - - size_t s; - in >> s; - consume_newline(in); - - v.reserve(s); - - for (size_t i = 0; i < s; ++i) - { - mnt6_G1 g; - in >> g; - consume_OUTPUT_NEWLINE(in); - v.emplace_back(g); - } - - return in; } void mnt6_G1::batch_to_special_all_non_zeros(std::vector &vec) @@ -504,4 +488,24 @@ void mnt6_G1::batch_to_special_all_non_zeros(std::vector &vec) } } +std::ostream& operator<<(std::ostream &out, const mnt6_G1 &g) +{ +#ifdef NO_PT_COMPRESSION + g.write_uncompressed(out); +#else + g.write_compressed(out); +#endif + return out; +} + +std::istream& operator>>(std::istream &in, mnt6_G1 &g) +{ +#ifdef NO_PT_COMPRESSION + mnt6_G1::read_uncompressed(in, g); +#else + mnt6_G1::read_compressed(in, g); +#endif + return in; +} + } // libff diff --git a/libff/algebra/curves/mnt/mnt6/mnt6_g1.hpp b/libff/algebra/curves/mnt/mnt6/mnt6_g1.hpp index 06e7b1ee..21bd6ef2 100755 --- a/libff/algebra/curves/mnt/mnt6/mnt6_g1.hpp +++ b/libff/algebra/curves/mnt/mnt6/mnt6_g1.hpp @@ -77,8 +77,10 @@ class mnt6_G1 { static bigint base_field_char() { return base_field::field_char(); } static bigint order() { return scalar_field::field_char(); } - friend std::ostream& operator<<(std::ostream &out, const mnt6_G1 &g); - friend std::istream& operator>>(std::istream &in, mnt6_G1 &g); + void write_uncompressed(std::ostream &) const; + void write_compressed(std::ostream &) const; + static void read_uncompressed(std::istream &, mnt6_G1 &); + static void read_compressed(std::istream &, mnt6_G1 &); static void batch_to_special_all_non_zeros(std::vector &vec); }; @@ -95,9 +97,6 @@ mnt6_G1 operator*(const Fp_model &lhs, const mnt6_G1 &rhs) return scalar_mul(rhs, lhs.as_bigint()); } -std::ostream& operator<<(std::ostream& out, const std::vector &v); -std::istream& operator>>(std::istream& in, std::vector &v); - } // libff #endif // MNT6_G1_HPP_ diff --git a/libff/algebra/curves/mnt/mnt6/mnt6_g2.cpp b/libff/algebra/curves/mnt/mnt6/mnt6_g2.cpp index e1412cac..300ea382 100755 --- a/libff/algebra/curves/mnt/mnt6/mnt6_g2.cpp +++ b/libff/algebra/curves/mnt/mnt6/mnt6_g2.cpp @@ -421,31 +421,51 @@ mnt6_G2 mnt6_G2::random_element() return (mnt6_Fr::random_element().as_bigint()) * G2_one; } -std::ostream& operator<<(std::ostream &out, const mnt6_G2 &g) +void mnt6_G2::write_uncompressed(std::ostream &out) const { - mnt6_G2 copy(g); + mnt6_G2 copy(*this); copy.to_affine_coordinates(); out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; -#ifdef NO_PT_COMPRESSION out << copy.X << OUTPUT_SEPARATOR << copy.Y; -#else +} + +void mnt6_G2::write_compressed(std::ostream &out) const +{ + mnt6_G2 copy(*this); + copy.to_affine_coordinates(); + + out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR; /* storing LSB of Y */ out << copy.X << OUTPUT_SEPARATOR << (copy.Y.c0.as_bigint().data[0] & 1); -#endif - - return out; } -std::istream& operator>>(std::istream &in, mnt6_G2 &g) +void mnt6_G2::read_uncompressed(std::istream &in, mnt6_G2 &g) { char is_zero; mnt6_Fq3 tX, tY; -#ifdef NO_PT_COMPRESSION in >> is_zero >> tX >> tY; is_zero -= '0'; -#else + + // using projective coordinates + if (!is_zero) + { + g.X = tX; + g.Y = tY; + g.Z = mnt6_Fq3::one(); + } + else + { + g = mnt6_G2::zero(); + } +} + +void mnt6_G2::read_compressed(std::istream &in, mnt6_G2 &g) +{ + char is_zero; + mnt6_Fq3 tX, tY; + in.read((char*)&is_zero, 1); // this reads is_zero; is_zero -= '0'; consume_OUTPUT_SEPARATOR(in); @@ -468,7 +488,7 @@ std::istream& operator>>(std::istream &in, mnt6_G2 &g) tY = -tY; } } -#endif + // using projective coordinates if (!is_zero) { @@ -480,8 +500,6 @@ std::istream& operator>>(std::istream &in, mnt6_G2 &g) { g = mnt6_G2::zero(); } - - return in; } void mnt6_G2::batch_to_special_all_non_zeros(std::vector &vec) @@ -503,4 +521,24 @@ void mnt6_G2::batch_to_special_all_non_zeros(std::vector &vec) } } +std::ostream& operator<<(std::ostream &out, const mnt6_G2 &g) +{ +#ifdef NO_PT_COMPRESSION + g.write_uncompressed(out); +#else + g.write_compressed(out); +#endif + return out; +} + +std::istream& operator>>(std::istream &in, mnt6_G2 &g) +{ +#ifdef NO_PT_COMPRESSION + mnt6_G2::read_uncompressed(in, g); +#else + mnt6_G2::read_compressed(in, g); +#endif + return in; +} + } // libff diff --git a/libff/algebra/curves/mnt/mnt6/mnt6_g2.hpp b/libff/algebra/curves/mnt/mnt6/mnt6_g2.hpp index 8c8d7dfa..6638658a 100755 --- a/libff/algebra/curves/mnt/mnt6/mnt6_g2.hpp +++ b/libff/algebra/curves/mnt/mnt6/mnt6_g2.hpp @@ -82,8 +82,10 @@ class mnt6_G2 { static bigint base_field_char() { return base_field::field_char(); } static bigint order() { return scalar_field::field_char(); } - friend std::ostream& operator<<(std::ostream &out, const mnt6_G2 &g); - friend std::istream& operator>>(std::istream &in, mnt6_G2 &g); + void write_uncompressed(std::ostream &) const; + void write_compressed(std::ostream &) const; + static void read_uncompressed(std::istream &, mnt6_G2 &); + static void read_compressed(std::istream &, mnt6_G2 &); static void batch_to_special_all_non_zeros(std::vector &vec); }; diff --git a/libff/algebra/curves/tests/test_groups.cpp b/libff/algebra/curves/tests/test_groups.cpp index b2ecf585..5eb34fe4 100755 --- a/libff/algebra/curves/tests/test_groups.cpp +++ b/libff/algebra/curves/tests/test_groups.cpp @@ -129,9 +129,19 @@ void test_output() { std::stringstream ss; ss << g; + g.write_compressed(ss); + g.write_uncompressed(ss); + GroupT gg; + GroupT gg_comp; + GroupT gg_uncomp; ss >> gg; + GroupT::read_compressed(ss, gg_comp); + GroupT::read_uncompressed(ss, gg_uncomp); + assert(g == gg); + assert(g == gg_comp); + assert(g == gg_uncomp); /* use a random point in next iteration */ g = GroupT::random_element(); }