barretenberg
Loading...
Searching...
No Matches
ultra_circuit_builder.hpp
1#pragma once
2// #include "barretenberg/plonk/proof_system/constants.hpp"
3// #include "barretenberg/plonk/proof_system/types/polynomial_manifest.hpp"
4// #include "barretenberg/plonk/proof_system/types/prover_settings.hpp"
5#include "barretenberg/polynomials/polynomial.hpp"
6#include "barretenberg/proof_system/op_queue/ecc_op_queue.hpp"
7#include "barretenberg/proof_system/plookup_tables/plookup_tables.hpp"
8#include "barretenberg/proof_system/plookup_tables/types.hpp"
9#include "barretenberg/proof_system/types/circuit_type.hpp"
10#include "barretenberg/proof_system/types/merkle_hash_type.hpp"
11#include "barretenberg/proof_system/types/pedersen_commitment_type.hpp"
12#include "circuit_builder_base.hpp"
13#include <optional>
14
15namespace proof_system {
16
17template <typename FF> struct non_native_field_witnesses {
18 // first 4 array elements = limbs
19 // 5th element = prime basis limb
20 std::array<uint32_t, 5> a;
21 std::array<uint32_t, 5> b;
22 std::array<uint32_t, 5> q;
23 std::array<uint32_t, 5> r;
24 std::array<FF, 5> neg_modulus;
25 FF modulus;
26};
27
28using namespace barretenberg;
29
30template <typename Arithmetization>
31class UltraCircuitBuilder_ : public CircuitBuilderBase<typename Arithmetization::FF> {
32 public:
33 using FF = typename Arithmetization::FF;
34 static constexpr size_t NUM_WIRES = Arithmetization::NUM_WIRES;
35 // Keeping NUM_WIRES, at least temporarily, for backward compatibility
36 static constexpr size_t program_width = Arithmetization::NUM_WIRES;
37 static constexpr size_t num_selectors = Arithmetization::NUM_SELECTORS;
38 std::vector<std::string> selector_names = Arithmetization::selector_names;
39
40 static constexpr std::string_view NAME_STRING = "UltraArithmetization";
41 static constexpr CircuitType CIRCUIT_TYPE = CircuitType::ULTRA;
42 static constexpr merkle::HashType merkle_hash_type = merkle::HashType::LOOKUP_PEDERSEN;
43 static constexpr pedersen::CommitmentType commitment_type = pedersen::CommitmentType::FIXED_BASE_PEDERSEN;
44 static constexpr size_t UINT_LOG2_BASE = 6; // DOCTODO: explain what this is, or rename.
45 // The plookup range proof requires work linear in range size, thus cannot be used directly for
46 // large ranges such as 2^64. For such ranges the element will be decomposed into smaller
47 // chuncks according to the parameter below
48 static constexpr size_t DEFAULT_PLOOKUP_RANGE_BITNUM = 14;
49 static constexpr size_t DEFAULT_PLOOKUP_RANGE_STEP_SIZE = 3;
50 static constexpr size_t DEFAULT_PLOOKUP_RANGE_SIZE = (1 << DEFAULT_PLOOKUP_RANGE_BITNUM) - 1;
51 static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS = 68;
52 static constexpr uint32_t UNINITIALIZED_MEMORY_RECORD = UINT32_MAX;
53 static constexpr size_t NUMBER_OF_GATES_PER_RAM_ACCESS = 2;
54 static constexpr size_t NUMBER_OF_ARITHMETIC_GATES_PER_RAM_ARRAY = 1;
55 static constexpr size_t NUM_RESERVED_GATES = 4;
56 // number of gates created per non-native field operation in process_non_native_field_multiplications
57 static constexpr size_t GATES_PER_NON_NATIVE_FIELD_MULTIPLICATION_ARITHMETIC = 7;
58
59 size_t num_vars_added_in_constructor = 0; // needed in constructing circuit from acir
60
61 enum AUX_SELECTORS {
62 NONE,
63 LIMB_ACCUMULATE_1,
64 LIMB_ACCUMULATE_2,
65 NON_NATIVE_FIELD_1,
66 NON_NATIVE_FIELD_2,
67 NON_NATIVE_FIELD_3,
68 RAM_CONSISTENCY_CHECK,
69 ROM_CONSISTENCY_CHECK,
70 RAM_TIMESTAMP_CHECK,
71 ROM_READ,
72 RAM_READ,
73 RAM_WRITE,
74 };
75
76 struct RangeList {
77 uint64_t target_range;
78 uint32_t range_tag;
79 uint32_t tau_tag;
80 std::vector<uint32_t> variable_indices;
81 bool operator==(const RangeList& other) const noexcept
82 {
83 return target_range == other.target_range && range_tag == other.range_tag && tau_tag == other.tau_tag &&
84 variable_indices == other.variable_indices;
85 }
86 };
87
93 struct RomRecord {
94 uint32_t index_witness = 0;
95 uint32_t value_column1_witness = 0;
96 uint32_t value_column2_witness = 0;
97 uint32_t index = 0;
98 uint32_t record_witness = 0;
99 size_t gate_index = 0;
100 bool operator<(const RomRecord& other) const { return index < other.index; }
101 bool operator==(const RomRecord& other) const noexcept
102 {
103 return index_witness == other.index_witness && value_column1_witness == other.value_column1_witness &&
104 value_column2_witness == other.value_column2_witness && index == other.index &&
105 record_witness == other.record_witness && gate_index == other.gate_index;
106 }
107 };
108
114 struct RamRecord {
115 enum AccessType {
116 READ,
117 WRITE,
118 };
119 uint32_t index_witness = 0;
120 uint32_t timestamp_witness = 0;
121 uint32_t value_witness = 0;
122 uint32_t index = 0;
123 uint32_t timestamp = 0;
124 AccessType access_type = AccessType::READ; // read or write?
125 uint32_t record_witness = 0;
126 size_t gate_index = 0;
127 bool operator<(const RamRecord& other) const
128 {
129 bool index_test = (index) < (other.index);
130 return index_test || (index == other.index && timestamp < other.timestamp);
131 }
132 bool operator==(const RamRecord& other) const noexcept
133 {
134 return index_witness == other.index_witness && timestamp_witness == other.timestamp_witness &&
135 value_witness == other.value_witness && index == other.index && timestamp == other.timestamp &&
136 access_type == other.access_type && record_witness == other.record_witness &&
137 gate_index == other.gate_index;
138 }
139 };
140
148 // Contains the value of each index of the array
149 std::vector<uint32_t> state;
150
151 // A vector of records, each of which contains:
152 // + The constant witness with the index
153 // + The value in the memory slot
154 // + The actual index value
155 std::vector<RamRecord> records;
156
157 // used for RAM records, to compute the timestamp when performing a read/write
158 size_t access_count = 0;
159 // Used to check that the state hasn't changed in tests
160 bool operator==(const RamTranscript& other) const noexcept
161 {
162 return (state == other.state && records == other.records && access_count == other.access_count);
163 }
164 };
165
173 // Contains the value of each index of the array
174 std::vector<std::array<uint32_t, 2>> state;
175
176 // A vector of records, each of which contains:
177 // + The constant witness with the index
178 // + The value in the memory slot
179 // + The actual index value
180 std::vector<RomRecord> records;
181
182 // Used to check that the state hasn't changed in tests
183 bool operator==(const RomTranscript& other) const noexcept
184 {
185 return (state == other.state && records == other.records);
186 }
187 };
188
195 std::array<uint32_t, 5> a;
196 std::array<uint32_t, 5> b;
197 FF lo_0;
198 FF hi_0;
199 FF hi_1;
200
201 bool operator==(const cached_partial_non_native_field_multiplication& other) const
202 {
203 bool valid = true;
204 for (size_t i = 0; i < 5; ++i) {
205 valid = valid && (a[i] == other.a[i]);
206 valid = valid && (b[i] == other.b[i]);
207 }
208 return valid;
209 }
210
211 static void deduplicate(std::vector<cached_partial_non_native_field_multiplication>& vec)
212 {
213 std::unordered_set<cached_partial_non_native_field_multiplication, Hash, std::equal_to<>> seen;
214
215 std::vector<cached_partial_non_native_field_multiplication> uniqueVec;
216
217 for (const auto& item : vec) {
218 if (seen.insert(item).second) {
219 uniqueVec.push_back(item);
220 }
221 }
222
223 vec.swap(uniqueVec);
224 }
225
226 bool operator<(const cached_partial_non_native_field_multiplication& other) const
227 {
228 if (a < other.a) {
229 return true;
230 }
231 if (other.a < a) {
232 return false;
233 }
234 if (b < other.b) {
235 return true;
236 }
237 return other.b < b;
238 }
239
240 struct Hash {
241 size_t operator()(const cached_partial_non_native_field_multiplication& obj) const
242 {
243 size_t combined_hash = 0;
244
245 // C++ does not have a standard way to hash values, so we use the
246 // common algorithm that boot uses.
247 // You can search for 'cpp hash_combine' to find more information.
248 // Here is one reference:
249 // https://stackoverflow.com/questions/2590677/how-do-i-combine-hash-values-in-c0x
250 auto hash_combiner = [](size_t lhs, size_t rhs) {
251 return lhs ^ (rhs + 0x9e3779b9 + (lhs << 6) + (lhs >> 2));
252 };
253
254 for (const auto& elem : obj.a) {
255 combined_hash = hash_combiner(combined_hash, std::hash<uint32_t>()(elem));
256 }
257 for (const auto& elem : obj.b) {
258 combined_hash = hash_combiner(combined_hash, std::hash<uint32_t>()(elem));
259 }
260
261 return combined_hash;
262 }
263 };
264 };
265
267 uint32_t lo_0_idx;
268 uint32_t lo_1_idx;
269 uint32_t hi_0_idx;
270 uint32_t hi_1_idx;
271 uint32_t hi_2_idx;
272 uint32_t hi_3_idx;
273 };
274
284 using WireVector = std::vector<uint32_t, barretenberg::ContainerSlabAllocator<uint32_t>>;
285 using SelectorVector = std::vector<FF, barretenberg::ContainerSlabAllocator<FF>>;
286
287 std::vector<uint32_t> public_inputs;
288 std::vector<FF> variables;
289 // index of next variable in equivalence class (=REAL_VARIABLE if you're last)
290 std::vector<uint32_t> next_var_index;
291 // index of previous variable in equivalence class (=FIRST if you're in a cycle alone)
292 std::vector<uint32_t> prev_var_index;
293 // indices of corresponding real variables
294 std::vector<uint32_t> real_variable_index;
295 std::vector<uint32_t> real_variable_tags;
296 std::map<FF, uint32_t> constant_variable_indices;
297 WireVector w_l;
298 WireVector w_r;
299 WireVector w_o;
300 WireVector w_4;
301 SelectorVector q_m;
302 SelectorVector q_c;
303 SelectorVector q_1;
304 SelectorVector q_2;
305 SelectorVector q_3;
306 SelectorVector q_4;
307 SelectorVector q_arith;
308 SelectorVector q_sort;
309 SelectorVector q_elliptic;
310 SelectorVector q_aux;
311 SelectorVector q_lookup_type;
312 uint32_t current_tag = DUMMY_TAG;
313 std::map<uint32_t, uint32_t> tau;
314
315 std::vector<RamTranscript> ram_arrays;
316 std::vector<RomTranscript> rom_arrays;
317
318 std::vector<uint32_t> memory_read_records;
319 std::vector<uint32_t> memory_write_records;
320 std::map<uint64_t, RangeList> range_lists;
321
322 std::vector<UltraCircuitBuilder_::cached_partial_non_native_field_multiplication>
323 cached_partial_non_native_field_multiplications;
324
325 size_t num_gates;
326 bool circuit_finalized = false;
336 template <typename CircuitBuilder> static CircuitDataBackup store_full_state(const CircuitBuilder& builder)
337 {
338 CircuitDataBackup stored_state;
339 stored_state.public_inputs = builder.public_inputs;
340 stored_state.variables = builder.variables;
341
342 stored_state.next_var_index = builder.next_var_index;
343
344 stored_state.prev_var_index = builder.prev_var_index;
345
346 stored_state.real_variable_index = builder.real_variable_index;
347 stored_state.real_variable_tags = builder.real_variable_tags;
348 stored_state.constant_variable_indices = builder.constant_variable_indices;
349 stored_state.w_l = builder.w_l();
350 stored_state.w_r = builder.w_r();
351 stored_state.w_o = builder.w_o();
352 stored_state.w_4 = builder.w_4();
353 stored_state.q_m = builder.q_m();
354 stored_state.q_c = builder.q_c();
355 stored_state.q_1 = builder.q_1();
356 stored_state.q_2 = builder.q_2();
357 stored_state.q_3 = builder.q_3();
358 stored_state.q_4 = builder.q_4();
359 stored_state.q_arith = builder.q_arith();
360 stored_state.q_sort = builder.q_sort();
361 stored_state.q_elliptic = builder.q_elliptic();
362 stored_state.q_aux = builder.q_aux();
363 stored_state.q_lookup_type = builder.q_lookup_type();
364 stored_state.current_tag = builder.current_tag;
365 stored_state.tau = builder.tau;
366
367 stored_state.ram_arrays = builder.ram_arrays;
368 stored_state.rom_arrays = builder.rom_arrays;
369
370 stored_state.memory_read_records = builder.memory_read_records;
371 stored_state.memory_write_records = builder.memory_write_records;
372 stored_state.range_lists = builder.range_lists;
373 stored_state.circuit_finalized = builder.circuit_finalized;
374 stored_state.num_gates = builder.num_gates;
375 stored_state.cached_partial_non_native_field_multiplications =
376 builder.cached_partial_non_native_field_multiplications;
377 return stored_state;
378 }
379
387 template <typename CircuitBuilder>
388 static CircuitDataBackup store_prefinilized_state(const CircuitBuilder* builder)
389 {
390 CircuitDataBackup stored_state;
391 stored_state.public_inputs = builder->public_inputs;
392 stored_state.variables = builder->variables;
393
394 stored_state.next_var_index = builder->next_var_index;
395
396 stored_state.prev_var_index = builder->prev_var_index;
397
398 stored_state.real_variable_index = builder->real_variable_index;
399 stored_state.real_variable_tags = builder->real_variable_tags;
400 stored_state.constant_variable_indices = builder->constant_variable_indices;
401 stored_state.current_tag = builder->current_tag;
402 stored_state.tau = builder->tau;
403
404 stored_state.ram_arrays = builder->ram_arrays;
405 stored_state.rom_arrays = builder->rom_arrays;
406
407 stored_state.memory_read_records = builder->memory_read_records;
408 stored_state.memory_write_records = builder->memory_write_records;
409 stored_state.range_lists = builder->range_lists;
410 stored_state.circuit_finalized = builder->circuit_finalized;
411 stored_state.num_gates = builder->num_gates;
412 stored_state.cached_partial_non_native_field_multiplications =
413 builder->cached_partial_non_native_field_multiplications;
414
415 return stored_state;
416 }
417
424 template <typename CircuitBuilder> void restore_prefinilized_state(CircuitBuilder* builder)
425 {
426 builder->public_inputs = public_inputs;
427 builder->variables = variables;
428
429 builder->next_var_index = next_var_index;
430
431 builder->prev_var_index = prev_var_index;
432
433 builder->real_variable_index = real_variable_index;
434 builder->real_variable_tags = real_variable_tags;
435 builder->constant_variable_indices = constant_variable_indices;
436 builder->current_tag = current_tag;
437 builder->tau = tau;
438
439 builder->ram_arrays = ram_arrays;
440 builder->rom_arrays = rom_arrays;
441
442 builder->memory_read_records = memory_read_records;
443 builder->memory_write_records = memory_write_records;
444 builder->range_lists = range_lists;
445 builder->circuit_finalized = circuit_finalized;
446 builder->num_gates = num_gates;
447 builder->cached_partial_non_native_field_multiplications = cached_partial_non_native_field_multiplications;
448 builder->w_l().resize(num_gates);
449 builder->w_r().resize(num_gates);
450 builder->w_o().resize(num_gates);
451 builder->w_4().resize(num_gates);
452 builder->q_m().resize(num_gates);
453 builder->q_c().resize(num_gates);
454 builder->q_1().resize(num_gates);
455 builder->q_2().resize(num_gates);
456 builder->q_3().resize(num_gates);
457 builder->q_4().resize(num_gates);
458 builder->q_arith().resize(num_gates);
459 builder->q_sort().resize(num_gates);
460 builder->q_elliptic().resize(num_gates);
461 builder->q_aux().resize(num_gates);
462 builder->q_lookup_type().resize(num_gates);
463 }
471 template <typename CircuitBuilder> bool is_same_state(const CircuitBuilder& builder)
472 {
473 if (!(public_inputs == builder.public_inputs)) {
474 return false;
475 }
476 if (!(variables == builder.variables)) {
477 return false;
478 }
479 if (!(next_var_index == builder.next_var_index)) {
480 return false;
481 }
482 if (!(prev_var_index == builder.prev_var_index)) {
483 return false;
484 }
485 if (!(real_variable_index == builder.real_variable_index)) {
486 return false;
487 }
488 if (!(real_variable_tags == builder.real_variable_tags)) {
489 return false;
490 }
491 if (!(constant_variable_indices == builder.constant_variable_indices)) {
492 return false;
493 }
494 if (!(w_l == builder.w_l())) {
495 return false;
496 }
497 if (!(w_r == builder.w_r())) {
498 return false;
499 }
500 if (!(w_o == builder.w_o())) {
501 return false;
502 }
503 if (!(w_4 == builder.w_4())) {
504 return false;
505 }
506 if (!(q_m == builder.q_m())) {
507 return false;
508 }
509 if (!(q_c == builder.q_c())) {
510 return false;
511 }
512 if (!(q_1 == builder.q_1())) {
513 return false;
514 }
515 if (!(q_2 == builder.q_2())) {
516 return false;
517 }
518 if (!(q_3 == builder.q_3())) {
519 return false;
520 }
521 if (!(q_4 == builder.q_4())) {
522 return false;
523 }
524 if (!(q_arith == builder.q_arith())) {
525 return false;
526 }
527 if (!(q_sort == builder.q_sort())) {
528 return false;
529 }
530 if (!(q_elliptic == builder.q_elliptic())) {
531 return false;
532 }
533 if (!(q_aux == builder.q_aux())) {
534 return false;
535 }
536 if (!(q_lookup_type == builder.q_lookup_type())) {
537 return false;
538 }
539 if (!(current_tag == builder.current_tag)) {
540 return false;
541 }
542 if (!(tau == builder.tau)) {
543 return false;
544 }
545 if (!(ram_arrays == builder.ram_arrays)) {
546 return false;
547 }
548 if (!(rom_arrays == builder.rom_arrays)) {
549 return false;
550 }
551 if (!(memory_read_records == builder.memory_read_records)) {
552 return false;
553 }
554 if (!(memory_write_records == builder.memory_write_records)) {
555 return false;
556 }
557 if (!(range_lists == builder.range_lists)) {
558 return false;
559 }
560 if (!(cached_partial_non_native_field_multiplications ==
561 builder.cached_partial_non_native_field_multiplications)) {
562 return false;
563 }
564 if (!(num_gates == builder.num_gates)) {
565 return false;
566 }
567 if (!(circuit_finalized == builder.circuit_finalized)) {
568 return false;
569 }
570 return true;
571 }
572 };
573
574 std::array<std::vector<uint32_t, barretenberg::ContainerSlabAllocator<uint32_t>>, NUM_WIRES> wires;
575 Arithmetization selectors;
576
577 using WireVector = std::vector<uint32_t, ContainerSlabAllocator<uint32_t>>;
578 using SelectorVector = std::vector<FF, ContainerSlabAllocator<FF>>;
579
580 WireVector& w_l() { return std::get<0>(wires); };
581 WireVector& w_r() { return std::get<1>(wires); };
582 WireVector& w_o() { return std::get<2>(wires); };
583 WireVector& w_4() { return std::get<3>(wires); };
584
585 const WireVector& w_l() const { return std::get<0>(wires); };
586 const WireVector& w_r() const { return std::get<1>(wires); };
587 const WireVector& w_o() const { return std::get<2>(wires); };
588 const WireVector& w_4() const { return std::get<3>(wires); };
589
590 SelectorVector& q_m() { return selectors.q_m(); };
591 SelectorVector& q_c() { return selectors.q_c(); };
592 SelectorVector& q_1() { return selectors.q_1(); };
593 SelectorVector& q_2() { return selectors.q_2(); };
594 SelectorVector& q_3() { return selectors.q_3(); };
595 SelectorVector& q_4() { return selectors.q_4(); };
596 SelectorVector& q_arith() { return selectors.q_arith(); };
597 SelectorVector& q_sort() { return selectors.q_sort(); };
598 SelectorVector& q_elliptic() { return selectors.q_elliptic(); };
599 SelectorVector& q_aux() { return selectors.q_aux(); };
600 SelectorVector& q_lookup_type() { return selectors.q_lookup_type(); };
601
602 const SelectorVector& q_c() const { return selectors.q_c(); };
603 const SelectorVector& q_1() const { return selectors.q_1(); };
604 const SelectorVector& q_2() const { return selectors.q_2(); };
605 const SelectorVector& q_3() const { return selectors.q_3(); };
606 const SelectorVector& q_4() const { return selectors.q_4(); };
607 const SelectorVector& q_arith() const { return selectors.q_arith(); };
608 const SelectorVector& q_sort() const { return selectors.q_sort(); };
609 const SelectorVector& q_elliptic() const { return selectors.q_elliptic(); };
610 const SelectorVector& q_aux() const { return selectors.q_aux(); };
611 const SelectorVector& q_lookup_type() const { return selectors.q_lookup_type(); };
612 const SelectorVector& q_m() const { return selectors.q_m(); };
613
614 // These are variables that we have used a gate on, to enforce that they are
615 // equal to a defined value.
616 // TODO(#216)(Adrian): Why is this not in CircuitBuilderBase
617 std::map<FF, uint32_t> constant_variable_indices;
618
619 std::vector<plookup::BasicTable> lookup_tables;
620 std::vector<plookup::MultiTable> lookup_multi_tables;
621 std::map<uint64_t, RangeList> range_lists; // DOCTODO: explain this.
622
630 std::vector<RamTranscript> ram_arrays;
631
638 std::vector<RomTranscript> rom_arrays;
639
640 // Stores gate index of ROM and RAM reads (required by proving key)
641 std::vector<uint32_t> memory_read_records;
642 // Stores gate index of RAM writes (required by proving key)
643 std::vector<uint32_t> memory_write_records;
644
645 std::vector<cached_partial_non_native_field_multiplication> cached_partial_non_native_field_multiplications;
646
647 bool circuit_finalized = false;
648
650 UltraCircuitBuilder_(const size_t size_hint = 0)
651 : CircuitBuilderBase<FF>(size_hint)
652 {
653 selectors.reserve(size_hint);
654 w_l().reserve(size_hint);
655 w_r().reserve(size_hint);
656 w_o().reserve(size_hint);
657 w_4().reserve(size_hint);
658 this->zero_idx = put_constant_variable(FF::zero());
659 this->tau.insert({ DUMMY_TAG, DUMMY_TAG }); // TODO(luke): explain this
660 num_vars_added_in_constructor = this->variables.size();
661 };
662 UltraCircuitBuilder_(const UltraCircuitBuilder_& other) = default;
663 UltraCircuitBuilder_(UltraCircuitBuilder_&& other)
664 : CircuitBuilderBase<FF>(std::move(other))
665 {
666 wires = other.wires;
667 selectors = other.selectors;
668 constant_variable_indices = other.constant_variable_indices;
669
670 lookup_tables = other.lookup_tables;
671 lookup_multi_tables = other.lookup_multi_tables;
672 range_lists = other.range_lists;
673 ram_arrays = other.ram_arrays;
674 rom_arrays = other.rom_arrays;
675 memory_read_records = other.memory_read_records;
676 memory_write_records = other.memory_write_records;
677 cached_partial_non_native_field_multiplications = other.cached_partial_non_native_field_multiplications;
678 circuit_finalized = other.circuit_finalized;
679 };
680 UltraCircuitBuilder_& operator=(const UltraCircuitBuilder_& other) = default;
681 UltraCircuitBuilder_& operator=(UltraCircuitBuilder_&& other)
682 {
683 CircuitBuilderBase<FF>::operator=(std::move(other));
684 wires = other.wires;
685 selectors = other.selectors;
686 constant_variable_indices = other.constant_variable_indices;
687
688 lookup_tables = other.lookup_tables;
689 lookup_multi_tables = other.lookup_multi_tables;
690 range_lists = other.range_lists;
691 ram_arrays = other.ram_arrays;
692 rom_arrays = other.rom_arrays;
693 memory_read_records = other.memory_read_records;
694 memory_write_records = other.memory_write_records;
695 cached_partial_non_native_field_multiplications = other.cached_partial_non_native_field_multiplications;
696 circuit_finalized = other.circuit_finalized;
697 return *this;
698 };
699 ~UltraCircuitBuilder_() override = default;
700
709 {
710#if NDEBUG
711 // do nothing
712#else
713 size_t nominal_size = selectors.get()[0].size();
714 for (size_t idx = 1; idx < selectors.get().size(); ++idx) {
715 ASSERT(selectors.get()[idx].size() == nominal_size);
716 }
717#endif // NDEBUG
718 }
719
720 void finalize_circuit();
721
723
724 void create_add_gate(const add_triple_<FF>& in) override;
725
726 void create_big_add_gate(const add_quad_<FF>& in, const bool use_next_gate_w_4 = false);
728 void create_big_mul_gate(const mul_quad_<FF>& in);
729 void create_balanced_add_gate(const add_quad_<FF>& in);
730
731 void create_mul_gate(const mul_triple_<FF>& in) override;
732 void create_bool_gate(const uint32_t a) override;
733 void create_poly_gate(const poly_triple_<FF>& in) override;
736
737 void fix_witness(const uint32_t witness_index, const FF& witness_value);
738
739 void create_new_range_constraint(const uint32_t variable_index,
740 const uint64_t target_range,
741 std::string const msg = "create_new_range_constraint");
742 void create_range_constraint(const uint32_t variable_index, const size_t num_bits, std::string const& msg)
743 {
744 if (num_bits <= DEFAULT_PLOOKUP_RANGE_BITNUM) {
760 .a = variable_index,
761 .b = variable_index,
762 .c = variable_index,
763 .q_m = 0,
764 .q_l = 1,
765 .q_r = -1,
766 .q_o = 0,
767 .q_c = 0,
768 });
769 create_new_range_constraint(variable_index, 1ULL << num_bits, msg);
770 } else {
771 decompose_into_default_range(variable_index, num_bits, DEFAULT_PLOOKUP_RANGE_BITNUM, msg);
772 }
773 }
774
775 accumulator_triple_<FF> create_logic_constraint(const uint32_t a,
776 const uint32_t b,
777 const size_t num_bits,
778 bool is_xor_gate);
779 accumulator_triple_<FF> create_and_constraint(const uint32_t a, const uint32_t b, const size_t num_bits);
780 accumulator_triple_<FF> create_xor_constraint(const uint32_t a, const uint32_t b, const size_t num_bits);
781
782 uint32_t put_constant_variable(const FF& variable);
783
784 public:
785 size_t get_num_constant_gates() const override { return 0; }
802 size_t& count, size_t& rangecount, size_t& romcount, size_t& ramcount, size_t& nnfcount) const
803 {
804 count = this->num_gates;
805 // each ROM gate adds +1 extra gate due to the rom reads being copied to a sorted list set
806 for (size_t i = 0; i < rom_arrays.size(); ++i) {
807 for (size_t j = 0; j < rom_arrays[i].state.size(); ++j) {
808 if (rom_arrays[i].state[j][0] == UNINITIALIZED_MEMORY_RECORD) {
809 romcount += 2;
810 }
811 }
812 romcount += (rom_arrays[i].records.size());
813 romcount += 1; // we add an addition gate after procesing a rom array
814 }
815
816 // each RAM gate adds +2 extra gates due to the ram reads being copied to a sorted list set,
817 // as well as an extra gate to validate timestamps
818 std::vector<size_t> ram_timestamps;
819 std::vector<size_t> ram_range_sizes;
820 std::vector<size_t> ram_range_exists;
821 for (size_t i = 0; i < ram_arrays.size(); ++i) {
822 for (size_t j = 0; j < ram_arrays[i].state.size(); ++j) {
823 if (ram_arrays[i].state[j] == UNINITIALIZED_MEMORY_RECORD) {
824 ramcount += NUMBER_OF_GATES_PER_RAM_ACCESS;
825 }
826 }
827 ramcount += (ram_arrays[i].records.size() * NUMBER_OF_GATES_PER_RAM_ACCESS);
828 ramcount += NUMBER_OF_ARITHMETIC_GATES_PER_RAM_ARRAY; // we add an addition gate after procesing a ram array
829
830 // there will be 'max_timestamp' number of range checks, need to calculate.
831 const auto max_timestamp = ram_arrays[i].access_count - 1;
832
833 // if a range check of length `max_timestamp` already exists, we are double counting.
834 // We record `ram_timestamps` to detect and correct for this error when we process range lists.
835 ram_timestamps.push_back(max_timestamp);
836 size_t padding = (NUM_WIRES - (max_timestamp % NUM_WIRES)) % NUM_WIRES;
837 if (max_timestamp == NUM_WIRES)
838 padding += NUM_WIRES;
839 const size_t ram_range_check_list_size = max_timestamp + padding;
840
841 size_t ram_range_check_gate_count = (ram_range_check_list_size / NUM_WIRES);
842 ram_range_check_gate_count += 1; // we need to add 1 extra addition gates for every distinct range list
843
844 ram_range_sizes.push_back(ram_range_check_gate_count);
845 ram_range_exists.push_back(false);
846 }
847 for (const auto& list : range_lists) {
848 auto list_size = list.second.variable_indices.size();
849 size_t padding = (NUM_WIRES - (list.second.variable_indices.size() % NUM_WIRES)) % NUM_WIRES;
850 if (list.second.variable_indices.size() == NUM_WIRES)
851 padding += NUM_WIRES;
852 list_size += padding;
853
854 for (size_t i = 0; i < ram_timestamps.size(); ++i) {
855 if (list.second.target_range == ram_timestamps[i]) {
856 ram_range_exists[i] = true;
857 }
858 }
859 rangecount += (list_size / NUM_WIRES);
860 rangecount += 1; // we need to add 1 extra addition gates for every distinct range list
861 }
862 // update rangecount to include the ram range checks the composer will eventually be creating
863 for (size_t i = 0; i < ram_range_sizes.size(); ++i) {
864 if (!ram_range_exists[i]) {
865 rangecount += ram_range_sizes[i];
866 }
867 }
868 std::vector<cached_partial_non_native_field_multiplication> nnf_copy(
869 cached_partial_non_native_field_multiplications);
870 // update nnfcount
871 std::sort(nnf_copy.begin(), nnf_copy.end());
872
873 auto last = std::unique(nnf_copy.begin(), nnf_copy.end());
874 const size_t num_nnf_ops = static_cast<size_t>(std::distance(nnf_copy.begin(), last));
875 nnfcount = num_nnf_ops * GATES_PER_NON_NATIVE_FIELD_MULTIPLICATION_ARITHMETIC;
876 }
877
888 size_t get_num_gates() const override
889 {
890 // if circuit finalized already added extra gates
891 if (circuit_finalized) {
892 return this->num_gates;
893 }
894 size_t count = 0;
895 size_t rangecount = 0;
896 size_t romcount = 0;
897 size_t ramcount = 0;
898 size_t nnfcount = 0;
899 get_num_gates_split_into_components(count, rangecount, romcount, ramcount, nnfcount);
900 return count + romcount + ramcount + rangecount + nnfcount;
901 }
902
913 {
914 size_t tables_size = 0;
915 size_t lookups_size = 0;
916 for (const auto& table : lookup_tables) {
917 tables_size += table.size;
918 lookups_size += table.lookup_gates.size();
919 }
920
921 auto minimum_circuit_size = tables_size + lookups_size;
922 auto num_filled_gates = get_num_gates() + this->public_inputs.size();
923 return std::max(minimum_circuit_size, num_filled_gates) + NUM_RESERVED_GATES;
924 }
925
930 virtual void print_num_gates() const override
931 {
932 size_t count = 0;
933 size_t rangecount = 0;
934 size_t romcount = 0;
935 size_t ramcount = 0;
936 size_t nnfcount = 0;
937 get_num_gates_split_into_components(count, rangecount, romcount, ramcount, nnfcount);
938
939 size_t total = count + romcount + ramcount + rangecount;
940 std::cout << "gates = " << total << " (arith " << count << ", rom " << romcount << ", ram " << ramcount
941 << ", range " << rangecount << ", non native field gates " << nnfcount
942 << "), pubinp = " << this->public_inputs.size() << std::endl;
943 }
944
945 void assert_equal_constant(const uint32_t a_idx, const FF& b, std::string const& msg = "assert equal constant")
946 {
947 if (this->variables[a_idx] != b && !this->failed()) {
948 this->failure(msg);
949 }
950 auto b_idx = put_constant_variable(b);
951 this->assert_equal(a_idx, b_idx, msg);
952 }
953
958 void initialize_precomputed_table(const plookup::BasicTableId id,
959 bool (*generator)(std::vector<FF>&, std::vector<FF>&, std::vector<FF>&),
960 std::array<FF, 2> (*get_values_from_key)(const std::array<uint64_t, 2>));
961
962 plookup::BasicTable& get_table(const plookup::BasicTableId id);
963 plookup::MultiTable& create_table(const plookup::MultiTableId id);
964
966 const plookup::MultiTableId& id,
967 const plookup::ReadData<FF>& read_values,
968 const uint32_t key_a_index,
969 std::optional<uint32_t> key_b_index = std::nullopt);
970
974 std::vector<uint32_t> decompose_into_default_range(
975 const uint32_t variable_index,
976 const uint64_t num_bits,
977 const uint64_t target_range_bitnum = DEFAULT_PLOOKUP_RANGE_BITNUM,
978 std::string const& msg = "decompose_into_default_range");
979 std::vector<uint32_t> decompose_into_default_range_better_for_oddlimbnum(
980 const uint32_t variable_index,
981 const size_t num_bits,
982 std::string const& msg = "decompose_into_default_range_better_for_oddlimbnum");
983 void create_dummy_constraints(const std::vector<uint32_t>& variable_index);
984 void create_sort_constraint(const std::vector<uint32_t>& variable_index);
985 void create_sort_constraint_with_edges(const std::vector<uint32_t>& variable_index, const FF&, const FF&);
986 void assign_tag(const uint32_t variable_index, const uint32_t tag)
987 {
988 ASSERT(tag <= this->current_tag);
989 // If we've already assigned this tag to this variable, return (can happen due to copy constraints)
990 if (this->real_variable_tags[this->real_variable_index[variable_index]] == tag) {
991 return;
992 }
993 ASSERT(this->real_variable_tags[this->real_variable_index[variable_index]] == DUMMY_TAG);
994 this->real_variable_tags[this->real_variable_index[variable_index]] = tag;
995 }
996
997 uint32_t create_tag(const uint32_t tag_index, const uint32_t tau_index)
998 {
999 this->tau.insert({ tag_index, tau_index });
1000 this->current_tag++; // Why exactly?
1001 return this->current_tag;
1002 }
1003
1004 uint32_t get_new_tag()
1005 {
1006 this->current_tag++;
1007 return this->current_tag;
1008 }
1009
1010 RangeList create_range_list(const uint64_t target_range);
1011 void process_range_list(RangeList& list);
1012 void process_range_lists();
1013
1017 void apply_aux_selectors(const AUX_SELECTORS type);
1018
1022 void range_constrain_two_limbs(const uint32_t lo_idx,
1023 const uint32_t hi_idx,
1024 const size_t lo_limb_bits = DEFAULT_NON_NATIVE_FIELD_LIMB_BITS,
1025 const size_t hi_limb_bits = DEFAULT_NON_NATIVE_FIELD_LIMB_BITS);
1026 std::array<uint32_t, 2> decompose_non_native_field_double_width_limb(
1027 const uint32_t limb_idx, const size_t num_limb_bits = (2 * DEFAULT_NON_NATIVE_FIELD_LIMB_BITS));
1028 std::array<uint32_t, 2> evaluate_non_native_field_multiplication(
1029 const non_native_field_witnesses<FF>& input, const bool range_constrain_quotient_and_remainder = true);
1030 std::array<uint32_t, 2> queue_partial_non_native_field_multiplication(const non_native_field_witnesses<FF>& input);
1031 typedef std::pair<uint32_t, FF> scaled_witness;
1032 typedef std::tuple<scaled_witness, scaled_witness, FF> add_simple;
1033 std::array<uint32_t, 5> evaluate_non_native_field_subtraction(add_simple limb0,
1034 add_simple limb1,
1035 add_simple limb2,
1036 add_simple limb3,
1037 std::tuple<uint32_t, uint32_t, FF> limbp);
1038 std::array<uint32_t, 5> evaluate_non_native_field_addition(add_simple limb0,
1039 add_simple limb1,
1040 add_simple limb2,
1041 add_simple limb3,
1042 std::tuple<uint32_t, uint32_t, FF> limbp);
1043
1048 // size_t create_RAM_array(const size_t array_size);
1049 size_t create_ROM_array(const size_t array_size);
1050
1051 void set_ROM_element(const size_t rom_id, const size_t index_value, const uint32_t value_witness);
1052 void set_ROM_element_pair(const size_t rom_id,
1053 const size_t index_value,
1054 const std::array<uint32_t, 2>& value_witnesses);
1055 uint32_t read_ROM_array(const size_t rom_id, const uint32_t index_witness);
1056 std::array<uint32_t, 2> read_ROM_array_pair(const size_t rom_id, const uint32_t index_witness);
1057 void create_ROM_gate(RomRecord& record);
1058 void create_sorted_ROM_gate(RomRecord& record);
1059 void process_ROM_array(const size_t rom_id);
1060 void process_ROM_arrays();
1061
1062 void create_RAM_gate(RamRecord& record);
1063 void create_sorted_RAM_gate(RamRecord& record);
1064 void create_final_sorted_RAM_gate(RamRecord& record, const size_t ram_array_size);
1065
1066 size_t create_RAM_array(const size_t array_size);
1067 void init_RAM_element(const size_t ram_id, const size_t index_value, const uint32_t value_witness);
1068 uint32_t read_RAM_array(const size_t ram_id, const uint32_t index_witness);
1069 void write_RAM_array(const size_t ram_id, const uint32_t index_witness, const uint32_t value_witness);
1070 void process_RAM_array(const size_t ram_id);
1071 void process_RAM_arrays();
1072
1073 // Circuit evaluation methods
1074
1075 FF compute_arithmetic_identity(FF q_arith_value,
1076 FF q_1_value,
1077 FF q_2_value,
1078 FF q_3_value,
1079 FF q_4_value,
1080 FF q_m_value,
1081 FF q_c_value,
1082 FF w_1_value,
1083 FF w_2_value,
1084 FF w_3_value,
1085 FF w_4_value,
1086 FF w_1_shifted_value,
1087 FF w_4_shifted_value,
1088 const FF alpha_base,
1089 const FF alpha) const;
1090 FF compute_auxilary_identity(FF q_aux_value,
1091 FF q_arith_value,
1092 FF q_1_value,
1093 FF q_2_value,
1094 FF q_3_value,
1095 FF q_4_value,
1096 FF q_m_value,
1097 FF q_c_value,
1098 FF w_1_value,
1099 FF w_2_value,
1100 FF w_3_value,
1101 FF w_4_value,
1102 FF w_1_shifted_value,
1103 FF w_2_shifted_value,
1104 FF w_3_shifted_value,
1105 FF w_4_shifted_value,
1106 FF alpha_base,
1107 FF alpha,
1108 FF eta) const;
1109 FF compute_elliptic_identity(FF q_elliptic_value,
1110 FF q_1_value,
1111 FF q_m_value,
1112 FF w_2_value,
1113 FF w_3_value,
1114 FF w_1_shifted_value,
1115 FF w_2_shifted_value,
1116 FF w_3_shifted_value,
1117 FF w_4_shifted_value,
1118 FF alpha_base,
1119 FF alpha) const;
1120 FF compute_genperm_sort_identity(FF q_sort_value,
1121 FF w_1_value,
1122 FF w_2_value,
1123 FF w_3_value,
1124 FF w_4_value,
1125 FF w_1_shifted_value,
1126 FF alpha_base,
1127 FF alpha) const;
1128
1129 bool check_circuit();
1130};
1131extern template class UltraCircuitBuilder_<arithmetization::Ultra<barretenberg::fr>>;
1132extern template class UltraCircuitBuilder_<arithmetization::UltraHonk<barretenberg::fr>>;
1133using UltraCircuitBuilder = UltraCircuitBuilder_<arithmetization::Ultra<barretenberg::fr>>;
1134} // namespace proof_system
Container type for lookup table reads.
Definition: types.hpp:316
Definition: circuit_builder_base.hpp:14
virtual void assert_equal(const uint32_t a_idx, const uint32_t b_idx, std::string const &msg="assert_equal")
Definition: circuit_builder_base.cpp:15
Definition: ultra_circuit_builder.hpp:31
std::vector< RamTranscript > ram_arrays
Each entry in ram_arrays represents an independent RAM table. RamTranscript tracks the current table ...
Definition: ultra_circuit_builder.hpp:630
virtual void print_num_gates() const override
Print the number and composition of gates in the circuit.
Definition: ultra_circuit_builder.hpp:930
void create_ROM_gate(RomRecord &record)
Gate that'reads' from a ROM table. i.e. table index is a witness not precomputed.
Definition: ultra_circuit_builder.cpp:2043
void process_ROM_array(const size_t rom_id)
Compute additional gates required to validate ROM reads. Called when generating the proving key.
Definition: ultra_circuit_builder.cpp:2436
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.
Definition: ultra_circuit_builder.cpp:809
std::array< uint32_t, 2 > evaluate_non_native_field_multiplication(const non_native_field_witnesses< FF > &input, const bool range_constrain_quotient_and_remainder=true)
Queue up non-native field multiplication data.
Definition: ultra_circuit_builder.cpp:1529
RangeList create_range_list(const uint64_t target_range)
Definition: ultra_circuit_builder.cpp:662
void add_table_column_selector_poly_to_proving_key(barretenberg::polynomial &small, const std::string &tag)
FF compute_auxilary_identity(FF q_aux_value, FF q_arith_value, FF q_1_value, FF q_2_value, FF q_3_value, FF q_4_value, FF q_m_value, FF q_c_value, FF w_1_value, FF w_2_value, FF w_3_value, FF w_4_value, FF w_1_shifted_value, FF w_2_shifted_value, FF w_3_shifted_value, FF w_4_shifted_value, FF alpha_base, FF alpha, FF eta) const
Plookup Auxiliary Gate Identity.
Definition: ultra_circuit_builder.cpp:2953
FF compute_genperm_sort_identity(FF q_sort_value, FF w_1_value, FF w_2_value, FF w_3_value, FF w_4_value, FF w_1_shifted_value, FF alpha_base, FF alpha) const
General permutation sorting identity.
Definition: ultra_circuit_builder.cpp:2809
void finalize_circuit()
Definition: ultra_circuit_builder.cpp:17
FF compute_elliptic_identity(FF q_elliptic_value, FF q_1_value, FF q_m_value, FF w_2_value, FF w_3_value, FF w_1_shifted_value, FF w_2_shifted_value, FF w_3_shifted_value, FF w_4_shifted_value, FF alpha_base, FF alpha) const
Elliptic curve identity gate methods implement elliptic curve point addition.
Definition: ultra_circuit_builder.cpp:2869
void create_big_add_gate_with_bit_extraction(const add_quad_< FF > &in)
A legacy method that was used to extract a bit from c-4d by using gate selectors in the Turboplonk,...
Definition: ultra_circuit_builder.cpp:188
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)
Definition: ultra_circuit_builder.cpp:1789
void check_selector_length_consistency()
Debug helper method for ensuring all selectors have the same size.
Definition: ultra_circuit_builder.hpp:708
std::vector< RomTranscript > rom_arrays
Each entry in ram_arrays represents an independent ROM table. RomTranscript tracks the current table ...
Definition: ultra_circuit_builder.hpp:638
void create_big_mul_gate(const mul_quad_< FF > &in)
Create a basic multiplication gate q_m * a * b + q_1 * a + q_2 * b + q_3 * c + q_4 * d + q_c = 0 (q_a...
Definition: ultra_circuit_builder.cpp:252
void create_sorted_ROM_gate(RomRecord &record)
Gate that performs consistency checks to validate that a claimed ROM read value is correct.
Definition: ultra_circuit_builder.cpp:2064
std::array< uint32_t, 2 > decompose_non_native_field_double_width_limb(const uint32_t limb_idx, const size_t num_limb_bits=(2 *DEFAULT_NON_NATIVE_FIELD_LIMB_BITS))
Decompose a single witness into two, where the lowest is DEFAULT_NON_NATIVE_FIELD_LIMB_BITS (68) rang...
Definition: ultra_circuit_builder.cpp:1490
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.
Definition: ultra_circuit_builder.cpp:2400
void create_range_constraint(const uint32_t variable_index, const size_t num_bits, std::string const &msg)
Definition: ultra_circuit_builder.hpp:742
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....
Definition: ultra_circuit_builder.cpp:157
void create_final_sorted_RAM_gate(RamRecord &record, const size_t ram_array_size)
Performs consistency checks to validate that a claimed RAM read/write value is correct....
Definition: ultra_circuit_builder.cpp:2150
void create_ecc_dbl_gate(const ecc_dbl_gate_< FF > &in)
Create an elliptic curve doubling gate.
Definition: ultra_circuit_builder.cpp:488
void process_RAM_array(const size_t ram_id)
Compute additional gates required to validate RAM read/writes. Called when generating the proving key...
Definition: ultra_circuit_builder.cpp:2522
void create_poly_gate(const poly_triple_< FF > &in) override
A plonk gate with disabled (set to zero) fourth wire. q_m * a * b + q_1 * a + q_2 * b + q_3.
Definition: ultra_circuit_builder.cpp:383
void fix_witness(const uint32_t witness_index, const FF &witness_value)
Add a gate equating a particular witness to a constant, fixing it the value.
Definition: ultra_circuit_builder.cpp:556
size_t get_num_gates() const override
Get the final number of gates in a circuit, which consists of the sum of: 1) Current number number of...
Definition: ultra_circuit_builder.hpp:888
void create_add_gate(const add_triple_< FF > &in) override
Create an addition gate, where in.a * in.a_scaling + in.b * in.b_scaling + in.c * in....
Definition: ultra_circuit_builder.cpp:124
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...
Definition: ultra_circuit_builder.cpp:62
size_t get_total_circuit_size() const
Get the size of the circuit if it was finalized now.
Definition: ultra_circuit_builder.hpp:912
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.
Definition: ultra_circuit_builder.cpp:2336
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")
Definition: ultra_circuit_builder.cpp:696
void apply_aux_selectors(const AUX_SELECTORS type)
Enable the auxilary gate of particular type.
Definition: ultra_circuit_builder.cpp:1214
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)
Definition: ultra_circuit_builder.cpp:1914
size_t create_RAM_array(const size_t array_size)
Create a new updatable memory region.
Definition: ultra_circuit_builder.cpp:2179
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)
Definition: ultra_circuit_builder.cpp:1399
void create_bool_gate(const uint32_t a) override
Generate an arithmetic gate equivalent to x^2 - x = 0, which forces x to be 0 or 1.
Definition: ultra_circuit_builder.cpp:351
void create_ecc_add_gate(const ecc_add_gate_< FF > &in)
Create an elliptic curve addition gate.
Definition: ultra_circuit_builder.cpp:417
void create_sorted_RAM_gate(RamRecord &record)
Gate that performs consistency checks to validate that a claimed RAM read/write value is correct.
Definition: ultra_circuit_builder.cpp:2131
void get_num_gates_split_into_components(size_t &count, size_t &rangecount, size_t &romcount, size_t &ramcount, size_t &nnfcount) const
Get the final number of gates in a circuit, which consists of the sum of: 1) Current number number of...
Definition: ultra_circuit_builder.hpp:801
size_t create_ROM_array(const size_t array_size)
Create a new read-only memory region.
Definition: ultra_circuit_builder.cpp:2088
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)
Perform a series of lookups, one for each 'row' in read_values.
Definition: ultra_circuit_builder.cpp:611
void create_RAM_gate(RamRecord &record)
Gate that performs a read/write operation into a RAM table. i.e. table index is a witness not precomp...
Definition: ultra_circuit_builder.cpp:2105
void create_mul_gate(const mul_triple_< FF > &in) override
Create a multiplication gate with q_m * a * b + q_3 * c + q_const = 0.
Definition: ultra_circuit_builder.cpp:322
std::array< uint32_t, 2 > queue_partial_non_native_field_multiplication(const non_native_field_witnesses< FF > &input)
Definition: ultra_circuit_builder.cpp:1742
FF compute_arithmetic_identity(FF q_arith_value, FF q_1_value, FF q_2_value, FF q_3_value, FF q_4_value, FF q_m_value, FF q_c_value, FF w_1_value, FF w_2_value, FF w_3_value, FF w_4_value, FF w_1_shifted_value, FF w_4_shifted_value, const FF alpha_base, const FF alpha) const
Arithmetic gate-related methods.
Definition: ultra_circuit_builder.cpp:2743
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
Definition: ultra_circuit_builder.cpp:2293
void process_non_native_field_multiplications()
Called in compute_proving_key when finalizing circuit. Iterates over the cached_non_native_field_mult...
Definition: ultra_circuit_builder.cpp:1692
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
Definition: ultra_circuit_builder.cpp:2197
uint32_t read_ROM_array(const size_t rom_id, const uint32_t index_witness)
Read a single element from ROM.
Definition: ultra_circuit_builder.cpp:2367
bool check_circuit()
Check that the circuit is correct in its current state.
Definition: ultra_circuit_builder.cpp:3227
constexpr_utils defines some helper methods that perform some stl-equivalent operations but in a cons...
Definition: constexpr_utils.hpp:16
The structure contains the most basic table serving one function (for, example an xor table)
Definition: types.hpp:263
Definition: types.hpp:124
CircuitDataBackup is a structure we use to store all the information about the circuit that is needed...
Definition: ultra_circuit_builder.hpp:283
static CircuitDataBackup store_full_state(const CircuitBuilder &builder)
Stores the state of everything logic-related in the builder.
Definition: ultra_circuit_builder.hpp:336
bool is_same_state(const CircuitBuilder &builder)
Checks that the circuit state is the same as the stored circuit's one.
Definition: ultra_circuit_builder.hpp:471
void restore_prefinilized_state(CircuitBuilder *builder)
Restores circuit constructor to a prefinilized state.
Definition: ultra_circuit_builder.hpp:424
static CircuitDataBackup store_prefinilized_state(const CircuitBuilder *builder)
Stores the state of all members of the circuit constructor that are needed to restore the state after...
Definition: ultra_circuit_builder.hpp:388
A RAM memory record that can be ordered.
Definition: ultra_circuit_builder.hpp:114
Each ram array is an instance of memory transcript. It saves values and indexes for a particular memo...
Definition: ultra_circuit_builder.hpp:147
Definition: ultra_circuit_builder.hpp:76
A ROM memory record that can be ordered.
Definition: ultra_circuit_builder.hpp:93
Each rom array is an instance of memory transcript. It saves values and indexes for a particular memo...
Definition: ultra_circuit_builder.hpp:172
Used to store instructions to create partial_non_native_field_multiplication gates....
Definition: ultra_circuit_builder.hpp:194
Definition: gate_data.hpp:115
Definition: gate_data.hpp:20
Definition: gate_data.hpp:10
Definition: gate_data.hpp:120
Definition: gate_data.hpp:129
Definition: gate_data.hpp:31
Definition: gate_data.hpp:43
Definition: ultra_circuit_builder.hpp:17
Definition: gate_data.hpp:51