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