Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
rom_ram_logic.cpp
Go to the documentation of this file.
1#include "rom_ram_logic.hpp"
4#include <execution>
5
6namespace bb {
7
8template <typename ExecutionTrace> size_t RomRamLogic_<ExecutionTrace>::create_ROM_array(const size_t array_size)
9{
10 RomTranscript new_transcript;
11 for (size_t i = 0; i < array_size; ++i) {
12 new_transcript.state.emplace_back(
13 std::array<uint32_t, 2>{ UNINITIALIZED_MEMORY_RECORD, UNINITIALIZED_MEMORY_RECORD });
14 }
15 rom_arrays.emplace_back(new_transcript);
16 return rom_arrays.size() - 1;
17}
24template <typename ExecutionTrace>
26 const size_t rom_id,
27 const size_t index_value,
28 const uint32_t value_witness)
29{
30 BB_ASSERT_GT(rom_arrays.size(), rom_id);
31 RomTranscript& rom_array = rom_arrays[rom_id];
32 const uint32_t index_witness =
33 (index_value == 0) ? builder->zero_idx : builder->put_constant_variable((uint64_t)index_value);
34 BB_ASSERT_GT(rom_array.state.size(), index_value);
35 BB_ASSERT_EQ(rom_array.state[index_value][0], UNINITIALIZED_MEMORY_RECORD);
36
37 RomRecord new_record{
38 .index_witness = index_witness,
39 .value_column1_witness = value_witness,
40 .value_column2_witness = builder->zero_idx,
41 .index = static_cast<uint32_t>(index_value),
42 .record_witness = 0,
43 .gate_index = 0,
44 };
45 rom_array.state[index_value][0] = value_witness;
46 rom_array.state[index_value][1] = builder->zero_idx;
47 create_ROM_gate(builder, new_record);
48 rom_array.records.emplace_back(new_record);
49}
50
51template <typename ExecutionTrace>
53 const size_t rom_id,
54 const size_t index_value,
55 const std::array<uint32_t, 2>& value_witnesses)
56{
57 BB_ASSERT_GT(rom_arrays.size(), rom_id);
58 RomTranscript& rom_array = rom_arrays[rom_id];
59 const uint32_t index_witness =
60 (index_value == 0) ? builder->zero_idx : builder->put_constant_variable((uint64_t)index_value);
61 BB_ASSERT_GT(rom_array.state.size(), index_value);
62 BB_ASSERT_EQ(rom_array.state[index_value][0], UNINITIALIZED_MEMORY_RECORD);
63 RomRecord new_record{
64 .index_witness = index_witness,
65 .value_column1_witness = value_witnesses[0],
66 .value_column2_witness = value_witnesses[1],
67 .index = static_cast<uint32_t>(index_value),
68 .record_witness = 0,
69 .gate_index = 0,
70 };
71 rom_array.state[index_value][0] = value_witnesses[0];
72 rom_array.state[index_value][1] = value_witnesses[1];
73 create_ROM_gate(builder, new_record);
74 rom_array.records.emplace_back(new_record);
75}
76
77template <typename ExecutionTrace>
79 const size_t rom_id,
80 const uint32_t index_witness)
81{
82 BB_ASSERT_GT(rom_arrays.size(), rom_id);
83 RomTranscript& rom_array = rom_arrays[rom_id];
84 const uint32_t index = static_cast<uint32_t>(uint256_t(builder->get_variable(index_witness)));
85 BB_ASSERT_GT(rom_array.state.size(), index);
86 ASSERT(rom_array.state[index][0] != UNINITIALIZED_MEMORY_RECORD);
87 const auto value = builder->get_variable(rom_array.state[index][0]);
88 const uint32_t value_witness = builder->add_variable(value);
89 RomRecord new_record{
90 .index_witness = index_witness,
91 .value_column1_witness = value_witness,
92 .value_column2_witness = builder->zero_idx,
93 .index = index,
94 .record_witness = 0,
95 .gate_index = 0,
96 };
97 create_ROM_gate(builder, new_record);
98 rom_array.records.emplace_back(new_record);
99
100 // create_read_gate
101 return value_witness;
102}
103
104template <typename ExecutionTrace>
106 const size_t rom_id,
107 const uint32_t index_witness)
108{
109 std::array<uint32_t, 2> value_witnesses;
110
111 const uint32_t index = static_cast<uint32_t>(uint256_t(builder->get_variable(index_witness)));
112 BB_ASSERT_GT(rom_arrays.size(), rom_id);
113 RomTranscript& rom_array = rom_arrays[rom_id];
114 BB_ASSERT_GT(rom_array.state.size(), index);
115 ASSERT(rom_array.state[index][0] != UNINITIALIZED_MEMORY_RECORD);
116 ASSERT(rom_array.state[index][1] != UNINITIALIZED_MEMORY_RECORD);
117 const auto value1 = builder->get_variable(rom_array.state[index][0]);
118 const auto value2 = builder->get_variable(rom_array.state[index][1]);
119 value_witnesses[0] = builder->add_variable(value1);
120 value_witnesses[1] = builder->add_variable(value2);
121 RomRecord new_record{
122 .index_witness = index_witness,
123 .value_column1_witness = value_witnesses[0],
124 .value_column2_witness = value_witnesses[1],
125 .index = index,
126 .record_witness = 0,
127 .gate_index = 0,
128 };
129 create_ROM_gate(builder, new_record);
130 rom_array.records.emplace_back(new_record);
131
132 // create_read_gate
133 return value_witnesses;
134}
135
136template <typename ExecutionTrace>
138{
139 // Record wire value can't yet be computed
140 record.record_witness = builder->add_variable(0);
141 builder->apply_memory_selectors(CircuitBuilder::MEMORY_SELECTORS::ROM_READ);
142 builder->blocks.memory.populate_wires(
144 // Note: record the index into the memory block that contains the RAM/ROM gates
145 record.gate_index = builder->blocks.memory.size() - 1;
146 builder->check_selector_length_consistency();
147 ++builder->num_gates;
148}
149
150template <typename ExecutionTrace>
152{
153 record.record_witness = builder->add_variable(0);
154 // record_witness is intentionally used only in a single gate
155 builder->update_used_witnesses(record.record_witness);
156 builder->apply_memory_selectors(CircuitBuilder::MEMORY_SELECTORS::ROM_CONSISTENCY_CHECK);
157 builder->blocks.memory.populate_wires(
159 // Note: record the index into the memory block that contains the RAM/ROM gates
160 record.gate_index = builder->blocks.memory.size() - 1;
161 builder->check_selector_length_consistency();
162 ++builder->num_gates;
163}
164
165template <typename ExecutionTrace>
167{
168 auto& rom_array = rom_arrays[rom_id];
169 const auto read_tag = builder->get_new_tag(); // current_tag + 1;
170 const auto sorted_list_tag = builder->get_new_tag(); // current_tag + 2;
171 builder->create_tag(read_tag, sorted_list_tag);
172 builder->create_tag(sorted_list_tag, read_tag);
173
174 // Make sure that every cell has been initialized
175 for (size_t i = 0; i < rom_array.state.size(); ++i) {
176 if (rom_array.state[i][0] == UNINITIALIZED_MEMORY_RECORD) {
177 set_ROM_element_pair(builder, rom_id, static_cast<uint32_t>(i), { builder->zero_idx, builder->zero_idx });
178 }
179 }
180
181#ifdef NO_PAR_ALGOS
182 std::sort(rom_array.records.begin(), rom_array.records.end());
183#else
184 std::sort(std::execution::par_unseq, rom_array.records.begin(), rom_array.records.end());
185#endif
186
187 for (const RomRecord& record : rom_array.records) {
188 const auto index = record.index;
189 const auto value1 = builder->get_variable(record.value_column1_witness);
190 const auto value2 = builder->get_variable(record.value_column2_witness);
191 const auto index_witness = builder->add_variable(FF((uint64_t)index));
192 // the same thing as with the record witness
193 builder->update_used_witnesses(index_witness);
194 const auto value1_witness = builder->add_variable(value1);
195 const auto value2_witness = builder->add_variable(value2);
196 RomRecord sorted_record{
197 .index_witness = index_witness,
198 .value_column1_witness = value1_witness,
199 .value_column2_witness = value2_witness,
200 .index = index,
201 .record_witness = 0,
202 .gate_index = 0,
203 };
204 create_sorted_ROM_gate(builder, sorted_record);
205
206 builder->assign_tag(record.record_witness, read_tag);
207 builder->assign_tag(sorted_record.record_witness, sorted_list_tag);
208
209 // For ROM/RAM gates, the 'record' wire value (wire column 4) is a linear combination of the first 3 wire
210 // values. However...the record value uses the random challenge 'eta', generated after the first 3 wires are
211 // committed to. i.e. we can't compute the record witness here because we don't know what `eta` is! Take the
212 // gate indices of the two rom gates (original read gate + sorted gate) and store in `memory_records`. Once
213 // we
214 // generate the `eta` challenge, we'll use `memory_records` to figure out which gates need a record wire
215 // value
216 // to be computed.
217 // record (w4) = w3 * eta^3 + w2 * eta^2 + w1 * eta + read_write_flag (0 for reads, 1 for writes)
218 // Separate containers used to store gate indices of reads and writes. Need to differentiate because of
219 // `read_write_flag` (N.B. all ROM accesses are considered reads. Writes are for RAM operations)
220 builder->memory_read_records.push_back(static_cast<uint32_t>(sorted_record.gate_index));
221 builder->memory_read_records.push_back(static_cast<uint32_t>(record.gate_index));
222 }
223 // One of the checks we run on the sorted list, is to validate the difference between
224 // the index field across two gates is either 0 or 1.
225 // If we add a dummy gate at the end of the sorted list, where we force the first wire to
226 // equal `m + 1`, where `m` is the maximum allowed index in the sorted list,
227 // we have validated that all ROM reads are correctly constrained
228 FF max_index_value((uint64_t)rom_array.state.size());
229 uint32_t max_index = builder->add_variable(max_index_value);
230 // TODO(https://github.com/AztecProtocol/barretenberg/issues/879): This was formerly a single arithmetic gate. A
231 // dummy gate has been added to allow the previous gate to access the required wire data via shifts, allowing the
232 // arithmetic gate to occur out of sequence.
233 builder->create_dummy_gate(
234 builder->blocks.memory, max_index, builder->zero_idx, builder->zero_idx, builder->zero_idx);
235 builder->create_big_add_gate(
236 {
237 max_index,
238 builder->zero_idx,
239 builder->zero_idx,
240 builder->zero_idx,
241 1,
242 0,
243 0,
244 0,
245 -max_index_value,
246 },
247 false);
248 // N.B. If the above check holds, we know the sorted list begins with an index value of 0,
249 // because the first cell is explicitly initialized using zero_idx as the index field.
250}
251
253{
254 for (size_t i = 0; i < rom_arrays.size(); ++i) {
255 process_ROM_array(builder, i);
256 }
257}
258
259template <typename ExecutionTrace> size_t RomRamLogic_<ExecutionTrace>::create_RAM_array(const size_t array_size)
260{
261 RamTranscript new_transcript;
262 for (size_t i = 0; i < array_size; ++i) {
263 new_transcript.state.emplace_back(UNINITIALIZED_MEMORY_RECORD);
264 }
265 ram_arrays.emplace_back(new_transcript);
266 return ram_arrays.size() - 1;
267}
268
269template <typename ExecutionTrace>
271 const size_t ram_id,
272 const size_t index_value,
273 const uint32_t value_witness)
274{
275 BB_ASSERT_GT(ram_arrays.size(), ram_id);
276 RamTranscript& ram_array = ram_arrays[ram_id];
277 const uint32_t index_witness =
278 (index_value == 0) ? builder->zero_idx : builder->put_constant_variable((uint64_t)index_value);
279 BB_ASSERT_GT(ram_array.state.size(), index_value);
280 BB_ASSERT_EQ(ram_array.state[index_value], UNINITIALIZED_MEMORY_RECORD);
281 RamRecord new_record{ .index_witness = index_witness,
282 .timestamp_witness = builder->put_constant_variable((uint64_t)ram_array.access_count),
283 .value_witness = value_witness,
284 .index = static_cast<uint32_t>(index_value), // TODO: size_t?
285 .timestamp = static_cast<uint32_t>(ram_array.access_count),
286 .access_type = RamRecord::AccessType::WRITE,
287 .record_witness = 0,
288 .gate_index = 0 };
289 ram_array.state[index_value] = value_witness;
290 ram_array.access_count++;
291 create_RAM_gate(builder, new_record);
292 ram_array.records.emplace_back(new_record);
293}
294
295template <typename ExecutionTrace>
297 const size_t ram_id,
298 const uint32_t index_witness)
299{
300 BB_ASSERT_GT(ram_arrays.size(), ram_id);
301 RamTranscript& ram_array = ram_arrays[ram_id];
302 const uint32_t index = static_cast<uint32_t>(uint256_t(builder->get_variable(index_witness)));
303 BB_ASSERT_GT(ram_array.state.size(), index);
304 ASSERT(ram_array.state[index] != UNINITIALIZED_MEMORY_RECORD);
305 const auto value = builder->get_variable(ram_array.state[index]);
306 const uint32_t value_witness = builder->add_variable(value);
307
308 RamRecord new_record{ .index_witness = index_witness,
309 .timestamp_witness = builder->put_constant_variable((uint64_t)ram_array.access_count),
310 .value_witness = value_witness,
311 .index = index,
312 .timestamp = static_cast<uint32_t>(ram_array.access_count),
313 .access_type = RamRecord::AccessType::READ,
314 .record_witness = 0,
315 .gate_index = 0 };
316 create_RAM_gate(builder, new_record);
317 ram_array.records.emplace_back(new_record);
318
319 // increment ram array's access count
320 ram_array.access_count++;
321
322 // return witness index of the value in the array
323 return value_witness;
324}
325
326template <typename ExecutionTrace>
328 const size_t ram_id,
329 const uint32_t index_witness,
330 const uint32_t value_witness)
331{
332 BB_ASSERT_GT(ram_arrays.size(), ram_id);
333 RamTranscript& ram_array = ram_arrays[ram_id];
334 const uint32_t index = static_cast<uint32_t>(uint256_t(builder->get_variable(index_witness)));
335 BB_ASSERT_GT(ram_array.state.size(), index);
336 ASSERT(ram_array.state[index] != UNINITIALIZED_MEMORY_RECORD);
337
338 RamRecord new_record{ .index_witness = index_witness,
339 .timestamp_witness = builder->put_constant_variable((uint64_t)ram_array.access_count),
340 .value_witness = value_witness,
341 .index = index,
342 .timestamp = static_cast<uint32_t>(ram_array.access_count),
343 .access_type = RamRecord::AccessType::WRITE,
344 .record_witness = 0,
345 .gate_index = 0 };
346 create_RAM_gate(builder, new_record);
347 ram_array.records.emplace_back(new_record);
348
349 // increment ram array's access count
350 ram_array.access_count++;
351
352 // update Composer's current state of RAM array
353 ram_array.state[index] = value_witness;
354}
355
356template <typename ExecutionTrace>
358{
359 // Record wire value can't yet be computed (uses randomnes generated during proof construction).
360 // However it needs a distinct witness index,
361 // we will be applying copy constraints + set membership constraints.
362 // Later on during proof construction we will compute the record wire value + assign it
363 record.record_witness = builder->add_variable(0);
364 builder->apply_memory_selectors(record.access_type == RamRecord::AccessType::READ
365 ? CircuitBuilder::MEMORY_SELECTORS::RAM_READ
366 : CircuitBuilder::MEMORY_SELECTORS::RAM_WRITE);
367 builder->blocks.memory.populate_wires(
368 record.index_witness, record.timestamp_witness, record.value_witness, record.record_witness);
369
370 // Note: record the index into the block that contains the RAM/ROM gates
371 record.gate_index = builder->blocks.memory.size() - 1;
372 ++builder->num_gates;
373}
374
375template <typename ExecutionTrace>
377{
378 record.record_witness = builder->add_variable(0);
379 builder->apply_memory_selectors(CircuitBuilder::MEMORY_SELECTORS::RAM_CONSISTENCY_CHECK);
380 builder->blocks.memory.populate_wires(
381 record.index_witness, record.timestamp_witness, record.value_witness, record.record_witness);
382 // Note: record the index into the memory block that contains the RAM/ROM gates
383 record.gate_index = builder->blocks.memory.size() - 1;
384 builder->check_selector_length_consistency();
385 ++builder->num_gates;
386}
387
388template <typename ExecutionTrace>
390 RamRecord& record,
391 const size_t ram_array_size)
392{
393 record.record_witness = builder->add_variable(0);
394 // Note: record the index into the block that contains the RAM/ROM gates
395 record.gate_index = builder->blocks.memory.size(); // no -1 since we havent added the gate yet
396
397 // TODO(https://github.com/AztecProtocol/barretenberg/issues/879): This method used to add a single arithmetic gate
398 // with two purposes: (1) to provide wire values to the previous RAM gate via shifts, and (2) to perform a
399 // consistency check on the value in wire 1. These two purposes have been split into a dummy gate and a simplified
400 // arithmetic gate, respectively. This allows both purposes to be served even after arithmetic gates are sorted out
401 // of sequence with the RAM gates.
402
403 // Create a final gate with all selectors zero; wire values are accessed by the previous RAM gate via
404 // shifted wires
405 builder->create_dummy_gate(builder->blocks.memory,
406 record.index_witness,
407 record.timestamp_witness,
408 record.value_witness,
409 record.record_witness);
410
411 // Create an add gate ensuring the final index is consistent with the size of the RAM array
412 builder->create_big_add_gate({
413 record.index_witness,
414 builder->zero_idx,
415 builder->zero_idx,
416 builder->zero_idx,
417 1,
418 0,
419 0,
420 0,
421 -FF(static_cast<uint64_t>(ram_array_size) - 1),
422 });
423}
424
425template <typename ExecutionTrace>
427{
428 RamTranscript& ram_array = ram_arrays[ram_id];
429 const auto access_tag = builder->get_new_tag(); // current_tag + 1;
430 const auto sorted_list_tag = builder->get_new_tag(); // current_tag + 2;
431 builder->create_tag(access_tag, sorted_list_tag);
432 builder->create_tag(sorted_list_tag, access_tag);
433
434 // Make sure that every cell has been initialized
435 // TODO: throw some kind of error here? Circuit should initialize all RAM elements to prevent errors.
436 // e.g. if a RAM record is uninitialized but the index of that record is a function of public/private inputs,
437 // different public iputs will produce different circuit constraints.
438 for (size_t i = 0; i < ram_array.state.size(); ++i) {
439 if (ram_array.state[i] == UNINITIALIZED_MEMORY_RECORD) {
440 init_RAM_element(builder, ram_id, static_cast<uint32_t>(i), builder->zero_idx);
441 }
442 }
443
444#ifdef NO_PAR_ALGOS
445 std::sort(ram_array.records.begin(), ram_array.records.end());
446#else
447 std::sort(std::execution::par_unseq, ram_array.records.begin(), ram_array.records.end());
448#endif
449
450 std::vector<RamRecord> sorted_ram_records;
451
452 // Iterate over all but final RAM record.
453 for (size_t i = 0; i < ram_array.records.size(); ++i) {
454 const RamRecord& record = ram_array.records[i];
455
456 const auto index = record.index;
457 const auto value = builder->get_variable(record.value_witness);
458 const auto index_witness = builder->add_variable(FF((uint64_t)index));
459 const auto timestamp_witess = builder->add_variable(record.timestamp);
460 const auto value_witness = builder->add_variable(value);
461 RamRecord sorted_record{
462 .index_witness = index_witness,
463 .timestamp_witness = timestamp_witess,
464 .value_witness = value_witness,
465 .index = index,
466 .timestamp = record.timestamp,
467 .access_type = record.access_type,
468 .record_witness = 0,
469 .gate_index = 0,
470 };
471
472 // create a list of sorted ram records
473 sorted_ram_records.emplace_back(sorted_record);
474
475 // We don't apply the RAM consistency check gate to the final record,
476 // as this gate expects a RAM record to be present at the next gate
477 if (i < ram_array.records.size() - 1) {
478 create_sorted_RAM_gate(builder, sorted_record);
479 } else {
480 // For the final record in the sorted list, we do not apply the full consistency check gate.
481 // Only need to check the index value = RAM array size - 1.
482 create_final_sorted_RAM_gate(builder, sorted_record, ram_array.state.size());
483 }
484
485 // Assign record/sorted records to tags that we will perform set equivalence checks on
486 builder->assign_tag(record.record_witness, access_tag);
487 builder->assign_tag(sorted_record.record_witness, sorted_list_tag);
488
489 // For ROM/RAM gates, the 'record' wire value (wire column 4) is a linear combination of the first 3 wire
490 // values. However...the record value uses the random challenge 'eta', generated after the first 3 wires are
491 // committed to. i.e. we can't compute the record witness here because we don't know what `eta` is! Take the
492 // gate indices of the two rom gates (original read gate + sorted gate) and store in `memory_records`. Once
493 // we
494 // generate the `eta` challenge, we'll use `memory_records` to figure out which gates need a record wire
495 // value
496 // to be computed.
497
498 switch (record.access_type) {
500 builder->memory_read_records.push_back(static_cast<uint32_t>(sorted_record.gate_index));
501 builder->memory_read_records.push_back(static_cast<uint32_t>(record.gate_index));
502 break;
503 }
505 builder->memory_write_records.push_back(static_cast<uint32_t>(sorted_record.gate_index));
506 builder->memory_write_records.push_back(static_cast<uint32_t>(record.gate_index));
507 break;
508 }
509 default: {
510 throw_or_abort("Unexpected record.access_type."); // shouldn't get here!
511 }
512 }
513 }
514
515 // Step 2: Create gates that validate correctness of RAM timestamps
516
517 std::vector<uint32_t> timestamp_deltas;
518 for (size_t i = 0; i < sorted_ram_records.size() - 1; ++i) {
519 // create_RAM_timestamp_gate(sorted_records[i], sorted_records[i + 1])
520 const auto& current = sorted_ram_records[i];
521 const auto& next = sorted_ram_records[i + 1];
522
523 const bool share_index = current.index == next.index;
524
525 FF timestamp_delta = 0;
526 if (share_index) {
527 BB_ASSERT_GT(next.timestamp, current.timestamp);
528 timestamp_delta = FF(next.timestamp - current.timestamp);
529 }
530
531 uint32_t timestamp_delta_witness = builder->add_variable(timestamp_delta);
532
533 builder->apply_memory_selectors(CircuitBuilder::MEMORY_SELECTORS::RAM_TIMESTAMP_CHECK);
534 builder->blocks.memory.populate_wires(
535 current.index_witness, current.timestamp_witness, timestamp_delta_witness, builder->zero_idx);
536
537 ++builder->num_gates;
538
539 // store timestamp offsets for later. Need to apply range checks to them, but calling
540 // `create_new_range_constraint` can add gates. Would ruin the structure of our sorted timestamp list.
541 timestamp_deltas.push_back(timestamp_delta_witness);
542 }
543
544 // add the index/timestamp values of the last sorted record in an empty add gate.
545 // (the previous gate will access the wires on this gate and requires them to be those of the last record)
546 const auto& last = sorted_ram_records[ram_array.records.size() - 1];
547 builder->create_dummy_gate(
548 builder->blocks.memory, last.index_witness, last.timestamp_witness, builder->zero_idx, builder->zero_idx);
549
550 // Step 3: validate difference in timestamps is monotonically increasing. i.e. is <= maximum timestamp
551 const size_t max_timestamp = ram_array.access_count - 1;
552 for (auto& w : timestamp_deltas) {
553 builder->create_new_range_constraint(w, max_timestamp);
554 }
555}
556
558{
559 for (size_t i = 0; i < ram_arrays.size(); ++i) {
560 process_RAM_array(builder, i);
561 }
562}
563
564// Template instantiations
567
568} // namespace bb
#define BB_ASSERT_GT(left, right,...)
Definition assert.hpp:87
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:59
#define ASSERT(expression,...)
Definition assert.hpp:49
ROM/RAM logic handler for UltraCircuitBuilder.
size_t create_ROM_array(const size_t array_size)
Create a new read-only memory region.
uint32_t read_ROM_array(CircuitBuilder *builder, const size_t rom_id, const uint32_t index_witness)
Read a single element from ROM.
void process_ROM_array(CircuitBuilder *builder, const size_t rom_id)
Compute additional gates required to validate ROM reads. Called when generating the proving key.
void create_sorted_RAM_gate(CircuitBuilder *builder, RamRecord &record)
Gate that performs consistency checks to validate that a claimed RAM read/write value is correct.
void process_ROM_arrays(CircuitBuilder *builder)
Process all of the ROM arrays.
std::array< uint32_t, 2 > read_ROM_array_pair(CircuitBuilder *builder, const size_t rom_id, const uint32_t index_witness)
Read a pair of elements from ROM.
void set_ROM_element(CircuitBuilder *builder, const size_t rom_id, const size_t index_value, const uint32_t value_witness)
Initialize a rom cell to equal value_witness
void create_final_sorted_RAM_gate(CircuitBuilder *builder, RamRecord &record, const size_t ram_array_size)
Performs consistency checks to validate that a claimed RAM read/write value is correct....
void process_RAM_arrays(CircuitBuilder *builder)
void init_RAM_element(CircuitBuilder *builder, const size_t ram_id, const size_t index_value, const uint32_t value_witness)
Initialize a RAM cell to equal value_witness
void create_sorted_ROM_gate(CircuitBuilder *builder, RomRecord &record)
Gate that performs consistency checks to validate that a claimed ROM read value is correct.
void write_RAM_array(CircuitBuilder *builder, const size_t ram_id, const uint32_t index_witness, const uint32_t value_witness)
void set_ROM_element_pair(CircuitBuilder *builder, 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.
void create_ROM_gate(CircuitBuilder *builder, RomRecord &record)
Gate that'reads' from a ROM table, i.e., the table index is a witness not precomputed.
uint32_t read_RAM_array(CircuitBuilder *builder, const size_t ram_id, const uint32_t index_witness)
typename ExecutionTrace::FF FF
void create_RAM_gate(CircuitBuilder *builder, RamRecord &record)
Gate that performs a read/write operation into a RAM table, i.e. table index is a witness not precomp...
void process_RAM_array(CircuitBuilder *builder, const size_t ram_id)
Compute additional gates required to validate RAM read/writes. Called when generating the proving key...
size_t create_RAM_array(const size_t array_size)
Create a new updatable memory region.
AluTraceBuilder builder
Definition alu.test.cpp:123
Entry point for Barretenberg command-line interface.
typename Flavor::FF FF
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
A RAM memory record that can be ordered.
uint32_t index_witness
uint32_t value_witness
AccessType access_type
uint32_t record_witness
uint32_t timestamp_witness
Each ram array is an instance of memory transcript. It saves values and indexes for a particular memo...
std::vector< RamRecord > records
std::vector< uint32_t > state
A ROM memory record that can be ordered.
uint32_t value_column1_witness
uint32_t index_witness
uint32_t record_witness
uint32_t value_column2_witness
Each rom array is an instance of memory transcript. It saves values and indexes for a particular memo...
std::vector< std::array< uint32_t, 2 > > state
std::vector< RomRecord > records
void throw_or_abort(std::string const &err)