21template <
typename FF,
typename CircuitBuilder>
24 auto blocks_data = circuit_builder.blocks.get();
26 for (
size_t i = 0; i < blocks_data.size(); i++) {
27 if ((
void*)(&blocks_data[i]) == (
void*)(&block)) {
49template <
typename FF,
typename CircuitBuilder>
54 auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end());
55 gate_variables.erase(unique_variables, gate_variables.end());
56 if (gate_variables.empty()) {
59 for (
auto& var_idx : gate_variables) {
61 variable_gates[
key].emplace_back(gate_index);
63 for (
const auto& variable_index : gate_variables) {
64 variables_gate_counts[variable_index] += 1;
79template <
typename FF,
typename CircuitBuilder>
81 size_t index,
size_t block_idx,
auto& blk)
83 auto q_arith = blk.q_arith()[index];
84 std::vector<uint32_t> all_variables;
85 std::vector<uint32_t> gate_variables;
86 std::vector<uint32_t> minigate_variables;
88 if (q_arith.is_zero()) {
91 auto q_m = blk.q_m()[index];
92 auto q_1 = blk.q_1()[index];
93 auto q_2 = blk.q_2()[index];
94 auto q_3 = blk.q_3()[index];
95 auto q_4 = blk.q_4()[index];
97 uint32_t left_idx = blk.w_l()[index];
98 uint32_t right_idx = blk.w_r()[index];
99 uint32_t out_idx = blk.w_o()[index];
100 uint32_t fourth_idx = blk.w_4()[index];
101 if (q_m.is_zero() && q_1 == 1 && q_2.is_zero() && q_3.is_zero() && q_4.is_zero() && q_arith == FF::one()) {
103 fixed_variables.insert(this->to_real(left_idx));
104 }
else if (!q_m.is_zero() || q_1 != FF::one() || !q_2.is_zero() || !q_3.is_zero() || !q_4.is_zero()) {
106 if (!q_m.is_zero()) {
107 gate_variables.emplace_back(left_idx);
108 gate_variables.emplace_back(right_idx);
110 if (!q_1.is_zero()) {
111 gate_variables.emplace_back(left_idx);
113 if (!q_2.is_zero()) {
114 gate_variables.emplace_back(right_idx);
118 if (!q_3.is_zero()) {
119 gate_variables.emplace_back(out_idx);
121 if (!q_4.is_zero()) {
122 gate_variables.emplace_back(fourth_idx);
124 if (q_arith ==
FF(2)) {
128 if (index != blk.size() - 1) {
129 gate_variables.emplace_back(blk.w_4()[index + 1]);
132 if (q_arith ==
FF(3)) {
136 minigate_variables.emplace_back(left_idx);
137 minigate_variables.emplace_back(fourth_idx);
138 if (index != blk.size() - 1) {
139 gate_variables.emplace_back(blk.w_4()[index + 1]);
140 minigate_variables.emplace_back(blk.w_l()[index + 1]);
144 gate_variables = to_real(gate_variables);
145 minigate_variables = to_real(minigate_variables);
146 all_variables.reserve(gate_variables.size() + minigate_variables.size());
147 all_variables.insert(all_variables.end(), gate_variables.begin(), gate_variables.end());
148 all_variables.insert(all_variables.end(), minigate_variables.begin(), minigate_variables.end());
149 process_gate_variables(all_variables, index, block_idx);
150 return all_variables;
164template <
typename FF,
typename CircuitBuilder>
166 size_t index,
size_t block_idx,
auto& blk)
168 std::vector<uint32_t> gate_variables;
169 if (!blk.q_elliptic()[index].is_zero()) {
170 std::vector<uint32_t> first_row_variables;
171 std::vector<uint32_t> second_row_variables;
172 gate_variables.reserve(6);
173 bool is_elliptic_add_gate = !blk.q_1()[index].is_zero() && blk.q_m()[index].is_zero();
174 bool is_elliptic_dbl_gate = blk.q_1()[index].is_zero() && blk.q_m()[index] == FF::one();
175 first_row_variables.emplace_back(blk.w_r()[index]);
176 first_row_variables.emplace_back(blk.w_o()[index]);
177 if (index != blk.size() - 1) {
178 if (is_elliptic_add_gate) {
180 second_row_variables.emplace_back(blk.w_l()[index + 1]);
181 second_row_variables.emplace_back(blk.w_r()[index + 1]);
182 second_row_variables.emplace_back(blk.w_o()[index + 1]);
183 second_row_variables.emplace_back(blk.w_4()[index + 1]);
185 if (is_elliptic_dbl_gate) {
187 second_row_variables.emplace_back(blk.w_r()[index + 1]);
188 second_row_variables.emplace_back(blk.w_o()[index + 1]);
191 if (!first_row_variables.empty()) {
192 first_row_variables = to_real(first_row_variables);
193 process_gate_variables(first_row_variables, index, block_idx);
194 gate_variables.insert(gate_variables.end(), first_row_variables.cbegin(), first_row_variables.cend());
196 if (!second_row_variables.empty()) {
197 second_row_variables = to_real(second_row_variables);
198 process_gate_variables(second_row_variables, index, block_idx);
199 gate_variables.insert(gate_variables.end(), second_row_variables.cbegin(), second_row_variables.cend());
202 return gate_variables;
216template <
typename FF,
typename CircuitBuilder>
218 size_t index,
size_t blk_idx,
auto& block)
220 std::vector<uint32_t> gate_variables = {};
221 if (!block.q_delta_range()[index].is_zero()) {
222 std::vector<uint32_t> row_variables = {
223 block.w_l()[index], block.w_r()[index], block.w_o()[index], block.w_4()[index]
229 for (
const auto& var_idx : row_variables) {
230 if (var_idx != circuit_builder.zero_idx()) {
231 gate_variables.emplace_back(var_idx);
234 if (index != block.size() - 1 && block.w_l()[index + 1] != circuit_builder.zero_idx()) {
235 gate_variables.emplace_back(block.w_l()[index + 1]);
238 gate_variables = to_real(gate_variables);
239 process_gate_variables(gate_variables, index, blk_idx);
240 return gate_variables;
254template <
typename FF,
typename CircuitBuilder>
259 std::vector<uint32_t> gate_variables;
260 auto q_lookup_type = block.q_lookup_type()[index];
261 if (!q_lookup_type.is_zero()) {
262 gate_variables.reserve(6);
263 auto q_2 = block.q_2()[index];
264 auto q_m = block.q_m()[index];
265 auto q_c = block.q_c()[index];
266 gate_variables.emplace_back(block.w_l()[index]);
267 gate_variables.emplace_back(block.w_r()[index]);
268 gate_variables.emplace_back(block.w_o()[index]);
269 if (index < block.size() - 1) {
270 if (!q_2.is_zero()) {
271 gate_variables.emplace_back(block.w_l()[index + 1]);
273 if (!q_m.is_zero()) {
274 gate_variables.emplace_back(block.w_r()[index + 1]);
276 if (!q_c.is_zero()) {
277 gate_variables.emplace_back(block.w_o()[index + 1]);
280 gate_variables = to_real(gate_variables);
281 process_gate_variables(gate_variables, index, blk_idx);
283 return gate_variables;
295template <
typename FF,
typename CircuitBuilder>
300 std::vector<uint32_t> gate_variables;
301 auto internal_selector = block.q_poseidon2_internal()[index];
302 auto external_selector = block.q_poseidon2_external()[index];
303 if (!internal_selector.is_zero() || !external_selector.is_zero()) {
304 gate_variables.reserve(8);
305 gate_variables.emplace_back(block.w_l()[index]);
306 gate_variables.emplace_back(block.w_r()[index]);
307 gate_variables.emplace_back(block.w_o()[index]);
308 gate_variables.emplace_back(block.w_4()[index]);
309 if (index != block.size() - 1) {
310 gate_variables.emplace_back(block.w_l()[index + 1]);
311 gate_variables.emplace_back(block.w_r()[index + 1]);
312 gate_variables.emplace_back(block.w_o()[index + 1]);
313 gate_variables.emplace_back(block.w_4()[index + 1]);
315 gate_variables = to_real(gate_variables);
316 process_gate_variables(gate_variables, index, blk_idx);
318 return gate_variables;
330template <
typename FF,
typename CircuitBuilder>
335 std::vector<uint32_t> gate_variables;
336 if (!block.q_memory()[index].is_zero()) {
337 gate_variables.reserve(8);
338 auto q_1 = block.q_1()[index];
339 auto q_2 = block.q_2()[index];
340 auto q_3 = block.q_3()[index];
341 auto q_4 = block.q_4()[index];
342 if (q_1 == FF::one() && q_4 == FF::one()) {
345 if (index < block.size() - 1) {
346 gate_variables.insert(gate_variables.end(),
347 { block.w_r()[index + 1],
350 block.w_l()[index + 1],
351 block.w_o()[index] });
353 }
else if (q_1 == FF::one() && q_2 == FF::one()) {
356 if (index < block.size() - 1) {
357 gate_variables.insert(
358 gate_variables.end(),
359 { block.w_l()[index], block.w_l()[index + 1], block.w_4()[index], block.w_4()[index + 1] });
363 if (!q_3.is_zero()) {
364 if (index < block.size() - 1) {
365 gate_variables.insert(gate_variables.end(),
366 { block.w_o()[index],
368 block.w_l()[index + 1],
369 block.w_r()[index + 1],
370 block.w_o()[index + 1],
371 block.w_4()[index + 1] });
376 gate_variables = to_real(gate_variables);
377 process_gate_variables(gate_variables, index, blk_idx);
378 return gate_variables;
390template <
typename FF,
typename CircuitBuilder>
392 size_t index,
size_t blk_idx,
auto& block)
394 std::vector<uint32_t> gate_variables;
395 if (!block.q_nnf()[index].is_zero()) {
396 gate_variables.reserve(8);
397 [[maybe_unused]]
auto q_1 = block.q_1()[index];
398 auto q_2 = block.q_2()[index];
399 auto q_3 = block.q_3()[index];
400 auto q_4 = block.q_4()[index];
401 auto q_m = block.q_m()[index];
403 auto w_l = block.w_l()[index];
404 auto w_r = block.w_r()[index];
405 auto w_o = block.w_o()[index];
406 auto w_4 = block.w_4()[index];
407 if (q_3 == FF::one() && q_4 == FF::one()) {
409 if (index < block.size() - 1) {
410 gate_variables.insert(gate_variables.end(),
411 { w_l, w_r, w_o, w_4, block.w_l()[index + 1], block.w_r()[index + 1] });
413 }
else if (q_3 == FF::one() && q_m == FF::one()) {
415 if (index < block.size() - 1) {
416 gate_variables.insert(gate_variables.end(),
419 block.w_l()[index + 1],
420 block.w_r()[index + 1],
421 block.w_o()[index + 1],
422 block.w_4()[index + 1] });
424 }
else if (q_2 == FF::one() && (q_3 == FF::one() || q_4 == FF::one() || q_m == FF::one())) {
426 if (index < block.size() - 1) {
427 std::vector<uint32_t> limb_subproduct_vars = {
428 w_l, w_r, block.w_l()[index + 1], block.w_r()[index + 1]
430 if (q_3 == FF::one()) {
432 ASSERT(q_4.is_zero() && q_m.is_zero());
433 gate_variables.insert(
434 gate_variables.end(), limb_subproduct_vars.begin(), limb_subproduct_vars.end());
435 gate_variables.insert(gate_variables.end(), { w_o, w_4 });
437 if (q_4 == FF::one()) {
439 ASSERT(q_3.is_zero() && q_m.is_zero());
440 std::vector<uint32_t> non_native_field_gate_2 = { w_l, w_4, w_r, w_o, block.w_o()[index + 1] };
441 gate_variables.insert(
442 gate_variables.end(), non_native_field_gate_2.begin(), non_native_field_gate_2.end());
443 gate_variables.emplace_back(block.w_4()[index + 1]);
444 gate_variables.insert(
445 gate_variables.end(), limb_subproduct_vars.begin(), limb_subproduct_vars.end());
447 if (q_m == FF::one()) {
449 ASSERT(q_4.is_zero() && q_3.is_zero());
450 gate_variables.insert(
451 gate_variables.end(), limb_subproduct_vars.begin(), limb_subproduct_vars.end());
452 gate_variables.insert(gate_variables.end(),
453 { w_4, block.w_o()[index + 1], block.w_4()[index + 1] });
458 gate_variables = to_real(gate_variables);
459 process_gate_variables(gate_variables, index, blk_idx);
460 return gate_variables;
470template <
typename FF,
typename CircuitBuilder>
478 std::vector<uint32_t> rom_table_variables;
484 for (
const auto& record : rom_array.
records) {
485 std::vector<uint32_t> gate_variables;
486 size_t gate_index = record.gate_index;
488 auto q_1 = circuit_builder.blocks.memory.q_1()[gate_index];
489 auto q_2 = circuit_builder.blocks.memory.q_2()[gate_index];
490 auto q_3 = circuit_builder.blocks.memory.q_3()[gate_index];
491 auto q_4 = circuit_builder.blocks.memory.q_4()[gate_index];
492 auto q_m = circuit_builder.blocks.memory.q_m()[gate_index];
493 auto q_c = circuit_builder.blocks.memory.q_c()[gate_index];
495 auto index_witness = record.index_witness;
496 auto vc1_witness = record.value_column1_witness;
497 auto vc2_witness = record.value_column2_witness;
498 auto record_witness = record.record_witness;
500 if (q_1 == FF::one() && q_m == FF::one() && q_2.is_zero() && q_3.is_zero() && q_4.is_zero() &&
504 gate_variables.emplace_back(index_witness);
505 if (vc1_witness != circuit_builder.zero_idx()) {
506 gate_variables.emplace_back(vc1_witness);
508 if (vc2_witness != circuit_builder.zero_idx()) {
509 gate_variables.emplace_back(vc2_witness);
511 gate_variables.emplace_back(record_witness);
513 gate_variables = to_real(gate_variables);
514 process_gate_variables(gate_variables, gate_index, *blk_idx);
517 if (!gate_variables.empty()) {
518 rom_table_variables.insert(rom_table_variables.end(), gate_variables.begin(), gate_variables.end());
522 return rom_table_variables;
532template <
typename FF,
typename CircuitBuilder>
536 std::vector<uint32_t> ram_table_variables;
538 for (
const auto& record : ram_array.
records) {
539 std::vector<uint32_t> gate_variables;
540 size_t gate_index = record.gate_index;
542 auto q_1 = circuit_builder.blocks.memory.q_1()[gate_index];
543 auto q_2 = circuit_builder.blocks.memory.q_2()[gate_index];
544 auto q_3 = circuit_builder.blocks.memory.q_3()[gate_index];
545 auto q_4 = circuit_builder.blocks.memory.q_4()[gate_index];
546 auto q_m = circuit_builder.blocks.memory.q_m()[gate_index];
547 auto q_c = circuit_builder.blocks.memory.q_c()[gate_index];
549 auto index_witness = record.index_witness;
550 auto timestamp_witness = record.timestamp_witness;
551 auto value_witness = record.value_witness;
552 auto record_witness = record.record_witness;
554 if (q_1 == FF::one() && q_m == FF::one() && q_2.is_zero() && q_3.is_zero() && q_4.is_zero() &&
555 (q_c.is_zero() || q_c == FF::one())) {
558 gate_variables.emplace_back(index_witness);
559 if (timestamp_witness != circuit_builder.zero_idx()) {
560 gate_variables.emplace_back(timestamp_witness);
562 if (value_witness != circuit_builder.zero_idx()) {
563 gate_variables.emplace_back(value_witness);
565 gate_variables.emplace_back(record_witness);
567 gate_variables = to_real(gate_variables);
568 process_gate_variables(gate_variables, gate_index, *blk_idx);
571 ram_table_variables.insert(ram_table_variables.end(), gate_variables.begin(), gate_variables.end());
574 return ram_table_variables;
586template <
typename FF,
typename CircuitBuilder>
591 std::vector<uint32_t> gate_variables;
592 if (!blk.q_busread()[index].is_zero()) {
593 gate_variables.insert(gate_variables.end(), { blk.w_l()[index], blk.w_r()[index] });
594 gate_variables = to_real(gate_variables);
595 process_gate_variables(gate_variables, index, block_idx);
597 return gate_variables;
610template <
typename FF,
typename CircuitBuilder>
615 std::vector<uint32_t> gate_variables;
616 std::vector<uint32_t> first_row_variables;
617 std::vector<uint32_t> second_row_variables;
618 auto w1 = blk.w_l()[index];
620 if (w1 != circuit_builder.zero_idx()) {
622 first_row_variables.insert(
623 first_row_variables.end(),
624 { w1, blk.w_r()[index], blk.w_o()[index], blk.w_4()[index] });
625 if (index < blk.size() - 1) {
626 second_row_variables.insert(
627 second_row_variables.end(),
628 { blk.w_r()[index + 1], blk.w_o()[index + 1], blk.w_4()[index + 1] });
630 first_row_variables = to_real(first_row_variables);
631 second_row_variables = to_real(second_row_variables);
632 process_gate_variables(first_row_variables, index, block_idx);
633 process_gate_variables(second_row_variables, index, block_idx);
635 if (!first_row_variables.empty()) {
636 gate_variables.insert(gate_variables.end(), first_row_variables.cbegin(), first_row_variables.cend());
638 if (!second_row_variables.empty()) {
639 gate_variables.insert(gate_variables.end(), second_row_variables.cbegin(), second_row_variables.cend());
641 return gate_variables;
646 auto block_data = circuit_builder.blocks.get();
651 size_t pub_inputs_block_idx = 0;
655 pub_inputs_block_idx = 3;
658 for (
size_t blk_idx = 0; blk_idx < block_data.size() - 1; blk_idx++) {
659 if (block_data[blk_idx].size() == 0 || blk_idx == pub_inputs_block_idx) {
662 std::vector<uint32_t> sorted_variables;
663 std::vector<uint32_t> eccop_variables;
664 for (
size_t gate_idx = 0; gate_idx < block_data[blk_idx].size(); gate_idx++) {
666 get_arithmetic_gate_connected_component(gate_idx, blk_idx, block_data[blk_idx]),
667 get_elliptic_gate_connected_component(gate_idx, blk_idx, block_data[blk_idx]),
668 get_plookup_gate_connected_component(gate_idx, blk_idx, block_data[blk_idx]),
669 get_poseido2s_gate_connected_component(gate_idx, blk_idx, block_data[blk_idx]),
670 get_non_native_field_gate_connected_component(gate_idx, blk_idx, block_data[blk_idx]),
671 get_memory_gate_connected_component(gate_idx, blk_idx, block_data[blk_idx]),
672 get_sort_constraint_connected_component(gate_idx, blk_idx, block_data[blk_idx])
674 auto non_empty_count =
675 std::count_if(all_cc.begin(), all_cc.end(), [](
const auto& vec) { return !vec.empty(); });
676 ASSERT(non_empty_count < 2U);
677 auto not_empty_cc_it =
678 std::find_if(all_cc.begin(), all_cc.end(), [](
const auto& vec) { return !vec.empty(); });
679 if (not_empty_cc_it != all_cc.end() && connect_variables) {
680 connect_all_variables_in_vector(*not_empty_cc_it);
685 auto databus_variables = get_databus_connected_component(gate_idx, blk_idx, block_data[blk_idx]);
686 if (connect_variables) {
687 connect_all_variables_in_vector(databus_variables);
689 auto eccop_gate_variables = get_eccop_part_connected_component(gate_idx, blk_idx, block_data[blk_idx]);
690 if (connect_variables) {
691 if (!eccop_gate_variables.empty()) {
693 eccop_variables.insert(
694 eccop_variables.end(), eccop_gate_variables.begin(), eccop_gate_variables.end());
697 if (eccop_gate_variables[0] == circuit_builder.equality_op_idx) {
698 connect_all_variables_in_vector(eccop_variables);
699 eccop_variables.clear();
707 const auto& rom_arrays = circuit_builder.rom_ram_logic.rom_arrays;
708 if (!rom_arrays.empty()) {
709 for (
const auto& rom_array : rom_arrays) {
710 std::vector<uint32_t> variable_indices = get_rom_table_connected_component(rom_array);
711 if (connect_variables) {
712 connect_all_variables_in_vector(variable_indices);
717 const auto& ram_arrays = circuit_builder.rom_ram_logic.ram_arrays;
718 if (!ram_arrays.empty()) {
719 for (
const auto& ram_array : ram_arrays) {
720 std::vector<uint32_t> variable_indices = get_ram_table_connected_component(ram_array);
721 if (connect_variables) {
722 connect_all_variables_in_vector(variable_indices);
748template <
typename FF,
typename CircuitBuilder>
750 : circuit_builder(circuit_builder)
751 , connect_variables(connect_variables)
774template <
typename FF,
typename CircuitBuilder>
777 bool is_not_constant =
true;
778 const auto& constant_variable_indices = circuit_builder.constant_variable_indices;
779 for (
const auto& pair : constant_variable_indices) {
780 if (pair.second == circuit_builder.real_variable_index[variable_index]) {
781 is_not_constant =
false;
785 return is_not_constant;
799template <
typename FF,
typename CircuitBuilder>
802 if (variables_vector.empty()) {
805 std::vector<uint32_t> filtered_variables_vector;
806 filtered_variables_vector.reserve(variables_vector.size());
809 variables_vector.end(),
811 [&](uint32_t variable_index) {
812 return variable_index != circuit_builder.zero_idx() &&
813 this->check_is_not_constant_variable(variable_index);
816 auto unique_pointer = std::unique(filtered_variables_vector.begin(), filtered_variables_vector.end());
817 filtered_variables_vector.erase(unique_pointer, filtered_variables_vector.end());
818 if (filtered_variables_vector.size() < 2) {
821 for (
size_t i = 0; i < filtered_variables_vector.size() - 1; i++) {
822 add_new_edge(filtered_variables_vector[i], filtered_variables_vector[i + 1]);
833template <
typename FF,
typename CircuitBuilder>
835 const uint32_t& second_variable_index)
837 variable_adjacency_lists[first_variable_index].emplace_back(second_variable_index);
838 variable_adjacency_lists[second_variable_index].emplace_back(first_variable_index);
839 variables_degree[first_variable_index] += 1;
840 variables_degree[second_variable_index] += 1;
851template <
typename FF,
typename CircuitBuilder>
853 std::unordered_set<uint32_t>& is_used,
854 std::vector<uint32_t>& connected_component)
856 std::stack<uint32_t> variable_stack;
857 variable_stack.push(variable_index);
858 while (!variable_stack.empty()) {
859 uint32_t current_index = variable_stack.top();
860 variable_stack.pop();
861 if (!is_used.contains(current_index)) {
862 is_used.insert(current_index);
863 connected_component.emplace_back(current_index);
864 for (
const auto& it : variable_adjacency_lists[current_index]) {
865 variable_stack.push(it);
878template <
typename FF,
typename CircuitBuilder>
880 bool return_all_connected_components)
882 if (!connect_variables) {
883 throw std::runtime_error(
"find_connected_components() can only be called when connect_variables is true");
885 std::unordered_set<uint32_t> visited;
886 for (
const auto& pair : variable_adjacency_lists) {
887 if (pair.first != 0 && variables_degree[pair.first] > 0) {
888 if (!visited.contains(pair.first)) {
889 std::vector<uint32_t> variable_indices;
890 depth_first_search(pair.first, visited, variable_indices);
891 std::sort(variable_indices.begin(), variable_indices.end());
896 mark_range_list_connected_components();
897 mark_finalize_connected_components();
898 if (!return_all_connected_components) {
899 main_connected_components.reserve(connected_components.size());
900 for (
auto& cc : connected_components) {
901 if (!cc.is_range_list_cc && !cc.is_finalize_cc) {
902 main_connected_components.emplace_back(
std::move(cc));
905 return main_connected_components;
907 return connected_components;
919template <
typename FF,
typename CircuitBuilder>
922 const auto& tags = circuit_builder.real_variable_tags;
923 std::unordered_set<uint32_t> tau_tags;
924 for (
const auto& pair : circuit_builder.range_lists) {
925 tau_tags.insert(pair.second.tau_tag);
927 for (
auto& cc : connected_components) {
928 const auto& variables = cc.variable_indices;
929 const uint32_t first_tag = tags[variables[0]];
930 if (tau_tags.contains(first_tag)) {
931 cc.is_range_list_cc =
932 std::all_of(variables.begin() + 1, variables.end(), [&tags, first_tag](uint32_t var_idx) {
933 return tags[var_idx] == first_tag;
947template <
typename FF,
typename CircuitBuilder>
950 const auto& finalize_witnesses = circuit_builder.finalize_witnesses;
951 for (
auto& cc : connected_components) {
952 const auto& vars = cc.vars();
953 cc.is_finalize_cc =
std::all_of(vars.begin(), vars.end(), [&finalize_witnesses](uint32_t var_idx) {
954 return finalize_witnesses.contains(var_idx);
974template <
typename FF,
typename CircuitBuilder>
977 auto& arithmetic_block = circuit_builder.blocks.arithmetic;
978 auto zero_idx = circuit_builder.zero_idx();
979 size_t current_index = index;
980 std::vector<uint32_t> accumulators_indices;
984 auto fourth_idx = arithmetic_block.w_4()[current_index];
985 accumulators_indices.emplace_back(this->to_real(fourth_idx));
986 auto left_idx = arithmetic_block.w_l()[current_index];
987 if (left_idx != zero_idx) {
988 variables_in_one_gate.erase(this->to_real(left_idx));
990 auto right_idx = arithmetic_block.w_r()[current_index];
991 if (right_idx != zero_idx) {
992 variables_in_one_gate.erase(this->to_real(right_idx));
994 auto out_idx = arithmetic_block.w_o()[current_index];
995 if (out_idx != zero_idx) {
996 variables_in_one_gate.erase(this->to_real(out_idx));
998 auto q_arith = arithmetic_block.q_arith()[current_index];
999 if (q_arith == 1 || current_index == arithmetic_block.size() - 1) {
1005 for (
size_t i = 0; i < accumulators_indices.size(); i++) {
1009 variables_gate_counts[accumulators_indices[i]] -= 1;
1013 variables_gate_counts[accumulators_indices[i]] = 0;
1017 return current_index;
1028template <
typename FF,
typename CircuitBuilder>
1030 const std::unordered_set<uint32_t>& decompose_variables)
1032 auto is_power_two = [&](
const uint256_t& number) {
return number > 0 && ((number & (number - 1)) == 0); };
1033 auto find_position = [&](uint32_t variable_index) {
1034 return decompose_variables.contains(this->to_real(variable_index));
1036 auto& arithmetic_block = circuit_builder.blocks.arithmetic;
1037 if (arithmetic_block.size() > 0) {
1038 for (
size_t i = 0; i < arithmetic_block.size(); i++) {
1039 auto q_1 = arithmetic_block.q_1()[i];
1040 auto q_2 = arithmetic_block.q_2()[i];
1041 auto q_3 = arithmetic_block.q_3()[i];
1048 bool q_1_is_power_two = is_power_two(q_1);
1049 bool q_2_is_power_two = is_power_two(q_2);
1050 bool q_3_is_power_two = is_power_two(q_3);
1051 if (q_2 * q_2 == q_1 * q_3 && q_1_is_power_two && q_2_is_power_two && q_3_is_power_two) {
1052 uint32_t left_idx = arithmetic_block.w_l()[i];
1053 uint32_t right_idx = arithmetic_block.w_r()[i];
1054 uint32_t out_idx = arithmetic_block.w_o()[i];
1055 uint32_t fourth_idx = arithmetic_block.w_4()[i];
1056 bool find_left = find_position(left_idx);
1057 bool find_right = find_position(right_idx);
1058 bool find_out = find_position(out_idx);
1059 bool find_fourth = find_position(fourth_idx);
1060 if (((find_left && find_right && find_out) || (find_left && find_right && !find_out) ||
1061 (find_left && find_right && !find_out) || (find_left && !find_right && !find_out)) &&
1063 i = this->process_current_decompose_chain(i);
1078template <
typename FF,
typename CircuitBuilder>
1082 std::unordered_set<uint32_t> range_lists_tau_tags;
1083 std::unordered_set<uint32_t> range_lists_range_tags;
1084 std::vector<uint32_t> real_variable_tags = circuit_builder.real_variable_tags;
1085 for (
const auto& pair : range_lists) {
1086 typename CircuitBuilder::RangeList list = pair.second;
1087 range_lists_tau_tags.insert(list.tau_tag);
1088 range_lists_range_tags.insert(list.range_tag);
1090 for (uint32_t real_index = 0; real_index < real_variable_tags.size(); real_index++) {
1091 if (variables_in_one_gate.contains(real_index)) {
1094 if (range_lists_tau_tags.contains(real_variable_tags[real_index])) {
1095 variables_in_one_gate.erase(real_index);
1099 if (range_lists_range_tags.contains(real_variable_tags[real_index])) {
1100 variables_in_one_gate.erase(real_index);
1117template <
typename FF,
typename CircuitBuilder>
1122 auto find_position = [&](uint32_t real_variable_index) {
1123 return variables_in_one_gate.contains(real_variable_index);
1126 BasicTableId::AES_SPARSE_MAP,
1127 BasicTableId::AES_SPARSE_NORMALIZE };
1128 auto& lookup_block = circuit_builder.blocks.lookup;
1129 if (aes_plookup_tables.contains(table_id)) {
1130 uint32_t real_out_idx = this->to_real(lookup_block.w_o()[gate_index]);
1131 uint32_t real_right_idx = this->to_real(lookup_block.w_r()[gate_index]);
1132 if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) {
1133 bool find_out = find_position(real_out_idx);
1134 auto q_c = lookup_block.q_c()[gate_index];
1135 if (q_c.is_zero()) {
1137 variables_in_one_gate.erase(real_out_idx);
1156template <
typename FF,
typename CircuitBuilder>
1161 auto find_position = [&](uint32_t real_variable_index) {
1162 return variables_in_one_gate.contains(real_variable_index);
1164 auto& lookup_block = circuit_builder.blocks.lookup;
1166 BasicTableId::SHA256_WITNESS_SLICE_7_ROTATE_4,
1167 BasicTableId::SHA256_WITNESS_SLICE_8_ROTATE_7,
1168 BasicTableId::SHA256_WITNESS_SLICE_14_ROTATE_1,
1169 BasicTableId::SHA256_BASE16,
1170 BasicTableId::SHA256_BASE16_ROTATE2,
1171 BasicTableId::SHA256_BASE16_ROTATE6,
1172 BasicTableId::SHA256_BASE16_ROTATE7,
1173 BasicTableId::SHA256_BASE16_ROTATE8,
1174 BasicTableId::SHA256_BASE28,
1175 BasicTableId::SHA256_BASE28_ROTATE3,
1176 BasicTableId::SHA256_BASE28_ROTATE6 };
1177 if (sha256_plookup_tables.contains(table_id)) {
1178 uint32_t real_right_idx = this->to_real(lookup_block.w_r()[gate_index]);
1179 uint32_t real_out_idx = this->to_real(lookup_block.w_o()[gate_index]);
1180 if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) {
1182 auto q_c = lookup_block.q_c()[gate_index];
1183 bool find_out = find_position(real_out_idx);
1185 if (q_c.is_zero()) {
1187 variables_in_one_gate.erase(real_out_idx);
1193 variables_in_one_gate.erase(real_out_idx);
1209template <
typename FF,
typename CircuitBuilder>
1212 auto find_position = [&](uint32_t real_variable_index) {
1213 return variables_in_one_gate.contains(real_variable_index);
1215 auto& lookup_block = circuit_builder.blocks.lookup;
1216 auto& lookup_tables = circuit_builder.lookup_tables;
1217 auto table_index =
static_cast<size_t>(
static_cast<uint256_t>(lookup_block.q_3()[gate_index]));
1218 for (
const auto& table : lookup_tables) {
1219 if (table.table_index == table_index) {
1225 this->remove_unnecessary_aes_plookup_variables(table_id, gate_index);
1227 this->remove_unnecessary_sha256_plookup_variables(table_id, gate_index);
1230 if (column_1.size() == 1) {
1231 uint32_t left_idx = lookup_block.w_l()[gate_index];
1232 uint32_t real_left_idx = this->to_real(left_idx);
1233 bool find_left = find_position(real_left_idx);
1235 variables_in_one_gate.erase(real_left_idx);
1238 if (column_2.size() == 1) {
1239 uint32_t real_right_idx = this->to_real(lookup_block.w_r()[gate_index]);
1240 bool find_right = find_position(real_right_idx);
1242 variables_in_one_gate.erase(real_right_idx);
1245 if (column_3.size() == 1) {
1246 uint32_t real_out_idx = this->to_real(lookup_block.w_o()[gate_index]);
1247 bool find_out = find_position(real_out_idx);
1249 variables_in_one_gate.erase(real_out_idx);
1263template <
typename FF,
typename CircuitBuilder>
1266 auto& lookup_block = circuit_builder.blocks.lookup;
1267 if (lookup_block.size() > 0) {
1268 for (
size_t i = 0; i < lookup_block.size(); i++) {
1269 this->process_current_plookup_gate(i);
1282template <
typename FF,
typename CircuitBuilder>
1285 auto block_data = circuit_builder.blocks.get();
1287 std::vector<uint32_t> to_remove;
1288 for (
const auto& var_idx : variables_in_one_gate) {
1290 if (
auto search = variable_gates.find(
key); search != variable_gates.end()) {
1291 std::vector<size_t> gate_indexes = variable_gates[
key];
1293 size_t gate_idx = gate_indexes[0];
1294 auto q_1 = block_data[*blk_idx].q_1()[gate_idx];
1295 auto q_2 = block_data[*blk_idx].q_2()[gate_idx];
1296 auto q_3 = block_data[*blk_idx].q_3()[gate_idx];
1297 auto q_4 = block_data[*blk_idx].q_4()[gate_idx];
1298 auto q_m = block_data[*blk_idx].q_m()[gate_idx];
1299 auto q_arith = block_data[*blk_idx].q_arith()[gate_idx];
1300 if (q_1 == FF::one() && q_m == FF::one() && q_2.is_zero() && q_3.is_zero() && q_4.is_zero() &&
1301 q_arith.is_zero()) {
1305 if (this->to_real(block_data[*blk_idx].w_4()[gate_idx]) == var_idx) {
1306 to_remove.emplace_back(var_idx);
1311 for (
const auto& elem : to_remove) {
1312 variables_in_one_gate.erase(elem);
1324template <
typename FF,
typename CircuitBuilder>
1327 for (
const auto& pair : variables_gate_counts) {
1328 bool is_not_constant_variable = check_is_not_constant_variable(pair.first);
1329 if (pair.second == 1 && pair.first != 0 && is_not_constant_variable) {
1330 variables_in_one_gate.insert(pair.first);
1333 auto range_lists = circuit_builder.range_lists;
1334 std::unordered_set<uint32_t> decompose_variables;
1335 for (
auto& pair : range_lists) {
1336 for (
auto& elem : pair.second.variable_indices) {
1337 bool is_not_constant_variable = check_is_not_constant_variable(elem);
1338 if (variables_gate_counts[circuit_builder.real_variable_index[elem]] == 1 && is_not_constant_variable) {
1339 decompose_variables.insert(circuit_builder.real_variable_index[elem]);
1343 remove_unnecessary_decompose_variables(decompose_variables);
1344 remove_unnecessary_plookup_variables();
1345 remove_unnecessary_range_constrains_variables();
1346 for (
const auto& elem : fixed_variables) {
1347 variables_in_one_gate.erase(elem);
1351 for (
const auto& elem : circuit_builder.get_used_witnesses()) {
1352 variables_in_one_gate.erase(elem);
1354 remove_record_witness_variables();
1355 return variables_in_one_gate;
1362template <
typename FF,
typename CircuitBuilder>
1365 for (
size_t i = 0; i < main_connected_components.size(); i++) {
1366 info(
"size of ", i + 1,
" connected component == ", main_connected_components[i].size(),
":");
1367 info(
"Does connected component represent range list? ", main_connected_components[i].is_range_list_cc);
1368 info(
"Does connected component represent something from finalize? ",
1369 main_connected_components[i].is_finalize_cc);
1370 if (main_connected_components[i].size() < 50) {
1371 for (
const auto& elem : main_connected_components[i].vars()) {
1372 info(
"elem == ", elem);
1385 for (
const auto& it : variables_gate_counts) {
1386 info(
"number of gates with variables ", it.first,
" == ", it.second);
1396template <
typename FF,
typename CircuitBuilder>
1399 auto q_arith = block.q_arith()[gate_index];
1400 if (!q_arith.is_zero()) {
1401 info(
"q_arith == ", q_arith);
1403 info(
"q_m == ", block.q_m()[gate_index]);
1404 info(
"q1 == ", block.q_1()[gate_index]);
1405 info(
"q2 == ", block.q_2()[gate_index]);
1406 info(
"q3 == ", block.q_3()[gate_index]);
1407 info(
"q4 == ", block.q_4()[gate_index]);
1408 info(
"q_c == ", block.q_c()[gate_index]);
1410 if (q_arith ==
FF(2)) {
1412 info(
"w_4_shift == ", block.w_4()[gate_index + 1]);
1414 if (q_arith ==
FF(3)) {
1416 info(
"w_1_shift == ", block.w_l()[gate_index + 1]);
1417 info(
"w_4_shift == ", block.w_4()[gate_index + 1]);
1430template <
typename FF,
typename CircuitBuilder>
1433 auto q_elliptic = block.q_elliptic()[gate_index];
1434 if (!q_elliptic.is_zero()) {
1435 info(
"q_elliptic == ", q_elliptic);
1436 info(
"q_1 == ", block.q_1()[gate_index]);
1437 info(
"q_m == ", block.q_m()[gate_index]);
1438 bool is_elliptic_add_gate = !block.q_1()[gate_index].is_zero() && block.q_m()[gate_index].is_zero();
1439 bool is_elliptic_dbl_gate = block.q_1()[gate_index].is_zero() && block.q_m()[gate_index] == FF::one();
1440 if (is_elliptic_add_gate) {
1441 info(
"x2 == ", block.w_l()[gate_index + 1]);
1442 info(
"x3 == ", block.w_r()[gate_index + 1]);
1443 info(
"y3 == ", block.w_o()[gate_index + 1]);
1444 info(
"y2 == ", block.w_4()[gate_index + 1]);
1446 if (is_elliptic_dbl_gate) {
1447 info(
"x3 == ", block.w_r()[gate_index + 1]);
1448 info(
"y3 == ", block.w_o()[gate_index + 1]);
1462template <
typename FF,
typename CircuitBuilder>
1465 auto q_lookup = block.q_lookup_type()[gate_index];
1466 if (!q_lookup.is_zero()) {
1467 info(
"q_lookup == ", q_lookup);
1468 auto q_2 = block.q_2()[gate_index];
1469 auto q_m = block.q_m()[gate_index];
1470 auto q_c = block.q_c()[gate_index];
1471 info(
"q_2 == ", q_2);
1472 info(
"q_m == ", q_m);
1473 info(
"q_c == ", q_c);
1474 if (!q_2.is_zero()) {
1475 info(
"w_1_shift == ", block.w_l()[gate_index + 1]);
1477 if (!q_m.is_zero()) {
1478 info(
"w_2_shift == ", block.w_r()[gate_index + 1]);
1480 if (!q_c.is_zero()) {
1481 info(
"w_3_shift == ", block.w_o()[gate_index + 1]);
1495template <
typename FF,
typename CircuitBuilder>
1498 auto q_delta_range = block.q_delta_range()[gate_index];
1499 if (!q_delta_range.is_zero()) {
1500 info(
"q_delta_range == ", q_delta_range);
1501 info(
"w_1 == ", block.w_l()[gate_index]);
1502 info(
"w_2 == ", block.w_r()[gate_index]);
1503 info(
"w_3 == ", block.w_o()[gate_index]);
1504 info(
"w_4 == ", block.w_4()[gate_index]);
1505 info(
"w_1_shift == ", block.w_l()[gate_index]);
1518template <
typename FF,
typename CircuitBuilder>
1521 auto internal_selector = block.q_poseidon2_internal()[gate_index];
1522 auto external_selector = block.q_poseidon2_external()[gate_index];
1523 if (!internal_selector.is_zero() || !external_selector.is_zero()) {
1524 info(
"q_poseidon2_internal == ", internal_selector);
1525 info(
"q_poseidon2_external == ", external_selector);
1526 info(
"w_1 == ", block.w_l()[gate_index]);
1527 info(
"w_2 == ", block.w_r()[gate_index]);
1528 info(
"w_3 == ", block.w_o()[gate_index]);
1529 info(
"w_4 == ", block.w_4()[gate_index]);
1530 info(
"w_1_shift == ", block.w_l()[gate_index + 1]);
1531 info(
"w_2_shift == ", block.w_r()[gate_index + 1]);
1532 info(
"w_3_shift == ", block.w_o()[gate_index + 1]);
1533 info(
"w_4_shift == ", block.w_4()[gate_index + 1]);
1546template <
typename FF,
typename CircuitBuilder>
1549 auto q_nnf = block.q_nnf()[gate_idx];
1550 if (!q_nnf.is_zero()) {
1551 info(
"q_nnf == ", q_nnf);
1552 auto q_2 = block.q_2()[gate_idx];
1553 auto q_3 = block.q_3()[gate_idx];
1554 auto q_4 = block.q_4()[gate_idx];
1555 auto q_m = block.q_m()[gate_idx];
1556 if (q_3 == FF::one() && q_4 == FF::one()) {
1557 info(
"w_1_shift == ", block.w_l()[gate_idx + 1]);
1558 info(
"w_2_shift == ", block.w_r()[gate_idx + 1]);
1560 }
else if (q_3 == FF::one() && q_m == FF::one()) {
1561 info(
"w_1_shift == ", block.w_l()[gate_idx + 1]);
1562 info(
"w_2_shift == ", block.w_r()[gate_idx + 1]);
1563 info(
"w_3_shift == ", block.w_o()[gate_idx + 1]);
1564 info(
"w_4_shift == ", block.w_4()[gate_idx + 1]);
1565 }
else if (q_2 == FF::one() && (q_3 == FF::one() || q_4 == FF::one() || q_m == FF::one())) {
1566 info(
"w_1_shift == ", block.w_l()[gate_idx + 1]);
1567 info(
"w_2_shift == ", block.w_r()[gate_idx + 1]);
1568 if (q_4 == FF::one() || q_m == FF::one()) {
1569 info(
"w_3_shift == ", block.w_o()[gate_idx + 1]);
1570 info(
"w_4_shift == ", block.w_4()[gate_idx + 1]);
1585template <
typename FF,
typename CircuitBuilder>
1588 auto q_memory = block.q_memory()[gate_index];
1589 if (!q_memory.is_zero()) {
1590 info(
"q_memory == ", q_memory);
1591 auto q_1 = block.q_1()[gate_index];
1592 auto q_2 = block.q_2()[gate_index];
1593 auto q_3 = block.q_3()[gate_index];
1594 auto q_4 = block.q_4()[gate_index];
1595 if (q_1 == FF::one() && q_4 == FF::one()) {
1596 info(
"w_1_shift == ", block.w_l()[gate_index + 1]);
1597 info(
"w_2_shift == ", block.w_r()[gate_index + 1]);
1598 }
else if (q_1 == FF::one() && q_2 == FF::one()) {
1599 info(
"w_1_shift == ", block.w_l()[gate_index + 1]);
1600 info(
"w_4_shift == ", block.w_4()[gate_index + 1]);
1601 }
else if (!q_3.is_zero()) {
1602 info(
"w_1_shift == ", block.w_l()[gate_index + 1]);
1603 info(
"w_2_shift == ", block.w_r()[gate_index + 1]);
1604 info(
"w_3_shift == ", block.w_o()[gate_index + 1]);
1605 info(
"w_4_shift == ", block.w_4()[gate_index + 1]);
1619template <
typename FF,
typename CircuitBuilder>
1622 const auto& block_data = circuit_builder.blocks.get();
1623 for (
const auto& [
key, gates] : variable_gates) {
1624 if (
key.first == real_idx) {
1625 for (
size_t i = 0; i < gates.size(); i++) {
1626 size_t gate_index = gates[i];
1627 auto& block = block_data[
key.second];
1628 info(
"---- printing variables in this gate");
1630 block.w_l()[gate_index],
1632 block.w_r()[gate_index],
1634 block.w_o()[gate_index],
1636 block.w_4()[gate_index]);
1637 info(
"---- printing gate info where variable with index ",
key.first,
" was found ----");
1638 print_arithmetic_gate_info(gate_index, block);
1639 print_elliptic_gate_info(gate_index, block);
1640 print_plookup_gate_info(gate_index, block);
1641 print_poseidon2s_gate_info(gate_index, block);
1642 print_delta_range_gate_info(gate_index, block);
1643 print_nnf_gate_info(gate_index, block);
1644 print_memory_gate_info(gate_index, block);
1646 auto q_databus = block.q_busread()[gate_index];
1647 if (!q_databus.is_zero()) {
1648 info(
"q_databus == ", q_databus);
1651 info(
"---- finished printing ----");
1657template <
typename FF,
typename CircuitBuilder>
1661 auto connected_components = find_connected_components();
1662 auto variables_in_one_gate = get_variables_in_one_gate();
1663 return std::make_pair(connected_components, variables_in_one_gate);
#define BB_ASSERT_EQ(actual, expected,...)
#define ASSERT(expression,...)
std::vector< uint32_t > real_variable_index
TranslatorCircuitBuilder creates a circuit that evaluates the correctness of the evaluation of EccOpQ...
void print_delta_range_gate_info(size_t gate_idx, auto &block)
this method prints all information about range constrain gate where variable was found
void process_execution_trace()
void print_memory_gate_info(size_t gate_idx, auto &block)
this method prints all information about memory gate where variable was found
void print_plookup_gate_info(size_t gate_idx, auto &block)
this method prints all information about plookup gate where variable was found
std::vector< uint32_t > get_ram_table_connected_component(const bb::RamTranscript &ram_array)
this method gets the RAM table connected component by processing RAM transcript records
std::unordered_map< uint32_t, std::vector< uint32_t > > variable_adjacency_lists
std::vector< uint32_t > get_eccop_part_connected_component(size_t index, size_t block_idx, auto &blk)
this method creates connected components from elliptic curve operation gates
std::vector< uint32_t > get_memory_gate_connected_component(size_t index, size_t block_idx, auto &blk)
this method creates connected components from Memory gates (RAM and ROM consistency checks)
std::vector< uint32_t > get_plookup_gate_connected_component(size_t index, size_t block_idx, auto &blk)
this method creates connected components from plookup gates
std::pair< std::vector< ConnectedComponent >, std::unordered_set< uint32_t > > analyze_circuit()
void remove_unnecessary_decompose_variables(const std::unordered_set< uint32_t > &decompose_variables)
this method removes unnecessary variables from decompose chains
void depth_first_search(const uint32_t &variable_index, std::unordered_set< uint32_t > &is_used, std::vector< uint32_t > &connected_component)
this method implements depth-first search algorithm for undirected graphs
bool check_is_not_constant_variable(const uint32_t &variable_index)
this method checks whether the variable with given index is not constant
std::vector< uint32_t > get_arithmetic_gate_connected_component(size_t index, size_t block_idx, auto &blk)
this method creates connected components from arithmetic gates
void remove_unnecessary_sha256_plookup_variables(bb::plookup::BasicTableId &table_id, size_t gate_index)
this method removes false cases in sha256 lookup tables. tables which are enumerated in the unordered...
std::unordered_set< uint32_t > get_variables_in_one_gate()
this method returns a final set of variables that were in one gate
std::vector< uint32_t > get_non_native_field_gate_connected_component(size_t index, size_t block_idx, auto &blk)
this method creates connected components from Non-Native Field gates (bigfield operations)
void remove_record_witness_variables()
this method removes record witness variables from variables in one gate. initially record witness is ...
void print_variable_info(const uint32_t real_idx)
this method prints all information about gates where variable was found
void remove_unnecessary_range_constrains_variables()
this method removes variables from range constraints that are not security critical
void print_elliptic_gate_info(size_t gate_idx, auto &block)
this method prints all information about elliptic gate where variable was found
size_t find_block_index(const auto &block)
this method finds index of the block in circuit builder by comparing pointers to blocks
StaticAnalyzer_()=default
std::vector< uint32_t > get_databus_connected_component(size_t index, size_t block_idx, auto &blk)
this method creates connected components from databus gates
void connect_all_variables_in_vector(const std::vector< uint32_t > &variables_vector)
this method connects 2 variables if they are in one gate and 1) have different indices,...
void print_connected_components_info()
this method prints additional information about connected components that were found in the graph
std::vector< uint32_t > get_rom_table_connected_component(const bb::RomTranscript &rom_array)
this method gets the ROM table connected component by processing ROM transcript records
std::vector< uint32_t > get_poseido2s_gate_connected_component(size_t index, size_t block_idx, auto &blk)
this method creates connected components from poseidon2 gates
void print_poseidon2s_gate_info(size_t gate_idx, auto &block)
this method prints all information about poseidon2s gate where variable was found
std::unordered_map< uint32_t, size_t > variables_gate_counts
std::vector< uint32_t > get_sort_constraint_connected_component(size_t index, size_t block_idx, auto &blk)
this method creates connected components from sorted constraints
void remove_unnecessary_aes_plookup_variables(bb::plookup::BasicTableId &table_id, size_t gate_index)
this method removes false positive cases variables from aes plookup tables. AES_SBOX_MAP,...
void process_gate_variables(std::vector< uint32_t > &gate_variables, size_t gate_index, size_t blk_idx)
this method processes variables from a gate by removing duplicates and updating tracking structures
CircuitBuilder & circuit_builder
void remove_unnecessary_plookup_variables()
this method removes false cases plookup variables from variables in one gate
std::vector< uint32_t > get_elliptic_gate_connected_component(size_t index, size_t block_idx, auto &blk)
this method creates connected components from elliptic gates
void print_nnf_gate_info(size_t gate_idx, auto &block)
this method prints all information about non natife field gate where variable was found
void print_arithmetic_gate_info(size_t gate_idx, auto &block)
this method prints all information about arithmetic gate where variable was found
void process_current_plookup_gate(size_t gate_index)
this method removes false cases in lookup table for a given gate. it uses all functions above for loo...
void mark_range_list_connected_components()
this method marks some connected componets like they represent range lists tool needs this method to ...
std::vector< ConnectedComponent > find_connected_components(bool return_all_connected_components=false)
this methond finds all connected components in the graph described by adjacency lists
void print_variables_gate_counts()
this method prints a number of gates for each variable
std::unordered_map< uint32_t, size_t > variables_degree
size_t process_current_decompose_chain(size_t index)
this method removes variables that were created in a function decompose_into_default_range because th...
void add_new_edge(const uint32_t &first_variable_index, const uint32_t &second_variable_index)
this method creates an edge between two variables in graph. All needed checks in a function above
void mark_finalize_connected_components()
this method marks some connected components like they represent separated finalize blocks the point i...
Entry point for Barretenberg command-line interface.
std::pair< uint32_t, size_t > KeyPair
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Each ram array is an instance of memory transcript. It saves values and indexes for a particular memo...
std::vector< RamRecord > records
Each rom array is an instance of memory transcript. It saves values and indexes for a particular memo...
std::vector< RomRecord > records