Fix libsnark dependency build.
This changes libsnark to build in-place, instead of copying first to a build directory. Previously, modifications made to the original sources wouldn't get rebuilt without a 'make clean' because users would be pointing to the copies. This closes #2689.
This commit is contained in:
524
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp
Normal file
524
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp
Normal file
@@ -0,0 +1,524 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_g1.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
long long alt_bn128_G1::add_cnt = 0;
|
||||
long long 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;
|
||||
alt_bn128_G1 alt_bn128_G1::G1_zero;
|
||||
alt_bn128_G1 alt_bn128_G1::G1_one;
|
||||
|
||||
alt_bn128_G1::alt_bn128_G1()
|
||||
{
|
||||
this->X = G1_zero.X;
|
||||
this->Y = G1_zero.Y;
|
||||
this->Z = G1_zero.Z;
|
||||
}
|
||||
|
||||
void alt_bn128_G1::print() const
|
||||
{
|
||||
if (this->is_zero())
|
||||
{
|
||||
printf("O\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
alt_bn128_G1 copy(*this);
|
||||
copy.to_affine_coordinates();
|
||||
gmp_printf("(%Nd , %Nd)\n",
|
||||
copy.X.as_bigint().data, alt_bn128_Fq::num_limbs,
|
||||
copy.Y.as_bigint().data, alt_bn128_Fq::num_limbs);
|
||||
}
|
||||
}
|
||||
|
||||
void alt_bn128_G1::print_coordinates() const
|
||||
{
|
||||
if (this->is_zero())
|
||||
{
|
||||
printf("O\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
gmp_printf("(%Nd : %Nd : %Nd)\n",
|
||||
this->X.as_bigint().data, alt_bn128_Fq::num_limbs,
|
||||
this->Y.as_bigint().data, alt_bn128_Fq::num_limbs,
|
||||
this->Z.as_bigint().data, alt_bn128_Fq::num_limbs);
|
||||
}
|
||||
}
|
||||
|
||||
void alt_bn128_G1::to_affine_coordinates()
|
||||
{
|
||||
if (this->is_zero())
|
||||
{
|
||||
this->X = alt_bn128_Fq::zero();
|
||||
this->Y = alt_bn128_Fq::one();
|
||||
this->Z = alt_bn128_Fq::zero();
|
||||
}
|
||||
else
|
||||
{
|
||||
alt_bn128_Fq Z_inv = Z.inverse();
|
||||
alt_bn128_Fq Z2_inv = Z_inv.squared();
|
||||
alt_bn128_Fq Z3_inv = Z2_inv * Z_inv;
|
||||
this->X = this->X * Z2_inv;
|
||||
this->Y = this->Y * Z3_inv;
|
||||
this->Z = alt_bn128_Fq::one();
|
||||
}
|
||||
}
|
||||
|
||||
void alt_bn128_G1::to_special()
|
||||
{
|
||||
this->to_affine_coordinates();
|
||||
}
|
||||
|
||||
bool alt_bn128_G1::is_special() const
|
||||
{
|
||||
return (this->is_zero() || this->Z == alt_bn128_Fq::one());
|
||||
}
|
||||
|
||||
bool alt_bn128_G1::is_zero() const
|
||||
{
|
||||
return (this->Z.is_zero());
|
||||
}
|
||||
|
||||
bool alt_bn128_G1::operator==(const alt_bn128_G1 &other) const
|
||||
{
|
||||
if (this->is_zero())
|
||||
{
|
||||
return other.is_zero();
|
||||
}
|
||||
|
||||
if (other.is_zero())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* now neither is O */
|
||||
|
||||
// using Jacobian coordinates so:
|
||||
// (X1:Y1:Z1) = (X2:Y2:Z2)
|
||||
// iff
|
||||
// X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3
|
||||
// iff
|
||||
// X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3
|
||||
|
||||
alt_bn128_Fq Z1_squared = (this->Z).squared();
|
||||
alt_bn128_Fq Z2_squared = (other.Z).squared();
|
||||
|
||||
if ((this->X * Z2_squared) != (other.X * Z1_squared))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
alt_bn128_Fq Z1_cubed = (this->Z) * Z1_squared;
|
||||
alt_bn128_Fq Z2_cubed = (other.Z) * Z2_squared;
|
||||
|
||||
if ((this->Y * Z2_cubed) != (other.Y * Z1_cubed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool alt_bn128_G1::operator!=(const alt_bn128_G1& other) const
|
||||
{
|
||||
return !(operator==(other));
|
||||
}
|
||||
|
||||
alt_bn128_G1 alt_bn128_G1::operator+(const alt_bn128_G1 &other) const
|
||||
{
|
||||
// handle special cases having to do with O
|
||||
if (this->is_zero())
|
||||
{
|
||||
return other;
|
||||
}
|
||||
|
||||
if (other.is_zero())
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// no need to handle points of order 2,4
|
||||
// (they cannot exist in a prime-order subgroup)
|
||||
|
||||
// check for doubling case
|
||||
|
||||
// using Jacobian coordinates so:
|
||||
// (X1:Y1:Z1) = (X2:Y2:Z2)
|
||||
// iff
|
||||
// X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3
|
||||
// iff
|
||||
// X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3
|
||||
|
||||
alt_bn128_Fq Z1Z1 = (this->Z).squared();
|
||||
alt_bn128_Fq Z2Z2 = (other.Z).squared();
|
||||
|
||||
alt_bn128_Fq U1 = this->X * Z2Z2;
|
||||
alt_bn128_Fq U2 = other.X * Z1Z1;
|
||||
|
||||
alt_bn128_Fq Z1_cubed = (this->Z) * Z1Z1;
|
||||
alt_bn128_Fq Z2_cubed = (other.Z) * Z2Z2;
|
||||
|
||||
alt_bn128_Fq S1 = (this->Y) * Z2_cubed; // S1 = Y1 * Z2 * Z2Z2
|
||||
alt_bn128_Fq S2 = (other.Y) * Z1_cubed; // S2 = Y2 * Z1 * Z1Z1
|
||||
|
||||
if (U1 == U2 && S1 == S2)
|
||||
{
|
||||
// dbl case; nothing of above can be reused
|
||||
return this->dbl();
|
||||
}
|
||||
|
||||
// rest of add case
|
||||
alt_bn128_Fq H = U2 - U1; // H = U2-U1
|
||||
alt_bn128_Fq S2_minus_S1 = S2-S1;
|
||||
alt_bn128_Fq I = (H+H).squared(); // I = (2 * H)^2
|
||||
alt_bn128_Fq J = H * I; // J = H * I
|
||||
alt_bn128_Fq r = S2_minus_S1 + S2_minus_S1; // r = 2 * (S2-S1)
|
||||
alt_bn128_Fq V = U1 * I; // V = U1 * I
|
||||
alt_bn128_Fq X3 = r.squared() - J - (V+V); // X3 = r^2 - J - 2 * V
|
||||
alt_bn128_Fq S1_J = S1 * J;
|
||||
alt_bn128_Fq Y3 = r * (V-X3) - (S1_J+S1_J); // Y3 = r * (V-X3)-2 S1 J
|
||||
alt_bn128_Fq Z3 = ((this->Z+other.Z).squared()-Z1Z1-Z2Z2) * H; // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H
|
||||
|
||||
return alt_bn128_G1(X3, Y3, Z3);
|
||||
}
|
||||
|
||||
alt_bn128_G1 alt_bn128_G1::operator-() const
|
||||
{
|
||||
return alt_bn128_G1(this->X, -(this->Y), this->Z);
|
||||
}
|
||||
|
||||
|
||||
alt_bn128_G1 alt_bn128_G1::operator-(const alt_bn128_G1 &other) const
|
||||
{
|
||||
return (*this) + (-other);
|
||||
}
|
||||
|
||||
alt_bn128_G1 alt_bn128_G1::add(const alt_bn128_G1 &other) const
|
||||
{
|
||||
// handle special cases having to do with O
|
||||
if (this->is_zero())
|
||||
{
|
||||
return other;
|
||||
}
|
||||
|
||||
if (other.is_zero())
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// no need to handle points of order 2,4
|
||||
// (they cannot exist in a prime-order subgroup)
|
||||
|
||||
// handle double case
|
||||
if (this->operator==(other))
|
||||
{
|
||||
return this->dbl();
|
||||
}
|
||||
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
this->add_cnt++;
|
||||
#endif
|
||||
// NOTE: does not handle O and pts of order 2,4
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
|
||||
|
||||
alt_bn128_Fq Z1Z1 = (this->Z).squared(); // Z1Z1 = Z1^2
|
||||
alt_bn128_Fq Z2Z2 = (other.Z).squared(); // Z2Z2 = Z2^2
|
||||
alt_bn128_Fq U1 = (this->X) * Z2Z2; // U1 = X1 * Z2Z2
|
||||
alt_bn128_Fq U2 = (other.X) * Z1Z1; // U2 = X2 * Z1Z1
|
||||
alt_bn128_Fq S1 = (this->Y) * (other.Z) * Z2Z2; // S1 = Y1 * Z2 * Z2Z2
|
||||
alt_bn128_Fq S2 = (other.Y) * (this->Z) * Z1Z1; // S2 = Y2 * Z1 * Z1Z1
|
||||
alt_bn128_Fq H = U2 - U1; // H = U2-U1
|
||||
alt_bn128_Fq S2_minus_S1 = S2-S1;
|
||||
alt_bn128_Fq I = (H+H).squared(); // I = (2 * H)^2
|
||||
alt_bn128_Fq J = H * I; // J = H * I
|
||||
alt_bn128_Fq r = S2_minus_S1 + S2_minus_S1; // r = 2 * (S2-S1)
|
||||
alt_bn128_Fq V = U1 * I; // V = U1 * I
|
||||
alt_bn128_Fq X3 = r.squared() - J - (V+V); // X3 = r^2 - J - 2 * V
|
||||
alt_bn128_Fq S1_J = S1 * J;
|
||||
alt_bn128_Fq Y3 = r * (V-X3) - (S1_J+S1_J); // Y3 = r * (V-X3)-2 S1 J
|
||||
alt_bn128_Fq Z3 = ((this->Z+other.Z).squared()-Z1Z1-Z2Z2) * H; // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H
|
||||
|
||||
return alt_bn128_G1(X3, Y3, Z3);
|
||||
}
|
||||
|
||||
alt_bn128_G1 alt_bn128_G1::mixed_add(const alt_bn128_G1 &other) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
assert(other.is_special());
|
||||
#endif
|
||||
|
||||
// handle special cases having to do with O
|
||||
if (this->is_zero())
|
||||
{
|
||||
return other;
|
||||
}
|
||||
|
||||
if (other.is_zero())
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// no need to handle points of order 2,4
|
||||
// (they cannot exist in a prime-order subgroup)
|
||||
|
||||
// check for doubling case
|
||||
|
||||
// using Jacobian coordinates so:
|
||||
// (X1:Y1:Z1) = (X2:Y2:Z2)
|
||||
// iff
|
||||
// X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3
|
||||
// iff
|
||||
// X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3
|
||||
|
||||
// we know that Z2 = 1
|
||||
|
||||
const alt_bn128_Fq Z1Z1 = (this->Z).squared();
|
||||
|
||||
const alt_bn128_Fq &U1 = this->X;
|
||||
const alt_bn128_Fq U2 = other.X * Z1Z1;
|
||||
|
||||
const alt_bn128_Fq Z1_cubed = (this->Z) * Z1Z1;
|
||||
|
||||
const alt_bn128_Fq &S1 = (this->Y); // S1 = Y1 * Z2 * Z2Z2
|
||||
const alt_bn128_Fq S2 = (other.Y) * Z1_cubed; // S2 = Y2 * Z1 * Z1Z1
|
||||
|
||||
if (U1 == U2 && S1 == S2)
|
||||
{
|
||||
// dbl case; nothing of above can be reused
|
||||
return this->dbl();
|
||||
}
|
||||
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
this->add_cnt++;
|
||||
#endif
|
||||
|
||||
// NOTE: does not handle O and pts of order 2,4
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
|
||||
alt_bn128_Fq H = U2-(this->X); // H = U2-X1
|
||||
alt_bn128_Fq HH = H.squared() ; // HH = H&2
|
||||
alt_bn128_Fq I = HH+HH; // I = 4*HH
|
||||
I = I + I;
|
||||
alt_bn128_Fq J = H*I; // J = H*I
|
||||
alt_bn128_Fq r = S2-(this->Y); // r = 2*(S2-Y1)
|
||||
r = r + r;
|
||||
alt_bn128_Fq V = (this->X) * I ; // V = X1*I
|
||||
alt_bn128_Fq X3 = r.squared()-J-V-V; // X3 = r^2-J-2*V
|
||||
alt_bn128_Fq Y3 = (this->Y)*J; // Y3 = r*(V-X3)-2*Y1*J
|
||||
Y3 = r*(V-X3) - Y3 - Y3;
|
||||
alt_bn128_Fq Z3 = ((this->Z)+H).squared() - Z1Z1 - HH; // Z3 = (Z1+H)^2-Z1Z1-HH
|
||||
|
||||
return alt_bn128_G1(X3, Y3, Z3);
|
||||
}
|
||||
|
||||
alt_bn128_G1 alt_bn128_G1::dbl() const
|
||||
{
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
this->dbl_cnt++;
|
||||
#endif
|
||||
// handle point at infinity
|
||||
if (this->is_zero())
|
||||
{
|
||||
return (*this);
|
||||
}
|
||||
|
||||
// no need to handle points of order 2,4
|
||||
// (they cannot exist in a prime-order subgroup)
|
||||
|
||||
// NOTE: does not handle O and pts of order 2,4
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
||||
|
||||
alt_bn128_Fq A = (this->X).squared(); // A = X1^2
|
||||
alt_bn128_Fq B = (this->Y).squared(); // B = Y1^2
|
||||
alt_bn128_Fq C = B.squared(); // C = B^2
|
||||
alt_bn128_Fq D = (this->X + B).squared() - A - C;
|
||||
D = D+D; // D = 2 * ((X1 + B)^2 - A - C)
|
||||
alt_bn128_Fq E = A + A + A; // E = 3 * A
|
||||
alt_bn128_Fq F = E.squared(); // F = E^2
|
||||
alt_bn128_Fq X3 = F - (D+D); // X3 = F - 2 D
|
||||
alt_bn128_Fq eightC = C+C;
|
||||
eightC = eightC + eightC;
|
||||
eightC = eightC + eightC;
|
||||
alt_bn128_Fq Y3 = E * (D - X3) - eightC; // Y3 = E * (D - X3) - 8 * C
|
||||
alt_bn128_Fq Y1Z1 = (this->Y)*(this->Z);
|
||||
alt_bn128_Fq Z3 = Y1Z1 + Y1Z1; // Z3 = 2 * Y1 * Z1
|
||||
|
||||
return alt_bn128_G1(X3, Y3, Z3);
|
||||
}
|
||||
|
||||
bool alt_bn128_G1::is_well_formed() const
|
||||
{
|
||||
if (this->is_zero())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
y^2 = x^3 + b
|
||||
|
||||
We are using Jacobian coordinates, so equation we need to check is actually
|
||||
|
||||
(y/z^3)^2 = (x/z^2)^3 + b
|
||||
y^2 / z^6 = x^3 / z^6 + b
|
||||
y^2 = x^3 + b z^6
|
||||
*/
|
||||
alt_bn128_Fq X2 = this->X.squared();
|
||||
alt_bn128_Fq Y2 = this->Y.squared();
|
||||
alt_bn128_Fq Z2 = this->Z.squared();
|
||||
|
||||
alt_bn128_Fq X3 = this->X * X2;
|
||||
alt_bn128_Fq Z3 = this->Z * Z2;
|
||||
alt_bn128_Fq Z6 = Z3.squared();
|
||||
|
||||
return (Y2 == X3 + alt_bn128_coeff_b * Z6);
|
||||
}
|
||||
}
|
||||
|
||||
alt_bn128_G1 alt_bn128_G1::zero()
|
||||
{
|
||||
return G1_zero;
|
||||
}
|
||||
|
||||
alt_bn128_G1 alt_bn128_G1::one()
|
||||
{
|
||||
return G1_one;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
alt_bn128_G1 copy(g);
|
||||
copy.to_affine_coordinates();
|
||||
|
||||
out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR;
|
||||
#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;
|
||||
}
|
||||
|
||||
std::istream& operator>>(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
|
||||
in.read((char*)&is_zero, 1); // this reads is_zero;
|
||||
is_zero -= '0';
|
||||
consume_OUTPUT_SEPARATOR(in);
|
||||
|
||||
unsigned char Y_lsb;
|
||||
in >> tX;
|
||||
consume_OUTPUT_SEPARATOR(in);
|
||||
in.read((char*)&Y_lsb, 1);
|
||||
Y_lsb -= '0';
|
||||
|
||||
// y = +/- sqrt(x^3 + b)
|
||||
if (!is_zero)
|
||||
{
|
||||
alt_bn128_Fq tX2 = tX.squared();
|
||||
alt_bn128_Fq tY2 = tX2*tX + alt_bn128_coeff_b;
|
||||
tY = tY2.sqrt();
|
||||
|
||||
if ((tY.as_bigint().data[0] & 1) != Y_lsb)
|
||||
{
|
||||
tY = -tY;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// using Jacobian coordinates
|
||||
if (!is_zero)
|
||||
{
|
||||
g.X = tX;
|
||||
g.Y = tY;
|
||||
g.Z = alt_bn128_Fq::one();
|
||||
}
|
||||
else
|
||||
{
|
||||
g = alt_bn128_G1::zero();
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const std::vector<alt_bn128_G1> &v)
|
||||
{
|
||||
out << v.size() << "\n";
|
||||
for (const alt_bn128_G1& t : v)
|
||||
{
|
||||
out << t << OUTPUT_NEWLINE;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& in, std::vector<alt_bn128_G1> &v)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
template<>
|
||||
void batch_to_special_all_non_zeros<alt_bn128_G1>(std::vector<alt_bn128_G1> &vec)
|
||||
{
|
||||
std::vector<alt_bn128_Fq> Z_vec;
|
||||
Z_vec.reserve(vec.size());
|
||||
|
||||
for (auto &el: vec)
|
||||
{
|
||||
Z_vec.emplace_back(el.Z);
|
||||
}
|
||||
batch_invert<alt_bn128_Fq>(Z_vec);
|
||||
|
||||
const alt_bn128_Fq one = alt_bn128_Fq::one();
|
||||
|
||||
for (size_t i = 0; i < vec.size(); ++i)
|
||||
{
|
||||
alt_bn128_Fq Z2 = Z_vec[i].squared();
|
||||
alt_bn128_Fq Z3 = Z_vec[i] * Z2;
|
||||
|
||||
vec[i].X = vec[i].X * Z2;
|
||||
vec[i].Y = vec[i].Y * Z3;
|
||||
vec[i].Z = one;
|
||||
}
|
||||
}
|
||||
|
||||
} // libsnark
|
||||
95
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.hpp
Normal file
95
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.hpp
Normal file
@@ -0,0 +1,95 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ALT_BN128_G1_HPP_
|
||||
#define ALT_BN128_G1_HPP_
|
||||
#include <vector>
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_init.hpp"
|
||||
#include "algebra/curves/curve_utils.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
class alt_bn128_G1;
|
||||
std::ostream& operator<<(std::ostream &, const alt_bn128_G1&);
|
||||
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;
|
||||
#endif
|
||||
static std::vector<size_t> wnaf_window_table;
|
||||
static std::vector<size_t> fixed_base_exp_window_table;
|
||||
static alt_bn128_G1 G1_zero;
|
||||
static alt_bn128_G1 G1_one;
|
||||
|
||||
typedef alt_bn128_Fq base_field;
|
||||
typedef alt_bn128_Fr scalar_field;
|
||||
|
||||
alt_bn128_Fq X, Y, Z;
|
||||
|
||||
// using Jacobian coordinates
|
||||
alt_bn128_G1();
|
||||
alt_bn128_G1(const alt_bn128_Fq& X, const alt_bn128_Fq& Y, const alt_bn128_Fq& Z) : X(X), Y(Y), Z(Z) {};
|
||||
|
||||
void print() const;
|
||||
void print_coordinates() const;
|
||||
|
||||
void to_affine_coordinates();
|
||||
void to_special();
|
||||
bool is_special() const;
|
||||
|
||||
bool is_zero() const;
|
||||
|
||||
bool operator==(const alt_bn128_G1 &other) const;
|
||||
bool operator!=(const alt_bn128_G1 &other) const;
|
||||
|
||||
alt_bn128_G1 operator+(const alt_bn128_G1 &other) const;
|
||||
alt_bn128_G1 operator-() const;
|
||||
alt_bn128_G1 operator-(const alt_bn128_G1 &other) const;
|
||||
|
||||
alt_bn128_G1 add(const alt_bn128_G1 &other) const;
|
||||
alt_bn128_G1 mixed_add(const alt_bn128_G1 &other) const;
|
||||
alt_bn128_G1 dbl() const;
|
||||
|
||||
bool is_well_formed() const;
|
||||
|
||||
static alt_bn128_G1 zero();
|
||||
static alt_bn128_G1 one();
|
||||
static alt_bn128_G1 random_element();
|
||||
|
||||
static size_t size_in_bits() { return base_field::size_in_bits() + 1; }
|
||||
static bigint<base_field::num_limbs> base_field_char() { return base_field::field_char(); }
|
||||
static bigint<scalar_field::num_limbs> 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);
|
||||
};
|
||||
|
||||
template<mp_size_t m>
|
||||
alt_bn128_G1 operator*(const bigint<m> &lhs, const alt_bn128_G1 &rhs)
|
||||
{
|
||||
return scalar_mul<alt_bn128_G1, m>(rhs, lhs);
|
||||
}
|
||||
|
||||
template<mp_size_t m, const bigint<m>& modulus_p>
|
||||
alt_bn128_G1 operator*(const Fp_model<m,modulus_p> &lhs, const alt_bn128_G1 &rhs)
|
||||
{
|
||||
return scalar_mul<alt_bn128_G1, m>(rhs, lhs.as_bigint());
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const std::vector<alt_bn128_G1> &v);
|
||||
std::istream& operator>>(std::istream& in, std::vector<alt_bn128_G1> &v);
|
||||
|
||||
template<typename T>
|
||||
void batch_to_special_all_non_zeros(std::vector<T> &vec);
|
||||
template<>
|
||||
void batch_to_special_all_non_zeros<alt_bn128_G1>(std::vector<alt_bn128_G1> &vec);
|
||||
|
||||
} // libsnark
|
||||
#endif // ALT_BN128_G1_HPP_
|
||||
505
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp
Normal file
505
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp
Normal file
@@ -0,0 +1,505 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_g2.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
long long alt_bn128_G2::add_cnt = 0;
|
||||
long long 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;
|
||||
alt_bn128_G2 alt_bn128_G2::G2_zero;
|
||||
alt_bn128_G2 alt_bn128_G2::G2_one;
|
||||
|
||||
alt_bn128_G2::alt_bn128_G2()
|
||||
{
|
||||
this->X = G2_zero.X;
|
||||
this->Y = G2_zero.Y;
|
||||
this->Z = G2_zero.Z;
|
||||
}
|
||||
|
||||
alt_bn128_Fq2 alt_bn128_G2::mul_by_b(const alt_bn128_Fq2 &elt)
|
||||
{
|
||||
return alt_bn128_Fq2(alt_bn128_twist_mul_by_b_c0 * elt.c0, alt_bn128_twist_mul_by_b_c1 * elt.c1);
|
||||
}
|
||||
|
||||
void alt_bn128_G2::print() const
|
||||
{
|
||||
if (this->is_zero())
|
||||
{
|
||||
printf("O\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
alt_bn128_G2 copy(*this);
|
||||
copy.to_affine_coordinates();
|
||||
gmp_printf("(%Nd*z + %Nd , %Nd*z + %Nd)\n",
|
||||
copy.X.c1.as_bigint().data, alt_bn128_Fq::num_limbs,
|
||||
copy.X.c0.as_bigint().data, alt_bn128_Fq::num_limbs,
|
||||
copy.Y.c1.as_bigint().data, alt_bn128_Fq::num_limbs,
|
||||
copy.Y.c0.as_bigint().data, alt_bn128_Fq::num_limbs);
|
||||
}
|
||||
}
|
||||
|
||||
void alt_bn128_G2::print_coordinates() const
|
||||
{
|
||||
if (this->is_zero())
|
||||
{
|
||||
printf("O\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
gmp_printf("(%Nd*z + %Nd : %Nd*z + %Nd : %Nd*z + %Nd)\n",
|
||||
this->X.c1.as_bigint().data, alt_bn128_Fq::num_limbs,
|
||||
this->X.c0.as_bigint().data, alt_bn128_Fq::num_limbs,
|
||||
this->Y.c1.as_bigint().data, alt_bn128_Fq::num_limbs,
|
||||
this->Y.c0.as_bigint().data, alt_bn128_Fq::num_limbs,
|
||||
this->Z.c1.as_bigint().data, alt_bn128_Fq::num_limbs,
|
||||
this->Z.c0.as_bigint().data, alt_bn128_Fq::num_limbs);
|
||||
}
|
||||
}
|
||||
|
||||
void alt_bn128_G2::to_affine_coordinates()
|
||||
{
|
||||
if (this->is_zero())
|
||||
{
|
||||
this->X = alt_bn128_Fq2::zero();
|
||||
this->Y = alt_bn128_Fq2::one();
|
||||
this->Z = alt_bn128_Fq2::zero();
|
||||
}
|
||||
else
|
||||
{
|
||||
alt_bn128_Fq2 Z_inv = Z.inverse();
|
||||
alt_bn128_Fq2 Z2_inv = Z_inv.squared();
|
||||
alt_bn128_Fq2 Z3_inv = Z2_inv * Z_inv;
|
||||
this->X = this->X * Z2_inv;
|
||||
this->Y = this->Y * Z3_inv;
|
||||
this->Z = alt_bn128_Fq2::one();
|
||||
}
|
||||
}
|
||||
|
||||
void alt_bn128_G2::to_special()
|
||||
{
|
||||
this->to_affine_coordinates();
|
||||
}
|
||||
|
||||
bool alt_bn128_G2::is_special() const
|
||||
{
|
||||
return (this->is_zero() || this->Z == alt_bn128_Fq2::one());
|
||||
}
|
||||
|
||||
bool alt_bn128_G2::is_zero() const
|
||||
{
|
||||
return (this->Z.is_zero());
|
||||
}
|
||||
|
||||
bool alt_bn128_G2::operator==(const alt_bn128_G2 &other) const
|
||||
{
|
||||
if (this->is_zero())
|
||||
{
|
||||
return other.is_zero();
|
||||
}
|
||||
|
||||
if (other.is_zero())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* now neither is O */
|
||||
|
||||
// using Jacobian coordinates so:
|
||||
// (X1:Y1:Z1) = (X2:Y2:Z2)
|
||||
// iff
|
||||
// X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3
|
||||
// iff
|
||||
// X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3
|
||||
|
||||
alt_bn128_Fq2 Z1_squared = (this->Z).squared();
|
||||
alt_bn128_Fq2 Z2_squared = (other.Z).squared();
|
||||
|
||||
if ((this->X * Z2_squared) != (other.X * Z1_squared))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
alt_bn128_Fq2 Z1_cubed = (this->Z) * Z1_squared;
|
||||
alt_bn128_Fq2 Z2_cubed = (other.Z) * Z2_squared;
|
||||
|
||||
if ((this->Y * Z2_cubed) != (other.Y * Z1_cubed))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool alt_bn128_G2::operator!=(const alt_bn128_G2& other) const
|
||||
{
|
||||
return !(operator==(other));
|
||||
}
|
||||
|
||||
alt_bn128_G2 alt_bn128_G2::operator+(const alt_bn128_G2 &other) const
|
||||
{
|
||||
// handle special cases having to do with O
|
||||
if (this->is_zero())
|
||||
{
|
||||
return other;
|
||||
}
|
||||
|
||||
if (other.is_zero())
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// no need to handle points of order 2,4
|
||||
// (they cannot exist in a prime-order subgroup)
|
||||
|
||||
// check for doubling case
|
||||
|
||||
// using Jacobian coordinates so:
|
||||
// (X1:Y1:Z1) = (X2:Y2:Z2)
|
||||
// iff
|
||||
// X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3
|
||||
// iff
|
||||
// X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3
|
||||
|
||||
alt_bn128_Fq2 Z1Z1 = (this->Z).squared();
|
||||
alt_bn128_Fq2 Z2Z2 = (other.Z).squared();
|
||||
|
||||
alt_bn128_Fq2 U1 = this->X * Z2Z2;
|
||||
alt_bn128_Fq2 U2 = other.X * Z1Z1;
|
||||
|
||||
alt_bn128_Fq2 Z1_cubed = (this->Z) * Z1Z1;
|
||||
alt_bn128_Fq2 Z2_cubed = (other.Z) * Z2Z2;
|
||||
|
||||
alt_bn128_Fq2 S1 = (this->Y) * Z2_cubed; // S1 = Y1 * Z2 * Z2Z2
|
||||
alt_bn128_Fq2 S2 = (other.Y) * Z1_cubed; // S2 = Y2 * Z1 * Z1Z1
|
||||
|
||||
if (U1 == U2 && S1 == S2)
|
||||
{
|
||||
// dbl case; nothing of above can be reused
|
||||
return this->dbl();
|
||||
}
|
||||
|
||||
// rest of add case
|
||||
alt_bn128_Fq2 H = U2 - U1; // H = U2-U1
|
||||
alt_bn128_Fq2 S2_minus_S1 = S2-S1;
|
||||
alt_bn128_Fq2 I = (H+H).squared(); // I = (2 * H)^2
|
||||
alt_bn128_Fq2 J = H * I; // J = H * I
|
||||
alt_bn128_Fq2 r = S2_minus_S1 + S2_minus_S1; // r = 2 * (S2-S1)
|
||||
alt_bn128_Fq2 V = U1 * I; // V = U1 * I
|
||||
alt_bn128_Fq2 X3 = r.squared() - J - (V+V); // X3 = r^2 - J - 2 * V
|
||||
alt_bn128_Fq2 S1_J = S1 * J;
|
||||
alt_bn128_Fq2 Y3 = r * (V-X3) - (S1_J+S1_J); // Y3 = r * (V-X3)-2 S1 J
|
||||
alt_bn128_Fq2 Z3 = ((this->Z+other.Z).squared()-Z1Z1-Z2Z2) * H; // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H
|
||||
|
||||
return alt_bn128_G2(X3, Y3, Z3);
|
||||
}
|
||||
|
||||
alt_bn128_G2 alt_bn128_G2::operator-() const
|
||||
{
|
||||
return alt_bn128_G2(this->X, -(this->Y), this->Z);
|
||||
}
|
||||
|
||||
|
||||
alt_bn128_G2 alt_bn128_G2::operator-(const alt_bn128_G2 &other) const
|
||||
{
|
||||
return (*this) + (-other);
|
||||
}
|
||||
|
||||
alt_bn128_G2 alt_bn128_G2::add(const alt_bn128_G2 &other) const
|
||||
{
|
||||
// handle special cases having to do with O
|
||||
if (this->is_zero())
|
||||
{
|
||||
return other;
|
||||
}
|
||||
|
||||
if (other.is_zero())
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// no need to handle points of order 2,4
|
||||
// (they cannot exist in a prime-order subgroup)
|
||||
|
||||
// handle double case
|
||||
if (this->operator==(other))
|
||||
{
|
||||
return this->dbl();
|
||||
}
|
||||
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
this->add_cnt++;
|
||||
#endif
|
||||
// NOTE: does not handle O and pts of order 2,4
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-projective.html#addition-add-1998-cmo-2
|
||||
|
||||
alt_bn128_Fq2 Z1Z1 = (this->Z).squared(); // Z1Z1 = Z1^2
|
||||
alt_bn128_Fq2 Z2Z2 = (other.Z).squared(); // Z2Z2 = Z2^2
|
||||
alt_bn128_Fq2 U1 = (this->X) * Z2Z2; // U1 = X1 * Z2Z2
|
||||
alt_bn128_Fq2 U2 = (other.X) * Z1Z1; // U2 = X2 * Z1Z1
|
||||
alt_bn128_Fq2 S1 = (this->Y) * (other.Z) * Z2Z2; // S1 = Y1 * Z2 * Z2Z2
|
||||
alt_bn128_Fq2 S2 = (other.Y) * (this->Z) * Z1Z1; // S2 = Y2 * Z1 * Z1Z1
|
||||
alt_bn128_Fq2 H = U2 - U1; // H = U2-U1
|
||||
alt_bn128_Fq2 S2_minus_S1 = S2-S1;
|
||||
alt_bn128_Fq2 I = (H+H).squared(); // I = (2 * H)^2
|
||||
alt_bn128_Fq2 J = H * I; // J = H * I
|
||||
alt_bn128_Fq2 r = S2_minus_S1 + S2_minus_S1; // r = 2 * (S2-S1)
|
||||
alt_bn128_Fq2 V = U1 * I; // V = U1 * I
|
||||
alt_bn128_Fq2 X3 = r.squared() - J - (V+V); // X3 = r^2 - J - 2 * V
|
||||
alt_bn128_Fq2 S1_J = S1 * J;
|
||||
alt_bn128_Fq2 Y3 = r * (V-X3) - (S1_J+S1_J); // Y3 = r * (V-X3)-2 S1 J
|
||||
alt_bn128_Fq2 Z3 = ((this->Z+other.Z).squared()-Z1Z1-Z2Z2) * H; // Z3 = ((Z1+Z2)^2-Z1Z1-Z2Z2) * H
|
||||
|
||||
return alt_bn128_G2(X3, Y3, Z3);
|
||||
}
|
||||
|
||||
alt_bn128_G2 alt_bn128_G2::mixed_add(const alt_bn128_G2 &other) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
assert(other.is_special());
|
||||
#endif
|
||||
|
||||
// handle special cases having to do with O
|
||||
if (this->is_zero())
|
||||
{
|
||||
return other;
|
||||
}
|
||||
|
||||
if (other.is_zero())
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
// no need to handle points of order 2,4
|
||||
// (they cannot exist in a prime-order subgroup)
|
||||
|
||||
// check for doubling case
|
||||
|
||||
// using Jacobian coordinates so:
|
||||
// (X1:Y1:Z1) = (X2:Y2:Z2)
|
||||
// iff
|
||||
// X1/Z1^2 == X2/Z2^2 and Y1/Z1^3 == Y2/Z2^3
|
||||
// iff
|
||||
// X1 * Z2^2 == X2 * Z1^2 and Y1 * Z2^3 == Y2 * Z1^3
|
||||
|
||||
// we know that Z2 = 1
|
||||
|
||||
const alt_bn128_Fq2 Z1Z1 = (this->Z).squared();
|
||||
|
||||
const alt_bn128_Fq2 &U1 = this->X;
|
||||
const alt_bn128_Fq2 U2 = other.X * Z1Z1;
|
||||
|
||||
const alt_bn128_Fq2 Z1_cubed = (this->Z) * Z1Z1;
|
||||
|
||||
const alt_bn128_Fq2 &S1 = (this->Y); // S1 = Y1 * Z2 * Z2Z2
|
||||
const alt_bn128_Fq2 S2 = (other.Y) * Z1_cubed; // S2 = Y2 * Z1 * Z1Z1
|
||||
|
||||
if (U1 == U2 && S1 == S2)
|
||||
{
|
||||
// dbl case; nothing of above can be reused
|
||||
return this->dbl();
|
||||
}
|
||||
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
this->add_cnt++;
|
||||
#endif
|
||||
|
||||
// NOTE: does not handle O and pts of order 2,4
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-madd-2007-bl
|
||||
alt_bn128_Fq2 H = U2-(this->X); // H = U2-X1
|
||||
alt_bn128_Fq2 HH = H.squared() ; // HH = H&2
|
||||
alt_bn128_Fq2 I = HH+HH; // I = 4*HH
|
||||
I = I + I;
|
||||
alt_bn128_Fq2 J = H*I; // J = H*I
|
||||
alt_bn128_Fq2 r = S2-(this->Y); // r = 2*(S2-Y1)
|
||||
r = r + r;
|
||||
alt_bn128_Fq2 V = (this->X) * I ; // V = X1*I
|
||||
alt_bn128_Fq2 X3 = r.squared()-J-V-V; // X3 = r^2-J-2*V
|
||||
alt_bn128_Fq2 Y3 = (this->Y)*J; // Y3 = r*(V-X3)-2*Y1*J
|
||||
Y3 = r*(V-X3) - Y3 - Y3;
|
||||
alt_bn128_Fq2 Z3 = ((this->Z)+H).squared() - Z1Z1 - HH; // Z3 = (Z1+H)^2-Z1Z1-HH
|
||||
|
||||
return alt_bn128_G2(X3, Y3, Z3);
|
||||
}
|
||||
|
||||
alt_bn128_G2 alt_bn128_G2::dbl() const
|
||||
{
|
||||
#ifdef PROFILE_OP_COUNTS
|
||||
this->dbl_cnt++;
|
||||
#endif
|
||||
// handle point at infinity
|
||||
if (this->is_zero())
|
||||
{
|
||||
return (*this);
|
||||
}
|
||||
|
||||
// NOTE: does not handle O and pts of order 2,4
|
||||
// http://www.hyperelliptic.org/EFD/g1p/auto-shortw-projective.html#doubling-dbl-2007-bl
|
||||
|
||||
alt_bn128_Fq2 A = (this->X).squared(); // A = X1^2
|
||||
alt_bn128_Fq2 B = (this->Y).squared(); // B = Y1^2
|
||||
alt_bn128_Fq2 C = B.squared(); // C = B^2
|
||||
alt_bn128_Fq2 D = (this->X + B).squared() - A - C;
|
||||
D = D+D; // D = 2 * ((X1 + B)^2 - A - C)
|
||||
alt_bn128_Fq2 E = A + A + A; // E = 3 * A
|
||||
alt_bn128_Fq2 F = E.squared(); // F = E^2
|
||||
alt_bn128_Fq2 X3 = F - (D+D); // X3 = F - 2 D
|
||||
alt_bn128_Fq2 eightC = C+C;
|
||||
eightC = eightC + eightC;
|
||||
eightC = eightC + eightC;
|
||||
alt_bn128_Fq2 Y3 = E * (D - X3) - eightC; // Y3 = E * (D - X3) - 8 * C
|
||||
alt_bn128_Fq2 Y1Z1 = (this->Y)*(this->Z);
|
||||
alt_bn128_Fq2 Z3 = Y1Z1 + Y1Z1; // Z3 = 2 * Y1 * Z1
|
||||
|
||||
return alt_bn128_G2(X3, Y3, Z3);
|
||||
}
|
||||
|
||||
alt_bn128_G2 alt_bn128_G2::mul_by_q() const
|
||||
{
|
||||
return alt_bn128_G2(alt_bn128_twist_mul_by_q_X * (this->X).Frobenius_map(1),
|
||||
alt_bn128_twist_mul_by_q_Y * (this->Y).Frobenius_map(1),
|
||||
(this->Z).Frobenius_map(1));
|
||||
}
|
||||
|
||||
bool alt_bn128_G2::is_well_formed() const
|
||||
{
|
||||
if (this->is_zero())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
y^2 = x^3 + b
|
||||
|
||||
We are using Jacobian coordinates, so equation we need to check is actually
|
||||
|
||||
(y/z^3)^2 = (x/z^2)^3 + b
|
||||
y^2 / z^6 = x^3 / z^6 + b
|
||||
y^2 = x^3 + b z^6
|
||||
*/
|
||||
alt_bn128_Fq2 X2 = this->X.squared();
|
||||
alt_bn128_Fq2 Y2 = this->Y.squared();
|
||||
alt_bn128_Fq2 Z2 = this->Z.squared();
|
||||
|
||||
alt_bn128_Fq2 X3 = this->X * X2;
|
||||
alt_bn128_Fq2 Z3 = this->Z * Z2;
|
||||
alt_bn128_Fq2 Z6 = Z3.squared();
|
||||
|
||||
return (Y2 == X3 + alt_bn128_twist_coeff_b * Z6);
|
||||
}
|
||||
}
|
||||
|
||||
alt_bn128_G2 alt_bn128_G2::zero()
|
||||
{
|
||||
return G2_zero;
|
||||
}
|
||||
|
||||
alt_bn128_G2 alt_bn128_G2::one()
|
||||
{
|
||||
return G2_one;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
alt_bn128_G2 copy(g);
|
||||
copy.to_affine_coordinates();
|
||||
out << (copy.is_zero() ? 1 : 0) << OUTPUT_SEPARATOR;
|
||||
#ifdef NO_PT_COMPRESSION
|
||||
out << copy.X << OUTPUT_SEPARATOR << copy.Y;
|
||||
#else
|
||||
/* 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)
|
||||
{
|
||||
char is_zero;
|
||||
alt_bn128_Fq2 tX, tY;
|
||||
|
||||
#ifdef NO_PT_COMPRESSION
|
||||
in >> is_zero >> tX >> tY;
|
||||
is_zero -= '0';
|
||||
#else
|
||||
in.read((char*)&is_zero, 1); // this reads is_zero;
|
||||
is_zero -= '0';
|
||||
consume_OUTPUT_SEPARATOR(in);
|
||||
|
||||
unsigned char Y_lsb;
|
||||
in >> tX;
|
||||
consume_OUTPUT_SEPARATOR(in);
|
||||
in.read((char*)&Y_lsb, 1);
|
||||
Y_lsb -= '0';
|
||||
|
||||
// y = +/- sqrt(x^3 + b)
|
||||
if (!is_zero)
|
||||
{
|
||||
alt_bn128_Fq2 tX2 = tX.squared();
|
||||
alt_bn128_Fq2 tY2 = tX2 * tX + alt_bn128_twist_coeff_b;
|
||||
tY = tY2.sqrt();
|
||||
|
||||
if ((tY.c0.as_bigint().data[0] & 1) != Y_lsb)
|
||||
{
|
||||
tY = -tY;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// using projective coordinates
|
||||
if (!is_zero)
|
||||
{
|
||||
g.X = tX;
|
||||
g.Y = tY;
|
||||
g.Z = alt_bn128_Fq2::one();
|
||||
}
|
||||
else
|
||||
{
|
||||
g = alt_bn128_G2::zero();
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
template<>
|
||||
void batch_to_special_all_non_zeros<alt_bn128_G2>(std::vector<alt_bn128_G2> &vec)
|
||||
{
|
||||
std::vector<alt_bn128_Fq2> Z_vec;
|
||||
Z_vec.reserve(vec.size());
|
||||
|
||||
for (auto &el: vec)
|
||||
{
|
||||
Z_vec.emplace_back(el.Z);
|
||||
}
|
||||
batch_invert<alt_bn128_Fq2>(Z_vec);
|
||||
|
||||
const alt_bn128_Fq2 one = alt_bn128_Fq2::one();
|
||||
|
||||
for (size_t i = 0; i < vec.size(); ++i)
|
||||
{
|
||||
alt_bn128_Fq2 Z2 = Z_vec[i].squared();
|
||||
alt_bn128_Fq2 Z3 = Z_vec[i] * Z2;
|
||||
|
||||
vec[i].X = vec[i].X * Z2;
|
||||
vec[i].Y = vec[i].Y * Z3;
|
||||
vec[i].Z = one;
|
||||
}
|
||||
}
|
||||
|
||||
} // libsnark
|
||||
96
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.hpp
Normal file
96
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.hpp
Normal file
@@ -0,0 +1,96 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ALT_BN128_G2_HPP_
|
||||
#define ALT_BN128_G2_HPP_
|
||||
#include <vector>
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_init.hpp"
|
||||
#include "algebra/curves/curve_utils.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
class alt_bn128_G2;
|
||||
std::ostream& operator<<(std::ostream &, const alt_bn128_G2&);
|
||||
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;
|
||||
#endif
|
||||
static std::vector<size_t> wnaf_window_table;
|
||||
static std::vector<size_t> fixed_base_exp_window_table;
|
||||
static alt_bn128_G2 G2_zero;
|
||||
static alt_bn128_G2 G2_one;
|
||||
|
||||
typedef alt_bn128_Fq base_field;
|
||||
typedef alt_bn128_Fq2 twist_field;
|
||||
typedef alt_bn128_Fr scalar_field;
|
||||
|
||||
alt_bn128_Fq2 X, Y, Z;
|
||||
|
||||
// using Jacobian coordinates
|
||||
alt_bn128_G2();
|
||||
alt_bn128_G2(const alt_bn128_Fq2& X, const alt_bn128_Fq2& Y, const alt_bn128_Fq2& Z) : X(X), Y(Y), Z(Z) {};
|
||||
|
||||
static alt_bn128_Fq2 mul_by_b(const alt_bn128_Fq2 &elt);
|
||||
|
||||
void print() const;
|
||||
void print_coordinates() const;
|
||||
|
||||
void to_affine_coordinates();
|
||||
void to_special();
|
||||
bool is_special() const;
|
||||
|
||||
bool is_zero() const;
|
||||
|
||||
bool operator==(const alt_bn128_G2 &other) const;
|
||||
bool operator!=(const alt_bn128_G2 &other) const;
|
||||
|
||||
alt_bn128_G2 operator+(const alt_bn128_G2 &other) const;
|
||||
alt_bn128_G2 operator-() const;
|
||||
alt_bn128_G2 operator-(const alt_bn128_G2 &other) const;
|
||||
|
||||
alt_bn128_G2 add(const alt_bn128_G2 &other) const;
|
||||
alt_bn128_G2 mixed_add(const alt_bn128_G2 &other) const;
|
||||
alt_bn128_G2 dbl() const;
|
||||
alt_bn128_G2 mul_by_q() const;
|
||||
|
||||
bool is_well_formed() const;
|
||||
|
||||
static alt_bn128_G2 zero();
|
||||
static alt_bn128_G2 one();
|
||||
static alt_bn128_G2 random_element();
|
||||
|
||||
static size_t size_in_bits() { return twist_field::size_in_bits() + 1; }
|
||||
static bigint<base_field::num_limbs> base_field_char() { return base_field::field_char(); }
|
||||
static bigint<scalar_field::num_limbs> 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);
|
||||
};
|
||||
|
||||
template<mp_size_t m>
|
||||
alt_bn128_G2 operator*(const bigint<m> &lhs, const alt_bn128_G2 &rhs)
|
||||
{
|
||||
return scalar_mul<alt_bn128_G2, m>(rhs, lhs);
|
||||
}
|
||||
|
||||
template<mp_size_t m, const bigint<m>& modulus_p>
|
||||
alt_bn128_G2 operator*(const Fp_model<m,modulus_p> &lhs, const alt_bn128_G2 &rhs)
|
||||
{
|
||||
return scalar_mul<alt_bn128_G2, m>(rhs, lhs.as_bigint());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void batch_to_special_all_non_zeros(std::vector<T> &vec);
|
||||
template<>
|
||||
void batch_to_special_all_non_zeros<alt_bn128_G2>(std::vector<alt_bn128_G2> &vec);
|
||||
|
||||
} // libsnark
|
||||
#endif // ALT_BN128_G2_HPP_
|
||||
273
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.cpp
Normal file
273
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_init.cpp
Normal file
@@ -0,0 +1,273 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_init.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_g1.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_g2.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
bigint<alt_bn128_r_limbs> alt_bn128_modulus_r;
|
||||
bigint<alt_bn128_q_limbs> alt_bn128_modulus_q;
|
||||
|
||||
alt_bn128_Fq alt_bn128_coeff_b;
|
||||
alt_bn128_Fq2 alt_bn128_twist;
|
||||
alt_bn128_Fq2 alt_bn128_twist_coeff_b;
|
||||
alt_bn128_Fq alt_bn128_twist_mul_by_b_c0;
|
||||
alt_bn128_Fq alt_bn128_twist_mul_by_b_c1;
|
||||
alt_bn128_Fq2 alt_bn128_twist_mul_by_q_X;
|
||||
alt_bn128_Fq2 alt_bn128_twist_mul_by_q_Y;
|
||||
|
||||
bigint<alt_bn128_q_limbs> alt_bn128_ate_loop_count;
|
||||
bool alt_bn128_ate_is_loop_count_neg;
|
||||
bigint<12*alt_bn128_q_limbs> alt_bn128_final_exponent;
|
||||
bigint<alt_bn128_q_limbs> alt_bn128_final_exponent_z;
|
||||
bool alt_bn128_final_exponent_is_z_neg;
|
||||
|
||||
void init_alt_bn128_params()
|
||||
{
|
||||
typedef bigint<alt_bn128_r_limbs> bigint_r;
|
||||
typedef bigint<alt_bn128_q_limbs> bigint_q;
|
||||
|
||||
assert(sizeof(mp_limb_t) == 8 || sizeof(mp_limb_t) == 4); // Montgomery assumes this
|
||||
|
||||
/* parameters for scalar field Fr */
|
||||
|
||||
alt_bn128_modulus_r = bigint_r("21888242871839275222246405745257275088548364400416034343698204186575808495617");
|
||||
assert(alt_bn128_Fr::modulus_is_valid());
|
||||
if (sizeof(mp_limb_t) == 8)
|
||||
{
|
||||
alt_bn128_Fr::Rsquared = bigint_r("944936681149208446651664254269745548490766851729442924617792859073125903783");
|
||||
alt_bn128_Fr::Rcubed = bigint_r("5866548545943845227489894872040244720403868105578784105281690076696998248512");
|
||||
alt_bn128_Fr::inv = 0xc2e1f593efffffff;
|
||||
}
|
||||
if (sizeof(mp_limb_t) == 4)
|
||||
{
|
||||
alt_bn128_Fr::Rsquared = bigint_r("944936681149208446651664254269745548490766851729442924617792859073125903783");
|
||||
alt_bn128_Fr::Rcubed = bigint_r("5866548545943845227489894872040244720403868105578784105281690076696998248512");
|
||||
alt_bn128_Fr::inv = 0xefffffff;
|
||||
}
|
||||
alt_bn128_Fr::num_bits = 254;
|
||||
alt_bn128_Fr::euler = bigint_r("10944121435919637611123202872628637544274182200208017171849102093287904247808");
|
||||
alt_bn128_Fr::s = 28;
|
||||
alt_bn128_Fr::t = bigint_r("81540058820840996586704275553141814055101440848469862132140264610111");
|
||||
alt_bn128_Fr::t_minus_1_over_2 = bigint_r("40770029410420498293352137776570907027550720424234931066070132305055");
|
||||
alt_bn128_Fr::multiplicative_generator = alt_bn128_Fr("5");
|
||||
alt_bn128_Fr::root_of_unity = alt_bn128_Fr("19103219067921713944291392827692070036145651957329286315305642004821462161904");
|
||||
alt_bn128_Fr::nqr = alt_bn128_Fr("5");
|
||||
alt_bn128_Fr::nqr_to_t = alt_bn128_Fr("19103219067921713944291392827692070036145651957329286315305642004821462161904");
|
||||
|
||||
/* parameters for base field Fq */
|
||||
|
||||
alt_bn128_modulus_q = bigint_q("21888242871839275222246405745257275088696311157297823662689037894645226208583");
|
||||
assert(alt_bn128_Fq::modulus_is_valid());
|
||||
if (sizeof(mp_limb_t) == 8)
|
||||
{
|
||||
alt_bn128_Fq::Rsquared = bigint_q("3096616502983703923843567936837374451735540968419076528771170197431451843209");
|
||||
alt_bn128_Fq::Rcubed = bigint_q("14921786541159648185948152738563080959093619838510245177710943249661917737183");
|
||||
alt_bn128_Fq::inv = 0x87d20782e4866389;
|
||||
}
|
||||
if (sizeof(mp_limb_t) == 4)
|
||||
{
|
||||
alt_bn128_Fq::Rsquared = bigint_q("3096616502983703923843567936837374451735540968419076528771170197431451843209");
|
||||
alt_bn128_Fq::Rcubed = bigint_q("14921786541159648185948152738563080959093619838510245177710943249661917737183");
|
||||
alt_bn128_Fq::inv = 0xe4866389;
|
||||
}
|
||||
alt_bn128_Fq::num_bits = 254;
|
||||
alt_bn128_Fq::euler = bigint_q("10944121435919637611123202872628637544348155578648911831344518947322613104291");
|
||||
alt_bn128_Fq::s = 1;
|
||||
alt_bn128_Fq::t = bigint_q("10944121435919637611123202872628637544348155578648911831344518947322613104291");
|
||||
alt_bn128_Fq::t_minus_1_over_2 = bigint_q("5472060717959818805561601436314318772174077789324455915672259473661306552145");
|
||||
alt_bn128_Fq::multiplicative_generator = alt_bn128_Fq("3");
|
||||
alt_bn128_Fq::root_of_unity = alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582");
|
||||
alt_bn128_Fq::nqr = alt_bn128_Fq("3");
|
||||
alt_bn128_Fq::nqr_to_t = alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582");
|
||||
|
||||
/* parameters for twist field Fq2 */
|
||||
alt_bn128_Fq2::euler = bigint<2*alt_bn128_q_limbs>("239547588008311421220994022608339370399626158265550411218223901127035046843189118723920525909718935985594116157406550130918127817069793474323196511433944");
|
||||
alt_bn128_Fq2::s = 4;
|
||||
alt_bn128_Fq2::t = bigint<2*alt_bn128_q_limbs>("29943448501038927652624252826042421299953269783193801402277987640879380855398639840490065738714866998199264519675818766364765977133724184290399563929243");
|
||||
alt_bn128_Fq2::t_minus_1_over_2 = bigint<2*alt_bn128_q_limbs>("14971724250519463826312126413021210649976634891596900701138993820439690427699319920245032869357433499099632259837909383182382988566862092145199781964621");
|
||||
alt_bn128_Fq2::non_residue = alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582");
|
||||
alt_bn128_Fq2::nqr = alt_bn128_Fq2(alt_bn128_Fq("2"),alt_bn128_Fq("1"));
|
||||
alt_bn128_Fq2::nqr_to_t = alt_bn128_Fq2(alt_bn128_Fq("5033503716262624267312492558379982687175200734934877598599011485707452665730"),alt_bn128_Fq("314498342015008975724433667930697407966947188435857772134235984660852259084"));
|
||||
alt_bn128_Fq2::Frobenius_coeffs_c1[0] = alt_bn128_Fq("1");
|
||||
alt_bn128_Fq2::Frobenius_coeffs_c1[1] = alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582");
|
||||
|
||||
/* parameters for Fq6 */
|
||||
alt_bn128_Fq6::non_residue = alt_bn128_Fq2(alt_bn128_Fq("9"),alt_bn128_Fq("1"));
|
||||
alt_bn128_Fq6::Frobenius_coeffs_c1[0] = alt_bn128_Fq2(alt_bn128_Fq("1"),alt_bn128_Fq("0"));
|
||||
alt_bn128_Fq6::Frobenius_coeffs_c1[1] = alt_bn128_Fq2(alt_bn128_Fq("21575463638280843010398324269430826099269044274347216827212613867836435027261"),alt_bn128_Fq("10307601595873709700152284273816112264069230130616436755625194854815875713954"));
|
||||
alt_bn128_Fq6::Frobenius_coeffs_c1[2] = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275220042445260109153167277707414472061641714758635765020556616"),alt_bn128_Fq("0"));
|
||||
alt_bn128_Fq6::Frobenius_coeffs_c1[3] = alt_bn128_Fq2(alt_bn128_Fq("3772000881919853776433695186713858239009073593817195771773381919316419345261"),alt_bn128_Fq("2236595495967245188281701248203181795121068902605861227855261137820944008926"));
|
||||
alt_bn128_Fq6::Frobenius_coeffs_c1[4] = alt_bn128_Fq2(alt_bn128_Fq("2203960485148121921418603742825762020974279258880205651966"),alt_bn128_Fq("0"));
|
||||
alt_bn128_Fq6::Frobenius_coeffs_c1[5] = alt_bn128_Fq2(alt_bn128_Fq("18429021223477853657660792034369865839114504446431234726392080002137598044644"),alt_bn128_Fq("9344045779998320333812420223237981029506012124075525679208581902008406485703"));
|
||||
alt_bn128_Fq6::Frobenius_coeffs_c2[0] = alt_bn128_Fq2(alt_bn128_Fq("1"),alt_bn128_Fq("0"));
|
||||
alt_bn128_Fq6::Frobenius_coeffs_c2[1] = alt_bn128_Fq2(alt_bn128_Fq("2581911344467009335267311115468803099551665605076196740867805258568234346338"),alt_bn128_Fq("19937756971775647987995932169929341994314640652964949448313374472400716661030"));
|
||||
alt_bn128_Fq6::Frobenius_coeffs_c2[2] = alt_bn128_Fq2(alt_bn128_Fq("2203960485148121921418603742825762020974279258880205651966"),alt_bn128_Fq("0"));
|
||||
alt_bn128_Fq6::Frobenius_coeffs_c2[3] = alt_bn128_Fq2(alt_bn128_Fq("5324479202449903542726783395506214481928257762400643279780343368557297135718"),alt_bn128_Fq("16208900380737693084919495127334387981393726419856888799917914180988844123039"));
|
||||
alt_bn128_Fq6::Frobenius_coeffs_c2[4] = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275220042445260109153167277707414472061641714758635765020556616"),alt_bn128_Fq("0"));
|
||||
alt_bn128_Fq6::Frobenius_coeffs_c2[5] = alt_bn128_Fq2(alt_bn128_Fq("13981852324922362344252311234282257507216387789820983642040889267519694726527"),alt_bn128_Fq("7629828391165209371577384193250820201684255241773809077146787135900891633097"));
|
||||
|
||||
/* parameters for Fq12 */
|
||||
|
||||
alt_bn128_Fq12::non_residue = alt_bn128_Fq2(alt_bn128_Fq("9"),alt_bn128_Fq("1"));
|
||||
alt_bn128_Fq12::Frobenius_coeffs_c1[0] = alt_bn128_Fq2(alt_bn128_Fq("1"),alt_bn128_Fq("0"));
|
||||
alt_bn128_Fq12::Frobenius_coeffs_c1[1] = alt_bn128_Fq2(alt_bn128_Fq("8376118865763821496583973867626364092589906065868298776909617916018768340080"),alt_bn128_Fq("16469823323077808223889137241176536799009286646108169935659301613961712198316"));
|
||||
alt_bn128_Fq12::Frobenius_coeffs_c1[2] = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275220042445260109153167277707414472061641714758635765020556617"),alt_bn128_Fq("0"));
|
||||
alt_bn128_Fq12::Frobenius_coeffs_c1[3] = alt_bn128_Fq2(alt_bn128_Fq("11697423496358154304825782922584725312912383441159505038794027105778954184319"),alt_bn128_Fq("303847389135065887422783454877609941456349188919719272345083954437860409601"));
|
||||
alt_bn128_Fq12::Frobenius_coeffs_c1[4] = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275220042445260109153167277707414472061641714758635765020556616"),alt_bn128_Fq("0"));
|
||||
alt_bn128_Fq12::Frobenius_coeffs_c1[5] = alt_bn128_Fq2(alt_bn128_Fq("3321304630594332808241809054958361220322477375291206261884409189760185844239"),alt_bn128_Fq("5722266937896532885780051958958348231143373700109372999374820235121374419868"));
|
||||
alt_bn128_Fq12::Frobenius_coeffs_c1[6] = alt_bn128_Fq2(alt_bn128_Fq("21888242871839275222246405745257275088696311157297823662689037894645226208582"),alt_bn128_Fq("0"));
|
||||
alt_bn128_Fq12::Frobenius_coeffs_c1[7] = alt_bn128_Fq2(alt_bn128_Fq("13512124006075453725662431877630910996106405091429524885779419978626457868503"),alt_bn128_Fq("5418419548761466998357268504080738289687024511189653727029736280683514010267"));
|
||||
alt_bn128_Fq12::Frobenius_coeffs_c1[8] = alt_bn128_Fq2(alt_bn128_Fq("2203960485148121921418603742825762020974279258880205651966"),alt_bn128_Fq("0"));
|
||||
alt_bn128_Fq12::Frobenius_coeffs_c1[9] = alt_bn128_Fq2(alt_bn128_Fq("10190819375481120917420622822672549775783927716138318623895010788866272024264"),alt_bn128_Fq("21584395482704209334823622290379665147239961968378104390343953940207365798982"));
|
||||
alt_bn128_Fq12::Frobenius_coeffs_c1[10] = alt_bn128_Fq2(alt_bn128_Fq("2203960485148121921418603742825762020974279258880205651967"),alt_bn128_Fq("0"));
|
||||
alt_bn128_Fq12::Frobenius_coeffs_c1[11] = alt_bn128_Fq2(alt_bn128_Fq("18566938241244942414004596690298913868373833782006617400804628704885040364344"),alt_bn128_Fq("16165975933942742336466353786298926857552937457188450663314217659523851788715"));
|
||||
|
||||
/* choice of short Weierstrass curve and its twist */
|
||||
|
||||
alt_bn128_coeff_b = alt_bn128_Fq("3");
|
||||
alt_bn128_twist = alt_bn128_Fq2(alt_bn128_Fq("9"), alt_bn128_Fq("1"));
|
||||
alt_bn128_twist_coeff_b = alt_bn128_coeff_b * alt_bn128_twist.inverse();
|
||||
alt_bn128_twist_mul_by_b_c0 = alt_bn128_coeff_b * alt_bn128_Fq2::non_residue;
|
||||
alt_bn128_twist_mul_by_b_c1 = alt_bn128_coeff_b * alt_bn128_Fq2::non_residue;
|
||||
alt_bn128_twist_mul_by_q_X = alt_bn128_Fq2(alt_bn128_Fq("21575463638280843010398324269430826099269044274347216827212613867836435027261"),
|
||||
alt_bn128_Fq("10307601595873709700152284273816112264069230130616436755625194854815875713954"));
|
||||
alt_bn128_twist_mul_by_q_Y = alt_bn128_Fq2(alt_bn128_Fq("2821565182194536844548159561693502659359617185244120367078079554186484126554"),
|
||||
alt_bn128_Fq("3505843767911556378687030309984248845540243509899259641013678093033130930403"));
|
||||
|
||||
/* choice of group G1 */
|
||||
alt_bn128_G1::G1_zero = alt_bn128_G1(alt_bn128_Fq::zero(),
|
||||
alt_bn128_Fq::one(),
|
||||
alt_bn128_Fq::zero());
|
||||
alt_bn128_G1::G1_one = alt_bn128_G1(alt_bn128_Fq("1"),
|
||||
alt_bn128_Fq("2"),
|
||||
alt_bn128_Fq::one());
|
||||
alt_bn128_G1::wnaf_window_table.push_back(11);
|
||||
alt_bn128_G1::wnaf_window_table.push_back(24);
|
||||
alt_bn128_G1::wnaf_window_table.push_back(60);
|
||||
alt_bn128_G1::wnaf_window_table.push_back(127);
|
||||
|
||||
alt_bn128_G1::fixed_base_exp_window_table.resize(0);
|
||||
// window 1 is unbeaten in [-inf, 4.99]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(1);
|
||||
// window 2 is unbeaten in [4.99, 10.99]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(5);
|
||||
// window 3 is unbeaten in [10.99, 32.29]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(11);
|
||||
// window 4 is unbeaten in [32.29, 55.23]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(32);
|
||||
// window 5 is unbeaten in [55.23, 162.03]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(55);
|
||||
// window 6 is unbeaten in [162.03, 360.15]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(162);
|
||||
// window 7 is unbeaten in [360.15, 815.44]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(360);
|
||||
// window 8 is unbeaten in [815.44, 2373.07]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(815);
|
||||
// window 9 is unbeaten in [2373.07, 6977.75]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(2373);
|
||||
// window 10 is unbeaten in [6977.75, 7122.23]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(6978);
|
||||
// window 11 is unbeaten in [7122.23, 57818.46]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(7122);
|
||||
// window 12 is never the best
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(0);
|
||||
// window 13 is unbeaten in [57818.46, 169679.14]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(57818);
|
||||
// window 14 is never the best
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(0);
|
||||
// window 15 is unbeaten in [169679.14, 439758.91]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(169679);
|
||||
// window 16 is unbeaten in [439758.91, 936073.41]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(439759);
|
||||
// window 17 is unbeaten in [936073.41, 4666554.74]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(936073);
|
||||
// window 18 is never the best
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(0);
|
||||
// window 19 is unbeaten in [4666554.74, 7580404.42]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(4666555);
|
||||
// window 20 is unbeaten in [7580404.42, 34552892.20]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(7580404);
|
||||
// window 21 is never the best
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(0);
|
||||
// window 22 is unbeaten in [34552892.20, inf]
|
||||
alt_bn128_G1::fixed_base_exp_window_table.push_back(34552892);
|
||||
|
||||
/* choice of group G2 */
|
||||
|
||||
alt_bn128_G2::G2_zero = alt_bn128_G2(alt_bn128_Fq2::zero(),
|
||||
alt_bn128_Fq2::one(),
|
||||
alt_bn128_Fq2::zero());
|
||||
|
||||
alt_bn128_G2::G2_one = alt_bn128_G2(alt_bn128_Fq2(alt_bn128_Fq("10857046999023057135944570762232829481370756359578518086990519993285655852781"),
|
||||
alt_bn128_Fq("11559732032986387107991004021392285783925812861821192530917403151452391805634")),
|
||||
alt_bn128_Fq2(alt_bn128_Fq("8495653923123431417604973247489272438418190587263600148770280649306958101930"),
|
||||
alt_bn128_Fq("4082367875863433681332203403145435568316851327593401208105741076214120093531")),
|
||||
alt_bn128_Fq2::one());
|
||||
alt_bn128_G2::wnaf_window_table.push_back(5);
|
||||
alt_bn128_G2::wnaf_window_table.push_back(15);
|
||||
alt_bn128_G2::wnaf_window_table.push_back(39);
|
||||
alt_bn128_G2::wnaf_window_table.push_back(109);
|
||||
|
||||
alt_bn128_G2::fixed_base_exp_window_table.resize(0);
|
||||
// window 1 is unbeaten in [-inf, 5.10]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(1);
|
||||
// window 2 is unbeaten in [5.10, 10.43]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(5);
|
||||
// window 3 is unbeaten in [10.43, 25.28]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(10);
|
||||
// window 4 is unbeaten in [25.28, 59.00]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(25);
|
||||
// window 5 is unbeaten in [59.00, 154.03]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(59);
|
||||
// window 6 is unbeaten in [154.03, 334.25]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(154);
|
||||
// window 7 is unbeaten in [334.25, 742.58]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(334);
|
||||
// window 8 is unbeaten in [742.58, 2034.40]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(743);
|
||||
// window 9 is unbeaten in [2034.40, 4987.56]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(2034);
|
||||
// window 10 is unbeaten in [4987.56, 8888.27]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(4988);
|
||||
// window 11 is unbeaten in [8888.27, 26271.13]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(8888);
|
||||
// window 12 is unbeaten in [26271.13, 39768.20]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(26271);
|
||||
// window 13 is unbeaten in [39768.20, 106275.75]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(39768);
|
||||
// window 14 is unbeaten in [106275.75, 141703.40]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(106276);
|
||||
// window 15 is unbeaten in [141703.40, 462422.97]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(141703);
|
||||
// window 16 is unbeaten in [462422.97, 926871.84]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(462423);
|
||||
// window 17 is unbeaten in [926871.84, 4873049.17]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(926872);
|
||||
// window 18 is never the best
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(0);
|
||||
// window 19 is unbeaten in [4873049.17, 5706707.88]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(4873049);
|
||||
// window 20 is unbeaten in [5706707.88, 31673814.95]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(5706708);
|
||||
// window 21 is never the best
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(0);
|
||||
// window 22 is unbeaten in [31673814.95, inf]
|
||||
alt_bn128_G2::fixed_base_exp_window_table.push_back(31673815);
|
||||
|
||||
/* pairing parameters */
|
||||
|
||||
alt_bn128_ate_loop_count = bigint_q("29793968203157093288");
|
||||
alt_bn128_ate_is_loop_count_neg = false;
|
||||
alt_bn128_final_exponent = bigint<12*alt_bn128_q_limbs>("552484233613224096312617126783173147097382103762957654188882734314196910839907541213974502761540629817009608548654680343627701153829446747810907373256841551006201639677726139946029199968412598804882391702273019083653272047566316584365559776493027495458238373902875937659943504873220554161550525926302303331747463515644711876653177129578303191095900909191624817826566688241804408081892785725967931714097716709526092261278071952560171111444072049229123565057483750161460024353346284167282452756217662335528813519139808291170539072125381230815729071544861602750936964829313608137325426383735122175229541155376346436093930287402089517426973178917569713384748081827255472576937471496195752727188261435633271238710131736096299798168852925540549342330775279877006784354801422249722573783561685179618816480037695005515426162362431072245638324744480");
|
||||
alt_bn128_final_exponent_z = bigint_q("4965661367192848881");
|
||||
alt_bn128_final_exponent_is_z_neg = false;
|
||||
|
||||
}
|
||||
} // libsnark
|
||||
@@ -0,0 +1,57 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ALT_BN128_INIT_HPP_
|
||||
#define ALT_BN128_INIT_HPP_
|
||||
#include "algebra/curves/public_params.hpp"
|
||||
#include "algebra/fields/fp.hpp"
|
||||
#include "algebra/fields/fp2.hpp"
|
||||
#include "algebra/fields/fp6_3over2.hpp"
|
||||
#include "algebra/fields/fp12_2over3over2.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
const mp_size_t alt_bn128_r_bitcount = 254;
|
||||
const mp_size_t alt_bn128_q_bitcount = 254;
|
||||
|
||||
const mp_size_t alt_bn128_r_limbs = (alt_bn128_r_bitcount+GMP_NUMB_BITS-1)/GMP_NUMB_BITS;
|
||||
const mp_size_t alt_bn128_q_limbs = (alt_bn128_q_bitcount+GMP_NUMB_BITS-1)/GMP_NUMB_BITS;
|
||||
|
||||
extern bigint<alt_bn128_r_limbs> alt_bn128_modulus_r;
|
||||
extern bigint<alt_bn128_q_limbs> alt_bn128_modulus_q;
|
||||
|
||||
typedef Fp_model<alt_bn128_r_limbs, alt_bn128_modulus_r> alt_bn128_Fr;
|
||||
typedef Fp_model<alt_bn128_q_limbs, alt_bn128_modulus_q> alt_bn128_Fq;
|
||||
typedef Fp2_model<alt_bn128_q_limbs, alt_bn128_modulus_q> alt_bn128_Fq2;
|
||||
typedef Fp6_3over2_model<alt_bn128_q_limbs, alt_bn128_modulus_q> alt_bn128_Fq6;
|
||||
typedef Fp12_2over3over2_model<alt_bn128_q_limbs, alt_bn128_modulus_q> alt_bn128_Fq12;
|
||||
typedef alt_bn128_Fq12 alt_bn128_GT;
|
||||
|
||||
// parameters for Barreto--Naehrig curve E/Fq : y^2 = x^3 + b
|
||||
extern alt_bn128_Fq alt_bn128_coeff_b;
|
||||
// parameters for twisted Barreto--Naehrig curve E'/Fq2 : y^2 = x^3 + b/xi
|
||||
extern alt_bn128_Fq2 alt_bn128_twist;
|
||||
extern alt_bn128_Fq2 alt_bn128_twist_coeff_b;
|
||||
extern alt_bn128_Fq alt_bn128_twist_mul_by_b_c0;
|
||||
extern alt_bn128_Fq alt_bn128_twist_mul_by_b_c1;
|
||||
extern alt_bn128_Fq2 alt_bn128_twist_mul_by_q_X;
|
||||
extern alt_bn128_Fq2 alt_bn128_twist_mul_by_q_Y;
|
||||
|
||||
// parameters for pairing
|
||||
extern bigint<alt_bn128_q_limbs> alt_bn128_ate_loop_count;
|
||||
extern bool alt_bn128_ate_is_loop_count_neg;
|
||||
extern bigint<12*alt_bn128_q_limbs> alt_bn128_final_exponent;
|
||||
extern bigint<alt_bn128_q_limbs> alt_bn128_final_exponent_z;
|
||||
extern bool alt_bn128_final_exponent_is_z_neg;
|
||||
|
||||
void init_alt_bn128_params();
|
||||
|
||||
class alt_bn128_G1;
|
||||
class alt_bn128_G2;
|
||||
|
||||
} // libsnark
|
||||
#endif // ALT_BN128_INIT_HPP_
|
||||
@@ -0,0 +1,547 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_pairing.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_init.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_g1.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_g2.hpp"
|
||||
#include <cassert>
|
||||
#include "common/profiling.hpp"
|
||||
#include "common/assert_except.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
bool alt_bn128_ate_G1_precomp::operator==(const alt_bn128_ate_G1_precomp &other) const
|
||||
{
|
||||
return (this->PX == other.PX &&
|
||||
this->PY == other.PY);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream &out, const alt_bn128_ate_G1_precomp &prec_P)
|
||||
{
|
||||
out << prec_P.PX << OUTPUT_SEPARATOR << prec_P.PY;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream &in, alt_bn128_ate_G1_precomp &prec_P)
|
||||
{
|
||||
in >> prec_P.PX;
|
||||
consume_OUTPUT_SEPARATOR(in);
|
||||
in >> prec_P.PY;
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
bool alt_bn128_ate_ell_coeffs::operator==(const alt_bn128_ate_ell_coeffs &other) const
|
||||
{
|
||||
return (this->ell_0 == other.ell_0 &&
|
||||
this->ell_VW == other.ell_VW &&
|
||||
this->ell_VV == other.ell_VV);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream &out, const alt_bn128_ate_ell_coeffs &c)
|
||||
{
|
||||
out << c.ell_0 << OUTPUT_SEPARATOR << c.ell_VW << OUTPUT_SEPARATOR << c.ell_VV;
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream &in, alt_bn128_ate_ell_coeffs &c)
|
||||
{
|
||||
in >> c.ell_0;
|
||||
consume_OUTPUT_SEPARATOR(in);
|
||||
in >> c.ell_VW;
|
||||
consume_OUTPUT_SEPARATOR(in);
|
||||
in >> c.ell_VV;
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
bool alt_bn128_ate_G2_precomp::operator==(const alt_bn128_ate_G2_precomp &other) const
|
||||
{
|
||||
return (this->QX == other.QX &&
|
||||
this->QY == other.QY &&
|
||||
this->coeffs == other.coeffs);
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const alt_bn128_ate_G2_precomp &prec_Q)
|
||||
{
|
||||
out << prec_Q.QX << OUTPUT_SEPARATOR << prec_Q.QY << "\n";
|
||||
out << prec_Q.coeffs.size() << "\n";
|
||||
for (const alt_bn128_ate_ell_coeffs &c : prec_Q.coeffs)
|
||||
{
|
||||
out << c << OUTPUT_NEWLINE;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::istream& operator>>(std::istream& in, alt_bn128_ate_G2_precomp &prec_Q)
|
||||
{
|
||||
in >> prec_Q.QX;
|
||||
consume_OUTPUT_SEPARATOR(in);
|
||||
in >> prec_Q.QY;
|
||||
consume_newline(in);
|
||||
|
||||
prec_Q.coeffs.clear();
|
||||
size_t s;
|
||||
in >> s;
|
||||
|
||||
consume_newline(in);
|
||||
|
||||
prec_Q.coeffs.reserve(s);
|
||||
|
||||
for (size_t i = 0; i < s; ++i)
|
||||
{
|
||||
alt_bn128_ate_ell_coeffs c;
|
||||
in >> c;
|
||||
consume_OUTPUT_NEWLINE(in);
|
||||
prec_Q.coeffs.emplace_back(c);
|
||||
}
|
||||
|
||||
return in;
|
||||
}
|
||||
|
||||
/* final exponentiations */
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_final_exponentiation_first_chunk(const alt_bn128_Fq12 &elt)
|
||||
{
|
||||
enter_block("Call to alt_bn128_final_exponentiation_first_chunk");
|
||||
|
||||
/*
|
||||
Computes result = elt^((q^6-1)*(q^2+1)).
|
||||
Follows, e.g., Beuchat et al page 9, by computing result as follows:
|
||||
elt^((q^6-1)*(q^2+1)) = (conj(elt) * elt^(-1))^(q^2+1)
|
||||
More precisely:
|
||||
A = conj(elt)
|
||||
B = elt.inverse()
|
||||
C = A * B
|
||||
D = C.Frobenius_map(2)
|
||||
result = D * C
|
||||
*/
|
||||
|
||||
const alt_bn128_Fq12 A = alt_bn128_Fq12(elt.c0,-elt.c1);
|
||||
const alt_bn128_Fq12 B = elt.inverse();
|
||||
const alt_bn128_Fq12 C = A * B;
|
||||
const alt_bn128_Fq12 D = C.Frobenius_map(2);
|
||||
const alt_bn128_Fq12 result = D * C;
|
||||
|
||||
leave_block("Call to alt_bn128_final_exponentiation_first_chunk");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_exp_by_neg_z(const alt_bn128_Fq12 &elt)
|
||||
{
|
||||
enter_block("Call to alt_bn128_exp_by_neg_z");
|
||||
|
||||
alt_bn128_Fq12 result = elt.cyclotomic_exp(alt_bn128_final_exponent_z);
|
||||
if (!alt_bn128_final_exponent_is_z_neg)
|
||||
{
|
||||
result = result.unitary_inverse();
|
||||
}
|
||||
|
||||
leave_block("Call to alt_bn128_exp_by_neg_z");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_final_exponentiation_last_chunk(const alt_bn128_Fq12 &elt)
|
||||
{
|
||||
enter_block("Call to alt_bn128_final_exponentiation_last_chunk");
|
||||
|
||||
/*
|
||||
Follows Laura Fuentes-Castaneda et al. "Faster hashing to G2"
|
||||
by computing:
|
||||
|
||||
result = elt^(q^3 * (12*z^3 + 6z^2 + 4z - 1) +
|
||||
q^2 * (12*z^3 + 6z^2 + 6z) +
|
||||
q * (12*z^3 + 6z^2 + 4z) +
|
||||
1 * (12*z^3 + 12z^2 + 6z + 1))
|
||||
which equals
|
||||
|
||||
result = elt^( 2z * ( 6z^2 + 3z + 1 ) * (q^4 - q^2 + 1)/r ).
|
||||
|
||||
Using the following addition chain:
|
||||
|
||||
A = exp_by_neg_z(elt) // = elt^(-z)
|
||||
B = A^2 // = elt^(-2*z)
|
||||
C = B^2 // = elt^(-4*z)
|
||||
D = C * B // = elt^(-6*z)
|
||||
E = exp_by_neg_z(D) // = elt^(6*z^2)
|
||||
F = E^2 // = elt^(12*z^2)
|
||||
G = epx_by_neg_z(F) // = elt^(-12*z^3)
|
||||
H = conj(D) // = elt^(6*z)
|
||||
I = conj(G) // = elt^(12*z^3)
|
||||
J = I * E // = elt^(12*z^3 + 6*z^2)
|
||||
K = J * H // = elt^(12*z^3 + 6*z^2 + 6*z)
|
||||
L = K * B // = elt^(12*z^3 + 6*z^2 + 4*z)
|
||||
M = K * E // = elt^(12*z^3 + 12*z^2 + 6*z)
|
||||
N = M * elt // = elt^(12*z^3 + 12*z^2 + 6*z + 1)
|
||||
O = L.Frobenius_map(1) // = elt^(q*(12*z^3 + 6*z^2 + 4*z))
|
||||
P = O * N // = elt^(q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1))
|
||||
Q = K.Frobenius_map(2) // = elt^(q^2 * (12*z^3 + 6*z^2 + 6*z))
|
||||
R = Q * P // = elt^(q^2 * (12*z^3 + 6*z^2 + 6*z) + q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1))
|
||||
S = conj(elt) // = elt^(-1)
|
||||
T = S * L // = elt^(12*z^3 + 6*z^2 + 4*z - 1)
|
||||
U = T.Frobenius_map(3) // = elt^(q^3(12*z^3 + 6*z^2 + 4*z - 1))
|
||||
V = U * R // = elt^(q^3(12*z^3 + 6*z^2 + 4*z - 1) + q^2 * (12*z^3 + 6*z^2 + 6*z) + q*(12*z^3 + 6*z^2 + 4*z) * (12*z^3 + 12*z^2 + 6*z + 1))
|
||||
result = V
|
||||
|
||||
*/
|
||||
|
||||
const alt_bn128_Fq12 A = alt_bn128_exp_by_neg_z(elt);
|
||||
const alt_bn128_Fq12 B = A.cyclotomic_squared();
|
||||
const alt_bn128_Fq12 C = B.cyclotomic_squared();
|
||||
const alt_bn128_Fq12 D = C * B;
|
||||
const alt_bn128_Fq12 E = alt_bn128_exp_by_neg_z(D);
|
||||
const alt_bn128_Fq12 F = E.cyclotomic_squared();
|
||||
const alt_bn128_Fq12 G = alt_bn128_exp_by_neg_z(F);
|
||||
const alt_bn128_Fq12 H = D.unitary_inverse();
|
||||
const alt_bn128_Fq12 I = G.unitary_inverse();
|
||||
const alt_bn128_Fq12 J = I * E;
|
||||
const alt_bn128_Fq12 K = J * H;
|
||||
const alt_bn128_Fq12 L = K * B;
|
||||
const alt_bn128_Fq12 M = K * E;
|
||||
const alt_bn128_Fq12 N = M * elt;
|
||||
const alt_bn128_Fq12 O = L.Frobenius_map(1);
|
||||
const alt_bn128_Fq12 P = O * N;
|
||||
const alt_bn128_Fq12 Q = K.Frobenius_map(2);
|
||||
const alt_bn128_Fq12 R = Q * P;
|
||||
const alt_bn128_Fq12 S = elt.unitary_inverse();
|
||||
const alt_bn128_Fq12 T = S * L;
|
||||
const alt_bn128_Fq12 U = T.Frobenius_map(3);
|
||||
const alt_bn128_Fq12 V = U * R;
|
||||
|
||||
const alt_bn128_Fq12 result = V;
|
||||
|
||||
leave_block("Call to alt_bn128_final_exponentiation_last_chunk");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
alt_bn128_GT alt_bn128_final_exponentiation(const alt_bn128_Fq12 &elt)
|
||||
{
|
||||
enter_block("Call to alt_bn128_final_exponentiation");
|
||||
/* OLD naive version:
|
||||
alt_bn128_GT result = elt^alt_bn128_final_exponent;
|
||||
*/
|
||||
alt_bn128_Fq12 A = alt_bn128_final_exponentiation_first_chunk(elt);
|
||||
alt_bn128_GT result = alt_bn128_final_exponentiation_last_chunk(A);
|
||||
|
||||
leave_block("Call to alt_bn128_final_exponentiation");
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ate pairing */
|
||||
|
||||
void doubling_step_for_flipped_miller_loop(const alt_bn128_Fq two_inv,
|
||||
alt_bn128_G2 ¤t,
|
||||
alt_bn128_ate_ell_coeffs &c)
|
||||
{
|
||||
const alt_bn128_Fq2 X = current.X, Y = current.Y, Z = current.Z;
|
||||
|
||||
const alt_bn128_Fq2 A = two_inv * (X * Y); // A = X1 * Y1 / 2
|
||||
const alt_bn128_Fq2 B = Y.squared(); // B = Y1^2
|
||||
const alt_bn128_Fq2 C = Z.squared(); // C = Z1^2
|
||||
const alt_bn128_Fq2 D = C+C+C; // D = 3 * C
|
||||
const alt_bn128_Fq2 E = alt_bn128_twist_coeff_b * D; // E = twist_b * D
|
||||
const alt_bn128_Fq2 F = E+E+E; // F = 3 * E
|
||||
const alt_bn128_Fq2 G = two_inv * (B+F); // G = (B+F)/2
|
||||
const alt_bn128_Fq2 H = (Y+Z).squared() - (B+C); // H = (Y1+Z1)^2-(B+C)
|
||||
const alt_bn128_Fq2 I = E-B; // I = E-B
|
||||
const alt_bn128_Fq2 J = X.squared(); // J = X1^2
|
||||
const alt_bn128_Fq2 E_squared = E.squared(); // E_squared = E^2
|
||||
|
||||
current.X = A * (B-F); // X3 = A * (B-F)
|
||||
current.Y = G.squared() - (E_squared+E_squared+E_squared); // Y3 = G^2 - 3*E^2
|
||||
current.Z = B * H; // Z3 = B * H
|
||||
c.ell_0 = alt_bn128_twist * I; // ell_0 = xi * I
|
||||
c.ell_VW = -H; // ell_VW = - H (later: * yP)
|
||||
c.ell_VV = J+J+J; // ell_VV = 3*J (later: * xP)
|
||||
}
|
||||
|
||||
void mixed_addition_step_for_flipped_miller_loop(const alt_bn128_G2 base,
|
||||
alt_bn128_G2 ¤t,
|
||||
alt_bn128_ate_ell_coeffs &c)
|
||||
{
|
||||
const alt_bn128_Fq2 X1 = current.X, Y1 = current.Y, Z1 = current.Z;
|
||||
const alt_bn128_Fq2 &x2 = base.X, &y2 = base.Y;
|
||||
|
||||
const alt_bn128_Fq2 D = X1 - x2 * Z1; // D = X1 - X2*Z1
|
||||
const alt_bn128_Fq2 E = Y1 - y2 * Z1; // E = Y1 - Y2*Z1
|
||||
const alt_bn128_Fq2 F = D.squared(); // F = D^2
|
||||
const alt_bn128_Fq2 G = E.squared(); // G = E^2
|
||||
const alt_bn128_Fq2 H = D*F; // H = D*F
|
||||
const alt_bn128_Fq2 I = X1 * F; // I = X1 * F
|
||||
const alt_bn128_Fq2 J = H + Z1*G - (I+I); // J = H + Z1*G - (I+I)
|
||||
|
||||
current.X = D * J; // X3 = D*J
|
||||
current.Y = E * (I-J)-(H * Y1); // Y3 = E*(I-J)-(H*Y1)
|
||||
current.Z = Z1 * H; // Z3 = Z1*H
|
||||
c.ell_0 = alt_bn128_twist * (E * x2 - D * y2); // ell_0 = xi * (E * X2 - D * Y2)
|
||||
c.ell_VV = - E; // ell_VV = - E (later: * xP)
|
||||
c.ell_VW = D; // ell_VW = D (later: * yP )
|
||||
}
|
||||
|
||||
alt_bn128_ate_G1_precomp alt_bn128_ate_precompute_G1(const alt_bn128_G1& P)
|
||||
{
|
||||
enter_block("Call to alt_bn128_ate_precompute_G1");
|
||||
|
||||
alt_bn128_G1 Pcopy = P;
|
||||
Pcopy.to_affine_coordinates();
|
||||
|
||||
alt_bn128_ate_G1_precomp result;
|
||||
result.PX = Pcopy.X;
|
||||
result.PY = Pcopy.Y;
|
||||
|
||||
leave_block("Call to alt_bn128_ate_precompute_G1");
|
||||
return result;
|
||||
}
|
||||
|
||||
alt_bn128_ate_G2_precomp alt_bn128_ate_precompute_G2(const alt_bn128_G2& Q)
|
||||
{
|
||||
enter_block("Call to alt_bn128_ate_precompute_G2");
|
||||
|
||||
alt_bn128_G2 Qcopy(Q);
|
||||
Qcopy.to_affine_coordinates();
|
||||
|
||||
alt_bn128_Fq two_inv = (alt_bn128_Fq("2").inverse()); // could add to global params if needed
|
||||
|
||||
alt_bn128_ate_G2_precomp result;
|
||||
result.QX = Qcopy.X;
|
||||
result.QY = Qcopy.Y;
|
||||
|
||||
alt_bn128_G2 R;
|
||||
R.X = Qcopy.X;
|
||||
R.Y = Qcopy.Y;
|
||||
R.Z = alt_bn128_Fq2::one();
|
||||
|
||||
const bigint<alt_bn128_Fr::num_limbs> &loop_count = alt_bn128_ate_loop_count;
|
||||
bool found_one = false;
|
||||
alt_bn128_ate_ell_coeffs c;
|
||||
|
||||
for (long i = loop_count.max_bits(); i >= 0; --i)
|
||||
{
|
||||
const bool bit = loop_count.test_bit(i);
|
||||
if (!found_one)
|
||||
{
|
||||
/* this skips the MSB itself */
|
||||
found_one |= bit;
|
||||
continue;
|
||||
}
|
||||
|
||||
doubling_step_for_flipped_miller_loop(two_inv, R, c);
|
||||
result.coeffs.push_back(c);
|
||||
|
||||
if (bit)
|
||||
{
|
||||
mixed_addition_step_for_flipped_miller_loop(Qcopy, R, c);
|
||||
result.coeffs.push_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
alt_bn128_G2 Q1 = Qcopy.mul_by_q();
|
||||
assert_except(Q1.Z == alt_bn128_Fq2::one());
|
||||
alt_bn128_G2 Q2 = Q1.mul_by_q();
|
||||
assert_except(Q2.Z == alt_bn128_Fq2::one());
|
||||
|
||||
if (alt_bn128_ate_is_loop_count_neg)
|
||||
{
|
||||
R.Y = - R.Y;
|
||||
}
|
||||
Q2.Y = - Q2.Y;
|
||||
|
||||
mixed_addition_step_for_flipped_miller_loop(Q1, R, c);
|
||||
result.coeffs.push_back(c);
|
||||
|
||||
mixed_addition_step_for_flipped_miller_loop(Q2, R, c);
|
||||
result.coeffs.push_back(c);
|
||||
|
||||
leave_block("Call to alt_bn128_ate_precompute_G2");
|
||||
return result;
|
||||
}
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_ate_miller_loop(const alt_bn128_ate_G1_precomp &prec_P,
|
||||
const alt_bn128_ate_G2_precomp &prec_Q)
|
||||
{
|
||||
enter_block("Call to alt_bn128_ate_miller_loop");
|
||||
|
||||
alt_bn128_Fq12 f = alt_bn128_Fq12::one();
|
||||
|
||||
bool found_one = false;
|
||||
size_t idx = 0;
|
||||
|
||||
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)
|
||||
{
|
||||
const bool bit = loop_count.test_bit(i);
|
||||
if (!found_one)
|
||||
{
|
||||
/* this skips the MSB itself */
|
||||
found_one |= bit;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* code below gets executed for all bits (EXCEPT the MSB itself) of
|
||||
alt_bn128_param_p (skipping leading zeros) in MSB to LSB
|
||||
order */
|
||||
|
||||
c = prec_Q.coeffs[idx++];
|
||||
f = f.squared();
|
||||
f = f.mul_by_024(c.ell_0, prec_P.PY * c.ell_VW, prec_P.PX * c.ell_VV);
|
||||
|
||||
if (bit)
|
||||
{
|
||||
c = prec_Q.coeffs[idx++];
|
||||
f = f.mul_by_024(c.ell_0, prec_P.PY * c.ell_VW, prec_P.PX * c.ell_VV);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (alt_bn128_ate_is_loop_count_neg)
|
||||
{
|
||||
f = f.inverse();
|
||||
}
|
||||
|
||||
c = prec_Q.coeffs[idx++];
|
||||
f = f.mul_by_024(c.ell_0,prec_P.PY * c.ell_VW,prec_P.PX * c.ell_VV);
|
||||
|
||||
c = prec_Q.coeffs[idx++];
|
||||
f = f.mul_by_024(c.ell_0,prec_P.PY * c.ell_VW,prec_P.PX * c.ell_VV);
|
||||
|
||||
leave_block("Call to alt_bn128_ate_miller_loop");
|
||||
return f;
|
||||
}
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp &prec_P1,
|
||||
const alt_bn128_ate_G2_precomp &prec_Q1,
|
||||
const alt_bn128_ate_G1_precomp &prec_P2,
|
||||
const alt_bn128_ate_G2_precomp &prec_Q2)
|
||||
{
|
||||
enter_block("Call to alt_bn128_ate_double_miller_loop");
|
||||
|
||||
alt_bn128_Fq12 f = alt_bn128_Fq12::one();
|
||||
|
||||
bool found_one = false;
|
||||
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)
|
||||
{
|
||||
const bool bit = loop_count.test_bit(i);
|
||||
if (!found_one)
|
||||
{
|
||||
/* this skips the MSB itself */
|
||||
found_one |= bit;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* code below gets executed for all bits (EXCEPT the MSB itself) of
|
||||
alt_bn128_param_p (skipping leading zeros) in MSB to LSB
|
||||
order */
|
||||
|
||||
alt_bn128_ate_ell_coeffs c1 = prec_Q1.coeffs[idx];
|
||||
alt_bn128_ate_ell_coeffs c2 = prec_Q2.coeffs[idx];
|
||||
++idx;
|
||||
|
||||
f = f.squared();
|
||||
|
||||
f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV);
|
||||
f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV);
|
||||
|
||||
if (bit)
|
||||
{
|
||||
alt_bn128_ate_ell_coeffs c1 = prec_Q1.coeffs[idx];
|
||||
alt_bn128_ate_ell_coeffs c2 = prec_Q2.coeffs[idx];
|
||||
++idx;
|
||||
|
||||
f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV);
|
||||
f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV);
|
||||
}
|
||||
}
|
||||
|
||||
if (alt_bn128_ate_is_loop_count_neg)
|
||||
{
|
||||
f = f.inverse();
|
||||
}
|
||||
|
||||
alt_bn128_ate_ell_coeffs c1 = prec_Q1.coeffs[idx];
|
||||
alt_bn128_ate_ell_coeffs c2 = prec_Q2.coeffs[idx];
|
||||
++idx;
|
||||
f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV);
|
||||
f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV);
|
||||
|
||||
c1 = prec_Q1.coeffs[idx];
|
||||
c2 = prec_Q2.coeffs[idx];
|
||||
++idx;
|
||||
f = f.mul_by_024(c1.ell_0, prec_P1.PY * c1.ell_VW, prec_P1.PX * c1.ell_VV);
|
||||
f = f.mul_by_024(c2.ell_0, prec_P2.PY * c2.ell_VW, prec_P2.PX * c2.ell_VV);
|
||||
|
||||
leave_block("Call to alt_bn128_ate_double_miller_loop");
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_ate_pairing(const alt_bn128_G1& P, const alt_bn128_G2 &Q)
|
||||
{
|
||||
enter_block("Call to alt_bn128_ate_pairing");
|
||||
alt_bn128_ate_G1_precomp prec_P = alt_bn128_ate_precompute_G1(P);
|
||||
alt_bn128_ate_G2_precomp prec_Q = alt_bn128_ate_precompute_G2(Q);
|
||||
alt_bn128_Fq12 result = alt_bn128_ate_miller_loop(prec_P, prec_Q);
|
||||
leave_block("Call to alt_bn128_ate_pairing");
|
||||
return result;
|
||||
}
|
||||
|
||||
alt_bn128_GT alt_bn128_ate_reduced_pairing(const alt_bn128_G1 &P, const alt_bn128_G2 &Q)
|
||||
{
|
||||
enter_block("Call to alt_bn128_ate_reduced_pairing");
|
||||
const alt_bn128_Fq12 f = alt_bn128_ate_pairing(P, Q);
|
||||
const alt_bn128_GT result = alt_bn128_final_exponentiation(f);
|
||||
leave_block("Call to alt_bn128_ate_reduced_pairing");
|
||||
return result;
|
||||
}
|
||||
|
||||
/* choice of pairing */
|
||||
|
||||
alt_bn128_G1_precomp alt_bn128_precompute_G1(const alt_bn128_G1& P)
|
||||
{
|
||||
return alt_bn128_ate_precompute_G1(P);
|
||||
}
|
||||
|
||||
alt_bn128_G2_precomp alt_bn128_precompute_G2(const alt_bn128_G2& Q)
|
||||
{
|
||||
return alt_bn128_ate_precompute_G2(Q);
|
||||
}
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_miller_loop(const alt_bn128_G1_precomp &prec_P,
|
||||
const alt_bn128_G2_precomp &prec_Q)
|
||||
{
|
||||
return alt_bn128_ate_miller_loop(prec_P, prec_Q);
|
||||
}
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_double_miller_loop(const alt_bn128_G1_precomp &prec_P1,
|
||||
const alt_bn128_G2_precomp &prec_Q1,
|
||||
const alt_bn128_G1_precomp &prec_P2,
|
||||
const alt_bn128_G2_precomp &prec_Q2)
|
||||
{
|
||||
return alt_bn128_ate_double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2);
|
||||
}
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_pairing(const alt_bn128_G1& P,
|
||||
const alt_bn128_G2 &Q)
|
||||
{
|
||||
return alt_bn128_ate_pairing(P, Q);
|
||||
}
|
||||
|
||||
alt_bn128_GT alt_bn128_reduced_pairing(const alt_bn128_G1 &P,
|
||||
const alt_bn128_G2 &Q)
|
||||
{
|
||||
return alt_bn128_ate_reduced_pairing(P, Q);
|
||||
}
|
||||
} // libsnark
|
||||
@@ -0,0 +1,92 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ALT_BN128_PAIRING_HPP_
|
||||
#define ALT_BN128_PAIRING_HPP_
|
||||
#include <vector>
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_init.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
/* final exponentiation */
|
||||
|
||||
alt_bn128_GT alt_bn128_final_exponentiation(const alt_bn128_Fq12 &elt);
|
||||
|
||||
/* ate pairing */
|
||||
|
||||
struct alt_bn128_ate_G1_precomp {
|
||||
alt_bn128_Fq PX;
|
||||
alt_bn128_Fq PY;
|
||||
|
||||
bool operator==(const alt_bn128_ate_G1_precomp &other) const;
|
||||
friend std::ostream& operator<<(std::ostream &out, const alt_bn128_ate_G1_precomp &prec_P);
|
||||
friend std::istream& operator>>(std::istream &in, alt_bn128_ate_G1_precomp &prec_P);
|
||||
};
|
||||
|
||||
struct alt_bn128_ate_ell_coeffs {
|
||||
alt_bn128_Fq2 ell_0;
|
||||
alt_bn128_Fq2 ell_VW;
|
||||
alt_bn128_Fq2 ell_VV;
|
||||
|
||||
bool operator==(const alt_bn128_ate_ell_coeffs &other) const;
|
||||
friend std::ostream& operator<<(std::ostream &out, const alt_bn128_ate_ell_coeffs &dc);
|
||||
friend std::istream& operator>>(std::istream &in, alt_bn128_ate_ell_coeffs &dc);
|
||||
};
|
||||
|
||||
struct alt_bn128_ate_G2_precomp {
|
||||
alt_bn128_Fq2 QX;
|
||||
alt_bn128_Fq2 QY;
|
||||
std::vector<alt_bn128_ate_ell_coeffs> coeffs;
|
||||
|
||||
bool operator==(const alt_bn128_ate_G2_precomp &other) const;
|
||||
friend std::ostream& operator<<(std::ostream &out, const alt_bn128_ate_G2_precomp &prec_Q);
|
||||
friend std::istream& operator>>(std::istream &in, alt_bn128_ate_G2_precomp &prec_Q);
|
||||
};
|
||||
|
||||
alt_bn128_ate_G1_precomp alt_bn128_ate_precompute_G1(const alt_bn128_G1& P);
|
||||
alt_bn128_ate_G2_precomp alt_bn128_ate_precompute_G2(const alt_bn128_G2& Q);
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_ate_miller_loop(const alt_bn128_ate_G1_precomp &prec_P,
|
||||
const alt_bn128_ate_G2_precomp &prec_Q);
|
||||
alt_bn128_Fq12 alt_bn128_ate_double_miller_loop(const alt_bn128_ate_G1_precomp &prec_P1,
|
||||
const alt_bn128_ate_G2_precomp &prec_Q1,
|
||||
const alt_bn128_ate_G1_precomp &prec_P2,
|
||||
const alt_bn128_ate_G2_precomp &prec_Q2);
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_ate_pairing(const alt_bn128_G1& P,
|
||||
const alt_bn128_G2 &Q);
|
||||
alt_bn128_GT alt_bn128_ate_reduced_pairing(const alt_bn128_G1 &P,
|
||||
const alt_bn128_G2 &Q);
|
||||
|
||||
/* choice of pairing */
|
||||
|
||||
typedef alt_bn128_ate_G1_precomp alt_bn128_G1_precomp;
|
||||
typedef alt_bn128_ate_G2_precomp alt_bn128_G2_precomp;
|
||||
|
||||
alt_bn128_G1_precomp alt_bn128_precompute_G1(const alt_bn128_G1& P);
|
||||
|
||||
alt_bn128_G2_precomp alt_bn128_precompute_G2(const alt_bn128_G2& Q);
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_miller_loop(const alt_bn128_G1_precomp &prec_P,
|
||||
const alt_bn128_G2_precomp &prec_Q);
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_double_miller_loop(const alt_bn128_G1_precomp &prec_P1,
|
||||
const alt_bn128_G2_precomp &prec_Q1,
|
||||
const alt_bn128_G1_precomp &prec_P2,
|
||||
const alt_bn128_G2_precomp &prec_Q2);
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_pairing(const alt_bn128_G1& P,
|
||||
const alt_bn128_G2 &Q);
|
||||
|
||||
alt_bn128_GT alt_bn128_reduced_pairing(const alt_bn128_G1 &P,
|
||||
const alt_bn128_G2 &Q);
|
||||
|
||||
alt_bn128_GT alt_bn128_affine_reduced_pairing(const alt_bn128_G1 &P,
|
||||
const alt_bn128_G2 &Q);
|
||||
|
||||
} // libsnark
|
||||
#endif // ALT_BN128_PAIRING_HPP_
|
||||
58
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.cpp
Normal file
58
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_pp.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
void alt_bn128_pp::init_public_params()
|
||||
{
|
||||
init_alt_bn128_params();
|
||||
}
|
||||
|
||||
alt_bn128_GT alt_bn128_pp::final_exponentiation(const alt_bn128_Fq12 &elt)
|
||||
{
|
||||
return alt_bn128_final_exponentiation(elt);
|
||||
}
|
||||
|
||||
alt_bn128_G1_precomp alt_bn128_pp::precompute_G1(const alt_bn128_G1 &P)
|
||||
{
|
||||
return alt_bn128_precompute_G1(P);
|
||||
}
|
||||
|
||||
alt_bn128_G2_precomp alt_bn128_pp::precompute_G2(const alt_bn128_G2 &Q)
|
||||
{
|
||||
return alt_bn128_precompute_G2(Q);
|
||||
}
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_pp::miller_loop(const alt_bn128_G1_precomp &prec_P,
|
||||
const alt_bn128_G2_precomp &prec_Q)
|
||||
{
|
||||
return alt_bn128_miller_loop(prec_P, prec_Q);
|
||||
}
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_pp::double_miller_loop(const alt_bn128_G1_precomp &prec_P1,
|
||||
const alt_bn128_G2_precomp &prec_Q1,
|
||||
const alt_bn128_G1_precomp &prec_P2,
|
||||
const alt_bn128_G2_precomp &prec_Q2)
|
||||
{
|
||||
return alt_bn128_double_miller_loop(prec_P1, prec_Q1, prec_P2, prec_Q2);
|
||||
}
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_pp::pairing(const alt_bn128_G1 &P,
|
||||
const alt_bn128_G2 &Q)
|
||||
{
|
||||
return alt_bn128_pairing(P, Q);
|
||||
}
|
||||
|
||||
alt_bn128_Fq12 alt_bn128_pp::reduced_pairing(const alt_bn128_G1 &P,
|
||||
const alt_bn128_G2 &Q)
|
||||
{
|
||||
return alt_bn128_reduced_pairing(P, Q);
|
||||
}
|
||||
|
||||
} // libsnark
|
||||
50
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.hpp
Normal file
50
src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_pp.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ALT_BN128_PP_HPP_
|
||||
#define ALT_BN128_PP_HPP_
|
||||
#include "algebra/curves/public_params.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_init.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_g1.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_g2.hpp"
|
||||
#include "algebra/curves/alt_bn128/alt_bn128_pairing.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
class alt_bn128_pp {
|
||||
public:
|
||||
typedef alt_bn128_Fr Fp_type;
|
||||
typedef alt_bn128_G1 G1_type;
|
||||
typedef alt_bn128_G2 G2_type;
|
||||
typedef alt_bn128_G1_precomp G1_precomp_type;
|
||||
typedef alt_bn128_G2_precomp G2_precomp_type;
|
||||
typedef alt_bn128_Fq Fq_type;
|
||||
typedef alt_bn128_Fq2 Fqe_type;
|
||||
typedef alt_bn128_Fq12 Fqk_type;
|
||||
typedef alt_bn128_GT GT_type;
|
||||
|
||||
static const bool has_affine_pairing = false;
|
||||
|
||||
static void init_public_params();
|
||||
static alt_bn128_GT final_exponentiation(const alt_bn128_Fq12 &elt);
|
||||
static alt_bn128_G1_precomp precompute_G1(const alt_bn128_G1 &P);
|
||||
static alt_bn128_G2_precomp precompute_G2(const alt_bn128_G2 &Q);
|
||||
static alt_bn128_Fq12 miller_loop(const alt_bn128_G1_precomp &prec_P,
|
||||
const alt_bn128_G2_precomp &prec_Q);
|
||||
static alt_bn128_Fq12 double_miller_loop(const alt_bn128_G1_precomp &prec_P1,
|
||||
const alt_bn128_G2_precomp &prec_Q1,
|
||||
const alt_bn128_G1_precomp &prec_P2,
|
||||
const alt_bn128_G2_precomp &prec_Q2);
|
||||
static alt_bn128_Fq12 pairing(const alt_bn128_G1 &P,
|
||||
const alt_bn128_G2 &Q);
|
||||
static alt_bn128_Fq12 reduced_pairing(const alt_bn128_G1 &P,
|
||||
const alt_bn128_G2 &Q);
|
||||
};
|
||||
|
||||
} // libsnark
|
||||
|
||||
#endif // ALT_BN128_PP_HPP_
|
||||
22
src/snark/libsnark/algebra/curves/curve_utils.hpp
Normal file
22
src/snark/libsnark/algebra/curves/curve_utils.hpp
Normal file
@@ -0,0 +1,22 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef CURVE_UTILS_HPP_
|
||||
#define CURVE_UTILS_HPP_
|
||||
#include <cstdint>
|
||||
|
||||
#include "algebra/fields/bigint.hpp"
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
template<typename GroupT, mp_size_t m>
|
||||
GroupT scalar_mul(const GroupT &base, const bigint<m> &scalar);
|
||||
|
||||
} // libsnark
|
||||
#include "algebra/curves/curve_utils.tcc"
|
||||
|
||||
#endif // CURVE_UTILS_HPP_
|
||||
37
src/snark/libsnark/algebra/curves/curve_utils.tcc
Normal file
37
src/snark/libsnark/algebra/curves/curve_utils.tcc
Normal file
@@ -0,0 +1,37 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef CURVE_UTILS_TCC_
|
||||
#define CURVE_UTILS_TCC_
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
template<typename GroupT, mp_size_t m>
|
||||
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)
|
||||
{
|
||||
if (found_one)
|
||||
{
|
||||
result = result.dbl();
|
||||
}
|
||||
|
||||
if (scalar.test_bit(i))
|
||||
{
|
||||
found_one = true;
|
||||
result = result + base;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // libsnark
|
||||
#endif // CURVE_UTILS_TCC_
|
||||
103
src/snark/libsnark/algebra/curves/public_params.hpp
Normal file
103
src/snark/libsnark/algebra/curves/public_params.hpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/** @file
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef PUBLIC_PARAMS_HPP_
|
||||
#define PUBLIC_PARAMS_HPP_
|
||||
#include <vector>
|
||||
|
||||
namespace libsnark {
|
||||
|
||||
/*
|
||||
for every curve the user should define corresponding
|
||||
public_params with the following typedefs:
|
||||
|
||||
Fp_type
|
||||
G1_type
|
||||
G2_type
|
||||
G1_precomp_type
|
||||
G2_precomp_type
|
||||
affine_ate_G1_precomp_type
|
||||
affine_ate_G2_precomp_type
|
||||
Fq_type
|
||||
Fqe_type
|
||||
Fqk_type
|
||||
GT_type
|
||||
|
||||
one should also define the following static methods:
|
||||
|
||||
void init_public_params();
|
||||
|
||||
GT<EC_ppT> final_exponentiation(const Fqk<EC_ppT> &elt);
|
||||
|
||||
G1_precomp<EC_ppT> precompute_G1(const G1<EC_ppT> &P);
|
||||
G2_precomp<EC_ppT> precompute_G2(const G2<EC_ppT> &Q);
|
||||
|
||||
Fqk<EC_ppT> miller_loop(const G1_precomp<EC_ppT> &prec_P,
|
||||
const G2_precomp<EC_ppT> &prec_Q);
|
||||
|
||||
affine_ate_G1_precomp<EC_ppT> affine_ate_precompute_G1(const G1<EC_ppT> &P);
|
||||
affine_ate_G2_precomp<EC_ppT> affine_ate_precompute_G2(const G2<EC_ppT> &Q);
|
||||
|
||||
|
||||
Fqk<EC_ppT> affine_ate_miller_loop(const affine_ate_G1_precomp<EC_ppT> &prec_P,
|
||||
const affine_ate_G2_precomp<EC_ppT> &prec_Q);
|
||||
Fqk<EC_ppT> affine_ate_e_over_e_miller_loop(const affine_ate_G1_precomp<EC_ppT> &prec_P1,
|
||||
const affine_ate_G2_precomp<EC_ppT> &prec_Q1,
|
||||
const affine_ate_G1_precomp<EC_ppT> &prec_P2,
|
||||
const affine_ate_G2_precomp<EC_ppT> &prec_Q2);
|
||||
Fqk<EC_ppT> affine_ate_e_times_e_over_e_miller_loop(const affine_ate_G1_precomp<EC_ppT> &prec_P1,
|
||||
const affine_ate_G2_precomp<EC_ppT> &prec_Q1,
|
||||
const affine_ate_G1_precomp<EC_ppT> &prec_P2,
|
||||
const affine_ate_G2_precomp<EC_ppT> &prec_Q2,
|
||||
const affine_ate_G1_precomp<EC_ppT> &prec_P3,
|
||||
const affine_ate_G2_precomp<EC_ppT> &prec_Q3);
|
||||
Fqk<EC_ppT> double_miller_loop(const G1_precomp<EC_ppT> &prec_P1,
|
||||
const G2_precomp<EC_ppT> &prec_Q1,
|
||||
const G1_precomp<EC_ppT> &prec_P2,
|
||||
const G2_precomp<EC_ppT> &prec_Q2);
|
||||
|
||||
Fqk<EC_ppT> pairing(const G1<EC_ppT> &P,
|
||||
const G2<EC_ppT> &Q);
|
||||
GT<EC_ppT> reduced_pairing(const G1<EC_ppT> &P,
|
||||
const G2<EC_ppT> &Q);
|
||||
GT<EC_ppT> affine_reduced_pairing(const G1<EC_ppT> &P,
|
||||
const G2<EC_ppT> &Q);
|
||||
*/
|
||||
|
||||
template<typename EC_ppT>
|
||||
using Fr = typename EC_ppT::Fp_type;
|
||||
template<typename EC_ppT>
|
||||
using G1 = typename EC_ppT::G1_type;
|
||||
template<typename EC_ppT>
|
||||
using G2 = typename EC_ppT::G2_type;
|
||||
template<typename EC_ppT>
|
||||
using G1_precomp = typename EC_ppT::G1_precomp_type;
|
||||
template<typename EC_ppT>
|
||||
using G2_precomp = typename EC_ppT::G2_precomp_type;
|
||||
template<typename EC_ppT>
|
||||
using affine_ate_G1_precomp = typename EC_ppT::affine_ate_G1_precomp_type;
|
||||
template<typename EC_ppT>
|
||||
using affine_ate_G2_precomp = typename EC_ppT::affine_ate_G2_precomp_type;
|
||||
template<typename EC_ppT>
|
||||
using Fq = typename EC_ppT::Fq_type;
|
||||
template<typename EC_ppT>
|
||||
using Fqe = typename EC_ppT::Fqe_type;
|
||||
template<typename EC_ppT>
|
||||
using Fqk = typename EC_ppT::Fqk_type;
|
||||
template<typename EC_ppT>
|
||||
using GT = typename EC_ppT::GT_type;
|
||||
|
||||
template<typename EC_ppT>
|
||||
using Fr_vector = std::vector<Fr<EC_ppT> >;
|
||||
template<typename EC_ppT>
|
||||
using G1_vector = std::vector<G1<EC_ppT> >;
|
||||
template<typename EC_ppT>
|
||||
using G2_vector = std::vector<G2<EC_ppT> >;
|
||||
|
||||
} // libsnark
|
||||
|
||||
#endif // PUBLIC_PARAMS_HPP_
|
||||
121
src/snark/libsnark/algebra/curves/tests/test_bilinearity.cpp
Normal file
121
src/snark/libsnark/algebra/curves/tests/test_bilinearity.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
#include "common/profiling.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>
|
||||
|
||||
using namespace libsnark;
|
||||
|
||||
template<typename ppT>
|
||||
void pairing_test()
|
||||
{
|
||||
GT<ppT> GT_one = GT<ppT>::one();
|
||||
|
||||
printf("Running bilinearity tests:\n");
|
||||
G1<ppT> P = (Fr<ppT>::random_element()) * G1<ppT>::one();
|
||||
//G1<ppT> P = Fr<ppT>("2") * G1<ppT>::one();
|
||||
G2<ppT> Q = (Fr<ppT>::random_element()) * G2<ppT>::one();
|
||||
//G2<ppT> Q = Fr<ppT>("3") * G2<ppT>::one();
|
||||
|
||||
printf("P:\n");
|
||||
P.print();
|
||||
P.print_coordinates();
|
||||
printf("Q:\n");
|
||||
Q.print();
|
||||
Q.print_coordinates();
|
||||
printf("\n\n");
|
||||
|
||||
Fr<ppT> s = Fr<ppT>::random_element();
|
||||
//Fr<ppT> s = Fr<ppT>("2");
|
||||
G1<ppT> sP = s * P;
|
||||
G2<ppT> sQ = s * Q;
|
||||
|
||||
printf("Pairing bilinearity tests (three must match):\n");
|
||||
GT<ppT> ans1 = ppT::reduced_pairing(sP, Q);
|
||||
GT<ppT> ans2 = ppT::reduced_pairing(P, sQ);
|
||||
GT<ppT> ans3 = ppT::reduced_pairing(P, Q)^s;
|
||||
ans1.print();
|
||||
ans2.print();
|
||||
ans3.print();
|
||||
EXPECT_EQ(ans1, ans2);
|
||||
EXPECT_EQ(ans2, ans3);
|
||||
|
||||
EXPECT_NE(ans1, GT_one);
|
||||
EXPECT_EQ((ans1^Fr<ppT>::field_char()), GT_one);
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
template<typename ppT>
|
||||
void double_miller_loop_test()
|
||||
{
|
||||
const G1<ppT> P1 = (Fr<ppT>::random_element()) * G1<ppT>::one();
|
||||
const G1<ppT> P2 = (Fr<ppT>::random_element()) * G1<ppT>::one();
|
||||
const G2<ppT> Q1 = (Fr<ppT>::random_element()) * G2<ppT>::one();
|
||||
const G2<ppT> Q2 = (Fr<ppT>::random_element()) * G2<ppT>::one();
|
||||
|
||||
const G1_precomp<ppT> prec_P1 = ppT::precompute_G1(P1);
|
||||
const G1_precomp<ppT> prec_P2 = ppT::precompute_G1(P2);
|
||||
const G2_precomp<ppT> prec_Q1 = ppT::precompute_G2(Q1);
|
||||
const G2_precomp<ppT> prec_Q2 = ppT::precompute_G2(Q2);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
template<typename ppT>
|
||||
void affine_pairing_test()
|
||||
{
|
||||
GT<ppT> GT_one = GT<ppT>::one();
|
||||
|
||||
printf("Running bilinearity tests:\n");
|
||||
G1<ppT> P = (Fr<ppT>::random_element()) * G1<ppT>::one();
|
||||
G2<ppT> Q = (Fr<ppT>::random_element()) * G2<ppT>::one();
|
||||
|
||||
printf("P:\n");
|
||||
P.print();
|
||||
printf("Q:\n");
|
||||
Q.print();
|
||||
printf("\n\n");
|
||||
|
||||
Fr<ppT> s = Fr<ppT>::random_element();
|
||||
G1<ppT> sP = s * P;
|
||||
G2<ppT> sQ = s * Q;
|
||||
|
||||
printf("Pairing bilinearity tests (three must match):\n");
|
||||
GT<ppT> ans1 = ppT::affine_reduced_pairing(sP, Q);
|
||||
GT<ppT> ans2 = ppT::affine_reduced_pairing(P, sQ);
|
||||
GT<ppT> ans3 = ppT::affine_reduced_pairing(P, Q)^s;
|
||||
ans1.print();
|
||||
ans2.print();
|
||||
ans3.print();
|
||||
EXPECT_EQ(ans1, ans2);
|
||||
EXPECT_EQ(ans2, ans3);
|
||||
|
||||
EXPECT_NE(ans1, GT_one);
|
||||
EXPECT_EQ((ans1^Fr<ppT>::field_char()), GT_one);
|
||||
printf("\n\n");
|
||||
}
|
||||
|
||||
TEST(algebra, bilinearity)
|
||||
{
|
||||
start_profiling();
|
||||
alt_bn128_pp::init_public_params();
|
||||
pairing_test<alt_bn128_pp>();
|
||||
double_miller_loop_test<alt_bn128_pp>();
|
||||
|
||||
#ifdef CURVE_BN128 // BN128 has fancy dependencies so it may be disabled
|
||||
bn128_pp::init_public_params();
|
||||
pairing_test<bn128_pp>();
|
||||
double_miller_loop_test<bn128_pp>();
|
||||
#endif
|
||||
}
|
||||
153
src/snark/libsnark/algebra/curves/tests/test_groups.cpp
Normal file
153
src/snark/libsnark/algebra/curves/tests/test_groups.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
*****************************************************************************
|
||||
* @author This file is part of libsnark, developed by SCIPR Lab
|
||||
* and contributors (see AUTHORS).
|
||||
* @copyright MIT license (see LICENSE file)
|
||||
*****************************************************************************/
|
||||
#include "common/profiling.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>
|
||||
void test_mixed_add()
|
||||
{
|
||||
GroupT base, el, result;
|
||||
|
||||
base = GroupT::zero();
|
||||
el = GroupT::zero();
|
||||
el.to_special();
|
||||
result = base.mixed_add(el);
|
||||
EXPECT_EQ(result, base + el);
|
||||
|
||||
base = GroupT::zero();
|
||||
el = GroupT::random_element();
|
||||
el.to_special();
|
||||
result = base.mixed_add(el);
|
||||
EXPECT_EQ(result, base + el);
|
||||
|
||||
base = GroupT::random_element();
|
||||
el = GroupT::zero();
|
||||
el.to_special();
|
||||
result = base.mixed_add(el);
|
||||
EXPECT_EQ(result, base + el);
|
||||
|
||||
base = GroupT::random_element();
|
||||
el = GroupT::random_element();
|
||||
el.to_special();
|
||||
result = base.mixed_add(el);
|
||||
EXPECT_EQ(result, base + el);
|
||||
|
||||
base = GroupT::random_element();
|
||||
el = base;
|
||||
el.to_special();
|
||||
result = base.mixed_add(el);
|
||||
EXPECT_EQ(result, base.dbl());
|
||||
}
|
||||
|
||||
template<typename GroupT>
|
||||
void test_group()
|
||||
{
|
||||
bigint<1> rand1 = bigint<1>("76749407");
|
||||
bigint<1> rand2 = bigint<1>("44410867");
|
||||
bigint<1> randsum = bigint<1>("121160274");
|
||||
|
||||
GroupT zero = GroupT::zero();
|
||||
EXPECT_EQ(zero, zero);
|
||||
GroupT one = GroupT::one();
|
||||
EXPECT_EQ(one, one);
|
||||
GroupT two = bigint<1>(2l) * GroupT::one();
|
||||
EXPECT_EQ(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);
|
||||
|
||||
GroupT a = GroupT::random_element();
|
||||
GroupT b = GroupT::random_element();
|
||||
|
||||
EXPECT_NE(one, zero);
|
||||
EXPECT_NE(a, zero);
|
||||
EXPECT_NE(a, one);
|
||||
|
||||
EXPECT_NE(b, zero);
|
||||
EXPECT_NE(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);
|
||||
|
||||
// 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);
|
||||
|
||||
EXPECT_EQ((a + b).dbl(), (a + b) + (b + a));
|
||||
EXPECT_EQ(bigint<1>("2") * (a + b), (a + b) + (b + a));
|
||||
|
||||
EXPECT_EQ((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);
|
||||
|
||||
test_mixed_add<GroupT>();
|
||||
}
|
||||
|
||||
template<typename GroupT>
|
||||
void test_mul_by_q()
|
||||
{
|
||||
GroupT a = GroupT::random_element();
|
||||
EXPECT_EQ((GroupT::base_field_char()*a), a.mul_by_q());
|
||||
}
|
||||
|
||||
template<typename GroupT>
|
||||
void test_output()
|
||||
{
|
||||
GroupT g = GroupT::zero();
|
||||
|
||||
for (size_t i = 0; i < 1000; ++i)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << g;
|
||||
GroupT gg;
|
||||
ss >> gg;
|
||||
EXPECT_EQ(g, gg);
|
||||
/* use a random point in next iteration */
|
||||
g = GroupT::random_element();
|
||||
}
|
||||
}
|
||||
|
||||
TEST(algebra, groups)
|
||||
{
|
||||
alt_bn128_pp::init_public_params();
|
||||
test_group<G1<alt_bn128_pp> >();
|
||||
test_output<G1<alt_bn128_pp> >();
|
||||
test_group<G2<alt_bn128_pp> >();
|
||||
test_output<G2<alt_bn128_pp> >();
|
||||
test_mul_by_q<G2<alt_bn128_pp> >();
|
||||
|
||||
#ifdef CURVE_BN128 // BN128 has fancy dependencies so it may be disabled
|
||||
bn128_pp::init_public_params();
|
||||
test_group<G1<bn128_pp> >();
|
||||
test_output<G1<bn128_pp> >();
|
||||
test_group<G2<bn128_pp> >();
|
||||
test_output<G2<bn128_pp> >();
|
||||
#endif
|
||||
}
|
||||
Reference in New Issue
Block a user