Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
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 "rom_table.hpp"
8
9#include "../circuit_builders/circuit_builders.hpp"
11
12using namespace bb;
13
14namespace bb::stdlib {
15
16template <typename Builder> rom_table<Builder>::rom_table(const std::vector<field_pt>& table_entries)
17{
18 static_assert(HasPlookup<Builder>);
19 // get the builder context
20 for (const auto& entry : table_entries) {
21 if (entry.get_context() != nullptr) {
22 context = entry.get_context();
23 break;
24 }
25 }
26 raw_entries = table_entries;
27 length = raw_entries.size();
28 // do not initialize the table yet. The input entries might all be constant,
29 // if this is the case we might not have a valid pointer to a Builder
30 // We get around this, by initializing the table when `operator[]` is called
31 // with a non-const field element.
32
33 // Initialize tags
34 _tags.resize(raw_entries.size());
35 for (size_t i = 0; i < length; ++i) {
36 _tags[i] = raw_entries[i].get_origin_tag();
37 }
38}
39
40// initialize the table once we perform a read. This ensures we always have a valid
41// pointer to a Builder.
42// (if both the table entries and the index are constant, we don't need a builder as we
43// can directly extract the desired value from `raw_entries`)
44template <typename Builder> void rom_table<Builder>::initialize_table() const
45{
46 if (initialized) {
47 return;
48 }
49 ASSERT(context != nullptr);
50 // populate table. Table entries must be normalized and cannot be constants
51 for (const auto& entry : raw_entries) {
52 if (entry.is_constant()) {
53 auto fixed_witness =
54 field_pt::from_witness_index(context, context->put_constant_variable(entry.get_value()));
55 fixed_witness.set_origin_tag(entry.get_origin_tag());
56 entries.emplace_back(fixed_witness);
57
58 } else {
59 entries.emplace_back(entry.normalize());
60 }
61 }
62 rom_id = context->create_ROM_array(length);
63
64 for (size_t i = 0; i < length; ++i) {
65 context->set_ROM_element(rom_id, i, entries[i].get_witness_index());
66 }
67
68 // Preserve tags to restore them in the future lookups
69 _tags.resize(raw_entries.size());
70 for (size_t i = 0; i < length; ++i) {
71 _tags[i] = raw_entries[i].get_origin_tag();
72 }
73 initialized = true;
74}
75
76template <typename Builder>
78 : raw_entries(other.raw_entries)
79 , entries(other.entries)
80 , _tags(other._tags)
81 , length(other.length)
82 , rom_id(other.rom_id)
83 , initialized(other.initialized)
84 , context(other.context)
85{}
86
87template <typename Builder>
89 : raw_entries(other.raw_entries)
90 , entries(other.entries)
91 , _tags(other._tags)
92 , length(other.length)
93 , rom_id(other.rom_id)
94 , initialized(other.initialized)
95 , context(other.context)
96{}
97
98template <typename Builder> rom_table<Builder>& rom_table<Builder>::operator=(const rom_table& other)
99{
100 raw_entries = other.raw_entries;
101 entries = other.entries;
102 _tags = other._tags;
103 length = other.length;
104 rom_id = other.rom_id;
105 initialized = other.initialized;
106 context = other.context;
107 return *this;
108}
109
110template <typename Builder> rom_table<Builder>& rom_table<Builder>::operator=(rom_table&& other)
111{
112 raw_entries = other.raw_entries;
113 entries = other.entries;
114 _tags = other._tags;
115 length = other.length;
116 rom_id = other.rom_id;
117 initialized = other.initialized;
118 context = other.context;
119 return *this;
120}
121
122template <typename Builder> field_t<Builder> rom_table<Builder>::operator[](const size_t index) const
123{
124 if (index >= length) {
125 ASSERT(context != nullptr);
126 context->failure("rom_rable: ROM array access out of bounds");
127 }
128
129 return entries[index];
130}
131
132template <typename Builder> field_t<Builder> rom_table<Builder>::operator[](const field_pt& index) const
133{
134 if (index.is_constant()) {
135 return operator[](static_cast<size_t>(uint256_t(index.get_value()).data[0]));
136 }
137 if (context == nullptr) {
138 context = index.get_context();
139 }
140
141 initialize_table();
142 const auto native_index = uint256_t(index.get_value());
143 if (native_index >= length) {
144 context->failure("rom_table: ROM array access out of bounds");
145 }
146
147 uint32_t output_idx = context->read_ROM_array(rom_id, index.get_normalized_witness_index());
148 auto element = field_pt::from_witness_index(context, output_idx);
149
150 const size_t cast_index = static_cast<size_t>(static_cast<uint64_t>(native_index));
151
152 // If the index is legitimate, restore the tag
153 if (native_index < length) {
154
155 element.set_origin_tag(_tags[cast_index]);
156 }
157 return element;
158}
159
162} // 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
bb::fr get_value() const
Given a := *this, compute its value given by a.v * a.mul + a.add.
Definition field.cpp:827
bool is_constant() const
Definition field.hpp:399
uint32_t get_normalized_witness_index() const
Get the index of a normalized version of this element.
Definition field.hpp:471
std::vector< field_pt > entries
Definition rom_table.hpp:43
std::vector< OriginTag > _tags
Definition rom_table.hpp:45
void initialize_table() const
Definition rom_table.cpp:44
rom_table & operator=(const rom_table &other)
Definition rom_table.cpp:98
std::vector< field_pt > raw_entries
Definition rom_table.hpp:42
field_pt operator[](const size_t index) const
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.
std::conditional_t< IsGoblinBigGroup< C, Fq, Fr, G >, element_goblin::goblin_element< C, goblin_field< C >, Fr, G >, element_default::element< C, Fq, Fr, G > > element
element wraps either element_default::element or element_goblin::goblin_element depending on parametr...
Entry point for Barretenberg command-line interface.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13