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;
30template <
typename ExecutionTrace>
33 const size_t index_value,
34 const uint32_t value_witness)
38 const uint32_t index_witness =
39 (index_value == 0) ?
builder->zero_idx() :
builder->put_constant_variable((uint64_t)index_value);
45 .value_column1_witness = value_witness,
46 .value_column2_witness =
builder->zero_idx(),
47 .index =
static_cast<uint32_t
>(index_value),
51 rom_array.
state[index_value][0] = value_witness;
53 create_ROM_gate(
builder, new_record);
54 rom_array.
records.emplace_back(new_record);
59template <
typename ExecutionTrace>
62 const size_t index_value,
63 const std::array<uint32_t, 2>& value_witnesses)
67 const uint32_t index_witness =
builder->put_constant_variable((uint64_t)index_value);
72 .value_column1_witness = value_witnesses[0],
73 .value_column2_witness = value_witnesses[1],
74 .index =
static_cast<uint32_t
>(index_value),
78 rom_array.
state[index_value][0] = value_witnesses[0];
79 rom_array.
state[index_value][1] = value_witnesses[1];
81 create_ROM_gate(
builder, new_record);
82 rom_array.
records.emplace_back(new_record);
85template <
typename ExecutionTrace>
88 const uint32_t index_witness)
96 const uint32_t value_witness =
builder->add_variable(
value);
99 .value_column1_witness = value_witness,
100 .value_column2_witness =
builder->zero_idx(),
105 create_ROM_gate(
builder, new_record);
106 rom_array.
records.emplace_back(new_record);
108 return value_witness;
111template <
typename ExecutionTrace>
114 const uint32_t index_witness)
116 std::array<uint32_t, 2> value_witnesses;
126 value_witnesses[0] =
builder->add_variable(value1);
127 value_witnesses[1] =
builder->add_variable(value2);
130 .value_column1_witness = value_witnesses[0],
131 .value_column2_witness = value_witnesses[1],
136 create_ROM_gate(
builder, new_record);
137 rom_array.
records.emplace_back(new_record);
139 return value_witnesses;
146template <
typename ExecutionTrace>
151 builder->apply_memory_selectors(CircuitBuilder::MEMORY_SELECTORS::ROM_READ);
152 builder->blocks.memory.populate_wires(
156 builder->check_selector_length_consistency();
157 builder->increment_num_gates();
160template <
typename ExecutionTrace>
166 builder->apply_memory_selectors(CircuitBuilder::MEMORY_SELECTORS::ROM_CONSISTENCY_CHECK);
167 builder->blocks.memory.populate_wires(
171 builder->check_selector_length_consistency();
172 builder->increment_num_gates();
175template <
typename ExecutionTrace>
178 auto& rom_array = rom_arrays[rom_id];
182 const auto read_tag =
builder->get_new_tag();
183 const auto sorted_list_tag =
builder->get_new_tag();
184 builder->set_tau_transposition(read_tag, sorted_list_tag);
187 for (
size_t i = 0; i < rom_array.state.size(); ++i) {
188 if (rom_array.state[i][0] == UNINITIALIZED_MEMORY_RECORD) {
189 set_ROM_element_pair(
195 std::sort(rom_array.records.begin(), rom_array.records.end());
197 std::sort(std::execution::par_unseq, rom_array.records.begin(), rom_array.records.end());
200 for (
const RomRecord& record : rom_array.records) {
201 const auto index = record.index;
202 const auto value1 =
builder->get_variable(record.value_column1_witness);
203 const auto value2 =
builder->get_variable(record.value_column2_witness);
204 const auto index_witness =
builder->add_variable(
FF((uint64_t)
index));
205 builder->update_used_witnesses(index_witness);
206 const auto value1_witness =
builder->add_variable(value1);
207 const auto value2_witness =
builder->add_variable(value2);
212 .value_column1_witness = value1_witness,
213 .value_column2_witness = value2_witness,
219 create_sorted_ROM_gate(
builder, sorted_record);
221 builder->assign_tag(record.record_witness, read_tag);
222 builder->assign_tag(sorted_record.record_witness, sorted_list_tag);
234 builder->memory_read_records.push_back(
static_cast<uint32_t
>(sorted_record.gate_index));
235 builder->memory_read_records.push_back(
static_cast<uint32_t
>(record.gate_index));
242 FF max_index_value((uint64_t)rom_array.state.size());
243 uint32_t max_index =
builder->add_variable(max_index_value);
245 builder->create_unconstrained_gate(
266 for (
size_t i = 0; i < rom_arrays.size(); ++i) {
274 for (
size_t i = 0; i < array_size; ++i) {
275 new_transcript.
state.emplace_back(UNINITIALIZED_MEMORY_RECORD);
277 ram_arrays.emplace_back(new_transcript);
278 return ram_arrays.size() - 1;
295template <
typename ExecutionTrace>
298 const size_t index_value,
299 const uint32_t value_witness)
303 const uint32_t index_witness =
304 (index_value == 0) ?
builder->zero_idx() :
builder->put_constant_variable((uint64_t)index_value);
309 .value_witness = value_witness,
310 .index =
static_cast<uint32_t
>(index_value),
311 .timestamp =
static_cast<uint32_t
>(ram_array.
access_count),
315 ram_array.
state[index_value] = value_witness;
318 create_RAM_gate(
builder, new_record);
319 ram_array.
records.emplace_back(new_record);
322template <
typename ExecutionTrace>
325 const uint32_t index_witness)
333 const uint32_t value_witness =
builder->add_variable(
value);
337 .value_witness = value_witness,
339 .timestamp =
static_cast<uint32_t
>(ram_array.
access_count),
345 create_RAM_gate(
builder, new_record);
346 ram_array.
records.emplace_back(new_record);
352 return value_witness;
366template <
typename ExecutionTrace>
369 const uint32_t index_witness,
370 const uint32_t value_witness)
380 .value_witness = value_witness,
382 .timestamp =
static_cast<uint32_t
>(ram_array.
access_count),
387 create_RAM_gate(
builder, new_record);
388 ram_array.
records.emplace_back(new_record);
397template <
typename ExecutionTrace>
406 ? CircuitBuilder::MEMORY_SELECTORS::RAM_READ
407 : CircuitBuilder::MEMORY_SELECTORS::RAM_WRITE);
408 builder->blocks.memory.populate_wires(
413 builder->increment_num_gates();
416template <
typename ExecutionTrace>
420 builder->apply_memory_selectors(CircuitBuilder::MEMORY_SELECTORS::RAM_CONSISTENCY_CHECK);
421 builder->blocks.memory.populate_wires(
425 builder->check_selector_length_consistency();
426 builder->increment_num_gates();
429template <
typename ExecutionTrace>
432 const size_t ram_array_size)
456 -
FF(
static_cast<uint64_t
>(ram_array_size) - 1),
460template <
typename ExecutionTrace>
464 const auto access_tag =
builder->get_new_tag();
465 const auto sorted_list_tag =
builder->get_new_tag();
469 builder->set_tau_transposition(access_tag, sorted_list_tag);
475 for (
size_t i = 0; i < ram_array.
state.size(); ++i) {
489 for (
size_t i = 0; i < ram_array.
records.size(); ++i) {
494 const auto index_witness =
builder->add_variable(
FF((uint64_t)
index));
496 const auto value_witness =
builder->add_variable(
value);
501 .timestamp_witness = timestamp_witess,
502 .value_witness = value_witness,
511 sorted_ram_records.emplace_back(sorted_record);
515 if (i < ram_array.
records.size() - 1) {
516 create_sorted_RAM_gate(
builder, sorted_record);
520 create_final_sorted_RAM_gate(
builder, sorted_record, ram_array.
state.size());
525 builder->assign_tag(sorted_record.record_witness, sorted_list_tag);
537 builder->memory_read_records.push_back(
static_cast<uint32_t
>(sorted_record.gate_index));
538 builder->memory_read_records.push_back(
static_cast<uint32_t
>(record.
gate_index));
542 builder->memory_write_records.push_back(
static_cast<uint32_t
>(sorted_record.gate_index));
543 builder->memory_write_records.push_back(
static_cast<uint32_t
>(record.
gate_index));
554 std::vector<uint32_t> timestamp_deltas;
556 if (sorted_ram_records.size() <= 1) {
559 for (
size_t i = 0; i < sorted_ram_records.size() - 1; ++i) {
560 const auto& current = sorted_ram_records[i];
561 const auto& next = sorted_ram_records[i + 1];
563 const bool share_index = current.index == next.index;
565 FF timestamp_delta = 0;
568 timestamp_delta =
FF(next.timestamp - current.timestamp);
571 uint32_t timestamp_delta_witness =
builder->add_variable(timestamp_delta);
575 builder->apply_memory_selectors(CircuitBuilder::MEMORY_SELECTORS::RAM_TIMESTAMP_CHECK);
576 builder->blocks.memory.populate_wires(
577 current.index_witness, current.timestamp_witness, timestamp_delta_witness,
builder->zero_idx());
579 builder->increment_num_gates();
583 timestamp_deltas.push_back(timestamp_delta_witness);
588 const auto& last = sorted_ram_records[ram_array.
records.size() - 1];
589 builder->create_unconstrained_gate(
590 builder->blocks.memory, last.index_witness, last.timestamp_witness,
builder->zero_idx(),
builder->zero_idx());
596 const size_t max_timestamp = ram_array.
access_count - 1;
597 for (
auto& w : timestamp_deltas) {
598 builder->create_new_range_constraint(w, max_timestamp);
604 for (
size_t i = 0; i < ram_arrays.size(); ++i) {
#define BB_ASSERT(expression,...)
#define BB_ASSERT_GT(left, right,...)
#define BB_ASSERT_NEQ(actual, expected,...)
#define BB_ASSERT_EQ(actual, expected,...)
bb::field< bb::Bn254FrParams > FF
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)
Write a cell in a RAM array.
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, first by index, then by timestamp.
uint32_t timestamp_witness
RamTranscript contains the RamRecords for a particular RAM table (recording READ and WRITE operations...
std::vector< RamRecord > records
std::vector< uint32_t > state
A ROM memory record that can be ordered, where the ordering is given by the index (a....
uint32_t value_column1_witness
uint32_t value_column2_witness
RomTranscript contains the RomRecords for a particular ROM table as well as the vector whose ith entr...
std::vector< std::array< uint32_t, 2 > > state
std::vector< RomRecord > records
void throw_or_abort(std::string const &err)