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: Complete, auditors: [Luke, Raju], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
7#pragma once
13
15#include "rom_ram_logic.hpp"
16#include <deque>
17#include <optional>
18#include <unordered_set>
19
21
22namespace bb {
23
24template <typename FF> struct non_native_multiplication_witnesses {
25 // first 4 array elements = limbs
26 std::array<uint32_t, 4> a;
27 std::array<uint32_t, 4> b;
28 std::array<uint32_t, 4> q;
29 std::array<uint32_t, 4> r;
30 std::array<FF, 4> neg_modulus;
31};
32
33template <typename FF> struct non_native_partial_multiplication_witnesses {
34 // first 4 array elements = limbs
35 std::array<uint32_t, 4> a;
36 std::array<uint32_t, 4> b;
37};
38
39template <typename ExecutionTrace_>
40class UltraCircuitBuilder_ : public CircuitBuilderBase<typename ExecutionTrace_::FF> {
41 public:
42 using ExecutionTrace = ExecutionTrace_;
43 using FF = typename ExecutionTrace::FF;
45
46 static constexpr size_t NUM_WIRES = ExecutionTrace::NUM_WIRES;
47
48 static constexpr std::string_view NAME_STRING = "UltraCircuitBuilder";
49 // The plookup-style range proof requires work linear in range size, thus cannot be used directly for
50 // large ranges such as 2^64. For such ranges the element will be decomposed into smaller
51 // chuncks according to the parameter below
52 static constexpr size_t DEFAULT_PLOOKUP_RANGE_BITNUM = 14;
53 static constexpr size_t DEFAULT_PLOOKUP_RANGE_STEP_SIZE = 3;
54 static constexpr size_t DEFAULT_PLOOKUP_RANGE_SIZE = (1 << DEFAULT_PLOOKUP_RANGE_BITNUM) - 1;
55 static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS = 68;
56 // We offer two types of range constraints: small (which can be non-dyadic) and general. The below constants
57 // determine their max values.
58 static constexpr size_t MAX_SMALL_RANGE_CONSTRAINT_VAL = (1 << 16) - 1;
59 static constexpr size_t MAX_NUM_BITS_RANGE_CONSTRAINT =
60 253; // the Grumpkin scalar field modulus is between 2^253 and 2^254 and has 254 bits. Therefore the largest
61 // non-vacuous dyadic range-constraint we can enforce is 2^253 - 1, i.e., `num_bits == 253`.
71
80
81 struct RangeList {
82 uint64_t target_range; // range constraint will be for the range [0, target_range], i.e., is inclusive of
83 // `target_range`.
84 uint32_t range_tag; // Every variable that is range-constrained to a given `target_range` has the same tag,
85 // namely, `range_tag`. Never `DEFAULT_TAG`.
86 uint32_t tau_tag; // Tag assigned to the sorted reference set. Never `DEFAULT_TAG`.
87 std::vector<uint32_t>
88 variable_indices; // All variable-indices constrained to this range. During processing, this will be
89 // mutated: replaced by real-variable-indices, then deduplicated.
90 bool operator==(const RangeList& other) const noexcept
91 {
92 return target_range == other.target_range && range_tag == other.range_tag && tau_tag == other.tau_tag &&
93 variable_indices == other.variable_indices;
94 }
95 };
96
97 // AUDITTODO: this is not a large optimization (~0.5% reduction for ultra rec verifier); consider removing
104 std::array<uint32_t, 4> a;
105 std::array<uint32_t, 4> b;
106 uint32_t lo_0;
107 uint32_t hi_0;
108 uint32_t hi_1;
109
111 {
112 bool valid = true;
113 for (size_t i = 0; i < 4; ++i) {
114 valid = valid && (a[i] == other.a[i]);
115 valid = valid && (b[i] == other.b[i]);
116 }
117 return valid;
118 }
119
131 {
133
135
136 for (const auto& item : vec) {
137 auto [existing_element, not_in_set] = seen.insert(item);
138 // Memorize if not in set yet
139 if (not_in_set) {
140 uniqueVec.push_back(item);
141 } else {
142 // If we already have a representative, we need to connect the outputs together
143 circuit_builder->assert_equal(item.lo_0, (*existing_element).lo_0);
144 circuit_builder->assert_equal(item.hi_0, (*existing_element).hi_0);
145 circuit_builder->assert_equal(item.hi_1, (*existing_element).hi_1);
146 }
147 }
148
149 vec.swap(uniqueVec);
150 }
151
153 {
154 if (a < other.a) {
155 return true;
156 }
157 if (other.a < a) {
158 return false;
159 }
160 if (b < other.b) {
161 return true;
162 }
163 return other.b < b;
164 }
165
166 struct Hash {
168 {
169 size_t combined_hash = 0;
170
171 // C++ does not have a standard way to hash values, so we use the
172 // common algorithm that boot uses.
173 // You can search for 'cpp hash_combine' to find more information.
174 // Here is one reference:
175 // https://stackoverflow.com/questions/2590677/how-do-i-combine-hash-values-in-c0x
176 auto hash_combiner = [](size_t lhs, size_t rhs) {
177 return lhs ^ (rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2));
178 };
179
180 for (const auto& elem : obj.a) {
181 combined_hash = hash_combiner(combined_hash, std::hash<uint32_t>()(elem));
182 }
183 for (const auto& elem : obj.b) {
184 combined_hash = hash_combiner(combined_hash, std::hash<uint32_t>()(elem));
185 }
186
187 return combined_hash;
188 }
189 };
190 };
191
192 private:
193 // The set of lookup tables used by the circuit, plus the gate data for the lookups from each table
195
196 public:
197 // Storage for wires and selectors for all gate types
199
200 // The set of variables which have been constrained to a particular value via an arithmetic gate
201 std::unordered_map<FF, uint32_t> constant_variable_indices;
202
203 // Rom/Ram logic
205
206 // Stores gate index of ROM/RAM reads (required by proving key)
207 std::vector<uint32_t> memory_read_records;
208 // Stores gate index of RAM writes (required by proving key)
209 std::vector<uint32_t> memory_write_records;
210 // Range constraints to be batched, keyed by target_range. See create_small_range_constraint() for details.
212
214
215 std::vector<fr> ipa_proof;
216
218
220
223 {
225 // The identity permutation on the set `{DEFAULT_TAG}`. We therefore assume that the
226 // `DEFAULT_TAG` is not involved in any non-trivial multiset-equality checks.
227 this->set_tau_at_index(DEFAULT_TAG, DEFAULT_TAG);
228 };
229
245 UltraCircuitBuilder_(const std::vector<FF>& witness_values,
246 const std::vector<uint32_t>& public_inputs,
247 const bool is_write_vk_mode)
249 {
250 for (const auto value : witness_values) {
251 this->add_variable(value);
252 }
253
254 // Initialize the builder public_inputs directly from the acir public inputs.
255 this->initialize_public_inputs(public_inputs);
256
257 // Add the const zero variable after the acir witness has been
258 // incorporated into variables.
260 this->set_tau_at_index(DEFAULT_TAG,
261 DEFAULT_TAG); // tau fixes the `DEFAULT_TAG`, as we assume that `DEFAULT_TAG` is not
262 // involved in any non-trivial multiset-equality checks.
263 };
268 ~UltraCircuitBuilder_() override = default;
269
278 {
279#if NDEBUG
280 // do nothing
281#else
282 for (auto& block : blocks.get()) {
283 const auto& block_selectors = block.get_selectors();
284 size_t nominal_size = block_selectors[0].size();
285 for (size_t idx = 1; idx < block_selectors.size(); ++idx) {
286 BB_ASSERT_EQ(block_selectors[idx].size(), nominal_size);
287 }
288 }
289
290#endif // NDEBUG
291 }
292
293 void finalize_circuit(const bool ensure_nonzero);
294
296
297 void create_add_gate(const add_triple_<FF>& in);
298 void create_big_mul_add_gate(const mul_quad_<FF>& in, const bool use_next_gate_w_4 = false);
299 void create_big_add_gate(const add_quad_<FF>& in, const bool use_next_gate_w_4 = false);
300
301 void create_bool_gate(const uint32_t a);
303 void create_ecc_add_gate(const ecc_add_gate_& in);
305
306 void fix_witness(const uint32_t witness_index, const FF& witness_value);
307
328 void create_small_range_constraint(const uint32_t variable_index,
329 const uint64_t target_range,
330 std::string const msg = "create_small_range_constraint");
331
342 void create_dyadic_range_constraint(const uint32_t variable_index, const size_t num_bits, std::string const& msg)
343 {
344 if (num_bits == 1) {
345 create_bool_gate(variable_index);
346 } else if (num_bits <= DEFAULT_PLOOKUP_RANGE_BITNUM) {
347 // Add an unconstrained gate to ensure variable_index appears in a wire. (See warning in
348 // `create_small_range_constraint` for more details.)
350 blocks.arithmetic, variable_index, this->zero_idx(), this->zero_idx(), this->zero_idx());
351 create_small_range_constraint(variable_index, (1ULL << num_bits) - 1, msg);
352 } else {
353 create_limbed_range_constraint(variable_index, num_bits, DEFAULT_PLOOKUP_RANGE_BITNUM, msg);
354 }
355 }
356
357 uint32_t put_constant_variable(const FF& variable);
358
359 size_t get_num_constant_gates() const override { return 0; }
360
365 size_t get_num_finalized_gates() const override
366 {
368 return this->num_gates();
369 }
370
379 size_t get_num_finalized_gates_inefficient(bool ensure_nonzero = true) const
380 {
381 UltraCircuitBuilder_ builder_copy = *this;
382 builder_copy.finalize_circuit(ensure_nonzero);
383 return builder_copy.get_num_finalized_gates();
384 }
385
390 size_t get_tables_size() const
391 {
392 size_t tables_size = 0;
393 for (const auto& table : lookup_tables) {
394 tables_size += table.size();
395 }
396 return tables_size;
397 }
398
409 {
411 auto num_filled_gates = get_num_finalized_gates() + this->num_public_inputs();
412 return std::max(get_tables_size(), num_filled_gates);
413 }
414
415 void assert_equal_constant(const uint32_t a_idx, const FF& b, std::string const& msg = "assert equal constant")
416 {
417 if (this->get_variable(a_idx) != b && !this->failed()) {
418 this->failure(msg);
419 }
420 auto b_idx = put_constant_variable(b);
421 this->assert_equal(a_idx, b_idx, msg);
422 }
423
429
430 // Accessors for lookup tables
433 size_t get_num_lookup_tables() const { return lookup_tables.size(); }
434
436 const plookup::MultiTableId& id,
437 const plookup::ReadData<FF>& read_values,
438 const uint32_t key_a_index,
440
449 std::vector<uint32_t> create_limbed_range_constraint(
450 const uint32_t variable_index,
451 const uint64_t num_bits,
452 const uint64_t target_range_bitnum = DEFAULT_PLOOKUP_RANGE_BITNUM,
453 std::string const& msg = "create_limbed_range_constraint");
454
464 auto& block, const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4)
465 {
466 block.populate_wires(idx_1, idx_2, idx_3, idx_4);
467 block.q_m().emplace_back(0);
468 block.q_1().emplace_back(0);
469 block.q_2().emplace_back(0);
470 block.q_3().emplace_back(0);
471 block.q_c().emplace_back(0);
472 block.q_4().emplace_back(0);
473 block.set_gate_selector(0); // all selectors zero
474
476 this->increment_num_gates();
477 }
478 void create_unconstrained_gates(const std::vector<uint32_t>& variable_index);
479
486 void enforce_small_deltas(const std::vector<uint32_t>& variable_indices);
503 void create_sort_constraint_with_edges(const std::vector<uint32_t>& variable_indices,
504 const FF& start,
505 const FF& end);
506
510 void assign_tag(const uint32_t variable_index, const uint32_t tag)
511 {
513 // If we've already assigned this tag to this variable, return (can happen due to copy constraints)
514 if (this->real_variable_tags[this->real_variable_index[variable_index]] == tag) {
515 return;
516 }
517
518 BB_ASSERT_EQ(this->real_variable_tags[this->real_variable_index[variable_index]], DEFAULT_TAG);
519 this->real_variable_tags[this->real_variable_index[variable_index]] = tag;
520 }
528 void set_tau_at_index(const uint32_t tag_index, const uint32_t tau_index)
529 {
530 this->_tau.insert({ tag_index, tau_index });
531 }
544 void set_tau_transposition(const uint32_t tag_index_1, const uint32_t tag_index_2)
545 {
546 set_tau_at_index(tag_index_1, tag_index_2);
547 set_tau_at_index(tag_index_2, tag_index_1);
548 }
549
550 uint32_t get_new_tag()
551 {
552 this->current_tag++;
553 return this->current_tag;
554 }
555
556 RangeList create_range_list(const uint64_t target_range);
557 void process_range_list(RangeList& list);
558 void process_range_lists();
559
565
569 void range_constrain_two_limbs(const uint32_t lo_idx,
570 const uint32_t hi_idx,
571 const size_t lo_limb_bits = DEFAULT_NON_NATIVE_FIELD_LIMB_BITS,
572 const size_t hi_limb_bits = DEFAULT_NON_NATIVE_FIELD_LIMB_BITS,
573 std::string const& msg = "range_constrain_two_limbs");
574 std::array<uint32_t, 2> evaluate_non_native_field_multiplication(
576 std::array<uint32_t, 2> queue_partial_non_native_field_multiplication(
581 add_simple limb1,
582 add_simple limb2,
583 add_simple limb3,
586 add_simple limb1,
587 add_simple limb2,
588 add_simple limb3,
590
594 size_t create_ROM_array(const size_t array_size);
595 void set_ROM_element(const size_t rom_id, const size_t index_value, const uint32_t value_witness);
596 void set_ROM_element_pair(const size_t rom_id,
597 const size_t index_value,
598 const std::array<uint32_t, 2>& value_witnesses);
599
600 uint32_t read_ROM_array(const size_t rom_id, const uint32_t index_witness);
601 std::array<uint32_t, 2> read_ROM_array_pair(const size_t rom_id, const uint32_t index_witness);
602
603 size_t create_RAM_array(const size_t array_size);
604 void init_RAM_element(const size_t ram_id, const size_t index_value, const uint32_t value_witness);
605
606 uint32_t read_RAM_array(const size_t ram_id, const uint32_t index_witness);
607 void write_RAM_array(const size_t ram_id, const uint32_t index_witness, const uint32_t value_witness);
608
611
612 // ========================================================================================
613 // TOOLING: Boomerang Detection
614 // ========================================================================================
615 // The boomerang mechanism enables detection of variables used in only one gate, which may
616 // indicate bugs.
617 // Note: some patterns (like x*(x^-1)=1 for non-zero checks) intentionally employ single-use witnesses. These
618 // members and methods allow excluding such witnesses from boomerang detection.
619
620 private:
621 // Witnesses that can be in one gate, but that's intentional (used in boomerang catcher)
622 std::vector<uint32_t> used_witnesses;
623 // Witnesses that appear in finalize method (used in boomerang catcher). Need to check
624 // that all variables from some connected component were created after finalize method was called
625 std::unordered_set<uint32_t> finalize_witnesses;
626
627 public:
628 const std::vector<uint32_t>& get_used_witnesses() const { return used_witnesses; }
629 const std::unordered_set<uint32_t>& get_finalize_witnesses() const { return finalize_witnesses; }
630
638 void update_used_witnesses(uint32_t var_idx) { used_witnesses.emplace_back(var_idx); }
639
647 void update_used_witnesses(const std::vector<uint32_t>& used_indices)
648 {
649 used_witnesses.reserve(used_witnesses.size() + used_indices.size());
650 for (const auto& it : used_indices) {
651 used_witnesses.emplace_back(it);
652 }
653 }
654
662 void update_finalize_witnesses(uint32_t var_idx) { finalize_witnesses.insert(var_idx); }
663
671 void update_finalize_witnesses(const std::vector<uint32_t>& finalize_indices)
672 {
673 for (const auto& it : finalize_indices) {
674 finalize_witnesses.insert(it);
675 }
676 }
677
678 // ========================================================================================
679
680 msgpack::sbuffer export_circuit();
681};
682using UltraCircuitBuilder = UltraCircuitBuilder_<UltraExecutionTraceBlocks>;
683} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:158
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 create_sort_constraint_with_edges(const std::vector< uint32_t > &variable_indices, const FF &start, const FF &end)
Constrain consecutive variable differences to be in {0, 1, 2, 3}, with boundary checks.
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.
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
static constexpr size_t MAX_NUM_BITS_RANGE_CONSTRAINT
std::vector< cached_partial_non_native_field_multiplication > cached_partial_non_native_field_multiplications
void create_small_range_constraint(const uint32_t variable_index, const uint64_t target_range, std::string const msg="create_small_range_constraint")
Range-constraints for small ranges, where the upper bound (target_range) need not be dyadic....
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....
void create_ecc_add_gate(const ecc_add_gate_ &in)
Create an elliptic curve addition gate.
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.
std::vector< uint32_t > create_limbed_range_constraint(const uint32_t variable_index, const uint64_t num_bits, const uint64_t target_range_bitnum=DEFAULT_PLOOKUP_RANGE_BITNUM, std::string const &msg="create_limbed_range_constraint")
Range-constrain a variable to [0, 2^num_bits - 1] by decomposing into smaller limbs.
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...
UltraCircuitBuilder_(bool is_write_vk_mode=false)
void create_dyadic_range_constraint(const uint32_t variable_index, const size_t num_bits, std::string const &msg)
Entry point for range constraints where the upper bound is a power of 2 (i.e., dyadic)....
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 finalize_circuit(const bool ensure_nonzero)
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.
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)
UltraCircuitBuilder_(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.
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
void enforce_small_deltas(const std::vector< uint32_t > &variable_indices)
Check for a sequence of variables that the neighboring differences are in {0, 1, 2,...
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.
static constexpr size_t MAX_SMALL_RANGE_CONSTRAINT_VAL
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
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_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 for lookup accumulator values and table reads.
Definition types.hpp:357
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:285
Container for managing multiple BasicTables plus the data needed to combine basic table outputs (e....
Definition types.hpp:147