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