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;
243 constexpr size_t CHUNK_SIZE = 2 * stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION;
248 .x_lo =
Fr(x_256.
slice(0, CHUNK_SIZE)),
249 .x_hi =
Fr(x_256.
slice(CHUNK_SIZE, CHUNK_SIZE * 2)),
250 .y_lo =
Fr(y_256.
slice(0, CHUNK_SIZE)),
251 .y_hi =
Fr(y_256.
slice(CHUNK_SIZE, CHUNK_SIZE * 2)),
254 .return_is_infinity =
false,
257 return { ultra_op, eccvm_op };
298 "Current subtable should be merged before computing the size of table of operations up to the tail.");
301 for (
size_t subtable_idx = 0; subtable_idx <
table.
num_subtables() - 1; ++subtable_idx) {
319 size_t prior_subtables_size = 0;
320 for (
const auto& subtable :
table.
get()) {
321 prior_subtables_size += subtable.size();
325 "Merged table size exceeds fixed append offset. This means that there are too many ops before "
326 "the last subtable. The last subtable doesn't fit at the end of the op queue.");
349 "current subtable should be merged before reconstructing the full table of operations.");
350 BB_ASSERT(!include_zk_ops ||
has_zk_ops(),
"ZK ops must be constructed before reconstructing the Ultra table.");
352 std::vector<UltraOp> reconstructed_table;
353 reconstructed_table.reserve(1 << CONST_OP_QUEUE_LOG_SIZE);
355 if (include_zk_ops) {
356 reconstructed_table.insert(reconstructed_table.end(),
zk_ops.begin(),
zk_ops.end());
360 for (
const auto& subtable :
table.
get()) {
361 reconstructed_table.insert(reconstructed_table.end(), subtable.begin(), subtable.end());
363 return reconstructed_table;
368 const auto& subtable =
table.
get()[idx];
369 reconstructed_table.insert(reconstructed_table.end(), subtable.begin(), subtable.end());
374 const size_t zk_offset_ops = include_zk_ops ?
zk_ops.size() : 0;
375 const size_t target_op_count =
fixed_append_offset.value() + zk_offset_ops + preamble_op_slots;
377 reconstructed_table.size(), target_op_count,
"Current table size is larger than fixed append offset.");
378 reconstructed_table.insert(
379 reconstructed_table.end(), target_op_count - reconstructed_table.size(),
UltraOp{ });
382 const auto& final_subtable =
table.
get().back();
383 reconstructed_table.insert(reconstructed_table.end(), final_subtable.begin(), final_subtable.end());
384 return reconstructed_table;
393 for (
size_t idx = 0; idx < ECC_NUM_NO_OPS_START; idx++) {
399 for (
size_t idx = 0; idx < ECC_NUM_RANDOM_OPS_START; idx++) {
409 .return_is_infinity =
false });
414 zk_ops.push_back(hiding_ultra_op);
421 for (
auto& poly : column_polynomials) {
426 for (
const auto& op :
zk_ops) {
431 return { column_polynomials, hiding_eccvm_op };
440 const auto& subtable =
table.
get()[idx];
443 subtable_columns.push_back(
std::move(columns));
446 return subtable_columns;
453 "ZK ops must be constructed before constructing the full Ultra table with ZK ops.");
461 BB_ASSERT(
has_zk_ops(),
"ZK ops should have been constructed before constructing the table up to tail");
464 "There should be at least two subtables (including the tail) to construct the table up to tail");
478 const auto& subtable =
table.
get().back();
479 const size_t poly_size = leading_zeros + (subtable.size() *
NUM_ROWS_PER_OP);
482 if (poly_size == 0) {
483 return column_polynomials;
485 for (
auto& poly : column_polynomials) {
489 size_t row = leading_zeros;
490 for (
const auto& op : subtable) {
494 return column_polynomials;
508 column_polynomials[1].at(row_idx) = op.
x_lo;
509 column_polynomials[2].at(row_idx) = op.
x_hi;
510 column_polynomials[3].at(row_idx) = op.
y_lo;
512 column_polynomials[1].at(row_idx + 1) = op.
y_hi;
513 column_polynomials[2].at(row_idx + 1) = op.
z_1;
514 column_polynomials[3].at(row_idx + 1) = op.
z_2;
530 const size_t poly_size,
531 const size_t subtable_start_idx,
532 const size_t subtable_end_idx,
533 const bool include_zk_ops =
false,
536 const size_t final_poly_size = poly_size + (include_zk_ops ?
ZK_ULTRA_OPS : 0);
539 if (final_poly_size == 0) {
540 return column_polynomials;
542 for (
auto& poly : column_polynomials) {
548 if (include_zk_ops) {
549 BB_ASSERT(
has_zk_ops(),
"ZK ops should have been constructed before including them in the columns");
550 for (
const auto& op :
zk_ops) {
558 const size_t sequential_end =
559 fixed_append_offset_for_last.has_value() ? subtable_end_idx - 1 : subtable_end_idx;
560 for (
size_t idx = subtable_start_idx; idx < sequential_end; ++idx) {
561 for (
const auto& op :
table.
get()[idx]) {
567 if (fixed_append_offset_for_last.has_value()) {
568 const size_t zk_prefix_rows = include_zk_ops ?
ZK_ULTRA_OPS : 0;
571 for (
const auto& op :
table.
get()[subtable_end_idx - 1]) {
577 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)
Structured polynomial class that represents the coefficients 'a' of a_0 + a_1 x .....
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
ColumnPolynomials construct_current_ultra_ops_subtable_columns() const
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)