Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(barretenberg): Graph methods for circuit analysis (part 2) #12110

Closed
wants to merge 49 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
f3ab6af
graph decription for ultra circuit builder
DanielKotov Aug 13, 2024
10508e1
update_edges_for_sorted_variabes, cause it's useless now
DanielKotov Aug 13, 2024
314f4f0
git ignore was added
DanielKotov Aug 13, 2024
346f1bc
remove some commentaries from tests
DanielKotov Aug 13, 2024
8375f46
remove all commentaries from another directiories and add my module i…
DanielKotov Aug 13, 2024
86339b2
forget to return fr(2) in standard_circuit_builder.cpp in the last co…
DanielKotov Aug 13, 2024
ddf3e98
static analyzer based on graph description for UltraCircuitBuilder. a…
DanielKotov Aug 23, 2024
0779bbb
tests for sha256 and blake2s
DanielKotov Aug 23, 2024
8a52e6d
fixes
Rumata888 Aug 23, 2024
0956684
variables gate counts metric for AES and sha256
DanielKotov Sep 9, 2024
637c203
remove changes from blake2s tests and circuit_builder_base
DanielKotov Sep 9, 2024
ff5df64
variables gate count for sha256 + tests
DanielKotov Sep 16, 2024
aef2249
remove some changes from workspace
DanielKotov Sep 16, 2024
bda8275
update for sha256 for PR
DanielKotov Sep 20, 2024
d9486f2
last commit
DanielKotov Oct 2, 2024
20eb663
final version of UltraCircuit graph description for PR
DanielKotov Oct 9, 2024
ad369c8
add commentaries for every class methods, data sturctures and tests +…
DanielKotov Oct 21, 2024
6e2933f
other changes for PR again
DanielKotov Oct 28, 2024
445e02e
add comments + inline + this to all class member functions
DanielKotov Nov 1, 2024
d0f4fd4
corrected Sasha's comments + renamed tests + removed some info from
DanielKotov Nov 1, 2024
2c842f6
Merge remote-tracking branch 'origin/master' into dk/boomerang_value
DanielKotov Nov 1, 2024
af9f73a
graph methods for circuit analysis
DanielKotov Nov 1, 2024
0e238ff
remove my useless solution for standard circuit builder and tests for it
DanielKotov Nov 1, 2024
582f4c9
graph description for stdlib/poseidon2 hash function + tests
DanielKotov Dec 3, 2024
e13c779
first steps for auxiliary gates
DanielKotov Dec 4, 2024
554bfd5
add graph description for bigfield product cases
DanielKotov Dec 9, 2024
24fa6e9
add auxiliary block graph creation + resize method test for dynamic a…
DanielKotov Dec 11, 2024
24f295f
rarewrite graph description fro or ram and rom tables + tests
DanielKotov Dec 18, 2024
4c504e4
tests for dynamic array + ram_rom
DanielKotov Dec 23, 2024
3c4ef33
fix error of graph creation for q_arith == 3
DanielKotov Feb 3, 2025
5a351ae
new graph constructor
DanielKotov Feb 12, 2025
4fce2a4
tests modification
DanielKotov Feb 12, 2025
076c140
redesign of the constructor for graph creation
DanielKotov Feb 17, 2025
ecf37b2
new tests for poseidon2s + other tests redesign
DanielKotov Feb 17, 2025
67130c9
new tests for bigfield primitive
DanielKotov Feb 17, 2025
5e3becf
add commentaries for new functions
DanielKotov Feb 17, 2025
108fd1d
commentaries for poseidon2s tests
DanielKotov Feb 17, 2025
0795ec3
tests descriptiion for ram/rom tables
DanielKotov Feb 17, 2025
5e54071
commentaries for bigfield and dynamic array tests
DanielKotov Feb 17, 2025
b08051f
this test fifile is useless now, sso we can remove it
DanielKotov Feb 17, 2025
1028343
final graph description + removing some unnesecary information from t…
DanielKotov Feb 18, 2025
5052554
fix for poseidon2 hash function on my branch
DanielKotov Feb 18, 2025
8c6010e
final tests for ran and rom tables
DanielKotov Feb 19, 2025
11d4c1b
final tests fixes after full run
DanielKotov Feb 19, 2025
085bb4a
merge conflict fixes
DanielKotov Feb 19, 2025
f16a1fc
some problems with commits
DanielKotov Feb 19, 2025
691c6eb
some problems with merges
DanielKotov Feb 19, 2025
ee13218
merge conflicts again
DanielKotov Feb 19, 2025
29ff134
some probles with merge again
DanielKotov Feb 20, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion barretenberg/barretenberg.code-workspace
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,6 @@
"cwd": "${command:cmake.buildDirectory}",
"internalConsoleOptions": "openOnSessionStart",
"console": "internalConsole",
}
}
},
}
Original file line number Diff line number Diff line change
@@ -1 +1 @@
barretenberg_module(boomerang_value_detection stdlib_circuit_builders circuit_checker stdlib_primitives numeric stdlib_aes128 stdlib_sha256 stdlib_blake2s stdlib_blake3s)
barretenberg_module(boomerang_value_detection stdlib_circuit_builders circuit_checker stdlib_primitives numeric stdlib_aes128 stdlib_sha256 stdlib_blake2s stdlib_blake3s stdlib_poseidon2 stdlib_primitives)
811 changes: 632 additions & 179 deletions barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <unordered_set>
#include <utility>
#include <vector>
#include <typeinfo>

