Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
ultra_circuit_builder.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
14
16#include "rom_ram_logic.hpp"
17#include <deque>
18#include <optional>
19#include <unordered_set>
20
22
23namespace bb {
24
25template <typename FF> struct non_native_multiplication_witnesses {
26 // first 4 array elements = limbs
27 std::array<uint32_t, 4> a;
28 std::array<uint32_t, 4> b;
29 std::array<uint32_t, 4> q;
30 std::array<uint32_t, 4> r;
31 std::array<FF, 4> neg_modulus;
32};
33
34template <typename FF> struct non_native_partial_multiplication_witnesses {
35 // first 4 array elements = limbs
36 std::array<uint32_t, 4> a;
37 std::array<uint32_t, 4> b;
38};
39
40template <typename ExecutionTrace_>
41class UltraCircuitBuilder_ : public CircuitBuilderBase<typename ExecutionTrace_::FF> {
42 public:
43 using ExecutionTrace = ExecutionTrace_;
44 using FF = typename ExecutionTrace::FF;
46
47 static constexpr size_t NUM_WIRES = ExecutionTrace::NUM_WIRES;
48
49 static constexpr std::string_view NAME_STRING = "UltraCircuitBuilder";
50 // The plookup range proof requires work linear in range size, thus cannot be used directly for
51 // large ranges such as 2^64. For such ranges the element will be decomposed into smaller
52 // chuncks according to the parameter below
53 static constexpr size_t DEFAULT_PLOOKUP_RANGE_BITNUM = 14;
54 static constexpr size_t DEFAULT_PLOOKUP_RANGE_STEP_SIZE = 3;
55 static constexpr size_t DEFAULT_PLOOKUP_RANGE_SIZE = (1 << DEFAULT_PLOOKUP_RANGE_BITNUM) - 1;
56 static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS = 68;
57
67
76
77 struct RangeList {
78 uint64_t target_range;
79 uint32_t range_tag;
80 uint32_t tau_tag;
81 std::vector<uint32_t> variable_indices;
82 bool operator==(const RangeList& other) const noexcept
83 {
84 return target_range == other.target_range && range_tag == other.range_tag && tau_tag == other.tau_tag &&
85 variable_indices == other.variable_indices;
86 }
87 };
88
89 // AUDITTODO: this is not a large optimization (~0.5% reduction for ultra rec verifier); consider removing
96 std::array<uint32_t, 4> a;
97 std::array<uint32_t, 4> b;
98 uint32_t lo_0;
99 uint32_t hi_0;
100 uint32_t hi_1;
101
103 {
104 bool valid = true;
105 for (size_t i = 0; i < 4; ++i) {
106 valid = valid && (a[i] == other.a[i]);
107 valid = valid && (b[i] == other.b[i]);
108 }
109 return valid;
110 }
111
123 {
125
127
128 for (const auto& item : vec) {
129 auto [existing_element, not_in_set] = seen.insert(item);
130 // Memorize if not in set yet
131 if (not_in_set) {
132 uniqueVec.push_back(item);
133 } else {
134 // If we already have a representative, we need to connect the outputs together
135 circuit_builder->assert_equal(item.lo_0, (*existing_element).lo_0);
136 circuit_builder->assert_equal(item.hi_0, (*existing_element).hi_0);
137 circuit_builder->assert_equal(item.hi_1, (*existing_element).hi_1);
138 }
139 }
140
141 vec.swap(uniqueVec);
142 }
143
145 {
146 if (a < other.a) {
147 return true;
148 }
149 if (other.a < a) {
150 return false;
151 }
152 if (b < other.b) {
153 return true;
154 }
155 return other.b < b;
156 }
157
158 struct Hash {
160 {
161 size_t combined_hash = 0;
162
163 // C++ does not have a standard way to hash values, so we use the
164 // common algorithm that boot uses.
165 // You can search for 'cpp hash_combine' to find more information.
166 // Here is one reference:
167 // https://stackoverflow.com/questions/2590677/how-do-i-combine-hash-values-in-c0x
168 auto hash_combiner = [](size_t lhs, size_t rhs) {
169 return lhs ^ (rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2));
170 };
171
172 for (const auto& elem : obj.a) {
173 combined_hash = hash_combiner(combined_hash, std::hash<uint32_t>()(elem));
174 }
175 for (const auto& elem : obj.b) {
176 combined_hash = hash_combiner(combined_hash, std::hash<uint32_t>()(elem));
177 }
178
179 return combined_hash;
180 }
181 };
182 };
183
184 private:
185 // The set of lookup tables used by the circuit, plus the gate data for the lookups from each table
187
188 public:
189 // Storage for wires and selectors for all gate types
191
192 // The set of variables which have been constrained to a particular value via an arithmetic gate
193 std::unordered_map<FF, uint32_t> constant_variable_indices;
194
195 // Rom/Ram logic
197
198 // Stores gate index of ROM/RAM reads (required by proving key)
199 std::vector<uint32_t> memory_read_records;
200 // Stores gate index of RAM writes (required by proving key)
201 std::vector<uint32_t> memory_write_records;
203
205
206 bool circuit_finalized = false;
207
208 std::vector<fr> ipa_proof;
209
211
213
214 UltraCircuitBuilder_(const size_t size_hint = 0, bool is_write_vk_mode = false)
216 {
218 this->_tau.insert(
219 { DUMMY_TAG, DUMMY_TAG }); // The identity permutation on the set `{DUMMY_TAG}`. We assume that the
220 // `DUMMY_TAG` is not involved in any non-trivial multiset-equality checks.
221 };
222
239 UltraCircuitBuilder_(const size_t size_hint,
240 const std::vector<FF>& witness_values,
241 const std::vector<uint32_t>& public_inputs,
242 const bool is_write_vk_mode)
244 {
245 for (const auto value : witness_values) {
246 this->add_variable(value);
247 }
248
249 // Initialize the builder public_inputs directly from the acir public inputs.
250 this->initialize_public_inputs(public_inputs);
251
252 // Add the const zero variable after the acir witness has been
253 // incorporated into variables.
255 this->_tau.insert({ DUMMY_TAG, DUMMY_TAG }); // TODO(luke): explain this
256 };
261 ~UltraCircuitBuilder_() override = default;
262
271 {
272#if NDEBUG
273 // do nothing
274#else
275 for (auto& block : blocks.get()) {
276 const auto& block_selectors = block.get_selectors();
277 size_t nominal_size = block_selectors[0].size();
278 for (size_t idx = 1; idx < block_selectors.size(); ++idx) {
279 BB_ASSERT_EQ(block_selectors[idx].size(), nominal_size);
280 }
281 }
282
283#endif // NDEBUG
284 }
285
286 void finalize_circuit(const bool ensure_nonzero);
287
289
290 void create_add_gate(const add_triple_<FF>& in);
291 void create_big_mul_add_gate(const mul_quad_<FF>& in, const bool use_next_gate_w_4 = false);
292 void create_big_add_gate(const add_quad_<FF>& in, const bool use_next_gate_w_4 = false);
293
294 void create_bool_gate(const uint32_t a);
298
299 void fix_witness(const uint32_t witness_index, const FF& witness_value);
300
301 void create_new_range_constraint(const uint32_t variable_index,
302 const uint64_t target_range,
303 std::string const msg = "create_new_range_constraint");
304 void create_range_constraint(const uint32_t variable_index, const size_t num_bits, std::string const& msg)
305 {
306 if (num_bits == 1) {
307 create_bool_gate(variable_index);
308 } else if (num_bits <= DEFAULT_PLOOKUP_RANGE_BITNUM) {
324 .a = variable_index,
325 .b = variable_index,
326 .c = variable_index,
327 .q_m = 0,
328 .q_l = 1,
329 .q_r = -1,
330 .q_o = 0,
331 .q_c = 0,
332 });
333 create_new_range_constraint(variable_index, (1ULL << num_bits) - 1, msg);
334 } else {
335 decompose_into_default_range(variable_index, num_bits, DEFAULT_PLOOKUP_RANGE_BITNUM, msg);
336 }
337 }
338
339 uint32_t put_constant_variable(const FF& variable);
340
341 size_t get_num_constant_gates() const override { return 0; }
342
347 size_t get_num_finalized_gates() const override
348 {
350 return this->num_gates();
351 }
352
361 size_t get_num_finalized_gates_inefficient(bool ensure_nonzero = true) const
362 {
363 UltraCircuitBuilder_ builder_copy = *this;
364 builder_copy.finalize_circuit(ensure_nonzero);
365 return builder_copy.get_num_finalized_gates();
366 }
367
372 size_t get_tables_size() const
373 {
374 size_t tables_size = 0;
375 for (const auto& table : lookup_tables) {
376 tables_size += table.size();
377 }
378 return tables_size;
379 }
380
391 {
393 auto num_filled_gates = get_num_finalized_gates() + this->num_public_inputs();
394 return std::max(get_tables_size(), num_filled_gates);
395 }
396
397 void assert_equal_constant(const uint32_t a_idx, const FF& b, std::string const& msg = "assert equal constant")
398 {
399 if (this->get_variable(a_idx) != b && !this->failed()) {
400 this->failure(msg);
401 }
402 auto b_idx = put_constant_variable(b);
403 this->assert_equal(a_idx, b_idx, msg);
404 }
405
411
412 // Accessors for lookup tables
415 size_t get_num_lookup_tables() const { return lookup_tables.size(); }
416
418 const plookup::MultiTableId& id,
419 const plookup::ReadData<FF>& read_values,
420 const uint32_t key_a_index,
422
423 std::vector<uint32_t> decompose_into_default_range(
424 const uint32_t variable_index,
425 const uint64_t num_bits,
426 const uint64_t target_range_bitnum = DEFAULT_PLOOKUP_RANGE_BITNUM,
427 std::string const& msg = "decompose_into_default_range");
428
438 auto& block, const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4)
439 {
440 block.populate_wires(idx_1, idx_2, idx_3, idx_4);
441 block.q_m().emplace_back(0);
442 block.q_1().emplace_back(0);
443 block.q_2().emplace_back(0);
444 block.q_3().emplace_back(0);
445 block.q_c().emplace_back(0);
446 block.q_4().emplace_back(0);
447 block.set_gate_selector(0); // all selectors zero
448
450 this->increment_num_gates();
451 }
452 void create_unconstrained_gates(const std::vector<uint32_t>& variable_index);
453
457 void create_sort_constraint(const std::vector<uint32_t>& variable_index);
458 void create_sort_constraint_with_edges(const std::vector<uint32_t>& variable_index, const FF&, const FF&);
459
463 void assign_tag(const uint32_t variable_index, const uint32_t tag)
464 {
466 // If we've already assigned this tag to this variable, return (can happen due to copy constraints)
467 if (this->real_variable_tags[this->real_variable_index[variable_index]] == tag) {
468 return;
469 }
470
471 BB_ASSERT_EQ(this->real_variable_tags[this->real_variable_index[variable_index]], DUMMY_TAG);
472 this->real_variable_tags[this->real_variable_index[variable_index]] = tag;
473 }
481 void set_tau_at_index(const uint32_t tag_index, const uint32_t tau_index)
482 {
483 this->_tau.insert({ tag_index, tau_index });
484 }
492 void set_tau_transposition(const uint32_t tag_index_1, const uint32_t tag_index_2)
493 {
494 set_tau_at_index(tag_index_1, tag_index_2);
495 set_tau_at_index(tag_index_2, tag_index_1);
496 }
497
498 uint32_t get_new_tag()
499 {
500 this->current_tag++;
501 return this->current_tag;
502 }
503
504 RangeList create_range_list(const uint64_t target_range);
505 void process_range_list(RangeList& list);
506 void process_range_lists();
507
513
517 void range_constrain_two_limbs(const uint32_t lo_idx,
518 const uint32_t hi_idx,
519 const size_t lo_limb_bits = DEFAULT_NON_NATIVE_FIELD_LIMB_BITS,
520 const size_t hi_limb_bits = DEFAULT_NON_NATIVE_FIELD_LIMB_BITS,
521 std::string const& msg = "range_constrain_two_limbs");
522 std::array<uint32_t, 2> evaluate_non_native_field_multiplication(
524 std::array<uint32_t, 2> queue_partial_non_native_field_multiplication(
529 add_simple limb1,
530 add_simple limb2,
531 add_simple limb3,
534 add_simple limb1,
535 add_simple limb2,
536 add_simple limb3,
538
542 size_t create_ROM_array(const size_t array_size);
543 void set_ROM_element(const size_t rom_id, const size_t index_value, const uint32_t value_witness);
544 void set_ROM_element_pair(const size_t rom_id,
545 const size_t index_value,
546 const std::array<uint32_t, 2>& value_witnesses);
547
548 uint32_t read_ROM_array(const size_t rom_id, const uint32_t index_witness);
549 std::array<uint32_t, 2> read_ROM_array_pair(const size_t rom_id, const uint32_t index_witness);
550
551 size_t create_RAM_array(const size_t array_size);
552 void init_RAM_element(const size_t ram_id, const size_t index_value, const uint32_t value_witness);
553
554 uint32_t read_RAM_array(const size_t ram_id, const uint32_t index_witness);
555 void write_RAM_array(const size_t ram_id, const uint32_t index_witness, const uint32_t value_witness);
556
559
560 // ========================================================================================
561 // TOOLING: Boomerang Detection
562 // ========================================================================================
563 // The boomerang mechanism enables detection of variables used in only one gate, which may
564 // indicate bugs.
565 // Note: some patterns (like x*(x^-1)=1 for non-zero checks) intentionally employ single-use witnesses. These
566 // members and methods allow excluding such witnesses from boomerang detection.
567
568 private:
569 // Witnesses that can be in one gate, but that's intentional (used in boomerang catcher)
570 std::vector<uint32_t> used_witnesses;
571 // Witnesses that appear in finalize method (used in boomerang catcher). Need to check
572 // that all variables from some connected component were created after finalize method was called
573 std::unordered_set<uint32_t> finalize_witnesses;
574
575 public:
576 const std::vector<uint32_t>& get_used_witnesses() const { return used_witnesses; }
577 const std::unordered_set<uint32_t>& get_finalize_witnesses() const { return finalize_witnesses; }
578
586 void update_used_witnesses(uint32_t var_idx) { used_witnesses.emplace_back(var_idx); }
587
595 void update_used_witnesses(const std::vector<uint32_t>& used_indices)
596 {
597 used_witnesses.reserve(used_witnesses.size() + used_indices.size());
598 for (const auto& it : used_indices) {
599 used_witnesses.emplace_back(it);
600 }
601 }
602
610 void update_finalize_witnesses(uint32_t var_idx) { finalize_witnesses.insert(var_idx); }
611
619 void update_finalize_witnesses(const std::vector<uint32_t>& finalize_indices)
620 {
621 for (const auto& it : finalize_indices) {
622 finalize_witnesses.insert(it);
623 }
624 }
625
626 // ========================================================================================
627
628 msgpack::sbuffer export_circuit() override;
629};
630using UltraCircuitBuilder = UltraCircuitBuilder_<UltraExecutionTraceBlocks>;
631} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:67
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:77
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:152
virtual uint32_t add_variable(const FF &in)
Add a variable to variables.
std::unordered_map< uint32_t, uint32_t > _tau
The permutation on variable tags, as a constituent of the generalized permutation argument.
void initialize_public_inputs(const std::vector< uint32_t > &public_inputs)
Directly initialize the public inputs vector.
const std::vector< uint32_t > & public_inputs() const
std::vector< uint32_t > real_variable_tags
real_variable_tags is the tagging mechanism for the the multiset-equality check.
virtual void assert_equal(uint32_t a_idx, uint32_t b_idx, std::string const &msg="assert_equal")
FF get_variable(const uint32_t index) const
Get the value of the variable v_{index}.
std::vector< uint32_t > real_variable_index
Map from witness index to real variable index.
ROM/RAM logic handler for UltraCircuitBuilder.
void fix_witness(const uint32_t witness_index, const FF &witness_value)
Add a gate equating a particular witness to a constant, fixing its value.
void init_RAM_element(const size_t ram_id, const size_t index_value, const uint32_t value_witness)
Initialize a RAM cell to equal value_witness
size_t get_num_finalized_gates() const override
Get the number of gates in a finalized circuit.
void create_ecc_dbl_gate(const ecc_dbl_gate_< FF > &in)
Create an elliptic curve doubling gate.
std::map< uint64_t, RangeList > range_lists
UltraCircuitBuilder_ & operator=(UltraCircuitBuilder_ &&other)=default
void add_gates_to_ensure_all_polys_are_non_zero()
Ensure all polynomials have at least one non-zero coefficient to avoid commiting to the zero-polynomi...
const std::unordered_set< uint32_t > & get_finalize_witnesses() const
UltraCircuitBuilder_(UltraCircuitBuilder_ &&other)=default
void update_used_witnesses(const std::vector< uint32_t > &used_indices)
Add a list of witness indices to the boomerang exclusion list.
plookup::MultiTable & get_multitable(const plookup::MultiTableId id)
void process_range_list(RangeList &list)
void create_poseidon2_internal_gate(const poseidon2_internal_gate_< FF > &in)
Poseidon2 internal round gate, activates the q_poseidon2_internal selector and relation.
size_t create_RAM_array(const size_t array_size)
Create a new updatable memory region.
UltraCircuitBuilder_(const size_t size_hint=0, bool is_write_vk_mode=false)
static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS
void create_unconstrained_gate(auto &block, const uint32_t &idx_1, const uint32_t &idx_2, const uint32_t &idx_3, const uint32_t &idx_4)
Create a gate with no constraints but with possibly non-trivial wire values.
void set_tau_at_index(const uint32_t tag_index, const uint32_t tau_index)
Set the tau(tag_index) = tau_index.
void update_finalize_witnesses(const std::vector< uint32_t > &finalize_indices)
Add a list of witness indices to the finalize exclusion list.
UltraCircuitBuilder_ & operator=(const UltraCircuitBuilder_ &other)=default
void create_big_mul_add_gate(const mul_quad_< FF > &in, const bool use_next_gate_w_4=false)
Create a big multiplication-addition gate, where in.a * in.b * in.mul_scaling + in....
std::unordered_set< uint32_t > finalize_witnesses
static constexpr size_t NUM_WIRES
std::vector< uint32_t > decompose_into_default_range(const uint32_t variable_index, const uint64_t num_bits, const uint64_t target_range_bitnum=DEFAULT_PLOOKUP_RANGE_BITNUM, std::string const &msg="decompose_into_default_range")
std::vector< cached_partial_non_native_field_multiplication > cached_partial_non_native_field_multiplications
msgpack::sbuffer export_circuit() override
void create_sort_constraint_with_edges(const std::vector< uint32_t > &variable_index, const FF &, const FF &)
std::tuple< scaled_witness, scaled_witness, FF > add_simple
uint32_t read_RAM_array(const size_t ram_id, const uint32_t index_witness)
void create_unconstrained_gates(const std::vector< uint32_t > &variable_index)
void create_add_gate(const add_triple_< FF > &in)
Create an addition gate, where in.a * in.a_scaling + in.b * in.b_scaling + in.c * in....
void create_big_add_gate(const add_quad_< FF > &in, const bool use_next_gate_w_4=false)
Create a big addition gate, where in.a * in.a_scaling + in.b * in.b_scaling + in.c * in....
typename ExecutionTrace::FF FF
const std::vector< uint32_t > & get_used_witnesses() const
std::vector< uint32_t > used_witnesses
std::array< uint32_t, 5 > evaluate_non_native_field_addition(add_simple limb0, add_simple limb1, add_simple limb2, add_simple limb3, std::tuple< uint32_t, uint32_t, FF > limbp)
Construct gates for non-native field addition.
const std::deque< plookup::BasicTable > & get_lookup_tables() const
size_t get_num_constant_gates() const override
size_t create_ROM_array(const size_t array_size)
Create a new read-only memory region (a.k.a. ROM table)
plookup::ReadData< uint32_t > create_gates_from_plookup_accumulators(const plookup::MultiTableId &id, const plookup::ReadData< FF > &read_values, const uint32_t key_a_index, std::optional< uint32_t > key_b_index=std::nullopt)
Create gates from pre-computed accumulator values which simultaneously establish individual basic-tab...
plookup::BasicTable & get_table(const plookup::BasicTableId id)
Get the basic table with provided ID from the set of tables for the present circuit; create it if it ...
static constexpr std::string_view NAME_STRING
void apply_nnf_selectors(const NNF_SELECTORS type)
Enable the nnf gate of particular type.
void create_ecc_add_gate(const ecc_add_gate_< FF > &in)
Create an elliptic curve addition gate.
void finalize_circuit(const bool ensure_nonzero)
void create_sort_constraint(const std::vector< uint32_t > &variable_index)
void create_poseidon2_external_gate(const poseidon2_external_gate_< FF > &in)
Poseidon2 external round gate, activates the q_poseidon2_external selector and relation.
std::array< uint32_t, 2 > evaluate_non_native_field_multiplication(const non_native_multiplication_witnesses< FF > &input)
Create gates for a full non-native field multiplication identity a * b = q * p + r.
void populate_public_inputs_block()
Copy the public input idx data into the public inputs trace block.
void create_range_constraint(const uint32_t variable_index, const size_t num_bits, std::string const &msg)
uint32_t read_ROM_array(const size_t rom_id, const uint32_t index_witness)
Read a single element from ROM.
RangeList create_range_list(const uint64_t target_range)
void assign_tag(const uint32_t variable_index, const uint32_t tag)
uint32_t put_constant_variable(const FF &variable)
void set_ROM_element(const size_t rom_id, const size_t index_value, const uint32_t value_witness)
Initialize a rom cell to equal value_witness
std::unordered_map< FF, uint32_t > constant_variable_indices
~UltraCircuitBuilder_() override=default
void create_bool_gate(const uint32_t a)
Generate an arithmetic gate equivalent to x^2 - x = 0, which forces x to be 0 or 1.
void update_finalize_witnesses(uint32_t var_idx)
Add a witness index to the finalize exclusion list.
void set_tau_transposition(const uint32_t tag_index_1, const uint32_t tag_index_2)
Add a transposition to tau.
UltraCircuitBuilder_(const UltraCircuitBuilder_ &other)=default
std::vector< uint32_t > memory_read_records
void update_used_witnesses(uint32_t var_idx)
Add a witness index to the boomerang exclusion list.
void check_selector_length_consistency()
Debug helper method for ensuring all selectors have the same size.
std::vector< uint32_t > memory_write_records
void write_RAM_array(const size_t ram_id, const uint32_t index_witness, const uint32_t value_witness)
void set_ROM_element_pair(const size_t rom_id, const size_t index_value, const std::array< uint32_t, 2 > &value_witnesses)
Initialize a ROM array element with a pair of witness values.
std::array< uint32_t, 2 > read_ROM_array_pair(const size_t rom_id, const uint32_t index_witness)
Read a pair of elements from ROM.
void assert_equal_constant(const uint32_t a_idx, const FF &b, std::string const &msg="assert equal constant")
void range_constrain_two_limbs(const uint32_t lo_idx, const uint32_t hi_idx, const size_t lo_limb_bits=DEFAULT_NON_NATIVE_FIELD_LIMB_BITS, const size_t hi_limb_bits=DEFAULT_NON_NATIVE_FIELD_LIMB_BITS, std::string const &msg="range_constrain_two_limbs")
std::pair< uint32_t, FF > scaled_witness
UltraCircuitBuilder_(const size_t size_hint, const std::vector< FF > &witness_values, const std::vector< uint32_t > &public_inputs, const bool is_write_vk_mode)
Constructor from data generated from ACIR.
std::array< uint32_t, 2 > queue_partial_non_native_field_multiplication(const non_native_partial_multiplication_witnesses< FF > &input)
Queue the addition of gates constraining the limb-multiplication part of a non native field mul.
std::array< uint32_t, 5 > evaluate_non_native_field_subtraction(add_simple limb0, add_simple limb1, add_simple limb2, add_simple limb3, std::tuple< uint32_t, uint32_t, FF > limbp)
Construct gates for non-native field subtraction.
void apply_memory_selectors(const MEMORY_SELECTORS type)
Enable the memory gate of particular type.
std::deque< plookup::BasicTable > lookup_tables
size_t get_finalized_total_circuit_size() const
Get the actual finalized size of a circuit. Assumes the circuit is finalized already.
static constexpr size_t DEFAULT_PLOOKUP_RANGE_SIZE
void process_non_native_field_multiplications()
Iterates over the cached_non_native_field_multiplication objects, removes duplicates,...
static constexpr size_t DEFAULT_PLOOKUP_RANGE_BITNUM
void create_new_range_constraint(const uint32_t variable_index, const uint64_t target_range, std::string const msg="create_new_range_constraint")
Constrain a variable to a range.
void create_arithmetic_gate(const arithmetic_triple_< FF > &in)
A plonk gate with disabled (set to zero) fourth wire. q_m * a * b + q_1 * a + q_2 * b + q_3.
size_t get_num_finalized_gates_inefficient(bool ensure_nonzero=true) const
Get the number of gates in the finalized version of the circuit.
std::deque< plookup::BasicTable > & get_lookup_tables()
size_t get_tables_size() const
Get combined size of all tables used in circuit.
static constexpr size_t DEFAULT_PLOOKUP_RANGE_STEP_SIZE
Container type for lookup table reads.
Definition types.hpp:341
FF a
FF b
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
UltraCircuitBuilder_< UltraExecutionTraceBlocks > UltraCircuitBuilder
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
bool operator==(const RangeList &other) const noexcept
size_t operator()(const cached_partial_non_native_field_multiplication &obj) const
Used to store instructions to create partial_non_native_field_multiplication gates.
static void deduplicate(std::vector< cached_partial_non_native_field_multiplication > &vec, UltraCircuitBuilder_< ExecutionTrace > *circuit_builder)
Dedupilcate cache entries which represent multiplication of the same witnesses.
bool operator<(const cached_partial_non_native_field_multiplication &other) const
bool operator==(const cached_partial_non_native_field_multiplication &other) const
A basic table from which we can perform lookups (for example, an xor table)
Definition types.hpp:271
Container for managing multiple BasicTables plus the data needed to combine basic table outputs (e....
Definition types.hpp:138