Skip to content

Commit e53d04d

Browse files
authored
refactor(Barretenberg): Static analysis of Protogalaxy Recursive Verifier (#16632)
This time Protogalaxy Recursive Verifier was tested. 1. The tool was modified in order to be able to process Ultra and Mega Circuit Builders depending on the type of the circuit 2. The algorithm for finding connected components was fixed 3. Small refactoring: unused functions were removed and new added new connected components algorithm, changed find_block_index to remove void* :) 4. Tests for Protogalaxy Recursive Verifier were added for folding and decider circuits. More false cases, 0 vulnerabilities.
2 parents b4460df + c43ae99 commit e53d04d

26 files changed

+1193
-681
lines changed

barretenberg/cpp/scripts/test_civc_standalone_vks_havent_changed.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ cd ..
1313
# - Generate a hash for versioning: sha256sum bb-civc-inputs.tar.gz
1414
# - Upload the compressed results: aws s3 cp bb-civc-inputs.tar.gz s3://aztec-ci-artifacts/protocol/bb-civc-inputs-[hash(0:8)].tar.gz
1515
# Note: In case of the "Test suite failed to run ... Unexpected token 'with' " error, need to run: docker pull aztecprotocol/build:3.0
16-
pinned_short_hash="d06b78a2"
16+
pinned_short_hash="98409939"
1717
pinned_civc_inputs_url="https://aztec-ci-artifacts.s3.us-east-2.amazonaws.com/protocol/bb-civc-inputs-${pinned_short_hash}.tar.gz"
1818

