Skip to content

Commit 62b9931

Browse files
committed
clean up some magic constants etc
1 parent a21b2f0 commit 62b9931

5 files changed

Lines changed: 134 additions & 65 deletions

File tree

barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ std::vector<ConnectedComponent> StaticAnalyzer_<FF, CircuitBuilder>::find_connec
526526
template <typename FF, typename CircuitBuilder>
527527
bool StaticAnalyzer_<FF, CircuitBuilder>::is_gate_sorted_rom(auto& memory_block, size_t gate_idx) const
528528
{
529+
BB_ASSERT(memory_block.kind == GateKind::Memory);
529530
return memory_block.gate_selector[gate_idx] == FF::one() && memory_block.q_1()[gate_idx] == FF::one() &&
530531
memory_block.q_2()[gate_idx] == FF::one();
531532
}
@@ -643,6 +644,7 @@ template <typename FF, typename CircuitBuilder>
643644
inline size_t StaticAnalyzer_<FF, CircuitBuilder>::process_current_decompose_chain(size_t index)
644645
{
645646
auto& arithmetic_block = circuit_builder.blocks.arithmetic;
647+
BB_ASSERT(arithmetic_block.kind == GateKind::Arith);
646648
auto zero_idx = circuit_builder.zero_idx();
647649
size_t current_index = index;
648650
std::vector<uint32_t> accumulators_indices;
@@ -1122,6 +1124,7 @@ template <typename FF, typename CircuitBuilder> void StaticAnalyzer_<FF, Circuit
11221124
template <typename FF, typename CircuitBuilder>
11231125
void StaticAnalyzer_<FF, CircuitBuilder>::print_arithmetic_gate_info(size_t gate_index, auto& block)
11241126
{
1127+
BB_ASSERT(block.kind == GateKind::Arith);
11251128
auto q_arith = block.gate_selector[gate_index];
11261129
if (q_arith.is_zero()) {
11271130
return;

barretenberg/cpp/src/barretenberg/honk/execution_trace/execution_trace_block.hpp

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ enum class GateKind : uint8_t {
102102
*
103103
* @details Each block holds:
104104
* - `wires` — variable indices for each row of this block.
105-
* - `non_gate_selectors[6]` — the always-present `q_m`, `q_c`, `q_1`..`q_4` columns.
105+
* - `non_gate_selectors[NUM_NON_GATE_SELECTORS]` — the always-present `q_m`, `q_c`, `q_1`..`q_4`
106+
* columns.
106107
* - `gate_selector` — present iff `kind != None`. Different blocks own different gate kinds
107108
* (arithmetic, lookup, elliptic, etc.); pub_inputs and Mega's ecc_op carry no gate selector.
108109
*
@@ -111,6 +112,11 @@ enum class GateKind : uint8_t {
111112
template <typename FF, size_t NUM_WIRES_> class GateBlock {
112113
public:
113114
static constexpr size_t NUM_WIRES = NUM_WIRES_;
115+
// q_m, q_c, q_1, q_2, q_3, q_4 — present on every block regardless of `kind`.
116+
static constexpr size_t NUM_NON_GATE_SELECTORS = 6;
117+
// Upper bound on the entries returned by `get_selectors()`: non-gate selectors plus at most one
118+
// gate selector. Drives the parallelism layout in `TraceToPolynomials::populate_wires_and_...`.
119+
static constexpr size_t MAX_SELECTORS = NUM_NON_GATE_SELECTORS + 1;
114120
using WireType = std::vector<uint32_t>;
115121
using Wires = std::array<WireType, NUM_WIRES>;
116122

@@ -124,7 +130,7 @@ template <typename FF, size_t NUM_WIRES_> class GateBlock {
124130

125131
GateKind kind = GateKind::None;
126132
Wires wires;
127-
std::array<Selector<FF>, 6> non_gate_selectors;
133+
std::array<Selector<FF>, NUM_NON_GATE_SELECTORS> non_gate_selectors;
128134
Selector<FF> gate_selector;
129135

130136
size_t cached_size_ = 0; // set by free_data() so size() works after freeing
@@ -168,9 +174,10 @@ template <typename FF, size_t NUM_WIRES_> class GateBlock {
168174
#endif
169175

170176
/**
171-
* @brief Returns 6 non-gate selectors plus, if `kind != None`, the gate selector. The order
172-
* matches the prefix of the corresponding flavor's `PrecomputedEntities` selectors; the gate
173-
* selector's destination polynomial index is determined by `kind` in `TraceToPolynomials`.
177+
* @brief Returns the `NUM_NON_GATE_SELECTORS` non-gate selectors plus, if `kind != None`, the
178+
* gate selector. The order matches the prefix of the corresponding flavor's
179+
* `PrecomputedEntities` selectors; the gate selector's destination polynomial index is
180+
* determined by `kind` in `TraceToPolynomials`.
174181
*/
175182
RefVector<Selector<FF>> get_selectors()
176183
{
@@ -240,15 +247,19 @@ template <typename FF, size_t NUM_WIRES_> class GateBlock {
240247

241248
/**
242249
* @brief Read a gate selector value at `(block, idx)` for a logical kind.
243-
* @details Returns `block.gate_selector[idx]` if the block owns kind `k`, otherwise zero. Use this
244-
* at cross-block read sites where the caller iterates blocks of unknown kind (e.g. circuit
245-
* checkers, graph builders). Within a path that already knows it has the owning block, just read
246-
* `block.gate_selector` directly.
250+
* @details Returns `block.gate_selector[idx]` if the block owns kind `k`, otherwise a reference to
251+
* a static zero. Use this at cross-block read sites where the caller iterates blocks of unknown
252+
* kind (e.g. circuit checkers, graph builders). Within a path that already knows it has the owning
253+
* block, just read `block.gate_selector` directly.
254+
*
255+
* @note `k` must not be `GateKind::None` which would index into a `gate_selector` that no None block populates.
247256
*/
248257
template <typename FF, size_t NUM_WIRES_>
249-
FF read_gate_selector(const GateBlock<FF, NUM_WIRES_>& block, GateKind k, size_t idx)
258+
const FF& read_gate_selector(const GateBlock<FF, NUM_WIRES_>& block, GateKind k, size_t idx)
250259
{
251-
return block.kind == k ? block.gate_selector[idx] : FF{ 0 };
260+
BB_ASSERT(k != GateKind::None);
261+
static const FF zero{ 0 };
262+
return block.kind == k ? block.gate_selector[idx] : zero;
252263
}
253264

254265
} // namespace bb

barretenberg/cpp/src/barretenberg/honk/execution_trace/mega_execution_trace.hpp

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,34 @@ struct MegaTraceBlockData {
4848

4949
static constexpr size_t NUM_BLOCKS = 11;
5050

51+
/**
52+
* @brief Single source of truth for which `GateKind` lands in which gate-selector polynomial.
53+
* @details The polynomial layout is `[q_m, q_c, q_1, q_2, q_3, q_4, GATE_SELECTOR_LAYOUT...]` —
54+
* i.e. the i-th entry maps to polynomial slot `NUM_NON_GATE_SELECTORS + i`. This must match the
55+
* gate-selector order in the Mega flavor's `PrecomputedEntities`, and (by `BB_ASSERT` in the
56+
* constructor) the block-traversal order of `get_gate_blocks()`.
57+
*/
58+
static constexpr std::array<GateKind, 9> GATE_SELECTOR_LAYOUT = {
59+
GateKind::BusRead, GateKind::Lookup, GateKind::Arith, GateKind::DeltaRange, GateKind::Elliptic,
60+
GateKind::Memory, GateKind::Nnf, GateKind::Poseidon2Ext, GateKind::Poseidon2Int,
61+
};
62+
63+
static_assert(
64+
[]() {
65+
for (size_t i = 0; i < GATE_SELECTOR_LAYOUT.size(); ++i) {
66+
if (GATE_SELECTOR_LAYOUT[i] == GateKind::None) {
67+
return false;
68+
}
69+
for (size_t j = i + 1; j < GATE_SELECTOR_LAYOUT.size(); ++j) {
70+
if (GATE_SELECTOR_LAYOUT[i] == GATE_SELECTOR_LAYOUT[j]) {
71+
return false;
72+
}
73+
}
74+
}
75+
return true;
76+
}(),
77+
"GATE_SELECTOR_LAYOUT must contain no GateKind::None and no duplicates");
78+
5179
MegaTraceBlockData()
5280
{
5381
// ecc_op and pub_inputs have no gate selector; their kind defaults to None.
@@ -64,34 +92,18 @@ struct MegaTraceBlockData {
6492

6593
/**
6694
* @brief Map a `GateKind` to its polynomial-array index for the Mega arithmetization.
67-
* @details The first 6 polynomial slots are non-gate selectors (q_m, q_c, q_1..q_4); the next 9 are the
68-
* Mega gate selectors in the order [busread, lookup, arith, delta_range, elliptic, memory, nnf,
69-
* poseidon2_ext, poseidon2_int]. Returns `SIZE_MAX` for `GateKind::None`.
95+
* @details The first `MegaTraceBlock::NUM_NON_GATE_SELECTORS` polynomial slots are non-gate
96+
* selectors; gate selectors follow in `GATE_SELECTOR_LAYOUT` order. Returns `SIZE_MAX` for
97+
* `GateKind::None` (ecc_op, pub_inputs — neither owns a gate selector).
7098
*/
7199
static constexpr size_t gate_kind_to_polynomial_idx(GateKind k)
72100
{
73-
switch (k) {
74-
case GateKind::BusRead:
75-
return 6;
76-
case GateKind::Lookup:
77-
return 7;
78-
case GateKind::Arith:
79-
return 8;
80-
case GateKind::DeltaRange:
81-
return 9;
82-
case GateKind::Elliptic:
83-
return 10;
84-
case GateKind::Memory:
85-
return 11;
86-
case GateKind::Nnf:
87-
return 12;
88-
case GateKind::Poseidon2Ext:
89-
return 13;
90-
case GateKind::Poseidon2Int:
91-
return 14;
92-
default:
93-
return SIZE_MAX;
101+
for (size_t i = 0; i < GATE_SELECTOR_LAYOUT.size(); ++i) {
102+
if (GATE_SELECTOR_LAYOUT[i] == k) {
103+
return MegaTraceBlock::NUM_NON_GATE_SELECTORS + i;
104+
}
94105
}
106+
return SIZE_MAX;
95107
}
96108

97109
std::vector<std::string_view> get_labels() const
@@ -148,6 +160,18 @@ struct MegaTraceBlockData {
148160
bool operator==(const MegaTraceBlockData& other) const = default;
149161
};
150162

163+
// Every kind set on a Mega block must have a polynomial slot in GATE_SELECTOR_LAYOUT, otherwise
164+
// that block's gate-selector data would be silently dropped at routing time.
165+
static_assert(MegaTraceBlockData::gate_kind_to_polynomial_idx(GateKind::BusRead) != SIZE_MAX);
166+
static_assert(MegaTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Lookup) != SIZE_MAX);
167+
static_assert(MegaTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Arith) != SIZE_MAX);
168+
static_assert(MegaTraceBlockData::gate_kind_to_polynomial_idx(GateKind::DeltaRange) != SIZE_MAX);
169+
static_assert(MegaTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Elliptic) != SIZE_MAX);
170+
static_assert(MegaTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Memory) != SIZE_MAX);
171+
static_assert(MegaTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Nnf) != SIZE_MAX);
172+
static_assert(MegaTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Poseidon2Ext) != SIZE_MAX);
173+
static_assert(MegaTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Poseidon2Int) != SIZE_MAX);
174+
151175
class MegaExecutionTraceBlocks : public MegaTraceBlockData {
152176
public:
153177
static constexpr size_t NUM_WIRES = MegaTraceBlock::NUM_WIRES;

barretenberg/cpp/src/barretenberg/honk/execution_trace/ultra_execution_trace.hpp

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,34 @@ struct UltraTraceBlockData {
3838

3939
static constexpr size_t NUM_BLOCKS = 9;
4040

41+
/**
42+
* @brief Single source of truth for which `GateKind` lands in which gate-selector polynomial.
43+
* @details The polynomial layout is `[q_m, q_c, q_1, q_2, q_3, q_4, GATE_SELECTOR_LAYOUT...]` —
44+
* i.e. the i-th entry maps to polynomial slot `NUM_NON_GATE_SELECTORS + i`. This must match the
45+
* gate-selector order in the Ultra flavor's `PrecomputedEntities`, and (by `BB_ASSERT` in the
46+
* constructor) the block-traversal order of `get_gate_blocks()`.
47+
*/
48+
static constexpr std::array<GateKind, 8> GATE_SELECTOR_LAYOUT = {
49+
GateKind::Lookup, GateKind::Arith, GateKind::DeltaRange, GateKind::Elliptic,
50+
GateKind::Memory, GateKind::Nnf, GateKind::Poseidon2Ext, GateKind::Poseidon2Int,
51+
};
52+
53+
static_assert(
54+
[]() {
55+
for (size_t i = 0; i < GATE_SELECTOR_LAYOUT.size(); ++i) {
56+
if (GATE_SELECTOR_LAYOUT[i] == GateKind::None) {
57+
return false;
58+
}
59+
for (size_t j = i + 1; j < GATE_SELECTOR_LAYOUT.size(); ++j) {
60+
if (GATE_SELECTOR_LAYOUT[i] == GATE_SELECTOR_LAYOUT[j]) {
61+
return false;
62+
}
63+
}
64+
}
65+
return true;
66+
}(),
67+
"GATE_SELECTOR_LAYOUT must contain no GateKind::None and no duplicates");
68+
4169
UltraTraceBlockData()
4270
{
4371
// pub_inputs has no gate selector; kind defaults to None.
@@ -53,32 +81,18 @@ struct UltraTraceBlockData {
5381

5482
/**
5583
* @brief Map a `GateKind` to its polynomial-array index for the Ultra arithmetization.
56-
* @details The first 6 polynomial slots are non-gate selectors (q_m, q_c, q_1..q_4); the next
57-
* 8 are the Ultra gate selectors in the order [lookup, arith, delta_range, elliptic, memory,
58-
* nnf, poseidon2_ext, poseidon2_int]. Returns `SIZE_MAX` for `GateKind::None`.
84+
* @details The first `UltraTraceBlock::NUM_NON_GATE_SELECTORS` polynomial slots are non-gate
85+
* selectors; gate selectors follow in `GATE_SELECTOR_LAYOUT` order. Returns `SIZE_MAX` for
86+
* `GateKind::None` (no block with that kind owns a gate selector).
5987
*/
6088
static constexpr size_t gate_kind_to_polynomial_idx(GateKind k)
6189
{
62-
switch (k) {
63-
case GateKind::Lookup:
64-
return 6;
65-
case GateKind::Arith:
66-
return 7;
67-
case GateKind::DeltaRange:
68-
return 8;
69-
case GateKind::Elliptic:
70-
return 9;
71-
case GateKind::Memory:
72-
return 10;
73-
case GateKind::Nnf:
74-
return 11;
75-
case GateKind::Poseidon2Ext:
76-
return 12;
77-
case GateKind::Poseidon2Int:
78-
return 13;
79-
default:
80-
return SIZE_MAX;
90+
for (size_t i = 0; i < GATE_SELECTOR_LAYOUT.size(); ++i) {
91+
if (GATE_SELECTOR_LAYOUT[i] == k) {
92+
return UltraTraceBlock::NUM_NON_GATE_SELECTORS + i;
93+
}
8194
}
95+
return SIZE_MAX;
8296
}
8397

8498
auto get()
@@ -124,6 +138,17 @@ struct UltraTraceBlockData {
124138
bool operator==(const UltraTraceBlockData& other) const = default;
125139
};
126140

141+
// Every kind set on an Ultra block must have a polynomial slot in GATE_SELECTOR_LAYOUT, otherwise
142+
// that block's gate-selector data would be silently dropped at routing time.
143+
static_assert(UltraTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Lookup) != SIZE_MAX);
144+
static_assert(UltraTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Arith) != SIZE_MAX);
145+
static_assert(UltraTraceBlockData::gate_kind_to_polynomial_idx(GateKind::DeltaRange) != SIZE_MAX);
146+
static_assert(UltraTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Elliptic) != SIZE_MAX);
147+
static_assert(UltraTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Memory) != SIZE_MAX);
148+
static_assert(UltraTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Nnf) != SIZE_MAX);
149+
static_assert(UltraTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Poseidon2Ext) != SIZE_MAX);
150+
static_assert(UltraTraceBlockData::gate_kind_to_polynomial_idx(GateKind::Poseidon2Int) != SIZE_MAX);
151+
127152
class UltraExecutionTraceBlocks : public UltraTraceBlockData {
128153

129154
public:

barretenberg/cpp/src/barretenberg/trace_to_polynomials/trace_to_polynomials.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,24 +118,30 @@ std::vector<CyclicPermutation> TraceToPolynomials<Flavor>::populate_wires_and_se
118118

119119
// Phase 2: copy each block's selectors into the prover-polynomial selector array.
120120
//
121-
// Non-gate selectors (q_m, q_c, q_1..q_4) sit at fixed polynomial slots 0..5; the optional gate
122-
// selector (one per block) routes to a kind-mapped slot. Blocks with `kind == None` (pub_inputs,
123-
// Mega's ecc_op) skip the gate copy entirely — no zero-fill needed since the destination polys
124-
// were zero-initialised in `allocate_selectors`. Parallelism is over `(block, selector_slot)`
125-
// pairs so the work distributes across cores rather than being bottlenecked at ~10 blocks.
121+
// Non-gate selectors (q_m, q_c, q_1..q_4) sit at fixed polynomial slots
122+
// 0..NUM_NON_GATE_SELECTORS-1; the optional gate selector (one per block) routes to a
123+
// kind-mapped slot. Blocks with `kind == None` (pub_inputs, Mega's ecc_op) skip the gate copy
124+
// entirely — no zero-fill needed since the destination polys were zero-initialised in
125+
// `allocate_selectors`. Parallelism is over `(block, selector_slot)` pairs so the work
126+
// distributes across cores rather than being bottlenecked at ~10 blocks.
126127
{
127128
BB_BENCH_NAME("populate_selectors");
128-
constexpr size_t SLOTS_PER_BLOCK = 7; // 6 non-gate + at most 1 gate
129+
using Block = std::remove_reference_t<decltype(blocks_array[0])>;
130+
constexpr size_t SLOTS_PER_BLOCK = Block::MAX_SELECTORS;
131+
constexpr size_t NUM_NON_GATE = Block::NUM_NON_GATE_SELECTORS;
129132
parallel_for(num_blocks * SLOTS_PER_BLOCK, [&](size_t task_idx) {
130133
const size_t block_idx = task_idx / SLOTS_PER_BLOCK;
131134
const size_t s = task_idx % SLOTS_PER_BLOCK;
132135
auto& block = blocks_array[block_idx];
133136
auto block_selectors = block.get_selectors();
134-
// get_selectors() returns 6 entries for kind=None blocks; skip the gate slot for those.
137+
BB_ASSERT_LTE(block_selectors.size(), SLOTS_PER_BLOCK);
138+
// get_selectors() returns NUM_NON_GATE entries for kind=None blocks; skip the gate slot
139+
// for those (its `s` value is past the end).
135140
if (s >= block_selectors.size()) {
136141
return;
137142
}
138-
const size_t dest = (s < 6) ? s : Builder::ExecutionTrace::gate_kind_to_polynomial_idx(block.kind);
143+
const size_t dest =
144+
(s < NUM_NON_GATE) ? s : Builder::ExecutionTrace::gate_kind_to_polynomial_idx(block.kind);
139145
auto& src = block_selectors[s];
140146
const size_t offset = block.trace_offset();
141147
const size_t block_size = block.size();

0 commit comments

Comments
 (0)