From f3ab6af6312823485ec834fd64ffcc60a55616ab Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Tue, 13 Aug 2024 15:35:44 +0000 Subject: [PATCH 01/21] graph decription for ultra circuit builder --- .../boomerang_value_detection/CMakeLists.txt | 1 + .../boomerang_value_detection/graph.cpp | 414 +++++++++++++++ .../boomerang_value_detection/graph.hpp | 54 ++ .../graph_description.test.cpp | 490 ++++++++++++++++++ 4 files changed, 959 insertions(+) create mode 100644 barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt create mode 100644 barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp create mode 100644 barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp create mode 100644 barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt new file mode 100644 index 000000000000..b9b2259602ee --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt @@ -0,0 +1 @@ +barretenberg_module(boomerang_value_detection stdlib_circuit_builders circuit_checker) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp new file mode 100644 index 000000000000..9aa9a905594c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -0,0 +1,414 @@ +#include "graph.hpp" +#include +#include + +template Graph_::Graph_(const bb::StandardCircuitBuilder_& circuit_constructor) +{ + this->variable_adjacency_lists = std::vector>(circuit_constructor.real_variable_index.size()); + this->variables_gate_counts = std::unordered_map(circuit_constructor.real_variable_index.size()); + const auto& block = circuit_constructor.blocks.arithmetic; + auto zero_idx = circuit_constructor.zero_idx; + std::map constant_variable_indices = circuit_constructor.constant_variable_indices; + for (auto key : circuit_constructor.real_variable_index) { + variables_gate_counts[key] = 0; + } + for (size_t i = 0; i < circuit_constructor.num_gates; i++) { + uint32_t left_idx = block.w_l()[i]; + uint32_t right_idx = block.w_r()[i]; + uint32_t out_idx = block.w_o()[i]; + + FF q_m = block.q_m()[i]; + FF q_1 = block.q_1()[i]; + FF q_2 = block.q_2()[i]; + FF q_3 = block.q_3()[i]; + std::set unique_gate_variables; + if ((q_m != FF::zero() || q_1 != FF::zero() || q_2 != FF::zero()) && + q_3 != FF::zero()) // this is not constant gate. we don't need constant variables + { + if (q_m != 0) { + unique_gate_variables.insert(left_idx); + unique_gate_variables.insert(right_idx); + } + if (q_1 != 0) { + unique_gate_variables.insert(left_idx); + } + if (q_2 != 0) { + unique_gate_variables.insert(right_idx); + } + if (q_3 != 0) { + unique_gate_variables.insert(out_idx); + } + } + for (const auto& elem : unique_gate_variables) { + variables_gate_counts[elem] += 1; + } + std::vector gate_variables(unique_gate_variables.begin(), unique_gate_variables.end()); + connect_all_variables_in_vector(gate_variables, zero_idx, constant_variable_indices, false); + } +} + +template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit_constructor) +{ + this->variables_gate_counts = + std::unordered_map(ultra_circuit_constructor.real_variable_index.size()); + this->variable_adjacency_lists = + std::vector>(ultra_circuit_constructor.real_variable_index.size()); + for (const auto& variables_index : ultra_circuit_constructor.real_variable_index) { + variables_gate_counts[variables_index] = 0; + } + std::map constant_variable_indices = ultra_circuit_constructor.constant_variable_indices; + uint32_t zero_idx = ultra_circuit_constructor.zero_idx; + auto& arithmetic_block = ultra_circuit_constructor.blocks.arithmetic; + auto arithmetic_gate_numbers = arithmetic_block.size(); + bool arithmetic_gate_exists = arithmetic_gate_numbers > 0; + if (arithmetic_gate_exists) { + for (size_t i = 0; i < arithmetic_gate_numbers; i++) { + if (arithmetic_block.q_arith()[i] != 0) { + uint32_t left_idx = arithmetic_block.w_l()[i]; + uint32_t right_idx = arithmetic_block.w_r()[i]; + uint32_t out_idx = arithmetic_block.w_o()[i]; + uint32_t fourth_idx = arithmetic_block.w_4()[i]; + FF q_m = arithmetic_block.q_m()[i]; + FF q_1 = arithmetic_block.q_1()[i]; + FF q_2 = arithmetic_block.q_2()[i]; + FF q_3 = arithmetic_block.q_3()[i]; + FF q_c = arithmetic_block.q_c()[i]; + FF q_4 = arithmetic_block.q_4()[i]; + std::set unique_gate_variables; + if (q_m == 0 && q_1 == 1 && q_2 == 0 && q_3 == 0 && q_c != 0 && q_4 == 0) { + info("This is the gate for fixing witness. We can ignore it"); + } else { + if (q_m != 0) { + unique_gate_variables.insert(left_idx); + unique_gate_variables.insert(right_idx); + } + if (q_1 != 0) { + unique_gate_variables.insert(left_idx); + } + if (q_2 != 0) { + unique_gate_variables.insert(right_idx); + } + if (q_3 != 0) { + unique_gate_variables.insert(out_idx); + } + if (q_4 != 0) { + unique_gate_variables.insert(fourth_idx); + } + for (const auto& elem : unique_gate_variables) { + variables_gate_counts[elem] += 1; + } + } + std::vector gate_variables(unique_gate_variables.begin(), unique_gate_variables.end()); + connect_all_variables_in_vector(gate_variables, zero_idx, constant_variable_indices, false); + } else { + // this is the dummy gate for arithmetic gate. From ultra_circuit_builder.cpp I know that it was + // created for sort_constraint with wires(variable_indx, zero_idx, zero_idx, zero_idx), + // so it's need to update number_gate_counts for variable w_l()[i] + variables_gate_counts[arithmetic_block.w_l()[i]] += 1; + } + } + } + auto& elliptic_block = ultra_circuit_constructor.blocks.elliptic; + auto elliptic_gate_numbers = elliptic_block.size(); + bool elliptic_gates_exist = elliptic_gate_numbers > 0; + if (elliptic_gates_exist) { + for (size_t i = 0; i < elliptic_gate_numbers; i++) { + std::vector wire_variables = { + elliptic_block.w_l()[i], elliptic_block.w_r()[i], elliptic_block.w_o()[i], elliptic_block.w_4()[i] + }; + for (const auto& elem : wire_variables) { + if (elem != zero_idx) { + variables_gate_counts[elem] += 1; + } + } + } + for (size_t i = 1; i < elliptic_gate_numbers; i++) { + if (elliptic_block.q_elliptic()[i - 1] == 1) { + // the previous gate was connected with our current gate, cause it has the value "q_elliptic = 0" + std::vector coordinates = { elliptic_block.w_l()[i], elliptic_block.w_r()[i], + elliptic_block.w_o()[i], elliptic_block.w_4()[i], + elliptic_block.w_r()[i - 1], elliptic_block.w_o()[i - 1] }; + + connect_all_variables_in_vector(coordinates, zero_idx, constant_variable_indices, false); + } + // if this condition is not approved, then then the previous was dummy gate, and it wasn't connected with + // out current gate, + // so we have to skip this gate and go to the next gate, cause it can extract variables from the current + // gate + } + } + auto& range_block = ultra_circuit_constructor.blocks.delta_range; + auto range_gates = range_block.size(); + bool range_gates_exists = range_gates > 0; + if (range_gates_exists) { + // just go through gates and collect all variables, while we don't meet dummy gate + std::vector sorted_variables; + for (size_t i = 0; i < range_gates; i++) { + if (range_block.q_delta_range()[i] == 1) { + uint32_t left_idx = range_block.w_l()[i]; + uint32_t right_idx = range_block.w_r()[i]; + uint32_t out_idx = range_block.w_o()[i]; + uint32_t fourth_idx = range_block.w_4()[i]; + sorted_variables.emplace_back(left_idx); + sorted_variables.emplace_back(right_idx); + sorted_variables.emplace_back(out_idx); + sorted_variables.emplace_back(fourth_idx); + } else { + // we go to the dummy gate, there's a shift of the variable from the previous gate and + // we have to update variable_gate_counts on 2 for this variable + // after processing the dummy gate we have to clean sorted_variables_vector + auto sorted_variables_size = sorted_variables.size(); + for (size_t i = 0; i < sorted_variables_size; i++) { + if (sorted_variables[i] != zero_idx) { + if (i == sorted_variables_size - 1) { + variables_gate_counts[sorted_variables[i]] += 2; + } else { + variables_gate_counts[sorted_variables[i]] += 1; + } + } + } + connect_all_variables_in_vector(sorted_variables, zero_idx, constant_variable_indices, true); + sorted_variables.clear(); + } + } + } + + auto& lookup_block = ultra_circuit_constructor.blocks.lookup; + auto lookup_gates = lookup_block.size(); + bool lookup_gates_exists = lookup_gates > 0; + if (lookup_gates_exists) { + std::vector left_indexes; + std::vector right_indexes; + std::vector out_indexes; + for (size_t i = 0; i < lookup_gates; i++) { + if (lookup_block.q_lookup_type()[i] == FF(1)) { + uint32_t left_idx = lookup_block.w_l()[i]; + uint32_t right_idx = lookup_block.w_r()[i]; + uint32_t out_idx = lookup_block.w_o()[i]; + left_indexes.emplace_back(left_idx); + right_indexes.emplace_back(right_idx); + out_indexes.emplace_back(out_idx); + std::vector current_gate_variables = { left_idx, right_idx, out_idx }; + for (const auto& variable : current_gate_variables) { + variables_gate_counts[variable] += 1; + } + connect_all_variables_in_vector(current_gate_variables, zero_idx, constant_variable_indices, false); + auto q_2 = lookup_block.q_2()[i]; + auto q_m = lookup_block.q_m()[i]; + auto q_c = lookup_block.q_c()[i]; + if (q_2 == 0 && q_m == 0 && q_c == 0) { + // this is the last gate in the in this blocks of lookup, so we can connect variables from + // left_indexes vectors, right_indexes vector, out_indexes vector + connect_all_variables_in_vector(left_indexes, zero_idx, constant_variable_indices, false); + connect_all_variables_in_vector(right_indexes, zero_idx, constant_variable_indices, false); + connect_all_variables_in_vector(out_indexes, zero_idx, constant_variable_indices, false); + // now we can erase all these vector to begin with new lookup accumulators + left_indexes.clear(); + right_indexes.clear(); + out_indexes.clear(); + } + } + } + } +} + +template +bool Graph_::check_is_not_constant_variable(const uint32_t& variable_index, + const std::map& constant_variable_indices) +{ + // this method checks that variable is not constant, so it's not in constant_variable_indices from ultra circuit + // builder + bool is_not_constant = true; + for (const auto& pair : constant_variable_indices) { + if (pair.second == variable_index) { + is_not_constant = false; + break; + } + } + return is_not_constant; +} + +template +void Graph_::connect_all_variables_in_vector(const std::vector& variables_vector, + const uint32_t& zero_idx, + const std::map& constant_variable_indices, + bool is_sorted_variables) +{ + // this method connects between each other variables that have different indexes, their indexes are not equal + // zero_idx and they are not constant variables, so they are not in constant_variable_indices from ultra circuit + // builder data structure + if (!variables_vector.empty()) { + if (is_sorted_variables) { + for (size_t i = 0; i < variables_vector.size() - 1; i++) { + if (variables_vector[i] != zero_idx && variables_vector[i + 1] != zero_idx && + variables_vector[i] != variables_vector[i + 1]) { + { + bool first_variable_is_not_constant = + check_is_not_constant_variable(variables_vector[i], constant_variable_indices); + bool second_variable_is_not_constant = + check_is_not_constant_variable(variables_vector[i + 1], constant_variable_indices); + if (first_variable_is_not_constant && second_variable_is_not_constant) { + add_new_edge(variables_vector[i], variables_vector[i + 1]); + } + } + } + } + } else { + for (size_t i = 0; i < variables_vector.size() - 1; i++) { + for (size_t j = 1; j < variables_vector.size(); j++) { + if (variables_vector[i] != zero_idx && variables_vector[j] != zero_idx && + variables_vector[i] != variables_vector[j]) { + bool first_variable_is_not_constant = + check_is_not_constant_variable(variables_vector[i], constant_variable_indices); + bool second_variable_is_not_constant = + check_is_not_constant_variable(variables_vector[j], constant_variable_indices); + if (first_variable_is_not_constant && second_variable_is_not_constant) { + add_new_edge(variables_vector[i], variables_vector[j]); + } + } + } + } + } + } +} + +template +void Graph_::add_new_edge(const uint32_t& first_variable_index, const uint32_t& second_variable_index) +{ + if (first_variable_index != second_variable_index) { + this->variable_adjacency_lists[first_variable_index].insert(second_variable_index); + this->variable_adjacency_lists[second_variable_index].insert(first_variable_index); + } +} + +// template +// void Graph_::update_edges_for_sorted_variables(const std::vector& sorted_variables, +// const uint32_t& zero_idx) +//{ +// for (size_t i = 0; i < sorted_variables.size() - 1; i++) { +// if (sorted_variables[i] != zero_idx && sorted_variables[i + 1] != zero_idx) { +// add_new_edge(sorted_variables[i], sorted_variables[i + 1]); +// } +// } +// } + +template std::set Graph_::get_variable_adjacency_list(const uint32_t& variable_index) +{ + if (variable_index >= (this->variable_adjacency_lists).size()) { + throw std::out_of_range("Variable index out of bounds"); + } + return variable_adjacency_lists[variable_index]; +} + +template +void Graph_::depth_first_search(const uint32_t& variable_index, + std::vector& is_used, + std::set& connected_component) +{ + // this method realizes algorith depth_first_search for undirected graph using the give variable + std::stack variable_stack; + variable_stack.push(variable_index); + while (!variable_stack.empty()) { + uint32_t current_index = variable_stack.top(); + variable_stack.pop(); + if (std::find(is_used.begin(), is_used.end(), current_index) == is_used.end()) { + is_used.emplace_back(current_index); + connected_component.insert(current_index); + for (const auto& it : variable_adjacency_lists[current_index]) { + variable_stack.push(it); + } + } + } +} + +template std::vector> Graph_::find_connected_components() +{ + // this methond finds connected components from the graph described by adjacency lists + std::vector is_used; + std::vector> connected_components; + for (size_t i = 2; i < variable_adjacency_lists.size(); i++) { + auto var_index = static_cast(i); + if (std::find(is_used.begin(), is_used.end(), var_index) == is_used.end()) { + std::set connected_component; + depth_first_search(var_index, is_used, connected_component); + connected_components.emplace_back(connected_component); + } + } + return connected_components; +} + +template std::vector Graph_::find_dangerous_variables() +{ + std::vector dangerous_variables; + for (auto& it : variables_gate_counts) { + if (it.first >= 2) { + if (it.second == 1) { + dangerous_variables.emplace_back(it.first); + } + } + } + return dangerous_variables; +} + +template void Graph_::print_graph() +{ + for (size_t i = 2; i < this->variable_adjacency_lists.size(); i++) { + info("variable with index ", i); + if (this->variable_adjacency_lists[i].size() == 0) { + info("is isolated"); + } else { + for (auto it = this->variable_adjacency_lists[i].begin(); it != this->variable_adjacency_lists[i].end(); + ++it) { + info(*it, " "); + } + } + } +} + +template void Graph_::print_connected_components() +{ + auto connected_components = find_connected_components(); + for (size_t i = 0; i < connected_components.size(); i++) { + info("printing the ", i, " connected component:"); + for (const auto& it : connected_components[i]) { + info(it, " "); + } + } +} + +template +void Graph_::print_dangerous_variables(const bb::StandardCircuitBuilder_& circuit_constructor) +{ + auto dangerous_variables = find_dangerous_variables(); + const auto& block = circuit_constructor.blocks.arithmetic; + for (const auto& it : dangerous_variables) { + info("index of the possible dangerous variable with index ", it); + for (size_t i = 0; i < circuit_constructor.num_gates; i++) { + uint32_t left_idx = block.w_l()[i]; + uint32_t right_idx = block.w_r()[i]; + uint32_t out_idx = block.w_o()[i]; + if (it == left_idx || it == right_idx || it == out_idx) { + info("variable ", it, " in the gate with number ", i); + // std::vector selectors = { + // block.q_m()[i], block.q_1()[i], block.q_2()[i], block.q_3()[i], + // block.q_c()[i] + // }; + // info("selectors of this gate: "); + // for (const auto& it : selectors) { + // info(it); + // } + break; + } + } + } +} + +template void Graph_::print_variables_gate_counts() +{ + for (auto& it : variables_gate_counts) { + info("number of gates with variables ", it.first); + info(it.second); + } +} + +template class Graph_; \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp new file mode 100644 index 000000000000..6a95554156f7 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp @@ -0,0 +1,54 @@ +#pragma once +#include "barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +#include +#include +#include +#include + +template class Graph_ { + public: + Graph_() = default; + Graph_(const Graph_& other) = delete; + Graph_(Graph_&& other) = delete; + Graph_& operator=(const Graph_& other) = delete; + Graph_&& operator=(Graph_&& other) = delete; + Graph_(const bb::StandardCircuitBuilder_& circuit_constructor); + Graph_(bb::UltraCircuitBuilder& ultra_circuit_constructor); + + bool is_variable_exist(const uint32_t& variable_index); + void add_new_edge(const uint32_t& first_variable_index, const uint32_t& second_variable_index); + + std::set get_variable_adjacency_list(const uint32_t& variable_index); + void depth_first_search(const uint32_t& variable_index, + std::vector& is_used, + std::set& connected_component); + std::vector> find_connected_components(); + std::vector find_dangerous_variables(); + std::unordered_map get_variables_gate_counts() { return this->variables_gate_counts; }; + size_t get_distance_between_variables(const uint32_t& first_variable_index, const uint32_t& second_variable_index); + bool check_vertex_in_connected_component(const std::vector& connected_component, + const uint32_t& var_index); + + void update_edges_for_sorted_variables(const std::vector& sorted_variables, + const uint32_t& zero_idx, + const std::map& constant_variable_indices); + void connect_all_variables_in_vector(const std::vector& variables_vector, + const uint32_t& zero_idx, + const std::map& constant_variable_indices, + bool is_sorted_variables); + bool check_is_not_constant_variable(const uint32_t& variable_index, + const std::map& constant_variable_indices); + + void print_graph(); + void print_connected_components(); + void print_variables_gate_counts(); + void print_dangerous_variables(const bb::StandardCircuitBuilder_& circuit_constructor); + ~Graph_() = default; + + private: + std::vector> variable_adjacency_lists; + std::unordered_map variables_gate_counts; +}; + +using Graph = Graph_; \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp new file mode 100644 index 000000000000..90b7d0dc1f44 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp @@ -0,0 +1,490 @@ +#include "barretenberg/boomerang_value_detection/graph.hpp" +#include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/crypto/generators/generator_data.hpp" +#include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" +#include "barretenberg/stdlib_circuit_builders/mock_circuits.hpp" +#include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" +#include "barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" + +#include + +using namespace bb; + +TEST(standard_circuit_constructor, test_empty_graph) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr::one(); + circuit_constructor.add_public_variable(a); + Graph graph = Graph(circuit_constructor); + + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); +} + +TEST(standard_circuit_constructor, test_graph_with_three_vertexes) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr::random_element(); + fr b = fr::random_element(); + fr c = a + b; + uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + uint32_t c_idx = circuit_constructor.add_variable(c); + circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + Graph graph = Graph(circuit_constructor); + graph.print_graph(); +} + +TEST(standard_circuit_constructor, test_graph_with_two_gates) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr::random_element(); + fr b = fr::random_element(); + fr c = fr::random_element(); + fr d = a + b; + + uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + uint32_t c_idx = circuit_constructor.add_variable(c); + uint32_t d_idx = circuit_constructor.add_variable(d); + circuit_constructor.create_add_gate({ a_idx, b_idx, d_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + fr g = c * d; + uint32_t g_idx = circuit_constructor.add_variable(g); + circuit_constructor.create_mul_gate({ c_idx, d_idx, g_idx, fr::one(), fr::neg_one(), fr::zero() }); + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + Graph graph = Graph(circuit_constructor); + graph.print_graph(); +} + +TEST(standard_circuit_constructor, test_graph_with_boomerang_variable) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr::random_element(); // взяли случайный элемент + uint32_t a_idx = circuit_constructor.add_public_variable(a); // добавили его в схему + fr b = fr::random_element(); // еще один случайный элемент + fr c = a + b; + fr d = fr::random_element(); + fr e = d + a; // + // uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + uint32_t c_idx = circuit_constructor.add_variable(c); + uint32_t d_idx = circuit_constructor.add_variable(d); + uint32_t e_idx = circuit_constructor.add_variable(e); + uint32_t a_duplicate_idx = circuit_constructor.add_variable( + a); // вот это бумеранг, потому что e работало именно с a, но между ними a_duplicate и a нет никакой связи. + circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + circuit_constructor.create_add_gate( + { a_duplicate_idx, d_idx, e_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + + bool result = CircuitChecker::check(circuit_constructor); + bool result1 = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + EXPECT_EQ(result1, true); + Graph graph = Graph(circuit_constructor); + graph.print_graph(); +} + +TEST(standard_circuit_constructor, test_graph_connected_components) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr::random_element(); + fr b = fr::random_element(); + fr c = a + b; + uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + uint32_t c_idx = circuit_constructor.add_variable(c); + circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + Graph graph = Graph(circuit_constructor); + graph.print_graph(); + graph.print_connected_components(); +} + +TEST(standard_circuit_constructor, test_graph_with_two_connected_components) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr::random_element(); // взяли случайный элемент + uint32_t a_idx = circuit_constructor.add_public_variable(a); // добавили его в схему + fr b = fr::random_element(); // еще один случайный элемент + fr c = a + b; + fr d = fr::random_element(); + fr e = d + a; // + // uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + uint32_t c_idx = circuit_constructor.add_variable(c); + uint32_t d_idx = circuit_constructor.add_variable(d); + uint32_t e_idx = circuit_constructor.add_variable(e); + uint32_t a_duplicate_idx = circuit_constructor.add_variable( + a); // вот это бумеранг, потому что e работало именно с a, но между ними a_duplicate и a нет никакой связи. + circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + circuit_constructor.create_add_gate( + { a_duplicate_idx, d_idx, e_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + + bool result = CircuitChecker::check(circuit_constructor); + bool result1 = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + EXPECT_EQ(result1, true); + Graph graph = Graph(circuit_constructor); + graph.print_connected_components(); +} + +TEST(standard_circuit_builder, test_graph_connected_component_boomerang_variable) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr::random_element(); + fr b = fr::random_element(); + fr c = a + b; + uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + uint32_t c_idx = circuit_constructor.add_variable(c); + circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + fr d = fr::random_element(); + fr e = fr::random_element(); + fr f = d + e; + uint32_t d_idx = circuit_constructor.add_variable(d); + uint32_t e_idx = circuit_constructor.add_variable(e); + uint32_t f_idx = circuit_constructor.add_variable(f); + circuit_constructor.create_add_gate({ d_idx, e_idx, f_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + fr g = c * f; + fr g1 = c + f; + uint32_t g_idx = circuit_constructor.add_variable(g); + uint32_t g1_idx = circuit_constructor.add_variable(g1); + circuit_constructor.create_mul_gate({ c_idx, f_idx, g_idx, fr::one(), fr::neg_one(), fr::zero() }); + circuit_constructor.create_add_gate({ c_idx, f_idx, g1_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + fr g_dupl = circuit_constructor.get_variable(g_idx); + fr g_inv = g_dupl.invert(); + fr g_2 = g_inv + g1; + uint32_t g_inv_idx = circuit_constructor.add_variable(g_inv); + uint32_t g2_idx = circuit_constructor.add_variable(g_2); + circuit_constructor.create_add_gate({ g_inv_idx, g1_idx, g2_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + Graph graph = Graph(circuit_constructor); + graph.print_connected_components(); +} + +TEST(standard_circuit_constructor, test_graph_for_logic_constraint) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr(1); + fr b = fr(2); + uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + size_t num_bits = 2; + auto accumulators = circuit_constructor.create_logic_constraint(a_idx, b_idx, num_bits, true); + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + Graph graph = Graph(circuit_constructor); + graph.print_connected_components(); +} + +TEST(standard_circuit_constructor, test_logic_constraint_degree_one) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr(1); + fr b = fr(2); + uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + size_t num_bits = 2; + auto accumulators = circuit_constructor.create_logic_constraint(a_idx, b_idx, num_bits, true); + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + Graph graph = Graph(circuit_constructor); + graph.print_dangerous_variables(circuit_constructor); +} + +TEST(standard_circuit_constructor, test_logic_constraint_also_degree_two) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr(1); + fr b = fr(2); + uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + size_t num_bits = 2; + auto accumulators = circuit_constructor.create_logic_constraint(a_idx, b_idx, num_bits, true); + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + Graph graph = Graph(circuit_constructor); + graph.print_dangerous_variables(circuit_constructor); +} + +TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + + for (size_t i = 0; i < 16; ++i) { + for (size_t j = 0; j < 16; ++j) { + uint64_t left = static_cast(j); + uint64_t right = static_cast(i); + uint32_t left_idx = circuit_constructor.add_variable(fr(left)); + uint32_t right_idx = circuit_constructor.add_variable(fr(right)); + uint32_t result_idx = circuit_constructor.add_variable(fr(left ^ right)); + + uint32_t add_idx = + circuit_constructor.add_variable(fr(left) + fr(right) + circuit_constructor.get_variable(result_idx)); + circuit_constructor.create_big_add_gate( + { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); + } + } + + bool result = CircuitChecker::check(circuit_constructor); + Graph graph = Graph(circuit_constructor); + // graph.print_graph(); + graph.print_connected_components(); + EXPECT_EQ(result, true); +} + +TEST(ultra_circuit_constructor, test_graph_for_bool_gates) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + + for (size_t i = 0; i < 20; ++i) { + fr a = fr::zero(); + uint32_t a_idx = circuit_constructor.add_variable(a); + circuit_constructor.create_bool_gate(a_idx); + } + + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + Graph graph = Graph(circuit_constructor); + graph.print_graph(); + graph.print_connected_components(); +} + +TEST(ultra_circuit_constructor, test_graph_for_elliptic_add_gate) +{ + typedef grumpkin::g1::affine_element affine_element; + typedef grumpkin::g1::element element; + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + + affine_element p1 = crypto::pedersen_commitment::commit_native({ bb::fr(1) }, 0); + + affine_element p2 = crypto::pedersen_commitment::commit_native({ bb::fr(1) }, 1); + affine_element p3(element(p1) + element(p2)); + + uint32_t x1 = circuit_constructor.add_variable(p1.x); + uint32_t y1 = circuit_constructor.add_variable(p1.y); + uint32_t x2 = circuit_constructor.add_variable(p2.x); + uint32_t y2 = circuit_constructor.add_variable(p2.y); + uint32_t x3 = circuit_constructor.add_variable(p3.x); + uint32_t y3 = circuit_constructor.add_variable(p3.y); + + circuit_constructor.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, 1 }); + + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + Graph graph = Graph(circuit_constructor); + graph.print_connected_components(); + graph.print_variables_gate_counts(); + // circuit_constructor.create_ecc_add_gate({ x1 + 1, y1, x2, y2, x3, y3, 1 }); + // EXPECT_EQ(CircuitChecker::check(circuit_constructor), false); +} + +TEST(ultra_circuit_constructor, test_for_elliptic_double_gate) +{ + typedef grumpkin::g1::affine_element affine_element; + typedef grumpkin::g1::element element; + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + + affine_element p1 = crypto::pedersen_commitment::commit_native({ bb::fr(1) }, 0); + affine_element p3(element(p1).dbl()); + + uint32_t x1 = circuit_constructor.add_variable(p1.x); + uint32_t y1 = circuit_constructor.add_variable(p1.y); + uint32_t x3 = circuit_constructor.add_variable(p3.x); + uint32_t y3 = circuit_constructor.add_variable(p3.y); + info("x1, y1, x3, y3 == ", x1, " ", y1, " ", x3, " ", y3); + + circuit_constructor.create_ecc_dbl_gate({ x1, y1, x3, y3 }); + + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + + Graph graph = Graph(circuit_constructor); + graph.print_connected_components(); + graph.print_variables_gate_counts(); +} + +TEST(ultra_circuit_constructor, test_graph_for_elliptic_gates_with_arithmetic_gates) +{ + // for (size_t i = 0; i < 5; ++i) { + // for (size_t j = 0; j < 5; ++j) { + // uint64_t left = static_cast(j); + // uint64_t right = static_cast(i); + // uint32_t left_idx = circuit_constructor.add_variable(fr(left)); + // uint32_t right_idx = circuit_constructor.add_variable(fr(right)); + // uint32_t result_idx = circuit_constructor.add_variable(fr(left ^ right)); + + // uint32_t add_idx = + // circuit_constructor.add_variable(fr(left) + fr(right) + circuit_constructor.get_variable(result_idx)); + // circuit_constructor.create_big_add_gate( + // { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); + // } + //} + + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + + typedef grumpkin::g1::affine_element affine_element; + typedef grumpkin::g1::element element; + + affine_element p1 = crypto::pedersen_commitment::commit_native({ bb::fr(1) }, 0); + affine_element p2 = crypto::pedersen_commitment::commit_native({ bb::fr(1) }, 1); + affine_element p3(element(p1) + element(p2)); + + uint32_t x1 = circuit_constructor.add_variable(p1.x); + uint32_t y1 = circuit_constructor.add_variable(p1.y); + uint32_t x2 = circuit_constructor.add_variable(p2.x); + uint32_t y2 = circuit_constructor.add_variable(p2.y); + uint32_t x3 = circuit_constructor.add_variable(p3.x); + uint32_t y3 = circuit_constructor.add_variable(p3.y); + + circuit_constructor.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, 1 }); + // info("number of elliptic gates after ecc_add_gate == ", circuit_constructor.blocks.elliptic.size()); + affine_element p4(element(p3).dbl()); + uint32_t x4 = circuit_constructor.add_variable(p4.x); + uint32_t y4 = circuit_constructor.add_variable(p4.y); + circuit_constructor.create_ecc_dbl_gate({ x3, y3, x4, y4 }); + // info("number of elliptic gates after ecc_dbl_gate == ", circuit_constructor.blocks.elliptic.size()); + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + + affine_element p5 = crypto::pedersen_commitment::commit_native({ bb::fr(2) }, 1); + affine_element p6 = crypto::pedersen_commitment::commit_native({ bb::fr(3) }, 1); + affine_element p7(element(p5) + element(p6)); + + uint32_t x5 = circuit_constructor.add_variable(p5.x); + uint32_t y5 = circuit_constructor.add_variable(p5.y); + uint32_t x6 = circuit_constructor.add_variable(p6.x); + uint32_t y6 = circuit_constructor.add_variable(p6.y); + uint32_t x7 = circuit_constructor.add_variable(p7.x); + uint32_t y7 = circuit_constructor.add_variable(p7.y); + + circuit_constructor.create_ecc_add_gate({ x5, y5, x6, y6, x7, y7, 1 }); + affine_element p8(element(p7).dbl()); + uint32_t x8 = circuit_constructor.add_variable(p8.x); + uint32_t y8 = circuit_constructor.add_variable(p8.y); + circuit_constructor.create_ecc_dbl_gate({ x7, y7, x8, y8 }); + + info("number of elliptic gates = ", circuit_constructor.blocks.elliptic.size()); + Graph graph = Graph(circuit_constructor); + graph.print_graph(); + graph.print_connected_components(); + graph.print_variables_gate_counts(); +} + +TEST(ultra_circuit_constructor, test_graph_with_sort_constraints) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + fr a = fr::one(); + fr b = fr(2); + fr c = fr(3); + fr d = fr(4); + + auto a_idx = circuit_constructor.add_variable(a); + auto b_idx = circuit_constructor.add_variable(b); + auto c_idx = circuit_constructor.add_variable(c); + auto d_idx = circuit_constructor.add_variable(d); + circuit_constructor.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); + + fr e = fr(5); + fr f = fr(6); + fr g = fr(7); + fr h = fr(8); + auto e_idx = circuit_constructor.add_variable(e); + auto f_idx = circuit_constructor.add_variable(f); + auto g_idx = circuit_constructor.add_variable(g); + auto h_idx = circuit_constructor.add_variable(h); + circuit_constructor.create_sort_constraint({ e_idx, f_idx, g_idx, h_idx }); + + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + + Graph graph = Graph(circuit_constructor); + graph.print_graph(); + graph.print_connected_components(); + graph.print_variables_gate_counts(); +} + +TEST(ultra_circuit_constructor, test_graph_with_sort_constraints_with_edges) +{ + fr a = fr::one(); + fr b = fr(2); + fr c = fr(3); + fr d = fr(4); + fr e = fr(5); + fr f = fr(6); + fr g = fr(7); + fr h = fr(8); + + UltraCircuitBuilder circuit_constructor; + auto a_idx = circuit_constructor.add_variable(a); + auto b_idx = circuit_constructor.add_variable(b); + auto c_idx = circuit_constructor.add_variable(c); + auto d_idx = circuit_constructor.add_variable(d); + auto e_idx = circuit_constructor.add_variable(e); + auto f_idx = circuit_constructor.add_variable(f); + auto g_idx = circuit_constructor.add_variable(g); + auto h_idx = circuit_constructor.add_variable(h); + circuit_constructor.create_sort_constraint_with_edges( + { a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, a, h); + + fr a1 = fr(9); + fr b1 = fr(10); + fr c1 = fr(11); + fr d1 = fr(12); + fr e1 = fr(13); + fr f1 = fr(14); + fr g1 = fr(15); + fr h1 = fr(16); + + auto a1_idx = circuit_constructor.add_variable(a1); + auto b1_idx = circuit_constructor.add_variable(b1); + auto c1_idx = circuit_constructor.add_variable(c1); + auto d1_idx = circuit_constructor.add_variable(d1); + auto e1_idx = circuit_constructor.add_variable(e1); + auto f1_idx = circuit_constructor.add_variable(f1); + auto g1_idx = circuit_constructor.add_variable(g1); + auto h1_idx = circuit_constructor.add_variable(h1); + + circuit_constructor.create_sort_constraint_with_edges( + { a1_idx, b1_idx, c1_idx, d1_idx, e1_idx, f1_idx, g1_idx, h1_idx }, a1, h1); + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + Graph graph = Graph(circuit_constructor); + + graph.print_graph(); + graph.print_connected_components(); + graph.print_variables_gate_counts(); +} + +TEST(ultra_circuit_constructor, create_gates_from_plookup_accumulators) +{ + + UltraCircuitBuilder circuit_builder = UltraCircuitBuilder(); + + fr input_value = fr::random_element(); + const fr input_lo = static_cast(input_value) + .slice(0, plookup::fixed_base::table::BITS_PER_LO_SCALAR); // обрезал последние 128 бит + const auto input_lo_index = circuit_builder.add_variable(input_lo); // добавил получившееся значение в схему + + const auto sequence_data_lo = plookup::get_lookup_accumulators(plookup::MultiTableId::FIXED_BASE_LEFT_LO, input_lo); + + const auto lookup_witnesses = circuit_builder.create_gates_from_plookup_accumulators( + plookup::MultiTableId::FIXED_BASE_LEFT_LO, sequence_data_lo, input_lo_index); + + const size_t num_lookups = plookup::fixed_base::table::NUM_TABLES_PER_LO_MULTITABLE; + + EXPECT_EQ(num_lookups, lookup_witnesses[plookup::ColumnIdx::C1].size()); + + bool result = CircuitChecker::check(circuit_builder); + EXPECT_EQ(result, true); + Graph graph = Graph(circuit_builder); + graph.print_connected_components(); +} \ No newline at end of file From 10508e1c7f4db08850da449c99263a875215b07b Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Tue, 13 Aug 2024 15:45:18 +0000 Subject: [PATCH 02/21] update_edges_for_sorted_variabes, cause it's useless now --- .../boomerang_value_detection/graph.cpp | 19 ------------------- .../boomerang_value_detection/graph.hpp | 8 ++++---- 2 files changed, 4 insertions(+), 23 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp index 9aa9a905594c..cee4ae7c80bb 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -281,17 +281,6 @@ void Graph_::add_new_edge(const uint32_t& first_variable_index, const uint32 } } -// template -// void Graph_::update_edges_for_sorted_variables(const std::vector& sorted_variables, -// const uint32_t& zero_idx) -//{ -// for (size_t i = 0; i < sorted_variables.size() - 1; i++) { -// if (sorted_variables[i] != zero_idx && sorted_variables[i + 1] != zero_idx) { -// add_new_edge(sorted_variables[i], sorted_variables[i + 1]); -// } -// } -// } - template std::set Graph_::get_variable_adjacency_list(const uint32_t& variable_index) { if (variable_index >= (this->variable_adjacency_lists).size()) { @@ -389,14 +378,6 @@ void Graph_::print_dangerous_variables(const bb::StandardCircuitBuilder_ uint32_t out_idx = block.w_o()[i]; if (it == left_idx || it == right_idx || it == out_idx) { info("variable ", it, " in the gate with number ", i); - // std::vector selectors = { - // block.q_m()[i], block.q_1()[i], block.q_2()[i], block.q_3()[i], - // block.q_c()[i] - // }; - // info("selectors of this gate: "); - // for (const auto& it : selectors) { - // info(it); - // } break; } } diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp index 6a95554156f7..bfe66e8f9dda 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp @@ -31,14 +31,14 @@ template class Graph_ { const uint32_t& var_index); void update_edges_for_sorted_variables(const std::vector& sorted_variables, - const uint32_t& zero_idx, - const std::map& constant_variable_indices); + const std::map& constant_variable_indices, + const uint32_t& zero_idx); void connect_all_variables_in_vector(const std::vector& variables_vector, const uint32_t& zero_idx, - const std::map& constant_variable_indices, + const std::map& constant_variables_indices, bool is_sorted_variables); bool check_is_not_constant_variable(const uint32_t& variable_index, - const std::map& constant_variable_indices); + const std::map& constant_variables_indices); void print_graph(); void print_connected_components(); From 314f4f096145f7cc5dfcde4cadc625030b73f22d Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Tue, 13 Aug 2024 16:42:30 +0000 Subject: [PATCH 03/21] git ignore was added --- .../cpp/src/barretenberg/boomerang_value_detection/.gitignore | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 barretenberg/cpp/src/barretenberg/boomerang_value_detection/.gitignore diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/.gitignore b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/.gitignore new file mode 100644 index 000000000000..c4794383345b --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/.gitignore @@ -0,0 +1,3 @@ +* +!.gitignore +!/src/barretenberg/boomerang_value_detection/** From 346f1bc8f423e8a21610be3bf9f07a92fa78682b Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Tue, 13 Aug 2024 16:47:27 +0000 Subject: [PATCH 04/21] remove some commentaries from tests --- .../boomerang_value_detection/graph.hpp | 2 +- .../graph_description.test.cpp | 38 ++++--------------- 2 files changed, 9 insertions(+), 31 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp index bfe66e8f9dda..668f589d0320 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp @@ -35,7 +35,7 @@ template class Graph_ { const uint32_t& zero_idx); void connect_all_variables_in_vector(const std::vector& variables_vector, const uint32_t& zero_idx, - const std::map& constant_variables_indices, + const std::map& constant_variable_indices, bool is_sorted_variables); bool check_is_not_constant_variable(const uint32_t& variable_index, const std::map& constant_variables_indices); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp index 90b7d0dc1f44..a0c9ce9bd781 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp @@ -64,9 +64,9 @@ TEST(standard_circuit_constructor, test_graph_with_two_gates) TEST(standard_circuit_constructor, test_graph_with_boomerang_variable) { StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::random_element(); // взяли случайный элемент - uint32_t a_idx = circuit_constructor.add_public_variable(a); // добавили его в схему - fr b = fr::random_element(); // еще один случайный элемент + fr a = fr::random_element(); + uint32_t a_idx = circuit_constructor.add_public_variable(a); + fr b = fr::random_element(); fr c = a + b; fr d = fr::random_element(); fr e = d + a; // @@ -75,8 +75,7 @@ TEST(standard_circuit_constructor, test_graph_with_boomerang_variable) uint32_t c_idx = circuit_constructor.add_variable(c); uint32_t d_idx = circuit_constructor.add_variable(d); uint32_t e_idx = circuit_constructor.add_variable(e); - uint32_t a_duplicate_idx = circuit_constructor.add_variable( - a); // вот это бумеранг, потому что e работало именно с a, но между ними a_duplicate и a нет никакой связи. + uint32_t a_duplicate_idx = circuit_constructor.add_variable(a); circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); circuit_constructor.create_add_gate( { a_duplicate_idx, d_idx, e_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); @@ -110,19 +109,17 @@ TEST(standard_circuit_constructor, test_graph_connected_components) TEST(standard_circuit_constructor, test_graph_with_two_connected_components) { StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::random_element(); // взяли случайный элемент - uint32_t a_idx = circuit_constructor.add_public_variable(a); // добавили его в схему - fr b = fr::random_element(); // еще один случайный элемент + fr a = fr::random_element(); + uint32_t a_idx = circuit_constructor.add_public_variable(a); + fr b = fr::random_element(); fr c = a + b; fr d = fr::random_element(); fr e = d + a; // - // uint32_t a_idx = circuit_constructor.add_variable(a); uint32_t b_idx = circuit_constructor.add_variable(b); uint32_t c_idx = circuit_constructor.add_variable(c); uint32_t d_idx = circuit_constructor.add_variable(d); uint32_t e_idx = circuit_constructor.add_variable(e); - uint32_t a_duplicate_idx = circuit_constructor.add_variable( - a); // вот это бумеранг, потому что e работало именно с a, но между ними a_duplicate и a нет никакой связи. + uint32_t a_duplicate_idx = circuit_constructor.add_variable(a); circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); circuit_constructor.create_add_gate( { a_duplicate_idx, d_idx, e_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); @@ -283,8 +280,6 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_add_gate) Graph graph = Graph(circuit_constructor); graph.print_connected_components(); graph.print_variables_gate_counts(); - // circuit_constructor.create_ecc_add_gate({ x1 + 1, y1, x2, y2, x3, y3, 1 }); - // EXPECT_EQ(CircuitChecker::check(circuit_constructor), false); } TEST(ultra_circuit_constructor, test_for_elliptic_double_gate) @@ -314,21 +309,6 @@ TEST(ultra_circuit_constructor, test_for_elliptic_double_gate) TEST(ultra_circuit_constructor, test_graph_for_elliptic_gates_with_arithmetic_gates) { - // for (size_t i = 0; i < 5; ++i) { - // for (size_t j = 0; j < 5; ++j) { - // uint64_t left = static_cast(j); - // uint64_t right = static_cast(i); - // uint32_t left_idx = circuit_constructor.add_variable(fr(left)); - // uint32_t right_idx = circuit_constructor.add_variable(fr(right)); - // uint32_t result_idx = circuit_constructor.add_variable(fr(left ^ right)); - - // uint32_t add_idx = - // circuit_constructor.add_variable(fr(left) + fr(right) + circuit_constructor.get_variable(result_idx)); - // circuit_constructor.create_big_add_gate( - // { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); - // } - //} - UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); typedef grumpkin::g1::affine_element affine_element; @@ -346,12 +326,10 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_gates_with_arithmetic_ga uint32_t y3 = circuit_constructor.add_variable(p3.y); circuit_constructor.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, 1 }); - // info("number of elliptic gates after ecc_add_gate == ", circuit_constructor.blocks.elliptic.size()); affine_element p4(element(p3).dbl()); uint32_t x4 = circuit_constructor.add_variable(p4.x); uint32_t y4 = circuit_constructor.add_variable(p4.y); circuit_constructor.create_ecc_dbl_gate({ x3, y3, x4, y4 }); - // info("number of elliptic gates after ecc_dbl_gate == ", circuit_constructor.blocks.elliptic.size()); bool result = CircuitChecker::check(circuit_constructor); EXPECT_EQ(result, true); From 8375f468f6d8b45efefc4efe38fd8cbb487d4749 Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Tue, 13 Aug 2024 17:05:22 +0000 Subject: [PATCH 05/21] remove all commentaries from another directiories and add my module in CMakeLists.txt --- barretenberg/barretenberg.code-workspace | 6 +- barretenberg/cpp/src/CMakeLists.txt | 1 + .../standard_circuit_builder.test.cpp | 97 +++++++++++++++++++ .../standard_circuit_builder.cpp | 59 ++++++++++- .../standard_circuit_builder.hpp | 1 + 5 files changed, 157 insertions(+), 7 deletions(-) diff --git a/barretenberg/barretenberg.code-workspace b/barretenberg/barretenberg.code-workspace index cd08c7a31666..1b3c9893e815 100644 --- a/barretenberg/barretenberg.code-workspace +++ b/barretenberg/barretenberg.code-workspace @@ -3,9 +3,9 @@ // relative to `.code-workspace`. "folders": [ { - "name": "barretenberg", - "path": "./" - }, + "name": "aztec-packages", + "path": ".." + } ], // List recommended extensions for the whole workspace. "extensions": { diff --git a/barretenberg/cpp/src/CMakeLists.txt b/barretenberg/cpp/src/CMakeLists.txt index 018021e33f91..85fbaf19f385 100644 --- a/barretenberg/cpp/src/CMakeLists.txt +++ b/barretenberg/cpp/src/CMakeLists.txt @@ -63,6 +63,7 @@ endif() add_subdirectory(barretenberg/client_ivc) add_subdirectory(barretenberg/bb) +add_subdirectory(barretenberg/boomerang_value_detection) add_subdirectory(barretenberg/circuit_checker) add_subdirectory(barretenberg/commitment_schemes) add_subdirectory(barretenberg/commitment_schemes_recursion) diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/standard_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/standard_circuit_builder.test.cpp index 65d96e1c998b..927a4fbd5cb7 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/standard_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/standard_circuit_builder.test.cpp @@ -466,3 +466,100 @@ TEST(standard_circuit_constructor, test_check_circuit_broken) bool result = CircuitChecker::check(circuit_constructor); EXPECT_EQ(result, false); } + +TEST(standard_circuit, test_boomerang_value_1) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr::random_element(); // взяли случайный элемент + uint32_t a_idx = circuit_constructor.add_public_variable(a); // добавили его в схему + fr b = fr::random_element(); // еще один случайный элемент + fr c = a + b; + fr d = fr::random_element(); + fr e = d + a; // + // uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + uint32_t c_idx = circuit_constructor.add_variable(c); + uint32_t d_idx = circuit_constructor.add_variable(d); + uint32_t e_idx = circuit_constructor.add_variable(e); + uint32_t a_duplicate_idx = circuit_constructor.add_variable( + a); // вот это бумеранг, потому что e работало именно с a, но между ними a_duplicate и a нет никакой связи. + circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + circuit_constructor.create_add_gate( + { a_duplicate_idx, d_idx, e_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + + bool result = CircuitChecker::check(circuit_constructor); + bool result1 = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + EXPECT_EQ(result1, true); + circuit_constructor.print_boomerang_variables(); +} + +TEST(standard_circuit_constructor, print_boomerang_variables) +{ + // need to calculate expression a + 2 * b + 3 * c + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr::random_element(); + fr b = fr::random_element(); + fr c = fr::random_element(); + fr two = fr(2); + fr three = fr(3); + uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + uint32_t c_idx = circuit_constructor.add_variable(c); + fr d1 = circuit_constructor.get_variable(a_idx) + two * circuit_constructor.get_variable(b_idx); + uint32_t d1_idx = circuit_constructor.add_variable(d1); + fr d2 = circuit_constructor.get_variable(d1_idx) + three * circuit_constructor.get_variable(c_idx); + uint32_t d2_idx = circuit_constructor.add_variable(d2); + circuit_constructor.create_add_gate({ d1_idx, c_idx, d2_idx, fr::one(), three, fr::neg_one(), fr::zero() }); + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + circuit_constructor.print_boomerang_variables(); +} + +TEST(standard_circuit_constructor, test_logic_constraint) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr(1); + fr b = fr(2); + uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + size_t num_bits = 2; + auto accumulators = circuit_constructor.create_logic_constraint(a_idx, b_idx, num_bits, true); + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + circuit_constructor.print_boomerang_variables(); +} + +TEST(standard_circuit_builder, test_boomerang_value_4) +{ + StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); + fr a = fr::random_element(); + fr b = fr::random_element(); + fr c = a + b; + uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t b_idx = circuit_constructor.add_variable(b); + uint32_t c_idx = circuit_constructor.add_variable(c); + circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + fr d = fr::random_element(); + fr e = fr::random_element(); + fr f = d + e; + uint32_t d_idx = circuit_constructor.add_variable(d); + uint32_t e_idx = circuit_constructor.add_variable(e); + uint32_t f_idx = circuit_constructor.add_variable(f); + circuit_constructor.create_add_gate({ d_idx, e_idx, f_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + fr g = c * f; + fr g1 = c + f; + uint32_t g_idx = circuit_constructor.add_variable(g); + uint32_t g1_idx = circuit_constructor.add_variable(g1); + circuit_constructor.create_mul_gate({ c_idx, f_idx, g_idx, fr::one(), fr::neg_one(), fr::zero() }); + circuit_constructor.create_add_gate({ c_idx, f_idx, g1_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + fr g_dupl = circuit_constructor.get_variable(g_idx); + fr g_inv = g_dupl.invert(); + fr g_2 = g_inv + g1; + uint32_t g_inv_idx = circuit_constructor.add_variable(g_inv); + uint32_t g2_idx = circuit_constructor.add_variable(g_2); + circuit_constructor.create_add_gate({ g_inv_idx, g1_idx, g2_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + bool result = CircuitChecker::check(circuit_constructor); + EXPECT_EQ(result, true); + circuit_constructor.print_boomerang_variables(); +} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.cpp index b2fada856cbb..30c222524223 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.cpp @@ -1,11 +1,11 @@ #include "standard_circuit_builder.hpp" #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" -#include -#include - #include "barretenberg/serialize/cbind.hpp" #include "barretenberg/serialize/msgpack.hpp" +#include +#include +#include namespace bb { @@ -319,7 +319,7 @@ accumulator_triple_ StandardCircuitBuilder_::create_logic_constraint(con uint32_t out_accumulator_idx = this->zero_idx; constexpr FF four = FF(4); constexpr FF neg_two = -FF(2); - constexpr FF two = FF(2); + // constexpr FF two = FF(2); // Num bits is expected to be even ASSERT(num_bits % 2 == 0); @@ -473,6 +473,57 @@ void StandardCircuitBuilder_::fix_witness(const uint32_t witness_index, cons ++this->num_gates; } +template void StandardCircuitBuilder_::print_boomerang_variables() +{ + std::set var_left; + std::set var_right; + std::set var_out; + std::unordered_set boomerang_idx; + std::set left_right_union; + for (size_t i = 0; i < this->num_gates; i++) { + uint32_t left_idx = blocks.arithmetic.w_l()[i]; + uint32_t right_idx = blocks.arithmetic.w_r()[i]; + uint32_t out_idx = blocks.arithmetic.w_o()[i]; + var_left.insert(left_idx); + var_right.insert(right_idx); + var_out.insert(out_idx); + } + + std::set_union(var_left.begin(), + var_left.end(), + var_right.begin(), + var_right.end(), + std::inserter(left_right_union, left_right_union.begin())); + std::set_difference(left_right_union.begin(), + left_right_union.end(), + var_out.begin(), + var_out.end(), + std::inserter(boomerang_idx, boomerang_idx.begin())); + for (size_t i = 0; i < this->num_gates; i++) { + uint32_t left_idx = blocks.arithmetic.w_l()[i]; + uint32_t right_idx = blocks.arithmetic.w_r()[i]; + if (boomerang_idx.contains(left_idx) && boomerang_idx.contains(right_idx)) { + if (left_idx == right_idx) { + std::cout << "possible boomerang variable with the index " << left_idx + << " is the left and right value for the gate with number " << i << "\n"; + } else { + std::cout << "possible boomerang variable with index " << left_idx + << " is the left value for the gate with number " << i << '\n'; + std::cout << "possible boomerang variable with the index " << right_idx + << " is the right value for the gate with number " << i << "\n"; + } + } + if (boomerang_idx.contains(left_idx) && !boomerang_idx.contains(right_idx)) { + std::cout << "possible boomerang variable with the index" << left_idx + << " is the left value for the gate with number " << i << "\n"; + } + if (!boomerang_idx.contains(left_idx) && boomerang_idx.contains(right_idx)) { + std::cout << "possible boomerang variable with the index" << right_idx + << " is the right value for the gate with number " << i << "\n"; + } + } +} + template uint32_t StandardCircuitBuilder_::put_constant_variable(const FF& variable) { if (constant_variable_indices.contains(variable)) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp index b25fc8d34abc..b0560ce17134 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp @@ -103,6 +103,7 @@ template class StandardCircuitBuilder_ : public CircuitBuilderBase // TODO(#216)(Adrian): The 2 following methods should be virtual in the base class uint32_t put_constant_variable(const FF& variable); + void print_boomerang_variables(); size_t get_num_constant_gates() const override { return 0; } From 86339b2b5eae474ab344b06eb6eab03f7987e990 Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Tue, 13 Aug 2024 17:20:28 +0000 Subject: [PATCH 06/21] forget to return fr(2) in standard_circuit_builder.cpp in the last commit --- barretenberg/barretenberg.code-workspace | 6 +++--- .../stdlib_circuit_builders/standard_circuit_builder.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/barretenberg/barretenberg.code-workspace b/barretenberg/barretenberg.code-workspace index 1b3c9893e815..cd08c7a31666 100644 --- a/barretenberg/barretenberg.code-workspace +++ b/barretenberg/barretenberg.code-workspace @@ -3,9 +3,9 @@ // relative to `.code-workspace`. "folders": [ { - "name": "aztec-packages", - "path": ".." - } + "name": "barretenberg", + "path": "./" + }, ], // List recommended extensions for the whole workspace. "extensions": { diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.cpp index 30c222524223..ecbbe808d8b6 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.cpp @@ -319,7 +319,7 @@ accumulator_triple_ StandardCircuitBuilder_::create_logic_constraint(con uint32_t out_accumulator_idx = this->zero_idx; constexpr FF four = FF(4); constexpr FF neg_two = -FF(2); - // constexpr FF two = FF(2); + constexpr FF two = FF(2); // Num bits is expected to be even ASSERT(num_bits % 2 == 0); From ddf3e98cca05836c8f2ad932b404e809980c13d3 Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Fri, 23 Aug 2024 15:11:04 +0000 Subject: [PATCH 07/21] static analyzer based on graph description for UltraCircuitBuilder. aes and sha256 were testted --- .../boomerang_value_detection/CMakeLists.txt | 2 +- .../boomerang_value_detection/graph.cpp | 419 ++++++----- .../boomerang_value_detection/graph.hpp | 36 +- .../graph_description.test.cpp | 684 ++++++++++++------ .../standard_circuit_builder.test.cpp | 6 +- .../stdlib/primitives/plookup/plookup.cpp | 1 + 6 files changed, 695 insertions(+), 453 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt index b9b2259602ee..4dad5ed7e3d9 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(boomerang_value_detection stdlib_circuit_builders circuit_checker) +barretenberg_module(boomerang_value_detection stdlib_circuit_builders circuit_checker stdlib_primitives numeric stdlib_aes128 stdlib_sha256) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp index cee4ae7c80bb..1d30f12b172c 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -2,49 +2,173 @@ #include #include -template Graph_::Graph_(const bb::StandardCircuitBuilder_& circuit_constructor) +template +std::vector Graph_::get_arithmetic_gate_connected_component( + bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) { - this->variable_adjacency_lists = std::vector>(circuit_constructor.real_variable_index.size()); - this->variables_gate_counts = std::unordered_map(circuit_constructor.real_variable_index.size()); - const auto& block = circuit_constructor.blocks.arithmetic; - auto zero_idx = circuit_constructor.zero_idx; - std::map constant_variable_indices = circuit_constructor.constant_variable_indices; - for (auto key : circuit_constructor.real_variable_index) { - variables_gate_counts[key] = 0; - } - for (size_t i = 0; i < circuit_constructor.num_gates; i++) { - uint32_t left_idx = block.w_l()[i]; - uint32_t right_idx = block.w_r()[i]; - uint32_t out_idx = block.w_o()[i]; - - FF q_m = block.q_m()[i]; - FF q_1 = block.q_1()[i]; - FF q_2 = block.q_2()[i]; - FF q_3 = block.q_3()[i]; - std::set unique_gate_variables; - if ((q_m != FF::zero() || q_1 != FF::zero() || q_2 != FF::zero()) && - q_3 != FF::zero()) // this is not constant gate. we don't need constant variables - { + auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; + auto arithmetic_block = ultra_circuit_builder.blocks.arithmetic; + uint32_t left_idx = arithmetic_block.w_l()[index]; + uint32_t right_idx = arithmetic_block.w_r()[index]; + uint32_t out_idx = arithmetic_block.w_o()[index]; + uint32_t fourth_idx = arithmetic_block.w_4()[index]; + auto q_m = arithmetic_block.q_m()[index]; + auto q_1 = arithmetic_block.q_1()[index]; + auto q_2 = arithmetic_block.q_2()[index]; + auto q_3 = arithmetic_block.q_3()[index]; + auto q_4 = arithmetic_block.q_4()[index]; + std::vector gate_variables; + if (q_m != 0 || q_1 != 1 || q_2 != 0 || q_3 != 0 || q_4 != 0) { + // this is not the gate for fix_witness, so we have to process this gate + if (arithmetic_block.q_arith()[index] > 0) { if (q_m != 0) { - unique_gate_variables.insert(left_idx); - unique_gate_variables.insert(right_idx); + gate_variables.emplace_back(left_idx); + gate_variables.emplace_back(right_idx); } if (q_1 != 0) { - unique_gate_variables.insert(left_idx); + gate_variables.emplace_back(left_idx); } if (q_2 != 0) { - unique_gate_variables.insert(right_idx); + gate_variables.emplace_back(right_idx); } if (q_3 != 0) { - unique_gate_variables.insert(out_idx); + gate_variables.emplace_back(out_idx); + } + if (q_4 != 0) { + gate_variables.emplace_back(fourth_idx); + } + if (arithmetic_block.q_arith()[index] == 1 && q_m == 0) { + } + if (arithmetic_block.q_arith()[index] == 2) { + // We have to use w_4_shift from the next gate + // if and only if the current gate isn't last, cause we can't + // look into the next gate + if (index != arithmetic_block.size() - 1) { + uint32_t fourth_shift_idx = arithmetic_block.w_4()[index + 1]; + gate_variables.emplace_back(fourth_shift_idx); + } + } + if (arithmetic_block.q_arith()[index] == 3) { + info("q_arith == 3 isn't implemented yet"); + } + } + } + auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end()); + gate_variables.erase(unique_variables, gate_variables.end()); + std::transform(gate_variables.cbegin(), gate_variables.cend(), gate_variables.begin(), to_real); + if (!gate_variables.empty()) { + for (const auto& real_variable_index : gate_variables) { + variables_gate_counts[real_variable_index] += 1; + } + } + return gate_variables; +} + +template +std::vector Graph_::get_elliptic_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder, + size_t index) +{ + auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; + auto elliptic_block = ultra_circuit_builder.blocks.elliptic; + std::vector gate_variables; + bool is_elliptic_gate = elliptic_block.q_elliptic()[index] == 1; + bool is_elliptic_add_gate = elliptic_block.q_1()[index] != 0 && elliptic_block.q_m()[index] == 0; + bool is_elliptic_dbl_gate = elliptic_block.q_1()[index] == 0 && elliptic_block.q_m()[index] == 1; + if (is_elliptic_gate) { + auto right_idx = elliptic_block.w_r()[index]; + auto out_idx = elliptic_block.w_o()[index]; + gate_variables.emplace_back(right_idx); + gate_variables.emplace_back(out_idx); + if (index != elliptic_block.size() - 1) { + if (is_elliptic_add_gate) { + // if this gate is ecc_add_gate, we have to get indices x2, x3, y3, y2 from the next gate + gate_variables.emplace_back(elliptic_block.w_l()[index + 1]); + gate_variables.emplace_back(elliptic_block.w_r()[index + 1]); + gate_variables.emplace_back(elliptic_block.w_o()[index + 1]); + gate_variables.emplace_back(elliptic_block.w_4()[index + 1]); } + if (is_elliptic_dbl_gate) { + // if this gate is ecc_dbl_gate, we have to indices x3, y3 from right and output wires + gate_variables.emplace_back(elliptic_block.w_r()[index + 1]); + gate_variables.emplace_back(elliptic_block.w_o()[index + 1]); + } + } + } + auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end()); + gate_variables.erase(unique_variables, gate_variables.end()); + std::transform(gate_variables.cbegin(), gate_variables.cend(), gate_variables.begin(), to_real); + if (!gate_variables.empty()) { + for (const auto& real_variable_index : gate_variables) { + variables_gate_counts[real_variable_index] += 1; } - for (const auto& elem : unique_gate_variables) { - variables_gate_counts[elem] += 1; + } + return gate_variables; +} + +template +std::pair> Graph_::get_sort_constraint_connected_component( + bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) +{ + auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; + auto delta_range_block = ultra_circuit_builder.blocks.delta_range; + std::vector gate_variables; + bool is_dummy_gate = false; + if (delta_range_block.q_delta_range()[index] == 1) { + auto left_idx = delta_range_block.w_l()[index]; + auto right_idx = delta_range_block.w_r()[index]; + auto out_idx = delta_range_block.w_o()[index]; + auto fourth_idx = delta_range_block.w_4()[index]; + gate_variables.insert(gate_variables.end(), { left_idx, right_idx, out_idx, fourth_idx }); + } + auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end()); + gate_variables.erase(unique_variables, gate_variables.end()); + std::transform(gate_variables.cbegin(), gate_variables.cend(), gate_variables.begin(), to_real); + if (!gate_variables.empty()) { + for (const auto& real_variable_index : gate_variables) { + variables_gate_counts[real_variable_index] += 1; } - std::vector gate_variables(unique_gate_variables.begin(), unique_gate_variables.end()); - connect_all_variables_in_vector(gate_variables, zero_idx, constant_variable_indices, false); } + return std::make_pair(is_dummy_gate, gate_variables); +} + +template +std::vector Graph_::get_plookup_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder, + size_t index) +{ + auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; + std::vector variable_indices; + auto& lookup_block = ultra_circuit_builder.blocks.lookup; + auto q_2 = lookup_block.q_2()[index]; + auto q_m = lookup_block.q_m()[index]; + auto q_c = lookup_block.q_c()[index]; + auto left_idx = lookup_block.w_l()[index]; + auto right_idx = lookup_block.w_r()[index]; + auto out_idx = lookup_block.w_o()[index]; + variable_indices.emplace_back(left_idx); + variable_indices.emplace_back(right_idx); + variable_indices.emplace_back(out_idx); + if (index < lookup_block.size() - 1) { + if (q_2 != 0 || q_m != 0 || q_c != 0) { + if (q_2 != 0) { + variable_indices.emplace_back(lookup_block.w_l()[index + 1]); + } + if (q_m != 0) { + variable_indices.emplace_back(lookup_block.w_r()[index + 1]); + } + if (q_c != 0) { + variable_indices.emplace_back(lookup_block.w_o()[index + 1]); + } + } + } + auto unique_variables = std::unique(variable_indices.begin(), variable_indices.end()); + variable_indices.erase(unique_variables, variable_indices.end()); + std::transform(variable_indices.cbegin(), variable_indices.cend(), variable_indices.begin(), to_real); + if (!variable_indices.empty()) { + for (const auto& real_variable_index : variable_indices) { + variables_gate_counts[real_variable_index] += 1; + } + } + return variable_indices; } template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit_constructor) @@ -52,60 +176,22 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit this->variables_gate_counts = std::unordered_map(ultra_circuit_constructor.real_variable_index.size()); this->variable_adjacency_lists = - std::vector>(ultra_circuit_constructor.real_variable_index.size()); - for (const auto& variables_index : ultra_circuit_constructor.real_variable_index) { - variables_gate_counts[variables_index] = 0; + std::unordered_map>(ultra_circuit_constructor.real_variable_index.size()); + this->variables_degree = std::unordered_map(ultra_circuit_constructor.real_variable_index.size()); + for (const auto& variable_index : ultra_circuit_constructor.real_variable_index) { + variables_gate_counts[variable_index] = 0; + variables_degree[variable_index] = 0; + variable_adjacency_lists[variable_index] = {}; } + std::map constant_variable_indices = ultra_circuit_constructor.constant_variable_indices; - uint32_t zero_idx = ultra_circuit_constructor.zero_idx; auto& arithmetic_block = ultra_circuit_constructor.blocks.arithmetic; auto arithmetic_gate_numbers = arithmetic_block.size(); bool arithmetic_gate_exists = arithmetic_gate_numbers > 0; if (arithmetic_gate_exists) { for (size_t i = 0; i < arithmetic_gate_numbers; i++) { - if (arithmetic_block.q_arith()[i] != 0) { - uint32_t left_idx = arithmetic_block.w_l()[i]; - uint32_t right_idx = arithmetic_block.w_r()[i]; - uint32_t out_idx = arithmetic_block.w_o()[i]; - uint32_t fourth_idx = arithmetic_block.w_4()[i]; - FF q_m = arithmetic_block.q_m()[i]; - FF q_1 = arithmetic_block.q_1()[i]; - FF q_2 = arithmetic_block.q_2()[i]; - FF q_3 = arithmetic_block.q_3()[i]; - FF q_c = arithmetic_block.q_c()[i]; - FF q_4 = arithmetic_block.q_4()[i]; - std::set unique_gate_variables; - if (q_m == 0 && q_1 == 1 && q_2 == 0 && q_3 == 0 && q_c != 0 && q_4 == 0) { - info("This is the gate for fixing witness. We can ignore it"); - } else { - if (q_m != 0) { - unique_gate_variables.insert(left_idx); - unique_gate_variables.insert(right_idx); - } - if (q_1 != 0) { - unique_gate_variables.insert(left_idx); - } - if (q_2 != 0) { - unique_gate_variables.insert(right_idx); - } - if (q_3 != 0) { - unique_gate_variables.insert(out_idx); - } - if (q_4 != 0) { - unique_gate_variables.insert(fourth_idx); - } - for (const auto& elem : unique_gate_variables) { - variables_gate_counts[elem] += 1; - } - } - std::vector gate_variables(unique_gate_variables.begin(), unique_gate_variables.end()); - connect_all_variables_in_vector(gate_variables, zero_idx, constant_variable_indices, false); - } else { - // this is the dummy gate for arithmetic gate. From ultra_circuit_builder.cpp I know that it was - // created for sort_constraint with wires(variable_indx, zero_idx, zero_idx, zero_idx), - // so it's need to update number_gate_counts for variable w_l()[i] - variables_gate_counts[arithmetic_block.w_l()[i]] += 1; - } + auto gate_variables = get_arithmetic_gate_connected_component(ultra_circuit_constructor, i); + connect_all_variables_in_vector(ultra_circuit_constructor, gate_variables, false); } } auto& elliptic_block = ultra_circuit_constructor.blocks.elliptic; @@ -113,63 +199,19 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit bool elliptic_gates_exist = elliptic_gate_numbers > 0; if (elliptic_gates_exist) { for (size_t i = 0; i < elliptic_gate_numbers; i++) { - std::vector wire_variables = { - elliptic_block.w_l()[i], elliptic_block.w_r()[i], elliptic_block.w_o()[i], elliptic_block.w_4()[i] - }; - for (const auto& elem : wire_variables) { - if (elem != zero_idx) { - variables_gate_counts[elem] += 1; - } - } - } - for (size_t i = 1; i < elliptic_gate_numbers; i++) { - if (elliptic_block.q_elliptic()[i - 1] == 1) { - // the previous gate was connected with our current gate, cause it has the value "q_elliptic = 0" - std::vector coordinates = { elliptic_block.w_l()[i], elliptic_block.w_r()[i], - elliptic_block.w_o()[i], elliptic_block.w_4()[i], - elliptic_block.w_r()[i - 1], elliptic_block.w_o()[i - 1] }; - - connect_all_variables_in_vector(coordinates, zero_idx, constant_variable_indices, false); - } - // if this condition is not approved, then then the previous was dummy gate, and it wasn't connected with - // out current gate, - // so we have to skip this gate and go to the next gate, cause it can extract variables from the current - // gate + std::vector gate_variables = get_elliptic_gate_connected_component(ultra_circuit_constructor, i); + connect_all_variables_in_vector(ultra_circuit_constructor, gate_variables, false); } } auto& range_block = ultra_circuit_constructor.blocks.delta_range; auto range_gates = range_block.size(); bool range_gates_exists = range_gates > 0; if (range_gates_exists) { - // just go through gates and collect all variables, while we don't meet dummy gate std::vector sorted_variables; for (size_t i = 0; i < range_gates; i++) { - if (range_block.q_delta_range()[i] == 1) { - uint32_t left_idx = range_block.w_l()[i]; - uint32_t right_idx = range_block.w_r()[i]; - uint32_t out_idx = range_block.w_o()[i]; - uint32_t fourth_idx = range_block.w_4()[i]; - sorted_variables.emplace_back(left_idx); - sorted_variables.emplace_back(right_idx); - sorted_variables.emplace_back(out_idx); - sorted_variables.emplace_back(fourth_idx); - } else { - // we go to the dummy gate, there's a shift of the variable from the previous gate and - // we have to update variable_gate_counts on 2 for this variable - // after processing the dummy gate we have to clean sorted_variables_vector - auto sorted_variables_size = sorted_variables.size(); - for (size_t i = 0; i < sorted_variables_size; i++) { - if (sorted_variables[i] != zero_idx) { - if (i == sorted_variables_size - 1) { - variables_gate_counts[sorted_variables[i]] += 2; - } else { - variables_gate_counts[sorted_variables[i]] += 1; - } - } - } - connect_all_variables_in_vector(sorted_variables, zero_idx, constant_variable_indices, true); - sorted_variables.clear(); - } + std::pair> current_gate = + get_sort_constraint_connected_component(ultra_circuit_constructor, i); + sorted_variables.insert(sorted_variables.end(), current_gate.second.begin(), current_gate.second.end()); } } @@ -177,50 +219,23 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit auto lookup_gates = lookup_block.size(); bool lookup_gates_exists = lookup_gates > 0; if (lookup_gates_exists) { - std::vector left_indexes; - std::vector right_indexes; - std::vector out_indexes; for (size_t i = 0; i < lookup_gates; i++) { - if (lookup_block.q_lookup_type()[i] == FF(1)) { - uint32_t left_idx = lookup_block.w_l()[i]; - uint32_t right_idx = lookup_block.w_r()[i]; - uint32_t out_idx = lookup_block.w_o()[i]; - left_indexes.emplace_back(left_idx); - right_indexes.emplace_back(right_idx); - out_indexes.emplace_back(out_idx); - std::vector current_gate_variables = { left_idx, right_idx, out_idx }; - for (const auto& variable : current_gate_variables) { - variables_gate_counts[variable] += 1; - } - connect_all_variables_in_vector(current_gate_variables, zero_idx, constant_variable_indices, false); - auto q_2 = lookup_block.q_2()[i]; - auto q_m = lookup_block.q_m()[i]; - auto q_c = lookup_block.q_c()[i]; - if (q_2 == 0 && q_m == 0 && q_c == 0) { - // this is the last gate in the in this blocks of lookup, so we can connect variables from - // left_indexes vectors, right_indexes vector, out_indexes vector - connect_all_variables_in_vector(left_indexes, zero_idx, constant_variable_indices, false); - connect_all_variables_in_vector(right_indexes, zero_idx, constant_variable_indices, false); - connect_all_variables_in_vector(out_indexes, zero_idx, constant_variable_indices, false); - // now we can erase all these vector to begin with new lookup accumulators - left_indexes.clear(); - right_indexes.clear(); - out_indexes.clear(); - } - } + std::vector variable_indices = get_plookup_gate_connected_component(ultra_circuit_constructor, i); + connect_all_variables_in_vector(ultra_circuit_constructor, variable_indices, false); } } } template -bool Graph_::check_is_not_constant_variable(const uint32_t& variable_index, - const std::map& constant_variable_indices) +bool Graph_::check_is_not_constant_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, + const uint32_t& variable_index) { // this method checks that variable is not constant, so it's not in constant_variable_indices from ultra circuit // builder bool is_not_constant = true; + auto constant_variable_indices = ultra_circuit_builder.constant_variable_indices; for (const auto& pair : constant_variable_indices) { - if (pair.second == variable_index) { + if (pair.second == ultra_circuit_builder.real_variable_index[variable_index]) { is_not_constant = false; break; } @@ -229,9 +244,8 @@ bool Graph_::check_is_not_constant_variable(const uint32_t& variable_index, } template -void Graph_::connect_all_variables_in_vector(const std::vector& variables_vector, - const uint32_t& zero_idx, - const std::map& constant_variable_indices, +void Graph_::connect_all_variables_in_vector(bb::UltraCircuitBuilder& ultra_circuit_builder, + const std::vector& variables_vector, bool is_sorted_variables) { // this method connects between each other variables that have different indexes, their indexes are not equal @@ -240,13 +254,14 @@ void Graph_::connect_all_variables_in_vector(const std::vector& va if (!variables_vector.empty()) { if (is_sorted_variables) { for (size_t i = 0; i < variables_vector.size() - 1; i++) { - if (variables_vector[i] != zero_idx && variables_vector[i + 1] != zero_idx && + if (variables_vector[i] != ultra_circuit_builder.zero_idx && + variables_vector[i + 1] != ultra_circuit_builder.zero_idx && variables_vector[i] != variables_vector[i + 1]) { { bool first_variable_is_not_constant = - check_is_not_constant_variable(variables_vector[i], constant_variable_indices); + check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i]); bool second_variable_is_not_constant = - check_is_not_constant_variable(variables_vector[i + 1], constant_variable_indices); + check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i + 1]); if (first_variable_is_not_constant && second_variable_is_not_constant) { add_new_edge(variables_vector[i], variables_vector[i + 1]); } @@ -256,12 +271,14 @@ void Graph_::connect_all_variables_in_vector(const std::vector& va } else { for (size_t i = 0; i < variables_vector.size() - 1; i++) { for (size_t j = 1; j < variables_vector.size(); j++) { - if (variables_vector[i] != zero_idx && variables_vector[j] != zero_idx && + if (variables_vector[i] != ultra_circuit_builder.zero_idx && + variables_vector[j] != ultra_circuit_builder.zero_idx && variables_vector[i] != variables_vector[j]) { + bool first_variable_is_not_constant = - check_is_not_constant_variable(variables_vector[i], constant_variable_indices); + check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i]); bool second_variable_is_not_constant = - check_is_not_constant_variable(variables_vector[j], constant_variable_indices); + check_is_not_constant_variable(ultra_circuit_builder, variables_vector[j]); if (first_variable_is_not_constant && second_variable_is_not_constant) { add_new_edge(variables_vector[i], variables_vector[j]); } @@ -275,26 +292,23 @@ void Graph_::connect_all_variables_in_vector(const std::vector& va template void Graph_::add_new_edge(const uint32_t& first_variable_index, const uint32_t& second_variable_index) { - if (first_variable_index != second_variable_index) { - this->variable_adjacency_lists[first_variable_index].insert(second_variable_index); - this->variable_adjacency_lists[second_variable_index].insert(first_variable_index); - } + variable_adjacency_lists[first_variable_index].emplace_back(second_variable_index); + variable_adjacency_lists[second_variable_index].emplace_back(first_variable_index); + variables_degree[first_variable_index] += 1; + variables_degree[second_variable_index] += 1; } -template std::set Graph_::get_variable_adjacency_list(const uint32_t& variable_index) +template std::vector Graph_::get_variable_adjacency_list(const uint32_t& variable_index) { - if (variable_index >= (this->variable_adjacency_lists).size()) { - throw std::out_of_range("Variable index out of bounds"); - } return variable_adjacency_lists[variable_index]; } template void Graph_::depth_first_search(const uint32_t& variable_index, std::vector& is_used, - std::set& connected_component) + std::vector& connected_component) { - // this method realizes algorith depth_first_search for undirected graph using the give variable + // this method realizes algorithm depth_first_search for undirected graph using the give variable std::stack variable_stack; variable_stack.push(variable_index); while (!variable_stack.empty()) { @@ -302,7 +316,7 @@ void Graph_::depth_first_search(const uint32_t& variable_index, variable_stack.pop(); if (std::find(is_used.begin(), is_used.end(), current_index) == is_used.end()) { is_used.emplace_back(current_index); - connected_component.insert(current_index); + connected_component.emplace_back(current_index); for (const auto& it : variable_adjacency_lists[current_index]) { variable_stack.push(it); } @@ -310,17 +324,19 @@ void Graph_::depth_first_search(const uint32_t& variable_index, } } -template std::vector> Graph_::find_connected_components() +template std::vector> Graph_::find_connected_components() { // this methond finds connected components from the graph described by adjacency lists std::vector is_used; - std::vector> connected_components; - for (size_t i = 2; i < variable_adjacency_lists.size(); i++) { - auto var_index = static_cast(i); - if (std::find(is_used.begin(), is_used.end(), var_index) == is_used.end()) { - std::set connected_component; - depth_first_search(var_index, is_used, connected_component); - connected_components.emplace_back(connected_component); + std::vector> connected_components; + for (const auto& pair : variable_adjacency_lists) { + if (pair.first != 0 && variables_degree[pair.first] > 0) { + if (std::find(is_used.begin(), is_used.end(), pair.first) == is_used.end()) { + std::vector connected_component; + depth_first_search(pair.first, is_used, connected_component); + std::sort(connected_component.begin(), connected_component.end()); + connected_components.emplace_back(connected_component); + } } } return connected_components; @@ -341,14 +357,13 @@ template std::vector Graph_::find_dangerous_variable template void Graph_::print_graph() { - for (size_t i = 2; i < this->variable_adjacency_lists.size(); i++) { - info("variable with index ", i); - if (this->variable_adjacency_lists[i].size() == 0) { + for (const auto& elem : variable_adjacency_lists) { + info("variable with index", elem.first); + if (variable_adjacency_lists[elem.first].empty()) { info("is isolated"); } else { - for (auto it = this->variable_adjacency_lists[i].begin(); it != this->variable_adjacency_lists[i].end(); - ++it) { - info(*it, " "); + for (const auto& it : elem.second) { + info(it); } } } @@ -358,7 +373,7 @@ template void Graph_::print_connected_components() { auto connected_components = find_connected_components(); for (size_t i = 0; i < connected_components.size(); i++) { - info("printing the ", i, " connected component:"); + info("printing the ", i + 1, " connected component:"); for (const auto& it : connected_components[i]) { info(it, " "); } @@ -386,10 +401,20 @@ void Graph_::print_dangerous_variables(const bb::StandardCircuitBuilder_ template void Graph_::print_variables_gate_counts() { - for (auto& it : variables_gate_counts) { - info("number of gates with variables ", it.first); + for (const auto& it : variables_gate_counts) { + info("number of gates with variables ", it.first, " == ", it.second); info(it.second); } } +template void Graph_::print_variables_edge_counts() +{ + for (const auto& it : variables_degree) { + if (it.first != 0) { + info("variable index = ", it.first); + info("number of edges for this variables = ", it.second); + } + } +} + template class Graph_; \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp index 668f589d0320..2535773e965b 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include template class Graph_ { @@ -16,39 +17,46 @@ template class Graph_ { Graph_(const bb::StandardCircuitBuilder_& circuit_constructor); Graph_(bb::UltraCircuitBuilder& ultra_circuit_constructor); - bool is_variable_exist(const uint32_t& variable_index); + std::unordered_map get_variables_gate_counts() { return this->variables_gate_counts; }; + + std::vector get_arithmetic_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder, + size_t index); + std::vector get_elliptic_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder, + size_t index); + std::vector get_plookup_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder, + size_t index); + std::pair> get_sort_constraint_connected_component( + bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index); + void add_new_edge(const uint32_t& first_variable_index, const uint32_t& second_variable_index); + std::vector get_variable_adjacency_list(const uint32_t& variable_index); - std::set get_variable_adjacency_list(const uint32_t& variable_index); void depth_first_search(const uint32_t& variable_index, std::vector& is_used, - std::set& connected_component); - std::vector> find_connected_components(); + std::vector& connected_component); + std::vector> find_connected_components(); std::vector find_dangerous_variables(); - std::unordered_map get_variables_gate_counts() { return this->variables_gate_counts; }; + size_t get_distance_between_variables(const uint32_t& first_variable_index, const uint32_t& second_variable_index); bool check_vertex_in_connected_component(const std::vector& connected_component, const uint32_t& var_index); - void update_edges_for_sorted_variables(const std::vector& sorted_variables, - const std::map& constant_variable_indices, - const uint32_t& zero_idx); - void connect_all_variables_in_vector(const std::vector& variables_vector, - const uint32_t& zero_idx, - const std::map& constant_variable_indices, + void connect_all_variables_in_vector(bb::UltraCircuitBuilder& ultra_circuit_builder, + const std::vector& variables_vector, bool is_sorted_variables); - bool check_is_not_constant_variable(const uint32_t& variable_index, - const std::map& constant_variables_indices); + bool check_is_not_constant_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, const uint32_t& variable_index); void print_graph(); void print_connected_components(); void print_variables_gate_counts(); void print_dangerous_variables(const bb::StandardCircuitBuilder_& circuit_constructor); + void print_variables_edge_counts(); ~Graph_() = default; private: - std::vector> variable_adjacency_lists; + std::unordered_map> variable_adjacency_lists; std::unordered_map variables_gate_counts; + std::unordered_map variables_degree; }; using Graph = Graph_; \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp index a0c9ce9bd781..52a090d5c96f 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp @@ -1,7 +1,9 @@ #include "barretenberg/boomerang_value_detection/graph.hpp" #include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/crypto/aes128/aes128.hpp" #include "barretenberg/crypto/generators/generator_data.hpp" #include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" +#include "barretenberg/stdlib/encryption/aes128/aes128.hpp" #include "barretenberg/stdlib_circuit_builders/mock_circuits.hpp" #include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" #include "barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp" @@ -11,211 +13,38 @@ using namespace bb; -TEST(standard_circuit_constructor, test_empty_graph) -{ - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::one(); - circuit_constructor.add_public_variable(a); - Graph graph = Graph(circuit_constructor); - - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); -} - -TEST(standard_circuit_constructor, test_graph_with_three_vertexes) -{ - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::random_element(); - fr b = fr::random_element(); - fr c = a + b; - uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - Graph graph = Graph(circuit_constructor); - graph.print_graph(); -} - -TEST(standard_circuit_constructor, test_graph_with_two_gates) -{ - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::random_element(); - fr b = fr::random_element(); - fr c = fr::random_element(); - fr d = a + b; - - uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - uint32_t d_idx = circuit_constructor.add_variable(d); - circuit_constructor.create_add_gate({ a_idx, b_idx, d_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - fr g = c * d; - uint32_t g_idx = circuit_constructor.add_variable(g); - circuit_constructor.create_mul_gate({ c_idx, d_idx, g_idx, fr::one(), fr::neg_one(), fr::zero() }); - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - Graph graph = Graph(circuit_constructor); - graph.print_graph(); -} - -TEST(standard_circuit_constructor, test_graph_with_boomerang_variable) -{ - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::random_element(); - uint32_t a_idx = circuit_constructor.add_public_variable(a); - fr b = fr::random_element(); - fr c = a + b; - fr d = fr::random_element(); - fr e = d + a; // - // uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - uint32_t d_idx = circuit_constructor.add_variable(d); - uint32_t e_idx = circuit_constructor.add_variable(e); - uint32_t a_duplicate_idx = circuit_constructor.add_variable(a); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate( - { a_duplicate_idx, d_idx, e_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - - bool result = CircuitChecker::check(circuit_constructor); - bool result1 = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - EXPECT_EQ(result1, true); - Graph graph = Graph(circuit_constructor); - graph.print_graph(); -} - -TEST(standard_circuit_constructor, test_graph_connected_components) -{ - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::random_element(); - fr b = fr::random_element(); - fr c = a + b; - uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - Graph graph = Graph(circuit_constructor); - graph.print_graph(); - graph.print_connected_components(); -} - -TEST(standard_circuit_constructor, test_graph_with_two_connected_components) +TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates) { - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::random_element(); - uint32_t a_idx = circuit_constructor.add_public_variable(a); - fr b = fr::random_element(); - fr c = a + b; - fr d = fr::random_element(); - fr e = d + a; // - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - uint32_t d_idx = circuit_constructor.add_variable(d); - uint32_t e_idx = circuit_constructor.add_variable(e); - uint32_t a_duplicate_idx = circuit_constructor.add_variable(a); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate( - { a_duplicate_idx, d_idx, e_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - - bool result = CircuitChecker::check(circuit_constructor); - bool result1 = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - EXPECT_EQ(result1, true); - Graph graph = Graph(circuit_constructor); - graph.print_connected_components(); -} + // this test checks graph description for the circuit with arithmetic gates + // the number of connected components = the number of pair (i, j), 0<=i, j <16, i.e 256 + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); -TEST(standard_circuit_builder, test_graph_connected_component_boomerang_variable) -{ - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::random_element(); - fr b = fr::random_element(); - fr c = a + b; - uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - fr d = fr::random_element(); - fr e = fr::random_element(); - fr f = d + e; - uint32_t d_idx = circuit_constructor.add_variable(d); - uint32_t e_idx = circuit_constructor.add_variable(e); - uint32_t f_idx = circuit_constructor.add_variable(f); - circuit_constructor.create_add_gate({ d_idx, e_idx, f_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - fr g = c * f; - fr g1 = c + f; - uint32_t g_idx = circuit_constructor.add_variable(g); - uint32_t g1_idx = circuit_constructor.add_variable(g1); - circuit_constructor.create_mul_gate({ c_idx, f_idx, g_idx, fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ c_idx, f_idx, g1_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - fr g_dupl = circuit_constructor.get_variable(g_idx); - fr g_inv = g_dupl.invert(); - fr g_2 = g_inv + g1; - uint32_t g_inv_idx = circuit_constructor.add_variable(g_inv); - uint32_t g2_idx = circuit_constructor.add_variable(g_2); - circuit_constructor.create_add_gate({ g_inv_idx, g1_idx, g2_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - Graph graph = Graph(circuit_constructor); - graph.print_connected_components(); -} + for (size_t i = 0; i < 16; ++i) { + for (size_t j = 0; j < 16; ++j) { + uint64_t left = static_cast(j); + uint64_t right = static_cast(i); + uint32_t left_idx = circuit_constructor.add_variable(fr(left)); + uint32_t right_idx = circuit_constructor.add_variable(fr(right)); + uint32_t result_idx = circuit_constructor.add_variable(fr(left ^ right)); -TEST(standard_circuit_constructor, test_graph_for_logic_constraint) -{ - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr(1); - fr b = fr(2); - uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - size_t num_bits = 2; - auto accumulators = circuit_constructor.create_logic_constraint(a_idx, b_idx, num_bits, true); - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - Graph graph = Graph(circuit_constructor); - graph.print_connected_components(); -} + uint32_t add_idx = + circuit_constructor.add_variable(fr(left) + fr(right) + circuit_constructor.get_variable(result_idx)); + circuit_constructor.create_big_add_gate( + { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); + } + } -TEST(standard_circuit_constructor, test_logic_constraint_degree_one) -{ - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr(1); - fr b = fr(2); - uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - size_t num_bits = 2; - auto accumulators = circuit_constructor.create_logic_constraint(a_idx, b_idx, num_bits, true); - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); Graph graph = Graph(circuit_constructor); - graph.print_dangerous_variables(circuit_constructor); -} - -TEST(standard_circuit_constructor, test_logic_constraint_also_degree_two) -{ - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr(1); - fr b = fr(2); - uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - size_t num_bits = 2; - auto accumulators = circuit_constructor.create_logic_constraint(a_idx, b_idx, num_bits, true); - bool result = CircuitChecker::check(circuit_constructor); + auto connected_components = graph.find_connected_components(); + auto num_connected_components = connected_components.size(); + info("number of connected components == ", num_connected_components); + bool result = num_connected_components == 256; EXPECT_EQ(result, true); - Graph graph = Graph(circuit_constructor); - graph.print_dangerous_variables(circuit_constructor); } -TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates) +TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates_with_shifts) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); - for (size_t i = 0; i < 16; ++i) { for (size_t j = 0; j < 16; ++j) { uint64_t left = static_cast(j); @@ -227,19 +56,24 @@ TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates) uint32_t add_idx = circuit_constructor.add_variable(fr(left) + fr(right) + circuit_constructor.get_variable(result_idx)); circuit_constructor.create_big_add_gate( - { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); + { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }, true); } } - bool result = CircuitChecker::check(circuit_constructor); Graph graph = Graph(circuit_constructor); - // graph.print_graph(); - graph.print_connected_components(); + auto connected_components = graph.find_connected_components(); + auto num_connected_components = connected_components.size(); + info("number of the connected components == ", num_connected_components); + bool result = num_connected_components == 1; EXPECT_EQ(result, true); + graph.print_connected_components(); } -TEST(ultra_circuit_constructor, test_graph_for_bool_gates) +TEST(ultra_circuit_constructor, test_graph_for_boolean_gates) { + // this test checks graph description for the circuit with boolean gates. + // all variables must be isolated and the number of connected components = 20 + // number of the variables in the circuit UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); for (size_t i = 0; i < 20; ++i) { @@ -248,15 +82,20 @@ TEST(ultra_circuit_constructor, test_graph_for_bool_gates) circuit_constructor.create_bool_gate(a_idx); } - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); Graph graph = Graph(circuit_constructor); - graph.print_graph(); + auto connected_components = graph.find_connected_components(); + auto num_connected_components = connected_components.size(); + info("number of the connected components == ", num_connected_components); + bool result = num_connected_components == 20; + EXPECT_EQ(result, true); graph.print_connected_components(); } TEST(ultra_circuit_constructor, test_graph_for_elliptic_add_gate) { + // this test checks graph decription for the circuit with one elliptic addition gate. + // The result is one connected component for 6 variables: + // x1, y1, x2, y2, x3, y3 typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -275,15 +114,19 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_add_gate) circuit_constructor.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, 1 }); - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); Graph graph = Graph(circuit_constructor); + auto connected_components = graph.find_connected_components(); + auto num_connected_components = connected_components.size(); + bool result = num_connected_components == 1; + EXPECT_EQ(result, true); graph.print_connected_components(); - graph.print_variables_gate_counts(); } -TEST(ultra_circuit_constructor, test_for_elliptic_double_gate) +TEST(ultra_circuit_constructor, test_graph_for_elliptic_double_gate) { + // this test checks graph description for the circuit with one elliptic double gate. + // The result is one connected component for 4 variables: + // x1, y1, x3, y3 typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -295,20 +138,24 @@ TEST(ultra_circuit_constructor, test_for_elliptic_double_gate) uint32_t y1 = circuit_constructor.add_variable(p1.y); uint32_t x3 = circuit_constructor.add_variable(p3.x); uint32_t y3 = circuit_constructor.add_variable(p3.y); - info("x1, y1, x3, y3 == ", x1, " ", y1, " ", x3, " ", y3); + info("string from the test: x1, y1, x3, y3 == ", x1, " ", y1, " ", x3, " ", y3); circuit_constructor.create_ecc_dbl_gate({ x1, y1, x3, y3 }); - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - Graph graph = Graph(circuit_constructor); + auto connected_components = graph.find_connected_components(); + auto num_connected_components = connected_components.size(); + bool result = num_connected_components == 1; + EXPECT_EQ(result, true); graph.print_connected_components(); - graph.print_variables_gate_counts(); } -TEST(ultra_circuit_constructor, test_graph_for_elliptic_gates_with_arithmetic_gates) +TEST(ultra_circuit_constructor, test_graph_for_elliptic_together) { + // this test checks the graph description for the circuit has elliptic addition and multiplication + // gates together. The result is 2 connected components: + // x1, y1, x2, y2, x3, y3, x4, y4 + // x5, y5, x6, y6, x7, y7, x8, y8 UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); typedef grumpkin::g1::affine_element affine_element; @@ -330,8 +177,6 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_gates_with_arithmetic_ga uint32_t x4 = circuit_constructor.add_variable(p4.x); uint32_t y4 = circuit_constructor.add_variable(p4.y); circuit_constructor.create_ecc_dbl_gate({ x3, y3, x4, y4 }); - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); affine_element p5 = crypto::pedersen_commitment::commit_native({ bb::fr(2) }, 1); affine_element p6 = crypto::pedersen_commitment::commit_native({ bb::fr(3) }, 1); @@ -352,13 +197,19 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_gates_with_arithmetic_ga info("number of elliptic gates = ", circuit_constructor.blocks.elliptic.size()); Graph graph = Graph(circuit_constructor); - graph.print_graph(); - graph.print_connected_components(); - graph.print_variables_gate_counts(); + auto connected_components = graph.find_connected_components(); + info("size of the first connected component == ", connected_components[0].size()); + info("size of the second connected component == ", connected_components[1].size()); + auto num_connected_components = connected_components.size(); + bool result = num_connected_components == 2; + EXPECT_EQ(result, true); } -TEST(ultra_circuit_constructor, test_graph_with_sort_constraints) +TEST(ultra_circuit_constructor, test_graph_for_sort_constraints) { + // this test check graph description for the circuit with 2 sort_constraint. The result is 2 connected components: + // a_idx, b_idx, c_idx, d_idx + // e_idx, f_idx, g_idx, h_idx UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); fr a = fr::one(); fr b = fr(2); @@ -381,17 +232,22 @@ TEST(ultra_circuit_constructor, test_graph_with_sort_constraints) auto h_idx = circuit_constructor.add_variable(h); circuit_constructor.create_sort_constraint({ e_idx, f_idx, g_idx, h_idx }); - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - Graph graph = Graph(circuit_constructor); - graph.print_graph(); - graph.print_connected_components(); - graph.print_variables_gate_counts(); + auto connected_components = graph.find_connected_components(); + info("size of the first connected component == ", connected_components[0].size()); + info("size of the second connected component == ", connected_components[1].size()); + auto num_connected_components = connected_components.size(); + bool result = num_connected_components == 2; + EXPECT_EQ(result, true); + // graph.print_connected_components(); } -TEST(ultra_circuit_constructor, test_graph_with_sort_constraints_with_edges) +TEST(ultra_circuit_constructor, test_graph_for_sort_constraints_with_edges) { + // this test checks graph description for the circuit with 2 sorted_constraints with edges. + // The result is 2 connected components: + // a_idx, b_idx, ... , h_idx + // a1_idx, b1_idx, ..., h1_idx fr a = fr::one(); fr b = fr(2); fr c = fr(3); @@ -433,24 +289,23 @@ TEST(ultra_circuit_constructor, test_graph_with_sort_constraints_with_edges) circuit_constructor.create_sort_constraint_with_edges( { a1_idx, b1_idx, c1_idx, d1_idx, e1_idx, f1_idx, g1_idx, h1_idx }, a1, h1); - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); Graph graph = Graph(circuit_constructor); - - graph.print_graph(); + auto connected_components = graph.find_connected_components(); + auto num_connected_components = connected_components.size(); + bool result = num_connected_components == 2; + EXPECT_EQ(result, true); graph.print_connected_components(); - graph.print_variables_gate_counts(); } -TEST(ultra_circuit_constructor, create_gates_from_plookup_accumulators) +TEST(ultra_circuit_constructor, test_graph_with_plookup_accumulators) { - + // this test checks graph decription for circuit with grate that were created from plookup accumulators + // the result is one connected component UltraCircuitBuilder circuit_builder = UltraCircuitBuilder(); fr input_value = fr::random_element(); - const fr input_lo = static_cast(input_value) - .slice(0, plookup::fixed_base::table::BITS_PER_LO_SCALAR); // обрезал последние 128 бит - const auto input_lo_index = circuit_builder.add_variable(input_lo); // добавил получившееся значение в схему + const fr input_lo = static_cast(input_value).slice(0, plookup::fixed_base::table::BITS_PER_LO_SCALAR); + const auto input_lo_index = circuit_builder.add_variable(input_lo); const auto sequence_data_lo = plookup::get_lookup_accumulators(plookup::MultiTableId::FIXED_BASE_LEFT_LO, input_lo); @@ -461,8 +316,361 @@ TEST(ultra_circuit_constructor, create_gates_from_plookup_accumulators) EXPECT_EQ(num_lookups, lookup_witnesses[plookup::ColumnIdx::C1].size()); - bool result = CircuitChecker::check(circuit_builder); - EXPECT_EQ(result, true); Graph graph = Graph(circuit_builder); + auto connected_components = graph.find_connected_components(); + auto num_connected_components = connected_components.size(); + bool result = num_connected_components == 1; + EXPECT_EQ(result, true); + graph.print_connected_components(); +} + +TEST(ultra_circuit_constructor, test_graph_for_aes_64_bytes) +{ + typedef stdlib::field_t field_pt; + typedef stdlib::witness_t witness_pt; + + uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; + uint8_t out[64]{ 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, + 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, + 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 }; + uint8_t iv[16]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; + uint8_t in[64]{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; + + const auto convert_bytes = [](uint8_t* data) { + uint256_t converted(0); + for (uint64_t i = 0; i < 16; ++i) { + uint256_t to_add = uint256_t((uint64_t)(data[i])) << uint256_t((15 - i) * 8); + converted += to_add; + } + return converted; + }; + + auto builder = UltraCircuitBuilder(); + + std::vector in_field{ + witness_pt(&builder, fr(convert_bytes(in))), + witness_pt(&builder, fr(convert_bytes(in + 16))), + witness_pt(&builder, fr(convert_bytes(in + 32))), + witness_pt(&builder, fr(convert_bytes(in + 48))), + }; + + field_pt key_field(witness_pt(&builder, fr(convert_bytes(key)))); + field_pt iv_field(witness_pt(&builder, fr(convert_bytes(iv)))); + + std::vector expected{ + convert_bytes(out), convert_bytes(out + 16), convert_bytes(out + 32), convert_bytes(out + 48) + }; + + const auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field); + + for (size_t i = 0; i < 4; ++i) { + EXPECT_EQ(result[i].get_value(), expected[i]); + } + + Graph graph = Graph(builder); + auto connected_components = graph.find_connected_components(); + auto num_connected_components = connected_components.size(); + bool graph_result = num_connected_components == 1; + EXPECT_EQ(graph_result, true); + std::cout << "num gates = " << builder.get_num_gates() << std::endl; + std::cout << "number of arithmetic gates = " << builder.blocks.arithmetic.size() << std::endl; + std::cout << "number of sorted gates = " << builder.blocks.delta_range.size() << std::endl; + std::cout << "number of plookup gates = " << builder.blocks.lookup.size() << std::endl; + std::cout << "number of elliptic gates = " << builder.blocks.elliptic.size() << std::endl; +} + +TEST(ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + + for (size_t i = 0; i < 25; ++i) { + for (size_t j = 0; j < 25; ++j) { + uint64_t left = static_cast(j); + uint64_t right = static_cast(i); + uint32_t left_idx = circuit_constructor.add_variable(fr(left)); + uint32_t right_idx = circuit_constructor.add_variable(fr(right)); + uint32_t result_idx = circuit_constructor.add_variable(fr(left ^ right)); + + uint32_t add_idx = + circuit_constructor.add_variable(fr(left) + fr(right) + circuit_constructor.get_variable(result_idx)); + circuit_constructor.create_big_add_gate( + { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); + } + } + + Graph graph = Graph(circuit_constructor); + auto variables_gate_counts = graph.get_variables_gate_counts(); + bool result = true; + for (const auto pair : variables_gate_counts) { + result = result && (pair.first > 0 ? (pair.second == 1) : (pair.second == 0)); + } + EXPECT_EQ(result, true); +} + +TEST(ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate_with_shifts) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + + for (size_t i = 0; i < 25; ++i) { + for (size_t j = 0; j < 25; ++j) { + uint64_t left = static_cast(j); + uint64_t right = static_cast(i); + uint32_t left_idx = circuit_constructor.add_variable(fr(left)); + uint32_t right_idx = circuit_constructor.add_variable(fr(right)); + uint32_t result_idx = circuit_constructor.add_variable(fr(left ^ right)); + + uint32_t add_idx = + circuit_constructor.add_variable(fr(left) + fr(right) + circuit_constructor.get_variable(result_idx)); + circuit_constructor.create_big_add_gate( + { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }, true); + } + } + + Graph graph = Graph(circuit_constructor); + bool result = true; + auto variables_gate_counts = graph.get_variables_gate_counts(); + for (const auto& pair : variables_gate_counts) { + if (pair.first > 0) { + result = result && (pair.first % 4 == 0 && pair.first != 4 ? (pair.second == 2) : (pair.second == 1)); + } else { + result = result && (pair.second == 0); + } + } + EXPECT_EQ(result, true); +} + +TEST(ultra_circuit_constructor, test_variables_gates_counts_for_boolean_gates) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + + for (size_t i = 0; i < 20; ++i) { + fr a = fr::zero(); + uint32_t a_idx = circuit_constructor.add_variable(a); + circuit_constructor.create_bool_gate(a_idx); + } + + Graph graph = Graph(circuit_constructor); + auto variables_gate_counts = graph.get_variables_gate_counts(); + bool result = true; + for (const auto& part : variables_gate_counts) { + info(part.first, " ", part.second); + result = result && (part.first == 0 ? (part.second == 0) : (part.first == 1)); + } + // EXPECT_EQ(result, true); +} + +TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constraints) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + fr a = fr::one(); + fr b = fr(2); + fr c = fr(3); + fr d = fr(4); + + auto a_idx = circuit_constructor.add_variable(a); + auto b_idx = circuit_constructor.add_variable(b); + auto c_idx = circuit_constructor.add_variable(c); + auto d_idx = circuit_constructor.add_variable(d); + circuit_constructor.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); + + fr e = fr(5); + fr f = fr(6); + fr g = fr(7); + fr h = fr(8); + auto e_idx = circuit_constructor.add_variable(e); + auto f_idx = circuit_constructor.add_variable(f); + auto g_idx = circuit_constructor.add_variable(g); + auto h_idx = circuit_constructor.add_variable(h); + circuit_constructor.create_sort_constraint({ e_idx, f_idx, g_idx, h_idx }); + + Graph graph = Graph(circuit_constructor); + auto variables_gate_counts = graph.get_variables_gate_counts(); + auto connected_components = graph.find_connected_components(); + bool result = true; + for (size_t i = 0; i < connected_components[0].size(); i++) { + result = result && + (i == connected_components[0].size() - 1 ? variables_gate_counts[connected_components[0][i]] == 2 + : variables_gate_counts[connected_components[0][i]] == 1); + /* info("result == ", result); + info(i, " ", connected_components[0][i], " ", variables_gate_counts[connected_components[0][i]]); */ + } + + for (size_t i = 0; i < connected_components[1].size(); i++) { + result = result && + (i == connected_components[1].size() - 1 ? variables_gate_counts[connected_components[1][i]] == 2 + : variables_gate_counts[connected_components[1][i]] == 1); + /* info("result == ", result); + info(i, " ", connected_components[1][i], " ", variables_gate_counts[connected_components[1][i]]); */ + } + for (const auto& pair : variables_gate_counts) { + info(pair.first, " ", pair.second); + } + EXPECT_EQ(result, true); +} + +TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constraints_with_edges) +{ + fr a = fr::one(); + fr b = fr(2); + fr c = fr(3); + fr d = fr(4); + fr e = fr(5); + fr f = fr(6); + fr g = fr(7); + fr h = fr(8); + + UltraCircuitBuilder circuit_constructor; + auto a_idx = circuit_constructor.add_variable(a); + auto b_idx = circuit_constructor.add_variable(b); + auto c_idx = circuit_constructor.add_variable(c); + auto d_idx = circuit_constructor.add_variable(d); + auto e_idx = circuit_constructor.add_variable(e); + auto f_idx = circuit_constructor.add_variable(f); + auto g_idx = circuit_constructor.add_variable(g); + auto h_idx = circuit_constructor.add_variable(h); + circuit_constructor.create_sort_constraint_with_edges( + { a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, a, h); + + fr a1 = fr(9); + fr b1 = fr(10); + fr c1 = fr(11); + fr d1 = fr(12); + fr e1 = fr(13); + fr f1 = fr(14); + fr g1 = fr(15); + fr h1 = fr(16); + + auto a1_idx = circuit_constructor.add_variable(a1); + auto b1_idx = circuit_constructor.add_variable(b1); + auto c1_idx = circuit_constructor.add_variable(c1); + auto d1_idx = circuit_constructor.add_variable(d1); + auto e1_idx = circuit_constructor.add_variable(e1); + auto f1_idx = circuit_constructor.add_variable(f1); + auto g1_idx = circuit_constructor.add_variable(g1); + auto h1_idx = circuit_constructor.add_variable(h1); + + circuit_constructor.create_sort_constraint_with_edges( + { a1_idx, b1_idx, c1_idx, d1_idx, e1_idx, f1_idx, g1_idx, h1_idx }, a1, h1); + Graph graph = Graph(circuit_constructor); + auto connected_components = graph.find_connected_components(); + auto variables_gate_counts = graph.get_variables_gate_counts(); + // graph.print_connected_components(); + bool result = true; + for (size_t i = 0; i < connected_components[0].size(); i++) { + result = result && + (i == connected_components[0].size() - 1 ? variables_gate_counts[connected_components[0][i]] == 2 + : variables_gate_counts[connected_components[0][i]] == 1); + } + + for (size_t i = 0; i < connected_components[1].size(); i++) { + result = result && + (i == connected_components[1].size() - 1 ? variables_gate_counts[connected_components[1][i]] == 2 + : variables_gate_counts[connected_components[1][i]] == 1); + } + EXPECT_EQ(result, true); +} + +TEST(ultra_circuit_constructor, test_variables_gates_counts_for_ecc_add_gates) +{ + typedef grumpkin::g1::affine_element affine_element; + typedef grumpkin::g1::element element; + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + + affine_element p1 = crypto::pedersen_commitment::commit_native({ bb::fr(1) }, 0); + + affine_element p2 = crypto::pedersen_commitment::commit_native({ bb::fr(1) }, 1); + affine_element p3(element(p1) + element(p2)); + + uint32_t x1 = circuit_constructor.add_variable(p1.x); + uint32_t y1 = circuit_constructor.add_variable(p1.y); + uint32_t x2 = circuit_constructor.add_variable(p2.x); + uint32_t y2 = circuit_constructor.add_variable(p2.y); + uint32_t x3 = circuit_constructor.add_variable(p3.x); + uint32_t y3 = circuit_constructor.add_variable(p3.y); + + circuit_constructor.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, 1 }); + + Graph graph = Graph(circuit_constructor); + auto variables_gate_counts = graph.get_variables_gate_counts(); + auto connected_components = graph.find_connected_components(); + bool result = (variables_gate_counts[connected_components[0][0]] == 1) && + (variables_gate_counts[connected_components[0][1]] == 1) && + (variables_gate_counts[connected_components[0][2]] == 2) && + (variables_gate_counts[connected_components[0][3]] == 2) && + (variables_gate_counts[connected_components[0][4]] == 2) && + (variables_gate_counts[connected_components[0][5]] == 2); + EXPECT_EQ(result, true); +} + +TEST(ultra_circuit_constructor, test_variables_gates_counts_for_ecc_dbl_gate) +{ + typedef grumpkin::g1::affine_element affine_element; + typedef grumpkin::g1::element element; + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + + affine_element p1 = crypto::pedersen_commitment::commit_native({ bb::fr(1) }, 0); + affine_element p3(element(p1).dbl()); + + uint32_t x1 = circuit_constructor.add_variable(p1.x); + uint32_t y1 = circuit_constructor.add_variable(p1.y); + uint32_t x3 = circuit_constructor.add_variable(p3.x); + uint32_t y3 = circuit_constructor.add_variable(p3.y); + // info("string from the test: x1, y1, x3, y3 == ", x1, " ", y1, " ", x3, " ", y3); + + circuit_constructor.create_ecc_dbl_gate({ x1, y1, x3, y3 }); + + Graph graph = Graph(circuit_constructor); + auto connected_components = graph.find_connected_components(); + auto variables_gate_counts = graph.get_variables_gate_counts(); + + bool result = (variables_gate_counts[connected_components[0][0]] == 1) && + (variables_gate_counts[connected_components[0][1]] == 1) && + (variables_gate_counts[connected_components[0][2]] == 2) && + (variables_gate_counts[connected_components[0][3]] == 2); + + for (const auto& pair : variables_gate_counts) { + info(pair.first, " ", pair.second); + } + EXPECT_EQ(result, true); +} + +std::vector add_variables(UltraCircuitBuilder& circuit_constructor, std::vector variables) +{ + std::vector res; + for (size_t i = 0; i < variables.size(); i++) { + res.emplace_back(circuit_constructor.add_variable(variables[i])); + } + return res; +} + +TEST(ultra_circuit_constructor, test_graph_for_range_constraints) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + auto indices = add_variables(circuit_constructor, { 1, 2, 3, 4 }); + for (size_t i = 0; i < indices.size(); i++) { + circuit_constructor.create_new_range_constraint(indices[i], 5); + } + // auto ind = {a_idx,b_idx,c_idx,d_idx,e_idx,f_idx,g_idx,h_idx}; + circuit_constructor.create_sort_constraint(indices); + Graph graph = Graph(circuit_constructor); + graph.print_connected_components(); +} + +TEST(ultra_circuit_constructor, composed_range_constraint) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + auto c = fr::random_element(); + auto d = uint256_t(c).slice(0, 133); + auto e = fr(d); + auto a_idx = circuit_constructor.add_variable(fr(e)); + circuit_constructor.create_add_gate( + { a_idx, circuit_constructor.zero_idx, circuit_constructor.zero_idx, 1, 0, 0, -fr(e) }); + circuit_constructor.decompose_into_default_range(a_idx, 134); + + Graph graph = Graph(circuit_constructor); graph.print_connected_components(); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/standard_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/standard_circuit_builder.test.cpp index 927a4fbd5cb7..4e6a039bbb18 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/standard_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/standard_circuit_builder.test.cpp @@ -470,9 +470,9 @@ TEST(standard_circuit_constructor, test_check_circuit_broken) TEST(standard_circuit, test_boomerang_value_1) { StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::random_element(); // взяли случайный элемент - uint32_t a_idx = circuit_constructor.add_public_variable(a); // добавили его в схему - fr b = fr::random_element(); // еще один случайный элемент + fr a = fr::random_element(); + uint32_t a_idx = circuit_constructor.add_public_variable(a); + fr b = fr::random_element(); fr c = a + b; fr d = fr::random_element(); fr e = d + a; // diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/plookup/plookup.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/plookup/plookup.cpp index 375211e12a09..9e26b77eb5b1 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/plookup/plookup.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/plookup/plookup.cpp @@ -48,6 +48,7 @@ plookup::ReadData> plookup_read::get_lookup_accumulato if (rhs_index == IS_CONSTANT) { key_b_witness = std::nullopt; } + const auto accumulator_witnesses = ctx->create_gates_from_plookup_accumulators(id, lookup_data, lhs_index, key_b_witness); From 0779bbb1d4b79fe9495d44112046371649b46a9f Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Fri, 23 Aug 2024 16:30:29 +0000 Subject: [PATCH 08/21] tests for sha256 and blake2s --- .../boomerang_value_detection/.gitignore | 3 - .../boomerang_value_detection/CMakeLists.txt | 2 +- .../graph_description.test.cpp | 6 +- .../graph_description_blake2s.test.cpp | 60 +++++++ .../graph_description_sha256.test.cpp | 160 ++++++++++++++++++ .../stdlib/hash/blake2s/blake2s.test.cpp | 3 +- 6 files changed, 226 insertions(+), 8 deletions(-) delete mode 100644 barretenberg/cpp/src/barretenberg/boomerang_value_detection/.gitignore create mode 100644 barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/.gitignore b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/.gitignore deleted file mode 100644 index c4794383345b..000000000000 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -* -!.gitignore -!/src/barretenberg/boomerang_value_detection/** diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt index 4dad5ed7e3d9..732bb03350a6 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(boomerang_value_detection stdlib_circuit_builders circuit_checker stdlib_primitives numeric stdlib_aes128 stdlib_sha256) \ No newline at end of file +barretenberg_module(boomerang_value_detection stdlib_circuit_builders circuit_checker stdlib_primitives numeric stdlib_aes128 stdlib_sha256 stdlib_blake2s) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp index 52a090d5c96f..4ccec6e82b82 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp @@ -657,7 +657,8 @@ TEST(ultra_circuit_constructor, test_graph_for_range_constraints) // auto ind = {a_idx,b_idx,c_idx,d_idx,e_idx,f_idx,g_idx,h_idx}; circuit_constructor.create_sort_constraint(indices); Graph graph = Graph(circuit_constructor); - graph.print_connected_components(); + auto connected_components = graph.find_connected_components(); + EXPECT_EQ(connected_components.size(), 1); } TEST(ultra_circuit_constructor, composed_range_constraint) @@ -672,5 +673,6 @@ TEST(ultra_circuit_constructor, composed_range_constraint) circuit_constructor.decompose_into_default_range(a_idx, 134); Graph graph = Graph(circuit_constructor); - graph.print_connected_components(); + auto connected_components = graph.find_connected_components(); + EXPECT_EQ(connected_components.size(), 1); } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp new file mode 100644 index 000000000000..c794b1ae1956 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp @@ -0,0 +1,60 @@ +#include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/crypto/blake2s/blake2s.hpp" +#include "barretenberg/stdlib/hash/blake2s/blake2s.hpp" +#include "barretenberg/stdlib/hash/blake2s/blake2s_plookup.hpp" +#include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp" +#include "barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +#include "graph.hpp" +#include + +using namespace bb; +using namespace bb::stdlib; + +using Builder = UltraCircuitBuilder; + +using field_ct = field_t; +using witness_ct = witness_t; +using byte_array_ct = byte_array; +using byte_array_plookup = byte_array; +using public_witness_t = public_witness_t; + +TEST(ultra_circuit_constructor, test_graph_for_blake2s_single_block_plookup) +{ + Builder builder; + std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01"; + std::vector input_v(input.begin(), input.end()); + + byte_array_plookup input_arr(&builder, input_v); + byte_array_plookup output = blake2s(input_arr); + + auto expected = crypto::blake2s(input_v); + + EXPECT_EQ(output.get_value(), std::vector(expected.begin(), expected.end())); + + info("builder gates = ", builder.get_num_gates()); + + Graph graph = Graph(builder); + auto connected_components = graph.find_connected_components(); + EXPECT_EQ(connected_components.size(), 1); +} + +TEST(ultra_circuit_constructor, test_graph_for_blake2s_double_block_plookup) +{ + Builder builder; + std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; + std::vector input_v(input.begin(), input.end()); + + byte_array_plookup input_arr(&builder, input_v); + byte_array_plookup output = blake2s(input_arr); + + auto expected = crypto::blake2s(input_v); + + EXPECT_EQ(output.get_value(), std::vector(expected.begin(), expected.end())); + + info("builder gates = ", builder.get_num_gates()); + + Graph graph = Graph(builder); + auto connected_components = graph.find_connected_components(); + EXPECT_EQ(connected_components.size(), 1); +} diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp new file mode 100644 index 000000000000..e9c2621877a7 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp @@ -0,0 +1,160 @@ +#include "barretenberg/boomerang_value_detection/graph.hpp" +#include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/common/test.hpp" +#include "barretenberg/crypto/sha256/sha256.hpp" +#include "barretenberg/stdlib/hash/sha256/sha256.hpp" +#include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp" +#include "barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.hpp" +#include "barretenberg/stdlib_circuit_builders/plookup_tables/plookup_tables.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" + +#include "barretenberg/numeric/bitop/rotate.hpp" +#include "barretenberg/numeric/bitop/sparse_form.hpp" +#include "barretenberg/numeric/random/engine.hpp" + +using namespace bb; +using namespace bb::stdlib; + +using Builder = UltraCircuitBuilder; + +using byte_array_ct = byte_array; +using packed_byte_array_ct = packed_byte_array; +using field_ct = field_t; + +constexpr uint64_t ror(uint64_t val, uint64_t shift) +{ + return (val >> (shift & 31U)) | (val << (32U - (shift & 31U))); +} + +std::array extend_witness(std::array& in) +{ + std::array w; + + for (size_t i = 0; i < 16; ++i) { + w[i] = in[i]; + } + + for (size_t i = 16; i < 64; ++i) { + uint64_t left = w[i - 15]; + uint64_t right = w[i - 2]; + + uint64_t left_rot7 = numeric::rotate32((uint32_t)left, 7); + uint64_t left_rot18 = numeric::rotate32((uint32_t)left, 18); + uint64_t left_sh3 = left >> 3; + + uint64_t right_rot17 = numeric::rotate32((uint32_t)right, 17); + uint64_t right_rot19 = numeric::rotate32((uint32_t)right, 19); + uint64_t right_sh10 = right >> 10; + + uint64_t s0 = left_rot7 ^ left_rot18 ^ left_sh3; + uint64_t s1 = right_rot17 ^ right_rot19 ^ right_sh10; + + w[i] = w[i - 16] + w[i - 7] + s0 + s1; + } + return w; +} +std::array inner_block(std::array& w) +{ + constexpr uint32_t init_constants[8]{ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; + + constexpr uint32_t round_constants[64]{ + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 + }; + uint32_t a = init_constants[0]; + uint32_t b = init_constants[1]; + uint32_t c = init_constants[2]; + uint32_t d = init_constants[3]; + uint32_t e = init_constants[4]; + uint32_t f = init_constants[5]; + uint32_t g = init_constants[6]; + uint32_t h = init_constants[7]; + for (size_t i = 0; i < 64; ++i) { + uint32_t S1 = numeric::rotate32((uint32_t)e, 6U) ^ numeric::rotate32((uint32_t)e, 11U) ^ + numeric::rotate32((uint32_t)e, 25U); + uint32_t ch = (e & f) ^ (~e & g); // === (e & f) ^ (~e & g), `+` op is cheaper + uint32_t temp1 = h + S1 + ch + round_constants[i] + (uint32_t)w[i]; + uint32_t S0 = numeric::rotate32((uint32_t)a, 2U) ^ numeric::rotate32((uint32_t)a, 13U) ^ + numeric::rotate32((uint32_t)a, 22U); + uint32_t maj = (a & b) ^ (a & c) ^ (b & c); // (a & (b + c - (T0 * 2))) + T0; // === (a & b) ^ (a & c) ^ (b & c) + uint32_t temp2 = S0 + maj; + + h = g; + g = f; + f = e; + e = d + temp1; + d = c; + c = b; + b = a; + a = temp1 + temp2; + } + + /** + * Add into previous block output and return + **/ + std::array output; + output[0] = (uint32_t)(a + init_constants[0]); + output[1] = (uint32_t)(b + init_constants[1]); + output[2] = (uint32_t)(c + init_constants[2]); + output[3] = (uint32_t)(d + init_constants[3]); + output[4] = (uint32_t)(e + init_constants[4]); + output[5] = (uint32_t)(f + init_constants[5]); + output[6] = (uint32_t)(g + init_constants[6]); + output[7] = (uint32_t)(h + init_constants[7]); + return output; +} + +TEST(ultra_circuit_constructor, test_sha256_55_bytes) +{ + // 55 bytes is the largest number of bytes that can be hashed in a single block, + // accounting for the single padding bit, and the 64 size bits required by the SHA-256 standard. + auto builder = Builder(); + packed_byte_array_ct input(&builder, "An 8 character password? Snow White and the 7 Dwarves.."); + + packed_byte_array_ct output_bits = stdlib::sha256(input); + + std::vector output = output_bits.to_unverified_byte_slices(4); + + info("num gates = ", builder.get_num_gates()); + + Graph graph = Graph(builder); + auto connected_components = graph.find_connected_components(); + EXPECT_EQ(connected_components.size(), 1); + graph.print_connected_components(); +} + +HEAVY_TEST(ultra_circuit_constructor, test_graph_for_sha256_NIST_vector_five) +{ + typedef stdlib::field_t field_pt; + typedef stdlib::packed_byte_array packed_byte_array_pt; + + auto builder = UltraCircuitBuilder(); + + packed_byte_array_pt input( + &builder, + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAA"); + + packed_byte_array_pt output_bits = stdlib::sha256(input); + + std::vector output = output_bits.to_unverified_byte_slices(4); + + Graph graph = Graph(builder); + auto connected_components = graph.find_connected_components(); + EXPECT_EQ(connected_components.size(), 1); +} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp index 1bba02baf908..c874b5668f03 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp @@ -88,6 +88,5 @@ TEST(stdlib_blake2s, test_double_block_plookup) info("builder gates = ", builder.get_num_gates()); - bool proof_result = CircuitChecker::check(builder); - EXPECT_EQ(proof_result, true); + Graph graph = Graph() } From 8a52e6dbfb161767c06bfb24f16108a5249a884d Mon Sep 17 00:00:00 2001 From: Rumata888 Date: Fri, 23 Aug 2024 17:32:22 +0000 Subject: [PATCH 09/21] fixes --- .../boomerang_value_detection/graph.cpp | 36 +++++++++---------- .../boomerang_value_detection/graph.hpp | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp index 1d30f12b172c..cf786ff89909 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -3,11 +3,11 @@ #include template -std::vector Graph_::get_arithmetic_gate_connected_component( +inline std::vector Graph_::get_arithmetic_gate_connected_component( bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) { auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; - auto arithmetic_block = ultra_circuit_builder.blocks.arithmetic; + auto& arithmetic_block = ultra_circuit_builder.blocks.arithmetic; uint32_t left_idx = arithmetic_block.w_l()[index]; uint32_t right_idx = arithmetic_block.w_r()[index]; uint32_t out_idx = arithmetic_block.w_o()[index]; @@ -65,11 +65,11 @@ std::vector Graph_::get_arithmetic_gate_connected_component( } template -std::vector Graph_::get_elliptic_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder, - size_t index) +inline std::vector Graph_::get_elliptic_gate_connected_component( + bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) { auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; - auto elliptic_block = ultra_circuit_builder.blocks.elliptic; + auto& elliptic_block = ultra_circuit_builder.blocks.elliptic; std::vector gate_variables; bool is_elliptic_gate = elliptic_block.q_elliptic()[index] == 1; bool is_elliptic_add_gate = elliptic_block.q_1()[index] != 0 && elliptic_block.q_m()[index] == 0; @@ -106,11 +106,11 @@ std::vector Graph_::get_elliptic_gate_connected_component(bb::Ultr } template -std::pair> Graph_::get_sort_constraint_connected_component( +inline std::pair> Graph_::get_sort_constraint_connected_component( bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) { auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; - auto delta_range_block = ultra_circuit_builder.blocks.delta_range; + auto& delta_range_block = ultra_circuit_builder.blocks.delta_range; std::vector gate_variables; bool is_dummy_gate = false; if (delta_range_block.q_delta_range()[index] == 1) { @@ -132,8 +132,8 @@ std::pair> Graph_::get_sort_constraint_connected } template -std::vector Graph_::get_plookup_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder, - size_t index) +inline std::vector Graph_::get_plookup_gate_connected_component( + bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) { auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; std::vector variable_indices; @@ -185,7 +185,7 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit } std::map constant_variable_indices = ultra_circuit_constructor.constant_variable_indices; - auto& arithmetic_block = ultra_circuit_constructor.blocks.arithmetic; + const auto& arithmetic_block = ultra_circuit_constructor.blocks.arithmetic; auto arithmetic_gate_numbers = arithmetic_block.size(); bool arithmetic_gate_exists = arithmetic_gate_numbers > 0; if (arithmetic_gate_exists) { @@ -194,7 +194,7 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit connect_all_variables_in_vector(ultra_circuit_constructor, gate_variables, false); } } - auto& elliptic_block = ultra_circuit_constructor.blocks.elliptic; + const auto& elliptic_block = ultra_circuit_constructor.blocks.elliptic; auto elliptic_gate_numbers = elliptic_block.size(); bool elliptic_gates_exist = elliptic_gate_numbers > 0; if (elliptic_gates_exist) { @@ -203,7 +203,7 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit connect_all_variables_in_vector(ultra_circuit_constructor, gate_variables, false); } } - auto& range_block = ultra_circuit_constructor.blocks.delta_range; + const auto& range_block = ultra_circuit_constructor.blocks.delta_range; auto range_gates = range_block.size(); bool range_gates_exists = range_gates > 0; if (range_gates_exists) { @@ -215,7 +215,7 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit } } - auto& lookup_block = ultra_circuit_constructor.blocks.lookup; + const auto& lookup_block = ultra_circuit_constructor.blocks.lookup; auto lookup_gates = lookup_block.size(); bool lookup_gates_exists = lookup_gates > 0; if (lookup_gates_exists) { @@ -305,7 +305,7 @@ template std::vector Graph_::get_variable_adjacency_ template void Graph_::depth_first_search(const uint32_t& variable_index, - std::vector& is_used, + std::unordered_set& is_used, std::vector& connected_component) { // this method realizes algorithm depth_first_search for undirected graph using the give variable @@ -314,8 +314,8 @@ void Graph_::depth_first_search(const uint32_t& variable_index, while (!variable_stack.empty()) { uint32_t current_index = variable_stack.top(); variable_stack.pop(); - if (std::find(is_used.begin(), is_used.end(), current_index) == is_used.end()) { - is_used.emplace_back(current_index); + if (!is_used.contains(current_index)) { + is_used.insert(current_index); connected_component.emplace_back(current_index); for (const auto& it : variable_adjacency_lists[current_index]) { variable_stack.push(it); @@ -327,11 +327,11 @@ void Graph_::depth_first_search(const uint32_t& variable_index, template std::vector> Graph_::find_connected_components() { // this methond finds connected components from the graph described by adjacency lists - std::vector is_used; + std::unordered_set is_used; std::vector> connected_components; for (const auto& pair : variable_adjacency_lists) { if (pair.first != 0 && variables_degree[pair.first] > 0) { - if (std::find(is_used.begin(), is_used.end(), pair.first) == is_used.end()) { + if (!is_used.contains(pair.first)) { std::vector connected_component; depth_first_search(pair.first, is_used, connected_component); std::sort(connected_component.begin(), connected_component.end()); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp index 2535773e965b..02c185baa676 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp @@ -32,7 +32,7 @@ template class Graph_ { std::vector get_variable_adjacency_list(const uint32_t& variable_index); void depth_first_search(const uint32_t& variable_index, - std::vector& is_used, + std::unordered_set& is_used, std::vector& connected_component); std::vector> find_connected_components(); std::vector find_dangerous_variables(); From 09566843974f65f8dfec3a1589648202efce2322 Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Mon, 9 Sep 2024 12:16:56 +0000 Subject: [PATCH 10/21] variables gate counts metric for AES and sha256 --- .../boomerang_value_detection/CMakeLists.txt | 2 +- .../boomerang_value_detection/graph.cpp | 263 +++++++++++++++--- .../boomerang_value_detection/graph.hpp | 34 ++- .../graph_description.test.cpp | 1 - .../graph_description_blake3s.test.cpp | 57 ++++ .../graph_description_sha256.test.cpp | 92 +----- .../variable_gates_count.test.cpp | 182 ++++++++++++ .../variables_gate_counts.sha256.test.cpp | 41 +++ 8 files changed, 539 insertions(+), 133 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/boomerang_value_detection/variable_gates_count.test.cpp create mode 100644 barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt index 732bb03350a6..dae39eee2de9 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(boomerang_value_detection stdlib_circuit_builders circuit_checker stdlib_primitives numeric stdlib_aes128 stdlib_sha256 stdlib_blake2s) \ No newline at end of file +barretenberg_module(boomerang_value_detection stdlib_circuit_builders circuit_checker stdlib_primitives numeric stdlib_aes128 stdlib_sha256 stdlib_blake2s stdlib_blake3s) \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp index cf786ff89909..2874a7c1f2e9 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -17,7 +17,7 @@ inline std::vector Graph_::get_arithmetic_gate_connected_component auto q_2 = arithmetic_block.q_2()[index]; auto q_3 = arithmetic_block.q_3()[index]; auto q_4 = arithmetic_block.q_4()[index]; - std::vector gate_variables; + std::vector gate_variables = {}; if (q_m != 0 || q_1 != 1 || q_2 != 0 || q_3 != 0 || q_4 != 0) { // this is not the gate for fix_witness, so we have to process this gate if (arithmetic_block.q_arith()[index] > 0) { @@ -70,7 +70,7 @@ inline std::vector Graph_::get_elliptic_gate_connected_component( { auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; auto& elliptic_block = ultra_circuit_builder.blocks.elliptic; - std::vector gate_variables; + std::vector gate_variables = {}; bool is_elliptic_gate = elliptic_block.q_elliptic()[index] == 1; bool is_elliptic_add_gate = elliptic_block.q_1()[index] != 0 && elliptic_block.q_m()[index] == 0; bool is_elliptic_dbl_gate = elliptic_block.q_1()[index] == 0 && elliptic_block.q_m()[index] == 1; @@ -106,13 +106,12 @@ inline std::vector Graph_::get_elliptic_gate_connected_component( } template -inline std::pair> Graph_::get_sort_constraint_connected_component( +inline std::vector Graph_::get_sort_constraint_connected_component( bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) { auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; auto& delta_range_block = ultra_circuit_builder.blocks.delta_range; - std::vector gate_variables; - bool is_dummy_gate = false; + std::vector gate_variables = {}; if (delta_range_block.q_delta_range()[index] == 1) { auto left_idx = delta_range_block.w_l()[index]; auto right_idx = delta_range_block.w_r()[index]; @@ -128,7 +127,7 @@ inline std::pair> Graph_::get_sort_constraint_co variables_gate_counts[real_variable_index] += 1; } } - return std::make_pair(is_dummy_gate, gate_variables); + return gate_variables; } template @@ -136,7 +135,7 @@ inline std::vector Graph_::get_plookup_gate_connected_component( bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) { auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; - std::vector variable_indices; + std::vector variable_indices = {}; auto& lookup_block = ultra_circuit_builder.blocks.lookup; auto q_2 = lookup_block.q_2()[index]; auto q_m = lookup_block.q_m()[index]; @@ -209,9 +208,13 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit if (range_gates_exists) { std::vector sorted_variables; for (size_t i = 0; i < range_gates; i++) { - std::pair> current_gate = - get_sort_constraint_connected_component(ultra_circuit_constructor, i); - sorted_variables.insert(sorted_variables.end(), current_gate.second.begin(), current_gate.second.end()); + auto current_gate = get_sort_constraint_connected_component(ultra_circuit_constructor, i); + if (!current_gate.empty()) { + sorted_variables.insert(sorted_variables.end(), current_gate.begin(), current_gate.end()); + } else { + connect_all_variables_in_vector(ultra_circuit_constructor, sorted_variables, true); + sorted_variables.clear(); + } } } @@ -342,17 +345,224 @@ template std::vector> Graph_::find_conne return connected_components; } -template std::vector Graph_::find_dangerous_variables() +template +inline size_t Graph_::process_current_decompose_chain(bb::UltraCircuitBuilder& ultra_circuit_constructor, + std::unordered_set& variables_in_on_gate, + size_t index) { - std::vector dangerous_variables; - for (auto& it : variables_gate_counts) { - if (it.first >= 2) { - if (it.second == 1) { - dangerous_variables.emplace_back(it.first); + auto to_real = [&](uint32_t variable_index) { + return ultra_circuit_constructor.real_variable_index[variable_index]; + }; + auto& arithmetic_block = ultra_circuit_constructor.blocks.arithmetic; + auto zero_idx = ultra_circuit_constructor.zero_idx; + size_t current_index = index; + std::vector accumulators_indices; + while (true) { + // we have to remove left, right and output wires of the current gate, cause they'are new_limbs, and they are + // useless for the analyzer + auto fourth_idx = arithmetic_block.w_4()[current_index]; + accumulators_indices.emplace_back(to_real(fourth_idx)); + auto left_idx = arithmetic_block.w_l()[current_index]; + if (left_idx != zero_idx) { + variables_in_on_gate.erase(to_real(left_idx)); + } + auto right_idx = arithmetic_block.w_r()[current_index]; + if (right_idx != zero_idx) { + variables_in_on_gate.erase(to_real(right_idx)); + } + auto out_idx = arithmetic_block.w_o()[current_index]; + if (out_idx != zero_idx) { + variables_in_on_gate.erase(to_real(out_idx)); + } + auto q_arith = arithmetic_block.q_arith()[current_index]; + if (q_arith == 1 || current_index == arithmetic_block.size() - 1) { + // this is the last gate in this chain, or we can't go next, so we have to stop a loop + break; + } + current_index++; + } + for (size_t i = 0; i < accumulators_indices.size(); i++) { + if (i == 0) { + // the first variable in accumulators is the variable which decompose was created. So, we have to decrement + // variable_gate_counts for this variable + variables_gate_counts[accumulators_indices[i]] -= 1; + } else { + // next accumulators are useless variables that are not interested for the analyzer. So, for these variables + // we can nullify variables_gate_counts + variables_gate_counts[accumulators_indices[i]] = 0; + } + } + // we don't want to make variables_gate_counts for intermediate variables negative, so, can go to the next gates + return current_index; +} + +template +inline void Graph_::remove_unnecessary_decompose_variables(bb::UltraCircuitBuilder& ultra_circuit_builder, + std::unordered_set& variables_in_one_gate, + const std::unordered_set& decompose_variables) +{ + auto is_power_two = [&](const uint256_t& number) { return number > 0 && ((number & (number - 1)) == 0); }; + auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; + auto find_position = [&](uint32_t variable_index) { return decompose_variables.contains(to_real(variable_index)); }; + // the idea of this function to get the endpoints of the decompose chains. For that we have to clean variable_index + // from unnecessary variables for example, left, right, output wires + auto& arithmetic_block = ultra_circuit_builder.blocks.arithmetic; + if (arithmetic_block.size() > 0) { + for (size_t i = 0; i < arithmetic_block.size(); i++) { + auto q_1 = arithmetic_block.q_1()[i]; + auto q_2 = arithmetic_block.q_2()[i]; + auto q_3 = arithmetic_block.q_3()[i]; + // big addition gate from decompose has selectors, which have the next property: + // q_1 = (1) << shifts[0], target_range_bitnum * (3 * i), + // q_2 = (1) << shifts[1], target_range_bitnum * (3 * i + 1), + // q_3 = (1) << shifts[2], target_range_bitnum * (3 * i + 2) + // so, they are power of two and satisfying the following equality: q_2 * q_2 = q_1 * q_3 + // this way we can differ them from other arithmetic gates + bool q_1_is_power_two = is_power_two(q_1); + bool q_2_is_power_two = is_power_two(q_2); + bool q_3_is_power_two = is_power_two(q_3); + if (q_2 * q_2 == q_1 * q_3 && q_1_is_power_two && q_2_is_power_two && q_3_is_power_two) { + uint32_t left_idx = arithmetic_block.w_l()[i]; + uint32_t right_idx = arithmetic_block.w_r()[i]; + uint32_t out_idx = arithmetic_block.w_o()[i]; + uint32_t fourth_idx = arithmetic_block.w_4()[i]; + bool find_left = find_position(left_idx); + bool find_right = find_position(right_idx); + bool find_out = find_position(out_idx); + bool find_fourth = find_position(fourth_idx); + if (((find_left && find_right && find_out) || (find_left && find_right && !find_out) || + (find_left && find_right && !find_out) || (find_left && !find_right && !find_out)) && + !find_fourth) { + i = process_current_decompose_chain(ultra_circuit_builder, variables_in_one_gate, i); + } } } } - return dangerous_variables; +} + +template +void Graph_::remove_unnecessary_plookup_variables(bb::UltraCircuitBuilder& ultra_circuit_builder, + std::unordered_set& variables_in_one_gate) +{ + auto& lookup_block = ultra_circuit_builder.blocks.lookup; + if (lookup_block.size() > 0) { + for (size_t i = 0; i < lookup_block.size(); i++) { + process_current_plookup_gate(ultra_circuit_builder, variables_in_one_gate, i); + } + } +} + +template +inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ultra_circuit_builder, + std::unordered_set& variables_in_one_gate, + size_t gate_index) +{ + auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; + auto find_position = [&](uint32_t variable_index) { + return variables_in_one_gate.contains(to_real(variable_index)); + }; + auto& lookup_block = ultra_circuit_builder.blocks.lookup; + auto& lookup_tables = ultra_circuit_builder.lookup_tables; + auto table_index = static_cast(lookup_block.q_3()[gate_index]); + for (const auto& table : lookup_tables) { + if (table.table_index == table_index) { + std::set column_1(table.column_1.begin(), table.column_1.end()); + std::set column_2(table.column_2.begin(), table.column_2.end()); + std::set column_3(table.column_3.begin(), table.column_3.end()); + bb::plookup::BasicTableId id = table.id; + if (id == bb::plookup::AES_SBOX_MAP || id == bb::plookup::AES_SPARSE_MAP) { + uint32_t out_idx = lookup_block.w_o()[gate_index]; + uint32_t real_out_idx = to_real(out_idx); + bool find_out = find_position(real_out_idx); + auto q_c = lookup_block.q_c()[gate_index]; + if (q_c == 0) { + if (find_out) { + variables_in_one_gate.erase(real_out_idx); + } + } + } + if (id == bb::plookup::SHA256_WITNESS_SLICE_3) { + uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); + uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); + auto q_m = lookup_block.q_m()[gate_index]; + auto q_c = lookup_block.q_c()[gate_index]; + bool find_out = find_position(real_out_idx); + bool find_right = find_position(real_right_idx); + if (q_c == 0) { + if (find_out) { + variables_in_one_gate.erase(real_out_idx); + } + } + if (q_m == 0) { + if (find_right) { + variables_in_one_gate.erase(real_right_idx); + } + } + } + if (column_1.size() == 1) { + uint32_t left_idx = lookup_block.w_l()[gate_index]; + uint32_t real_left_idx = to_real(left_idx); + bool find_left = find_position(real_left_idx); + if (find_left) { + variables_in_one_gate.erase(real_left_idx); + } + } + if (column_2.size() == 1) { + uint32_t right_idx = lookup_block.w_r()[gate_index]; + uint32_t real_right_idx = to_real(right_idx); + bool find_right = find_position(real_right_idx); + if (find_right) { + variables_in_one_gate.erase(real_right_idx); + } + } + if (column_3.size() == 1) { + uint32_t out_idx = lookup_block.w_o()[gate_index]; + /* if (out_idx == 2506) { + info("break here"); + info("out_idx == ", out_idx); + } */ + uint32_t real_out_idx = to_real(out_idx); + bool find_out = find_position(real_out_idx); + if (find_out) { + variables_in_one_gate.erase(real_out_idx); + } + } + } + } +} + +template +std::unordered_set Graph_::show_variables_in_one_gate(bb::UltraCircuitBuilder& ultra_circuit_builder) +{ + std::unordered_set variables_in_one_gate; + for (const auto& pair : variables_gate_counts) { + bool is_not_constant_variable = check_is_not_constant_variable(ultra_circuit_builder, pair.first); + if (pair.second == 1 && pair.first != 0 && is_not_constant_variable) { + variables_in_one_gate.insert(pair.first); + } + } + auto range_lists = ultra_circuit_builder.range_lists; + std::unordered_set decompose_varialbes; + for (auto& pair : range_lists) { + for (auto& elem : pair.second.variable_indices) { + bool is_not_constant_variable = check_is_not_constant_variable(ultra_circuit_builder, elem); + if (variables_gate_counts[ultra_circuit_builder.real_variable_index[elem]] == 1 && + is_not_constant_variable) { + decompose_varialbes.insert(ultra_circuit_builder.real_variable_index[elem]); + } + } + } + remove_unnecessary_decompose_variables(ultra_circuit_builder, variables_in_one_gate, decompose_varialbes); + remove_unnecessary_plookup_variables(ultra_circuit_builder, variables_in_one_gate); + return variables_in_one_gate; +} + +std::pair, size_t> get_connected_component_with_index( + const std::vector>& connected_components, size_t index) +{ + auto connected_component = connected_components[index]; + auto size = connected_component.size(); + return std::make_pair(connected_component, size); } template void Graph_::print_graph() @@ -380,25 +590,6 @@ template void Graph_::print_connected_components() } } -template -void Graph_::print_dangerous_variables(const bb::StandardCircuitBuilder_& circuit_constructor) -{ - auto dangerous_variables = find_dangerous_variables(); - const auto& block = circuit_constructor.blocks.arithmetic; - for (const auto& it : dangerous_variables) { - info("index of the possible dangerous variable with index ", it); - for (size_t i = 0; i < circuit_constructor.num_gates; i++) { - uint32_t left_idx = block.w_l()[i]; - uint32_t right_idx = block.w_r()[i]; - uint32_t out_idx = block.w_o()[i]; - if (it == left_idx || it == right_idx || it == out_idx) { - info("variable ", it, " in the gate with number ", i); - break; - } - } - } -} - template void Graph_::print_variables_gate_counts() { for (const auto& it : variables_gate_counts) { diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp index 02c185baa676..26b63fbeebce 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -25,8 +26,8 @@ template class Graph_ { size_t index); std::vector get_plookup_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index); - std::pair> get_sort_constraint_connected_component( - bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index); + std::vector get_sort_constraint_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder, + size_t index); void add_new_edge(const uint32_t& first_variable_index, const uint32_t& second_variable_index); std::vector get_variable_adjacency_list(const uint32_t& variable_index); @@ -35,7 +36,14 @@ template class Graph_ { std::unordered_set& is_used, std::vector& connected_component); std::vector> find_connected_components(); - std::vector find_dangerous_variables(); + + std::vector find_variables_with_degree_one(); + std::unordered_set get_variables_in_one_gate(); + + bool find_arithmetic_gate_for_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, + const uint32_t& variable_idx); + bool find_elliptic_gate_for_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, const uint32_t& variable_idx); + bool find_lookup_gate_for_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, const uint32_t& variable_idx); size_t get_distance_between_variables(const uint32_t& first_variable_index, const uint32_t& second_variable_index); bool check_vertex_in_connected_component(const std::vector& connected_component, @@ -46,10 +54,28 @@ template class Graph_ { bool is_sorted_variables); bool check_is_not_constant_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, const uint32_t& variable_index); + std::pair, size_t> get_connected_component_with_index( + const std::vector>& connected_components, size_t index); + + std::unordered_set get_variables_in_one_gate_without_range_constraints( + bb::UltraCircuitBuilder& ultra_circuit_builder); + + size_t process_current_decompose_chain(bb::UltraCircuitBuilder& ultra_circuit_constructor, + std::unordered_set& variables_in_one_gate, + size_t index); + void process_current_plookup_gate(bb::UltraCircuitBuilder& ultra_circuit_builder, + std::unordered_set& variables_in_one_gate, + size_t gate_index); + void remove_unnecessary_decompose_variables(bb::UltraCircuitBuilder& ultra_circuit_builder, + std::unordered_set& variables_in_on_gate, + const std::unordered_set& decompose_variables); + void remove_unnecessary_plookup_variables(bb::UltraCircuitBuilder& ultra_circuit_builder, + std::unordered_set& variables_in_on_gate); + std::unordered_set show_variables_in_one_gate(bb::UltraCircuitBuilder& ultra_circuit_builder); + void print_graph(); void print_connected_components(); void print_variables_gate_counts(); - void print_dangerous_variables(const bb::StandardCircuitBuilder_& circuit_constructor); void print_variables_edge_counts(); ~Graph_() = default; diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp index 4ccec6e82b82..19db97ddcf82 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp @@ -6,7 +6,6 @@ #include "barretenberg/stdlib/encryption/aes128/aes128.hpp" #include "barretenberg/stdlib_circuit_builders/mock_circuits.hpp" #include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" -#include "barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" #include diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp new file mode 100644 index 000000000000..9b54e81c573c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp @@ -0,0 +1,57 @@ +#include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/common/streams.hpp" +#include "barretenberg/crypto/blake3s/blake3s.hpp" +#include "barretenberg/stdlib/hash/blake3s/blake3s.hpp" +#include "barretenberg/stdlib/hash/blake3s/blake3s_plookup.hpp" +#include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp" +#include "barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.hpp" +#include "graph.hpp" +#include + +using namespace bb; + +using byte_array = stdlib::byte_array; +using public_witness_t = stdlib::public_witness_t; +using byte_array_plookup = stdlib::byte_array; +using public_witness_t_plookup = stdlib::public_witness_t; +using UltraBuilder = UltraCircuitBuilder; + +TEST(stdlib_blake3s, test_single_block_plookup) +{ + auto builder = UltraBuilder(); + std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01"; + std::vector input_v(input.begin(), input.end()); + + byte_array_plookup input_arr(&builder, input_v); + byte_array_plookup output = stdlib::blake3s(input_arr); + + std::vector expected = blake3::blake3s(input_v); + + EXPECT_EQ(output.get_value(), expected); + + info("builder gates = ", builder.get_num_gates()); + + Graph graph = Graph(builder); + auto connected_components = graph.find_connected_components(); + EXPECT_EQ(connected_components.size(), 1); +} + +TEST(stdlib_blake3s, test_double_block_plookup) +{ + auto builder = UltraBuilder(); + std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; + std::vector input_v(input.begin(), input.end()); + + byte_array_plookup input_arr(&builder, input_v); + byte_array_plookup output = stdlib::blake3s(input_arr); + + std::vector expected = blake3::blake3s(input_v); + + EXPECT_EQ(output.get_value(), expected); + + info("builder gates = ", builder.get_num_gates()); + + Graph graph = Graph(builder); + auto connected_components = graph.find_connected_components(); + EXPECT_EQ(connected_components.size(), 1); +} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp index e9c2621877a7..5555d1a99639 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp @@ -21,96 +21,6 @@ using byte_array_ct = byte_array; using packed_byte_array_ct = packed_byte_array; using field_ct = field_t; -constexpr uint64_t ror(uint64_t val, uint64_t shift) -{ - return (val >> (shift & 31U)) | (val << (32U - (shift & 31U))); -} - -std::array extend_witness(std::array& in) -{ - std::array w; - - for (size_t i = 0; i < 16; ++i) { - w[i] = in[i]; - } - - for (size_t i = 16; i < 64; ++i) { - uint64_t left = w[i - 15]; - uint64_t right = w[i - 2]; - - uint64_t left_rot7 = numeric::rotate32((uint32_t)left, 7); - uint64_t left_rot18 = numeric::rotate32((uint32_t)left, 18); - uint64_t left_sh3 = left >> 3; - - uint64_t right_rot17 = numeric::rotate32((uint32_t)right, 17); - uint64_t right_rot19 = numeric::rotate32((uint32_t)right, 19); - uint64_t right_sh10 = right >> 10; - - uint64_t s0 = left_rot7 ^ left_rot18 ^ left_sh3; - uint64_t s1 = right_rot17 ^ right_rot19 ^ right_sh10; - - w[i] = w[i - 16] + w[i - 7] + s0 + s1; - } - return w; -} -std::array inner_block(std::array& w) -{ - constexpr uint32_t init_constants[8]{ 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, - 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 }; - - constexpr uint32_t round_constants[64]{ - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 - }; - uint32_t a = init_constants[0]; - uint32_t b = init_constants[1]; - uint32_t c = init_constants[2]; - uint32_t d = init_constants[3]; - uint32_t e = init_constants[4]; - uint32_t f = init_constants[5]; - uint32_t g = init_constants[6]; - uint32_t h = init_constants[7]; - for (size_t i = 0; i < 64; ++i) { - uint32_t S1 = numeric::rotate32((uint32_t)e, 6U) ^ numeric::rotate32((uint32_t)e, 11U) ^ - numeric::rotate32((uint32_t)e, 25U); - uint32_t ch = (e & f) ^ (~e & g); // === (e & f) ^ (~e & g), `+` op is cheaper - uint32_t temp1 = h + S1 + ch + round_constants[i] + (uint32_t)w[i]; - uint32_t S0 = numeric::rotate32((uint32_t)a, 2U) ^ numeric::rotate32((uint32_t)a, 13U) ^ - numeric::rotate32((uint32_t)a, 22U); - uint32_t maj = (a & b) ^ (a & c) ^ (b & c); // (a & (b + c - (T0 * 2))) + T0; // === (a & b) ^ (a & c) ^ (b & c) - uint32_t temp2 = S0 + maj; - - h = g; - g = f; - f = e; - e = d + temp1; - d = c; - c = b; - b = a; - a = temp1 + temp2; - } - - /** - * Add into previous block output and return - **/ - std::array output; - output[0] = (uint32_t)(a + init_constants[0]); - output[1] = (uint32_t)(b + init_constants[1]); - output[2] = (uint32_t)(c + init_constants[2]); - output[3] = (uint32_t)(d + init_constants[3]); - output[4] = (uint32_t)(e + init_constants[4]); - output[5] = (uint32_t)(f + init_constants[5]); - output[6] = (uint32_t)(g + init_constants[6]); - output[7] = (uint32_t)(h + init_constants[7]); - return output; -} - TEST(ultra_circuit_constructor, test_sha256_55_bytes) { // 55 bytes is the largest number of bytes that can be hashed in a single block, @@ -127,7 +37,7 @@ TEST(ultra_circuit_constructor, test_sha256_55_bytes) Graph graph = Graph(builder); auto connected_components = graph.find_connected_components(); EXPECT_EQ(connected_components.size(), 1); - graph.print_connected_components(); + // graph.print_connected_components(); } HEAVY_TEST(ultra_circuit_constructor, test_graph_for_sha256_NIST_vector_five) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variable_gates_count.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variable_gates_count.test.cpp new file mode 100644 index 000000000000..91aaee1adf8c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variable_gates_count.test.cpp @@ -0,0 +1,182 @@ +#include "barretenberg/boomerang_value_detection/graph.hpp" +#include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/crypto/aes128/aes128.hpp" +#include "barretenberg/crypto/generators/generator_data.hpp" +#include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" +#include "barretenberg/stdlib/encryption/aes128/aes128.hpp" +#include "barretenberg/stdlib_circuit_builders/mock_circuits.hpp" +#include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" +#include "barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" + +#include + +using namespace bb; + +TEST(ultra_circuit_constructor, test_variable_gates_count_for_decompose) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + auto c = fr::random_element(); + auto d = uint256_t(c).slice(0, 133); + auto e = fr(d); + auto a_idx = circuit_constructor.add_variable(fr(e)); + circuit_constructor.create_add_gate( + { a_idx, circuit_constructor.zero_idx, circuit_constructor.zero_idx, 1, 0, 0, -fr(e) }); + circuit_constructor.decompose_into_default_range(a_idx, 134); + + Graph graph = Graph(circuit_constructor); + std::unordered_set variables_in_on_gate = graph.show_variables_in_one_gate(circuit_constructor); + EXPECT_EQ(variables_in_on_gate.size(), 1); +} + +TEST(ultra_circuit_constructor, test_variable_gates_count_for_decompose2) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + auto c = fr::random_element(); + auto d = uint256_t(c).slice(0, 41); + auto e = fr(d); + auto a_idx = circuit_constructor.add_variable(fr(e)); + circuit_constructor.create_add_gate( + { a_idx, circuit_constructor.zero_idx, circuit_constructor.zero_idx, 1, 0, 0, -fr(e) }); + circuit_constructor.decompose_into_default_range(a_idx, 42); + + Graph graph = Graph(circuit_constructor); + auto variables_in_on_gate = graph.show_variables_in_one_gate(circuit_constructor); + EXPECT_EQ(variables_in_on_gate.size(), 1); +} + +TEST(utils, test_selectors_for_decompose) +{ + auto is_power_two = [&](const uint256_t& number) { return number > 0 && ((number & (number - 1)) == 0); }; + const uint64_t target_range_bitnum = 14; + size_t i = 0; + const uint64_t shifts[3]{ + target_range_bitnum * (3 * i), + target_range_bitnum * (3 * i + 1), + target_range_bitnum * (3 * i + 2), + }; + uint256_t q_1 = uint256_t(1) << shifts[0]; + uint256_t q_2 = uint256_t(1) << shifts[1]; + uint256_t q_3 = uint256_t(1) << shifts[2]; + bool q_1_is_power_two = is_power_two(q_1); + bool q_2_is_power_two = is_power_two(q_2); + bool q_3_is_power_two = is_power_two(q_3); + EXPECT_EQ(q_2 * q_2, q_1 * q_3); + EXPECT_EQ(q_1_is_power_two, true); + EXPECT_EQ(q_2_is_power_two, true); + EXPECT_EQ(q_3_is_power_two, true); +} + +TEST(ultra_circuit_constructor, test_variable_gates_count_for_two_decomposes) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + auto c1 = fr::random_element(); + auto c2 = fr::random_element(); + auto d1 = uint256_t(c1).slice(0, 41); + auto d2 = uint256_t(c2).slice(0, 41); + auto e1 = fr(d1); + auto e2 = fr(d2); + auto a1_idx = circuit_constructor.add_variable(fr(e1)); + auto a2_idx = circuit_constructor.add_variable(fr(e2)); + circuit_constructor.create_add_gate( + { a1_idx, circuit_constructor.zero_idx, circuit_constructor.zero_idx, 1, 0, 0, -fr(e1) }); + circuit_constructor.create_add_gate( + { a2_idx, circuit_constructor.zero_idx, circuit_constructor.zero_idx, 1, 0, 0, -fr(e2) }); + circuit_constructor.decompose_into_default_range(a1_idx, 42); + circuit_constructor.decompose_into_default_range(a2_idx, 42); + + Graph graph = Graph(circuit_constructor); + std::unordered_set variables_in_one_gate = graph.show_variables_in_one_gate(circuit_constructor); + EXPECT_EQ(variables_in_one_gate.size(), 2); +} + +TEST(ultra_circuit_constructor, test_decompose_with_boolean_gates) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + auto c1 = fr::random_element(); + auto c2 = fr::random_element(); + auto d1 = uint256_t(c1).slice(0, 41); + auto d2 = uint256_t(c2).slice(0, 41); + auto e1 = fr(d1); + auto e2 = fr(d2); + auto a1_idx = circuit_constructor.add_variable(fr(e1)); + auto a2_idx = circuit_constructor.add_variable(fr(e2)); + circuit_constructor.decompose_into_default_range(a1_idx, 42); + circuit_constructor.decompose_into_default_range(a2_idx, 42); + + for (size_t i = 0; i < 20; ++i) { + fr a = fr::zero(); + uint32_t a_idx = circuit_constructor.add_variable(a); + circuit_constructor.create_bool_gate(a_idx); + } + + Graph graph = Graph(circuit_constructor); + std::unordered_set variables_in_one_gate = graph.show_variables_in_one_gate(circuit_constructor); + EXPECT_EQ(variables_in_one_gate.size(), 22); +} + +TEST(ultra_circuit_constructor, test_decompose_for_6_bit_number) +{ + UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); + auto c = fr::random_element(); + auto d = uint256_t(c).slice(0, 5); + auto e = fr(d); + auto a_idx = circuit_constructor.add_variable(fr(d)); + circuit_constructor.create_add_gate( + { a_idx, circuit_constructor.zero_idx, circuit_constructor.zero_idx, 1, 0, 0, -fr(e) }); + circuit_constructor.decompose_into_default_range(a_idx, 6); + + Graph graph = Graph(circuit_constructor); + std::unordered_set variables_in_on_gate = graph.show_variables_in_one_gate(circuit_constructor); + EXPECT_EQ(variables_in_on_gate.size(), 1); +} + +TEST(ultra_circuit_constructor, test_decompose_for_aes_64bytes) +{ + typedef stdlib::field_t field_pt; + typedef stdlib::witness_t witness_pt; + + uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; + uint8_t out[64]{ 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, + 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, + 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, + 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 }; + uint8_t iv[16]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; + uint8_t in[64]{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; + const auto convert_bytes = [](uint8_t* data) { + uint256_t converted(0); + for (uint64_t i = 0; i < 16; ++i) { + uint256_t to_add = uint256_t((uint64_t)(data[i])) << uint256_t((15 - i) * 8); + converted += to_add; + } + return converted; + }; + auto builder = UltraCircuitBuilder(); + std::vector in_field{ + witness_pt(&builder, fr(convert_bytes(in))), + witness_pt(&builder, fr(convert_bytes(in + 16))), + witness_pt(&builder, fr(convert_bytes(in + 32))), + witness_pt(&builder, fr(convert_bytes(in + 48))), + }; + field_pt key_field(witness_pt(&builder, fr(convert_bytes(key)))); + field_pt iv_field(witness_pt(&builder, fr(convert_bytes(iv)))); + + std::vector expected{ + convert_bytes(out), convert_bytes(out + 16), convert_bytes(out + 32), convert_bytes(out + 48) + }; + + const auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field); + + for (size_t i = 0; i < 4; ++i) { + EXPECT_EQ(result[i].get_value(), expected[i]); + } + + Graph graph = Graph(builder); + std::unordered_set variables_in_on_gate = graph.show_variables_in_one_gate(builder); + for (const auto& elem : variables_in_on_gate) { + info("elem == ", elem); + } +} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp new file mode 100644 index 000000000000..e7866f518625 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp @@ -0,0 +1,41 @@ +#include "barretenberg/boomerang_value_detection/graph.hpp" +#include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/crypto/sha256/sha256.hpp" +#include "barretenberg/stdlib/hash/sha256/sha256.hpp" +#include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp" +#include "barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.hpp" +#include "barretenberg/stdlib_circuit_builders/plookup_tables/plookup_tables.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" + +#include "barretenberg/numeric/bitop/rotate.hpp" +#include "barretenberg/numeric/bitop/sparse_form.hpp" +#include "barretenberg/numeric/random/engine.hpp" + +#include + +using namespace bb; +using namespace bb::stdlib; + +using Builder = UltraCircuitBuilder; + +using byte_array_ct = byte_array; +using packed_byte_array_ct = packed_byte_array; +using field_ct = field_t; + +TEST(ultra_circuit_constructor, test_variables_gate_counts_for_sha256_55_bytes) +{ + // 55 bytes is the largest number of bytes that can be hashed in a single block, + // accounting for the single padding bit, and the 64 size bits required by the SHA-256 standard. + auto builder = Builder(); + packed_byte_array_ct input(&builder, "An 8 character password? Snow White and the 7 Dwarves.."); + + packed_byte_array_ct output_bits = stdlib::sha256(input); + + // std::vector output = output_bits.to_unverified_byte_slices(4); + + Graph graph = Graph(builder); + std::unordered_set variables_in_on_gate = graph.show_variables_in_one_gate(builder); + for (const auto& elem : variables_in_on_gate) { + info("elem == ", elem); + } +} \ No newline at end of file From 637c203301591b9d14656157f745fe57011a9d62 Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Mon, 9 Sep 2024 12:52:31 +0000 Subject: [PATCH 11/21] remove changes from blake2s tests and circuit_builder_base --- .../cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp index c874b5668f03..99c29d7751f8 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp @@ -87,6 +87,4 @@ TEST(stdlib_blake2s, test_double_block_plookup) EXPECT_EQ(output.get_value(), std::vector(expected.begin(), expected.end())); info("builder gates = ", builder.get_num_gates()); - - Graph graph = Graph() } From ff5df64bcaf3312dec80865eb4547740c4328d7d Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Mon, 16 Sep 2024 10:51:27 +0000 Subject: [PATCH 12/21] variables gate count for sha256 + tests --- barretenberg/barretenberg.code-workspace | 2 +- .../boomerang_value_detection/graph.cpp | 109 ++++++++++++++---- .../variables_gate_counts.sha256.test.cpp | 35 +++++- .../stdlib/hash/sha256/sha256_plookup.cpp | 1 - 4 files changed, 123 insertions(+), 24 deletions(-) diff --git a/barretenberg/barretenberg.code-workspace b/barretenberg/barretenberg.code-workspace index cd08c7a31666..0d6e91f15839 100644 --- a/barretenberg/barretenberg.code-workspace +++ b/barretenberg/barretenberg.code-workspace @@ -145,6 +145,6 @@ "cwd": "${command:cmake.buildDirectory}", "internalConsoleOptions": "openOnSessionStart", "console": "internalConsole", - } + }, }, } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp index 2874a7c1f2e9..b308fcb11f52 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -471,31 +471,102 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul std::set column_3(table.column_3.begin(), table.column_3.end()); bb::plookup::BasicTableId id = table.id; if (id == bb::plookup::AES_SBOX_MAP || id == bb::plookup::AES_SPARSE_MAP) { - uint32_t out_idx = lookup_block.w_o()[gate_index]; - uint32_t real_out_idx = to_real(out_idx); - bool find_out = find_position(real_out_idx); - auto q_c = lookup_block.q_c()[gate_index]; - if (q_c == 0) { - if (find_out) { - variables_in_one_gate.erase(real_out_idx); + uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); + uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); + if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { + bool find_out = find_position(real_out_idx); + bool find_right = find_position(real_right_idx); + auto q_m = lookup_block.q_m()[gate_index]; + auto q_c = lookup_block.q_c()[gate_index]; + if (q_c == 0) { + if (find_out) { + variables_in_one_gate.erase(real_out_idx); + } + } + if (q_m == 0) { + if (find_right) { + variables_in_one_gate.erase(real_right_idx); + } } } } if (id == bb::plookup::SHA256_WITNESS_SLICE_3) { uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); - auto q_m = lookup_block.q_m()[gate_index]; - auto q_c = lookup_block.q_c()[gate_index]; - bool find_out = find_position(real_out_idx); - bool find_right = find_position(real_right_idx); - if (q_c == 0) { - if (find_out) { - variables_in_one_gate.erase(real_out_idx); + if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { + auto q_m = lookup_block.q_m()[gate_index]; + auto q_c = lookup_block.q_c()[gate_index]; + bool find_out = find_position(real_out_idx); + bool find_right = find_position(real_right_idx); + if (q_c == 0) { + if (find_out) { + variables_in_one_gate.erase(real_out_idx); + } + } + if (q_m == 0) { + if (find_right) { + variables_in_one_gate.erase(real_right_idx); + } } } - if (q_m == 0) { - if (find_right) { - variables_in_one_gate.erase(real_right_idx); + } + if (id == bb::plookup::SHA256_WITNESS_SLICE_7_ROTATE_4) { + uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); + uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); + if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { + auto q_m = lookup_block.q_m()[gate_index]; + auto q_c = lookup_block.q_c()[gate_index]; + bool find_out = find_position(real_out_idx); + bool find_right = find_position(real_right_idx); + if (q_c == 0) { + if (find_out) { + variables_in_one_gate.erase(real_out_idx); + } + } + if (q_m == 0) { + if (find_right) { + variables_in_one_gate.erase(real_right_idx); + } + } + } + } + if (id == bb::plookup::SHA256_WITNESS_SLICE_8_ROTATE_7) { + uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); + uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); + if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { + auto q_m = lookup_block.q_m()[gate_index]; + auto q_c = lookup_block.q_c()[gate_index]; + bool find_out = find_position(real_out_idx); + bool find_right = find_position(real_right_idx); + if (q_c == 0) { + if (find_out) { + variables_in_one_gate.erase(real_out_idx); + } + } + if (q_m == 0) { + if (find_right) { + variables_in_one_gate.erase(real_right_idx); + } + } + } + } + if (id == bb::plookup::SHA256_WITNESS_SLICE_14_ROTATE_1) { + uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); + uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); + if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { + auto q_m = lookup_block.q_m()[gate_index]; + auto q_c = lookup_block.q_c()[gate_index]; + bool find_out = find_position(real_out_idx); + bool find_right = find_position(real_right_idx); + if (q_c == 0) { + if (find_out) { + variables_in_one_gate.erase(real_out_idx); + } + } + if (q_m == 0) { + if (find_right) { + variables_in_one_gate.erase(real_right_idx); + } } } } @@ -517,10 +588,6 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul } if (column_3.size() == 1) { uint32_t out_idx = lookup_block.w_o()[gate_index]; - /* if (out_idx == 2506) { - info("break here"); - info("out_idx == ", out_idx); - } */ uint32_t real_out_idx = to_real(out_idx); bool find_out = find_position(real_out_idx); if (find_out) { diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp index e7866f518625..93144029a567 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp @@ -11,6 +11,8 @@ #include "barretenberg/numeric/bitop/sparse_form.hpp" #include "barretenberg/numeric/random/engine.hpp" +#include + #include using namespace bb; @@ -20,6 +22,7 @@ using Builder = UltraCircuitBuilder; using byte_array_ct = byte_array; using packed_byte_array_ct = packed_byte_array; +using witness_ct = stdlib::witness_t; using field_ct = field_t; TEST(ultra_circuit_constructor, test_variables_gate_counts_for_sha256_55_bytes) @@ -35,7 +38,37 @@ TEST(ultra_circuit_constructor, test_variables_gate_counts_for_sha256_55_bytes) Graph graph = Graph(builder); std::unordered_set variables_in_on_gate = graph.show_variables_in_one_gate(builder); - for (const auto& elem : variables_in_on_gate) { + std::vector vector_variables_in_on_gate(variables_in_on_gate.begin(), variables_in_on_gate.end()); + std::sort(vector_variables_in_on_gate.begin(), vector_variables_in_on_gate.end()); + for (const auto& elem : vector_variables_in_on_gate) { info("elem == ", elem); } +} + +TEST(ultra_circuit_constructor, test_boomerang_value_in_sha256) +{ + auto builder = Builder(); + std::array, 16> input; + for (size_t i = 0; i < 16; i++) { + auto variable = fr::random_element(); + auto var_slice = uint256_t(variable).slice(0, 32); + field_ct elt(witness_ct(&builder, fr(var_slice))); + builder.fix_witness(elt.witness_index, elt.get_value()); + input[i] = elt; + } + std::array, 64> w_ext = sha256_plookup::extend_witness(input); + bool result1 = CircuitChecker::check(builder); + EXPECT_EQ(result1, true); + while (true) { + auto change_variable = fr::random_element(); + auto change_var_slice = uint256_t(change_variable).slice(0, 32); + field_t change_elt(&builder, fr(change_var_slice)); + uint32_t variable_index = w_ext[62].witness_index; + if (builder.variables[builder.real_variable_index[variable_index]] != fr(change_var_slice)) { + builder.variables[builder.real_variable_index[variable_index]] = fr(change_var_slice); + bool result2 = CircuitChecker::check(builder); + EXPECT_EQ(result2, true); + break; + } + } } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256_plookup.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256_plookup.cpp index 6c809f12d840..65cff037e952 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256_plookup.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256_plookup.cpp @@ -316,7 +316,6 @@ std::array, 8> sha256_block(const std::array, output[5] = add_normalize(f.normal, h_init[5]); output[6] = add_normalize(g.normal, h_init[6]); output[7] = add_normalize(h.normal, h_init[7]); - /** * At this point, a malicilous prover could tweak the add_normalise function and the result could be 'overflowed'. * Thus, we need 32-bit range checks on the outputs. Note that we won't need range checks while applying the SHA-256 From aef2249eb33392c75cf73c4439eb7befcbb5c2b9 Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Mon, 16 Sep 2024 10:54:00 +0000 Subject: [PATCH 13/21] remove some changes from workspace --- barretenberg/barretenberg.code-workspace | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/barretenberg.code-workspace b/barretenberg/barretenberg.code-workspace index 0d6e91f15839..c150125270a7 100644 --- a/barretenberg/barretenberg.code-workspace +++ b/barretenberg/barretenberg.code-workspace @@ -145,6 +145,6 @@ "cwd": "${command:cmake.buildDirectory}", "internalConsoleOptions": "openOnSessionStart", "console": "internalConsole", - }, + } }, } \ No newline at end of file From bda8275041917a9f5ba9a8e77840351ab4bc067c Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Fri, 20 Sep 2024 10:09:40 +0000 Subject: [PATCH 14/21] update for sha256 for PR --- .../boomerang_value_detection/graph.cpp | 84 +++------- .../graph_description_sha256.test.cpp | 1 - .../variables_gate_counts.sha256.test.cpp | 158 +++++++++++++++--- .../stdlib/hash/sha256/sha256_plookup.cpp | 1 + 4 files changed, 156 insertions(+), 88 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp index b308fcb11f52..7ddef3a7e649 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -441,8 +441,8 @@ inline void Graph_::remove_unnecessary_decompose_variables(bb::UltraCircuitB } template -void Graph_::remove_unnecessary_plookup_variables(bb::UltraCircuitBuilder& ultra_circuit_builder, - std::unordered_set& variables_in_one_gate) +inline void Graph_::remove_unnecessary_plookup_variables(bb::UltraCircuitBuilder& ultra_circuit_builder, + std::unordered_set& variables_in_one_gate) { auto& lookup_block = ultra_circuit_builder.blocks.lookup; if (lookup_block.size() > 0) { @@ -470,6 +470,8 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul std::set column_2(table.column_2.begin(), table.column_2.end()); std::set column_3(table.column_3.begin(), table.column_3.end()); bb::plookup::BasicTableId id = table.id; + // in some table we don't use variables from third column. So, these variables are false-case for a + // analyzer, and we have to remove them false cases for AES if (id == bb::plookup::AES_SBOX_MAP || id == bb::plookup::AES_SPARSE_MAP) { uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); @@ -490,7 +492,12 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul } } } - if (id == bb::plookup::SHA256_WITNESS_SLICE_3) { + // false cases for sha256 + if (id == bb::plookup::SHA256_WITNESS_SLICE_3 || id == bb::plookup::SHA256_WITNESS_SLICE_7_ROTATE_4 || + id == bb::plookup::SHA256_WITNESS_SLICE_8_ROTATE_7 || + id == bb::plookup::SHA256_WITNESS_SLICE_14_ROTATE_1 || id == bb::plookup::SHA256_BASE16_ROTATE2 || + id == bb::plookup::SHA256_BASE16 || id == bb::plookup::SHA256_BASE28_ROTATE6 || + id == bb::plookup::SHA256_BASE28_ROTATE3) { uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { @@ -498,66 +505,9 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul auto q_c = lookup_block.q_c()[gate_index]; bool find_out = find_position(real_out_idx); bool find_right = find_position(real_right_idx); - if (q_c == 0) { - if (find_out) { - variables_in_one_gate.erase(real_out_idx); - } - } - if (q_m == 0) { - if (find_right) { - variables_in_one_gate.erase(real_right_idx); - } - } - } - } - if (id == bb::plookup::SHA256_WITNESS_SLICE_7_ROTATE_4) { - uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); - uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); - if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { - auto q_m = lookup_block.q_m()[gate_index]; - auto q_c = lookup_block.q_c()[gate_index]; - bool find_out = find_position(real_out_idx); - bool find_right = find_position(real_right_idx); - if (q_c == 0) { - if (find_out) { - variables_in_one_gate.erase(real_out_idx); - } - } - if (q_m == 0) { - if (find_right) { - variables_in_one_gate.erase(real_right_idx); - } + if (real_out_idx == 1504) { + info("it's selector == ", q_m); } - } - } - if (id == bb::plookup::SHA256_WITNESS_SLICE_8_ROTATE_7) { - uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); - uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); - if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { - auto q_m = lookup_block.q_m()[gate_index]; - auto q_c = lookup_block.q_c()[gate_index]; - bool find_out = find_position(real_out_idx); - bool find_right = find_position(real_right_idx); - if (q_c == 0) { - if (find_out) { - variables_in_one_gate.erase(real_out_idx); - } - } - if (q_m == 0) { - if (find_right) { - variables_in_one_gate.erase(real_right_idx); - } - } - } - } - if (id == bb::plookup::SHA256_WITNESS_SLICE_14_ROTATE_1) { - uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); - uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); - if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { - auto q_m = lookup_block.q_m()[gate_index]; - auto q_c = lookup_block.q_c()[gate_index]; - bool find_out = find_position(real_out_idx); - bool find_right = find_position(real_right_idx); if (q_c == 0) { if (find_out) { variables_in_one_gate.erase(real_out_idx); @@ -568,6 +518,12 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul variables_in_one_gate.erase(real_right_idx); } } + } else { + info("gates_count: ", + variables_gate_counts[real_out_idx], + " ", + variables_gate_counts[real_right_idx]); + info("variable indices: ", real_right_idx, " ", real_out_idx); } } if (column_1.size() == 1) { @@ -661,7 +617,6 @@ template void Graph_::print_variables_gate_counts() { for (const auto& it : variables_gate_counts) { info("number of gates with variables ", it.first, " == ", it.second); - info(it.second); } } @@ -669,8 +624,7 @@ template void Graph_::print_variables_edge_counts() { for (const auto& it : variables_degree) { if (it.first != 0) { - info("variable index = ", it.first); - info("number of edges for this variables = ", it.second); + info("variable index = ", it.first, "number of edges for this variable = ", it.second); } } } diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp index 5555d1a99639..c48144b3fc90 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp @@ -37,7 +37,6 @@ TEST(ultra_circuit_constructor, test_sha256_55_bytes) Graph graph = Graph(builder); auto connected_components = graph.find_connected_components(); EXPECT_EQ(connected_components.size(), 1); - // graph.print_connected_components(); } HEAVY_TEST(ultra_circuit_constructor, test_graph_for_sha256_NIST_vector_five) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp index 93144029a567..ca23325f7228 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp @@ -1,5 +1,6 @@ #include "barretenberg/boomerang_value_detection/graph.hpp" #include "barretenberg/circuit_checker/circuit_checker.hpp" +#include "barretenberg/common/test.hpp" #include "barretenberg/crypto/sha256/sha256.hpp" #include "barretenberg/stdlib/hash/sha256/sha256.hpp" #include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp" @@ -25,6 +26,29 @@ using packed_byte_array_ct = packed_byte_array; using witness_ct = stdlib::witness_t; using field_ct = field_t; +bool check_in_byte_array(const uint32_t& real_var_index, const packed_byte_array_ct& byte_array) +{ + std::vector> limbs = byte_array.get_limbs(); + for (const auto& elem : limbs) { + if (elem.witness_index == real_var_index) { + return true; + } + } + return false; +} + +bool check_in_range_lists(const uint32_t& real_var_index, const uint64_t& target_range, const Builder& builder) +{ + auto range_lists = builder.range_lists; + auto target_list = range_lists[target_range]; + for (const auto elem : target_list.variable_indices) { + if (elem == real_var_index) { + return true; + } + } + return false; +} + TEST(ultra_circuit_constructor, test_variables_gate_counts_for_sha256_55_bytes) { // 55 bytes is the largest number of bytes that can be hashed in a single block, @@ -41,34 +65,124 @@ TEST(ultra_circuit_constructor, test_variables_gate_counts_for_sha256_55_bytes) std::vector vector_variables_in_on_gate(variables_in_on_gate.begin(), variables_in_on_gate.end()); std::sort(vector_variables_in_on_gate.begin(), vector_variables_in_on_gate.end()); for (const auto& elem : vector_variables_in_on_gate) { - info("elem == ", elem); + bool result1 = check_in_byte_array(elem, input); + bool result2 = check_in_byte_array(elem, output_bits); + bool result3 = check_in_range_lists(elem, 3, builder); + bool check = (result1 == 1) || (result2 == 1) || (result3 == 1); + EXPECT_EQ(check, true); + } +} + +HEAVY_TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_vector_five) +{ + auto builder = Builder(); + + packed_byte_array_ct input( + &builder, + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAA"); + + packed_byte_array_ct output_bits = stdlib::sha256(input); + Graph graph = Graph(builder); + std::unordered_set variables_in_on_gate = graph.show_variables_in_one_gate(builder); + for (const auto& elem : variables_in_on_gate) { + bool result1 = check_in_byte_array(elem, input); + bool result2 = check_in_byte_array(elem, output_bits); + bool result3 = check_in_range_lists(elem, 3, builder); + bool check = (result1 == 1) || (result2 == 1) || (result3 == 1); + if (check == false) { + info("elem == ", elem); + info(result1); + info(result2); + info(result3); + info(); + } + EXPECT_EQ(check, true); } } -TEST(ultra_circuit_constructor, test_boomerang_value_in_sha256) +TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_vector_one) { auto builder = Builder(); - std::array, 16> input; - for (size_t i = 0; i < 16; i++) { - auto variable = fr::random_element(); - auto var_slice = uint256_t(variable).slice(0, 32); - field_ct elt(witness_ct(&builder, fr(var_slice))); - builder.fix_witness(elt.witness_index, elt.get_value()); - input[i] = elt; + packed_byte_array_ct input(&builder, "abc"); + packed_byte_array_ct output_bits = stdlib::sha256(input); + + Graph graph = Graph(builder); + std::unordered_set variables_in_one_gate = graph.show_variables_in_one_gate(builder); + for (const auto& elem : variables_in_one_gate) { + bool result1 = check_in_byte_array(elem, input); + bool result2 = check_in_byte_array(elem, output_bits); + bool result3 = check_in_range_lists(elem, 3, builder); + bool check = (result1 == 1) || (result2 == 1) || (result3 == 1); + EXPECT_EQ(check, true); } - std::array, 64> w_ext = sha256_plookup::extend_witness(input); - bool result1 = CircuitChecker::check(builder); - EXPECT_EQ(result1, true); - while (true) { - auto change_variable = fr::random_element(); - auto change_var_slice = uint256_t(change_variable).slice(0, 32); - field_t change_elt(&builder, fr(change_var_slice)); - uint32_t variable_index = w_ext[62].witness_index; - if (builder.variables[builder.real_variable_index[variable_index]] != fr(change_var_slice)) { - builder.variables[builder.real_variable_index[variable_index]] = fr(change_var_slice); - bool result2 = CircuitChecker::check(builder); - EXPECT_EQ(result2, true); - break; +} + +TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_vector_two) +{ + auto builder = Builder(); + + packed_byte_array_ct input(&builder, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); + + packed_byte_array_ct output_bits = stdlib::sha256(input); + Graph graph = Graph(builder); + std::unordered_set variables_in_one_gate = graph.show_variables_in_one_gate(builder); + for (const auto& elem : variables_in_one_gate) { + bool result1 = check_in_byte_array(elem, input); + bool result2 = check_in_byte_array(elem, output_bits); + bool result3 = check_in_range_lists(elem, 3, builder); + bool check = (result1 == 1) || (result2 == 1) || (result3 == 1); + if (check == false) { + info("elem == ", elem); + info(result1); + info(result2); + info(result3); + info(); } + EXPECT_EQ(check, true); + } +} + +TEST(ultra_circuit_constructor, test_variable_gates_count_sha256_NIST_vector_three) +{ + auto builder = Builder(); + + // one byte, 0xbd + packed_byte_array_ct input(&builder, std::vector{ 0xbd }); + packed_byte_array_ct output_bits = stdlib::sha256(input); + Graph graph = Graph(builder); + std::unordered_set variables_in_one_gate = graph.show_variables_in_one_gate(builder); + for (const auto& elem : variables_in_one_gate) { + bool result1 = check_in_byte_array(elem, input); + bool result2 = check_in_byte_array(elem, output_bits); + bool result3 = check_in_range_lists(elem, 3, builder); + bool check = (result1 == 1) || (result2 == 1) || (result3 == 1); + EXPECT_EQ(check, true); + } +} + +TEST(ultra_circuit_constructor, test_variable_gates_count_sha256_NIST_vector_four) +{ + auto builder = Builder(); + + // 4 bytes, 0xc98c8e55 + packed_byte_array_ct input(&builder, std::vector{ 0xc9, 0x8c, 0x8e, 0x55 }); + packed_byte_array_ct output_bits = stdlib::sha256(input); + Graph graph = Graph(builder); + std::unordered_set variables_in_one_gate = graph.show_variables_in_one_gate(builder); + for (const auto& elem : variables_in_one_gate) { + bool result1 = check_in_byte_array(elem, input); + bool result2 = check_in_byte_array(elem, output_bits); + bool result3 = check_in_range_lists(elem, 3, builder); + bool check = (result1 == 1) || (result2 == 1) || (result3 == 1); + EXPECT_EQ(check, true); } } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256_plookup.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256_plookup.cpp index 65cff037e952..e03367ebed0a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256_plookup.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256_plookup.cpp @@ -274,6 +274,7 @@ std::array, 8> sha256_block(const std::array, auto a = map_into_maj_sparse_form(h_init[0]); auto b = map_into_maj_sparse_form(h_init[1]); auto c = map_into_maj_sparse_form(h_init[2]); + // auto d = sparse_value(h_init[3]); auto d = map_into_maj_sparse_form(h_init[3]); auto e = map_into_choose_sparse_form(h_init[4]); auto f = map_into_choose_sparse_form(h_init[5]); From d9486f273736d28bcb03e4a0689ffe1a8c348c99 Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Wed, 2 Oct 2024 16:43:30 +0000 Subject: [PATCH 15/21] last commit --- .../boomerang_value_detection/graph.cpp | 6 +- .../variables_gate_counts.sha256.test.cpp | 72 +++++++++---------- .../stdlib/hash/sha256/sha256_plookup.cpp | 8 +-- 3 files changed, 44 insertions(+), 42 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp index 7ddef3a7e649..f8c8a97eb4f8 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -496,8 +496,10 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul if (id == bb::plookup::SHA256_WITNESS_SLICE_3 || id == bb::plookup::SHA256_WITNESS_SLICE_7_ROTATE_4 || id == bb::plookup::SHA256_WITNESS_SLICE_8_ROTATE_7 || id == bb::plookup::SHA256_WITNESS_SLICE_14_ROTATE_1 || id == bb::plookup::SHA256_BASE16_ROTATE2 || - id == bb::plookup::SHA256_BASE16 || id == bb::plookup::SHA256_BASE28_ROTATE6 || - id == bb::plookup::SHA256_BASE28_ROTATE3) { + id == bb::plookup::SHA256_BASE16 || id == bb::plookup::SHA256_BASE16_ROTATE6 || + id == bb::plookup::SHA256_BASE16_ROTATE7 || id == bb::plookup::SHA256_BASE16_ROTATE8 || + id == bb::plookup::SHA256_BASE28_ROTATE6 || id == bb::plookup::SHA256_BASE28_ROTATE3 || + id == bb::plookup::SHA256_BASE28) { uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp index ca23325f7228..973a05ebc641 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp @@ -73,42 +73,6 @@ TEST(ultra_circuit_constructor, test_variables_gate_counts_for_sha256_55_bytes) } } -HEAVY_TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_vector_five) -{ - auto builder = Builder(); - - packed_byte_array_ct input( - &builder, - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - "AAAAAAAAAA"); - - packed_byte_array_ct output_bits = stdlib::sha256(input); - Graph graph = Graph(builder); - std::unordered_set variables_in_on_gate = graph.show_variables_in_one_gate(builder); - for (const auto& elem : variables_in_on_gate) { - bool result1 = check_in_byte_array(elem, input); - bool result2 = check_in_byte_array(elem, output_bits); - bool result3 = check_in_range_lists(elem, 3, builder); - bool check = (result1 == 1) || (result2 == 1) || (result3 == 1); - if (check == false) { - info("elem == ", elem); - info(result1); - info(result2); - info(result3); - info(); - } - EXPECT_EQ(check, true); - } -} - TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_vector_one) { auto builder = Builder(); @@ -185,4 +149,40 @@ TEST(ultra_circuit_constructor, test_variable_gates_count_sha256_NIST_vector_fou bool check = (result1 == 1) || (result2 == 1) || (result3 == 1); EXPECT_EQ(check, true); } +} + +HEAVY_TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_vector_five) +{ + auto builder = Builder(); + + packed_byte_array_ct input( + &builder, + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAA"); + + packed_byte_array_ct output_bits = stdlib::sha256(input); + Graph graph = Graph(builder); + std::unordered_set variables_in_on_gate = graph.show_variables_in_one_gate(builder); + for (const auto& elem : variables_in_on_gate) { + bool result1 = check_in_byte_array(elem, input); + bool result2 = check_in_byte_array(elem, output_bits); + bool result3 = check_in_range_lists(elem, 3, builder); + bool check = (result1 == 1) || (result2 == 1) || (result3 == 1); + if (check == false) { + info("elem == ", elem); + info(result1); + info(result2); + info(result3); + info(); + } + EXPECT_EQ(check, true); + } } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256_plookup.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256_plookup.cpp index e03367ebed0a..4f25f514c01f 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256_plookup.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/sha256/sha256_plookup.cpp @@ -271,15 +271,15 @@ std::array, 8> sha256_block(const std::array, /** * Initialize round variables with previous block output **/ - auto a = map_into_maj_sparse_form(h_init[0]); + sparse_value a = sparse_value(h_init[0]); auto b = map_into_maj_sparse_form(h_init[1]); auto c = map_into_maj_sparse_form(h_init[2]); // auto d = sparse_value(h_init[3]); - auto d = map_into_maj_sparse_form(h_init[3]); - auto e = map_into_choose_sparse_form(h_init[4]); + sparse_value d = sparse_value(h_init[3]); + sparse_value e = sparse_value(h_init[4]); auto f = map_into_choose_sparse_form(h_init[5]); auto g = map_into_choose_sparse_form(h_init[6]); - auto h = map_into_choose_sparse_form(h_init[7]); + sparse_value h = sparse_value(h_init[7]); /** * Extend witness From 20eb663f1ba15bb5c931cb48dd24ba08ae840480 Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Wed, 9 Oct 2024 12:07:28 +0000 Subject: [PATCH 16/21] final version of UltraCircuit graph description for PR --- .../boomerang_value_detection/graph.cpp | 158 +++++++++++------- .../boomerang_value_detection/graph.hpp | 9 + .../graph_description.test.cpp | 141 +++------------- .../graph_description_aes128.test.cpp | 114 +++++++++++++ .../graph_description_blake2s.test.cpp | 6 - .../graph_description_blake3s.test.cpp | 4 - .../variable_gates_count.test.cpp | 52 ------ .../variables_gate_counts.sha256.test.cpp | 14 -- 8 files changed, 246 insertions(+), 252 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp index f8c8a97eb4f8..6aab73c99c52 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -2,6 +2,8 @@ #include #include +using namespace bb::plookup; +using namespace bb; template inline std::vector Graph_::get_arithmetic_gate_connected_component( bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) @@ -37,8 +39,6 @@ inline std::vector Graph_::get_arithmetic_gate_connected_component if (q_4 != 0) { gate_variables.emplace_back(fourth_idx); } - if (arithmetic_block.q_arith()[index] == 1 && q_m == 0) { - } if (arithmetic_block.q_arith()[index] == 2) { // We have to use w_4_shift from the next gate // if and only if the current gate isn't last, cause we can't @@ -452,6 +452,94 @@ inline void Graph_::remove_unnecessary_plookup_variables(bb::UltraCircuitBui } } +template +inline void Graph_::remove_unnecessary_aes_plookup_variables(std::unordered_set& variables_in_one_gate, + UltraCircuitBuilder& ultra_circuit_builder, + BasicTableId& table_id, + size_t gate_index) +{ + + auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; + auto find_position = [&](uint32_t variable_index) { + return variables_in_one_gate.contains(to_real(variable_index)); + }; + std::unordered_set aes_plookup_tables{ BasicTableId::AES_SBOX_MAP, + BasicTableId::AES_SPARSE_MAP, + BasicTableId::AES_SPARSE_NORMALIZE }; + auto& lookup_block = ultra_circuit_builder.blocks.lookup; + if (aes_plookup_tables.contains(table_id)) { + uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); + uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); + if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { + bool find_out = find_position(real_out_idx); + bool find_right = find_position(real_right_idx); + auto q_m = lookup_block.q_m()[gate_index]; + auto q_c = lookup_block.q_c()[gate_index]; + if (q_c == 0) { + if (find_out) { + variables_in_one_gate.erase(real_out_idx); + } + } + if (q_m == 0) { + if (find_right) { + variables_in_one_gate.erase(real_right_idx); + } + } + } + } +} + +template +inline void Graph_::remove_unnecessary_sha256_plookup_variables(std::unordered_set& variables_in_one_gate, + UltraCircuitBuilder& ultra_circuit_builder, + BasicTableId& table_id, + size_t gate_index) +{ + + auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; + auto find_position = [&](uint32_t variable_index) { + return variables_in_one_gate.contains(to_real(variable_index)); + }; + auto& lookup_block = ultra_circuit_builder.blocks.lookup; + std::unordered_set sha256_plookup_tables{ BasicTableId::SHA256_WITNESS_SLICE_3, + BasicTableId::SHA256_WITNESS_SLICE_7_ROTATE_4, + BasicTableId::SHA256_WITNESS_SLICE_8_ROTATE_7, + BasicTableId::SHA256_WITNESS_SLICE_14_ROTATE_1, + BasicTableId::SHA256_BASE16, + BasicTableId::SHA256_BASE16_ROTATE2, + BasicTableId::SHA256_BASE16_ROTATE6, + BasicTableId::SHA256_BASE16_ROTATE7, + BasicTableId::SHA256_BASE16_ROTATE8, + BasicTableId::SHA256_BASE28, + BasicTableId::SHA256_BASE28_ROTATE3, + BasicTableId::SHA256_BASE28_ROTATE6 }; + if (sha256_plookup_tables.contains(table_id)) { + uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); + uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); + if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { + auto q_m = lookup_block.q_m()[gate_index]; + auto q_c = lookup_block.q_c()[gate_index]; + bool find_out = find_position(real_out_idx); + bool find_right = find_position(real_right_idx); + if (q_c == 0) { + if (find_out) { + variables_in_one_gate.erase(real_out_idx); + } + } + if (q_m == 0) { + if (find_right) { + variables_in_one_gate.erase(real_right_idx); + } + } + if (table_id == SHA256_BASE16_ROTATE2 || table_id == SHA256_BASE28_ROTATE6) { + // we want to remove false cases for special tables even though their selectors != 0 + // because it's from_1_to_2_table cases, and they aren't dangerous + variables_in_one_gate.erase(real_out_idx); + } + } + } +} + template inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ultra_circuit_builder, std::unordered_set& variables_in_one_gate, @@ -469,65 +557,15 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul std::set column_1(table.column_1.begin(), table.column_1.end()); std::set column_2(table.column_2.begin(), table.column_2.end()); std::set column_3(table.column_3.begin(), table.column_3.end()); - bb::plookup::BasicTableId id = table.id; - // in some table we don't use variables from third column. So, these variables are false-case for a - // analyzer, and we have to remove them false cases for AES - if (id == bb::plookup::AES_SBOX_MAP || id == bb::plookup::AES_SPARSE_MAP) { - uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); - uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); - if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { - bool find_out = find_position(real_out_idx); - bool find_right = find_position(real_right_idx); - auto q_m = lookup_block.q_m()[gate_index]; - auto q_c = lookup_block.q_c()[gate_index]; - if (q_c == 0) { - if (find_out) { - variables_in_one_gate.erase(real_out_idx); - } - } - if (q_m == 0) { - if (find_right) { - variables_in_one_gate.erase(real_right_idx); - } - } - } - } + bb::plookup::BasicTableId table_id = table.id; + // in some tables we don't use variables from third column. So, these variables are false-case for a + // analyzer, and we have to remove them + // false cases for AES + remove_unnecessary_aes_plookup_variables( + variables_in_one_gate, ultra_circuit_builder, table_id, gate_index); // false cases for sha256 - if (id == bb::plookup::SHA256_WITNESS_SLICE_3 || id == bb::plookup::SHA256_WITNESS_SLICE_7_ROTATE_4 || - id == bb::plookup::SHA256_WITNESS_SLICE_8_ROTATE_7 || - id == bb::plookup::SHA256_WITNESS_SLICE_14_ROTATE_1 || id == bb::plookup::SHA256_BASE16_ROTATE2 || - id == bb::plookup::SHA256_BASE16 || id == bb::plookup::SHA256_BASE16_ROTATE6 || - id == bb::plookup::SHA256_BASE16_ROTATE7 || id == bb::plookup::SHA256_BASE16_ROTATE8 || - id == bb::plookup::SHA256_BASE28_ROTATE6 || id == bb::plookup::SHA256_BASE28_ROTATE3 || - id == bb::plookup::SHA256_BASE28) { - uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); - uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); - if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { - auto q_m = lookup_block.q_m()[gate_index]; - auto q_c = lookup_block.q_c()[gate_index]; - bool find_out = find_position(real_out_idx); - bool find_right = find_position(real_right_idx); - if (real_out_idx == 1504) { - info("it's selector == ", q_m); - } - if (q_c == 0) { - if (find_out) { - variables_in_one_gate.erase(real_out_idx); - } - } - if (q_m == 0) { - if (find_right) { - variables_in_one_gate.erase(real_right_idx); - } - } - } else { - info("gates_count: ", - variables_gate_counts[real_out_idx], - " ", - variables_gate_counts[real_right_idx]); - info("variable indices: ", real_right_idx, " ", real_out_idx); - } - } + remove_unnecessary_sha256_plookup_variables( + variables_in_one_gate, ultra_circuit_builder, table_id, gate_index); if (column_1.size() == 1) { uint32_t left_idx = lookup_block.w_l()[gate_index]; uint32_t real_left_idx = to_real(left_idx); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp index 26b63fbeebce..dd5e08844ad7 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp @@ -73,6 +73,15 @@ template class Graph_ { std::unordered_set& variables_in_on_gate); std::unordered_set show_variables_in_one_gate(bb::UltraCircuitBuilder& ultra_circuit_builder); + void remove_unnecessary_aes_plookup_variables(std::unordered_set& variables_in_one_gate, + bb::UltraCircuitBuilder& ultra_circuit_builder, + bb::plookup::BasicTableId& table_id, + size_t gate_index); + void remove_unnecessary_sha256_plookup_variables(std::unordered_set& variables_in_one_gate, + bb::UltraCircuitBuilder& ultra_circuit_builder, + bb::plookup::BasicTableId& table_id, + size_t gate_index); + void print_graph(); void print_connected_components(); void print_variables_gate_counts(); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp index 19db97ddcf82..76e18673b362 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp @@ -36,7 +36,7 @@ TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates) Graph graph = Graph(circuit_constructor); auto connected_components = graph.find_connected_components(); auto num_connected_components = connected_components.size(); - info("number of connected components == ", num_connected_components); + auto variables_in_one_gate = graph.show_variables_in_one_gate(circuit_constructor); bool result = num_connected_components == 256; EXPECT_EQ(result, true); } @@ -62,17 +62,15 @@ TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates_with_shifts) Graph graph = Graph(circuit_constructor); auto connected_components = graph.find_connected_components(); auto num_connected_components = connected_components.size(); - info("number of the connected components == ", num_connected_components); bool result = num_connected_components == 1; EXPECT_EQ(result, true); - graph.print_connected_components(); } TEST(ultra_circuit_constructor, test_graph_for_boolean_gates) { // this test checks graph description for the circuit with boolean gates. - // all variables must be isolated and the number of connected components = 20 - // number of the variables in the circuit + // all variables must be isolated and the number of connected components = 0 + // and variables in one gate = 20. UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); for (size_t i = 0; i < 20; ++i) { @@ -84,10 +82,10 @@ TEST(ultra_circuit_constructor, test_graph_for_boolean_gates) Graph graph = Graph(circuit_constructor); auto connected_components = graph.find_connected_components(); auto num_connected_components = connected_components.size(); - info("number of the connected components == ", num_connected_components); - bool result = num_connected_components == 20; + auto variables_in_one_gate = graph.show_variables_in_one_gate(circuit_constructor); + bool result = num_connected_components == 0; EXPECT_EQ(result, true); - graph.print_connected_components(); + EXPECT_EQ(variables_in_one_gate.size(), 20); } TEST(ultra_circuit_constructor, test_graph_for_elliptic_add_gate) @@ -118,7 +116,6 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_add_gate) auto num_connected_components = connected_components.size(); bool result = num_connected_components == 1; EXPECT_EQ(result, true); - graph.print_connected_components(); } TEST(ultra_circuit_constructor, test_graph_for_elliptic_double_gate) @@ -137,7 +134,6 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_double_gate) uint32_t y1 = circuit_constructor.add_variable(p1.y); uint32_t x3 = circuit_constructor.add_variable(p3.x); uint32_t y3 = circuit_constructor.add_variable(p3.y); - info("string from the test: x1, y1, x3, y3 == ", x1, " ", y1, " ", x3, " ", y3); circuit_constructor.create_ecc_dbl_gate({ x1, y1, x3, y3 }); @@ -146,7 +142,6 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_double_gate) auto num_connected_components = connected_components.size(); bool result = num_connected_components == 1; EXPECT_EQ(result, true); - graph.print_connected_components(); } TEST(ultra_circuit_constructor, test_graph_for_elliptic_together) @@ -194,11 +189,8 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_together) uint32_t y8 = circuit_constructor.add_variable(p8.y); circuit_constructor.create_ecc_dbl_gate({ x7, y7, x8, y8 }); - info("number of elliptic gates = ", circuit_constructor.blocks.elliptic.size()); Graph graph = Graph(circuit_constructor); auto connected_components = graph.find_connected_components(); - info("size of the first connected component == ", connected_components[0].size()); - info("size of the second connected component == ", connected_components[1].size()); auto num_connected_components = connected_components.size(); bool result = num_connected_components == 2; EXPECT_EQ(result, true); @@ -233,12 +225,9 @@ TEST(ultra_circuit_constructor, test_graph_for_sort_constraints) Graph graph = Graph(circuit_constructor); auto connected_components = graph.find_connected_components(); - info("size of the first connected component == ", connected_components[0].size()); - info("size of the second connected component == ", connected_components[1].size()); - auto num_connected_components = connected_components.size(); - bool result = num_connected_components == 2; - EXPECT_EQ(result, true); - // graph.print_connected_components(); + EXPECT_EQ(connected_components[0].size(), 4); + EXPECT_EQ(connected_components[1].size(), 4); + EXPECT_EQ(connected_components.size(), 2); } TEST(ultra_circuit_constructor, test_graph_for_sort_constraints_with_edges) @@ -293,7 +282,6 @@ TEST(ultra_circuit_constructor, test_graph_for_sort_constraints_with_edges) auto num_connected_components = connected_components.size(); bool result = num_connected_components == 2; EXPECT_EQ(result, true); - graph.print_connected_components(); } TEST(ultra_circuit_constructor, test_graph_with_plookup_accumulators) @@ -320,66 +308,6 @@ TEST(ultra_circuit_constructor, test_graph_with_plookup_accumulators) auto num_connected_components = connected_components.size(); bool result = num_connected_components == 1; EXPECT_EQ(result, true); - graph.print_connected_components(); -} - -TEST(ultra_circuit_constructor, test_graph_for_aes_64_bytes) -{ - typedef stdlib::field_t field_pt; - typedef stdlib::witness_t witness_pt; - - uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; - uint8_t out[64]{ 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, - 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, - 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, - 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 }; - uint8_t iv[16]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; - uint8_t in[64]{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; - - const auto convert_bytes = [](uint8_t* data) { - uint256_t converted(0); - for (uint64_t i = 0; i < 16; ++i) { - uint256_t to_add = uint256_t((uint64_t)(data[i])) << uint256_t((15 - i) * 8); - converted += to_add; - } - return converted; - }; - - auto builder = UltraCircuitBuilder(); - - std::vector in_field{ - witness_pt(&builder, fr(convert_bytes(in))), - witness_pt(&builder, fr(convert_bytes(in + 16))), - witness_pt(&builder, fr(convert_bytes(in + 32))), - witness_pt(&builder, fr(convert_bytes(in + 48))), - }; - - field_pt key_field(witness_pt(&builder, fr(convert_bytes(key)))); - field_pt iv_field(witness_pt(&builder, fr(convert_bytes(iv)))); - - std::vector expected{ - convert_bytes(out), convert_bytes(out + 16), convert_bytes(out + 32), convert_bytes(out + 48) - }; - - const auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field); - - for (size_t i = 0; i < 4; ++i) { - EXPECT_EQ(result[i].get_value(), expected[i]); - } - - Graph graph = Graph(builder); - auto connected_components = graph.find_connected_components(); - auto num_connected_components = connected_components.size(); - bool graph_result = num_connected_components == 1; - EXPECT_EQ(graph_result, true); - std::cout << "num gates = " << builder.get_num_gates() << std::endl; - std::cout << "number of arithmetic gates = " << builder.blocks.arithmetic.size() << std::endl; - std::cout << "number of sorted gates = " << builder.blocks.delta_range.size() << std::endl; - std::cout << "number of plookup gates = " << builder.blocks.lookup.size() << std::endl; - std::cout << "number of elliptic gates = " << builder.blocks.elliptic.size() << std::endl; } TEST(ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate) @@ -456,10 +384,9 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_boolean_gates) auto variables_gate_counts = graph.get_variables_gate_counts(); bool result = true; for (const auto& part : variables_gate_counts) { - info(part.first, " ", part.second); - result = result && (part.first == 0 ? (part.second == 0) : (part.first == 1)); + result = result && (part.first == 0 ? (part.second == 0) : (part.second == 1)); } - // EXPECT_EQ(result, true); + EXPECT_EQ(result, true); } TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constraints) @@ -491,22 +418,11 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constrain auto connected_components = graph.find_connected_components(); bool result = true; for (size_t i = 0; i < connected_components[0].size(); i++) { - result = result && - (i == connected_components[0].size() - 1 ? variables_gate_counts[connected_components[0][i]] == 2 - : variables_gate_counts[connected_components[0][i]] == 1); - /* info("result == ", result); - info(i, " ", connected_components[0][i], " ", variables_gate_counts[connected_components[0][i]]); */ + result = result && (variables_gate_counts[connected_components[0][i]] == 1); } for (size_t i = 0; i < connected_components[1].size(); i++) { - result = result && - (i == connected_components[1].size() - 1 ? variables_gate_counts[connected_components[1][i]] == 2 - : variables_gate_counts[connected_components[1][i]] == 1); - /* info("result == ", result); - info(i, " ", connected_components[1][i], " ", variables_gate_counts[connected_components[1][i]]); */ - } - for (const auto& pair : variables_gate_counts) { - info(pair.first, " ", pair.second); + result = result && (variables_gate_counts[connected_components[1][i]] == 1); } EXPECT_EQ(result, true); } @@ -557,19 +473,15 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constrain Graph graph = Graph(circuit_constructor); auto connected_components = graph.find_connected_components(); auto variables_gate_counts = graph.get_variables_gate_counts(); - // graph.print_connected_components(); bool result = true; for (size_t i = 0; i < connected_components[0].size(); i++) { - result = result && - (i == connected_components[0].size() - 1 ? variables_gate_counts[connected_components[0][i]] == 2 - : variables_gate_counts[connected_components[0][i]] == 1); + result = result && (variables_gate_counts[connected_components[0][i]] == 1); } for (size_t i = 0; i < connected_components[1].size(); i++) { - result = result && - (i == connected_components[1].size() - 1 ? variables_gate_counts[connected_components[1][i]] == 2 - : variables_gate_counts[connected_components[1][i]] == 1); + result = result && (variables_gate_counts[connected_components[1][i]] == 1); } + EXPECT_EQ(connected_components.size(), 2); EXPECT_EQ(result, true); } @@ -598,10 +510,11 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_ecc_add_gates) auto connected_components = graph.find_connected_components(); bool result = (variables_gate_counts[connected_components[0][0]] == 1) && (variables_gate_counts[connected_components[0][1]] == 1) && - (variables_gate_counts[connected_components[0][2]] == 2) && - (variables_gate_counts[connected_components[0][3]] == 2) && - (variables_gate_counts[connected_components[0][4]] == 2) && - (variables_gate_counts[connected_components[0][5]] == 2); + (variables_gate_counts[connected_components[0][2]] == 1) && + (variables_gate_counts[connected_components[0][3]] == 1) && + (variables_gate_counts[connected_components[0][4]] == 1) && + (variables_gate_counts[connected_components[0][5]] == 1); + EXPECT_EQ(connected_components.size(), 1); EXPECT_EQ(result, true); } @@ -618,22 +531,19 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_ecc_dbl_gate) uint32_t y1 = circuit_constructor.add_variable(p1.y); uint32_t x3 = circuit_constructor.add_variable(p3.x); uint32_t y3 = circuit_constructor.add_variable(p3.y); - // info("string from the test: x1, y1, x3, y3 == ", x1, " ", y1, " ", x3, " ", y3); circuit_constructor.create_ecc_dbl_gate({ x1, y1, x3, y3 }); Graph graph = Graph(circuit_constructor); - auto connected_components = graph.find_connected_components(); auto variables_gate_counts = graph.get_variables_gate_counts(); + auto connected_components = graph.find_connected_components(); bool result = (variables_gate_counts[connected_components[0][0]] == 1) && (variables_gate_counts[connected_components[0][1]] == 1) && - (variables_gate_counts[connected_components[0][2]] == 2) && - (variables_gate_counts[connected_components[0][3]] == 2); + (variables_gate_counts[connected_components[0][2]] == 1) && + (variables_gate_counts[connected_components[0][3]] == 1); - for (const auto& pair : variables_gate_counts) { - info(pair.first, " ", pair.second); - } + EXPECT_EQ(connected_components.size(), 1); EXPECT_EQ(result, true); } @@ -653,7 +563,6 @@ TEST(ultra_circuit_constructor, test_graph_for_range_constraints) for (size_t i = 0; i < indices.size(); i++) { circuit_constructor.create_new_range_constraint(indices[i], 5); } - // auto ind = {a_idx,b_idx,c_idx,d_idx,e_idx,f_idx,g_idx,h_idx}; circuit_constructor.create_sort_constraint(indices); Graph graph = Graph(circuit_constructor); auto connected_components = graph.find_connected_components(); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp new file mode 100644 index 000000000000..126ef3c5c175 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp @@ -0,0 +1,114 @@ +#include "barretenberg/boomerang_value_detection/graph.hpp" +#include "barretenberg/common/test.hpp" +#include "barretenberg/crypto/aes128/aes128.hpp" +#include "barretenberg/crypto/generators/generator_data.hpp" +#include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" +#include "barretenberg/stdlib/encryption/aes128/aes128.hpp" +#include "barretenberg/stdlib_circuit_builders/mock_circuits.hpp" +#include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" + +#include + +using namespace bb; +using namespace bb::stdlib; + +using Builder = UltraCircuitBuilder; +typedef stdlib::field_t field_pt; +typedef stdlib::witness_t witness_pt; + +bool check_in_vector(const std::vector& input_vector, const uint32_t& real_var_index) +{ + for (const auto& elem : input_vector) { + if (elem.witness_index == real_var_index) { + return true; + } + } + return false; +} + +TEST(ultra_circuit_constructor, test_graph_for_aes_64_bytes) +{ + uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; + uint8_t iv[16]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; + uint8_t in[64]{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; + + const auto convert_bytes = [](uint8_t* data) { + uint256_t converted(0); + for (uint64_t i = 0; i < 16; ++i) { + uint256_t to_add = uint256_t((uint64_t)(data[i])) << uint256_t((15 - i) * 8); + converted += to_add; + } + return converted; + }; + + auto builder = Builder(); + + std::vector in_field{ + witness_pt(&builder, fr(convert_bytes(in))), + witness_pt(&builder, fr(convert_bytes(in + 16))), + witness_pt(&builder, fr(convert_bytes(in + 32))), + witness_pt(&builder, fr(convert_bytes(in + 48))), + }; + + field_pt key_field(witness_pt(&builder, fr(convert_bytes(key)))); + field_pt iv_field(witness_pt(&builder, fr(convert_bytes(iv)))); + + const auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field); + + Graph graph = Graph(builder); + auto connected_components = graph.find_connected_components(); + auto num_connected_components = connected_components.size(); + bool graph_result = num_connected_components == 1; + EXPECT_EQ(graph_result, true); +} + +TEST(ultra_circuit_constructor, test_variable_gates_count_for_aes128cbc) +{ + + uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; + uint8_t iv[16]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; + uint8_t in[64]{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; + + const auto convert_bytes = [](uint8_t* data) { + uint256_t converted(0); + for (uint64_t i = 0; i < 16; ++i) { + uint256_t to_add = uint256_t((uint64_t)(data[i])) << uint256_t((15 - i) * 8); + converted += to_add; + } + return converted; + }; + + auto builder = Builder(); + + std::vector in_field{ + witness_pt(&builder, fr(convert_bytes(in))), + witness_pt(&builder, fr(convert_bytes(in + 16))), + witness_pt(&builder, fr(convert_bytes(in + 32))), + witness_pt(&builder, fr(convert_bytes(in + 48))), + }; + + field_pt key_field(witness_pt(&builder, fr(convert_bytes(key)))); + field_pt iv_field(witness_pt(&builder, fr(convert_bytes(iv)))); + + const auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field); + + Graph graph = Graph(builder); + std::unordered_set variables_in_one_gate = graph.show_variables_in_one_gate(builder); + for (const auto& elem : variables_in_one_gate) { + bool result1 = check_in_vector(in_field, elem); + bool result2 = check_in_vector(result, elem); + bool check = + (result1 == 1) || (result2 == 1) || (elem == key_field.witness_index) || (elem == iv_field.witness_index); + if (check == false) { + info("elem == ", elem); + } + EXPECT_EQ(check, true); + } +} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp index c794b1ae1956..099c8b58fa97 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp @@ -28,12 +28,6 @@ TEST(ultra_circuit_constructor, test_graph_for_blake2s_single_block_plookup) byte_array_plookup input_arr(&builder, input_v); byte_array_plookup output = blake2s(input_arr); - auto expected = crypto::blake2s(input_v); - - EXPECT_EQ(output.get_value(), std::vector(expected.begin(), expected.end())); - - info("builder gates = ", builder.get_num_gates()); - Graph graph = Graph(builder); auto connected_components = graph.find_connected_components(); EXPECT_EQ(connected_components.size(), 1); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp index 9b54e81c573c..dcffb6029529 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp @@ -29,8 +29,6 @@ TEST(stdlib_blake3s, test_single_block_plookup) EXPECT_EQ(output.get_value(), expected); - info("builder gates = ", builder.get_num_gates()); - Graph graph = Graph(builder); auto connected_components = graph.find_connected_components(); EXPECT_EQ(connected_components.size(), 1); @@ -49,8 +47,6 @@ TEST(stdlib_blake3s, test_double_block_plookup) EXPECT_EQ(output.get_value(), expected); - info("builder gates = ", builder.get_num_gates()); - Graph graph = Graph(builder); auto connected_components = graph.find_connected_components(); EXPECT_EQ(connected_components.size(), 1); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variable_gates_count.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variable_gates_count.test.cpp index 91aaee1adf8c..9b989350cb5f 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variable_gates_count.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variable_gates_count.test.cpp @@ -1,12 +1,10 @@ #include "barretenberg/boomerang_value_detection/graph.hpp" -#include "barretenberg/circuit_checker/circuit_checker.hpp" #include "barretenberg/crypto/aes128/aes128.hpp" #include "barretenberg/crypto/generators/generator_data.hpp" #include "barretenberg/crypto/pedersen_commitment/pedersen.hpp" #include "barretenberg/stdlib/encryption/aes128/aes128.hpp" #include "barretenberg/stdlib_circuit_builders/mock_circuits.hpp" #include "barretenberg/stdlib_circuit_builders/plookup_tables/fixed_base/fixed_base.hpp" -#include "barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" #include @@ -130,53 +128,3 @@ TEST(ultra_circuit_constructor, test_decompose_for_6_bit_number) std::unordered_set variables_in_on_gate = graph.show_variables_in_one_gate(circuit_constructor); EXPECT_EQ(variables_in_on_gate.size(), 1); } - -TEST(ultra_circuit_constructor, test_decompose_for_aes_64bytes) -{ - typedef stdlib::field_t field_pt; - typedef stdlib::witness_t witness_pt; - - uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; - uint8_t out[64]{ 0x76, 0x49, 0xab, 0xac, 0x81, 0x19, 0xb2, 0x46, 0xce, 0xe9, 0x8e, 0x9b, 0x12, 0xe9, 0x19, 0x7d, - 0x50, 0x86, 0xcb, 0x9b, 0x50, 0x72, 0x19, 0xee, 0x95, 0xdb, 0x11, 0x3a, 0x91, 0x76, 0x78, 0xb2, - 0x73, 0xbe, 0xd6, 0xb8, 0xe3, 0xc1, 0x74, 0x3b, 0x71, 0x16, 0xe6, 0x9e, 0x22, 0x22, 0x95, 0x16, - 0x3f, 0xf1, 0xca, 0xa1, 0x68, 0x1f, 0xac, 0x09, 0x12, 0x0e, 0xca, 0x30, 0x75, 0x86, 0xe1, 0xa7 }; - uint8_t iv[16]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; - uint8_t in[64]{ 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, - 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, - 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, - 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }; - const auto convert_bytes = [](uint8_t* data) { - uint256_t converted(0); - for (uint64_t i = 0; i < 16; ++i) { - uint256_t to_add = uint256_t((uint64_t)(data[i])) << uint256_t((15 - i) * 8); - converted += to_add; - } - return converted; - }; - auto builder = UltraCircuitBuilder(); - std::vector in_field{ - witness_pt(&builder, fr(convert_bytes(in))), - witness_pt(&builder, fr(convert_bytes(in + 16))), - witness_pt(&builder, fr(convert_bytes(in + 32))), - witness_pt(&builder, fr(convert_bytes(in + 48))), - }; - field_pt key_field(witness_pt(&builder, fr(convert_bytes(key)))); - field_pt iv_field(witness_pt(&builder, fr(convert_bytes(iv)))); - - std::vector expected{ - convert_bytes(out), convert_bytes(out + 16), convert_bytes(out + 32), convert_bytes(out + 48) - }; - - const auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field); - - for (size_t i = 0; i < 4; ++i) { - EXPECT_EQ(result[i].get_value(), expected[i]); - } - - Graph graph = Graph(builder); - std::unordered_set variables_in_on_gate = graph.show_variables_in_one_gate(builder); - for (const auto& elem : variables_in_on_gate) { - info("elem == ", elem); - } -} \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp index 973a05ebc641..b28fd0b6d004 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp @@ -104,13 +104,6 @@ TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_vector bool result2 = check_in_byte_array(elem, output_bits); bool result3 = check_in_range_lists(elem, 3, builder); bool check = (result1 == 1) || (result2 == 1) || (result3 == 1); - if (check == false) { - info("elem == ", elem); - info(result1); - info(result2); - info(result3); - info(); - } EXPECT_EQ(check, true); } } @@ -176,13 +169,6 @@ HEAVY_TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_ bool result2 = check_in_byte_array(elem, output_bits); bool result3 = check_in_range_lists(elem, 3, builder); bool check = (result1 == 1) || (result2 == 1) || (result3 == 1); - if (check == false) { - info("elem == ", elem); - info(result1); - info(result2); - info(result3); - info(); - } EXPECT_EQ(check, true); } } \ No newline at end of file From ad369c87f85139d194454cc4ae5d02e3061deafd Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Mon, 21 Oct 2024 14:35:34 +0000 Subject: [PATCH 17/21] add commentaries for every class methods, data sturctures and tests + some naming changes --- .../boomerang_value_detection/graph.cpp | 238 ++++++++++++++---- .../boomerang_value_detection/graph.hpp | 15 +- .../graph_description.test.cpp | 122 +++++++-- .../graph_description_aes128.test.cpp | 14 +- .../graph_description_blake2s.test.cpp | 5 + .../graph_description_blake3s.test.cpp | 5 + .../graph_description_sha256.test.cpp | 4 + .../variables_gate_counts.sha256.test.cpp | 6 + 8 files changed, 335 insertions(+), 74 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp index 6aab73c99c52..503ad58cf761 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -4,11 +4,19 @@ using namespace bb::plookup; using namespace bb; + +/** + * @brief this method implements connected components from arithmetic gates + * @tparam FF + * @param ultra_circuit_builder + * @param index + * @return std::vector + */ + template inline std::vector Graph_::get_arithmetic_gate_connected_component( bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) { - auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; auto& arithmetic_block = ultra_circuit_builder.blocks.arithmetic; uint32_t left_idx = arithmetic_block.w_l()[index]; uint32_t right_idx = arithmetic_block.w_r()[index]; @@ -49,10 +57,11 @@ inline std::vector Graph_::get_arithmetic_gate_connected_component } } if (arithmetic_block.q_arith()[index] == 3) { - info("q_arith == 3 isn't implemented yet"); + info("TODO"); } } } + auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end()); gate_variables.erase(unique_variables, gate_variables.end()); std::transform(gate_variables.cbegin(), gate_variables.cend(), gate_variables.begin(), to_real); @@ -64,6 +73,14 @@ inline std::vector Graph_::get_arithmetic_gate_connected_component return gate_variables; } +/** + * @brief this method creates connected components from elliptic gates + * @tparam FF + * @param ultra_circuit_builder + * @param index + * @return std::vector + */ + template inline std::vector Graph_::get_elliptic_gate_connected_component( bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) @@ -105,11 +122,19 @@ inline std::vector Graph_::get_elliptic_gate_connected_component( return gate_variables; } +/** + * @brief this method creates connected components from sorted constraints + * + * @tparam FF + * @param ultra_circuit_builder + * @param index + * @return std::vector + */ + template inline std::vector Graph_::get_sort_constraint_connected_component( bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) { - auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; auto& delta_range_block = ultra_circuit_builder.blocks.delta_range; std::vector gate_variables = {}; if (delta_range_block.q_delta_range()[index] == 1) { @@ -121,6 +146,7 @@ inline std::vector Graph_::get_sort_constraint_connected_component } auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end()); gate_variables.erase(unique_variables, gate_variables.end()); + auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; std::transform(gate_variables.cbegin(), gate_variables.cend(), gate_variables.begin(), to_real); if (!gate_variables.empty()) { for (const auto& real_variable_index : gate_variables) { @@ -130,6 +156,15 @@ inline std::vector Graph_::get_sort_constraint_connected_component return gate_variables; } +/** + * @brief this method creates connected_components from plookup gates + * + * @tparam FF + * @param ultra_circuit_builder + * @param index + * @return std::vector + */ + template inline std::vector Graph_::get_plookup_gate_connected_component( bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) @@ -170,6 +205,13 @@ inline std::vector Graph_::get_plookup_gate_connected_component( return variable_indices; } +/** + * @brief Construct a new Graph from Ultra_Circuit_Builder + * + * @tparam FF + * @param ultra_circuit_constructor + */ + template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit_constructor) { this->variables_gate_counts = @@ -185,19 +227,19 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit std::map constant_variable_indices = ultra_circuit_constructor.constant_variable_indices; const auto& arithmetic_block = ultra_circuit_constructor.blocks.arithmetic; - auto arithmetic_gate_numbers = arithmetic_block.size(); - bool arithmetic_gate_exists = arithmetic_gate_numbers > 0; - if (arithmetic_gate_exists) { - for (size_t i = 0; i < arithmetic_gate_numbers; i++) { + auto arithmetic_gates_numbers = arithmetic_block.size(); + bool arithmetic_gates_exists = arithmetic_gates_numbers > 0; + if (arithmetic_gates_exists) { + for (size_t i = 0; i < arithmetic_gates_numbers; i++) { auto gate_variables = get_arithmetic_gate_connected_component(ultra_circuit_constructor, i); connect_all_variables_in_vector(ultra_circuit_constructor, gate_variables, false); } } const auto& elliptic_block = ultra_circuit_constructor.blocks.elliptic; - auto elliptic_gate_numbers = elliptic_block.size(); - bool elliptic_gates_exist = elliptic_gate_numbers > 0; + auto elliptic_gates_numbers = elliptic_block.size(); + bool elliptic_gates_exist = elliptic_gates_numbers > 0; if (elliptic_gates_exist) { - for (size_t i = 0; i < elliptic_gate_numbers; i++) { + for (size_t i = 0; i < elliptic_gates_numbers; i++) { std::vector gate_variables = get_elliptic_gate_connected_component(ultra_circuit_constructor, i); connect_all_variables_in_vector(ultra_circuit_constructor, gate_variables, false); } @@ -229,12 +271,20 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit } } +/** + * @brief this method checks that variable with given index is not constant + * + * @tparam FF + * @param ultra_circuit_builder + * @param variable_index + * @return true + * @return false + */ + template bool Graph_::check_is_not_constant_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, const uint32_t& variable_index) { - // this method checks that variable is not constant, so it's not in constant_variable_indices from ultra circuit - // builder bool is_not_constant = true; auto constant_variable_indices = ultra_circuit_builder.constant_variable_indices; for (const auto& pair : constant_variable_indices) { @@ -246,14 +296,21 @@ bool Graph_::check_is_not_constant_variable(bb::UltraCircuitBuilder& ultra_c return is_not_constant; } +/** + * @brief this method connects between each other variables that have different indexes, if their indexes are not equal + * zero_idx and they are not constant variables, so they are not in constant_variable_indices from ultra circuit + * builder data structure + * @tparam FF + * @param ultra_circuit_builder + * @param variables_vector + * @param is_sorted_variables + */ + template void Graph_::connect_all_variables_in_vector(bb::UltraCircuitBuilder& ultra_circuit_builder, const std::vector& variables_vector, bool is_sorted_variables) { - // this method connects between each other variables that have different indexes, their indexes are not equal - // zero_idx and they are not constant variables, so they are not in constant_variable_indices from ultra circuit - // builder data structure if (!variables_vector.empty()) { if (is_sorted_variables) { for (size_t i = 0; i < variables_vector.size() - 1; i++) { @@ -273,7 +330,7 @@ void Graph_::connect_all_variables_in_vector(bb::UltraCircuitBuilder& ultra_ } } else { for (size_t i = 0; i < variables_vector.size() - 1; i++) { - for (size_t j = 1; j < variables_vector.size(); j++) { + for (size_t j = i + 1; j < variables_vector.size(); j++) { if (variables_vector[i] != ultra_circuit_builder.zero_idx && variables_vector[j] != ultra_circuit_builder.zero_idx && variables_vector[i] != variables_vector[j]) { @@ -292,6 +349,13 @@ void Graph_::connect_all_variables_in_vector(bb::UltraCircuitBuilder& ultra_ } } +/** + * @brief this method creates an edge between two variables in graph. All needed checks in a function above + * @tparam FF + * @param first_variable_index + * @param second_variable_index + */ + template void Graph_::add_new_edge(const uint32_t& first_variable_index, const uint32_t& second_variable_index) { @@ -301,17 +365,19 @@ void Graph_::add_new_edge(const uint32_t& first_variable_index, const uint32 variables_degree[second_variable_index] += 1; } -template std::vector Graph_::get_variable_adjacency_list(const uint32_t& variable_index) -{ - return variable_adjacency_lists[variable_index]; -} +/** + * @brief this method implements algorithm depth first search for undirected graph + * @tparam FF + * @param variable_index + * @param is_used + * @param connected_component + */ template void Graph_::depth_first_search(const uint32_t& variable_index, std::unordered_set& is_used, std::vector& connected_component) { - // this method realizes algorithm depth_first_search for undirected graph using the give variable std::stack variable_stack; variable_stack.push(variable_index); while (!variable_stack.empty()) { @@ -327,9 +393,14 @@ void Graph_::depth_first_search(const uint32_t& variable_index, } } +/** + * @brief this methond finds connected components from the graph described by adjacency lists + * @tparam FF + * @return std::vector> + */ + template std::vector> Graph_::find_connected_components() { - // this methond finds connected components from the graph described by adjacency lists std::unordered_set is_used; std::vector> connected_components; for (const auto& pair : variable_adjacency_lists) { @@ -345,9 +416,19 @@ template std::vector> Graph_::find_conne return connected_components; } +/** + * @brief this method removes variables that were created in a function decompose_into_default_range + * because they are false cases and don't give any useful information about security + * @tparam FF + * @param ultra_circuit_constructor + * @param variables_in_one_gate + * @param index + * @return size_t + */ + template inline size_t Graph_::process_current_decompose_chain(bb::UltraCircuitBuilder& ultra_circuit_constructor, - std::unordered_set& variables_in_on_gate, + std::unordered_set& variables_in_one_gate, size_t index) { auto to_real = [&](uint32_t variable_index) { @@ -364,15 +445,15 @@ inline size_t Graph_::process_current_decompose_chain(bb::UltraCircuitBuilde accumulators_indices.emplace_back(to_real(fourth_idx)); auto left_idx = arithmetic_block.w_l()[current_index]; if (left_idx != zero_idx) { - variables_in_on_gate.erase(to_real(left_idx)); + variables_in_one_gate.erase(to_real(left_idx)); } auto right_idx = arithmetic_block.w_r()[current_index]; if (right_idx != zero_idx) { - variables_in_on_gate.erase(to_real(right_idx)); + variables_in_one_gate.erase(to_real(right_idx)); } auto out_idx = arithmetic_block.w_o()[current_index]; if (out_idx != zero_idx) { - variables_in_on_gate.erase(to_real(out_idx)); + variables_in_one_gate.erase(to_real(out_idx)); } auto q_arith = arithmetic_block.q_arith()[current_index]; if (q_arith == 1 || current_index == arithmetic_block.size() - 1) { @@ -396,6 +477,15 @@ inline size_t Graph_::process_current_decompose_chain(bb::UltraCircuitBuilde return current_index; } +/** + * @brief this method gets the endpoints of the decompose chains. For that it has to clean variable_index + from unnecessary variables for example, left, right, output wires and go through all decompose chain + * @tparam FF + * @param ultra_circuit_builder + * @param variables_in_one_gate + * @param decompose_variables + */ + template inline void Graph_::remove_unnecessary_decompose_variables(bb::UltraCircuitBuilder& ultra_circuit_builder, std::unordered_set& variables_in_one_gate, @@ -404,8 +494,6 @@ inline void Graph_::remove_unnecessary_decompose_variables(bb::UltraCircuitB auto is_power_two = [&](const uint256_t& number) { return number > 0 && ((number & (number - 1)) == 0); }; auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; auto find_position = [&](uint32_t variable_index) { return decompose_variables.contains(to_real(variable_index)); }; - // the idea of this function to get the endpoints of the decompose chains. For that we have to clean variable_index - // from unnecessary variables for example, left, right, output wires auto& arithmetic_block = ultra_circuit_builder.blocks.arithmetic; if (arithmetic_block.size() > 0) { for (size_t i = 0; i < arithmetic_block.size(); i++) { @@ -439,19 +527,14 @@ inline void Graph_::remove_unnecessary_decompose_variables(bb::UltraCircuitB } } } - -template -inline void Graph_::remove_unnecessary_plookup_variables(bb::UltraCircuitBuilder& ultra_circuit_builder, - std::unordered_set& variables_in_one_gate) -{ - auto& lookup_block = ultra_circuit_builder.blocks.lookup; - if (lookup_block.size() > 0) { - for (size_t i = 0; i < lookup_block.size(); i++) { - process_current_plookup_gate(ultra_circuit_builder, variables_in_one_gate, i); - } - } -} - +/** + * @brief this method removes false cases variables in aes plookup tables + * @tparam FF + * @param variables_in_one_gate + * @param ultra_circuit_builder + * @param table_id + * @param gate_index + */ template inline void Graph_::remove_unnecessary_aes_plookup_variables(std::unordered_set& variables_in_one_gate, UltraCircuitBuilder& ultra_circuit_builder, @@ -489,6 +572,15 @@ inline void Graph_::remove_unnecessary_aes_plookup_variables(std::unordered_ } } +/** + * @brief this method removes false cases in sha256 lookup tables + * @tparam FF + * @param variables_in_one_gate + * @param ultra_circuit_builder + * @param table_id + * @param gate_index + */ + template inline void Graph_::remove_unnecessary_sha256_plookup_variables(std::unordered_set& variables_in_one_gate, UltraCircuitBuilder& ultra_circuit_builder, @@ -540,6 +632,14 @@ inline void Graph_::remove_unnecessary_sha256_plookup_variables(std::unorder } } +/** + * @brief this method removes false cases in lookup table for a given gate + * @tparam FF + * @param ultra_circuit_builder + * @param variables_in_one_gate + * @param gate_index + */ + template inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ultra_circuit_builder, std::unordered_set& variables_in_one_gate, @@ -558,8 +658,6 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul std::set column_2(table.column_2.begin(), table.column_2.end()); std::set column_3(table.column_3.begin(), table.column_3.end()); bb::plookup::BasicTableId table_id = table.id; - // in some tables we don't use variables from third column. So, these variables are false-case for a - // analyzer, and we have to remove them // false cases for AES remove_unnecessary_aes_plookup_variables( variables_in_one_gate, ultra_circuit_builder, table_id, gate_index); @@ -594,6 +692,32 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul } } +/** + * @brief this method removes false cases plookup variables from variables in one gate + * @tparam FF + * @param ultra_circuit_builder + * @param variables_in_one_gate + */ + +template +inline void Graph_::remove_unnecessary_plookup_variables(bb::UltraCircuitBuilder& ultra_circuit_builder, + std::unordered_set& variables_in_one_gate) +{ + auto& lookup_block = ultra_circuit_builder.blocks.lookup; + if (lookup_block.size() > 0) { + for (size_t i = 0; i < lookup_block.size(); i++) { + process_current_plookup_gate(ultra_circuit_builder, variables_in_one_gate, i); + } + } +} + +/** + * @brief this method returns a final set of variables that were in one gate + * @tparam FF + * @param ultra_circuit_builder + * @return std::unordered_set + */ + template std::unordered_set Graph_::show_variables_in_one_gate(bb::UltraCircuitBuilder& ultra_circuit_builder) { @@ -620,6 +744,14 @@ std::unordered_set Graph_::show_variables_in_one_gate(bb::UltraCir return variables_in_one_gate; } +/** + * @brief this method returns connected component with a given index and size of this component + * + * @param connected_components + * @param index + * @return std::pair, size_t> + */ + std::pair, size_t> get_connected_component_with_index( const std::vector>& connected_components, size_t index) { @@ -628,6 +760,11 @@ std::pair, size_t> get_connected_component_with_index( return std::make_pair(connected_component, size); } +/** + * @brief this method prints graph as vertice and its adjacency list + * @tparam FF + */ + template void Graph_::print_graph() { for (const auto& elem : variable_adjacency_lists) { @@ -642,6 +779,11 @@ template void Graph_::print_graph() } } +/** + * @brief this method prints all connected components that were found in the graph + * @tparam FF + */ + template void Graph_::print_connected_components() { auto connected_components = find_connected_components(); @@ -653,6 +795,11 @@ template void Graph_::print_connected_components() } } +/** + * @brief this method prints a number of gate for each variable + * @tparam FF + */ + template void Graph_::print_variables_gate_counts() { for (const auto& it : variables_gate_counts) { @@ -660,6 +807,11 @@ template void Graph_::print_variables_gate_counts() } } +/** + * @brief this method prints a number of edges for each variable + * @tparam FF + */ + template void Graph_::print_variables_edge_counts() { for (const auto& it : variables_degree) { diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp index dd5e08844ad7..abfaff0e82be 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp @@ -30,7 +30,10 @@ template class Graph_ { size_t index); void add_new_edge(const uint32_t& first_variable_index, const uint32_t& second_variable_index); - std::vector get_variable_adjacency_list(const uint32_t& variable_index); + std::vector get_variable_adjacency_list(const uint32_t& variable_index) + { + return variable_adjacency_lists[variable_index]; + }; void depth_first_search(const uint32_t& variable_index, std::unordered_set& is_used, @@ -89,9 +92,13 @@ template class Graph_ { ~Graph_() = default; private: - std::unordered_map> variable_adjacency_lists; - std::unordered_map variables_gate_counts; - std::unordered_map variables_degree; + std::unordered_map> + variable_adjacency_lists; // we use this data structure to contain information about variables and their + // connections between each other + std::unordered_map + variables_gate_counts; // we use this data structure to count, how many gates used every variable + std::unordered_map + variables_degree; // we use this data structure to count, how many edges have every variable }; using Graph = Graph_; \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp index 76e18673b362..10d4376698f4 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp @@ -12,10 +12,13 @@ using namespace bb; +/** + * @brief this test checks graph description of the circuit with arithmetic gates + the number of connected components = the number of pair (i, j), 0<=i, j <16, i.e 256 + */ + TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates) { - // this test checks graph description for the circuit with arithmetic gates - // the number of connected components = the number of pair (i, j), 0<=i, j <16, i.e 256 UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); for (size_t i = 0; i < 16; ++i) { @@ -41,6 +44,11 @@ TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates) EXPECT_EQ(result, true); } +/** + * @brief This test checks graph description of Ultra Circuit Builder with arithmetic gates with shifts + * It must be one connected component, cause all gates have shifts + */ + TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates_with_shifts) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -66,11 +74,13 @@ TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates_with_shifts) EXPECT_EQ(result, true); } +/** + * @brief this test checks graph description of the circuit with boolean gates. + all variables must be isolated and the number of connected components = 0, all variables in one gate + */ + TEST(ultra_circuit_constructor, test_graph_for_boolean_gates) { - // this test checks graph description for the circuit with boolean gates. - // all variables must be isolated and the number of connected components = 0 - // and variables in one gate = 20. UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); for (size_t i = 0; i < 20; ++i) { @@ -88,11 +98,14 @@ TEST(ultra_circuit_constructor, test_graph_for_boolean_gates) EXPECT_EQ(variables_in_one_gate.size(), 20); } +/** + * @brief this test checks graph decription for the circuit with one elliptic addition gate. + * The result is one connected component for 6 variables: + * x1, y1, x2, y2, x3, y3 + */ + TEST(ultra_circuit_constructor, test_graph_for_elliptic_add_gate) { - // this test checks graph decription for the circuit with one elliptic addition gate. - // The result is one connected component for 6 variables: - // x1, y1, x2, y2, x3, y3 typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -118,11 +131,14 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_add_gate) EXPECT_EQ(result, true); } +/** + * @brief this test checks graph description of the circuit with one elliptic double gate. + The result is one connected component for 4 variables: + x1, y1, x3, y3 + */ + TEST(ultra_circuit_constructor, test_graph_for_elliptic_double_gate) { - // this test checks graph description for the circuit with one elliptic double gate. - // The result is one connected component for 4 variables: - // x1, y1, x3, y3 typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -144,12 +160,15 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_double_gate) EXPECT_EQ(result, true); } +/** + * @brief this test checks the graph description of the circuit has elliptic addition and multiplication + gates together. The result is 2 connected components: + x1, y1, x2, y2, x3, y3, x4, y4 + x5, y5, x6, y6, x7, y7, x8, y8 + */ + TEST(ultra_circuit_constructor, test_graph_for_elliptic_together) { - // this test checks the graph description for the circuit has elliptic addition and multiplication - // gates together. The result is 2 connected components: - // x1, y1, x2, y2, x3, y3, x4, y4 - // x5, y5, x6, y6, x7, y7, x8, y8 UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); typedef grumpkin::g1::affine_element affine_element; @@ -196,11 +215,14 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_together) EXPECT_EQ(result, true); } +/** + * @brief this test check graph description of the circuit with 2 sort_constraint. The result is 2 connected components: + a_idx, b_idx, c_idx, d_idx + e_idx, f_idx, g_idx, h_idx + */ + TEST(ultra_circuit_constructor, test_graph_for_sort_constraints) { - // this test check graph description for the circuit with 2 sort_constraint. The result is 2 connected components: - // a_idx, b_idx, c_idx, d_idx - // e_idx, f_idx, g_idx, h_idx UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); fr a = fr::one(); fr b = fr(2); @@ -230,12 +252,15 @@ TEST(ultra_circuit_constructor, test_graph_for_sort_constraints) EXPECT_EQ(connected_components.size(), 2); } +/** + * @brief this test checks graph description of the circuit with 2 sorted_constraints with edges. + The result is 2 connected components: + a_idx, b_idx, ... , h_idx + a1_idx, b1_idx, ..., h1_idx + */ + TEST(ultra_circuit_constructor, test_graph_for_sort_constraints_with_edges) { - // this test checks graph description for the circuit with 2 sorted_constraints with edges. - // The result is 2 connected components: - // a_idx, b_idx, ... , h_idx - // a1_idx, b1_idx, ..., h1_idx fr a = fr::one(); fr b = fr(2); fr c = fr(3); @@ -284,10 +309,13 @@ TEST(ultra_circuit_constructor, test_graph_for_sort_constraints_with_edges) EXPECT_EQ(result, true); } +/** + * @brief this test checks graph decription for circuit with gates that were created from plookup accumulators + the result is one connected component + */ + TEST(ultra_circuit_constructor, test_graph_with_plookup_accumulators) { - // this test checks graph decription for circuit with grate that were created from plookup accumulators - // the result is one connected component UltraCircuitBuilder circuit_builder = UltraCircuitBuilder(); fr input_value = fr::random_element(); @@ -310,6 +338,11 @@ TEST(ultra_circuit_constructor, test_graph_with_plookup_accumulators) EXPECT_EQ(result, true); } +/** + * @brief this test checks variable gates counts for variable from arithmetic gates without shifts + in circuit + */ + TEST(ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -338,6 +371,12 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate) EXPECT_EQ(result, true); } +/** + * @brief this test checks variables gates count for variable in circuit with gates with shifts. + * All variables except for zero index, which index == 0 mod 4 and index != 4 have gates count == 2. + * Other variables have gates count = 1. + */ + TEST(ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate_with_shifts) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -370,6 +409,11 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate_ EXPECT_EQ(result, true); } +/** + * @brief this test checks variables gates count for variables in circuit with boolean gates + * all variables except for zero index must have gates count = 1. + */ + TEST(ultra_circuit_constructor, test_variables_gates_counts_for_boolean_gates) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -389,6 +433,11 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_boolean_gates) EXPECT_EQ(result, true); } +/** + * @brief this test checks variables gate counts in circuit with sorted constraints. + * all variables in 2 connected components must have gates count = 1 + */ + TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constraints) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -427,6 +476,11 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constrain EXPECT_EQ(result, true); } +/** + * @brief this test checks variable gates count for variables in circuit with sorted constraints with edges + * all variables in 2 connected components must have gates count = 1 + */ + TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constraints_with_edges) { fr a = fr::one(); @@ -485,6 +539,11 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constrain EXPECT_EQ(result, true); } +/** + * @brief this test checks variables gates count for variables in circuit with 1 elliptic addition gates + * all variables in connected components must have gates count = 1 + */ + TEST(ultra_circuit_constructor, test_variables_gates_counts_for_ecc_add_gates) { typedef grumpkin::g1::affine_element affine_element; @@ -518,6 +577,11 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_ecc_add_gates) EXPECT_EQ(result, true); } +/** + * @brief this test checks variables gates count for variables in circuit with 1 elliptic double gates + * all variables in connected components must have gates count = 1. + */ + TEST(ultra_circuit_constructor, test_variables_gates_counts_for_ecc_dbl_gate) { typedef grumpkin::g1::affine_element affine_element; @@ -556,6 +620,11 @@ std::vector add_variables(UltraCircuitBuilder& circuit_constructor, st return res; } +/** + * @brief this test checks graph description of circuit with range constraints. + * all variables must be in one connected component. + */ + TEST(ultra_circuit_constructor, test_graph_for_range_constraints) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -569,6 +638,11 @@ TEST(ultra_circuit_constructor, test_graph_for_range_constraints) EXPECT_EQ(connected_components.size(), 1); } +/** + * @brief this checks graph description of circuit with decompose function. + * all variables must be in one connected component + */ + TEST(ultra_circuit_constructor, composed_range_constraint) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp index 126ef3c5c175..230aa4a1703b 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp @@ -27,6 +27,11 @@ bool check_in_vector(const std::vector& input_vector, const uint32_t& return false; } +/** + * @brief this test checks graph description of circuit for AES128CBC + * graph must be consist from one connected component + */ + TEST(ultra_circuit_constructor, test_graph_for_aes_64_bytes) { uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; @@ -66,6 +71,12 @@ TEST(ultra_circuit_constructor, test_graph_for_aes_64_bytes) EXPECT_EQ(graph_result, true); } +/** + * @brief this test checks variables gate counts for variables in circuit for AES128CBC + * Some variables can be from input/output vectors, or they are key and iv, and they have variable + * gates count = 1, because it's the circuit for test. So, we can ignore these variables + */ + TEST(ultra_circuit_constructor, test_variable_gates_count_for_aes128cbc) { @@ -106,9 +117,6 @@ TEST(ultra_circuit_constructor, test_variable_gates_count_for_aes128cbc) bool result2 = check_in_vector(result, elem); bool check = (result1 == 1) || (result2 == 1) || (elem == key_field.witness_index) || (elem == iv_field.witness_index); - if (check == false) { - info("elem == ", elem); - } EXPECT_EQ(check, true); } } \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp index 099c8b58fa97..908af796ba7b 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp @@ -19,6 +19,11 @@ using byte_array_ct = byte_array; using byte_array_plookup = byte_array; using public_witness_t = public_witness_t; +/** + * @brief this tests check graph description of circuit for blake2s for one and two blocks. + * all graphs must have one connected component. + */ + TEST(ultra_circuit_constructor, test_graph_for_blake2s_single_block_plookup) { Builder builder; diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp index dcffb6029529..668d2486d258 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp @@ -16,6 +16,11 @@ using byte_array_plookup = stdlib::byte_array; using public_witness_t_plookup = stdlib::public_witness_t; using UltraBuilder = UltraCircuitBuilder; +/** + * @brief this tests check that graph description of circuit for blake3s for different blocks. + * All graphs must have one connected component + */ + TEST(stdlib_blake3s, test_single_block_plookup) { auto builder = UltraBuilder(); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp index c48144b3fc90..85d3e51c10a9 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp @@ -21,6 +21,10 @@ using byte_array_ct = byte_array; using packed_byte_array_ct = packed_byte_array; using field_ct = field_t; +/** + all these tests check graph description for sha256 circuits. All circuits have to consist from 1 connected component + */ + TEST(ultra_circuit_constructor, test_sha256_55_bytes) { // 55 bytes is the largest number of bytes that can be hashed in a single block, diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp index b28fd0b6d004..1e39701670c6 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp @@ -49,6 +49,12 @@ bool check_in_range_lists(const uint32_t& real_var_index, const uint64_t& target return false; } +/** + * @brief all these tests check circuits for sha256 NIST VECTORS to find variables that won't properly constrained, + * i.e. have variable gates count = 1. Some variables can be from input/output vectors or from range_constraints, + * and they are not dangerous. + */ + TEST(ultra_circuit_constructor, test_variables_gate_counts_for_sha256_55_bytes) { // 55 bytes is the largest number of bytes that can be hashed in a single block, From 6e2933f1df2334fc7fb3c1583ee2ef8ae852e2be Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Mon, 28 Oct 2024 15:28:33 +0000 Subject: [PATCH 18/21] other changes for PR again --- .../boomerang_value_detection/graph.cpp | 169 ++++++++---------- .../boomerang_value_detection/graph.hpp | 15 ++ .../graph_description.test.cpp | 1 + .../graph_description_aes128.test.cpp | 5 +- .../graph_description_blake2s.test.cpp | 5 +- .../graph_description_sha256.test.cpp | 4 +- .../variables_gate_counts.sha256.test.cpp | 12 +- .../standard_circuit_builder.cpp | 51 ------ .../standard_circuit_builder.hpp | 1 - 9 files changed, 106 insertions(+), 157 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp index 503ad58cf761..0e498c6c99c4 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -5,6 +5,29 @@ using namespace bb::plookup; using namespace bb; +/** + * @brief this method removes duplicate variables from a gate, + * converts variables from a gate to real variables, and then + * updates variable gates count for real variable indexes + */ + +template +void Graph_::process_gate_variables(UltraCircuitBuilder& ultra_circuit_builder, + std::vector& gate_variables) +{ + auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end()); + gate_variables.erase(unique_variables, gate_variables.end()); + if (gate_variables.empty()) { + } else { + for (size_t i = 0; i < gate_variables.size(); i++) { + gate_variables[i] = to_real(ultra_circuit_builder, gate_variables[i]); + } + for (const auto& variable_index : gate_variables) { + variables_gate_counts[variable_index] += 1; + } + } +} + /** * @brief this method implements connected components from arithmetic gates * @tparam FF @@ -61,15 +84,7 @@ inline std::vector Graph_::get_arithmetic_gate_connected_component } } } - auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; - auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end()); - gate_variables.erase(unique_variables, gate_variables.end()); - std::transform(gate_variables.cbegin(), gate_variables.cend(), gate_variables.begin(), to_real); - if (!gate_variables.empty()) { - for (const auto& real_variable_index : gate_variables) { - variables_gate_counts[real_variable_index] += 1; - } - } + process_gate_variables(ultra_circuit_builder, gate_variables); return gate_variables; } @@ -85,7 +100,6 @@ template inline std::vector Graph_::get_elliptic_gate_connected_component( bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) { - auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; auto& elliptic_block = ultra_circuit_builder.blocks.elliptic; std::vector gate_variables = {}; bool is_elliptic_gate = elliptic_block.q_elliptic()[index] == 1; @@ -111,14 +125,7 @@ inline std::vector Graph_::get_elliptic_gate_connected_component( } } } - auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end()); - gate_variables.erase(unique_variables, gate_variables.end()); - std::transform(gate_variables.cbegin(), gate_variables.cend(), gate_variables.begin(), to_real); - if (!gate_variables.empty()) { - for (const auto& real_variable_index : gate_variables) { - variables_gate_counts[real_variable_index] += 1; - } - } + process_gate_variables(ultra_circuit_builder, gate_variables); return gate_variables; } @@ -146,18 +153,12 @@ inline std::vector Graph_::get_sort_constraint_connected_component } auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end()); gate_variables.erase(unique_variables, gate_variables.end()); - auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; - std::transform(gate_variables.cbegin(), gate_variables.cend(), gate_variables.begin(), to_real); - if (!gate_variables.empty()) { - for (const auto& real_variable_index : gate_variables) { - variables_gate_counts[real_variable_index] += 1; - } - } + process_gate_variables(ultra_circuit_builder, gate_variables); return gate_variables; } /** - * @brief this method creates connected_components from plookup gates + * @brief this method creates connected components from plookup gates * * @tparam FF * @param ultra_circuit_builder @@ -169,8 +170,7 @@ template inline std::vector Graph_::get_plookup_gate_connected_component( bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index) { - auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; - std::vector variable_indices = {}; + std::vector gate_variables; auto& lookup_block = ultra_circuit_builder.blocks.lookup; auto q_2 = lookup_block.q_2()[index]; auto q_m = lookup_block.q_m()[index]; @@ -178,31 +178,24 @@ inline std::vector Graph_::get_plookup_gate_connected_component( auto left_idx = lookup_block.w_l()[index]; auto right_idx = lookup_block.w_r()[index]; auto out_idx = lookup_block.w_o()[index]; - variable_indices.emplace_back(left_idx); - variable_indices.emplace_back(right_idx); - variable_indices.emplace_back(out_idx); + gate_variables.emplace_back(left_idx); + gate_variables.emplace_back(right_idx); + gate_variables.emplace_back(out_idx); if (index < lookup_block.size() - 1) { if (q_2 != 0 || q_m != 0 || q_c != 0) { if (q_2 != 0) { - variable_indices.emplace_back(lookup_block.w_l()[index + 1]); + gate_variables.emplace_back(lookup_block.w_l()[index + 1]); } if (q_m != 0) { - variable_indices.emplace_back(lookup_block.w_r()[index + 1]); + gate_variables.emplace_back(lookup_block.w_r()[index + 1]); } if (q_c != 0) { - variable_indices.emplace_back(lookup_block.w_o()[index + 1]); + gate_variables.emplace_back(lookup_block.w_o()[index + 1]); } } } - auto unique_variables = std::unique(variable_indices.begin(), variable_indices.end()); - variable_indices.erase(unique_variables, variable_indices.end()); - std::transform(variable_indices.cbegin(), variable_indices.cend(), variable_indices.begin(), to_real); - if (!variable_indices.empty()) { - for (const auto& real_variable_index : variable_indices) { - variables_gate_counts[real_variable_index] += 1; - } - } - return variable_indices; + process_gate_variables(ultra_circuit_builder, gate_variables); + return gate_variables; } /** @@ -272,7 +265,7 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit } /** - * @brief this method checks that variable with given index is not constant + * @brief this method checks whether the variable with given index is not constant * * @tparam FF * @param ultra_circuit_builder @@ -297,9 +290,8 @@ bool Graph_::check_is_not_constant_variable(bb::UltraCircuitBuilder& ultra_c } /** - * @brief this method connects between each other variables that have different indexes, if their indexes are not equal - * zero_idx and they are not constant variables, so they are not in constant_variable_indices from ultra circuit - * builder data structure + * @brief this method adds connection between 2 variables, if they are in one gate, they are not constrant variables, + * and they have different indexes * @tparam FF * @param ultra_circuit_builder * @param variables_vector @@ -394,7 +386,7 @@ void Graph_::depth_first_search(const uint32_t& variable_index, } /** - * @brief this methond finds connected components from the graph described by adjacency lists + * @brief this methond finds all connected components in the graph described by adjacency lists * @tparam FF * @return std::vector> */ @@ -431,9 +423,6 @@ inline size_t Graph_::process_current_decompose_chain(bb::UltraCircuitBuilde std::unordered_set& variables_in_one_gate, size_t index) { - auto to_real = [&](uint32_t variable_index) { - return ultra_circuit_constructor.real_variable_index[variable_index]; - }; auto& arithmetic_block = ultra_circuit_constructor.blocks.arithmetic; auto zero_idx = ultra_circuit_constructor.zero_idx; size_t current_index = index; @@ -442,18 +431,18 @@ inline size_t Graph_::process_current_decompose_chain(bb::UltraCircuitBuilde // we have to remove left, right and output wires of the current gate, cause they'are new_limbs, and they are // useless for the analyzer auto fourth_idx = arithmetic_block.w_4()[current_index]; - accumulators_indices.emplace_back(to_real(fourth_idx)); + accumulators_indices.emplace_back(to_real(ultra_circuit_constructor, fourth_idx)); auto left_idx = arithmetic_block.w_l()[current_index]; if (left_idx != zero_idx) { - variables_in_one_gate.erase(to_real(left_idx)); + variables_in_one_gate.erase(to_real(ultra_circuit_constructor, left_idx)); } auto right_idx = arithmetic_block.w_r()[current_index]; if (right_idx != zero_idx) { - variables_in_one_gate.erase(to_real(right_idx)); + variables_in_one_gate.erase(to_real(ultra_circuit_constructor, right_idx)); } auto out_idx = arithmetic_block.w_o()[current_index]; if (out_idx != zero_idx) { - variables_in_one_gate.erase(to_real(out_idx)); + variables_in_one_gate.erase(to_real(ultra_circuit_constructor, out_idx)); } auto q_arith = arithmetic_block.q_arith()[current_index]; if (q_arith == 1 || current_index == arithmetic_block.size() - 1) { @@ -492,8 +481,9 @@ inline void Graph_::remove_unnecessary_decompose_variables(bb::UltraCircuitB const std::unordered_set& decompose_variables) { auto is_power_two = [&](const uint256_t& number) { return number > 0 && ((number & (number - 1)) == 0); }; - auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; - auto find_position = [&](uint32_t variable_index) { return decompose_variables.contains(to_real(variable_index)); }; + auto find_position = [&](uint32_t variable_index) { + return decompose_variables.contains(to_real(ultra_circuit_builder, variable_index)); + }; auto& arithmetic_block = ultra_circuit_builder.blocks.arithmetic; if (arithmetic_block.size() > 0) { for (size_t i = 0; i < arithmetic_block.size(); i++) { @@ -528,7 +518,10 @@ inline void Graph_::remove_unnecessary_decompose_variables(bb::UltraCircuitB } } /** - * @brief this method removes false cases variables in aes plookup tables + * @brief this method removes false cases variables from aes plookup tables. + * AES_SBOX_MAP, AES_SPARSE_MAP, AES_SPARSE_NORMALIZE tables are used in read_from_1_to_2_table function which + * return values C2[0], so C3[0] isn't used anymore in these cases, but this situation isn't dangerous. + * So, we have to remove these variables. * @tparam FF * @param variables_in_one_gate * @param ultra_circuit_builder @@ -542,32 +535,24 @@ inline void Graph_::remove_unnecessary_aes_plookup_variables(std::unordered_ size_t gate_index) { - auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; - auto find_position = [&](uint32_t variable_index) { - return variables_in_one_gate.contains(to_real(variable_index)); + auto find_position = [&](uint32_t real_variable_index) { + return variables_in_one_gate.contains(real_variable_index); }; std::unordered_set aes_plookup_tables{ BasicTableId::AES_SBOX_MAP, BasicTableId::AES_SPARSE_MAP, BasicTableId::AES_SPARSE_NORMALIZE }; auto& lookup_block = ultra_circuit_builder.blocks.lookup; if (aes_plookup_tables.contains(table_id)) { - uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); - uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); + uint32_t real_out_idx = to_real(ultra_circuit_builder, lookup_block.w_o()[gate_index]); + uint32_t real_right_idx = to_real(ultra_circuit_builder, lookup_block.w_r()[gate_index]); if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { bool find_out = find_position(real_out_idx); - bool find_right = find_position(real_right_idx); - auto q_m = lookup_block.q_m()[gate_index]; auto q_c = lookup_block.q_c()[gate_index]; if (q_c == 0) { if (find_out) { variables_in_one_gate.erase(real_out_idx); } } - if (q_m == 0) { - if (find_right) { - variables_in_one_gate.erase(real_right_idx); - } - } } } } @@ -588,9 +573,8 @@ inline void Graph_::remove_unnecessary_sha256_plookup_variables(std::unorder size_t gate_index) { - auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; - auto find_position = [&](uint32_t variable_index) { - return variables_in_one_gate.contains(to_real(variable_index)); + auto find_position = [&](uint32_t real_variable_index) { + return variables_in_one_gate.contains(real_variable_index); }; auto& lookup_block = ultra_circuit_builder.blocks.lookup; std::unordered_set sha256_plookup_tables{ BasicTableId::SHA256_WITNESS_SLICE_3, @@ -606,26 +590,21 @@ inline void Graph_::remove_unnecessary_sha256_plookup_variables(std::unorder BasicTableId::SHA256_BASE28_ROTATE3, BasicTableId::SHA256_BASE28_ROTATE6 }; if (sha256_plookup_tables.contains(table_id)) { - uint32_t real_right_idx = to_real(lookup_block.w_r()[gate_index]); - uint32_t real_out_idx = to_real(lookup_block.w_o()[gate_index]); + uint32_t real_right_idx = to_real(ultra_circuit_builder, lookup_block.w_r()[gate_index]); + uint32_t real_out_idx = to_real(ultra_circuit_builder, lookup_block.w_o()[gate_index]); if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { - auto q_m = lookup_block.q_m()[gate_index]; + // auto q_m = lookup_block.q_m()[gate_index]; auto q_c = lookup_block.q_c()[gate_index]; bool find_out = find_position(real_out_idx); - bool find_right = find_position(real_right_idx); + // bool find_right = find_position(real_right_idx); if (q_c == 0) { if (find_out) { variables_in_one_gate.erase(real_out_idx); } } - if (q_m == 0) { - if (find_right) { - variables_in_one_gate.erase(real_right_idx); - } - } if (table_id == SHA256_BASE16_ROTATE2 || table_id == SHA256_BASE28_ROTATE6) { // we want to remove false cases for special tables even though their selectors != 0 - // because it's from_1_to_2_table cases, and they aren't dangerous + // because they are used in read_from_1_to_2_table function, and they aren't dangerous variables_in_one_gate.erase(real_out_idx); } } @@ -645,9 +624,8 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul std::unordered_set& variables_in_one_gate, size_t gate_index) { - auto to_real = [&](uint32_t variable_index) { return ultra_circuit_builder.real_variable_index[variable_index]; }; - auto find_position = [&](uint32_t variable_index) { - return variables_in_one_gate.contains(to_real(variable_index)); + auto find_position = [&](uint32_t real_variable_index) { + return variables_in_one_gate.contains(real_variable_index); }; auto& lookup_block = ultra_circuit_builder.blocks.lookup; auto& lookup_tables = ultra_circuit_builder.lookup_tables; @@ -666,23 +644,21 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul variables_in_one_gate, ultra_circuit_builder, table_id, gate_index); if (column_1.size() == 1) { uint32_t left_idx = lookup_block.w_l()[gate_index]; - uint32_t real_left_idx = to_real(left_idx); + uint32_t real_left_idx = to_real(ultra_circuit_builder, left_idx); bool find_left = find_position(real_left_idx); if (find_left) { variables_in_one_gate.erase(real_left_idx); } } if (column_2.size() == 1) { - uint32_t right_idx = lookup_block.w_r()[gate_index]; - uint32_t real_right_idx = to_real(right_idx); + uint32_t real_right_idx = to_real(ultra_circuit_builder, lookup_block.w_r()[gate_index]); bool find_right = find_position(real_right_idx); if (find_right) { variables_in_one_gate.erase(real_right_idx); } } if (column_3.size() == 1) { - uint32_t out_idx = lookup_block.w_o()[gate_index]; - uint32_t real_out_idx = to_real(out_idx); + uint32_t real_out_idx = to_real(ultra_circuit_builder, lookup_block.w_o()[gate_index]); bool find_out = find_position(real_out_idx); if (find_out) { variables_in_one_gate.erase(real_out_idx); @@ -746,7 +722,8 @@ std::unordered_set Graph_::show_variables_in_one_gate(bb::UltraCir /** * @brief this method returns connected component with a given index and size of this component - * + * sometimes for debugging we want to check the size one of the connected component, so it would be + * useful to know its size * @param connected_components * @param index * @return std::pair, size_t> @@ -761,7 +738,13 @@ std::pair, size_t> get_connected_component_with_index( } /** - * @brief this method prints graph as vertice and its adjacency list + * @brief this method prints graph as vertices and their adjacency lists + * example: we have an undirected graph from 3 variables: a, b, c. + * we have edges: a - b, b - c, c - a. + * so, there will be next adjacency lists: + * a: b -> c -> 0\ + * b: a -> c -> 0\ + * c: a -> b -> 0\ * @tparam FF */ diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp index abfaff0e82be..929d02efaa59 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp @@ -8,6 +8,14 @@ #include #include +/* + * this class describes arithmetic circuit as an undirected graph, where vertices are variables from circuit. + * edges describe connections between variables through gates. We want to find variables that weren't properly + * constrainted/some connections were missed using additional metrics, like in how much gate variable was and number of + * connected components in the graph. if variable was in one connected component, it means that this variable wasn't + * constrained properly. if number of connected components > 1, it means that there were missed some connections between + * variables. + */ template class Graph_ { public: Graph_() = default; @@ -18,6 +26,13 @@ template class Graph_ { Graph_(const bb::StandardCircuitBuilder_& circuit_constructor); Graph_(bb::UltraCircuitBuilder& ultra_circuit_constructor); + uint32_t to_real(bb::UltraCircuitBuilder& ultra_circuit_constructor, const uint32_t& variable_index) + { + return ultra_circuit_constructor.real_variable_index[variable_index]; + }; + void process_gate_variables(bb::UltraCircuitBuilder& ultra_circuit_constructor, + std::vector& gate_variables); + std::unordered_map get_variables_gate_counts() { return this->variables_gate_counts; }; std::vector get_arithmetic_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder, diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp index 10d4376698f4..ed9977095e55 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp @@ -465,6 +465,7 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constrain Graph graph = Graph(circuit_constructor); auto variables_gate_counts = graph.get_variables_gate_counts(); auto connected_components = graph.find_connected_components(); + EXPECT_EQ(connected_components.size(), 2); bool result = true; for (size_t i = 0; i < connected_components[0].size(); i++) { result = result && (variables_gate_counts[connected_components[0][i]] == 1); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp index 230aa4a1703b..ae31a62d7aa4 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp @@ -32,7 +32,7 @@ bool check_in_vector(const std::vector& input_vector, const uint32_t& * graph must be consist from one connected component */ -TEST(ultra_circuit_constructor, test_graph_for_aes_64_bytes) +TEST(stdlib_aes, test_graph_for_aes_64_bytes) { uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; uint8_t iv[16]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; @@ -68,6 +68,7 @@ TEST(ultra_circuit_constructor, test_graph_for_aes_64_bytes) auto connected_components = graph.find_connected_components(); auto num_connected_components = connected_components.size(); bool graph_result = num_connected_components == 1; + EXPECT_EQ(graph_result, true); } @@ -77,7 +78,7 @@ TEST(ultra_circuit_constructor, test_graph_for_aes_64_bytes) * gates count = 1, because it's the circuit for test. So, we can ignore these variables */ -TEST(ultra_circuit_constructor, test_variable_gates_count_for_aes128cbc) +TEST(stdlib_aes, test_variable_gates_count_for_aes128cbc) { uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp index 908af796ba7b..4af9be1e1b3c 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp @@ -24,7 +24,7 @@ using public_witness_t = public_witness_t; * all graphs must have one connected component. */ -TEST(ultra_circuit_constructor, test_graph_for_blake2s_single_block_plookup) +TEST(stdlib_blake2s, test_graph_for_blake2s_single_block_plookup) { Builder builder; std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01"; @@ -36,9 +36,10 @@ TEST(ultra_circuit_constructor, test_graph_for_blake2s_single_block_plookup) Graph graph = Graph(builder); auto connected_components = graph.find_connected_components(); EXPECT_EQ(connected_components.size(), 1); + graph.print_connected_components(); } -TEST(ultra_circuit_constructor, test_graph_for_blake2s_double_block_plookup) +TEST(stdlib_blake2s, test_graph_for_blake2s_double_block_plookup) { Builder builder; std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp index 85d3e51c10a9..afa8f5e2e760 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp @@ -25,7 +25,7 @@ using field_ct = field_t; all these tests check graph description for sha256 circuits. All circuits have to consist from 1 connected component */ -TEST(ultra_circuit_constructor, test_sha256_55_bytes) +TEST(stdlib_sha256, test_graph_for_sha256_55_bytes) { // 55 bytes is the largest number of bytes that can be hashed in a single block, // accounting for the single padding bit, and the 64 size bits required by the SHA-256 standard. @@ -43,7 +43,7 @@ TEST(ultra_circuit_constructor, test_sha256_55_bytes) EXPECT_EQ(connected_components.size(), 1); } -HEAVY_TEST(ultra_circuit_constructor, test_graph_for_sha256_NIST_vector_five) +HEAVY_TEST(stdlib_sha256, test_graph_for_sha256_NIST_vector_five) { typedef stdlib::field_t field_pt; typedef stdlib::packed_byte_array packed_byte_array_pt; diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp index 1e39701670c6..8a756becb661 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp @@ -55,7 +55,7 @@ bool check_in_range_lists(const uint32_t& real_var_index, const uint64_t& target * and they are not dangerous. */ -TEST(ultra_circuit_constructor, test_variables_gate_counts_for_sha256_55_bytes) +TEST(stdlib_sha256, test_variables_gate_counts_for_sha256_55_bytes) { // 55 bytes is the largest number of bytes that can be hashed in a single block, // accounting for the single padding bit, and the 64 size bits required by the SHA-256 standard. @@ -79,7 +79,7 @@ TEST(ultra_circuit_constructor, test_variables_gate_counts_for_sha256_55_bytes) } } -TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_vector_one) +TEST(stdlib_sha256, test_variable_gates_count_for_sha256_NIST_vector_one) { auto builder = Builder(); packed_byte_array_ct input(&builder, "abc"); @@ -96,7 +96,7 @@ TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_vector } } -TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_vector_two) +TEST(stdlib_sha256, test_variable_gates_count_for_sha256_NIST_vector_two) { auto builder = Builder(); @@ -114,7 +114,7 @@ TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_vector } } -TEST(ultra_circuit_constructor, test_variable_gates_count_sha256_NIST_vector_three) +TEST(stdlib_sha256, test_variable_gates_count_sha256_NIST_vector_three) { auto builder = Builder(); @@ -132,7 +132,7 @@ TEST(ultra_circuit_constructor, test_variable_gates_count_sha256_NIST_vector_thr } } -TEST(ultra_circuit_constructor, test_variable_gates_count_sha256_NIST_vector_four) +TEST(stdlib_sha256, test_variable_gates_count_sha256_NIST_vector_four) { auto builder = Builder(); @@ -150,7 +150,7 @@ TEST(ultra_circuit_constructor, test_variable_gates_count_sha256_NIST_vector_fou } } -HEAVY_TEST(ultra_circuit_constructor, test_variable_gates_count_for_sha256_NIST_vector_five) +HEAVY_TEST(stdlib_sha256, test_variable_gates_count_for_sha256_NIST_vector_five) { auto builder = Builder(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.cpp index ecbbe808d8b6..4bec396ef314 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.cpp @@ -473,57 +473,6 @@ void StandardCircuitBuilder_::fix_witness(const uint32_t witness_index, cons ++this->num_gates; } -template void StandardCircuitBuilder_::print_boomerang_variables() -{ - std::set var_left; - std::set var_right; - std::set var_out; - std::unordered_set boomerang_idx; - std::set left_right_union; - for (size_t i = 0; i < this->num_gates; i++) { - uint32_t left_idx = blocks.arithmetic.w_l()[i]; - uint32_t right_idx = blocks.arithmetic.w_r()[i]; - uint32_t out_idx = blocks.arithmetic.w_o()[i]; - var_left.insert(left_idx); - var_right.insert(right_idx); - var_out.insert(out_idx); - } - - std::set_union(var_left.begin(), - var_left.end(), - var_right.begin(), - var_right.end(), - std::inserter(left_right_union, left_right_union.begin())); - std::set_difference(left_right_union.begin(), - left_right_union.end(), - var_out.begin(), - var_out.end(), - std::inserter(boomerang_idx, boomerang_idx.begin())); - for (size_t i = 0; i < this->num_gates; i++) { - uint32_t left_idx = blocks.arithmetic.w_l()[i]; - uint32_t right_idx = blocks.arithmetic.w_r()[i]; - if (boomerang_idx.contains(left_idx) && boomerang_idx.contains(right_idx)) { - if (left_idx == right_idx) { - std::cout << "possible boomerang variable with the index " << left_idx - << " is the left and right value for the gate with number " << i << "\n"; - } else { - std::cout << "possible boomerang variable with index " << left_idx - << " is the left value for the gate with number " << i << '\n'; - std::cout << "possible boomerang variable with the index " << right_idx - << " is the right value for the gate with number " << i << "\n"; - } - } - if (boomerang_idx.contains(left_idx) && !boomerang_idx.contains(right_idx)) { - std::cout << "possible boomerang variable with the index" << left_idx - << " is the left value for the gate with number " << i << "\n"; - } - if (!boomerang_idx.contains(left_idx) && boomerang_idx.contains(right_idx)) { - std::cout << "possible boomerang variable with the index" << right_idx - << " is the right value for the gate with number " << i << "\n"; - } - } -} - template uint32_t StandardCircuitBuilder_::put_constant_variable(const FF& variable) { if (constant_variable_indices.contains(variable)) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp index b0560ce17134..b25fc8d34abc 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp @@ -103,7 +103,6 @@ template class StandardCircuitBuilder_ : public CircuitBuilderBase // TODO(#216)(Adrian): The 2 following methods should be virtual in the base class uint32_t put_constant_variable(const FF& variable); - void print_boomerang_variables(); size_t get_num_constant_gates() const override { return 0; } From 445e02e6e7435992205d98f2754f69f8fb4a1137 Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Fri, 1 Nov 2024 10:53:38 +0000 Subject: [PATCH 19/21] add comments + inline + this to all class member functions --- .../boomerang_value_detection/graph.cpp | 122 ++++++++++-------- .../boomerang_value_detection/graph.hpp | 4 +- .../graph_description_aes128.test.cpp | 4 +- .../graph_description_blake2s.test.cpp | 7 +- .../graph_description_blake3s.test.cpp | 4 +- .../graph_description_sha256.test.cpp | 4 +- .../stdlib/hash/blake2s/blake2s.test.cpp | 3 + 7 files changed, 81 insertions(+), 67 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp index 0e498c6c99c4..efb2ff3b1316 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -12,15 +12,15 @@ using namespace bb; */ template -void Graph_::process_gate_variables(UltraCircuitBuilder& ultra_circuit_builder, - std::vector& gate_variables) +inline void Graph_::process_gate_variables(UltraCircuitBuilder& ultra_circuit_builder, + std::vector& gate_variables) { auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end()); gate_variables.erase(unique_variables, gate_variables.end()); if (gate_variables.empty()) { } else { for (size_t i = 0; i < gate_variables.size(); i++) { - gate_variables[i] = to_real(ultra_circuit_builder, gate_variables[i]); + gate_variables[i] = this->to_real(ultra_circuit_builder, gate_variables[i]); } for (const auto& variable_index : gate_variables) { variables_gate_counts[variable_index] += 1; @@ -80,11 +80,11 @@ inline std::vector Graph_::get_arithmetic_gate_connected_component } } if (arithmetic_block.q_arith()[index] == 3) { - info("TODO"); + // TODO(daniel): want to process this case later } } } - process_gate_variables(ultra_circuit_builder, gate_variables); + this->process_gate_variables(ultra_circuit_builder, gate_variables); return gate_variables; } @@ -125,7 +125,7 @@ inline std::vector Graph_::get_elliptic_gate_connected_component( } } } - process_gate_variables(ultra_circuit_builder, gate_variables); + this->process_gate_variables(ultra_circuit_builder, gate_variables); return gate_variables; } @@ -151,9 +151,7 @@ inline std::vector Graph_::get_sort_constraint_connected_component auto fourth_idx = delta_range_block.w_4()[index]; gate_variables.insert(gate_variables.end(), { left_idx, right_idx, out_idx, fourth_idx }); } - auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end()); - gate_variables.erase(unique_variables, gate_variables.end()); - process_gate_variables(ultra_circuit_builder, gate_variables); + this->process_gate_variables(ultra_circuit_builder, gate_variables); return gate_variables; } @@ -194,13 +192,12 @@ inline std::vector Graph_::get_plookup_gate_connected_component( } } } - process_gate_variables(ultra_circuit_builder, gate_variables); + this->process_gate_variables(ultra_circuit_builder, gate_variables); return gate_variables; } /** - * @brief Construct a new Graph from Ultra_Circuit_Builder - * + * @brief Construct a new Graph from Ultra Circuit Builder * @tparam FF * @param ultra_circuit_constructor */ @@ -224,8 +221,8 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit bool arithmetic_gates_exists = arithmetic_gates_numbers > 0; if (arithmetic_gates_exists) { for (size_t i = 0; i < arithmetic_gates_numbers; i++) { - auto gate_variables = get_arithmetic_gate_connected_component(ultra_circuit_constructor, i); - connect_all_variables_in_vector(ultra_circuit_constructor, gate_variables, false); + auto gate_variables = this->get_arithmetic_gate_connected_component(ultra_circuit_constructor, i); + this->connect_all_variables_in_vector(ultra_circuit_constructor, gate_variables, false); } } const auto& elliptic_block = ultra_circuit_constructor.blocks.elliptic; @@ -233,8 +230,9 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit bool elliptic_gates_exist = elliptic_gates_numbers > 0; if (elliptic_gates_exist) { for (size_t i = 0; i < elliptic_gates_numbers; i++) { - std::vector gate_variables = get_elliptic_gate_connected_component(ultra_circuit_constructor, i); - connect_all_variables_in_vector(ultra_circuit_constructor, gate_variables, false); + std::vector gate_variables = + this->get_elliptic_gate_connected_component(ultra_circuit_constructor, i); + this->connect_all_variables_in_vector(ultra_circuit_constructor, gate_variables, false); } } const auto& range_block = ultra_circuit_constructor.blocks.delta_range; @@ -243,11 +241,11 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit if (range_gates_exists) { std::vector sorted_variables; for (size_t i = 0; i < range_gates; i++) { - auto current_gate = get_sort_constraint_connected_component(ultra_circuit_constructor, i); + auto current_gate = this->get_sort_constraint_connected_component(ultra_circuit_constructor, i); if (!current_gate.empty()) { sorted_variables.insert(sorted_variables.end(), current_gate.begin(), current_gate.end()); } else { - connect_all_variables_in_vector(ultra_circuit_constructor, sorted_variables, true); + this->connect_all_variables_in_vector(ultra_circuit_constructor, sorted_variables, true); sorted_variables.clear(); } } @@ -258,15 +256,15 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit bool lookup_gates_exists = lookup_gates > 0; if (lookup_gates_exists) { for (size_t i = 0; i < lookup_gates; i++) { - std::vector variable_indices = get_plookup_gate_connected_component(ultra_circuit_constructor, i); - connect_all_variables_in_vector(ultra_circuit_constructor, variable_indices, false); + std::vector variable_indices = + this->get_plookup_gate_connected_component(ultra_circuit_constructor, i); + this->connect_all_variables_in_vector(ultra_circuit_constructor, variable_indices, false); } } } /** * @brief this method checks whether the variable with given index is not constant - * * @tparam FF * @param ultra_circuit_builder * @param variable_index @@ -303,7 +301,8 @@ void Graph_::connect_all_variables_in_vector(bb::UltraCircuitBuilder& ultra_ const std::vector& variables_vector, bool is_sorted_variables) { - if (!variables_vector.empty()) { + if (variables_vector.empty()) { + } else { if (is_sorted_variables) { for (size_t i = 0; i < variables_vector.size() - 1; i++) { if (variables_vector[i] != ultra_circuit_builder.zero_idx && @@ -311,11 +310,11 @@ void Graph_::connect_all_variables_in_vector(bb::UltraCircuitBuilder& ultra_ variables_vector[i] != variables_vector[i + 1]) { { bool first_variable_is_not_constant = - check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i]); + this->check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i]); bool second_variable_is_not_constant = - check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i + 1]); + this->check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i + 1]); if (first_variable_is_not_constant && second_variable_is_not_constant) { - add_new_edge(variables_vector[i], variables_vector[i + 1]); + this->add_new_edge(variables_vector[i], variables_vector[i + 1]); } } } @@ -328,11 +327,11 @@ void Graph_::connect_all_variables_in_vector(bb::UltraCircuitBuilder& ultra_ variables_vector[i] != variables_vector[j]) { bool first_variable_is_not_constant = - check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i]); + this->check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i]); bool second_variable_is_not_constant = - check_is_not_constant_variable(ultra_circuit_builder, variables_vector[j]); + this->check_is_not_constant_variable(ultra_circuit_builder, variables_vector[j]); if (first_variable_is_not_constant && second_variable_is_not_constant) { - add_new_edge(variables_vector[i], variables_vector[j]); + this->add_new_edge(variables_vector[i], variables_vector[j]); } } } @@ -358,7 +357,7 @@ void Graph_::add_new_edge(const uint32_t& first_variable_index, const uint32 } /** - * @brief this method implements algorithm depth first search for undirected graph + * @brief this method implements depth-first search algorithm for undirected graphs * @tparam FF * @param variable_index * @param is_used @@ -399,7 +398,7 @@ template std::vector> Graph_::find_conne if (pair.first != 0 && variables_degree[pair.first] > 0) { if (!is_used.contains(pair.first)) { std::vector connected_component; - depth_first_search(pair.first, is_used, connected_component); + this->depth_first_search(pair.first, is_used, connected_component); std::sort(connected_component.begin(), connected_component.end()); connected_components.emplace_back(connected_component); } @@ -410,7 +409,12 @@ template std::vector> Graph_::find_conne /** * @brief this method removes variables that were created in a function decompose_into_default_range - * because they are false cases and don't give any useful information about security + * because they are false cases and don't give any useful information about security of the circuit. + * decompose_into_default_range function creates addition gates with shifts for intermediate variables, + * i.e. variables from left, right and output wires. They have variable gates count = 1 or 2, but they are not + * dangerous. so, we have to remove these variables from the analyzer. The situation is dangerous, if first variable + * from accumulators have variables gate count = 1. It means that it was used only in decompose gate, and it's not + * properly constrained. * @tparam FF * @param ultra_circuit_constructor * @param variables_in_one_gate @@ -431,18 +435,18 @@ inline size_t Graph_::process_current_decompose_chain(bb::UltraCircuitBuilde // we have to remove left, right and output wires of the current gate, cause they'are new_limbs, and they are // useless for the analyzer auto fourth_idx = arithmetic_block.w_4()[current_index]; - accumulators_indices.emplace_back(to_real(ultra_circuit_constructor, fourth_idx)); + accumulators_indices.emplace_back(this->to_real(ultra_circuit_constructor, fourth_idx)); auto left_idx = arithmetic_block.w_l()[current_index]; if (left_idx != zero_idx) { - variables_in_one_gate.erase(to_real(ultra_circuit_constructor, left_idx)); + variables_in_one_gate.erase(this->to_real(ultra_circuit_constructor, left_idx)); } auto right_idx = arithmetic_block.w_r()[current_index]; if (right_idx != zero_idx) { - variables_in_one_gate.erase(to_real(ultra_circuit_constructor, right_idx)); + variables_in_one_gate.erase(this->to_real(ultra_circuit_constructor, right_idx)); } auto out_idx = arithmetic_block.w_o()[current_index]; if (out_idx != zero_idx) { - variables_in_one_gate.erase(to_real(ultra_circuit_constructor, out_idx)); + variables_in_one_gate.erase(this->to_real(ultra_circuit_constructor, out_idx)); } auto q_arith = arithmetic_block.q_arith()[current_index]; if (q_arith == 1 || current_index == arithmetic_block.size() - 1) { @@ -482,7 +486,7 @@ inline void Graph_::remove_unnecessary_decompose_variables(bb::UltraCircuitB { auto is_power_two = [&](const uint256_t& number) { return number > 0 && ((number & (number - 1)) == 0); }; auto find_position = [&](uint32_t variable_index) { - return decompose_variables.contains(to_real(ultra_circuit_builder, variable_index)); + return decompose_variables.contains(this->to_real(ultra_circuit_builder, variable_index)); }; auto& arithmetic_block = ultra_circuit_builder.blocks.arithmetic; if (arithmetic_block.size() > 0) { @@ -511,7 +515,7 @@ inline void Graph_::remove_unnecessary_decompose_variables(bb::UltraCircuitB if (((find_left && find_right && find_out) || (find_left && find_right && !find_out) || (find_left && find_right && !find_out) || (find_left && !find_right && !find_out)) && !find_fourth) { - i = process_current_decompose_chain(ultra_circuit_builder, variables_in_one_gate, i); + i = this->process_current_decompose_chain(ultra_circuit_builder, variables_in_one_gate, i); } } } @@ -543,8 +547,8 @@ inline void Graph_::remove_unnecessary_aes_plookup_variables(std::unordered_ BasicTableId::AES_SPARSE_NORMALIZE }; auto& lookup_block = ultra_circuit_builder.blocks.lookup; if (aes_plookup_tables.contains(table_id)) { - uint32_t real_out_idx = to_real(ultra_circuit_builder, lookup_block.w_o()[gate_index]); - uint32_t real_right_idx = to_real(ultra_circuit_builder, lookup_block.w_r()[gate_index]); + uint32_t real_out_idx = this->to_real(ultra_circuit_builder, lookup_block.w_o()[gate_index]); + uint32_t real_right_idx = this->to_real(ultra_circuit_builder, lookup_block.w_r()[gate_index]); if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { bool find_out = find_position(real_out_idx); auto q_c = lookup_block.q_c()[gate_index]; @@ -558,7 +562,10 @@ inline void Graph_::remove_unnecessary_aes_plookup_variables(std::unordered_ } /** - * @brief this method removes false cases in sha256 lookup tables + * @brief this method removes false cases in sha256 lookup tables. + * tables which are enumerated in the unordered set sha256_plookup_tables + * are used in read_from_1_to_2_table function which return C2[0], so C3[0] + * isn't used anymore, but this situation isn't dangerous. So, we have to remove these variables. * @tparam FF * @param variables_in_one_gate * @param ultra_circuit_builder @@ -590,8 +597,8 @@ inline void Graph_::remove_unnecessary_sha256_plookup_variables(std::unorder BasicTableId::SHA256_BASE28_ROTATE3, BasicTableId::SHA256_BASE28_ROTATE6 }; if (sha256_plookup_tables.contains(table_id)) { - uint32_t real_right_idx = to_real(ultra_circuit_builder, lookup_block.w_r()[gate_index]); - uint32_t real_out_idx = to_real(ultra_circuit_builder, lookup_block.w_o()[gate_index]); + uint32_t real_right_idx = this->to_real(ultra_circuit_builder, lookup_block.w_r()[gate_index]); + uint32_t real_out_idx = this->to_real(ultra_circuit_builder, lookup_block.w_o()[gate_index]); if (variables_gate_counts[real_out_idx] != 1 || variables_gate_counts[real_right_idx] != 1) { // auto q_m = lookup_block.q_m()[gate_index]; auto q_c = lookup_block.q_c()[gate_index]; @@ -637,28 +644,30 @@ inline void Graph_::process_current_plookup_gate(bb::UltraCircuitBuilder& ul std::set column_3(table.column_3.begin(), table.column_3.end()); bb::plookup::BasicTableId table_id = table.id; // false cases for AES - remove_unnecessary_aes_plookup_variables( + this->remove_unnecessary_aes_plookup_variables( variables_in_one_gate, ultra_circuit_builder, table_id, gate_index); // false cases for sha256 - remove_unnecessary_sha256_plookup_variables( + this->remove_unnecessary_sha256_plookup_variables( variables_in_one_gate, ultra_circuit_builder, table_id, gate_index); + // if the amount of unique elements from columns of plookup tables = 1, it means that + // variable from this column aren't used and we can remove it. if (column_1.size() == 1) { uint32_t left_idx = lookup_block.w_l()[gate_index]; - uint32_t real_left_idx = to_real(ultra_circuit_builder, left_idx); + uint32_t real_left_idx = this->to_real(ultra_circuit_builder, left_idx); bool find_left = find_position(real_left_idx); if (find_left) { variables_in_one_gate.erase(real_left_idx); } } if (column_2.size() == 1) { - uint32_t real_right_idx = to_real(ultra_circuit_builder, lookup_block.w_r()[gate_index]); + uint32_t real_right_idx = this->to_real(ultra_circuit_builder, lookup_block.w_r()[gate_index]); bool find_right = find_position(real_right_idx); if (find_right) { variables_in_one_gate.erase(real_right_idx); } } if (column_3.size() == 1) { - uint32_t real_out_idx = to_real(ultra_circuit_builder, lookup_block.w_o()[gate_index]); + uint32_t real_out_idx = this->to_real(ultra_circuit_builder, lookup_block.w_o()[gate_index]); bool find_out = find_position(real_out_idx); if (find_out) { variables_in_one_gate.erase(real_out_idx); @@ -682,7 +691,7 @@ inline void Graph_::remove_unnecessary_plookup_variables(bb::UltraCircuitBui auto& lookup_block = ultra_circuit_builder.blocks.lookup; if (lookup_block.size() > 0) { for (size_t i = 0; i < lookup_block.size(); i++) { - process_current_plookup_gate(ultra_circuit_builder, variables_in_one_gate, i); + this->process_current_plookup_gate(ultra_circuit_builder, variables_in_one_gate, i); } } } @@ -699,7 +708,7 @@ std::unordered_set Graph_::show_variables_in_one_gate(bb::UltraCir { std::unordered_set variables_in_one_gate; for (const auto& pair : variables_gate_counts) { - bool is_not_constant_variable = check_is_not_constant_variable(ultra_circuit_builder, pair.first); + bool is_not_constant_variable = this->check_is_not_constant_variable(ultra_circuit_builder, pair.first); if (pair.second == 1 && pair.first != 0 && is_not_constant_variable) { variables_in_one_gate.insert(pair.first); } @@ -708,15 +717,15 @@ std::unordered_set Graph_::show_variables_in_one_gate(bb::UltraCir std::unordered_set decompose_varialbes; for (auto& pair : range_lists) { for (auto& elem : pair.second.variable_indices) { - bool is_not_constant_variable = check_is_not_constant_variable(ultra_circuit_builder, elem); + bool is_not_constant_variable = this->check_is_not_constant_variable(ultra_circuit_builder, elem); if (variables_gate_counts[ultra_circuit_builder.real_variable_index[elem]] == 1 && is_not_constant_variable) { decompose_varialbes.insert(ultra_circuit_builder.real_variable_index[elem]); } } } - remove_unnecessary_decompose_variables(ultra_circuit_builder, variables_in_one_gate, decompose_varialbes); - remove_unnecessary_plookup_variables(ultra_circuit_builder, variables_in_one_gate); + this->remove_unnecessary_decompose_variables(ultra_circuit_builder, variables_in_one_gate, decompose_varialbes); + this->remove_unnecessary_plookup_variables(ultra_circuit_builder, variables_in_one_gate); return variables_in_one_gate; } @@ -779,7 +788,9 @@ template void Graph_::print_connected_components() } /** - * @brief this method prints a number of gate for each variable + * @brief this method prints a number of gates for each variable. + * while processing the arithmetic circuit, we count for each variable the number of gates it has participated in. + * sometimes for debugging purposes it is useful to see how many gates each variable has participated in. * @tparam FF */ @@ -791,7 +802,10 @@ template void Graph_::print_variables_gate_counts() } /** - * @brief this method prints a number of edges for each variable + * @brief this method prints a number of edges for each variable. + * while processing the arithmetic circuit, we conut for each variable the number of edges, i.e. connections with other + * variables though the gates. perhaps in the future counting the number of edges for each vertex can be useful for + * analysis, and this function will be used for debugging. * @tparam FF */ diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp index 929d02efaa59..c4c88e1e1596 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.hpp @@ -111,9 +111,9 @@ template class Graph_ { variable_adjacency_lists; // we use this data structure to contain information about variables and their // connections between each other std::unordered_map - variables_gate_counts; // we use this data structure to count, how many gates used every variable + variables_gate_counts; // we use this data structure to count, how many gates use every variable std::unordered_map - variables_degree; // we use this data structure to count, how many edges have every variable + variables_degree; // we use this data structure to count, how many every variable have edges }; using Graph = Graph_; \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp index ae31a62d7aa4..9db54f964295 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_aes128.test.cpp @@ -32,7 +32,7 @@ bool check_in_vector(const std::vector& input_vector, const uint32_t& * graph must be consist from one connected component */ -TEST(stdlib_aes, test_graph_for_aes_64_bytes) +TEST(boomerang_stdlib_aes, test_graph_for_aes_64_bytes) { uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; uint8_t iv[16]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; @@ -78,7 +78,7 @@ TEST(stdlib_aes, test_graph_for_aes_64_bytes) * gates count = 1, because it's the circuit for test. So, we can ignore these variables */ -TEST(stdlib_aes, test_variable_gates_count_for_aes128cbc) +TEST(boomerang_stdlib_aes, test_variable_gates_count_for_aes128cbc) { uint8_t key[16]{ 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }; diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp index 4af9be1e1b3c..934e92b568a5 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake2s.test.cpp @@ -24,7 +24,7 @@ using public_witness_t = public_witness_t; * all graphs must have one connected component. */ -TEST(stdlib_blake2s, test_graph_for_blake2s_single_block_plookup) +TEST(boomerang_stdlib_blake2s, test_graph_for_blake2s_single_block_plookup) { Builder builder; std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01"; @@ -36,10 +36,9 @@ TEST(stdlib_blake2s, test_graph_for_blake2s_single_block_plookup) Graph graph = Graph(builder); auto connected_components = graph.find_connected_components(); EXPECT_EQ(connected_components.size(), 1); - graph.print_connected_components(); } -TEST(stdlib_blake2s, test_graph_for_blake2s_double_block_plookup) +TEST(boomerang_stdlib_blake2s, test_graph_for_blake2s_double_block_plookup) { Builder builder; std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; @@ -52,8 +51,6 @@ TEST(stdlib_blake2s, test_graph_for_blake2s_double_block_plookup) EXPECT_EQ(output.get_value(), std::vector(expected.begin(), expected.end())); - info("builder gates = ", builder.get_num_gates()); - Graph graph = Graph(builder); auto connected_components = graph.find_connected_components(); EXPECT_EQ(connected_components.size(), 1); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp index 668d2486d258..d826f1e080b2 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_blake3s.test.cpp @@ -21,7 +21,7 @@ using UltraBuilder = UltraCircuitBuilder; * All graphs must have one connected component */ -TEST(stdlib_blake3s, test_single_block_plookup) +TEST(boomerang_stdlib_blake3s, test_single_block_plookup) { auto builder = UltraBuilder(); std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz01"; @@ -39,7 +39,7 @@ TEST(stdlib_blake3s, test_single_block_plookup) EXPECT_EQ(connected_components.size(), 1); } -TEST(stdlib_blake3s, test_double_block_plookup) +TEST(boomerang_stdlib_blake3s, test_double_block_plookup) { auto builder = UltraBuilder(); std::string input = "abcdefghijklmnopqrstuvwxyz0123456789abcdefghijklmnopqrstuvwxyz0123456789"; diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp index afa8f5e2e760..4a10bb5d804e 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp @@ -25,7 +25,7 @@ using field_ct = field_t; all these tests check graph description for sha256 circuits. All circuits have to consist from 1 connected component */ -TEST(stdlib_sha256, test_graph_for_sha256_55_bytes) +TEST(boomerang_stdlib_sha256, test_graph_for_sha256_55_bytes) { // 55 bytes is the largest number of bytes that can be hashed in a single block, // accounting for the single padding bit, and the 64 size bits required by the SHA-256 standard. @@ -43,7 +43,7 @@ TEST(stdlib_sha256, test_graph_for_sha256_55_bytes) EXPECT_EQ(connected_components.size(), 1); } -HEAVY_TEST(stdlib_sha256, test_graph_for_sha256_NIST_vector_five) +HEAVY_TEST(boomerang_stdlib_sha256, test_graph_for_sha256_NIST_vector_five) { typedef stdlib::field_t field_pt; typedef stdlib::packed_byte_array packed_byte_array_pt; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp index 99c29d7751f8..1bba02baf908 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/hash/blake2s/blake2s.test.cpp @@ -87,4 +87,7 @@ TEST(stdlib_blake2s, test_double_block_plookup) EXPECT_EQ(output.get_value(), std::vector(expected.begin(), expected.end())); info("builder gates = ", builder.get_num_gates()); + + bool proof_result = CircuitChecker::check(builder); + EXPECT_EQ(proof_result, true); } From d0f4fd4f9dbd88aca769bab4fa2d7d31bbb66a91 Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Fri, 1 Nov 2024 17:56:22 +0000 Subject: [PATCH 20/21] corrected Sasha's comments + renamed tests + removed some info from sha256 tests --- .../boomerang_value_detection/graph.cpp | 80 ++++++++++--------- .../graph_description.test.cpp | 36 ++++----- .../graph_description_sha256.test.cpp | 2 - .../variables_gate_counts.sha256.test.cpp | 12 +-- 4 files changed, 65 insertions(+), 65 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp index efb2ff3b1316..4e518243fa01 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp @@ -18,13 +18,13 @@ inline void Graph_::process_gate_variables(UltraCircuitBuilder& ultra_circui auto unique_variables = std::unique(gate_variables.begin(), gate_variables.end()); gate_variables.erase(unique_variables, gate_variables.end()); if (gate_variables.empty()) { - } else { - for (size_t i = 0; i < gate_variables.size(); i++) { - gate_variables[i] = this->to_real(ultra_circuit_builder, gate_variables[i]); - } - for (const auto& variable_index : gate_variables) { - variables_gate_counts[variable_index] += 1; - } + return; + } + for (size_t i = 0; i < gate_variables.size(); i++) { + gate_variables[i] = this->to_real(ultra_circuit_builder, gate_variables[i]); + } + for (const auto& variable_index : gate_variables) { + variables_gate_counts[variable_index] += 1; } } @@ -242,11 +242,11 @@ template Graph_::Graph_(bb::UltraCircuitBuilder& ultra_circuit std::vector sorted_variables; for (size_t i = 0; i < range_gates; i++) { auto current_gate = this->get_sort_constraint_connected_component(ultra_circuit_constructor, i); - if (!current_gate.empty()) { - sorted_variables.insert(sorted_variables.end(), current_gate.begin(), current_gate.end()); - } else { + if (current_gate.empty()) { this->connect_all_variables_in_vector(ultra_circuit_constructor, sorted_variables, true); sorted_variables.clear(); + } else { + sorted_variables.insert(sorted_variables.end(), current_gate.begin(), current_gate.end()); } } } @@ -302,37 +302,37 @@ void Graph_::connect_all_variables_in_vector(bb::UltraCircuitBuilder& ultra_ bool is_sorted_variables) { if (variables_vector.empty()) { - } else { - if (is_sorted_variables) { - for (size_t i = 0; i < variables_vector.size() - 1; i++) { - if (variables_vector[i] != ultra_circuit_builder.zero_idx && - variables_vector[i + 1] != ultra_circuit_builder.zero_idx && - variables_vector[i] != variables_vector[i + 1]) { - { - bool first_variable_is_not_constant = - this->check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i]); - bool second_variable_is_not_constant = - this->check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i + 1]); - if (first_variable_is_not_constant && second_variable_is_not_constant) { - this->add_new_edge(variables_vector[i], variables_vector[i + 1]); - } + return; + } + if (is_sorted_variables) { + for (size_t i = 0; i < variables_vector.size() - 1; i++) { + if (variables_vector[i] != ultra_circuit_builder.zero_idx && + variables_vector[i + 1] != ultra_circuit_builder.zero_idx && + variables_vector[i] != variables_vector[i + 1]) { + { + bool first_variable_is_not_constant = + this->check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i]); + bool second_variable_is_not_constant = + this->check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i + 1]); + if (first_variable_is_not_constant && second_variable_is_not_constant) { + this->add_new_edge(variables_vector[i], variables_vector[i + 1]); } } } - } else { - for (size_t i = 0; i < variables_vector.size() - 1; i++) { - for (size_t j = i + 1; j < variables_vector.size(); j++) { - if (variables_vector[i] != ultra_circuit_builder.zero_idx && - variables_vector[j] != ultra_circuit_builder.zero_idx && - variables_vector[i] != variables_vector[j]) { - - bool first_variable_is_not_constant = - this->check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i]); - bool second_variable_is_not_constant = - this->check_is_not_constant_variable(ultra_circuit_builder, variables_vector[j]); - if (first_variable_is_not_constant && second_variable_is_not_constant) { - this->add_new_edge(variables_vector[i], variables_vector[j]); - } + } + } else { + for (size_t i = 0; i < variables_vector.size() - 1; i++) { + for (size_t j = i + 1; j < variables_vector.size(); j++) { + if (variables_vector[i] != ultra_circuit_builder.zero_idx && + variables_vector[j] != ultra_circuit_builder.zero_idx && + variables_vector[i] != variables_vector[j]) { + + bool first_variable_is_not_constant = + this->check_is_not_constant_variable(ultra_circuit_builder, variables_vector[i]); + bool second_variable_is_not_constant = + this->check_is_not_constant_variable(ultra_circuit_builder, variables_vector[j]); + if (first_variable_is_not_constant && second_variable_is_not_constant) { + this->add_new_edge(variables_vector[i], variables_vector[j]); } } } @@ -619,7 +619,9 @@ inline void Graph_::remove_unnecessary_sha256_plookup_variables(std::unorder } /** - * @brief this method removes false cases in lookup table for a given gate + * @brief this method removes false cases in lookup table for a given gate. + * it uses all functions above for lookup tables to remove all variables that appear in one gate, + * if they are not dangerous * @tparam FF * @param ultra_circuit_builder * @param variables_in_one_gate diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp index ed9977095e55..26f50cc8db11 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description.test.cpp @@ -17,7 +17,7 @@ using namespace bb; the number of connected components = the number of pair (i, j), 0<=i, j <16, i.e 256 */ -TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates) +TEST(boomerang_ultra_circuit_constructor, test_graph_for_arithmetic_gates) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -49,7 +49,7 @@ TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates) * It must be one connected component, cause all gates have shifts */ -TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates_with_shifts) +TEST(boomerang_ultra_circuit_constructor, test_graph_for_arithmetic_gates_with_shifts) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); for (size_t i = 0; i < 16; ++i) { @@ -79,7 +79,7 @@ TEST(ultra_circuit_constructor, test_graph_for_arithmetic_gates_with_shifts) all variables must be isolated and the number of connected components = 0, all variables in one gate */ -TEST(ultra_circuit_constructor, test_graph_for_boolean_gates) +TEST(boomerang_ultra_circuit_constructor, test_graph_for_boolean_gates) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -104,7 +104,7 @@ TEST(ultra_circuit_constructor, test_graph_for_boolean_gates) * x1, y1, x2, y2, x3, y3 */ -TEST(ultra_circuit_constructor, test_graph_for_elliptic_add_gate) +TEST(boomerang_ultra_circuit_constructor, test_graph_for_elliptic_add_gate) { typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; @@ -137,7 +137,7 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_add_gate) x1, y1, x3, y3 */ -TEST(ultra_circuit_constructor, test_graph_for_elliptic_double_gate) +TEST(boomerang_ultra_circuit_constructor, test_graph_for_elliptic_double_gate) { typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; @@ -167,7 +167,7 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_double_gate) x5, y5, x6, y6, x7, y7, x8, y8 */ -TEST(ultra_circuit_constructor, test_graph_for_elliptic_together) +TEST(boomerang_ultra_circuit_constructor, test_graph_for_elliptic_together) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -221,7 +221,7 @@ TEST(ultra_circuit_constructor, test_graph_for_elliptic_together) e_idx, f_idx, g_idx, h_idx */ -TEST(ultra_circuit_constructor, test_graph_for_sort_constraints) +TEST(boomerang_ultra_circuit_constructor, test_graph_for_sort_constraints) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); fr a = fr::one(); @@ -259,7 +259,7 @@ TEST(ultra_circuit_constructor, test_graph_for_sort_constraints) a1_idx, b1_idx, ..., h1_idx */ -TEST(ultra_circuit_constructor, test_graph_for_sort_constraints_with_edges) +TEST(boomerang_ultra_circuit_constructor, test_graph_for_sort_constraints_with_edges) { fr a = fr::one(); fr b = fr(2); @@ -314,7 +314,7 @@ TEST(ultra_circuit_constructor, test_graph_for_sort_constraints_with_edges) the result is one connected component */ -TEST(ultra_circuit_constructor, test_graph_with_plookup_accumulators) +TEST(boomerang_ultra_circuit_constructor, test_graph_with_plookup_accumulators) { UltraCircuitBuilder circuit_builder = UltraCircuitBuilder(); @@ -343,7 +343,7 @@ TEST(ultra_circuit_constructor, test_graph_with_plookup_accumulators) in circuit */ -TEST(ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate) +TEST(boomerang_ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -377,7 +377,7 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate) * Other variables have gates count = 1. */ -TEST(ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate_with_shifts) +TEST(boomerang_ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate_with_shifts) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -414,7 +414,7 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_arithmetic_gate_ * all variables except for zero index must have gates count = 1. */ -TEST(ultra_circuit_constructor, test_variables_gates_counts_for_boolean_gates) +TEST(boomerang_ultra_circuit_constructor, test_variables_gates_counts_for_boolean_gates) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); @@ -438,7 +438,7 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_boolean_gates) * all variables in 2 connected components must have gates count = 1 */ -TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constraints) +TEST(boomerang_ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constraints) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); fr a = fr::one(); @@ -482,7 +482,7 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constrain * all variables in 2 connected components must have gates count = 1 */ -TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constraints_with_edges) +TEST(boomerang_ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constraints_with_edges) { fr a = fr::one(); fr b = fr(2); @@ -545,7 +545,7 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_sorted_constrain * all variables in connected components must have gates count = 1 */ -TEST(ultra_circuit_constructor, test_variables_gates_counts_for_ecc_add_gates) +TEST(boomerang_ultra_circuit_constructor, test_variables_gates_counts_for_ecc_add_gates) { typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; @@ -583,7 +583,7 @@ TEST(ultra_circuit_constructor, test_variables_gates_counts_for_ecc_add_gates) * all variables in connected components must have gates count = 1. */ -TEST(ultra_circuit_constructor, test_variables_gates_counts_for_ecc_dbl_gate) +TEST(boomerang_ultra_circuit_constructor, test_variables_gates_counts_for_ecc_dbl_gate) { typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; @@ -626,7 +626,7 @@ std::vector add_variables(UltraCircuitBuilder& circuit_constructor, st * all variables must be in one connected component. */ -TEST(ultra_circuit_constructor, test_graph_for_range_constraints) +TEST(boomerang_ultra_circuit_constructor, test_graph_for_range_constraints) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); auto indices = add_variables(circuit_constructor, { 1, 2, 3, 4 }); @@ -644,7 +644,7 @@ TEST(ultra_circuit_constructor, test_graph_for_range_constraints) * all variables must be in one connected component */ -TEST(ultra_circuit_constructor, composed_range_constraint) +TEST(boomerang_ultra_circuit_constructor, composed_range_constraint) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); auto c = fr::random_element(); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp index 4a10bb5d804e..0370398d81d2 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_sha256.test.cpp @@ -36,8 +36,6 @@ TEST(boomerang_stdlib_sha256, test_graph_for_sha256_55_bytes) std::vector output = output_bits.to_unverified_byte_slices(4); - info("num gates = ", builder.get_num_gates()); - Graph graph = Graph(builder); auto connected_components = graph.find_connected_components(); EXPECT_EQ(connected_components.size(), 1); diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp index 8a756becb661..c85b25a52179 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/variables_gate_counts.sha256.test.cpp @@ -55,7 +55,7 @@ bool check_in_range_lists(const uint32_t& real_var_index, const uint64_t& target * and they are not dangerous. */ -TEST(stdlib_sha256, test_variables_gate_counts_for_sha256_55_bytes) +TEST(boomerang_stdlib_sha256, test_variables_gate_counts_for_sha256_55_bytes) { // 55 bytes is the largest number of bytes that can be hashed in a single block, // accounting for the single padding bit, and the 64 size bits required by the SHA-256 standard. @@ -79,7 +79,7 @@ TEST(stdlib_sha256, test_variables_gate_counts_for_sha256_55_bytes) } } -TEST(stdlib_sha256, test_variable_gates_count_for_sha256_NIST_vector_one) +TEST(boomerang_stdlib_sha256, test_variable_gates_count_for_sha256_NIST_vector_one) { auto builder = Builder(); packed_byte_array_ct input(&builder, "abc"); @@ -96,7 +96,7 @@ TEST(stdlib_sha256, test_variable_gates_count_for_sha256_NIST_vector_one) } } -TEST(stdlib_sha256, test_variable_gates_count_for_sha256_NIST_vector_two) +TEST(boomerang_stdlib_sha256, test_variable_gates_count_for_sha256_NIST_vector_two) { auto builder = Builder(); @@ -114,7 +114,7 @@ TEST(stdlib_sha256, test_variable_gates_count_for_sha256_NIST_vector_two) } } -TEST(stdlib_sha256, test_variable_gates_count_sha256_NIST_vector_three) +TEST(boomerang_stdlib_sha256, test_variable_gates_count_sha256_NIST_vector_three) { auto builder = Builder(); @@ -132,7 +132,7 @@ TEST(stdlib_sha256, test_variable_gates_count_sha256_NIST_vector_three) } } -TEST(stdlib_sha256, test_variable_gates_count_sha256_NIST_vector_four) +TEST(boomerang_stdlib_sha256, test_variable_gates_count_sha256_NIST_vector_four) { auto builder = Builder(); @@ -150,7 +150,7 @@ TEST(stdlib_sha256, test_variable_gates_count_sha256_NIST_vector_four) } } -HEAVY_TEST(stdlib_sha256, test_variable_gates_count_for_sha256_NIST_vector_five) +HEAVY_TEST(boomerang_stdlib_sha256, test_variable_gates_count_for_sha256_NIST_vector_five) { auto builder = Builder(); From 0e238fff23ea50f4d22f201831052badb10ae231 Mon Sep 17 00:00:00 2001 From: DanielKotov Date: Fri, 1 Nov 2024 19:16:53 +0000 Subject: [PATCH 21/21] remove my useless solution for standard circuit builder and tests for it --- .../standard_circuit_builder.test.cpp | 97 ------------------- 1 file changed, 97 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/standard_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/standard_circuit_builder.test.cpp index 4e6a039bbb18..56f12a173487 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/standard_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/standard_circuit_builder.test.cpp @@ -465,101 +465,4 @@ TEST(standard_circuit_constructor, test_check_circuit_broken) bool result = CircuitChecker::check(circuit_constructor); EXPECT_EQ(result, false); -} - -TEST(standard_circuit, test_boomerang_value_1) -{ - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::random_element(); - uint32_t a_idx = circuit_constructor.add_public_variable(a); - fr b = fr::random_element(); - fr c = a + b; - fr d = fr::random_element(); - fr e = d + a; // - // uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - uint32_t d_idx = circuit_constructor.add_variable(d); - uint32_t e_idx = circuit_constructor.add_variable(e); - uint32_t a_duplicate_idx = circuit_constructor.add_variable( - a); // вот это бумеранг, потому что e работало именно с a, но между ними a_duplicate и a нет никакой связи. - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate( - { a_duplicate_idx, d_idx, e_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - - bool result = CircuitChecker::check(circuit_constructor); - bool result1 = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - EXPECT_EQ(result1, true); - circuit_constructor.print_boomerang_variables(); -} - -TEST(standard_circuit_constructor, print_boomerang_variables) -{ - // need to calculate expression a + 2 * b + 3 * c - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::random_element(); - fr b = fr::random_element(); - fr c = fr::random_element(); - fr two = fr(2); - fr three = fr(3); - uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - fr d1 = circuit_constructor.get_variable(a_idx) + two * circuit_constructor.get_variable(b_idx); - uint32_t d1_idx = circuit_constructor.add_variable(d1); - fr d2 = circuit_constructor.get_variable(d1_idx) + three * circuit_constructor.get_variable(c_idx); - uint32_t d2_idx = circuit_constructor.add_variable(d2); - circuit_constructor.create_add_gate({ d1_idx, c_idx, d2_idx, fr::one(), three, fr::neg_one(), fr::zero() }); - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - circuit_constructor.print_boomerang_variables(); -} - -TEST(standard_circuit_constructor, test_logic_constraint) -{ - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr(1); - fr b = fr(2); - uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - size_t num_bits = 2; - auto accumulators = circuit_constructor.create_logic_constraint(a_idx, b_idx, num_bits, true); - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - circuit_constructor.print_boomerang_variables(); -} - -TEST(standard_circuit_builder, test_boomerang_value_4) -{ - StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); - fr a = fr::random_element(); - fr b = fr::random_element(); - fr c = a + b; - uint32_t a_idx = circuit_constructor.add_variable(a); - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - fr d = fr::random_element(); - fr e = fr::random_element(); - fr f = d + e; - uint32_t d_idx = circuit_constructor.add_variable(d); - uint32_t e_idx = circuit_constructor.add_variable(e); - uint32_t f_idx = circuit_constructor.add_variable(f); - circuit_constructor.create_add_gate({ d_idx, e_idx, f_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - fr g = c * f; - fr g1 = c + f; - uint32_t g_idx = circuit_constructor.add_variable(g); - uint32_t g1_idx = circuit_constructor.add_variable(g1); - circuit_constructor.create_mul_gate({ c_idx, f_idx, g_idx, fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate({ c_idx, f_idx, g1_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - fr g_dupl = circuit_constructor.get_variable(g_idx); - fr g_inv = g_dupl.invert(); - fr g_2 = g_inv + g1; - uint32_t g_inv_idx = circuit_constructor.add_variable(g_inv); - uint32_t g2_idx = circuit_constructor.add_variable(g_2); - circuit_constructor.create_add_gate({ g_inv_idx, g1_idx, g2_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - bool result = CircuitChecker::check(circuit_constructor); - EXPECT_EQ(result, true); - circuit_constructor.print_boomerang_variables(); } \ No newline at end of file