Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
affine_element.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
8
14#include <cstring>
15#include <type_traits>
16#include <vector>
17
19template <typename T>
20concept SupportsHashToCurve = T::can_hash_to_curve;
21template <typename Fq_, typename Fr_, typename Params_> class alignas(64) affine_element {
22 public:
23 using Fq = Fq_;
24 using Fr = Fr_;
25 using Params = Params_;
26
27 using in_buf = const uint8_t*;
28 using vec_in_buf = const uint8_t*;
29 using out_buf = uint8_t*;
30 using vec_out_buf = uint8_t**;
31
39
40 affine_element() noexcept = default;
41 ~affine_element() noexcept = default;
42
43 constexpr affine_element(const Fq& x, const Fq& y) noexcept;
44
45 constexpr affine_element(const affine_element& other) noexcept = default;
46
47 constexpr affine_element(affine_element&& other) noexcept = default;
48
49 static constexpr affine_element one() noexcept { return { Params::one_x, Params::one_y }; };
50
60 template <typename BaseField = Fq,
61 typename CompileTimeEnabled = std::enable_if_t<(BaseField::modulus >> 255) == uint256_t(0), void>>
62 static constexpr affine_element from_compressed(const uint256_t& compressed) noexcept;
63
73 template <typename BaseField = Fq,
74 typename CompileTimeEnabled = std::enable_if_t<(BaseField::modulus >> 255) == uint256_t(1), void>>
75 static constexpr std::array<affine_element, 2> from_compressed_unsafe(const uint256_t& compressed) noexcept;
76
77 constexpr affine_element& operator=(const affine_element& other) noexcept = default;
78
79 constexpr affine_element& operator=(affine_element&& other) noexcept = default;
80
81 constexpr affine_element operator+(const affine_element& other) const noexcept;
82
83 constexpr affine_element operator*(const Fr& exponent) const noexcept;
84
85 template <typename BaseField = Fq,
86 typename CompileTimeEnabled = std::enable_if_t<(BaseField::modulus >> 255) == uint256_t(0), void>>
87 [[nodiscard]] constexpr uint256_t compress() const noexcept;
88
89 static affine_element infinity();
90 constexpr affine_element set_infinity() const noexcept;
91 constexpr void self_set_infinity() noexcept;
92
93 [[nodiscard]] constexpr bool is_point_at_infinity() const noexcept;
94
95 [[nodiscard]] constexpr bool on_curve() const noexcept;
96
97 static constexpr std::optional<affine_element> derive_from_x_coordinate(const Fq& x, bool sign_bit) noexcept;
98
104 static affine_element random_element(numeric::RNG* engine = nullptr) noexcept;
105 static constexpr affine_element hash_to_curve(const std::vector<uint8_t>& seed, uint8_t attempt_count = 0) noexcept
106 requires SupportsHashToCurve<Params>;
107
108 constexpr bool operator==(const affine_element& other) const noexcept;
109
110 constexpr affine_element operator-() const noexcept { return { x, -y }; }
111
112 constexpr bool operator>(const affine_element& other) const noexcept;
113 constexpr bool operator<(const affine_element& other) const noexcept { return (other > *this); }
114
124 static void serialize_to_buffer(const affine_element& value, uint8_t* buffer, bool write_x_first = false)
125 {
126 using namespace serialize;
127 if (value.is_point_at_infinity()) {
128 // if we are infinity, just set all buffer bits to 1
129 // we only need this case because the below gets mangled converting from montgomery for infinity points
130 memset(buffer, 255, sizeof(Fq) * 2);
131 } else {
132 // Note: for historic reasons we will need to redo downstream hashes if we want this to always be written in
133 // the same order in our various serialization flows
134 write(buffer, write_x_first ? value.x : value.y);
135 write(buffer, write_x_first ? value.y : value.x);
136 }
137 }
138
151 static affine_element serialize_from_buffer(const uint8_t* buffer, bool write_x_first = false)
152 {
153 using namespace serialize;
154 // Does the buffer consist entirely of set bits? If so, we have a point at infinity
155 // Note that if it isn't, this loop should end early.
156 // We only need this case because the below gets mangled converting to montgomery for infinity points
158 std::all_of(buffer, buffer + sizeof(Fq) * 2, [](uint8_t val) { return val == 255; });
161 }
162 affine_element result;
163 // Note: for historic reasons we will need to redo downstream hashes if we want this to always be read in the
164 // same order in our various serialization flows
165 read(buffer, write_x_first ? result.x : result.y);
166 read(buffer, write_x_first ? result.y : result.x);
167 return result;
168 }
169
175 [[nodiscard]] inline std::vector<uint8_t> to_buffer() const
176 {
177 std::vector<uint8_t> buffer(sizeof(affine_element));
179 return buffer;
180 }
181
183 {
187
188 affine_element result;
189 result.x = Fq::reconstruct_from_public(x_limbs);
190 result.y = Fq::reconstruct_from_public(y_limbs);
191
192 ASSERT(result.on_curve());
193 return result;
194 }
195
196 friend std::ostream& operator<<(std::ostream& os, const affine_element& a)
197 {
198 os << "{ " << a.x << ", " << a.y << " }";
199 return os;
200 }
203
204 // Note: only applicable to field-templated curves (i.e. not something like G2).
210 void msgpack_pack(auto& packer) const
211 {
212 MsgpackRawAffineElement raw_element{};
213 if (is_point_at_infinity()) {
214 // If we are a point at infinity, just set all bits to 1
215 // We only need this case because the below gets mangled converting from montgomery for infinity points
216 constexpr uint256_t all_ones = {
217 0xffffffffffffffffUL, 0xffffffffffffffffUL, 0xffffffffffffffffUL, 0xffffffffffffffffUL
218 };
219 raw_element = { all_ones, all_ones };
220 } else {
221 // Note: internally calls from_montgomery_form()
222 raw_element = { x, y };
223 }
224 packer.pack(raw_element);
225 }
226 void msgpack_unpack(auto o)
227 {
228 using namespace serialize;
229 MsgpackRawAffineElement raw_element = o;
230 // If we are point and infinity, the serialized bits will be all ones.
231 constexpr uint256_t all_ones = {
232 0xffffffffffffffffUL, 0xffffffffffffffffUL, 0xffffffffffffffffUL, 0xffffffffffffffffUL
233 };
234 if (raw_element.x == all_ones && raw_element.y == all_ones) {
235 // If we are infinity, just set all bits to 1
236 // We only need this case because the below gets mangled converting from montgomery for infinity points
238 } else {
239 // Note: internally calls to_montgomery_form()
240 x = raw_element.x;
241 y = raw_element.y;
242 }
243 }
244 void msgpack_schema(auto& packer) const
245 {
246 if (packer.set_emitted("affine_element")) {
247 packer.pack("affine_element");
248 return; // already emitted
249 }
250 packer.pack_map(3);
251 packer.pack("__typename");
252 packer.pack("affine_element");
253 packer.pack("x");
254 packer.pack_schema(x);
255 packer.pack("y");
256 packer.pack_schema(y);
257 }
258};
259
260template <typename B, typename Fq_, typename Fr_, typename Params>
262{
263 using namespace serialize;
264 std::array<uint8_t, sizeof(element)> buffer;
265 read(it, buffer);
267 buffer.data(), /* use legacy field order */ true);
268}
269
270template <typename B, typename Fq_, typename Fr_, typename Params>
272{
273 using namespace serialize;
274 std::array<uint8_t, sizeof(element)> buffer;
276 element, buffer.data(), /* use legacy field order */ true);
277 write(it, buffer);
278}
279} // namespace bb::group_elements
280
#define ASSERT(expression,...)
Definition assert.hpp:49
friend std::ostream & operator<<(std::ostream &os, const affine_element &a)
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
constexpr affine_element & operator=(const affine_element &other) noexcept=default
static constexpr affine_element hash_to_curve(const std::vector< uint8_t > &seed, uint8_t attempt_count=0) noexcept
Hash a seed buffer into a point.
static affine_element random_element(numeric::RNG *engine=nullptr) noexcept
Samples a random point on the curve.
std::vector< uint8_t > to_buffer() const
Serialize the point to a byte vector.
void msgpack_pack(auto &packer) const
constexpr uint256_t compress() const noexcept
static affine_element serialize_from_buffer(const uint8_t *buffer, bool write_x_first=false)
Restore point from a buffer.
constexpr void self_set_infinity() noexcept
constexpr affine_element & operator=(affine_element &&other) noexcept=default
constexpr bool operator<(const affine_element &other) const noexcept
static affine_element reconstruct_from_public(const std::span< const bb::fr, PUBLIC_INPUTS_SIZE > &limbs)
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.
constexpr bool on_curve() const noexcept
static constexpr affine_element one() noexcept
static constexpr size_t PUBLIC_INPUTS_SIZE
static constexpr std::optional< affine_element > derive_from_x_coordinate(const Fq &x, bool sign_bit) noexcept
static void serialize_to_buffer(const affine_element &value, uint8_t *buffer, bool write_x_first=false)
Serialize the point to the given buffer.
constexpr bool operator>(const affine_element &other) const noexcept
constexpr affine_element operator*(const Fr &exponent) const noexcept
void msgpack_schema(auto &packer) const
constexpr affine_element set_infinity() const noexcept
element class. Implements ecc group arithmetic using Jacobian coordinates See https://hyperelliptic....
Definition element.hpp:33
FF a
numeric::RNG & engine
uint8_t buffer[RANDOM_BUFFER_SIZE]
Definition engine.cpp:34
void read(B &it, group_elements::affine_element< Fq_, Fr_, Params > &element)
void write(B &it, group_elements::affine_element< Fq_, Fr_, Params > const &element)
STL namespace.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr size_t PUBLIC_INPUTS_SIZE
static field reconstruct_from_public(const std::span< const field< V >, PUBLIC_INPUTS_SIZE > &limbs)