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
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-style 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 // We offer two types of range constraints: small (which can be non-dyadic) and general. The below constants
58 // determine their max values.
59 static constexpr size_t MAX_SMALL_RANGE_CONSTRAINT_VAL = (1 << 16) - 1;
60 static constexpr size_t MAX_NUM_BITS_RANGE_CONSTRAINT =
61 253; // the Grumpkin scalar field modulus is between 2^253 and 2^254 and has 254 bits. Therefore the largest
62 // non-vacuous dyadic range-constraint we can enforce is 2^253 - 1, i.e., `num_bits == 253`.
72
81
82 struct RangeList {
83 uint64_t target_range; // range constraint will be for the range [0, target_range], i.e., is inclusive of
84 // `target_range`.
85 uint32_t range_tag; // Every variable that is range-constrained to a given `target_range` has the same tag,
86 // namely, `range_tag`. Never `DEFAULT_TAG`.
87 uint32_t tau_tag; // Tag assigned to the sorted reference set. Never `DEFAULT_TAG`.
88 std::vector<uint32_t>
89 variable_indices; // All variable-indices constrained to this range. During processing, this will be
90 // mutated: replaced by real-variable-indices, then deduplicated.
91 bool operator==(const RangeList& other) const noexcept
92 {
93 return target_range == other.target_range && range_tag == other.range_tag && tau_tag == other.tau_tag &&
94 variable_indices == other.variable_indices;
95 }
96 };
97
98 // AUDITTODO: this is not a large optimization (~0.5% reduction for ultra rec verifier); consider removing
105 std::array<uint32_t, 4> a;
106 std::array<uint32_t, 4> b;
107 uint32_t lo_0;
108 uint32_t hi_0;
109 uint32_t hi_1;
110
112 {
113 bool valid = true;
114 for (size_t i = 0; i < 4; ++i) {
115 valid = valid && (a[i] == other.a[i]);
116 valid = valid && (b[i] == other.b[i]);
117 }
118 return valid;
119 }
120
132 {
134
136
137 for (const auto& item : vec) {
138 auto [existing_element, not_in_set] = seen.insert(item);
139 // Memorize if not in set yet
140 if (not_in_set) {
141 uniqueVec.push_back(item);
142 } else {
143 // If we already have a representative, we need to connect the outputs together
144 circuit_builder->assert_equal(item.lo_0, (*existing_element).lo_0);
145 circuit_builder->assert_equal(item.hi_0, (*existing_element).hi_0);
146 circuit_builder->assert_equal(item.hi_1, (*existing_element).hi_1);
147 }
148 }
149
150 vec.swap(uniqueVec);
151 }
152
154 {
155 if (a < other.a) {
156 return true;
157 }
158 if (other.a < a) {
159 return false;
160 }
161 if (b < other.b) {
162 return true;
163 }
164 return other.b < b;
165 }
166
167 struct Hash {
169 {
170 size_t combined_hash = 0;
171
172 // C++ does not have a standard way to hash values, so we use the
173 // common algorithm that boot uses.
174 // You can search for 'cpp hash_combine' to find more information.
175 // Here is one reference:
176 // https://stackoverflow.com/questions/2590677/how-do-i-combine-hash-values-in-c0x
177 auto hash_combiner = [](size_t lhs, size_t rhs) {
178 return lhs ^ (rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2));
179 };
180
181 for (const auto& elem : obj.a) {
182 combined_hash = hash_combiner(combined_hash, std::hash<uint32_t>()(elem));
183 }
184 for (const auto& elem : obj.b) {
185 combined_hash = hash_combiner(combined_hash, std::hash<uint32_t>()(elem));
186 }
187
188 return combined_hash;
189 }
190 };
191 };
192
193 private:
194 // The set of lookup tables used by the circuit, plus the gate data for the lookups from each table
196
197 public:
198 // Storage for wires and selectors for all gate types
200
201 // The set of variables which have been constrained to a particular value via an arithmetic gate
202 std::unordered_map<FF, uint32_t> constant_variable_indices;
203
204 // Rom/Ram logic
206
207 // Stores gate index of ROM/RAM reads (required by proving key)
208 std::vector<uint32_t> memory_read_records;
209 // Stores gate index of RAM writes (required by proving key)
210 std::vector<uint32_t> memory_write_records;
212
214
215 bool circuit_finalized = false;
216
217 std::vector<fr> ipa_proof;
218
220
222
225 {
227 // The identity permutation on the set `{DEFAULT_TAG}`. We therefore assume that the
228 // `DEFAULT_TAG` is not involved in any non-trivial multiset-equality checks.
229 this->set_tau_at_index(DEFAULT_TAG, DEFAULT_TAG);
230 };
231
247 UltraCircuitBuilder_(const std::vector<FF>& witness_values,
248 const std::vector<uint32_t>& public_inputs,
249 const bool is_write_vk_mode)
251 {
252 for (const auto value : witness_values) {
253 this->add_variable(value);
254 }
255
256 // Initialize the builder public_inputs directly from the acir public inputs.
257 this->initialize_public_inputs(public_inputs);
258
259 // Add the const zero variable after the acir witness has been
260 // incorporated into variables.
262 this->set_tau_at_index(DEFAULT_TAG,
263 DEFAULT_TAG); // tau fixes the `DEFAULT_TAG`, as we assume that `DEFAULT_TAG` is not
264 // involved in any non-trivial multiset-equality checks.
265 };
270 ~UltraCircuitBuilder_() override = default;
271
280 {
281#if NDEBUG
282 // do nothing
283#else
284 for (auto& block : blocks.get()) {
285 const auto& block_selectors = block.get_selectors();
286 size_t nominal_size = block_selectors[0].size();
287 for (size_t idx = 1; idx < block_selectors.size(); ++idx) {
288 BB_ASSERT_EQ(block_selectors[idx].size(), nominal_size);
289 }
290 }
291
292#endif // NDEBUG
293 }
294
295 void finalize_circuit(const bool ensure_nonzero);
296
298
299 void create_add_gate(const add_triple_<FF>& in);
300 void create_big_mul_add_gate(const mul_quad_<FF>& in, const bool use_next_gate_w_4 = false);
301 void create_big_add_gate(const add_quad_<FF>& in, const bool use_next_gate_w_4 = false);
302
303 void create_bool_gate(const uint32_t a);
307
308 void fix_witness(const uint32_t witness_index, const FF& witness_value);
309
329 void create_small_range_constraint(const uint32_t variable_index,
330 const uint64_t target_range,
331 std::string const msg = "create_small_range_constraint");
332
343 void create_dyadic_range_constraint(const uint32_t variable_index, const size_t num_bits, std::string const& msg)
344 {
345 if (num_bits == 1) {
346 create_bool_gate(variable_index);
347 } else if (num_bits <= DEFAULT_PLOOKUP_RANGE_BITNUM) {
348 // Add an unconstrained gate to ensure variable_index appears in a wire. (See warning in
349 // `create_small_range_constraint` for more details.)
351 blocks.arithmetic, variable_index, this->zero_idx(), this->zero_idx(), this->zero_idx());
352 create_small_range_constraint(variable_index, (1ULL << num_bits) - 1, msg);
353 } else {
354 create_limbed_range_constraint(variable_index, num_bits, DEFAULT_PLOOKUP_RANGE_BITNUM, msg);
355 }
356 }
357
358 uint32_t put_constant_variable(const FF& variable);
359
360 size_t get_num_constant_gates() const override { return 0; }
361
366 size_t get_num_finalized_gates() const override
367 {
369 return this->num_gates();
370 }
371
380 size_t get_num_finalized_gates_inefficient(bool ensure_nonzero = true) const
381 {
382 UltraCircuitBuilder_ builder_copy = *this;
383 builder_copy.finalize_circuit(ensure_nonzero);
384 return builder_copy.get_num_finalized_gates();
385 }
386
391 size_t get_tables_size() const
392 {
393 size_t tables_size = 0;
394 for (const auto& table : lookup_tables) {
395 tables_size += table.size();
396 }
397 return tables_size;
398 }
399
410 {
412 auto num_filled_gates = get_num_finalized_gates() + this->num_public_inputs();
413 return std::max(get_tables_size(), num_filled_gates);
414 }
415
416 void assert_equal_constant(const uint32_t a_idx, const FF& b, std::string const& msg = "assert equal constant")
417 {
418 if (this->get_variable(a_idx) != b && !this->failed()) {
419 this->failure(msg);
420 }
421 auto b_idx = put_constant_variable(b);
422 this->assert_equal(a_idx, b_idx, msg);
423 }
424
430
431 // Accessors for lookup tables
434 size_t get_num_lookup_tables() const { return lookup_tables.size(); }
435
437 const plookup::MultiTableId& id,
438 const plookup::ReadData<FF>& read_values,
439 const uint32_t key_a_index,
441
450 std::vector<uint32_t> create_limbed_range_constraint(
451 const uint32_t variable_index,
452 const uint64_t num_bits,
453 const uint64_t target_range_bitnum = DEFAULT_PLOOKUP_RANGE_BITNUM,
454 std::string const& msg = "create_limbed_range_constraint");
455
465 auto& block, const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4)
466 {
467 block.populate_wires(idx_1, idx_2, idx_3, idx_4);
468 block.q_m().emplace_back(0);
469 block.q_1().emplace_back(0);
470 block.q_2().emplace_back(0);
471 block.q_3().emplace_back(0);
472 block.q_c().emplace_back(0);
473 block.q_4().emplace_back(0);
474 block.set_gate_selector(0); // all selectors zero
475
477 this->increment_num_gates();
478 }
479 void create_unconstrained_gates(const std::vector<uint32_t>& variable_index);
480
487 void enforce_small_deltas(const std::vector<uint32_t>& variable_indices);
504 void create_sort_constraint_with_edges(const std::vector<uint32_t>& variable_indices,
505 const FF& start,
506 const FF& end);
507
511 void assign_tag(const uint32_t variable_index, const uint32_t tag)
512 {
514 // If we've already assigned this tag to this variable, return (can happen due to copy constraints)
515 if (this->real_variable_tags[this->real_variable_index[variable_index]] == tag) {
516 return;
517 }
518
519 BB_ASSERT_EQ(this->real_variable_tags[this->real_variable_index[variable_index]], DEFAULT_TAG);
520 this->real_variable_tags[this->real_variable_index[variable_index]] = tag;
521 }
529 void set_tau_at_index(const uint32_t tag_index, const uint32_t tau_index)
530 {
531 this->_tau.insert({ tag_index, tau_index });
532 }
545 void set_tau_transposition(const uint32_t tag_index_1, const uint32_t tag_index_2)
546 {
547 set_tau_at_index(tag_index_1, tag_index_2);
548 set_tau_at_index(tag_index_2, tag_index_1);
549 }
550
551 uint32_t get_new_tag()
552 {
553 this->current_tag++;
554 return this->current_tag;
555 }
556
557 RangeList create_range_list(const uint64_t target_range);
558 void process_range_list(RangeList& list);
559 void process_range_lists();
560
566
570 void range_constrain_two_limbs(const uint32_t lo_idx,
571 const uint32_t hi_idx,
572 const size_t lo_limb_bits = DEFAULT_NON_NATIVE_FIELD_LIMB_BITS,
573 const size_t hi_limb_bits = DEFAULT_NON_NATIVE_FIELD_LIMB_BITS,
574 std::string const& msg = "range_constrain_two_limbs");
575 std::array<uint32_t, 2> evaluate_non_native_field_multiplication(
577 std::array<uint32_t, 2> queue_partial_non_native_field_multiplication(
582 add_simple limb1,
583 add_simple limb2,
584 add_simple limb3,
587 add_simple limb1,
588 add_simple limb2,
589 add_simple limb3,
591
595 size_t create_ROM_array(const size_t array_size);
596 void set_ROM_element(const size_t rom_id, const size_t index_value, const uint32_t value_witness);
597 void set_ROM_element_pair(const size_t rom_id,
598 const size_t index_value,
599 const std::array<uint32_t, 2>& value_witnesses);
600
601 uint32_t read_ROM_array(const size_t rom_id, const uint32_t index_witness);
602 std::array<uint32_t, 2> read_ROM_array_pair(const size_t rom_id, const uint32_t index_witness);
603
604 size_t create_RAM_array(const size_t array_size);
605 void init_RAM_element(const size_t ram_id, const size_t index_value, const uint32_t value_witness);
606
607 uint32_t read_RAM_array(const size_t ram_id, const uint32_t index_witness);
608 void write_RAM_array(const size_t ram_id, const uint32_t index_witness, const uint32_t value_witness);
609
612
613 // ========================================================================================
614 // TOOLING: Boomerang Detection
615 // ========================================================================================
616 // The boomerang mechanism enables detection of variables used in only one gate, which may
617 // indicate bugs.
618 // Note: some patterns (like x*(x^-1)=1 for non-zero checks) intentionally employ single-use witnesses. These
619 // members and methods allow excluding such witnesses from boomerang detection.
620
621 private:
622 // Witnesses that can be in one gate, but that's intentional (used in boomerang catcher)
623 std::vector<uint32_t> used_witnesses;
624 // Witnesses that appear in finalize method (used in boomerang catcher). Need to check
625 // that all variables from some connected component were created after finalize method was called
626 std::unordered_set<uint32_t> finalize_witnesses;
627
628 public:
629 const std::vector<uint32_t>& get_used_witnesses() const { return used_witnesses; }
630 const std::unordered_set<uint32_t>& get_finalize_witnesses() const { return finalize_witnesses; }
631
639 void update_used_witnesses(uint32_t var_idx) { used_witnesses.emplace_back(var_idx); }
640
648 void update_used_witnesses(const std::vector<uint32_t>& used_indices)
649 {
650 used_witnesses.reserve(used_witnesses.size() + used_indices.size());
651 for (const auto& it : used_indices) {
652 used_witnesses.emplace_back(it);
653 }
654 }
655
663 void update_finalize_witnesses(uint32_t var_idx) { finalize_witnesses.insert(var_idx); }
664
672 void update_finalize_witnesses(const std::vector<uint32_t>& finalize_indices)
673 {
674 for (const auto& it : finalize_indices) {
675 finalize_witnesses.insert(it);
676 }
677 }
678
679 // ========================================================================================
680
681 msgpack::sbuffer export_circuit() override;
682};
683using UltraCircuitBuilder = UltraCircuitBuilder_<UltraExecutionTraceBlocks>;
684} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:80
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:93
#define BB_ASSERT_LTE(left, right,...)
Definition assert.hpp:168
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
msgpack::sbuffer export_circuit() override
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....
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 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_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