13template <
class Fq,
class Fr,
class T>
19template <
class Fq,
class Fr,
class T>
20template <
typename BaseField,
typename CompileTimeEnabled>
24 x_coordinate.
data[3] = x_coordinate.
data[3] & (~UINT256_TOP_LIMB_MSB);
25 bool y_bit = compressed.get_bit(255);
27 Fq x =
Fq(x_coordinate);
28 Fq y2 = (x.sqr() * x + T::b);
29 if constexpr (T::has_a) {
32 auto [is_quadratic_remainder, y] = y2.sqrt();
33 if (!is_quadratic_remainder) {
43template <
class Fq,
class Fr,
class T>
44template <
typename BaseField,
typename CompileTimeEnabled>
55 Fq x =
Fq(x_coordinate);
56 Fq y2 = ((x.sqr() * x) + T::b);
57 if constexpr (T::has_a) {
60 auto [is_qr, y] = y2.sqrt();
64 return { try_candidate(compressed), try_candidate(compressed +
Fr::modulus) };
67template <
class Fq,
class Fr,
class T>
74template <
class Fq,
class Fr,
class T>
87template <
class Fq,
class Fr,
class T>
97 if constexpr (
Fq::modulus.
data[3] >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) {
115 if constexpr (
Fq::modulus.
data[3] >= MODULUS_TOP_LIMB_LARGE_THRESHOLD) {
121 return (x.is_msb_set());
127 if (is_point_at_infinity()) {
130 Fq xxx = x.
sqr() * x + T::b;
132 if constexpr (T::has_a) {
140 if (is_point_at_infinity()) {
153 const uint64_t r_msb = r.
get_msb();
158 for (uint64_t i = r_msb - 1; i < r_msb; --i) {
164 return acc.is_point_at_infinity();
167template <
class Fq,
class Fr,
class T>
170 bool this_is_infinity = is_point_at_infinity();
171 bool other_is_infinity = other.is_point_at_infinity();
172 bool both_infinity = this_is_infinity && other_is_infinity;
173 bool only_one_is_infinity = this_is_infinity != other_is_infinity;
174 return !only_one_is_infinity && (both_infinity || ((x == other.x) && (y == other.y)));
177template <
class Fq,
class Fr,
class T>
180 if (is_point_at_infinity()) {
183 if (other.is_point_at_infinity()) {
190 if (x == other.x && y > other.y) {
196template <
class Fq,
class Fr,
class T>
198 const Fq& x,
bool sign_bit)
noexcept
200 auto yy = x.sqr() * x + T::b;
201 if constexpr (T::has_a) {
204 auto [found_root, y] = yy.sqrt();
247template <
class Fq,
class Fr,
class T>
249 uint8_t attempt_count)
noexcept
252 std::vector<uint8_t> target_seed(seed);
254 const size_t seed_size = seed.size();
255 for (
size_t i = 0; i < 2; ++i) {
256 target_seed.push_back(0);
258 target_seed[seed_size] = attempt_count;
259 target_seed[seed_size + 1] = 0;
261 target_seed[seed_size + 1] = 1;
265 const auto read_limb = [](
const uint8_t* in, uint64_t& out) {
266 for (
size_t i = 0; i < 8; ++i) {
267 out +=
static_cast<uint64_t
>(in[i]) << ((7 - i) * 8);
271 read_limb(&in[0], out.
data[3]);
272 read_limb(&in[8], out.
data[2]);
273 read_limb(&in[16], out.
data[1]);
274 read_limb(&in[24], out.
data[0]);
280 bool sign_bit = hash_hi[0] > 127;
282 if (result.has_value()) {
283 return result.value();
285 return hash_to_curve(seed, attempt_count + 1);
288template <
typename Fq,
typename Fr,
typename T>
301 bool sign_bit = (
engine->get_random_uint8() & 1) != 0;
305 if (result.has_value()) {
306 return result.value();
bool is_in_prime_subgroup() const noexcept
Check that the point lies in the prime-order subgroup of size Fr::modulus.
static constexpr std::array< affine_element, 2 > from_compressed_unsafe(const uint256_t &compressed) noexcept
Reconstruct a point in affine coordinates from compressed form.
constexpr bool is_point_at_infinity() const noexcept
static affine_element random_element(numeric::RNG *engine=nullptr) noexcept
Samples a random point on the curve.
constexpr void self_set_infinity() noexcept
static constexpr affine_element infinity()
constexpr affine_element operator+(const affine_element &other) const noexcept
static constexpr affine_element from_compressed(const uint256_t &compressed) noexcept
Reconstruct a point in affine coordinates from compressed form.
static affine_element hash_to_curve(const std::vector< uint8_t > &seed, uint8_t attempt_count=0) noexcept
Hash a seed buffer into a point.
constexpr bool on_curve() const noexcept
affine_element() noexcept=default
constexpr bool operator==(const affine_element &other) const noexcept
static constexpr std::optional< affine_element > derive_from_x_coordinate(const Fq &x, bool sign_bit) noexcept
constexpr bool operator>(const affine_element &other) const noexcept
constexpr affine_element operator*(const Fr &exponent) const noexcept
constexpr affine_element set_infinity() const noexcept
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
constexpr bool get_bit(uint64_t bit_index) const
constexpr uint64_t get_msb() const
bb::curve::BN254::Element Element
uint256_t read_uint256(const uint8_t *data, size_t buffer_size=32)
AffineElement const size_t Fq *scratch_space noexcept
uintx< uint256_t > uint512_t
constexpr std::array< uint8_t, BLAKE3_OUT_LEN > blake3s_constexpr(const uint8_t *input, size_t input_size)
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
static constexpr uint256_t modulus
static field random_element(numeric::RNG *engine=nullptr) noexcept
BB_INLINE constexpr field sqr() const noexcept
static constexpr field zero()
void throw_or_abort(std::string const &err)