Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
ecc_op_queue.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
14namespace bb {
15
29 using Fq = Curve::BaseField; // Grumpkin's scalar field
31 Point point_at_infinity = Curve::Group::affine_point_at_infinity;
32
33 // The operations written to the queue are also performed natively; the result is stored in accumulator
35
36 EccvmOpsTable eccvm_ops_table; // table of ops in the ECCVM format
37 UltraEccOpsTable ultra_ops_table; // table of ops in the Ultra-arithmetization format
38
39 // Storage for the reconstructed eccvm ops table in contiguous memory. (Intended to be constructed once and for all
40 // prior to ECCVM construction to avoid repeated prepending of subtables in physical memory).
41 std::vector<ECCVMOperation> eccvm_ops_reconstructed;
42
43 // Storage for the reconstructed ultra ops table in contiguous memory. (Intended to be constructed once and for all
44 // prior to Translator circuit construction to avoid repeated prepending of subtables in physical memory).
45 std::vector<UltraOp> ultra_ops_reconstructed;
46
47 // Tracks number of muls and size of eccvm in real time as the op queue is updated
49
50 public:
51 static const size_t OP_QUEUE_SIZE = 1 << CONST_OP_QUEUE_LOG_SIZE;
56
66
68
70 {
71 eccvm_ops_table.merge(settings);
72 ultra_ops_table.merge(settings, ultra_fixed_offset);
73 }
74
75 // Construct polynomials corresponding to the columns of the full aggregate ultra ecc ops table
80
81 // Construct polys corresponding to the columns of the aggregate ultra ops table, excluding the most recent
82 // subtable
87
88 // Construct polynomials corresponding to the columns of the current subtable of ultra ecc ops
93
94 // Reconstruct the full table of eccvm ops in contiguous memory from the independent subtables
96
97 // Reconstruct the full table of ultra ops in contiguous memory from the independent subtables
99
103
104 // TODO(https://github.com/AztecProtocol/barretenberg/issues/1339): Consider making the ultra and eccvm ops
105 // getters more memory efficient
106
107 // Get the full table of ECCVM ops in contiguous memory; construct it if it has not been constructed already
108 std::vector<ECCVMOperation>& get_eccvm_ops()
109 {
110 if (eccvm_ops_reconstructed.empty()) {
112 }
114 }
115
116 std::vector<UltraOp>& get_ultra_ops()
117 {
118 if (ultra_ops_reconstructed.empty()) {
120 }
122 }
123
128
132 size_t get_num_rows() const { return eccvm_row_tracker.get_num_rows(); }
133
138
143 void set_eccvm_ops_for_fuzzing(std::vector<ECCVMOperation>& eccvm_ops_in)
144 {
145 eccvm_ops_reconstructed = eccvm_ops_in;
146 }
147
154 {
155 EccOpCode op_code{ .eq = true, .reset = true };
156 append_eccvm_op(ECCVMOperation{ .op_code = op_code, .base_point = Point::random_element() });
157 }
158
165 {
167 accumulator.self_set_infinity();
168 }
169
171
178 {
179 // Update the accumulator natively
180 accumulator = accumulator + to_add;
181 EccOpCode op_code{ .add = true };
182 // Store the eccvm operation
183 append_eccvm_op(ECCVMOperation{ .op_code = op_code, .base_point = to_add });
184
185 // Construct and store the operation in the ultra op format
186 return construct_and_populate_ultra_ops(op_code, to_add);
187 }
188
194 UltraOp mul_accumulate(const Point& to_mul, const Fr& scalar)
195 {
196 // Update the accumulator natively
197 accumulator = accumulator + to_mul * scalar;
198 EccOpCode op_code{ .mul = true };
199
200 // Construct and store the operation in the ultra op format
201 UltraOp ultra_op = construct_and_populate_ultra_ops(op_code, to_mul, scalar);
202
203 // Store the eccvm operation
205 .op_code = op_code,
206 .base_point = to_mul,
207 .z1 = ultra_op.z_1,
208 .z2 = ultra_op.z_2,
209 .mul_scalar_full = scalar,
210 });
211
212 return ultra_op;
213 }
214
223 {
224 UltraOp no_op{};
225 ultra_ops_table.push(no_op);
226 return no_op;
227 }
228
237 {
238 UltraOp random_op{ .op_code = EccOpCode{ .is_random_op = true,
239 .random_value_1 = Fr::random_element(),
240 .random_value_2 = Fr::random_element() },
241 .x_lo = Fr::random_element(),
242 .x_hi = Fr::random_element(),
243 .y_lo = Fr::random_element(),
244 .y_hi = Fr::random_element(),
245 .z_1 = Fr::random_element(),
246 .z_2 = Fr::random_element(),
247 .return_is_infinity = false };
248 ultra_ops_table.push(random_op);
249 return random_op;
250 }
251
258 {
259 auto expected = accumulator;
260 accumulator.self_set_infinity();
261 EccOpCode op_code{ .eq = true, .reset = true };
262 // Store eccvm operation
263 append_eccvm_op(ECCVMOperation{ .op_code = op_code, .base_point = expected });
264
265 // Construct and store the operation in the ultra op format
266 return construct_and_populate_ultra_ops(op_code, expected);
267 }
268
269 private:
287 UltraOp construct_and_populate_ultra_ops(EccOpCode op_code, const Point& point, const Fr& scalar = Fr::zero())
288 {
289 UltraOp ultra_op;
290 ultra_op.op_code = op_code;
291
292 // Decompose point coordinates (Fq) into hi-lo chunks (Fr)
293 const size_t CHUNK_SIZE = 2 * stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION;
294 uint256_t x_256(point.x);
295 uint256_t y_256(point.y);
296 ultra_op.return_is_infinity = point.is_point_at_infinity();
297 // if we have a point at infinity, set x/y to zero
298 // in the biggroup_goblin class we use `assert_equal` statements to validate
299 // the original in-circuit coordinate values are also zero
300 if (point.is_point_at_infinity()) {
301 x_256 = 0;
302 y_256 = 0;
303 }
304 ultra_op.x_lo = Fr(x_256.slice(0, CHUNK_SIZE));
305 ultra_op.x_hi = Fr(x_256.slice(CHUNK_SIZE, CHUNK_SIZE * 2));
306 ultra_op.y_lo = Fr(y_256.slice(0, CHUNK_SIZE));
307 ultra_op.y_hi = Fr(y_256.slice(CHUNK_SIZE, CHUNK_SIZE * 2));
308
309 // Split scalar into 128 bit endomorphism scalars
310 Fr z_1 = 0;
311 Fr z_2 = 0;
312 auto converted = scalar.from_montgomery_form();
313 uint256_t converted_u256(scalar);
314 if (converted_u256.get_msb() < 128) {
315 ultra_op.z_1 = scalar;
316 ultra_op.z_2 = 0;
317 } else {
318 Fr::split_into_endomorphism_scalars(converted, z_1, z_2);
319 ultra_op.z_1 = z_1.to_montgomery_form();
320 ultra_op.z_2 = z_2.to_montgomery_form();
321 }
322
323 ultra_ops_table.push(ultra_op);
324
325 return ultra_op;
326 }
327};
328
329} // namespace bb
Used to construct execution trace representations of elliptic curve operations.
Curve::ScalarField Fr
Curve::AffineElement Point
size_t get_num_rows() const
Get the number of rows for the current ECCVM circuit.
EccvmOpsTable eccvm_ops_table
std::vector< ECCVMOperation > eccvm_ops_reconstructed
void construct_full_eccvm_ops_table()
UltraOp add_accumulate(const Point &to_add)
Write point addition op to queue and natively perform addition.
std::array< Polynomial< Fr >, ULTRA_TABLE_WIDTH > construct_ultra_ops_table_columns() const
void initialize_new_subtable()
Initialize a new subtable for eccvm and ultra ops with the given merge settings.
Point get_accumulator()
size_t get_ultra_ops_table_num_rows() const
void merge(MergeSettings settings=MergeSettings::PREPEND, std::optional< size_t > ultra_fixed_offset=std::nullopt)
void construct_full_ultra_ops_table()
UltraEccOpsTable ultra_ops_table
void append_eccvm_op(const ECCVMOperation &op)
Append an eccvm operation to the eccvm ops table; update the eccvm row tracker.
uint32_t get_number_of_muls() const
get number of muls for the current ECCVM circuit
std::vector< ECCVMOperation > & get_eccvm_ops()
size_t get_num_msm_rows() const
Get the number of rows in the 'msm' column section, for all msms in the circuit.
std::vector< UltraOp > ultra_ops_reconstructed
std::array< Polynomial< Fr >, ULTRA_TABLE_WIDTH > construct_current_ultra_ops_subtable_columns() const
size_t get_current_ultra_ops_subtable_num_rows() const
UltraOp construct_and_populate_ultra_ops(EccOpCode op_code, const Point &point, const Fr &scalar=Fr::zero())
Given an ecc operation and its inputs, decompose into ultra format and populate ultra_ops.
UltraOp mul_accumulate(const Point &to_mul, const Fr &scalar)
Write multiply and add op to queue and natively perform operation.
std::vector< UltraOp > & get_ultra_ops()
std::array< Polynomial< Fr >, ULTRA_TABLE_WIDTH > construct_previous_ultra_ops_table_columns() const
UltraOp random_op_ultra_only()
Writes randomness to the ultra ops table but adds no eccvm operations.
UltraOp no_op_ultra_only()
Writes a no op (i.e. two zero rows) to the ultra ops table but adds no eccvm operations.
static const size_t OP_QUEUE_SIZE
UltraOp eq_and_reset()
Write equality op using internal accumulator point.
size_t get_current_subtable_size() const
void empty_row_for_testing()
Write empty row to queue.
ECCOpQueue()
Instantiate an initial ECC op subtable.
void set_eccvm_ops_for_fuzzing(std::vector< ECCVMOperation > &eccvm_ops_in)
A fuzzing only method for setting eccvm ops directly.
EccvmRowTracker eccvm_row_tracker
void add_erroneous_equality_op_for_testing()
A testing only method that adds an erroneous equality op to the eccvm ops.
size_t get_previous_ultra_ops_table_num_rows() const
static constexpr size_t ULTRA_TABLE_WIDTH
void create_new_subtable(size_t size_hint=0)
std::vector< OpFormat > get_reconstructed() const
void merge(MergeSettings settings=MergeSettings::PREPEND)
void push(const OpFormat &op)
Class for tracking the number of rows in the ECCVM circuit and the number of muls performed as the op...
size_t get_num_rows() const
Get the number of rows for the current ECCVM circuit.
size_t get_num_msm_rows() const
Get the number of rows in the 'msm' column section, for all msms in the circuit.
uint32_t get_number_of_muls() const
void update_cached_msms(const ECCVMOperation &op)
Update cached_active_msm_count or update other row counts and reset cached_active_msm_count.
Stores a table of elliptic curve operations represented in the Ultra format.
size_t get_current_subtable_size() const
void push(const UltraOp &op)
ColumnPolynomials construct_current_ultra_ops_subtable_columns() const
ColumnPolynomials construct_table_columns() const
ColumnPolynomials construct_previous_table_columns() const
void create_new_subtable(size_t size_hint=0)
size_t current_ultra_subtable_size() const
size_t previous_ultra_table_size() const
std::vector< UltraOp > get_reconstructed() const
static constexpr size_t TABLE_WIDTH
size_t ultra_table_size() const
void merge(MergeSettings settings=MergeSettings::PREPEND, std::optional< size_t > offset=std::nullopt)
bb::fq BaseField
Definition bn254.hpp:19
typename Group::affine_element AffineElement
Definition bn254.hpp:22
bb::fr ScalarField
Definition bn254.hpp:18
constexpr uint256_t slice(uint64_t start, uint64_t end) const
constexpr uint64_t get_msb() const
Entry point for Barretenberg command-line interface.
MergeSettings
The MergeSettings define whether an current subtable will be added at the beginning (PREPEND) or at t...
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
AffineElement base_point
Defines the opcodes for ECC operations used in both the Ultra and ECCVM formats. There are three opco...
bool return_is_infinity
EccOpCode op_code
BB_INLINE constexpr field to_montgomery_form() const noexcept
static void split_into_endomorphism_scalars(const field &k, field &k1, field &k2)
static field random_element(numeric::RNG *engine=nullptr) noexcept
BB_INLINE constexpr field from_montgomery_form() const noexcept
static constexpr field zero()