barretenberg
Loading...
Searching...
No Matches
eccvm_circuit_builder.hpp
1#pragma once
2
3#include "./eccvm_builder_types.hpp"
4#include "./msm_builder.hpp"
5#include "./precomputed_tables_builder.hpp"
6#include "./transcript_builder.hpp"
7#include "barretenberg/ecc/curves/bn254/fr.hpp"
8#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp"
9#include "barretenberg/flavor/ecc_vm.hpp"
10#include "barretenberg/honk/proof_system/logderivative_library.hpp"
11#include "barretenberg/honk/proof_system/permutation_library.hpp"
12#include "barretenberg/proof_system/op_queue/ecc_op_queue.hpp"
13#include "barretenberg/relations/relation_parameters.hpp"
14
15namespace proof_system {
16
17template <typename Flavor> class ECCVMCircuitBuilder {
18 public:
19 using CycleGroup = typename Flavor::CycleGroup;
20 using FF = typename Flavor::FF;
21 using Polynomial = typename Flavor::Polynomial;
22
23 using CycleScalar = typename CycleGroup::subgroup_field;
24 using Element = typename CycleGroup::element;
25 using AffineElement = typename CycleGroup::affine_element;
26
27 static constexpr size_t NUM_SCALAR_BITS = proof_system_eccvm::NUM_SCALAR_BITS;
28 static constexpr size_t WNAF_SLICE_BITS = proof_system_eccvm::WNAF_SLICE_BITS;
29 static constexpr size_t NUM_WNAF_SLICES = proof_system_eccvm::NUM_WNAF_SLICES;
30 static constexpr uint64_t WNAF_MASK = proof_system_eccvm::WNAF_MASK;
31 static constexpr size_t POINT_TABLE_SIZE = proof_system_eccvm::POINT_TABLE_SIZE;
32 static constexpr size_t WNAF_SLICES_PER_ROW = proof_system_eccvm::WNAF_SLICES_PER_ROW;
33 static constexpr size_t ADDITIONS_PER_ROW = proof_system_eccvm::ADDITIONS_PER_ROW;
34
35 static constexpr size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES;
36 static constexpr size_t NUM_WIRES = Flavor::NUM_WIRES;
37
38 using MSM = proof_system_eccvm::MSM<CycleGroup>;
40 std::shared_ptr<ECCOpQueue> op_queue;
42 using ProverPolynomials = typename Flavor::ProverPolynomials;
43
45 : op_queue(std::make_shared<ECCOpQueue>()){};
46
47 ECCVMCircuitBuilder(std::shared_ptr<ECCOpQueue>& op_queue)
48 : op_queue(op_queue){};
49
50 [[nodiscard]] uint32_t get_number_of_muls() const
51 {
52 uint32_t num_muls = 0;
53 for (auto& op : op_queue->raw_ops) {
54 if (op.mul) {
55 if (op.z1 != 0) {
56 num_muls++;
57 }
58 if (op.z2 != 0) {
59 num_muls++;
60 }
61 }
62 }
63 return num_muls;
64 }
65
66 std::vector<MSM> get_msms() const
67 {
68 const uint32_t num_muls = get_number_of_muls();
72 const auto compute_precomputed_table = [](const AffineElement& base_point) {
73 const auto d2 = Element(base_point).dbl();
74 std::array<AffineElement, POINT_TABLE_SIZE> table;
75 table[POINT_TABLE_SIZE / 2] = base_point;
76 for (size_t i = 1; i < POINT_TABLE_SIZE / 2; ++i) {
77 table[i + POINT_TABLE_SIZE / 2] = Element(table[i + POINT_TABLE_SIZE / 2 - 1]) + d2;
78 }
79 for (size_t i = 0; i < POINT_TABLE_SIZE / 2; ++i) {
80 table[i] = -table[POINT_TABLE_SIZE - 1 - i];
81 }
82 return table;
83 };
84 const auto compute_wnaf_slices = [](uint256_t scalar) {
85 std::array<int, NUM_WNAF_SLICES> output;
86 int previous_slice = 0;
87 for (size_t i = 0; i < NUM_WNAF_SLICES; ++i) {
88 // slice the scalar into 4-bit chunks, starting with the least significant bits
89 uint64_t raw_slice = static_cast<uint64_t>(scalar) & WNAF_MASK;
90
91 bool is_even = ((raw_slice & 1ULL) == 0ULL);
92
93 int wnaf_slice = static_cast<int>(raw_slice);
94
95 if (i == 0 && is_even) {
96 // if least significant slice is even, we add 1 to create an odd value && set 'skew' to true
97 wnaf_slice += 1;
98 } else if (is_even) {
99 // for other slices, if it's even, we add 1 to the slice value
100 // and subtract 16 from the previous slice to preserve the total scalar sum
101 static constexpr int borrow_constant = static_cast<int>(1ULL << WNAF_SLICE_BITS);
102 previous_slice -= borrow_constant;
103 wnaf_slice += 1;
104 }
105
106 if (i > 0) {
107 const size_t idx = i - 1;
108 output[NUM_WNAF_SLICES - idx - 1] = previous_slice;
109 }
110 previous_slice = wnaf_slice;
111
112 // downshift raw_slice by 4 bits
113 scalar = scalar >> WNAF_SLICE_BITS;
114 }
115
116 ASSERT(scalar == 0);
117
118 output[0] = previous_slice;
119
120 return output;
121 };
122 std::vector<MSM> msms;
123 std::vector<ScalarMul> active_msm;
124
125 // We start pc at `num_muls` and decrement for each mul processed.
126 // This gives us two desired properties:
127 // 1: the value of pc at the 1st row = number of muls (easy to check)
128 // 2: the value of pc for the final mul = 1
129 // The latter point is valuable as it means that we can add empty rows (where pc = 0) and still satisfy our
130 // sumcheck relations that involve pc (if we did the other way around, starting at 1 and ending at num_muls,
131 // we create a discontinuity in pc values between the last transcript row and the following empty row)
132 uint32_t pc = num_muls;
133
134 const auto process_mul = [&active_msm, &pc, &compute_wnaf_slices, &compute_precomputed_table](
135 const auto& scalar, const auto& base_point) {
136 if (scalar != 0) {
137 active_msm.push_back(ScalarMul{
138 .pc = pc,
139 .scalar = scalar,
140 .base_point = base_point,
141 .wnaf_slices = compute_wnaf_slices(scalar),
142 .wnaf_skew = (scalar & 1) == 0,
143 .precomputed_table = compute_precomputed_table(base_point),
144 });
145 pc--;
146 }
147 };
148
149 for (auto& op : op_queue->raw_ops) {
150 if (op.mul) {
151 process_mul(op.z1, op.base_point);
152 process_mul(op.z2, AffineElement{ op.base_point.x * FF::cube_root_of_unity(), -op.base_point.y });
153
154 } else {
155 if (!active_msm.empty()) {
156 msms.push_back(active_msm);
157 active_msm = {};
158 }
159 }
160 }
161 if (!active_msm.empty()) {
162 msms.push_back(active_msm);
163 }
164
165 ASSERT(pc == 0);
166 return msms;
167 }
168
169 static std::vector<ScalarMul> get_flattened_scalar_muls(const std::vector<MSM>& msms)
170 {
171 std::vector<ScalarMul> result;
172 for (const auto& msm : msms) {
173 for (const auto& mul : msm) {
174 result.push_back(mul);
175 }
176 }
177 return result;
178 }
179
180 void add_accumulate(const AffineElement& to_add)
181 {
182 op_queue->raw_ops.emplace_back(VMOperation{
183 .add = true,
184 .mul = false,
185 .eq = false,
186 .reset = false,
187 .base_point = to_add,
188 .z1 = 0,
189 .z2 = 0,
190 .mul_scalar_full = 0,
191 });
192 }
193
194 void mul_accumulate(const AffineElement& to_mul, const CycleScalar& scalar)
195 {
196 CycleScalar z1 = 0;
197 CycleScalar z2 = 0;
198 auto converted = scalar.from_montgomery_form();
199 CycleScalar::split_into_endomorphism_scalars(converted, z1, z2);
200 z1 = z1.to_montgomery_form();
201 z2 = z2.to_montgomery_form();
202 op_queue->raw_ops.emplace_back(VMOperation{
203 .add = false,
204 .mul = true,
205 .eq = false,
206 .reset = false,
207 .base_point = to_mul,
208 .z1 = z1,
209 .z2 = z2,
210 .mul_scalar_full = scalar,
211 });
212 }
213
214 void eq_and_reset(const AffineElement& expected)
215 {
216 op_queue->raw_ops.emplace_back(VMOperation{
217 .add = false,
218 .mul = false,
219 .eq = true,
220 .reset = true,
221 .base_point = expected,
222 .z1 = 0,
223 .z2 = 0,
224 .mul_scalar_full = 0,
225 });
226 }
227
228 void empty_row()
229 {
230 op_queue->raw_ops.emplace_back(VMOperation{
231 .add = false,
232 .mul = false,
233 .eq = false,
234 .reset = false,
235 .base_point = CycleGroup::affine_point_at_infinity,
236 .z1 = 0,
237 .z2 = 0,
238 .mul_scalar_full = 0,
239 });
240 }
241
320 ProverPolynomials compute_polynomials()
321 {
322 const auto msms = get_msms();
323 const auto flattened_muls = get_flattened_scalar_muls(msms);
324
325 std::array<std::vector<size_t>, 2> point_table_read_counts;
326 const auto transcript_state =
327 ECCVMTranscriptBuilder<Flavor>::compute_transcript_state(op_queue->raw_ops, get_number_of_muls());
328 const auto precompute_table_state =
330 const auto msm_state =
331 ECCVMMSMMBuilder<Flavor>::compute_msm_state(msms, point_table_read_counts, get_number_of_muls());
332
333 const size_t msm_size = msm_state.size();
334 const size_t transcript_size = transcript_state.size();
335 const size_t precompute_table_size = precompute_table_state.size();
336
337 const size_t num_rows = std::max(precompute_table_size, std::max(msm_size, transcript_size));
338
339 const auto num_rows_log2 = static_cast<size_t>(numeric::get_msb64(num_rows));
340 size_t num_rows_pow2 = 1UL << (num_rows_log2 + (1UL << num_rows_log2 == num_rows ? 0 : 1));
341
342 ProverPolynomials polys;
343 for (auto& poly : polys.get_all()) {
344 poly = Polynomial(num_rows_pow2);
345 }
346
347 polys.lagrange_first[0] = 1;
348 polys.lagrange_second[1] = 1;
349 polys.lagrange_last[polys.lagrange_last.size() - 1] = 1;
350
351 for (size_t i = 0; i < point_table_read_counts[0].size(); ++i) {
352 // Explanation of off-by-one offset
353 // When computing the WNAF slice for a point at point counter value `pc` and a round index `round`, the row
354 // number that computes the slice can be derived. This row number is then mapped to the index of
355 // `lookup_read_counts`. We do this mapping in `ecc_msm_relation`. We are off-by-one because we add an empty
356 // row at the start of the WNAF columns that is not accounted for (index of lookup_read_counts maps to the
357 // row in our WNAF columns that computes a slice for a given value of pc and round)
358 polys.lookup_read_counts_0[i + 1] = point_table_read_counts[0][i];
359 polys.lookup_read_counts_1[i + 1] = point_table_read_counts[1][i];
360 }
361 for (size_t i = 0; i < transcript_state.size(); ++i) {
362 polys.transcript_accumulator_empty[i] = transcript_state[i].accumulator_empty;
363 polys.transcript_add[i] = transcript_state[i].q_add;
364 polys.transcript_mul[i] = transcript_state[i].q_mul;
365 polys.transcript_eq[i] = transcript_state[i].q_eq;
366 polys.transcript_reset_accumulator[i] = transcript_state[i].q_reset_accumulator;
367 polys.transcript_msm_transition[i] = transcript_state[i].msm_transition;
368 polys.transcript_pc[i] = transcript_state[i].pc;
369 polys.transcript_msm_count[i] = transcript_state[i].msm_count;
370 polys.transcript_Px[i] = transcript_state[i].base_x;
371 polys.transcript_Py[i] = transcript_state[i].base_y;
372 polys.transcript_z1[i] = transcript_state[i].z1;
373 polys.transcript_z2[i] = transcript_state[i].z2;
374 polys.transcript_z1zero[i] = transcript_state[i].z1_zero;
375 polys.transcript_z2zero[i] = transcript_state[i].z2_zero;
376 polys.transcript_op[i] = transcript_state[i].opcode;
377 polys.transcript_accumulator_x[i] = transcript_state[i].accumulator_x;
378 polys.transcript_accumulator_y[i] = transcript_state[i].accumulator_y;
379 polys.transcript_msm_x[i] = transcript_state[i].msm_output_x;
380 polys.transcript_msm_y[i] = transcript_state[i].msm_output_y;
381 polys.transcript_collision_check[i] = transcript_state[i].collision_check;
382 }
383
384 // TODO(@zac-williamson) if final opcode resets accumulator, all subsequent "is_accumulator_empty" row values
385 // must be 1. Ideally we find a way to tweak this so that empty rows that do nothing have column values that are
386 // all zero (issue #2217)
387 if (transcript_state[transcript_state.size() - 1].accumulator_empty == 1) {
388 for (size_t i = transcript_state.size(); i < num_rows_pow2; ++i) {
389 polys.transcript_accumulator_empty[i] = 1;
390 }
391 }
392 for (size_t i = 0; i < precompute_table_state.size(); ++i) {
393 // first row is always an empty row (to accommodate shifted polynomials which must have 0 as 1st
394 // coefficient). All other rows in the precompute_table_state represent active wnaf gates (i.e.
395 // precompute_select = 1)
396 polys.precompute_select[i] = (i != 0) ? 1 : 0;
397 polys.precompute_pc[i] = precompute_table_state[i].pc;
398 polys.precompute_point_transition[i] = static_cast<uint64_t>(precompute_table_state[i].point_transition);
399 polys.precompute_round[i] = precompute_table_state[i].round;
400 polys.precompute_scalar_sum[i] = precompute_table_state[i].scalar_sum;
401
402 polys.precompute_s1hi[i] = precompute_table_state[i].s1;
403 polys.precompute_s1lo[i] = precompute_table_state[i].s2;
404 polys.precompute_s2hi[i] = precompute_table_state[i].s3;
405 polys.precompute_s2lo[i] = precompute_table_state[i].s4;
406 polys.precompute_s3hi[i] = precompute_table_state[i].s5;
407 polys.precompute_s3lo[i] = precompute_table_state[i].s6;
408 polys.precompute_s4hi[i] = precompute_table_state[i].s7;
409 polys.precompute_s4lo[i] = precompute_table_state[i].s8;
410 // If skew is active (i.e. we need to subtract a base point from the msm result),
411 // write `7` into rows.precompute_skew. `7`, in binary representation, equals `-1` when converted into WNAF
412 // form
413 polys.precompute_skew[i] = precompute_table_state[i].skew ? 7 : 0;
414
415 polys.precompute_dx[i] = precompute_table_state[i].precompute_double.x;
416 polys.precompute_dy[i] = precompute_table_state[i].precompute_double.y;
417 polys.precompute_tx[i] = precompute_table_state[i].precompute_accumulator.x;
418 polys.precompute_ty[i] = precompute_table_state[i].precompute_accumulator.y;
419 }
420
421 for (size_t i = 0; i < msm_state.size(); ++i) {
422 polys.msm_transition[i] = static_cast<int>(msm_state[i].msm_transition);
423 polys.msm_add[i] = static_cast<int>(msm_state[i].q_add);
424 polys.msm_double[i] = static_cast<int>(msm_state[i].q_double);
425 polys.msm_skew[i] = static_cast<int>(msm_state[i].q_skew);
426 polys.msm_accumulator_x[i] = msm_state[i].accumulator_x;
427 polys.msm_accumulator_y[i] = msm_state[i].accumulator_y;
428 polys.msm_pc[i] = msm_state[i].pc;
429 polys.msm_size_of_msm[i] = msm_state[i].msm_size;
430 polys.msm_count[i] = msm_state[i].msm_count;
431 polys.msm_round[i] = msm_state[i].msm_round;
432 polys.msm_add1[i] = static_cast<int>(msm_state[i].add_state[0].add);
433 polys.msm_add2[i] = static_cast<int>(msm_state[i].add_state[1].add);
434 polys.msm_add3[i] = static_cast<int>(msm_state[i].add_state[2].add);
435 polys.msm_add4[i] = static_cast<int>(msm_state[i].add_state[3].add);
436 polys.msm_x1[i] = msm_state[i].add_state[0].point.x;
437 polys.msm_y1[i] = msm_state[i].add_state[0].point.y;
438 polys.msm_x2[i] = msm_state[i].add_state[1].point.x;
439 polys.msm_y2[i] = msm_state[i].add_state[1].point.y;
440 polys.msm_x3[i] = msm_state[i].add_state[2].point.x;
441 polys.msm_y3[i] = msm_state[i].add_state[2].point.y;
442 polys.msm_x4[i] = msm_state[i].add_state[3].point.x;
443 polys.msm_y4[i] = msm_state[i].add_state[3].point.y;
444 polys.msm_collision_x1[i] = msm_state[i].add_state[0].collision_inverse;
445 polys.msm_collision_x2[i] = msm_state[i].add_state[1].collision_inverse;
446 polys.msm_collision_x3[i] = msm_state[i].add_state[2].collision_inverse;
447 polys.msm_collision_x4[i] = msm_state[i].add_state[3].collision_inverse;
448 polys.msm_lambda1[i] = msm_state[i].add_state[0].lambda;
449 polys.msm_lambda2[i] = msm_state[i].add_state[1].lambda;
450 polys.msm_lambda3[i] = msm_state[i].add_state[2].lambda;
451 polys.msm_lambda4[i] = msm_state[i].add_state[3].lambda;
452 polys.msm_slice1[i] = msm_state[i].add_state[0].slice;
453 polys.msm_slice2[i] = msm_state[i].add_state[1].slice;
454 polys.msm_slice3[i] = msm_state[i].add_state[2].slice;
455 polys.msm_slice4[i] = msm_state[i].add_state[3].slice;
456 }
457
458 polys.transcript_mul_shift = Polynomial(polys.transcript_mul.shifted());
459 polys.transcript_msm_count_shift = Polynomial(polys.transcript_msm_count.shifted());
460 polys.transcript_accumulator_x_shift = Polynomial(polys.transcript_accumulator_x.shifted());
461 polys.transcript_accumulator_y_shift = Polynomial(polys.transcript_accumulator_y.shifted());
462 polys.precompute_scalar_sum_shift = Polynomial(polys.precompute_scalar_sum.shifted());
463 polys.precompute_s1hi_shift = Polynomial(polys.precompute_s1hi.shifted());
464 polys.precompute_dx_shift = Polynomial(polys.precompute_dx.shifted());
465 polys.precompute_dy_shift = Polynomial(polys.precompute_dy.shifted());
466 polys.precompute_tx_shift = Polynomial(polys.precompute_tx.shifted());
467 polys.precompute_ty_shift = Polynomial(polys.precompute_ty.shifted());
468 polys.msm_transition_shift = Polynomial(polys.msm_transition.shifted());
469 polys.msm_add_shift = Polynomial(polys.msm_add.shifted());
470 polys.msm_double_shift = Polynomial(polys.msm_double.shifted());
471 polys.msm_skew_shift = Polynomial(polys.msm_skew.shifted());
472 polys.msm_accumulator_x_shift = Polynomial(polys.msm_accumulator_x.shifted());
473 polys.msm_accumulator_y_shift = Polynomial(polys.msm_accumulator_y.shifted());
474 polys.msm_count_shift = Polynomial(polys.msm_count.shifted());
475 polys.msm_round_shift = Polynomial(polys.msm_round.shifted());
476 polys.msm_add1_shift = Polynomial(polys.msm_add1.shifted());
477 polys.msm_pc_shift = Polynomial(polys.msm_pc.shifted());
478 polys.precompute_pc_shift = Polynomial(polys.precompute_pc.shifted());
479 polys.transcript_pc_shift = Polynomial(polys.transcript_pc.shifted());
480 polys.precompute_round_shift = Polynomial(polys.precompute_round.shifted());
481 polys.transcript_accumulator_empty_shift = Polynomial(polys.transcript_accumulator_empty.shifted());
482 polys.precompute_select_shift = Polynomial(polys.precompute_select.shifted());
483 return polys;
484 }
485
486 bool check_circuit()
487 {
488 const FF gamma = FF::random_element();
489 const FF beta = FF::random_element();
490 const FF beta_sqr = beta.sqr();
491 const FF beta_cube = beta_sqr * beta;
492 auto eccvm_set_permutation_delta =
493 gamma * (gamma + beta_sqr) * (gamma + beta_sqr + beta_sqr) * (gamma + beta_sqr + beta_sqr + beta_sqr);
494 eccvm_set_permutation_delta = eccvm_set_permutation_delta.invert();
496 .eta = 0,
497 .beta = beta,
498 .gamma = gamma,
499 .public_input_delta = 0,
500 .lookup_grand_product_delta = 0,
501 .beta_sqr = beta_sqr,
502 .beta_cube = beta_cube,
503 .eccvm_set_permutation_delta = eccvm_set_permutation_delta,
504 };
505
506 auto polynomials = compute_polynomials();
507 const size_t num_rows = polynomials.get_polynomial_size();
508 proof_system::honk::logderivative_library::
509 compute_logderivative_inverse<Flavor, honk::sumcheck::ECCVMLookupRelation<FF>>(
510 polynomials, params, num_rows);
511
512 honk::permutation_library::compute_permutation_grand_product<Flavor, honk::sumcheck::ECCVMSetRelation<FF>>(
513 num_rows, polynomials, params);
514
515 polynomials.z_perm_shift = Polynomial(polynomials.z_perm.shifted());
516
517 const auto evaluate_relation = [&]<typename Relation>(const std::string& relation_name) {
518 typename Relation::SumcheckArrayOfValuesOverSubrelations result;
519 for (auto& r : result) {
520 r = 0;
521 }
522 constexpr size_t NUM_SUBRELATIONS = result.size();
523
524 for (size_t i = 0; i < num_rows; ++i) {
525 Relation::accumulate(result, polynomials.get_row(i), params, 1);
526
527 bool x = true;
528 for (size_t j = 0; j < NUM_SUBRELATIONS; ++j) {
529 if (result[j] != 0) {
530 info("Relation ", relation_name, ", subrelation index ", j, " failed at row ", i);
531 x = false;
532 }
533 }
534 if (!x) {
535 return false;
536 }
537 }
538 return true;
539 };
540
541 bool result = true;
542 result = result && evaluate_relation.template operator()<honk::sumcheck::ECCVMTranscriptRelation<FF>>(
543 "ECCVMTranscriptRelation");
544 result = result && evaluate_relation.template operator()<honk::sumcheck::ECCVMPointTableRelation<FF>>(
545 "ECCVMPointTableRelation");
546 result =
547 result && evaluate_relation.template operator()<honk::sumcheck::ECCVMWnafRelation<FF>>("ECCVMWnafRelation");
548 result =
549 result && evaluate_relation.template operator()<honk::sumcheck::ECCVMMSMRelation<FF>>("ECCVMMSMRelation");
550 result =
551 result && evaluate_relation.template operator()<honk::sumcheck::ECCVMSetRelation<FF>>("ECCVMSetRelation");
552
553 using LookupRelation = honk::sumcheck::ECCVMLookupRelation<FF>;
554 typename honk::sumcheck::ECCVMLookupRelation<typename Flavor::FF>::SumcheckArrayOfValuesOverSubrelations
555 lookup_result;
556 for (auto& r : lookup_result) {
557 r = 0;
558 }
559 for (size_t i = 0; i < num_rows; ++i) {
560 LookupRelation::accumulate(lookup_result, polynomials.get_row(i), params, 1);
561 }
562 for (auto r : lookup_result) {
563 if (r != 0) {
564 info("Relation ECCVMLookupRelation failed.");
565 return false;
566 }
567 }
568 return result;
569 }
570
571 [[nodiscard]] size_t get_num_gates() const
572 {
573 // TODO(@zac-williamson) once we have a stable base to work off of, optimize this method!
574 // (issue #2218)
575 const auto msms = get_msms();
576 const auto flattened_muls = get_flattened_scalar_muls(msms);
577
578 std::array<std::vector<size_t>, 2> point_table_read_counts;
579 const auto transcript_state =
580 ECCVMTranscriptBuilder<Flavor>::compute_transcript_state(op_queue->raw_ops, get_number_of_muls());
581 const auto precompute_table_state =
582 ECCVMPrecomputedTablesBuilder<Flavor>::compute_precompute_state(flattened_muls);
583 const auto msm_state =
584 ECCVMMSMMBuilder<Flavor>::compute_msm_state(msms, point_table_read_counts, get_number_of_muls());
585
586 const size_t msm_size = msm_state.size();
587 const size_t transcript_size = transcript_state.size();
588 const size_t precompute_table_size = precompute_table_state.size();
589
590 const size_t num_rows = std::max(precompute_table_size, std::max(msm_size, transcript_size));
591 return num_rows;
592 }
593
594 [[nodiscard]] size_t get_circuit_subgroup_size(const size_t num_rows) const
595 {
596
597 const auto num_rows_log2 = static_cast<size_t>(numeric::get_msb64(num_rows));
598 size_t num_rows_pow2 = 1UL << (num_rows_log2 + (1UL << num_rows_log2 == num_rows ? 0 : 1));
599 return num_rows_pow2;
600 }
601};
602} // namespace proof_system
Definition: polynomial.hpp:12
Definition: uint256.hpp:25
Definition: eccvm_circuit_builder.hpp:17
ProverPolynomials compute_polynomials()
Compute the ECCVM flavor polynomial data required to generate an ECCVM Proof.
Definition: eccvm_circuit_builder.hpp:320
std::vector< MSM > get_msms() const
Definition: eccvm_circuit_builder.hpp:66
static std::vector< MSMState > compute_msm_state(const std::vector< proof_system_eccvm::MSM< CycleGroup > > &msms, std::array< std::vector< size_t >, 2 > &point_table_read_counts, const uint32_t total_number_of_muls)
Computes the row values for the Straus MSM columns of the ECCVM.
Definition: msm_builder.hpp:56
Definition: precomputed_tables_builder.hpp:7
Definition: transcript_builder.hpp:7
A container for the prover polynomials handles.
Definition: AvmMini_flavor.hpp:263
Container for parameters used by the grand product (permutation, lookup) Honk relations.
Definition: relation_parameters.hpp:12
Definition: eccvm_builder_types.hpp:36
Definition: eccvm_builder_types.hpp:15