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{
19 static_assert(HasPlookup<Builder>);
20 // get the builder context
21 for (const auto& entry : table_entries) {
22 if (entry[0].get_context() != nullptr) {
23 context = entry[0].get_context();
24 break;
25 }
26 if (entry[1].get_context() != nullptr) {
27 context = entry[1].get_context();
28 break;
29 }
30 }
31 raw_entries = table_entries;
32 length = raw_entries.size();
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].normalize();
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].normalize();
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>
92 : raw_entries(other.raw_entries)
93 , entries(other.entries)
94 , tags(other.tags)
95 , length(other.length)
96 , rom_id(other.rom_id)
97 , initialized(other.initialized)
98 , context(other.context)
99{}
100
101template <typename Builder>
103 : raw_entries(other.raw_entries)
104 , entries(other.entries)
105 , tags(other.tags)
106 , length(other.length)
107 , rom_id(other.rom_id)
108 , initialized(other.initialized)
109 , context(other.context)
110{}
111
113{
114 raw_entries = other.raw_entries;
115 entries = other.entries;
116 tags = other.tags;
117 length = other.length;
118 rom_id = other.rom_id;
119 initialized = other.initialized;
120 context = other.context;
121 return *this;
122}
123
125{
126 raw_entries = other.raw_entries;
127 entries = other.entries;
128 tags = other.tags;
129 length = other.length;
130 rom_id = other.rom_id;
131 initialized = other.initialized;
132 context = other.context;
133 return *this;
134}
135
136template <typename Builder>
138{
139 if (index >= length) {
140 ASSERT(context != nullptr);
141 context->failure("twin_rom_table: ROM array access out of bounds");
142 }
143
144 return entries[index];
145}
146
147template <typename Builder>
149{
150 if (index.is_constant()) {
151 return operator[](static_cast<size_t>(uint256_t(index.get_value()).data[0]));
152 }
153 if (context == nullptr) {
154 context = index.get_context();
155 }
156
157 initialize_table();
158 if (uint256_t(index.get_value()) >= length) {
159 context->failure("twin_rom_table: ROM array access out of bounds");
160 }
161
162 auto output_indices = context->read_ROM_array_pair(rom_id, index.get_normalized_witness_index());
163 auto pair = field_pair_pt{
164 field_pt::from_witness_index(context, output_indices[0]),
165 field_pt::from_witness_index(context, output_indices[1]),
166 };
167
168 const auto native_index = uint256_t(index.get_value());
169 const size_t cast_index = static_cast<size_t>(static_cast<uint64_t>(native_index));
170 // In case of a legitimate lookup, restore the tags of the original entries to the output
171 if (native_index < length) {
172 pair[0].set_origin_tag(tags[cast_index][0]);
173 pair[1].set_origin_tag(tags[cast_index][1]);
174 }
175 return pair;
176}
177
180} // namespace bb::stdlib
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:88
#define ASSERT(expression,...)
Definition assert.hpp:77
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
Definition field.cpp:61
Builder * get_context() const
Definition field.hpp:397
OriginTag get_origin_tag() const
Definition field.hpp:333
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
Definition field.cpp:829
field_t normalize() const
Return a new element, where the in-circuit witness contains the actual represented value (multiplicat...
Definition field.cpp:637
bool is_constant() const
Definition field.hpp:407
uint32_t get_normalized_witness_index() const
Get the index of a normalized version of this element.
Definition field.hpp:479
std::vector< field_pair_pt > entries
field_pair_pt operator[](const size_t index) const
std::vector< std::array< OriginTag, 2 > > tags
twin_rom_table & operator=(const twin_rom_table &other)
std::array< field_pt, 2 > field_pair_pt
std::vector< field_pair_pt > raw_entries
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.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13