/*
* this class describes arithmetic circuit as an undirected graph, where vertices are variables from circuit.
Expand All @@ -16,6 +17,38 @@
* constrained properly. if number of connected components > 1, it means that there were missed some connections between
* variables.
*/

namespace cdg {

/*
* we add a new feature for static analyzer, now it contains gates where it found every variable. This may be helpful, if we want to do functions that
* remove false-positive variables from the analyzer using selectors in the gate + some additional knowledge about this variable, for example, tau or range tags.
* this info contains in unordered map with key as std::pair<uint32_t, size_t>, where uint32_t -- real variable index and size_t -- index of UltraTraceBlock in
* Reference Array with all TraceBlocks, that Ultra Circuit Builder contains inside. But there was a problem with unordered map -- it doesn't have default hash function and
* function for checking equivalence for std::pair as a key, so we had to implement it ourselves. We decided to choose approach based on function hash_combine from boost library
* for C++, and it's not so difficult to hash 2 elements in pair and check their equivalence.
*/
using UltraBlock = bb::UltraCircuitBuilder::Arithmetization::UltraTraceBlock;
using KeyPair = std::pair<uint32_t, size_t>;

struct KeyHasher{
size_t operator()(const KeyPair& pair) const {
size_t combined_hash = 0;
auto hash_combiner = [](size_t lhs, size_t rhs) {
return lhs ^ (rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2));
};
combined_hash = hash_combiner(combined_hash, std::hash<uint32_t>()(pair.first));
combined_hash = hash_combiner(combined_hash, std::hash<size_t>()(pair.second));
return combined_hash;
}
};

struct KeyEquals{
bool operator()(const KeyPair& p1, const KeyPair& p2) const {
return (p1.first == p2.first && p1.second == p2.second);
}
};

template <typename FF> class Graph_ {
public:
Graph_() = default;
Expand All @@ -25,24 +58,36 @@ template <typename FF> class Graph_ {
Graph_&& operator=(Graph_&& other) = delete;
Graph_(const bb::StandardCircuitBuilder_<FF>& 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];
};
size_t find_block_index(bb::UltraCircuitBuilder& ultra_builder, const UltraBlock& block);
void process_gate_variables(bb::UltraCircuitBuilder& ultra_circuit_constructor,
std::vector<uint32_t>& gate_variables);

std::vector<uint32_t>& gate_variables,
size_t gate_index,
size_t blk_idx);
std::unordered_map<uint32_t, size_t> get_variables_gate_counts() { return this->variables_gate_counts; };

std::vector<uint32_t> get_arithmetic_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
size_t index);
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);
std::vector<uint32_t> get_elliptic_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
size_t index);
size_t index, size_t block_idx, UltraBlock& blk);
std::vector<uint32_t> get_plookup_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
size_t index);
size_t index, size_t block_idx, UltraBlock& blk);
std::vector<uint32_t> get_sort_constraint_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
size_t index);
size_t index, size_t block_idx, UltraBlock& blk);
std::vector<uint32_t> get_poseido2s_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
size_t index,
size_t block_idx,
UltraBlock& blk);
std::vector<uint32_t> get_auxiliary_gate_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
size_t index, size_t block_idx, UltraBlock& blk);
std::vector<uint32_t> get_rom_table_connected_component(bb::UltraCircuitBuilder& ultra_circuit_builder,
const bb::UltraCircuitBuilder::RomTranscript& rom_array);
std::vector<uint32_t> get_ram_table_connected_component(bb::UltraCircuitBuilder& ultra_builder,
const bb::UltraCircuitBuilder::RamTranscript& ram_array);

void add_new_edge(const uint32_t& first_variable_index, const uint32_t& second_variable_index);
std::vector<uint32_t> get_variable_adjacency_list(const uint32_t& variable_index)
Expand Down Expand Up @@ -89,6 +134,7 @@ template <typename FF> class Graph_ {
const std::unordered_set<uint32_t>& decompose_variables);
void remove_unnecessary_plookup_variables(bb::UltraCircuitBuilder& ultra_circuit_builder,
std::unordered_set<uint32_t>& variables_in_on_gate);
void remove_unnecessary_range_constrains_variables(bb::UltraCircuitBuilder& ultra_builder);
std::unordered_set<uint32_t> show_variables_in_one_gate(bb::UltraCircuitBuilder& ultra_circuit_builder);

