Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
graph.hpp
Go to the documentation of this file.
1#pragma once
3#include <list>
4#include <set>
5#include <typeinfo>
6#include <unordered_map>
7#include <unordered_set>
8#include <utility>
9#include <vector>
10
11namespace cdg {
12
29
30struct KeyHasher {
31 size_t operator()(const KeyPair& pair) const
32 {
33 size_t combined_hash = 0;
34 // Golden ratio constant (2^32 / phi) used in hash combining for better distribution
35 constexpr size_t HASH_COMBINE_CONSTANT = 0x9e3779b9;
36 auto hash_combiner = [](size_t lhs, size_t rhs) {
37 return lhs ^ (rhs + HASH_COMBINE_CONSTANT + (lhs << 6) + (lhs >> 2));
38 };
39 combined_hash = hash_combiner(combined_hash, std::hash<uint32_t>()(pair.first));
40 combined_hash = hash_combiner(combined_hash, std::hash<size_t>()(pair.second));
41 return combined_hash;
42 }
43};
44
45struct KeyEquals {
46 bool operator()(const KeyPair& p1, const KeyPair& p2) const
47 {
48 return (p1.first == p2.first && p1.second == p2.second);
49 }
50};
51
52/*
53 * This class describes an arithmetic circuit as an undirected graph, where vertices are variables from the circuit.
54 * Edges describe connections between variables through gates. We want to find variables that weren't properly
55 * constrained or where some connections were missed using additional metrics, such as how many gates a variable appears
56 * in and the number of connected components in the graph. If a variable appears in only one gate, it means that this
57 * variable wasn't constrained properly. If the number of connected components > 1, it means that there were some missed
58 * connections between variables.
59 */
60template <typename FF> class StaticAnalyzer_ {
61 public:
62 StaticAnalyzer_() = default;
63 StaticAnalyzer_(const StaticAnalyzer_& other) = delete;
65 StaticAnalyzer_& operator=(const StaticAnalyzer_& other) = delete;
67 StaticAnalyzer_(bb::UltraCircuitBuilder& ultra_circuit_constructor, bool connect_variables = true);
68
75 std::vector<uint32_t> to_real(bb::UltraCircuitBuilder& ultra_circuit_constructor,
76 std::vector<uint32_t>& variable_indices)
77 {
78 std::vector<uint32_t> real_variable_indices;
79 real_variable_indices.reserve(variable_indices.size());
80 for (auto& variable_index : variable_indices) {
81 real_variable_indices.push_back(to_real(ultra_circuit_constructor, variable_index));
82 }
83 return real_variable_indices;
84 };
85
86 uint32_t to_real(bb::UltraCircuitBuilder& ultra_circuit_constructor, const uint32_t& variable_index)
87 {
88 return ultra_circuit_constructor.real_variable_index[variable_index];
89 };
90 size_t find_block_index(bb::UltraCircuitBuilder& ultra_builder, const UltraBlock& block);
91 void process_gate_variables(std::vector<uint32_t>& gate_variables, size_t gate_index, size_t blk_idx);
92 std::unordered_map<uint32_t, size_t> get_variables_gate_counts() { return this->variables_gate_counts; };
93
95 bb::UltraCircuitBuilder& ultra_circuit_builder, size_t index, size_t block_idx, UltraBlock& blk);
96 std::vector<uint32_t> get_elliptic_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
97 size_t index,
98 size_t block_idx,
99 UltraBlock& blk);
100 std::vector<uint32_t> get_plookup_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
101 size_t index,
102 size_t block_idx,
103 UltraBlock& blk);
104 std::vector<uint32_t> get_sort_constraint_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
105 size_t index,
106 size_t block_idx,
107 UltraBlock& blk);
108 std::vector<uint32_t> get_poseido2s_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
109 size_t index,
110 size_t block_idx,
111 UltraBlock& blk);
112 std::vector<uint32_t> get_memory_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
113 size_t index,
114 size_t block_idx,
115 UltraBlock& blk);
116 std::vector<uint32_t> get_non_native_field_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
117 size_t index,
118 size_t block_idx,
119 UltraBlock& blk);
120 std::vector<uint32_t> get_rom_table_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
121 const bb::RomTranscript& rom_array);
122 std::vector<uint32_t> get_ram_table_connected_component(bb::UltraCircuitBuilder& ultra_builder,
123 const bb::RamTranscript& ram_array);
124
125 void add_new_edge(const uint32_t& first_variable_index, const uint32_t& second_variable_index);
126 std::vector<uint32_t> get_variable_adjacency_list(const uint32_t& variable_index)
127 {
128 return variable_adjacency_lists[variable_index];
129 };
130
131 void depth_first_search(const uint32_t& variable_index,
132 std::unordered_set<uint32_t>& is_used,
133 std::vector<uint32_t>& connected_component);
135
136 std::vector<uint32_t> find_variables_with_degree_one();
137 std::unordered_set<uint32_t> get_variables_in_one_gate();
138
140 const uint32_t& variable_idx);
141 bool find_elliptic_gate_for_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, const uint32_t& variable_idx);
142 bool find_lookup_gate_for_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, const uint32_t& variable_idx);
143
144 size_t get_distance_between_variables(const uint32_t& first_variable_index, const uint32_t& second_variable_index);
145 bool check_vertex_in_connected_component(const std::vector<uint32_t>& connected_component,
146 const uint32_t& var_index);
147
149 const std::vector<uint32_t>& variables_vector);
150 bool check_is_not_constant_variable(bb::UltraCircuitBuilder& ultra_circuit_builder, const uint32_t& variable_index);
151
153 const std::vector<std::vector<uint32_t>>& connected_components, size_t index);
154
156 bb::UltraCircuitBuilder& ultra_circuit_builder);
157
158 size_t process_current_decompose_chain(bb::UltraCircuitBuilder& ultra_circuit_constructor,
159 std::unordered_set<uint32_t>& variables_in_one_gate,
160 size_t index);
161 void process_current_plookup_gate(bb::UltraCircuitBuilder& ultra_circuit_builder, size_t gate_index);
163 std::unordered_set<uint32_t>& variables_in_on_gate,
164 const std::unordered_set<uint32_t>& decompose_variables);
167 std::unordered_set<uint32_t> show_variables_in_one_gate(bb::UltraCircuitBuilder& ultra_circuit_builder);
168
169 void remove_unnecessary_aes_plookup_variables(std::unordered_set<uint32_t>& variables_in_one_gate,
170 bb::UltraCircuitBuilder& ultra_circuit_builder,
172 size_t gate_index);
174 bb::UltraCircuitBuilder& ultra_circuit_builder,
176 size_t gate_index);
178
179 void print_graph();
183 void print_variable_in_one_gate(bb::UltraCircuitBuilder& ultra_builder, const uint32_t real_idx);
184 ~StaticAnalyzer_() = default;
185
186 private:
188 variable_adjacency_lists; // we use this data structure to contain information about variables and their
189 // connections between each other
190 std::unordered_map<uint32_t, size_t>
191 variables_gate_counts; // we use this data structure to count, how many gates use every variable
192 std::unordered_map<uint32_t, size_t>
193 variables_degree; // we use this data structure to count, how many every variable have edges
195 variable_gates; // we use this data structure to store gates and TraceBlocks for every variables, where static
196 // analyzer found them in the circuit.
197 std::unordered_set<uint32_t> variables_in_one_gate;
198 std::unordered_set<uint32_t> fixed_variables;
199};
200
202
203} // namespace cdg
std::vector< uint32_t > real_variable_index
bool find_lookup_gate_for_variable(bb::UltraCircuitBuilder &ultra_circuit_builder, const uint32_t &variable_idx)
std::vector< uint32_t > get_poseido2s_gate_connected_component(bb::UltraCircuitBuilder &ultra_circuit_builder, size_t index, size_t block_idx, UltraBlock &blk)
this method creates connected components from poseidon2 gates
Definition graph.cpp:278
std::unordered_map< uint32_t, std::vector< uint32_t > > variable_adjacency_lists
Definition graph.hpp:188
std::unordered_set< uint32_t > show_variables_in_one_gate(bb::UltraCircuitBuilder &ultra_circuit_builder)
this method returns a final set of variables that were in one gate
Definition graph.cpp:1190
std::vector< uint32_t > get_rom_table_connected_component(bb::UltraCircuitBuilder &ultra_circuit_builder, const bb::RomTranscript &rom_array)
this method gets the ROM table connected component by processing ROM transcript records
Definition graph.cpp:460
std::unordered_set< uint32_t > get_variables_in_one_gate_without_range_constraints(bb::UltraCircuitBuilder &ultra_circuit_builder)
std::unordered_set< uint32_t > variables_in_one_gate
Definition graph.hpp:197
size_t process_current_decompose_chain(bb::UltraCircuitBuilder &ultra_circuit_constructor, std::unordered_set< uint32_t > &variables_in_one_gate, size_t index)
this method removes variables that were created in a function decompose_into_default_range because th...
Definition graph.cpp:827
StaticAnalyzer_(const StaticAnalyzer_ &other)=delete
std::vector< uint32_t > get_variable_adjacency_list(const uint32_t &variable_index)
Definition graph.hpp:126
std::vector< std::vector< uint32_t > > find_connected_components()
this methond finds all connected components in the graph described by adjacency lists
Definition graph.cpp:794
std::vector< uint32_t > get_memory_gate_connected_component(bb::UltraCircuitBuilder &ultra_circuit_builder, size_t index, size_t block_idx, UltraBlock &blk)
this method creates connected components from Memory gates (RAM and ROM consistency checks)
Definition graph.cpp:312
void remove_unnecessary_plookup_variables(bb::UltraCircuitBuilder &ultra_circuit_builder)
this method removes false cases plookup variables from variables in one gate
Definition graph.cpp:1129
std::unordered_map< uint32_t, size_t > variables_degree
Definition graph.hpp:193
void remove_unnecessary_aes_plookup_variables(std::unordered_set< uint32_t > &variables_in_one_gate, bb::UltraCircuitBuilder &ultra_circuit_builder, bb::plookup::BasicTableId &table_id, size_t gate_index)
this method removes false positive cases variables from aes plookup tables. AES_SBOX_MAP,...
Definition graph.cpp:974
bool check_vertex_in_connected_component(const std::vector< uint32_t > &connected_component, const uint32_t &var_index)
void print_graph()
this method prints graph as vertices and their adjacency lists example: we have an undirected graph f...
Definition graph.cpp:1252
~StaticAnalyzer_()=default
std::pair< std::vector< uint32_t >, size_t > get_connected_component_with_index(const std::vector< std::vector< uint32_t > > &connected_components, size_t index)
std::vector< uint32_t > get_ram_table_connected_component(bb::UltraCircuitBuilder &ultra_builder, const bb::RamTranscript &ram_array)
this method gets the RAM table connected component by processing RAM transcript records
Definition graph.cpp:519
void print_variable_in_one_gate(bb::UltraCircuitBuilder &ultra_builder, const uint32_t real_idx)
this method prints all information about the gate where variable was found
Definition graph.cpp:1302
std::unordered_map< uint32_t, size_t > variables_gate_counts
Definition graph.hpp:191
std::vector< uint32_t > get_non_native_field_gate_connected_component(bb::UltraCircuitBuilder &ultra_circuit_builder, size_t index, size_t block_idx, UltraBlock &blk)
this method creates connected components from Non-Native Field gates (bigfield operations)
Definition graph.cpp:379
size_t get_distance_between_variables(const uint32_t &first_variable_index, const uint32_t &second_variable_index)
void print_variables_gate_counts()
this method prints a number of gates for each variable
Definition graph.cpp:1287
std::unordered_map< KeyPair, std::vector< size_t >, KeyHasher, KeyEquals > variable_gates
Definition graph.hpp:195
std::vector< std::vector< uint32_t > > get_arithmetic_gate_connected_component(bb::UltraCircuitBuilder &ultra_circuit_builder, size_t index, size_t block_idx, UltraBlock &blk)
this method creates connected components from arithmetic gates
Definition graph.cpp:79
StaticAnalyzer_ && operator=(StaticAnalyzer_ &&other)=delete
bool check_is_not_constant_variable(bb::UltraCircuitBuilder &ultra_circuit_builder, const uint32_t &variable_index)
this method checks whether the variable with given index is not constant
Definition graph.cpp:690
void print_connected_components()
this method prints all connected components that were found in the graph
Definition graph.cpp:1271
bool find_arithmetic_gate_for_variable(bb::UltraCircuitBuilder &ultra_circuit_builder, const uint32_t &variable_idx)
std::unordered_set< uint32_t > fixed_variables
Definition graph.hpp:198
std::unordered_map< uint32_t, size_t > get_variables_gate_counts()
Definition graph.hpp:92
void print_variables_edge_counts()
std::vector< uint32_t > get_sort_constraint_connected_component(bb::UltraCircuitBuilder &ultra_circuit_builder, size_t index, size_t block_idx, UltraBlock &blk)
this method creates connected components from sorted constraints
Definition graph.cpp:210
std::vector< uint32_t > get_plookup_gate_connected_component(bb::UltraCircuitBuilder &ultra_circuit_builder, size_t index, size_t block_idx, UltraBlock &blk)
this method creates connected components from plookup gates
Definition graph.cpp:238
void remove_unnecessary_range_constrains_variables(bb::UltraCircuitBuilder &ultra_builder)
this method removes variables from range constraints that are not security critical
Definition graph.cpp:935
StaticAnalyzer_(StaticAnalyzer_ &&other)=delete
size_t find_block_index(bb::UltraCircuitBuilder &ultra_builder, const UltraBlock &block)
this method finds index of the block in circuit builder by comparing pointers to blocks
Definition graph.cpp:21
void remove_unnecessary_decompose_variables(bb::UltraCircuitBuilder &ultra_circuit_builder, std::unordered_set< uint32_t > &variables_in_on_gate, const std::unordered_set< uint32_t > &decompose_variables)
this method removes unnecessary variables from decompose chains
Definition graph.cpp:883
uint32_t to_real(bb::UltraCircuitBuilder &ultra_circuit_constructor, const uint32_t &variable_index)
Definition graph.hpp:86
std::vector< uint32_t > find_variables_with_degree_one()
StaticAnalyzer_ & operator=(const StaticAnalyzer_ &other)=delete
void depth_first_search(const uint32_t &variable_index, std::unordered_set< uint32_t > &is_used, std::vector< uint32_t > &connected_component)
this method implements depth-first search algorithm for undirected graphs
Definition graph.cpp:768
std::unordered_set< uint32_t > get_variables_in_one_gate()
void remove_record_witness_variables(bb::UltraCircuitBuilder &ultra_builder)
this method removes record witness variables from variables in one gate. initially record witness is ...
Definition graph.cpp:1148
void connect_all_variables_in_vector(bb::UltraCircuitBuilder &ultra_circuit_builder, const std::vector< uint32_t > &variables_vector)
this method connects 2 variables if they are in one gate and 1) have different indices,...
Definition graph.cpp:716
bool find_elliptic_gate_for_variable(bb::UltraCircuitBuilder &ultra_circuit_builder, const uint32_t &variable_idx)
void add_new_edge(const uint32_t &first_variable_index, const uint32_t &second_variable_index)
this method creates an edge between two variables in graph. All needed checks in a function above
Definition graph.cpp:751
std::vector< uint32_t > get_elliptic_gate_connected_component(bb::UltraCircuitBuilder &ultra_circuit_builder, size_t index, size_t block_idx, UltraBlock &blk)
this method creates connected components from elliptic gates
Definition graph.cpp:166
std::vector< uint32_t > to_real(bb::UltraCircuitBuilder &ultra_circuit_constructor, std::vector< uint32_t > &variable_indices)
Convert a vector of variable indices to their real indices.
Definition graph.hpp:75
void process_current_plookup_gate(bb::UltraCircuitBuilder &ultra_circuit_builder, size_t gate_index)
this method removes false cases in lookup table for a given gate. it uses all functions above for loo...
Definition graph.cpp:1072
void remove_unnecessary_sha256_plookup_variables(std::unordered_set< uint32_t > &variables_in_one_gate, bb::UltraCircuitBuilder &ultra_circuit_builder, bb::plookup::BasicTableId &table_id, size_t gate_index)
this method removes false cases in sha256 lookup tables. tables which are enumerated in the unordered...
Definition graph.cpp:1016
void process_gate_variables(std::vector< uint32_t > &gate_variables, size_t gate_index, size_t blk_idx)
this method processes variables from a gate by removing duplicates and updating tracking structures
Definition graph.cpp:49
StaticAnalyzer_()=default
Definition graph.cpp:11
std::pair< uint32_t, size_t > KeyPair
Definition graph.hpp:28
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Each ram array is an instance of memory transcript. It saves values and indexes for a particular memo...
Each rom array is an instance of memory transcript. It saves values and indexes for a particular memo...
bool operator()(const KeyPair &p1, const KeyPair &p2) const
Definition graph.hpp:46
size_t operator()(const KeyPair &pair) const
Definition graph.hpp:31