Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
execution_trace_block.hpp
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#pragma once
14#include <cstddef>
15
16#ifdef CHECK_CIRCUIT_STACKTRACES
17#include <backward.hpp>
18#endif
19
20namespace bb {
21
22#ifdef CHECK_CIRCUIT_STACKTRACES
23struct BbStackTrace : backward::StackTrace {
24 BbStackTrace() { load_here(32); }
25};
26struct StackTraces {
27 std::vector<BbStackTrace> stack_traces;
28 void populate() { stack_traces.emplace_back(); }
29 void print(size_t gate_idx) const { backward::Printer{}.print(stack_traces.at(gate_idx)); }
30 // Don't interfere with equality semantics of structs that include this in debug builds
31 bool operator==(const StackTraces& other) const
32 {
33 static_cast<void>(other);
34 return true;
35 }
36};
37#endif
38
46template <typename FF> class Selector {
47 public:
48 Selector() = default;
49 virtual ~Selector() = default;
50
51 // Delete copy/move to avoid object slicing and unintended behavior
52 Selector(const Selector&) = default;
53 Selector& operator=(const Selector&) = default;
54 Selector(Selector&&) = delete;
56
61 void emplace_back(const FF& value) { push_back(value); }
62
67 virtual void emplace_back(int value) = 0;
68
73 virtual void push_back(const FF& value) = 0;
74
79 virtual void resize(size_t new_size) = 0;
80
86 virtual const FF& operator[](size_t index) const = 0;
87
92 virtual const FF& back() const = 0;
93
97 virtual size_t size() const = 0;
98
102 virtual bool empty() const = 0;
103
109 virtual void set(size_t idx, int value) = 0;
110
115 virtual void set_back(int value) = 0;
116
122 virtual void set(size_t idx, const FF& value) = 0;
123};
124
131template <typename FF> class ZeroSelector : public Selector<FF> {
132 public:
134
135 void emplace_back(int value) override
136 {
137 BB_ASSERT_EQ(value, 0, "Calling ZeroSelector::emplace_back with a non zero value.");
138 size_++;
139 }
140
141 void push_back(const FF& value) override
142 {
144 size_++;
145 }
146
147 void set_back(int value) override
148 {
149 BB_ASSERT_EQ(value, 0, "Calling ZeroSelector::set_back with a non zero value.");
150 BB_ASSERT_GT(size_, 0U);
151 }
152
153 void set(size_t idx, int value) override
154 {
155 BB_ASSERT_DEBUG(idx < size_);
156 BB_ASSERT_EQ(value, 0, "Calling ZeroSelector::set with a non zero value.");
157 }
158
159 void set(size_t idx, const FF& value) override
160 {
161 BB_ASSERT_DEBUG(idx < size_);
163 size_++;
164 }
165
166 void resize(size_t new_size) override { size_ = new_size; }
167
168 bool operator==(const ZeroSelector& other) const { return size_ == other.size(); }
169
170 const FF& operator[](size_t index) const override
171 {
173 return zero;
174 }
175
176 const FF& back() const override { return zero; }
177
178 size_t size() const override { return size_; }
179
180 bool empty() const override { return size_ == 0; }
181
182 private:
183 static constexpr FF zero = 0;
184 size_t size_ = 0;
185};
186
193template <typename FF> class SlabVectorSelector : public Selector<FF> {
194 public:
196
197 void emplace_back(int i) override { data.emplace_back(i); }
198 void push_back(const FF& value) override { data.push_back(value); }
199 void set_back(int value) override { data.back() = value; }
200 void set(size_t idx, int i) override { data[idx] = i; }
201 void set(size_t idx, const FF& value) override { data[idx] = value; }
202 void resize(size_t new_size) override { data.resize(new_size); }
203
204 bool operator==(const SlabVectorSelector& other) const { return data == other.data; }
205
206 const FF& operator[](size_t i) const override { return data[i]; }
207 const FF& back() const override { return data.back(); }
208
209 size_t size() const override { return data.size(); }
210 bool empty() const override { return data.empty(); }
211
212 private:
213 std::vector<FF> data;
214};
215
222template <typename FF, size_t NUM_WIRES_> class ExecutionTraceBlock {
223 public:
224 static constexpr size_t NUM_WIRES = NUM_WIRES_;
225
227 using WireType = std::vector<uint32_t>;
228 using Wires = std::array<WireType, NUM_WIRES>;
229
234 ExecutionTraceBlock& operator=(ExecutionTraceBlock&&) noexcept = default;
235
236 virtual ~ExecutionTraceBlock() = default;
237
238#ifdef CHECK_CIRCUIT_STACKTRACES
239 // If enabled, we keep slow stack traces to be able to correlate gates with code locations where they were added
240 StackTraces stack_traces;
241#endif
242#ifdef TRACY_HACK_GATES_AS_MEMORY
243 std::vector<size_t> allocated_gates;
244#endif
246 {
247#ifdef TRACY_HACK_GATES_AS_MEMORY
248 std::unique_lock<std::mutex> lock(GLOBAL_GATE_MUTEX);
249 GLOBAL_GATE++;
250 TRACY_GATE_ALLOC(GLOBAL_GATE);
251 allocated_gates.push_back(GLOBAL_GATE);
252#endif
253 }
254
255 Wires wires; // vectors of indices into a witness variables array
256 uint32_t trace_offset_ = std::numeric_limits<uint32_t>::max(); // where this block starts in the trace
257
258 uint32_t trace_offset() const
259 {
260 BB_ASSERT(trace_offset_ != std::numeric_limits<uint32_t>::max());
261 return trace_offset_;
262 }
263
264 bool operator==(const ExecutionTraceBlock& other) const = default;
265
266 size_t size() const { return std::get<0>(this->wires).size(); }
267
268 void reserve(size_t size_hint)
269 {
270 for (auto& w : wires) {
271 w.reserve(size_hint);
272 }
273 for (auto& p : get_selectors()) {
274 p.reserve(size_hint);
275 }
276#ifdef CHECK_CIRCUIT_STACKTRACES
277 stack_traces.stack_traces.reserve(size_hint);
278#endif
279 }
280
281#ifdef TRACY_HACK_GATES_AS_MEMORY
283 {
284 std::unique_lock<std::mutex> lock(GLOBAL_GATE_MUTEX);
285 for ([[maybe_unused]] size_t gate : allocated_gates) {
286 if (!FREED_GATES.contains(gate)) {
287 TRACY_GATE_FREE(gate);
288 FREED_GATES.insert(gate);
289 }
290 }
291 }
292#endif
293
295
296 void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4)
297 {
298#ifdef CHECK_CIRCUIT_STACKTRACES
299 this->stack_traces.populate();
300#endif
301 this->tracy_gate();
302 this->wires[0].emplace_back(idx_1);
303 this->wires[1].emplace_back(idx_2);
304 this->wires[2].emplace_back(idx_3);
305 this->wires[3].emplace_back(idx_4);
306 }
307
308 auto& w_l() { return std::get<0>(this->wires); };
309 auto& w_r() { return std::get<1>(this->wires); };
310 auto& w_o() { return std::get<2>(this->wires); };
311 auto& w_4() { return std::get<3>(this->wires); };
312
319
320 protected:
322};
323
324} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:67
#define BB_ASSERT_GT(left, right,...)
Definition assert.hpp:107
#define BB_ASSERT_DEBUG(expression,...)
Definition assert.hpp:54
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:77
Basic structure for storing gate data in a builder.
std::vector< uint32_t > WireType
std::array< WireType, NUM_WIRES > Wires
ExecutionTraceBlock(ExecutionTraceBlock &&) noexcept=default
static constexpr size_t NUM_WIRES
bool operator==(const ExecutionTraceBlock &other) const =default
void reserve(size_t size_hint)
virtual ~ExecutionTraceBlock()=default
ExecutionTraceBlock & operator=(const ExecutionTraceBlock &)=default
void populate_wires(const uint32_t &idx_1, const uint32_t &idx_2, const uint32_t &idx_3, const uint32_t &idx_4)
virtual RefVector< Selector< FF > > get_selectors()=0
std::array< SlabVectorSelector< FF >, 6 > non_gate_selectors
ExecutionTraceBlock(const ExecutionTraceBlock &)=default
A template class for a reference vector. Behaves as if std::vector<T&> was possible.
Abstract interface for a generic selector.
virtual void resize(size_t new_size)=0
Resize the selector.
virtual size_t size() const =0
Get the number of elements.
virtual ~Selector()=default
virtual void emplace_back(int value)=0
Append an integer value to the selector.
virtual const FF & back() const =0
Get the last value in the selector.
Selector(Selector &&)=delete
virtual void set(size_t idx, int value)=0
Set the value at index using integer.
virtual bool empty() const =0
Check if the selector is empty.
virtual void push_back(const FF &value)=0
Push a field element to the selector.
Selector & operator=(const Selector &)=default
Selector & operator=(Selector &&)=delete
virtual void set(size_t idx, const FF &value)=0
Set the value at index using a field element.
virtual const FF & operator[](size_t index) const =0
Get value at specified index.
Selector()=default
void emplace_back(const FF &value)
Append a field element to the selector.
virtual void set_back(int value)=0
Set the last value using integer.
Selector(const Selector &)=default
Selector backed by a slab allocator vector.
void push_back(const FF &value) override
Push a field element to the selector.
void set(size_t idx, const FF &value) override
Set the value at index using a field element.
void resize(size_t new_size) override
Resize the selector.
size_t size() const override
Get the number of elements.
void set_back(int value) override
Set the last value using integer.
bool operator==(const SlabVectorSelector &other) const
const FF & operator[](size_t i) const override
Get value at specified index.
void emplace_back(int i) override
Append an integer value to the selector.
const FF & back() const override
Get the last value in the selector.
void set(size_t idx, int i) override
Set the value at index using integer.
bool empty() const override
Check if the selector is empty.
Selector specialization that only allows zeros.
static constexpr FF zero
const FF & operator[](size_t index) const override
Get value at specified index.
void set(size_t idx, const FF &value) override
Set the value at index using a field element.
void emplace_back(int value) override
Append an integer value to the selector.
bool empty() const override
Check if the selector is empty.
bool operator==(const ZeroSelector &other) const
const FF & back() const override
Get the last value in the selector.
size_t size() const override
Get the number of elements.
void set(size_t idx, int value) override
Set the value at index using integer.
void push_back(const FF &value) override
Push a field element to the selector.
void set_back(int value) override
Set the last value using integer.
void resize(size_t new_size) override
Resize the selector.
#define TRACY_GATE_ALLOC(t)
Definition mem.hpp:16
#define TRACY_GATE_FREE(t)
Definition mem.hpp:17
bool operator==(ecdsa_signature const &lhs, ecdsa_signature const &rhs)
Definition ecdsa.hpp:45
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
BB_INLINE constexpr bool is_zero() const noexcept