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 });
15 rom_arrays.emplace_back(new_transcript);
16 return rom_arrays.size() - 1;
24template <
typename ExecutionTrace>
27 const size_t index_value,
28 const uint32_t value_witness)
32 const uint32_t index_witness =
33 (index_value == 0) ?
builder->zero_idx :
builder->put_constant_variable((uint64_t)index_value);
39 .value_column1_witness = value_witness,
40 .value_column2_witness =
builder->zero_idx,
41 .index =
static_cast<uint32_t
>(index_value),
45 rom_array.
state[index_value][0] = value_witness;
47 create_ROM_gate(
builder, new_record);
48 rom_array.
records.emplace_back(new_record);
51template <
typename ExecutionTrace>
54 const size_t index_value,
55 const std::array<uint32_t, 2>& value_witnesses)
59 const uint32_t index_witness =
60 (index_value == 0) ?
builder->zero_idx :
builder->put_constant_variable((uint64_t)index_value);
65 .value_column1_witness = value_witnesses[0],
66 .value_column2_witness = value_witnesses[1],
67 .index =
static_cast<uint32_t
>(index_value),
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);
77template <
typename ExecutionTrace>
80 const uint32_t index_witness)
84 const uint32_t index =
static_cast<uint32_t
>(
uint256_t(
builder->get_variable(index_witness)));
86 ASSERT(rom_array.
state[index][0] != UNINITIALIZED_MEMORY_RECORD);
88 const uint32_t value_witness =
builder->add_variable(
value);
91 .value_column1_witness = value_witness,
92 .value_column2_witness =
builder->zero_idx,
97 create_ROM_gate(
builder, new_record);
98 rom_array.
records.emplace_back(new_record);
101 return value_witness;
104template <
typename ExecutionTrace>
107 const uint32_t index_witness)
109 std::array<uint32_t, 2> value_witnesses;
111 const uint32_t index =
static_cast<uint32_t
>(
uint256_t(
builder->get_variable(index_witness)));
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);
123 .value_column1_witness = value_witnesses[0],
124 .value_column2_witness = value_witnesses[1],
129 create_ROM_gate(
builder, new_record);
130 rom_array.
records.emplace_back(new_record);
133 return value_witnesses;
136template <
typename ExecutionTrace>
141 builder->apply_memory_selectors(CircuitBuilder::MEMORY_SELECTORS::ROM_READ);
142 builder->blocks.memory.populate_wires(
146 builder->check_selector_length_consistency();
150template <
typename ExecutionTrace>
156 builder->apply_memory_selectors(CircuitBuilder::MEMORY_SELECTORS::ROM_CONSISTENCY_CHECK);
157 builder->blocks.memory.populate_wires(
161 builder->check_selector_length_consistency();
165template <
typename ExecutionTrace>
168 auto& rom_array = rom_arrays[rom_id];
169 const auto read_tag =
builder->get_new_tag();
170 const auto sorted_list_tag =
builder->get_new_tag();
171 builder->create_tag(read_tag, sorted_list_tag);
172 builder->create_tag(sorted_list_tag, read_tag);
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 });
182 std::sort(rom_array.records.begin(), rom_array.records.end());
184 std::sort(std::execution::par_unseq, rom_array.records.begin(), rom_array.records.end());
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));
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);
198 .value_column1_witness = value1_witness,
199 .value_column2_witness = value2_witness,
204 create_sorted_ROM_gate(
builder, sorted_record);
206 builder->assign_tag(record.record_witness, read_tag);
207 builder->assign_tag(sorted_record.record_witness, sorted_list_tag);
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));
228 FF max_index_value((uint64_t)rom_array.state.size());
229 uint32_t max_index =
builder->add_variable(max_index_value);
254 for (
size_t i = 0; i < rom_arrays.size(); ++i) {
262 for (
size_t i = 0; i < array_size; ++i) {
263 new_transcript.
state.emplace_back(UNINITIALIZED_MEMORY_RECORD);
265 ram_arrays.emplace_back(new_transcript);
266 return ram_arrays.size() - 1;
269template <
typename ExecutionTrace>
272 const size_t index_value,
273 const uint32_t value_witness)
277 const uint32_t index_witness =
278 (index_value == 0) ?
builder->zero_idx :
builder->put_constant_variable((uint64_t)index_value);
283 .value_witness = value_witness,
284 .index =
static_cast<uint32_t
>(index_value),
285 .timestamp =
static_cast<uint32_t
>(ram_array.
access_count),
289 ram_array.
state[index_value] = value_witness;
291 create_RAM_gate(
builder, new_record);
292 ram_array.
records.emplace_back(new_record);
295template <
typename ExecutionTrace>
298 const uint32_t index_witness)
302 const uint32_t index =
static_cast<uint32_t
>(
uint256_t(
builder->get_variable(index_witness)));
304 ASSERT(ram_array.
state[index] != UNINITIALIZED_MEMORY_RECORD);
306 const uint32_t value_witness =
builder->add_variable(
value);
310 .value_witness = value_witness,
312 .timestamp =
static_cast<uint32_t
>(ram_array.
access_count),
316 create_RAM_gate(
builder, new_record);
317 ram_array.
records.emplace_back(new_record);
323 return value_witness;
326template <
typename ExecutionTrace>
329 const uint32_t index_witness,
330 const uint32_t value_witness)
334 const uint32_t index =
static_cast<uint32_t
>(
uint256_t(
builder->get_variable(index_witness)));
336 ASSERT(ram_array.
state[index] != UNINITIALIZED_MEMORY_RECORD);
340 .value_witness = value_witness,
342 .timestamp =
static_cast<uint32_t
>(ram_array.
access_count),
346 create_RAM_gate(
builder, new_record);
347 ram_array.
records.emplace_back(new_record);
353 ram_array.
state[index] = value_witness;
356template <
typename ExecutionTrace>
365 ? CircuitBuilder::MEMORY_SELECTORS::RAM_READ
366 : CircuitBuilder::MEMORY_SELECTORS::RAM_WRITE);
367 builder->blocks.memory.populate_wires(
375template <
typename ExecutionTrace>
379 builder->apply_memory_selectors(CircuitBuilder::MEMORY_SELECTORS::RAM_CONSISTENCY_CHECK);
380 builder->blocks.memory.populate_wires(
384 builder->check_selector_length_consistency();
388template <
typename ExecutionTrace>
391 const size_t ram_array_size)
421 -
FF(
static_cast<uint64_t
>(ram_array_size) - 1),
425template <
typename ExecutionTrace>
429 const auto access_tag =
builder->get_new_tag();
430 const auto sorted_list_tag =
builder->get_new_tag();
431 builder->create_tag(access_tag, sorted_list_tag);
432 builder->create_tag(sorted_list_tag, access_tag);
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);
453 for (
size_t i = 0; i < ram_array.
records.size(); ++i) {
456 const auto index = record.
index;
458 const auto index_witness =
builder->add_variable(
FF((uint64_t)index));
460 const auto value_witness =
builder->add_variable(
value);
463 .timestamp_witness = timestamp_witess,
464 .value_witness = value_witness,
473 sorted_ram_records.emplace_back(sorted_record);
477 if (i < ram_array.
records.size() - 1) {
478 create_sorted_RAM_gate(
builder, sorted_record);
482 create_final_sorted_RAM_gate(
builder, sorted_record, ram_array.
state.size());
487 builder->assign_tag(sorted_record.record_witness, sorted_list_tag);
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));
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));
517 std::vector<uint32_t> timestamp_deltas;
518 for (
size_t i = 0; i < sorted_ram_records.size() - 1; ++i) {
520 const auto& current = sorted_ram_records[i];
521 const auto& next = sorted_ram_records[i + 1];
523 const bool share_index = current.index == next.index;
525 FF timestamp_delta = 0;
528 timestamp_delta =
FF(next.timestamp - current.timestamp);
531 uint32_t timestamp_delta_witness =
builder->add_variable(timestamp_delta);
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);
541 timestamp_deltas.push_back(timestamp_delta_witness);
546 const auto& last = sorted_ram_records[ram_array.
records.size() - 1];
548 builder->blocks.memory, last.index_witness, last.timestamp_witness,
builder->zero_idx,
builder->zero_idx);
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);
559 for (
size_t i = 0; i < ram_arrays.size(); ++i) {
#define BB_ASSERT_GT(left, right,...)
#define BB_ASSERT_EQ(actual, expected,...)
#define ASSERT(expression,...)
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.
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
A RAM memory record that can be ordered.
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 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)