@@ -12,57 +12,63 @@ namespace
1212// / https://eips.ethereum.org/EIPS/eip-2537#field-elements-encoding
1313constexpr auto FP_BYTES_OFFSET = 64 - 48 ;
1414
15+ // / Validates that integer encoded in big endian is valid element of BLS12-381 Fp field
16+ [[nodiscard]] std::optional<blst_fp> validate_fp (const uint8_t _p[64 ]) noexcept
17+ {
18+ if (intx::be::unsafe::load<intx::uint512>(_p) >= BLS_FIELD_MODULUS )
19+ return std::nullopt ;
20+
21+ blst_fp p;
22+ blst_fp_from_bendian (&p, &_p[FP_BYTES_OFFSET ]);
23+ return p;
24+ }
25+
1526// / Validates p1 affine point. Checks that point coordinates are from the BLS12-381 field and
1627// / that the point is on curve. https://eips.ethereum.org/EIPS/eip-2537#abi-for-g1-addition
1728[[nodiscard]] std::optional<blst_p1_affine> validate_p1 (
1829 const uint8_t _x[64 ], const uint8_t _y[64 ]) noexcept
1930{
20- constexpr auto is_field_element = [](const uint8_t _p[64 ]) {
21- return intx::be::unsafe::load<intx::uint512>(_p) < BLS_FIELD_MODULUS ;
22- };
23-
24- if (!is_field_element (_x))
31+ const auto x = validate_fp (_x);
32+ if (!x.has_value ())
2533 return std::nullopt ;
26- if (!is_field_element (_y))
34+ const auto y = validate_fp (_y);
35+ if (!y.has_value ())
2736 return std::nullopt ;
2837
29- blst_fp x;
30- blst_fp y;
31- blst_fp_from_bendian (&x, &_x[FP_BYTES_OFFSET ]);
32- blst_fp_from_bendian (&y, &_y[FP_BYTES_OFFSET ]);
33-
34- const blst_p1_affine p0_affine{x, y};
38+ const blst_p1_affine p0_affine{*x, *y};
3539 if (!blst_p1_affine_on_curve (&p0_affine))
3640 return std::nullopt ;
3741
3842 return p0_affine;
3943}
4044
45+ // / Validates that integer encoded in big endian is valid element of BLS12-381 Fp2 extension field
46+ [[nodiscard]] std::optional<blst_fp2> validate_fp2 (const uint8_t _p[128 ]) noexcept
47+ {
48+ const auto fp0 = validate_fp (_p);
49+ if (!fp0.has_value ())
50+ return std::nullopt ;
51+ const auto fp1 = validate_fp (&_p[64 ]);
52+ if (!fp1.has_value ())
53+ return std::nullopt ;
54+
55+ return {{*fp0, *fp1}};
56+ }
57+
4158// / Validates p2 affine point. Checks that point coordinates are from the BLS12-381 field and
4259// / that the point is on curve. https://eips.ethereum.org/EIPS/eip-2537#abi-for-g2-addition
4360[[nodiscard]] std::optional<blst_p2_affine> validate_p2 (
4461 const uint8_t _x[128 ], const uint8_t _y[128 ]) noexcept
4562{
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))
63+ const auto x = validate_fp2 (_x);
64+ if (!x.has_value ())
5465 return std::nullopt ;
5566
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 ]);
67+ const auto y = validate_fp2 (_y);
68+ if (!y.has_value ())
69+ return std::nullopt ;
6470
65- const blst_p2_affine p_affine{{x0, x1}, {y0, y1} };
71+ const blst_p2_affine p_affine{*x, *y };
6672 if (!blst_p2_affine_on_curve (&p_affine))
6773 return std::nullopt ;
6874
@@ -315,4 +321,39 @@ void store(uint8_t _rx[128], const blst_fp2& _x) noexcept
315321 return true ;
316322}
317323
324+ [[nodiscard]] bool map_fp_to_g1 (uint8_t _rx[64 ], uint8_t _ry[64 ], const uint8_t _fp[64 ]) noexcept
325+ {
326+ const auto fp = validate_fp (_fp);
327+ if (!fp.has_value ())
328+ return false ;
329+
330+ blst_p1 out;
331+ blst_map_to_g1 (&out, &*fp);
332+
333+ blst_p1_affine result;
334+ blst_p1_to_affine (&result, &out);
335+ store (_rx, result.x );
336+ store (_ry, result.y );
337+
338+ return true ;
339+ }
340+
341+ [[nodiscard]] bool map_fp2_to_g2 (
342+ uint8_t _rx[128 ], uint8_t _ry[128 ], const uint8_t _fp2[128 ]) noexcept
343+ {
344+ const auto fp2 = validate_fp2 (_fp2);
345+ if (!fp2.has_value ())
346+ return false ;
347+
348+ blst_p2 out;
349+ blst_map_to_g2 (&out, &*fp2);
350+
351+ blst_p2_affine result;
352+ blst_p2_to_affine (&result, &out);
353+ store (_rx, result.x );
354+ store (_ry, result.y );
355+
356+ return true ;
357+ }
358+
318359} // namespace evmone::crypto::bls
0 commit comments