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 // do not initialize the table yet. The input entries might all be constant,
34 // if this is the case we might not have a valid pointer to a Builder
35 // We get around this, by initializing the table when `operator[]` is called
36 // with a non-const field element.
37
38 // Ensure that the origin tags of all entries are preserved so we can assign them on lookups
39 tags.resize(length);
40 for (size_t i = 0; i < length; ++i) {
41 tags[i] = { raw_entries[i][0].get_origin_tag(), raw_entries[i][1].get_origin_tag() };
42 }
43}
44
45// initialize the table once we perform a read. This ensures we always have a valid
46// pointer to a Builder.
47// (if both the table entries and the index are constant, we don't need a builder as we
48// can directly extract the desired value from `raw_entries`)
49template <typename Builder> void twin_rom_table<Builder>::initialize_table() const
50{
51 if (initialized) {
52 return;
53 }
54 ASSERT(context != nullptr);
55 // populate table. Table entries must be normalized and cannot be constants
56 for (const auto& entry : raw_entries) {
57 field_pt first;
58 field_pt second;
59 if (entry[0].is_constant()) {
60 first = field_pt::from_witness_index(context, context->put_constant_variable(entry[0].get_value()));
61 } else {
62 first = entry[0].normalize();
63 }
64 if (entry[1].is_constant()) {
65 second = field_pt::from_witness_index(context, context->put_constant_variable(entry[1].get_value()));
66 } else {
67 second = entry[1].normalize();
68 }
69 entries.emplace_back(field_pair_pt{ first, second });
70 }
71 rom_id = context->create_ROM_array(length);
72
73 for (size_t i = 0; i < length; ++i) {
74 context->set_ROM_element_pair(
75 rom_id, i, std::array<uint32_t, 2>{ entries[i][0].get_witness_index(), entries[i][1].get_witness_index() });
76 }
77
78 // Ensure that the origin tags of all entries are preserved so we can assign them on lookups
79 tags.resize(length);
80 for (size_t i = 0; i < length; ++i) {
81 tags[i] = { raw_entries[i][0].get_origin_tag(), raw_entries[i][1].get_origin_tag() };
82 }
83 initialized = true;
84}
85
86template <typename Builder>
88 : raw_entries(other.raw_entries)
89 , entries(other.entries)
90 , tags(other.tags)
91 , length(other.length)
92 , rom_id(other.rom_id)
93 , initialized(other.initialized)
94 , context(other.context)
95{}
96
97template <typename Builder>
99 : raw_entries(other.raw_entries)
100 , entries(other.entries)
101 , tags(other.tags)
102 , length(other.length)
103 , rom_id(other.rom_id)
104 , initialized(other.initialized)
105 , context(other.context)
106{}
107
109{
110 raw_entries = other.raw_entries;
111 entries = other.entries;
112 tags = other.tags;
113 length = other.length;
114 rom_id = other.rom_id;
115 initialized = other.initialized;
116 context = other.context;
117 return *this;
118}
119
121{
122 raw_entries = other.raw_entries;
123 entries = other.entries;
124 tags = other.tags;
125 length = other.length;
126 rom_id = other.rom_id;
127 initialized = other.initialized;
128 context = other.context;
129 return *this;
130}
131
132template <typename Builder>
134{
135 if (index >= length) {
136 ASSERT(context != nullptr);
137 context->failure("twin_rom_table: ROM array access out of bounds");
138 }
139
140 return entries[index];
141}
142
143template <typename Builder>
145{
146 if (index.is_constant()) {
147 return operator[](static_cast<size_t>(uint256_t(index.get_value()).data[0]));
148 }
149 if (context == nullptr) {
150 context = index.get_context();
151 }
152
153 initialize_table();
154 if (uint256_t(index.get_value()) >= length) {
155 context->failure("twin_rom_table: ROM array access out of bounds");
156 }
157
158 auto output_indices = context->read_ROM_array_pair(rom_id, index.normalize().get_witness_index());
159 auto pair = field_pair_pt{
160 field_pt::from_witness_index(context, output_indices[0]),
161 field_pt::from_witness_index(context, output_indices[1]),
162 };
163
164 const auto native_index = uint256_t(index.get_value());
165 const size_t cast_index = static_cast<size_t>(static_cast<uint64_t>(native_index));
166 // In case of a legitimate lookup, restore the tags of the original entries to the output
167 if (native_index < length) {
168 pair[0].set_origin_tag(tags[cast_index][0]);
169 pair[1].set_origin_tag(tags[cast_index][1]);
170 }
171 return pair;
172}
173
176} // namespace bb::stdlib
#define ASSERT(expression,...)
Definition assert.hpp:49
static field_t from_witness_index(Builder *ctx, uint32_t witness_index)
Definition field.cpp:59
Builder * get_context() const
Definition field.hpp:389
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:827
field_t normalize() const
Return a new element, where the in-circuit witness contains the actual represented value (multiplicat...
Definition field.cpp:635
bool is_constant() const
Definition field.hpp:399
uint32_t get_witness_index() const
Get the witness index of the current field element.
Definition field.hpp:461
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
FF const & operator[](size_t idx) const
Retruns the element in beta_products at place #idx.
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13