@@ -17,7 +17,7 @@ constexpr auto MAIN_SUBGROUP_ORDER =
17
17
18
18
// / Validates p1 affine point. Checks that point coordinates are from the BLS12-381 field and
19
19
// / that the point is on curve. https://eips.ethereum.org/EIPS/eip-2537#abi-for-g1-addition
20
- [[nodiscard]] std::optional<blst_p1_affine> validate_point (
20
+ [[nodiscard]] std::optional<blst_p1_affine> validate_point_g1 (
21
21
const uint8_t _x[64 ], const uint8_t _y[64 ]) noexcept
22
22
{
23
23
constexpr auto is_field_element = [](const uint8_t _p[64 ]) {
@@ -41,8 +41,39 @@ constexpr auto MAIN_SUBGROUP_ORDER =
41
41
return p0_affine;
42
42
}
43
43
44
+ // / Validates p2 affine point. Checks that point coordinates are from the BLS12-381 field and
45
+ // / that the point is on curve. https://eips.ethereum.org/EIPS/eip-2537#abi-for-g2-addition
46
+ [[nodiscard]] std::optional<blst_p2_affine> validate_point_g2 (
47
+ const uint8_t _x[128 ], const uint8_t _y[128 ]) noexcept
48
+ {
49
+ constexpr auto is_field_element = [](const uint8_t _p[128 ]) {
50
+ return intx::be::unsafe::load<intx::uint512>(_p) < BLS_FIELD_MODULUS &&
51
+ intx::be::unsafe::load<intx::uint512>(&_p[64 ]) < BLS_FIELD_MODULUS;
52
+ };
53
+
54
+ if (!is_field_element (_x))
55
+ return std::nullopt;
56
+ if (!is_field_element (_y))
57
+ return std::nullopt;
58
+
59
+ blst_fp x0;
60
+ blst_fp x1;
61
+ blst_fp y0 ;
62
+ blst_fp y1 ;
63
+ blst_fp_from_bendian (&x0, &_x[FP_BYTES_OFFSET]);
64
+ blst_fp_from_bendian (&x1, &_x[FP_BYTES_OFFSET + 64 ]);
65
+ blst_fp_from_bendian (&y0 , &_y[FP_BYTES_OFFSET]);
66
+ blst_fp_from_bendian (&y1 , &_y[FP_BYTES_OFFSET + 64 ]);
67
+
68
+ const blst_p2_affine p_affine{{x0, x1}, {y0 , y1 }};
69
+ if (!blst_p2_affine_on_curve (&p_affine))
70
+ return std::nullopt;
71
+
72
+ return p_affine;
73
+ }
74
+
44
75
// / Stores p1 point in two 64-bytes arrays with big endian encoding zero padded.
45
- void store_result (uint8_t _rx[64 ], uint8_t _ry[64 ], const blst_p1* out) noexcept
76
+ void store_result_g1 (uint8_t _rx[64 ], uint8_t _ry[64 ], const blst_p1* out) noexcept
46
77
{
47
78
blst_p1_affine result;
48
79
blst_p1_to_affine (&result, out);
@@ -52,13 +83,31 @@ void store_result(uint8_t _rx[64], uint8_t _ry[64], const blst_p1* out) noexcept
52
83
std::memset (_ry, 0 , FP_BYTES_OFFSET);
53
84
blst_bendian_from_fp (&_ry[FP_BYTES_OFFSET], &result.y );
54
85
}
86
+
87
+ // / Stores p2 point in two 128-bytes arrays with big endian encoding zero padded.
88
+ void store_result_g2 (uint8_t _rx[128 ], uint8_t _ry[128 ], const blst_p2* out) noexcept
89
+ {
90
+ blst_p2_affine result;
91
+ blst_p2_to_affine (&result, out);
92
+
93
+ std::memset (_rx, 0 , FP_BYTES_OFFSET);
94
+ blst_bendian_from_fp (&_rx[FP_BYTES_OFFSET], &result.x .fp [0 ]);
95
+ std::memset (&_rx[64 ], 0 , FP_BYTES_OFFSET);
96
+ blst_bendian_from_fp (&_rx[FP_BYTES_OFFSET + 64 ], &result.x .fp [1 ]);
97
+
98
+ std::memset (_ry, 0 , FP_BYTES_OFFSET);
99
+ blst_bendian_from_fp (&_ry[FP_BYTES_OFFSET], &result.y .fp [0 ]);
100
+ std::memset (&_ry[64 ], 0 , FP_BYTES_OFFSET);
101
+ blst_bendian_from_fp (&_ry[FP_BYTES_OFFSET + 64 ], &result.y .fp [1 ]);
102
+ }
103
+
55
104
} // namespace
56
105
57
106
[[nodiscard]] bool g1_add (uint8_t _rx[64 ], uint8_t _ry[64 ], const uint8_t _x0[64 ],
58
107
const uint8_t _y0[64 ], const uint8_t _x1[64 ], const uint8_t _y1[64 ]) noexcept
59
108
{
60
- const auto p0_affine = validate_point (_x0, _y0);
61
- const auto p1_affine = validate_point (_x1, _y1);
109
+ const auto p0_affine = validate_point_g1 (_x0, _y0);
110
+ const auto p1_affine = validate_point_g1 (_x1, _y1);
62
111
63
112
if (!p0_affine.has_value () || !p1_affine.has_value ())
64
113
return false ;
@@ -69,7 +118,7 @@ void store_result(uint8_t _rx[64], uint8_t _ry[64], const blst_p1* out) noexcept
69
118
blst_p1 out;
70
119
blst_p1_add_or_double_affine (&out, &p0, &*p1_affine);
71
120
72
- store_result (_rx, _ry, &out);
121
+ store_result_g1 (_rx, _ry, &out);
73
122
74
123
return true ;
75
124
}
@@ -81,7 +130,7 @@ void store_result(uint8_t _rx[64], uint8_t _ry[64], const blst_p1* out) noexcept
81
130
blst_scalar scalar;
82
131
blst_scalar_from_uint64 (&scalar, as_words (c));
83
132
84
- const auto p_affine = validate_point (_x, _y);
133
+ const auto p_affine = validate_point_g1 (_x, _y);
85
134
if (!p_affine.has_value ())
86
135
return false ;
87
136
@@ -94,8 +143,29 @@ void store_result(uint8_t _rx[64], uint8_t _ry[64], const blst_p1* out) noexcept
94
143
blst_p1 out;
95
144
blst_p1_mult (&out, &p, scalar.b , BLS_MODULUS_BITS);
96
145
97
- store_result (_rx, _ry, &out);
146
+ store_result_g1 (_rx, _ry, &out);
147
+
148
+ return true ;
149
+ }
150
+
151
+ [[nodiscard]] bool g2_add (uint8_t _rx[128 ], uint8_t _ry[128 ], const uint8_t _x0[128 ],
152
+ const uint8_t _y0[128 ], const uint8_t _x1[128 ], const uint8_t _y1[128 ]) noexcept
153
+ {
154
+ const auto p0_affine = validate_point_g2 (_x0, _y0);
155
+ const auto p1_affine = validate_point_g2 (_x1, _y1);
156
+
157
+ if (!p0_affine.has_value () || !p1_affine.has_value ())
158
+ return false ;
159
+
160
+ blst_p2 p0;
161
+ blst_p2_from_affine (&p0, &*p0_affine);
162
+
163
+ blst_p2 out;
164
+ blst_p2_add_or_double_affine (&out, &p0, &*p1_affine);
165
+
166
+ store_result_g2 (_rx, _ry, &out);
98
167
99
168
return true ;
100
169
}
170
+
101
171
} // namespace evmone::crypto::bls
0 commit comments