void remove_unnecessary_aes_plookup_variables(std::unordered_set<uint32_t>& variables_in_one_gate,
Expand All @@ -99,11 +145,13 @@ template <typename FF> class Graph_ {
bb::UltraCircuitBuilder& ultra_circuit_builder,
bb::plookup::BasicTableId& table_id,
size_t gate_index);
void remove_record_witness_variables(bb::UltraCircuitBuilder& ultra_builder);

void print_graph();
void print_connected_components();
void print_variables_gate_counts();
void print_variables_edge_counts();
void print_variables_in_one_gate(bb::UltraCircuitBuilder& ultra_builder);
~Graph_() = default;

private:
Expand All @@ -114,6 +162,10 @@ template <typename FF> class Graph_ {
variables_gate_counts; // we use this data structure to count, how many gates use every variable
std::unordered_map<uint32_t, size_t>
variables_degree; // we use this data structure to count, how many every variable have edges
std::unordered_map<KeyPair, std::vector<size_t>, KeyHasher, KeyEquals> variable_gates; //we use this data structure to store gates and TraceBlocks for every variables, where static analyzer found them in the circuit.
std::unordered_set<uint32_t> variables_in_one_gate;
std::unordered_set<uint32_t> fixed_variables;
};

using Graph = Graph_<bb::fr>;
using Graph = Graph_<bb::fr>;
} //namespace cgd
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <gtest/gtest.h>

using namespace bb;

using namespace cdg;
/**
* @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
Expand All @@ -38,10 +38,8 @@ TEST(boomerang_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();
auto variables_in_one_gate = graph.show_variables_in_one_gate(circuit_constructor);
bool result = num_connected_components == 256;
EXPECT_EQ(result, true);
[[maybe_unused]]auto variables_in_one_gate = graph.show_variables_in_one_gate(circuit_constructor);
EXPECT_EQ(connected_components.size(), 256);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,17 @@

using namespace bb;
using namespace bb::stdlib;
using namespace cdg;

using Builder = UltraCircuitBuilder;
typedef stdlib::field_t<UltraCircuitBuilder> field_pt;
typedef stdlib::witness_t<bb::UltraCircuitBuilder> witness_pt;
using field_pt = stdlib::field_t<UltraCircuitBuilder>;
using witness_pt = stdlib::witness_t<bb::UltraCircuitBuilder>;

bool check_in_vector(const std::vector<field_pt>& input_vector, const uint32_t& real_var_index)
void fix_vector_witness(std::vector<field_pt>& input_vector)
{
for (const auto& elem : input_vector) {
if (elem.witness_index == real_var_index) {
return true;
}
for (auto& elem : input_vector) {
elem.fix_witness();
}
return false;
}

/**
Expand All @@ -41,7 +39,7 @@ TEST(boomerang_stdlib_aes, test_graph_for_aes_64_bytes)
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) {
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);
Expand All @@ -59,17 +57,21 @@ TEST(boomerang_stdlib_aes, test_graph_for_aes_64_bytes)
witness_pt(&builder, fr(convert_bytes(in + 48))),
};

fix_vector_witness(in_field);

field_pt key_field(witness_pt(&builder, fr(convert_bytes(key))));
field_pt iv_field(witness_pt(&builder, fr(convert_bytes(iv))));
key_field.fix_witness();
iv_field.fix_witness();

const auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field);
auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field);
fix_vector_witness(result);

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);
EXPECT_EQ(connected_components.size(), 1);
auto variables_in_one_gate = graph.show_variables_in_one_gate(builder);
EXPECT_EQ(variables_in_one_gate.size(), 0);
}

/**
Expand All @@ -88,7 +90,7 @@ TEST(boomerang_stdlib_aes, test_variable_gates_count_for_aes128cbc)
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) {
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);
Expand All @@ -106,18 +108,19 @@ TEST(boomerang_stdlib_aes, test_variable_gates_count_for_aes128cbc)
witness_pt(&builder, fr(convert_bytes(in + 48))),
};

fix_vector_witness(in_field);

field_pt key_field(witness_pt(&builder, fr(convert_bytes(key))));
field_pt iv_field(witness_pt(&builder, fr(convert_bytes(iv))));
key_field.fix_witness();
iv_field.fix_witness();

const auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field);
auto result = stdlib::aes128::encrypt_buffer_cbc(in_field, iv_field, key_field);
fix_vector_witness(result);

Graph graph = Graph(builder);
auto connected_components = graph.find_connected_components();
EXPECT_EQ(connected_components.size(), 1);
std::unordered_set<uint32_t> 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);
EXPECT_EQ(check, true);
}
EXPECT_EQ(variables_in_one_gate.size(), 0);
}
Loading
Loading