1 /** @file
2 ********************************************************************************
3 Implements functions for computing Ate pairings over the bn128 curves, split into a
4 offline and online stages.
5 ********************************************************************************
6 * @author This file is part of libff, developed by SCIPR Lab
7 * and contributors (see AUTHORS).
8 * @copyright MIT license (see LICENSE file)
9 *******************************************************************************/
10
11 #include <sstream>
12
13 #include <libff/algebra/curves/bn128/bn128_g1.hpp>
14 #include <libff/algebra/curves/bn128/bn128_g2.hpp>
15 #include <libff/algebra/curves/bn128/bn128_gt.hpp>
16 #include <libff/algebra/curves/bn128/bn128_init.hpp>
17 #include <libff/algebra/curves/bn128/bn128_pairing.hpp>
18 #include <libff/common/profiling.hpp>
19
20 namespace libff {
21
operator ==(const bn128_ate_G1_precomp & other) const22 bool bn128_ate_G1_precomp::operator==(const bn128_ate_G1_precomp &other) const
23 {
24 return (this->P[0] == other.P[0] &&
25 this->P[1] == other.P[1] &&
26 this->P[2] == other.P[2]);
27 }
28
operator <<(std::ostream & out,const bn128_ate_G1_precomp & prec_P)29 std::ostream& operator<<(std::ostream &out, const bn128_ate_G1_precomp &prec_P)
30 {
31 for (size_t i = 0; i < 3; ++i)
32 {
33 #ifndef BINARY_OUTPUT
34 out << prec_P.P[i] << "\n";
35 #else
36 out.write((char*) &prec_P.P[i], sizeof(prec_P.P[i]));
37 #endif
38 }
39 return out;
40 }
41
operator >>(std::istream & in,bn128_ate_G1_precomp & prec_P)42 std::istream& operator>>(std::istream &in, bn128_ate_G1_precomp &prec_P)
43 {
44 for (size_t i = 0; i < 3; ++i)
45 {
46 #ifndef BINARY_OUTPUT
47 in >> prec_P.P[i];
48 consume_newline(in);
49 #else
50 in.read((char*) &prec_P.P[i], sizeof(prec_P.P[i]));
51 #endif
52 }
53 return in;
54 }
55
operator ==(const bn128_ate_G2_precomp & other) const56 bool bn128_ate_G2_precomp::operator==(const bn128_ate_G2_precomp &other) const
57 {
58 if (!(this->Q[0] == other.Q[0] &&
59 this->Q[1] == other.Q[1] &&
60 this->Q[2] == other.Q[2] &&
61 this->coeffs.size() == other.coeffs.size()))
62 {
63 return false;
64 }
65
66 /* work around for upstream serialization bug */
67 for (size_t i = 0; i < this->coeffs.size(); ++i)
68 {
69 std::stringstream this_ss, other_ss;
70 this_ss << this->coeffs[i];
71 other_ss << other.coeffs[i];
72 if (this_ss.str() != other_ss.str())
73 {
74 return false;
75 }
76 }
77
78 return true;
79 }
80
operator <<(std::ostream & out,const bn128_ate_G2_precomp & prec_Q)81 std::ostream& operator<<(std::ostream &out, const bn128_ate_G2_precomp &prec_Q)
82 {
83 for (size_t i = 0; i < 3; ++i)
84 {
85 #ifndef BINARY_OUTPUT
86 out << prec_Q.Q[i].a_ << "\n";
87 out << prec_Q.Q[i].b_ << "\n";
88 #else
89 out.write((char*) &prec_Q.Q[i].a_, sizeof(prec_Q.Q[i].a_));
90 out.write((char*) &prec_Q.Q[i].b_, sizeof(prec_Q.Q[i].b_));
91 #endif
92 }
93
94 out << prec_Q.coeffs.size() << "\n";
95
96 for (size_t i = 0; i < prec_Q.coeffs.size(); ++i)
97 {
98 #ifndef BINARY_OUTPUT
99 out << prec_Q.coeffs[i].a_.a_ << "\n";
100 out << prec_Q.coeffs[i].a_.b_ << "\n";
101 out << prec_Q.coeffs[i].b_.a_ << "\n";
102 out << prec_Q.coeffs[i].b_.b_ << "\n";
103 out << prec_Q.coeffs[i].c_.a_ << "\n";
104 out << prec_Q.coeffs[i].c_.b_ << "\n";
105 #else
106 out.write((char*) &prec_Q.coeffs[i].a_.a_, sizeof(prec_Q.coeffs[i].a_.a_));
107 out.write((char*) &prec_Q.coeffs[i].a_.b_, sizeof(prec_Q.coeffs[i].a_.b_));
108 out.write((char*) &prec_Q.coeffs[i].b_.a_, sizeof(prec_Q.coeffs[i].b_.a_));
109 out.write((char*) &prec_Q.coeffs[i].b_.b_, sizeof(prec_Q.coeffs[i].b_.b_));
110 out.write((char*) &prec_Q.coeffs[i].c_.a_, sizeof(prec_Q.coeffs[i].c_.a_));
111 out.write((char*) &prec_Q.coeffs[i].c_.b_, sizeof(prec_Q.coeffs[i].c_.b_));
112 #endif
113 }
114
115 return out;
116 }
117
operator >>(std::istream & in,bn128_ate_G2_precomp & prec_Q)118 std::istream& operator>>(std::istream &in, bn128_ate_G2_precomp &prec_Q)
119 {
120 for (size_t i = 0; i < 3; ++i)
121 {
122 #ifndef BINARY_OUTPUT
123 in >> prec_Q.Q[i].a_;
124 consume_newline(in);
125 in >> prec_Q.Q[i].b_;
126 consume_newline(in);
127 #else
128 in.read((char*) &prec_Q.Q[i].a_, sizeof(prec_Q.Q[i].a_));
129 in.read((char*) &prec_Q.Q[i].b_, sizeof(prec_Q.Q[i].b_));
130 #endif
131 }
132
133 size_t count;
134 in >> count;
135 consume_newline(in);
136 prec_Q.coeffs.resize(count);
137 for (size_t i = 0; i < count; ++i)
138 {
139 #ifndef BINARY_OUTPUT
140 in >> prec_Q.coeffs[i].a_.a_;
141 consume_newline(in);
142 in >> prec_Q.coeffs[i].a_.b_;
143 consume_newline(in);
144 in >> prec_Q.coeffs[i].b_.a_;
145 consume_newline(in);
146 in >> prec_Q.coeffs[i].b_.b_;
147 consume_newline(in);
148 in >> prec_Q.coeffs[i].c_.a_;
149 consume_newline(in);
150 in >> prec_Q.coeffs[i].c_.b_;
151 consume_newline(in);
152 #else
153 in.read((char*) &prec_Q.coeffs[i].a_.a_, sizeof(prec_Q.coeffs[i].a_.a_));
154 in.read((char*) &prec_Q.coeffs[i].a_.b_, sizeof(prec_Q.coeffs[i].a_.b_));
155 in.read((char*) &prec_Q.coeffs[i].b_.a_, sizeof(prec_Q.coeffs[i].b_.a_));
156 in.read((char*) &prec_Q.coeffs[i].b_.b_, sizeof(prec_Q.coeffs[i].b_.b_));
157 in.read((char*) &prec_Q.coeffs[i].c_.a_, sizeof(prec_Q.coeffs[i].c_.a_));
158 in.read((char*) &prec_Q.coeffs[i].c_.b_, sizeof(prec_Q.coeffs[i].c_.b_));
159 #endif
160 }
161 return in;
162 }
163
bn128_ate_precompute_G1(const bn128_G1 & P)164 bn128_ate_G1_precomp bn128_ate_precompute_G1(const bn128_G1& P)
165 {
166 enter_block("Call to bn128_ate_precompute_G1");
167
168 bn128_ate_G1_precomp result;
169 bn::ecop::NormalizeJac(result.P, P.coord);
170
171 leave_block("Call to bn128_ate_precompute_G1");
172 return result;
173 }
174
bn128_ate_precompute_G2(const bn128_G2 & Q)175 bn128_ate_G2_precomp bn128_ate_precompute_G2(const bn128_G2& Q)
176 {
177 enter_block("Call to bn128_ate_precompute_G2");
178
179 bn128_ate_G2_precomp result;
180 bn::components::precomputeG2(result.coeffs, result.Q, Q.coord);
181
182 leave_block("Call to bn128_ate_precompute_G2");
183 return result;
184 }
185
bn128_ate_miller_loop(const bn128_ate_G1_precomp & prec_P,const bn128_ate_G2_precomp & prec_Q)186 bn128_Fq12 bn128_ate_miller_loop(const bn128_ate_G1_precomp &prec_P,
187 const bn128_ate_G2_precomp &prec_Q)
188 {
189 bn128_Fq12 f;
190 bn::components::millerLoop(f.elem, prec_Q.coeffs, prec_P.P);
191 return f;
192 }
193
bn128_double_ate_miller_loop(const bn128_ate_G1_precomp & prec_P1,const bn128_ate_G2_precomp & prec_Q1,const bn128_ate_G1_precomp & prec_P2,const bn128_ate_G2_precomp & prec_Q2)194 bn128_Fq12 bn128_double_ate_miller_loop(const bn128_ate_G1_precomp &prec_P1,
195 const bn128_ate_G2_precomp &prec_Q1,
196 const bn128_ate_G1_precomp &prec_P2,
197 const bn128_ate_G2_precomp &prec_Q2)
198 {
199 bn128_Fq12 f;
200 bn::components::millerLoop2(f.elem, prec_Q1.coeffs, prec_P1.P, prec_Q2.coeffs, prec_P2.P);
201 return f;
202 }
203
bn128_final_exponentiation(const bn128_Fq12 & elt)204 bn128_GT bn128_final_exponentiation(const bn128_Fq12 &elt)
205 {
206 enter_block("Call to bn128_final_exponentiation");
207 bn128_GT eltcopy = elt;
208 eltcopy.elem.final_exp();
209 leave_block("Call to bn128_final_exponentiation");
210 return eltcopy;
211 }
212 } // libff
213