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
15#include <cstddef>
16
17#ifdef CHECK_CIRCUIT_STACKTRACES
18#include <backward.hpp>
19#endif
20
21namespace bb {
22
23#ifdef CHECK_CIRCUIT_STACKTRACES
24struct BbStackTrace : backward::StackTrace {
25 BbStackTrace() { load_here(32); }
26};
27struct StackTraces {
28 std::vector<BbStackTrace> stack_traces;
29 void populate() { stack_traces.emplace_back(); }
30 void print(size_t gate_idx) const { backward::Printer{}.print(stack_traces.at(gate_idx)); }
31 // Don't interfere with equality semantics of structs that include this in debug builds
32 bool operator==(const StackTraces& other) const
33 {
34 static_cast<void>(other);
35 return true;
36 }
37};
38#endif
39
47template <typename FF> class Selector {
48 public:
49 Selector() = default;
50 virtual ~Selector() = default;
51
52 // Delete copy/move to avoid object slicing and unintended behavior
53 Selector(const Selector&) = default;
54 Selector& operator=(const Selector&) = default;
55 Selector(Selector&&) = delete;
57
62 void emplace_back(const FF& value) { push_back(value); }
63
68 virtual void emplace_back(int value) = 0;
69
74 virtual void push_back(const FF& value) = 0;
75
80 virtual void resize(size_t new_size) = 0;
81
87 virtual const FF& operator[](size_t index) const = 0;
88
93 virtual const FF& back() const = 0;
94
98 virtual size_t size() const = 0;
99
103 virtual bool empty() const = 0;
104
110 virtual void set(size_t idx, int value) = 0;
111
116 virtual void set_back(int value) = 0;
117
123 virtual void set(size_t idx, const FF& value) = 0;
124};
125
132template <typename FF> class ZeroSelector : public Selector<FF> {
133 public:
135
136 void emplace_back(int value) override
137 {
138 BB_ASSERT_EQ(value, 0, "Calling ZeroSelector::emplace_back with a non zero value.");
139 size_++;
140 }
141
142 void push_back(const FF& value) override
143 {
145 size_++;
146 }
147
148 void set_back(int value) override
149 {
150 BB_ASSERT_EQ(value, 0, "Calling ZeroSelector::set_back with a non zero value.");
151 BB_ASSERT_GT(size_, 0U);
152 }
153
154 void set(size_t idx, int value) override
155 {
156 BB_ASSERT_LT(idx, size_);
157 BB_ASSERT_EQ(value, 0, "Calling ZeroSelector::set with a non zero value.");
158 }
159
160 void set(size_t idx, const FF& value) override
161 {
162 BB_ASSERT_LT(idx, size_);
164 size_++;
165 }
166
167 void resize(size_t new_size) override { size_ = new_size; }
168
169 bool operator==(const ZeroSelector& other) const { return size_ == other.size(); }
170
171 const FF& operator[](size_t index) const override
172 {
173 BB_ASSERT_LT(index, size_);
174 return zero;
175 }
176
177 const FF& back() const override { return zero; }
178
179 size_t size() const override { return size_; }
180
181 bool empty() const override { return size_ == 0; }
182
183 private:
184 static constexpr FF zero = 0;
185 size_t size_ = 0;
186};
187
194template <typename FF> class SlabVectorSelector : public Selector<FF> {
195 public:
197
198 void emplace_back(int i) override { data.emplace_back(i); }
199 void push_back(const FF& value) override { data.push_back(value); }
200 void set_back(int value) override { data.back() = value; }
201 void set(size_t idx, int i) override { data[idx] = i; }
202 void set(size_t idx, const FF& value) override { data[idx] = value; }
203 void resize(size_t new_size) override { data.resize(new_size); }
204
205 bool operator==(const SlabVectorSelector& other) const { return data == other.data; }
206
207 const FF& operator[](size_t i) const override { return data[i]; }
208 const FF& back() const override { return data.back(); }
209
210 size_t size() const override { return data.size(); }
211 bool empty() const override { return data.empty(); }
212
213 private:
215};
216
223template <typename FF, size_t NUM_WIRES_> class ExecutionTraceBlock {
224 public:
225 static constexpr size_t NUM_WIRES = NUM_WIRES_;
226
229 using Wires = std::array<WireType, NUM_WIRES>;
230
235 ExecutionTraceBlock& operator=(ExecutionTraceBlock&&) noexcept = default;
236
237 virtual ~ExecutionTraceBlock() = default;
238
239#ifdef CHECK_CIRCUIT_STACKTRACES
240 // If enabled, we keep slow stack traces to be able to correlate gates with code locations where they were added
241 StackTraces stack_traces;
242#endif
243#ifdef TRACY_HACK_GATES_AS_MEMORY
244 std::vector<size_t> allocated_gates;
245#endif
247 {
248#ifdef TRACY_HACK_GATES_AS_MEMORY
249 std::unique_lock<std::mutex> lock(GLOBAL_GATE_MUTEX);
250 GLOBAL_GATE++;
251 TRACY_GATE_ALLOC(GLOBAL_GATE);
252 allocated_gates.push_back(GLOBAL_GATE);
253#endif
254 }
255
256 Wires wires; // vectors of indices into a witness variables array
257 uint32_t trace_offset_ = std::numeric_limits<uint32_t>::max(); // where this block starts in the trace
258
259 uint32_t trace_offset() const
260 {
261 ASSERT(trace_offset_ != std::numeric_limits<uint32_t>::max());
262 return trace_offset_;
263 }
264
265 bool operator==(const ExecutionTraceBlock& other) const = default;
266
267 size_t size() const { return std::get<0>(this->wires).size(); }
268
269 void reserve(size_t size_hint)
270 {
271 for (auto& w : wires) {
272 w.reserve(size_hint);
273 }
274 for (auto& p : get_selectors()) {
275 p.reserve(size_hint);
276 }
277#ifdef CHECK_CIRCUIT_STACKTRACES
278 stack_traces.stack_traces.reserve(size_hint);
279#endif
280 }
281
282 uint32_t get_fixed_size(bool is_structured = true) const
283 {
284 return is_structured ? fixed_size : static_cast<uint32_t>(size());
285 }
286
287#ifdef TRACY_HACK_GATES_AS_MEMORY
289 {
290 std::unique_lock<std::mutex> lock(GLOBAL_GATE_MUTEX);
291 for ([[maybe_unused]] size_t gate : allocated_gates) {
292 if (!FREED_GATES.contains(gate)) {
293 TRACY_GATE_FREE(gate);
294 FREED_GATES.insert(gate);
295 }
296 }
297 }
298#endif
299 uint32_t fixed_size = 0; // Fixed size for use in structured trace
300
302
303 void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4)
304 {
305#ifdef CHECK_CIRCUIT_STACKTRACES
306 this->stack_traces.populate();
307#endif
308 this->tracy_gate();
309 this->wires[0].emplace_back(idx_1);
310 this->wires[1].emplace_back(idx_2);
311 this->wires[2].emplace_back(idx_3);
312 this->wires[3].emplace_back(idx_4);
313 }
314
315 auto& w_l() { return std::get<0>(this->wires); };
316 auto& w_r() { return std::get<1>(this->wires); };
317 auto& w_o() { return std::get<2>(this->wires); };
318 auto& w_4() { return std::get<3>(this->wires); };
319
326
327 protected:
329};
330
331} // namespace bb
#define BB_ASSERT_GT(left, right,...)
Definition assert.hpp:87
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:59
#define BB_ASSERT_LT(left, right,...)
Definition assert.hpp:115
#define ASSERT(expression,...)
Definition assert.hpp:49
Basic structure for storing gate data in a builder.
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
SlabVector< uint32_t > WireType
ExecutionTraceBlock(const ExecutionTraceBlock &)=default
uint32_t get_fixed_size(bool is_structured=true) const
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.
typename Flavor::FF FF
std::vector< T, bb::ContainerSlabAllocator< T > > SlabVector
A vector that uses the slab allocator.
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
BB_INLINE constexpr bool is_zero() const noexcept