Skip to content

Commit eeea55a

Browse files
authored
feat: Graph methods for circuit analysis (part 1) (#7948)
Boomerang value detection in ultra circuits not using poseidon and auxiliary gates
1 parent 969a3f0 commit eeea55a

13 files changed

+2228
-2
lines changed

barretenberg/cpp/src/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ endif()
6363

6464
add_subdirectory(barretenberg/client_ivc)
6565
add_subdirectory(barretenberg/bb)
66+
add_subdirectory(barretenberg/boomerang_value_detection)
6667
add_subdirectory(barretenberg/circuit_checker)
6768
add_subdirectory(barretenberg/commitment_schemes)
6869
add_subdirectory(barretenberg/commitment_schemes_recursion)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
barretenberg_module(boomerang_value_detection stdlib_circuit_builders circuit_checker stdlib_primitives numeric stdlib_aes128 stdlib_sha256 stdlib_blake2s stdlib_blake3s)

barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp

+824
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#pragma once
2+
#include "barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp"
3+
#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp"
4+
#include <list>
5+
#include <set>
6+
#include <unordered_map>
7+
#include <unordered_set>
8+
#include <utility>
9+
#include <vector>
10+
11+
/*
12+
* this class describes arithmetic circuit as an undirected graph, where vertices are variables from circuit.
13+
* edges describe connections between variables through gates. We want to find variables that weren't properly
14+
* constrainted/some connections were missed using additional metrics, like in how much gate variable was and number of
15+
* connected components in the graph. if variable was in one connected component, it means that this variable wasn't
16+
* constrained properly. if number of connected components > 1, it means that there were missed some connections between
17+
* variables.
18+
*/
19+
template <typename FF> class Graph_ {
20+
public:
21+
Graph_() = default;
22+
Graph_(const Graph_& other) = delete;
23+
Graph_(Graph_&& other) = delete;
24+
Graph_& operator=(const Graph_& other) = delete;
25+
Graph_&& operator=(Graph_&& other) = delete;
26+
Graph_(const bb::StandardCircuitBuilder_<FF>& circuit_constructor);
27+
Graph_(bb::UltraCircuitBuilder& ultra_circuit_constructor);
28+
29+
uint32_t to_real(bb::UltraCircuitBuilder& ultra_circuit_constructor, const uint32_t& variable_index)
30+
{
31+
return ultra_circuit_constructor.real_variable_index[variable_index];
32+
};
33+
void process_gate_variables(bb::UltraCircuitBuilder& ultra_circuit_constructor,
34+
std::vector<uint32_t>& gate_variables);
35+
36+
std::unordered_map<uint32_t, size_t> get_variables_gate_counts() { return this->variables_gate_counts; };
37+
38+
std::vector<uint32_t> get_arithmetic_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
39+
size_t index);
40+
std::vector<uint32_t> get_elliptic_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
41+
size_t index);
42+
std::vector<uint32_t> get_plookup_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
43+
size_t index);
44+
std::vector<uint32_t> get_sort_constraint_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
45+
size_t index);
46+
47+
void add_new_edge(const uint32_t& first_variable_index, const uint32_t& second_variable_index);
48+
std::vector<uint32_t> get_variable_adjacency_list(const uint32_t& variable_index)
49+
{
50+
return variable_adjacency_lists[variable_index];
51+
};
52+
53+
void depth_first_search(const uint32_t& variable_index,
54+
std::unordered_set<uint32_t>& is_used,
55+
std::vector<uint32_t>& connected_component);
56+
std::vector<std::vector<uint32_t>> find_connected_components();
57+
58+
std::vector<uint32_t> find_variables_with_degree_one();
59+
std::unordered_set<uint32_t> get_variables_in_one_gate();
60+
61+
bool find_arithmetic_gate_for_variable(bb::UltraCircuitBuilder& ultra_circuit_builder,
62+
const uint32_t& variable_idx);
63+
bool find_elliptic_gate_for_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, const uint32_t& variable_idx);
64+
bool find_lookup_gate_for_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, const uint32_t& variable_idx);
65+
66+
size_t get_distance_between_variables(const uint32_t& first_variable_index, const uint32_t& second_variable_index);
67+
bool check_vertex_in_connected_component(const std::vector<uint32_t>& connected_component,
68+
const uint32_t& var_index);
69+
70+
void connect_all_variables_in_vector(bb::UltraCircuitBuilder& ultra_circuit_builder,
71+
const std::vector<uint32_t>& variables_vector,
72+
bool is_sorted_variables);
73+
bool check_is_not_constant_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, const uint32_t& variable_index);
74+
75+
std::pair<std::vector<uint32_t>, size_t> get_connected_component_with_index(
76+
const std::vector<std::vector<uint32_t>>& connected_components, size_t index);
77+
78+
std::unordered_set<uint32_t> get_variables_in_one_gate_without_range_constraints(
79+
bb::UltraCircuitBuilder& ultra_circuit_builder);
80+
81+
size_t process_current_decompose_chain(bb::UltraCircuitBuilder& ultra_circuit_constructor,
82+
std::unordered_set<uint32_t>& variables_in_one_gate,
83+
size_t index);
84+
void process_current_plookup_gate(bb::UltraCircuitBuilder& ultra_circuit_builder,
85+
std::unordered_set<uint32_t>& variables_in_one_gate,
86+
size_t gate_index);
87+
void remove_unnecessary_decompose_variables(bb::UltraCircuitBuilder& ultra_circuit_builder,
88+
std::unordered_set<uint32_t>& variables_in_on_gate,
89+
const std::unordered_set<uint32_t>& decompose_variables);
90+
void remove_unnecessary_plookup_variables(bb::UltraCircuitBuilder& ultra_circuit_builder,
91+
std::unordered_set<uint32_t>& variables_in_on_gate);
92+
std::unordered_set<uint32_t> show_variables_in_one_gate(bb::UltraCircuitBuilder& ultra_circuit_builder);
93+
94+
void remove_unnecessary_aes_plookup_variables(std::unordered_set<uint32_t>& variables_in_one_gate,
95+
bb::UltraCircuitBuilder& ultra_circuit_builder,
96+
bb::plookup::BasicTableId& table_id,
97+
size_t gate_index);
98+
void remove_unnecessary_sha256_plookup_variables(std::unordered_set<uint32_t>& variables_in_one_gate,
99+
bb::UltraCircuitBuilder& ultra_circuit_builder,
100+
bb::plookup::BasicTableId& table_id,
101+
size_t gate_index);
102+
103+
void print_graph();
104+
void print_connected_components();
105+
void print_variables_gate_counts();
106+
void print_variables_edge_counts();
107+
~Graph_() = default;
108+
109+
private:
110+
std::unordered_map<uint32_t, std::vector<uint32_t>>
111+
variable_adjacency_lists; // we use this data structure to contain information about variables and their
112+
// connections between each other
113+
std::unordered_map<uint32_t, size_t>
114+
variables_gate_counts; // we use this data structure to count, how many gates use every variable
115+
std::unordered_map<uint32_t, size_t>
116+
variables_degree; // we use this data structure to count, how many every variable have edges
117+
};
118+
119+
using Graph = Graph_<bb::fr>;

0 commit comments

Comments
 (0)