Skip to content
This repository was archived by the owner on Feb 17, 2025. It is now read-only.

Commit 25ab668

Browse files
ayashunskyIluvmagick
authored andcommitted
g2 point addition and tests
1 parent 00f1749 commit 25ab668

File tree

5 files changed

+592
-126
lines changed

5 files changed

+592
-126
lines changed
Lines changed: 369 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
1+
//---------------------------------------------------------------------------//
2+
// Copyright (c) 2023 Alexey Yashunsky <[email protected]>
3+
//
4+
// MIT License
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to deal
8+
// in the Software without restriction, including without limitation the rights
9+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
// copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in all
14+
// copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
// SOFTWARE.
23+
//---------------------------------------------------------------------------//
24+
// @file Declaration of interfaces for point addition in the elliptic
25+
// curve group G2 = E'(F_p^2) : y^2 = x^3 + 4(1+u) with
26+
// F_p^2 = F_p[u]/(u^2 - (-1)).
27+
//---------------------------------------------------------------------------//
28+
29+
#ifndef CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_BLS12_G2_POINT_ADDITION_HPP
30+
#define CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_BLS12_G2_POINT_ADDITION_HPP
31+
32+
#include <nil/crypto3/zk/snark/arithmetization/plonk/constraint_system.hpp>
33+
34+
#include <nil/blueprint/blueprint/plonk/assignment.hpp>
35+
#include <nil/blueprint/blueprint/plonk/circuit.hpp>
36+
#include <nil/blueprint/component.hpp>
37+
#include <nil/blueprint/manifest.hpp>
38+
39+
#include <nil/crypto3/algebra/fields/detail/element/fp2.hpp>
40+
#include <nil/crypto3/algebra/fields/fp2.hpp>
41+
42+
#include <nil/blueprint/components/algebra/fields/plonk/non_native/detail/abstract_fp2.hpp>
43+
44+
namespace nil {
45+
namespace blueprint {
46+
namespace components {
47+
// E'(F_p^2) : y^2 = x^3 + 4(1+u) point addition gate.
48+
// Expects point at infinity encoded by (0,0) in input and output
49+
// Input: (xP, yP) = P[4], (xQ, yQ) = Q[4]
50+
// Output: (xR, yR) = R[4], R = P + Q as element of E'(F_p^2)
51+
//
52+
// We organize the computations in 2-cell blocks for storing Fp2 elements
53+
// The 12 blocks used are stored in 1 row with 24 cells or 2 rows with 12 cells.
54+
// Block contents are:
55+
// 0 1 2 3 4 5 6 7 8 9 10 11
56+
// +--+--+--+--+--+--+---+---+--+--+--+--+
57+
// |xP|yP|xQ|yQ|zP|zQ|zPQ|wPQ|la| |xR|yR|
58+
// +--+--+--+--+--+--+---+---+--+--+--+--+
59+
//
60+
61+
template<typename ArithmetizationType, typename BlueprintFieldType>
62+
class bls12_g2_point_addition;
63+
64+
template<typename BlueprintFieldType, typename ArithmetizationParams>
65+
class bls12_g2_point_addition<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType, ArithmetizationParams>,
66+
BlueprintFieldType>
67+
: public plonk_component<BlueprintFieldType, ArithmetizationParams, 0, 0> {
68+
69+
public:
70+
using component_type = plonk_component<BlueprintFieldType, ArithmetizationParams, 0, 0>;
71+
72+
using var = typename component_type::var;
73+
using manifest_type = plonk_component_manifest;
74+
75+
class gate_manifest_type : public component_gate_manifest {
76+
public:
77+
std::uint32_t gates_amount() const override {
78+
return bls12_g2_point_addition::gates_amount;
79+
}
80+
};
81+
82+
static gate_manifest get_gate_manifest(std::size_t witness_amount,
83+
std::size_t lookup_column_amount) {
84+
static gate_manifest manifest = gate_manifest(gate_manifest_type());
85+
return manifest;
86+
}
87+
88+
static manifest_type get_manifest() {
89+
static manifest_type manifest = manifest_type(
90+
std::shared_ptr<manifest_param>(new manifest_range_param(12,24,12)), // 12 or 24
91+
false
92+
);
93+
return manifest;
94+
}
95+
96+
constexpr static std::size_t get_rows_amount(std::size_t witness_amount,
97+
std::size_t lookup_column_amount) {
98+
return 1 + (witness_amount < 24);
99+
}
100+
101+
constexpr static const std::size_t gates_amount = 1;
102+
const std::size_t rows_amount = get_rows_amount(this->witness_amount(), 0);
103+
104+
struct input_type {
105+
std::array<var,4> P, Q;
106+
107+
std::vector<var> all_vars() const {
108+
std::vector<var> res = {};
109+
for(auto & e : P) { res.push_back(e); }
110+
for(auto & e : Q) { res.push_back(e); }
111+
return res;
112+
}
113+
};
114+
115+
struct result_type {
116+
std::array<var,4> R;
117+
118+
result_type(const bls12_g2_point_addition &component, std::uint32_t start_row_index) {
119+
const std::size_t WA = component.witness_amount();
120+
121+
for(std::size_t i = 0; i < 4; i++) {
122+
R[i] = var(component.W(WA - 4 + i), start_row_index + (WA < 24), false, var::column_type::witness);
123+
}
124+
}
125+
126+
std::vector<var> all_vars() const {
127+
std::vector<var> res = {};
128+
129+
for(auto & e : R) { res.push_back(e); }
130+
return res;
131+
}
132+
};
133+
134+
template<typename ContainerType>
135+
explicit bls12_g2_point_addition(ContainerType witness) : component_type(witness, {}, {}, get_manifest()) {};
136+
137+
template<typename WitnessContainerType, typename ConstantContainerType,
138+
typename PublicInputContainerType>
139+
bls12_g2_point_addition(WitnessContainerType witness, ConstantContainerType constant,
140+
PublicInputContainerType public_input) :
141+
component_type(witness, constant, public_input, get_manifest()) {};
142+
143+
bls12_g2_point_addition(
144+
std::initializer_list<typename component_type::witness_container_type::value_type>
145+
witnesses,
146+
std::initializer_list<typename component_type::constant_container_type::value_type>
147+
constants,
148+
std::initializer_list<typename component_type::public_input_container_type::value_type>
149+
public_inputs) :
150+
component_type(witnesses, constants, public_inputs, get_manifest()) {};
151+
};
152+
153+
template<typename BlueprintFieldType, typename ArithmetizationParams>
154+
using plonk_bls12_g2_point_addition =
155+
bls12_g2_point_addition<
156+
crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType, ArithmetizationParams>,
157+
BlueprintFieldType>;
158+
159+
template<typename BlueprintFieldType, typename ArithmetizationParams>
160+
typename plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams>::result_type generate_assignments(
161+
const plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams> &component,
162+
assignment<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType, ArithmetizationParams>>
163+
&assignment,
164+
const typename plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams>::input_type
165+
&instance_input,
166+
const std::uint32_t start_row_index) {
167+
168+
using value_type = typename BlueprintFieldType::value_type;
169+
170+
const std::size_t WA = component.witness_amount();
171+
172+
using policy_type_fp2 = crypto3::algebra::fields::fp2<BlueprintFieldType>;
173+
using fp2_element = typename policy_type_fp2::value_type;
174+
175+
fp2_element fp2zero = fp2_element(0,0),
176+
xP = fp2_element(var_value(assignment, instance_input.P[0]),
177+
var_value(assignment, instance_input.P[1])),
178+
yP = fp2_element(var_value(assignment, instance_input.P[2]),
179+
var_value(assignment, instance_input.P[3])),
180+
xQ = fp2_element(var_value(assignment, instance_input.Q[0]),
181+
var_value(assignment, instance_input.Q[1])),
182+
yQ = fp2_element(var_value(assignment, instance_input.Q[2]),
183+
var_value(assignment, instance_input.Q[3])),
184+
zP = yP.inversed(), // NB: division by 0 is defined as 0
185+
zQ = yQ.inversed(),
186+
zPQ = (xP - xQ).inversed(),
187+
wPQ = (yP + yQ).inversed(),
188+
lambda = (xP == xQ)? (3*xP.pow(2) / (2*yP)) : ((yP-yQ)/(xP-xQ)),
189+
nu = yP - lambda*xP,
190+
xR, yR;
191+
if (yP == fp2zero) {
192+
xR = xQ;
193+
yR = yQ;
194+
} else {
195+
if (yQ == fp2zero) {
196+
xR = xP;
197+
yR = yP;
198+
} else {
199+
if ((xP == xQ) && (yP == -yQ)) {
200+
xR = fp2zero;
201+
yR = fp2zero;
202+
} else {
203+
xR = lambda.pow(2) - xP - xQ,
204+
yR = -(lambda*xR + nu);
205+
}
206+
}
207+
}
208+
209+
for(std::size_t i = 0; i < 2; i++) {
210+
assignment.witness(component.W(i),start_row_index) = xP.data[i];
211+
assignment.witness(component.W(2 + i),start_row_index) = yP.data[i];
212+
assignment.witness(component.W(4 + i),start_row_index) = xQ.data[i];
213+
assignment.witness(component.W(6 + i),start_row_index) = yQ.data[i];
214+
assignment.witness(component.W(8 + i),start_row_index) = zP.data[i];
215+
assignment.witness(component.W(10 + i),start_row_index) = zQ.data[i];
216+
217+
assignment.witness(component.W((12 + i) % WA),start_row_index + (WA < 24)) = zPQ.data[i];
218+
assignment.witness(component.W((14 + i) % WA),start_row_index + (WA < 24)) = wPQ.data[i];
219+
assignment.witness(component.W((16 + i) % WA),start_row_index + (WA < 24)) = lambda.data[i];
220+
// block #9 is skipped for alignment purposes
221+
assignment.witness(component.W((20 + i) % WA),start_row_index + (WA < 24)) = xR.data[i];
222+
assignment.witness(component.W((22 + i) % WA),start_row_index + (WA < 24)) = yR.data[i];
223+
}
224+
225+
return typename plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams>::result_type(
226+
component, start_row_index);
227+
}
228+
229+
template<typename BlueprintFieldType, typename ArithmetizationParams>
230+
std::size_t generate_gates(
231+
const plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams> &component,
232+
circuit<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType, ArithmetizationParams>> &bp,
233+
assignment<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType, ArithmetizationParams>>
234+
&assignment,
235+
const typename plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams>::input_type
236+
&instance_input) {
237+
238+
const std::size_t WA = component.witness_amount();
239+
240+
using var = typename plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams>::var;
241+
using constraint_type = crypto3::zk::snark::plonk_constraint<BlueprintFieldType>;
242+
243+
// Fp2 field over constraints:
244+
using fp2_constraint = detail::abstract_fp2_element<constraint_type>;
245+
246+
constraint_type cnstr_zero = constraint_type(),
247+
cnstr_one = cnstr_zero + 1;
248+
249+
fp2_constraint one = {cnstr_one,cnstr_zero},
250+
xP = {var(component.W(0), 0, true),var(component.W(1), 0, true)},
251+
yP = {var(component.W(2), 0, true),var(component.W(3), 0, true)},
252+
xQ = {var(component.W(4), 0, true),var(component.W(5), 0, true)},
253+
yQ = {var(component.W(6), 0, true),var(component.W(7), 0, true)},
254+
zP = {var(component.W(8), 0, true),var(component.W(9), 0, true)},
255+
zQ = {var(component.W(10), 0, true),var(component.W(11), 0, true)},
256+
zPQ = {var(component.W(12 % WA), (WA < 24), true),var(component.W(13 % WA), (WA < 24), true)},
257+
wPQ = {var(component.W(14 % WA), (WA < 24), true),var(component.W(15 % WA), (WA < 24), true)},
258+
la = {var(component.W(16 % WA), (WA < 24), true),var(component.W(17 % WA), (WA < 24), true)},
259+
xR = {var(component.W(20 % WA), (WA < 24), true),var(component.W(21 % WA), (WA < 24), true)},
260+
yR = {var(component.W(22 % WA), (WA < 24), true),var(component.W(23 % WA), (WA < 24), true)};
261+
fp2_constraint C;
262+
263+
std::vector<constraint_type> Cs = {};
264+
265+
// yP(1 - yP zP) = 0 (1)
266+
C = yP * (one - yP * zP);
267+
Cs.push_back(C[0]); Cs.push_back(C[1]);
268+
269+
// yQ(1 - yQ zQ) = 0 (2)
270+
C = yQ * (one - yQ * zQ);
271+
Cs.push_back(C[0]); Cs.push_back(C[1]);
272+
273+
// (xR - xQ)(1 - yP zP) = 0 (3)
274+
C = (xR - xQ) * (one - yP * zP);
275+
Cs.push_back(C[0]); Cs.push_back(C[1]);
276+
277+
// (yR - yQ)(1 - yP zP) = 0 (4)
278+
C = (yR - yQ)*(one - yP * zP);
279+
Cs.push_back(C[0]); Cs.push_back(C[1]);
280+
281+
// (xR - xP)(1 - yQ zQ) = 0 (5)
282+
C = (xR - xP)*(one - yQ*zQ);
283+
Cs.push_back(C[0]); Cs.push_back(C[1]);
284+
285+
// (yR - yP)(1 - yQ zQ) = 0 (6)
286+
C = (yR - yP)*(one - yQ*zQ);
287+
Cs.push_back(C[0]); Cs.push_back(C[1]);
288+
289+
// (xP - xQ)(1 - (xP-xQ) zPQ) = 0 (7)
290+
C = (xP - xQ)*(one - (xP - xQ)*zPQ);
291+
Cs.push_back(C[0]); Cs.push_back(C[1]);
292+
293+
// zPQ (1 - (xP - xQ) zPQ) = 0 (8)
294+
C = zPQ * (one - (xP - xQ) * zPQ);
295+
Cs.push_back(C[0]); Cs.push_back(C[1]);
296+
297+
// (yP + yQ)(1 - (yP + yQ) wPQ) = 0 (9)
298+
C = (yP + yQ)*(one - (yP + yQ)*wPQ);
299+
Cs.push_back(C[0]); Cs.push_back(C[1]);
300+
301+
// wPQ (1 - (yP + yQ) wPQ) = 0 (10)
302+
C = wPQ * (one - (yP + yQ)*wPQ);
303+
Cs.push_back(C[0]); Cs.push_back(C[1]);
304+
305+
// yP(1 - (xP - xQ) zPQ) yQ(1 - (yP + yQ) wPQ) xR = 0 (11)
306+
C = yP * (one - (xP-xQ)*zPQ) * yQ * (one - (yP + yQ)* wPQ) * xR;
307+
Cs.push_back(C[0]); Cs.push_back(C[1]);
308+
309+
// yP(1 - (xP - xQ) zPQ) yQ(1 - (yP + yQ) wPQ) yR = 0 (12)
310+
C = yP * (one - (xP-xQ)*zPQ) * yQ * (one - (yP + yQ)* wPQ) * yR;
311+
Cs.push_back(C[0]); Cs.push_back(C[1]);
312+
313+
// yP yQ (zPQ + wPQ (1 - (xP - xQ) zPQ)) (xR - la^2 + xP + xQ) = 0 (13)
314+
C = yP * yQ * (zPQ + wPQ * (one - (xP - xQ)*zPQ)) * (xR - la*la + xP + xQ);
315+
Cs.push_back(C[0]); Cs.push_back(C[1]);
316+
317+
// yP yQ (zPQ + wPQ (1 - (xP - xQ) zPQ)) (yR + yP + la(xR - xP)) = 0 (14)
318+
C = yP * yQ * (zPQ + wPQ * (one - (xP - xQ)*zPQ)) * (yR + yP + la*(xR - xP));
319+
Cs.push_back(C[0]); Cs.push_back(C[1]);
320+
321+
// yQ ( 2yP zPQ ( (xP - xQ)la - (yP - yQ) ) + (1 - (xP - xQ)zPQ) wPQ (2yP la - 3xP^2)) = 0 (15)
322+
C = yQ * (2*yP * zPQ * ((xP - xQ)*la - (yP - yQ)) + (one - (xP - xQ)*zPQ) * wPQ *(2*yP*la - 3*xP*xP));
323+
Cs.push_back(C[0]); Cs.push_back(C[1]);
324+
325+
return bp.add_gate(Cs);
326+
}
327+
328+
template<typename BlueprintFieldType, typename ArithmetizationParams>
329+
void generate_copy_constraints(
330+
const plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams> &component,
331+
circuit<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType, ArithmetizationParams>> &bp,
332+
assignment<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType, ArithmetizationParams>>
333+
&assignment,
334+
const typename plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams>::input_type &instance_input,
335+
const std::size_t start_row_index) {
336+
337+
using var = typename plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams>::var;
338+
339+
const std::size_t WA = component.witness_amount();
340+
341+
for(std::size_t i = 0; i < 4; i++) {
342+
bp.add_copy_constraint({var(component.W(i), start_row_index, false), instance_input.P[i]});
343+
}
344+
}
345+
346+
template<typename BlueprintFieldType, typename ArithmetizationParams>
347+
typename plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams>::result_type generate_circuit(
348+
const plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams> &component,
349+
circuit<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType, ArithmetizationParams>> &bp,
350+
assignment<crypto3::zk::snark::plonk_constraint_system<BlueprintFieldType, ArithmetizationParams>>
351+
&assignment,
352+
const typename plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams>::input_type &instance_input,
353+
const std::size_t start_row_index) {
354+
355+
std::size_t selector_index = generate_gates(component, bp, assignment, instance_input);
356+
357+
assignment.enable_selector(selector_index, start_row_index);
358+
359+
generate_copy_constraints(component, bp, assignment, instance_input, start_row_index);
360+
361+
return typename plonk_bls12_g2_point_addition<BlueprintFieldType, ArithmetizationParams>::result_type(
362+
component, start_row_index);
363+
}
364+
365+
} // namespace components
366+
} // namespace blueprint
367+
} // namespace nil
368+
369+
#endif // CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_BLS12_G2_POINT_ADDITION_HPP

0 commit comments

Comments
 (0)