19static constexpr size_t ECC_NUM_RANDOM_OPS_START = 3;
20static constexpr size_t ECC_NUM_NO_OPS_START = 1;
21static constexpr size_t ECC_NUM_HIDING_OPS_START = 1;
50 [[nodiscard]] uint32_t
value()
const
53 throw_or_abort(
"EccOpCode::value() should not be called on a random op");
55 auto res =
static_cast<uint32_t
>(
add);
57 res +=
static_cast<uint32_t
>(
mul);
59 res +=
static_cast<uint32_t
>(
eq);
61 res +=
static_cast<uint32_t
>(
reset);
88 return {
Fq(0),
Fq(0) };
124 "Current subtable should be merged before computing the size of the full table of ecc ops.");
150 "Current subtable should be merged before attempting to index into the full table.");
161 "Unreachable: something has gone wrong with the subtable sizes, which do not add up to the table size.");
163 return table.front().front();
171 "current subtable should be merged before reconstructing the full table of operations.");
215 (ECC_NUM_RANDOM_OPS_START + ECC_NUM_NO_OPS_START + ECC_NUM_HIDING_OPS_START) *
NUM_ROWS_PER_OP;
255 constexpr size_t CHUNK_SIZE = 2 * stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION;
260 .x_lo =
Fr(x_256.
slice(0, CHUNK_SIZE)),
261 .x_hi =
Fr(x_256.
slice(CHUNK_SIZE, CHUNK_SIZE * 2)),
262 .y_lo =
Fr(y_256.
slice(0, CHUNK_SIZE)),
263 .y_hi =
Fr(y_256.
slice(CHUNK_SIZE, CHUNK_SIZE * 2)),
266 .return_is_infinity =
false,
269 return { ultra_op, eccvm_op };
319 "Current subtable should be merged before computing the size of table of operations up to the tail.");
322 for (
size_t subtable_idx = 0; subtable_idx <
table.
num_subtables() - 1; ++subtable_idx) {
340 size_t prior_subtables_size = 0;
341 for (
const auto& subtable :
table.
get()) {
342 prior_subtables_size += subtable.size();
346 "Merged table size exceeds fixed append offset. This means that there are too many ops before "
347 "the last subtable. The last subtable doesn't fit at the end of the op queue.");
370 "current subtable should be merged before reconstructing the full table of operations.");
371 BB_ASSERT(!include_zk_ops ||
has_zk_ops(),
"ZK ops must be constructed before reconstructing the Ultra table.");
373 std::vector<UltraOp> reconstructed_table;
374 reconstructed_table.reserve(1 << CONST_OP_QUEUE_LOG_SIZE);
376 if (include_zk_ops) {
377 reconstructed_table.insert(reconstructed_table.end(),
zk_ops.begin(),
zk_ops.end());
381 for (
const auto& subtable :
table.
get()) {
382 reconstructed_table.insert(reconstructed_table.end(), subtable.begin(), subtable.end());
384 return reconstructed_table;
389 const auto& subtable =
table.
get()[idx];
390 reconstructed_table.insert(reconstructed_table.end(), subtable.begin(), subtable.end());
395 const size_t zk_offset_ops = include_zk_ops ?
zk_ops.size() : 0;
396 const size_t target_op_count =
fixed_append_offset.value() + zk_offset_ops + preamble_op_slots;
398 reconstructed_table.size(), target_op_count,
"Current table size is larger than fixed append offset.");
399 reconstructed_table.insert(
400 reconstructed_table.end(), target_op_count - reconstructed_table.size(),
UltraOp{ });
403 const auto& final_subtable =
table.
get().back();
404 reconstructed_table.insert(reconstructed_table.end(), final_subtable.begin(), final_subtable.end());
405 return reconstructed_table;
414 for (
size_t idx = 0; idx < ECC_NUM_NO_OPS_START; idx++) {
420 for (
size_t idx = 0; idx < ECC_NUM_RANDOM_OPS_START; idx++) {
430 .return_is_infinity =
false });
435 zk_ops.push_back(hiding_ultra_op);
442 for (
auto& poly : column_polynomials) {
447 for (
const auto& op :
zk_ops) {
452 return { column_polynomials, hiding_eccvm_op };
461 const auto& subtable =
table.
get()[idx];
464 subtable_columns.push_back(
std::move(columns));
467 return subtable_columns;
474 "ZK ops must be constructed before constructing the full Ultra table with ZK ops.");
482 BB_ASSERT(
has_zk_ops(),
"ZK ops should have been constructed before constructing the table up to tail");
485 "There should be at least two subtables (including the tail) to construct the table up to tail");
499 const auto& subtable =
table.
get().back();
500 const size_t poly_size = leading_zeros + (subtable.size() *
NUM_ROWS_PER_OP);
503 if (poly_size == 0) {
504 return column_polynomials;
506 for (
auto& poly : column_polynomials) {
510 size_t row = leading_zeros;
511 for (
const auto& op : subtable) {
515 return column_polynomials;
529 column_polynomials[1].at(row_idx) = op.
x_lo;
530 column_polynomials[2].at(row_idx) = op.
x_hi;
531 column_polynomials[3].at(row_idx) = op.
y_lo;
533 column_polynomials[1].at(row_idx + 1) = op.
y_hi;
534 column_polynomials[2].at(row_idx + 1) = op.
z_1;
535 column_polynomials[3].at(row_idx + 1) = op.
z_2;
551 const size_t poly_size,
552 const size_t subtable_start_idx,
553 const size_t subtable_end_idx,
554 const bool include_zk_ops =
false,
557 const size_t final_poly_size = poly_size + (include_zk_ops ?
ZK_ULTRA_OPS : 0);
560 if (final_poly_size == 0) {
561 return column_polynomials;
563 for (
auto& poly : column_polynomials) {
569 if (include_zk_ops) {
570 BB_ASSERT(
has_zk_ops(),
"ZK ops should have been constructed before including them in the columns");
571 for (
const auto& op :
zk_ops) {
579 const size_t sequential_end =
580 fixed_append_offset_for_last.has_value() ? subtable_end_idx - 1 : subtable_end_idx;
581 for (
size_t idx = subtable_start_idx; idx < sequential_end; ++idx) {
582 for (
const auto& op :
table.
get()[idx]) {
588 if (fixed_append_offset_for_last.has_value()) {
592 for (
const auto& op :
table.
get()[subtable_end_idx - 1]) {
598 return column_polynomials;
#define BB_ASSERT(expression,...)
#define BB_ASSERT_GT(left, right,...)
#define BB_ASSERT_EQ(actual, expected,...)
#define BB_ASSERT_LTE(left, right,...)
#define BB_ASSERT_LT(left, right,...)
A table of ECC operations.
std::vector< OpFormat > Subtable
std::vector< Subtable > table
size_t get_current_subtable_size() const
void create_new_subtable(size_t size_hint=0)
Subtable current_subtable
size_t num_subtables() const
std::vector< OpFormat > get_reconstructed() const
const OpFormat & operator[](size_t index) const
void push(const OpFormat &op)
Stores a table of elliptic curve operations represented in the Ultra format.
std::pair< ColumnPolynomials, ECCVMOperation > construct_zk_columns()
size_t get_current_subtable_size() const
std::vector< UltraOp > zk_ops
std::optional< size_t > fixed_append_offset
size_t ultra_table_size_up_to_tail() const
std::vector< ColumnPolynomials > construct_subtable_columns() const
void push(const UltraOp &op)
size_t num_ultra_rows() const
static constexpr size_t compute_fixed_append_offset(size_t append_offset, bool include_zk_prefix=true)
Shift size of the APPEND merge: the start row of the appended subtable's polynomial in the merged tab...
ColumnPolynomials construct_current_ultra_ops_subtable_columns() const
static constexpr size_t compute_fixed_append_ops_row(size_t append_offset, bool include_zk_prefix)
static constexpr size_t APPEND_TRACE_OFFSET
ColumnPolynomials construct_table_columns_up_to_tail() const
std::array< Polynomial< Fr >, TABLE_WIDTH > ColumnPolynomials
std::vector< UltraOp > get_reconstructed(const bool include_zk_ops) const
static constexpr size_t NUM_ROWS_PER_OP
ColumnPolynomials construct_columns_in_range(const size_t poly_size, const size_t subtable_start_idx, const size_t subtable_end_idx, const bool include_zk_ops=false, const std::optional< size_t > fixed_append_offset_for_last=std::nullopt) const
Construct column polynomials covering subtables [start, end), optionally with a ZK prefix and an opti...
void create_new_subtable(size_t size_hint=0)
static std::pair< UltraOp, ECCVMOperation > make_hiding_op_pair(const curve::BN254::BaseField &Px, const curve::BN254::BaseField &Py)
Build a hiding op as paired Ultra and ECCVM operations from raw Fq coordinates.
std::vector< UltraOp > get_no_zk_reconstructed_ultra_ops() const
bool has_fixed_append_offset() const
static void write_op_to_polynomials(ColumnPolynomials &column_polynomials, const UltraOp &op, const size_t row_idx)
Write a single UltraOp to the column polynomials at the given position.
static constexpr size_t TABLE_WIDTH
ColumnPolynomials construct_table_columns(const bool include_zk_ops=true) const
static constexpr size_t ZK_ULTRA_OPS
void merge_with_fixed_append_offset(size_t offset)
std::vector< UltraOp > get_zk_reconstructed_ultra_ops() const
typename Group::affine_element AffineElement
constexpr uint256_t slice(uint64_t start, uint64_t end) const
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Curve::Group::affine_element AffineElement
bool operator==(const ECCVMOperation &other) const =default
Defines the opcodes for ECC operations used in both the Ultra and ECCVM formats. There are three opco...
bool operator==(const EccOpCode &other) const =default
curve::BN254::ScalarField Fr
bool operator==(const UltraOp &other) const =default
std::array< Fq, 2 > get_base_point_standard_form() const
Get the point in standard form i.e. as two coordinates x and y in the base field or as a point at inf...
curve::BN254::BaseField Fq
static field random_element(numeric::RNG *engine=nullptr) noexcept
void throw_or_abort(std::string const &err)