Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
twin_rom_table.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
5// =====================
6
7#include "twin_rom_table.hpp"
8
9#include "../circuit_builders/circuit_builders.hpp"
11
12using namespace bb;
13
14namespace bb::stdlib {
15
16template <typename Builder>
18 : raw_entries(table_entries)
19 , length(raw_entries.size())
20{
21 static_assert(IsUltraOrMegaBuilder<Builder>);
22 // get the builder context
23 for (const auto& entry : table_entries) {
24 if (entry[0].get_context() != nullptr) {
25 context = entry[0].get_context();
26 break;
27 }
28 if (entry[1].get_context() != nullptr) {
29 context = entry[1].get_context();
30 break;
31 }
32 }
33
34 // We do not initialize the table yet. The input entries might all be constant,
35 // if this is the case we might not have a valid pointer to a Builder
36 // We get around this, by initializing the table when `operator[]` is called
37 // with a non-const field element.
38
39 // Ensure that the origin tags of all entries are preserved so we can assign them on lookups
40 _tags.resize(length);
41 for (size_t i = 0; i < length; ++i) {
42 _tags[i] = { raw_entries[i][0].get_origin_tag(), raw_entries[i][1].get_origin_tag() };
43 }
44}
45
46// initialize the table once we perform a read. This ensures we always have a valid
47// pointer to a Builder.
48// (if both the table entries and the index are constant, we don't need a builder as we
49// can directly extract the desired value from `raw_entries`)
50template <typename Builder> void twin_rom_table<Builder>::initialize_table() const
51{
52 if (initialized) {
53 return;
54 }
55 BB_ASSERT_EQ(context != nullptr, true, "twin_rom_table: context must be set before initializing the table");
56
57 // populate table. Table entries must be normalized and cannot be constants
58 for (const auto& entry : raw_entries) {
59 field_pt first;
60 field_pt second;
61 if (entry[0].is_constant()) {
62 first = field_pt::from_witness_index(context, context->put_constant_variable(entry[0].get_value()));
63 } else {
64 first = entry[0];
65 }
66 if (entry[1].is_constant()) {
67 second = field_pt::from_witness_index(context, context->put_constant_variable(entry[1].get_value()));
68 } else {
69 second = entry[1];
70 }
71 entries.emplace_back(field_pair_pt{ first, second });
72 }
73
74 // create uninitialized table of size `length`
75 rom_id = context->create_ROM_array(length);
76
77 for (size_t i = 0; i < length; ++i) {
78 context->set_ROM_element_pair(
79 rom_id, i, std::array<uint32_t, 2>{ entries[i][0].get_witness_index(), entries[i][1].get_witness_index() });
80 }
81
82 // Ensure that the origin tags of all entries are preserved so we can assign them on lookups
83 _tags.resize(length);
84 for (size_t i = 0; i < length; ++i) {
85 _tags[i] = { raw_entries[i][0].get_origin_tag(), raw_entries[i][1].get_origin_tag() };
86 }
87 initialized = true;
88}
89
90template <typename Builder> twin_rom_table<Builder>::twin_rom_table(const twin_rom_table& other) = default;
91template <typename Builder> twin_rom_table<Builder>::twin_rom_table(twin_rom_table&& other) = default;
92template <typename Builder>
94template <typename Builder>
96
97template <typename Builder>
99{
100 if (index >= length) {
101 BB_ASSERT(context != nullptr);
102 context->failure("twin_rom_table: ROM array access out of bounds");
103 }
104
105 return entries[index];
106}
107
108template <typename Builder>
110{
111 if (index.is_constant()) {
112 return operator[](static_cast<size_t>(uint256_t(index.get_value()).data[0]));
113 }
114 if (context == nullptr) {
115 context = index.get_context();
116 }
117
118 initialize_table();
119 if (uint256_t(index.get_value()) >= length) {
120 context->failure("twin_rom_table: ROM array access out of bounds");
121 }
122
123 auto output_indices = context->read_ROM_array_pair(rom_id, index.get_witness_index());
124 auto pair = field_pair_pt{
125 field_pt::from_witness_index(context, output_indices[0]),
126 field_pt::from_witness_index(context, output_indices[1]),
127 };
128
129 const auto native_index = uint256_t(index.get_value());
130 const size_t cast_index = static_cast<size_t>(static_cast<uint64_t>(native_index));
131 // In case of a legitimate lookup, restore the tags of the original entries to the output
132 if (native_index < length) {
133 pair[0].set_origin_tag(_tags[cast_index][0]);
134 pair[1].set_origin_tag(_tags[cast_index][1]);
135 }
136 return pair;
137}
138
141} // namespace bb::stdlib
#define BB_ASSERT(expression,...)
Definition assert.hpp:67
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:77
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
Definition field.cpp:62
OriginTag get_origin_tag() const
Definition field.hpp:346
std::array< field_pt, 2 > field_pair_pt
Contains all the headers required to adequately compile the types defined in circuit_builders_fwd....
StrictMock< MockContext > context
uint8_t const size_t length
Definition data_store.hpp:9
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13