1919
function compress_and_upload {
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
barretenberg_module(boomerang_value_detection stdlib_circuit_builders circuit_checker stdlib_primitives numeric stdlib_aes128 stdlib_sha256 stdlib_blake2s stdlib_blake3s stdlib_poseidon2 stdlib_goblin_verifier)
1+
barretenberg_module(boomerang_value_detection stdlib_circuit_builders circuit_checker
2+
stdlib_primitives numeric stdlib_aes128 stdlib_sha256 stdlib_blake2s
3+
stdlib_blake3s stdlib_poseidon2 stdlib_honk_verifier stdlib_protogalaxy_verifier)

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

Lines changed: 535 additions & 411 deletions
Large diffs are not rendered by default.
Lines changed: 71 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#pragma once
2+
#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp"
23
#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp"
34
#include <list>
45
#include <set>
@@ -9,8 +10,6 @@
910
#include <vector>
1011

1112
namespace cdg {
12-
13-
using UltraBlock = bb::UltraTraceBlock;
1413
/**
1514
* We've added a new feature to the static analyzer that tracks which gates contain each variable.
1615
* This is helpful for removing false-positive variables from the analyzer by using gate selectors
@@ -49,6 +48,19 @@ struct KeyEquals {
4948
}
5049
};
5150

51+
struct ConnectedComponent {
52+
std::vector<uint32_t> variable_indices;
53+
bool is_range_list_cc;
54+
bool is_finalize_cc;
55+
ConnectedComponent() = default;
56+
ConnectedComponent(const std::vector<uint32_t>& vector)
57+
: variable_indices(vector)
58+
, is_range_list_cc(false)
59+
, is_finalize_cc(false) {};
60+
size_t size() const { return variable_indices.size(); }
61+
const std::vector<uint32_t>& vars() const { return variable_indices; }
62+
};
63+
5264
/*
5365
* This class describes an arithmetic circuit as an undirected graph, where vertices are variables from the circuit.
5466
* Edges describe connections between variables through gates. We want to find variables that weren't properly
@@ -57,133 +69,91 @@ struct KeyEquals {
5769
* variable wasn't constrained properly. If the number of connected components > 1, it means that there were some missed
5870
* connections between variables.
5971
*/
60-
template <typename FF> class StaticAnalyzer_ {
72+
template <typename FF, typename CircuitBuilder> class StaticAnalyzer_ {
6173
public:
6274
StaticAnalyzer_() = default;
6375
StaticAnalyzer_(const StaticAnalyzer_& other) = delete;
6476
StaticAnalyzer_(StaticAnalyzer_&& other) = delete;
6577
StaticAnalyzer_& operator=(const StaticAnalyzer_& other) = delete;
6678
StaticAnalyzer_&& operator=(StaticAnalyzer_&& other) = delete;
67-
StaticAnalyzer_(bb::UltraCircuitBuilder& ultra_circuit_constructor, bool connect_variables = true);
79+
StaticAnalyzer_(CircuitBuilder& circuit_builder, bool connect_variables = true);
6880

6981
/**
7082
* @brief Convert a vector of variable indices to their real indices
71-
* @param ultra_circuit_constructor The UltraCircuitBuilder instance
7283
* @param variable_indices The vector of variable indices to convert
7384
* @return std::vector<uint32_t> A vector of real variable indices
7485
*/
75-
std::vector<uint32_t> to_real(bb::UltraCircuitBuilder& ultra_circuit_constructor,
76-
std::vector<uint32_t>& variable_indices)
86+
std::vector<uint32_t> to_real(std::vector<uint32_t>& variable_indices)
7787
{
7888
std::vector<uint32_t> real_variable_indices;
7989
real_variable_indices.reserve(variable_indices.size());
8090
for (auto& variable_index : variable_indices) {
81-
real_variable_indices.push_back(to_real(ultra_circuit_constructor, variable_index));
91+
real_variable_indices.push_back(to_real(variable_index));
8292
}
8393
return real_variable_indices;
8494
};
85-
86-
uint32_t to_real(bb::UltraCircuitBuilder& ultra_circuit_constructor, const uint32_t& variable_index)
95+
uint32_t to_real(const uint32_t& variable_index) const
8796
{
88-
return ultra_circuit_constructor.real_variable_index[variable_index];
89-
};
90-
size_t find_block_index(bb::UltraCircuitBuilder& ultra_builder, const UltraBlock& block);
97+
return circuit_builder.real_variable_index[variable_index];
98+
}
99+
size_t find_block_index(const auto& block);
91100
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-
94-
std::vector<std::vector<uint32_t>> get_arithmetic_gate_connected_component(
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);
101+
std::unordered_map<uint32_t, size_t> get_variables_gate_counts() const { return this->variables_gate_counts; };
102+
103+
void process_execution_trace();
104+
105+
std::vector<std::vector<uint32_t>> get_arithmetic_gate_connected_component(size_t index,
106+
size_t block_idx,
107+
auto& blk);
108+
std::vector<uint32_t> get_elliptic_gate_connected_component(size_t index, size_t block_idx, auto& blk);
109+
std::vector<uint32_t> get_plookup_gate_connected_component(size_t index, size_t block_idx, auto& blk);
110+
std::vector<uint32_t> get_sort_constraint_connected_component(size_t index, size_t block_idx, auto& blk);
111+
std::vector<uint32_t> get_poseido2s_gate_connected_component(size_t index, size_t block_idx, auto& blk);
112+
std::vector<uint32_t> get_non_native_field_gate_connected_component(size_t index, size_t block_idx, auto& blk);
113+
std::vector<uint32_t> get_memory_gate_connected_component(size_t index, size_t block_idx, auto& blk);
114+
std::vector<uint32_t> get_rom_table_connected_component(const bb::RomTranscript& rom_array);
115+
std::vector<uint32_t> get_ram_table_connected_component(const bb::RamTranscript& ram_array);
116+
// functions for MegaCircuitBuilder
117+
std::vector<uint32_t> get_databus_connected_component(size_t index, size_t block_idx, auto& blk);
118+
std::vector<uint32_t> get_eccop_connected_component(size_t index, size_t block_idx, auto& blk);
119+
std::vector<uint32_t> get_eccop_part_connected_component(size_t index, size_t block_idx, auto& blk);
124120

125121
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-
131122
void depth_first_search(const uint32_t& variable_index,
132123
std::unordered_set<uint32_t>& is_used,
133124
std::vector<uint32_t>& connected_component);
134-
std::vector<std::vector<uint32_t>> find_connected_components();
135-
136-
std::vector<uint32_t> find_variables_with_degree_one();
137-
std::unordered_set<uint32_t> get_variables_in_one_gate();
138-
139-
bool find_arithmetic_gate_for_variable(bb::UltraCircuitBuilder& ultra_circuit_builder,
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);
125+
void mark_range_list_connected_components();
126+
void mark_finalize_connected_components();
127+
std::vector<ConnectedComponent> find_connected_components(bool return_all_connected_components = false);
145128
bool check_vertex_in_connected_component(const std::vector<uint32_t>& connected_component,
146129
const uint32_t& var_index);
147-
148-
void connect_all_variables_in_vector(bb::UltraCircuitBuilder& ultra_circuit_builder,
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);
130+
void connect_all_variables_in_vector(const std::vector<uint32_t>& variables_vector);
131+
bool check_is_not_constant_variable(const uint32_t& variable_index);
151132

152133
std::pair<std::vector<uint32_t>, size_t> get_connected_component_with_index(
153134
const std::vector<std::vector<uint32_t>>& connected_components, size_t index);
154135

155-
std::unordered_set<uint32_t> get_variables_in_one_gate_without_range_constraints(
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);
162-
void remove_unnecessary_decompose_variables(bb::UltraCircuitBuilder& ultra_circuit_builder,
163-
std::unordered_set<uint32_t>& variables_in_on_gate,
164-
const std::unordered_set<uint32_t>& decompose_variables);
165-
void remove_unnecessary_plookup_variables(bb::UltraCircuitBuilder& ultra_circuit_builder);
166-
void remove_unnecessary_range_constrains_variables(bb::UltraCircuitBuilder& ultra_builder);
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,
171-
bb::plookup::BasicTableId& table_id,
172-
size_t gate_index);
173-
void remove_unnecessary_sha256_plookup_variables(std::unordered_set<uint32_t>& variables_in_one_gate,
174-
bb::UltraCircuitBuilder& ultra_circuit_builder,
175-
bb::plookup::BasicTableId& table_id,
176-
size_t gate_index);
177-
void remove_record_witness_variables(bb::UltraCircuitBuilder& ultra_builder);
178-
179-
void print_graph();
180-
void print_connected_components();
136+
size_t process_current_decompose_chain(size_t index);
137+
void process_current_plookup_gate(size_t gate_index);
138+
void remove_unnecessary_decompose_variables(const std::unordered_set<uint32_t>& decompose_variables);
139+
void remove_unnecessary_plookup_variables();
140+
void remove_unnecessary_range_constrains_variables();
141+
std::unordered_set<uint32_t> get_variables_in_one_gate();
142+
143+
void remove_unnecessary_aes_plookup_variables(bb::plookup::BasicTableId& table_id, size_t gate_index);
144+
void remove_unnecessary_sha256_plookup_variables(bb::plookup::BasicTableId& table_id, size_t gate_index);
145+
void remove_record_witness_variables();
146+
147+
void print_connected_components_info();
181148
void print_variables_gate_counts();
182-
void print_variables_edge_counts();
183-
void print_variable_in_one_gate(bb::UltraCircuitBuilder& ultra_builder, const uint32_t real_idx);
149+
void print_variable_in_one_gate(const uint32_t real_idx);
184150
~StaticAnalyzer_() = default;
185151

186152
private:
153+
// Store reference to the circuit builder
154+
CircuitBuilder& circuit_builder;
155+
bool connect_variables;
156+
187157
std::unordered_map<uint32_t, std::vector<uint32_t>>
188158
variable_adjacency_lists; // we use this data structure to contain information about variables and their
189159
// connections between each other
@@ -193,11 +163,17 @@ template <typename FF> class StaticAnalyzer_ {
193163
variables_degree; // we use this data structure to count, how many every variable have edges
194164
std::unordered_map<KeyPair, std::vector<size_t>, KeyHasher, KeyEquals>
195165
variable_gates; // we use this data structure to store gates and TraceBlocks for every variables, where static
196-
// analyzer found them in the circuit.
166+
// analyzer finds them in the circuit.
197167
std::unordered_set<uint32_t> variables_in_one_gate;
198168
std::unordered_set<uint32_t> fixed_variables;
169+
std::vector<ConnectedComponent> connected_components;
170+
std::vector<ConnectedComponent>
171+
main_connected_components; // connected components without finalize blocks and range lists
199172
};
200173

201-
using StaticAnalyzer = StaticAnalyzer_<bb::fr>;
174+
// Type aliases for convenience
175+
using UltraStaticAnalyzer = StaticAnalyzer_<bb::fr, bb::UltraCircuitBuilder>;
176+
using MegaStaticAnalyzer = StaticAnalyzer_<bb::fr, bb::MegaCircuitBuilder>;
177+
using StaticAnalyzer = UltraStaticAnalyzer; // Default to Ultra for backward compatibility
202178

203179
} // namespace cdg

0 commit comments

Comments
 (0)