Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
circuit_builder_base_impl.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#pragma once
11
12namespace bb {
13template <typename FF_>
14CircuitBuilderBase<FF_>::CircuitBuilderBase(size_t size_hint, bool has_dummy_witnesses)
15 : has_dummy_witnesses(has_dummy_witnesses)
16{
17 variables.reserve(size_hint * 3);
18 variable_names.reserve(size_hint * 3);
19 next_var_index.reserve(size_hint * 3);
20 prev_var_index.reserve(size_hint * 3);
21 real_variable_index.reserve(size_hint * 3);
22 real_variable_tags.reserve(size_hint * 3);
23}
24
25template <typename FF_> size_t CircuitBuilderBase<FF_>::get_num_finalized_gates() const
26{
27 return num_gates;
28}
29
31{
32 return num_gates;
33}
34
36{
37 std::cout << num_gates << std::endl;
38}
39
40template <typename FF_> size_t CircuitBuilderBase<FF_>::get_num_variables() const
41{
42 return variables.size();
43}
44
45template <typename FF_> uint32_t CircuitBuilderBase<FF_>::get_first_variable_in_class(uint32_t index) const
46{
47 while (prev_var_index[index] != FIRST_VARIABLE_IN_CLASS) {
48 index = prev_var_index[index];
49 }
50 return index;
51}
52
53template <typename FF_>
54void CircuitBuilderBase<FF_>::update_real_variable_indices(uint32_t index, uint32_t new_real_index)
55{
56 auto cur_index = index;
57 do {
58 real_variable_index[cur_index] = new_real_index;
59 cur_index = next_var_index[cur_index];
60 } while (cur_index != REAL_VARIABLE);
61}
62
63template <typename FF_> uint32_t CircuitBuilderBase<FF_>::get_public_input_index(const uint32_t witness_index) const
64{
65 uint32_t result = static_cast<uint32_t>(-1);
66 for (size_t i = 0; i < num_public_inputs(); ++i) {
67 if (real_variable_index[public_inputs_[i]] == real_variable_index[witness_index]) {
68 result = static_cast<uint32_t>(i);
69 break;
70 }
71 }
72 ASSERT(result != static_cast<uint32_t>(-1));
73 return result;
74}
75
76template <typename FF_>
78{
79 BB_ASSERT_LT(index, public_inputs_.size(), "Index out of bounds for public inputs.");
80 return get_variable(public_inputs_[index]);
83template <typename FF_> uint32_t CircuitBuilderBase<FF_>::add_variable(const FF& in)
85 variables.emplace_back(in);
86 const uint32_t index = static_cast<uint32_t>(variables.size()) - 1U;
87 real_variable_index.emplace_back(index);
88 next_var_index.emplace_back(REAL_VARIABLE);
89 prev_var_index.emplace_back(FIRST_VARIABLE_IN_CLASS);
90 real_variable_tags.emplace_back(DUMMY_TAG);
91 return index;
92}
93
94template <typename FF_> void CircuitBuilderBase<FF_>::set_variable_name(uint32_t index, const std::string& name)
95{
96 BB_ASSERT_GT(variables.size(), index);
97 uint32_t first_idx = get_first_variable_in_class(index);
98
99 if (variable_names.contains(first_idx)) {
100 failure("Attempted to assign a name to a variable that already has a name");
101 return;
102 }
103 variable_names.insert({ first_idx, name });
105
106template <typename FF_> void CircuitBuilderBase<FF_>::update_variable_names(uint32_t index)
107{
108 uint32_t first_idx = get_first_variable_in_class(index);
109
110 uint32_t cur_idx = next_var_index[first_idx];
111 while (cur_idx != REAL_VARIABLE && !variable_names.contains(cur_idx)) {
112 cur_idx = next_var_index[cur_idx];
113 }
114
115 if (variable_names.contains(first_idx)) {
116 if (cur_idx != REAL_VARIABLE) {
117 variable_names.extract(cur_idx);
118 }
119 return;
120 }
121
122 if (cur_idx != REAL_VARIABLE) {
123 std::string var_name = variable_names.find(cur_idx)->second;
124 variable_names.erase(cur_idx);
125 variable_names.insert({ first_idx, var_name });
126 return;
127 }
128 failure("No previously assigned names found");
129}
130
131template <typename FF_> size_t CircuitBuilderBase<FF_>::get_circuit_subgroup_size(const size_t num_gates) const
132{
133 auto log2_n = static_cast<size_t>(numeric::get_msb(num_gates));
134 if ((1UL << log2_n) != (num_gates)) {
135 ++log2_n;
136 }
137 return 1UL << log2_n;
138}
139
140template <typename FF_> msgpack::sbuffer CircuitBuilderBase<FF_>::export_circuit()
141{
142 info("not implemented");
143 return { 0 };
144}
145
146template <typename FF_> uint32_t CircuitBuilderBase<FF_>::add_public_variable(const FF& in)
147{
148 const uint32_t index = add_variable(in);
149 BB_ASSERT_EQ(public_inputs_finalized_, false, "Cannot add to public inputs after they have been finalized.");
150 public_inputs_.emplace_back(index);
151 return index;
152}
153
154template <typename FF_> uint32_t CircuitBuilderBase<FF_>::set_public_input(const uint32_t witness_index)
155{
156 for (const uint32_t public_input : public_inputs()) {
157 if (public_input == witness_index) {
158 if (!failed()) {
159 failure("Attempted to set a public input that is already public!");
160 }
161 return 0;
162 }
163 }
164 uint32_t public_input_index = static_cast<uint32_t>(num_public_inputs());
165 BB_ASSERT_EQ(public_inputs_finalized_, false, "Cannot add to public inputs after they have been finalized.");
166 public_inputs_.emplace_back(witness_index);
167
168 return public_input_index;
169}
170
178template <typename FF>
179void CircuitBuilderBase<FF>::assert_equal(const uint32_t a_variable_idx,
180 const uint32_t b_variable_idx,
181 std::string const& msg)
182{
183 assert_valid_variables({ a_variable_idx, b_variable_idx });
184 bool values_equal = (get_variable(a_variable_idx) == get_variable(b_variable_idx));
185 if (!values_equal && !failed()) {
186 failure(msg);
187 }
188 uint32_t a_real_idx = real_variable_index[a_variable_idx];
189 uint32_t b_real_idx = real_variable_index[b_variable_idx];
190 // If a==b is already enforced, exit method
191 if (a_real_idx == b_real_idx) {
192 return;
193 }
194 // Otherwise update the real_idx of b-chain members to that of a
195
196 auto b_start_idx = get_first_variable_in_class(b_variable_idx);
197 update_real_variable_indices(b_start_idx, a_real_idx);
198 // Now merge equivalence classes of a and b by tying last (= real) element of b-chain to first element of a-chain
199 auto a_start_idx = get_first_variable_in_class(a_variable_idx);
200 next_var_index[b_real_idx] = a_start_idx;
201 prev_var_index[a_start_idx] = b_real_idx;
202 bool no_tag_clash = (real_variable_tags[a_real_idx] == DUMMY_TAG || real_variable_tags[b_real_idx] == DUMMY_TAG ||
203 real_variable_tags[a_real_idx] == real_variable_tags[b_real_idx]);
204 if (!no_tag_clash && !failed()) {
205 failure(msg);
206 }
207 if (real_variable_tags[a_real_idx] == DUMMY_TAG) {
208 real_variable_tags[a_real_idx] = real_variable_tags[b_real_idx];
209 }
210}
211
212template <typename FF_>
213void CircuitBuilderBase<FF_>::assert_valid_variables(const std::vector<uint32_t>& variable_indices)
214{
215 for (const auto& variable_index : variable_indices) {
216 BB_ASSERT_LT(variable_index, variables.size());
217 }
218}
220template <typename FF_> bool CircuitBuilderBase<FF_>::failed() const
221{
222 return _failed;
223}
224
225template <typename FF_> const std::string& CircuitBuilderBase<FF_>::err() const
226{
227 return _err;
229
230template <typename FF_> void CircuitBuilderBase<FF_>::set_err(std::string msg)
231{
232 _err = std::move(msg);
233}
234
235template <typename FF_> void CircuitBuilderBase<FF_>::failure(std::string msg)
236{
237#ifndef FUZZING_DISABLE_WARNINGS
238 if (!has_dummy_witnesses) {
239 // Not a catch-all error log. We have a builder failure when we have real witnesses which is a mistake.
240 info("(Experimental) WARNING: Builder failure when we have real witnesses! Ignore if writing vk.");
242#endif
243 _failed = true;
244 set_err(std::move(msg));
245}
246} // namespace bb
#define BB_ASSERT_GT(left, right,...)
Definition assert.hpp:87
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:59
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:115
#define ASSERT(expression,...)
Definition assert.hpp:49
virtual size_t get_num_finalized_gates() const
CircuitBuilderBase(size_t size_hint=0, bool has_dummy_witnesses=false)
uint32_t get_public_input_index(const uint32_t witness_index) const
const std::string & err() const
virtual uint32_t add_variable(const FF &in)
virtual msgpack::sbuffer export_circuit()
virtual uint32_t set_public_input(uint32_t witness_index)
Make a witness variable public.
std::unordered_map< uint32_t, std::string > variable_names
std::vector< uint32_t > prev_var_index
virtual size_t get_estimated_num_finalized_gates() const
void assert_valid_variables(const std::vector< uint32_t > &variable_indices)
FF get_public_input(const uint32_t index) const
std::vector< uint32_t > next_var_index
std::vector< uint32_t > real_variable_tags
virtual void assert_equal(uint32_t a_idx, uint32_t b_idx, std::string const &msg="assert_equal")
virtual size_t get_num_variables() const
virtual void print_num_estimated_finalized_gates() const
virtual void set_variable_name(uint32_t index, const std::string &name)
uint32_t get_first_variable_in_class(uint32_t index) const
void update_real_variable_indices(uint32_t index, uint32_t new_real_index)
virtual void update_variable_names(uint32_t index)
std::vector< uint32_t > real_variable_index
virtual uint32_t add_public_variable(const FF &in)
size_t get_circuit_subgroup_size(size_t num_gates) const
void info(Args... args)
Definition log.hpp:70
constexpr T get_msb(const T in)
Definition get_msb.hpp:47
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13