Skip to content

Commit 40306b6

Browse files
authored
refactor: Make MSM builder more explicit (#6110)
After trying to understand the MSM builder part of the ECCVM builder, I did a refactor for clarity. This is almost entirely naming (e.g we had sometimes 4+ indices `i, j, k, m, idx` in deeply nested loops that I gave more explicit names) and comments. I also made the function that computes the trace rows return a table rather than to mutate one since there was no real reason to take the latter pattern.
1 parent cd05b91 commit 40306b6

7 files changed

Lines changed: 392 additions & 388 deletions

File tree

barretenberg/cpp/src/barretenberg/eccvm/eccvm_builder_types.hpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,12 @@
44
#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp"
55

66
namespace bb::eccvm {
7-
8-
static constexpr size_t NUM_SCALAR_BITS = 128;
9-
static constexpr size_t WNAF_SLICE_BITS = 4;
10-
static constexpr size_t NUM_WNAF_SLICES = (NUM_SCALAR_BITS + WNAF_SLICE_BITS - 1) / WNAF_SLICE_BITS;
11-
static constexpr uint64_t WNAF_MASK = static_cast<uint64_t>((1ULL << WNAF_SLICE_BITS) - 1ULL);
12-
static constexpr size_t POINT_TABLE_SIZE = 1ULL << (WNAF_SLICE_BITS);
13-
static constexpr size_t WNAF_SLICES_PER_ROW = 4;
7+
static constexpr size_t NUM_SCALAR_BITS = 128; // The length of scalars handled by the ECCVVM
8+
static constexpr size_t NUM_WNAF_DIGIT_BITS = 4; // Scalars are decompose into base 16 in wNAF form
9+
static constexpr size_t NUM_WNAF_DIGITS_PER_SCALAR = NUM_SCALAR_BITS / NUM_WNAF_DIGIT_BITS; // 32
10+
static constexpr uint64_t WNAF_MASK = static_cast<uint64_t>((1ULL << NUM_WNAF_DIGIT_BITS) - 1ULL);
11+
static constexpr size_t POINT_TABLE_SIZE = 1ULL << (NUM_WNAF_DIGIT_BITS);
12+
static constexpr size_t WNAF_DIGITS_PER_ROW = 4;
1413
static constexpr size_t ADDITIONS_PER_ROW = 4;
1514

1615
template <typename CycleGroup> struct VMOperation {
@@ -39,7 +38,7 @@ template <typename CycleGroup> struct ScalarMul {
3938
uint32_t pc;
4039
uint256_t scalar;
4140
typename CycleGroup::affine_element base_point;
42-
std::array<int, NUM_WNAF_SLICES> wnaf_slices;
41+
std::array<int, NUM_WNAF_DIGITS_PER_SCALAR> wnaf_digits;
4342
bool wnaf_skew;
4443
// size bumped by 1 to record base_point.dbl()
4544
std::array<typename CycleGroup::affine_element, POINT_TABLE_SIZE + 1> precomputed_table;

barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@ class ECCVMCircuitBuilder {
2424
using AffineElement = typename CycleGroup::affine_element;
2525

2626
static constexpr size_t NUM_SCALAR_BITS = bb::eccvm::NUM_SCALAR_BITS;
27-
static constexpr size_t WNAF_SLICE_BITS = bb::eccvm::WNAF_SLICE_BITS;
28-
static constexpr size_t NUM_WNAF_SLICES = bb::eccvm::NUM_WNAF_SLICES;
27+
static constexpr size_t NUM_WNAF_DIGIT_BITS = bb::eccvm::NUM_WNAF_DIGIT_BITS;
28+
static constexpr size_t NUM_WNAF_DIGITS_PER_SCALAR = bb::eccvm::NUM_WNAF_DIGITS_PER_SCALAR;
2929
static constexpr uint64_t WNAF_MASK = bb::eccvm::WNAF_MASK;
3030
static constexpr size_t POINT_TABLE_SIZE = bb::eccvm::POINT_TABLE_SIZE;
31-
static constexpr size_t WNAF_SLICES_PER_ROW = bb::eccvm::WNAF_SLICES_PER_ROW;
31+
static constexpr size_t WNAF_DIGITS_PER_ROW = bb::eccvm::WNAF_DIGITS_PER_ROW;
3232
static constexpr size_t ADDITIONS_PER_ROW = bb::eccvm::ADDITIONS_PER_ROW;
3333

3434
using MSM = bb::eccvm::MSM<CycleGroup>;
@@ -50,7 +50,8 @@ class ECCVMCircuitBuilder {
5050
/**
5151
* For input point [P], return { -15[P], -13[P], ..., -[P], [P], ..., 13[P], 15[P] }
5252
*/
53-
const auto compute_precomputed_table = [](const AffineElement& base_point) {
53+
const auto compute_precomputed_table =
54+
[](const AffineElement& base_point) -> std::array<AffineElement, POINT_TABLE_SIZE + 1> {
5455
const auto d2 = Element(base_point).dbl();
5556
std::array<Element, POINT_TABLE_SIZE + 1> table;
5657
table[POINT_TABLE_SIZE] = d2; // need this for later
@@ -69,10 +70,10 @@ class ECCVMCircuitBuilder {
6970
}
7071
return result;
7172
};
72-
const auto compute_wnaf_slices = [](uint256_t scalar) {
73-
std::array<int, NUM_WNAF_SLICES> output;
73+
const auto compute_wnaf_digits = [](uint256_t scalar) -> std::array<int, NUM_WNAF_DIGITS_PER_SCALAR> {
74+
std::array<int, NUM_WNAF_DIGITS_PER_SCALAR> output;
7475
int previous_slice = 0;
75-
for (size_t i = 0; i < NUM_WNAF_SLICES; ++i) {
76+
for (size_t i = 0; i < NUM_WNAF_DIGITS_PER_SCALAR; ++i) {
7677
// slice the scalar into 4-bit chunks, starting with the least significant bits
7778
uint64_t raw_slice = static_cast<uint64_t>(scalar) & WNAF_MASK;
7879

@@ -86,19 +87,19 @@ class ECCVMCircuitBuilder {
8687
} else if (is_even) {
8788
// for other slices, if it's even, we add 1 to the slice value
8889
// and subtract 16 from the previous slice to preserve the total scalar sum
89-
static constexpr int borrow_constant = static_cast<int>(1ULL << WNAF_SLICE_BITS);
90+
static constexpr int borrow_constant = static_cast<int>(1ULL << NUM_WNAF_DIGIT_BITS);
9091
previous_slice -= borrow_constant;
9192
wnaf_slice += 1;
9293
}
9394

9495
if (i > 0) {
9596
const size_t idx = i - 1;
96-
output[NUM_WNAF_SLICES - idx - 1] = previous_slice;
97+
output[NUM_WNAF_DIGITS_PER_SCALAR - idx - 1] = previous_slice;
9798
}
9899
previous_slice = wnaf_slice;
99100

100101
// downshift raw_slice by 4 bits
101-
scalar = scalar >> WNAF_SLICE_BITS;
102+
scalar = scalar >> NUM_WNAF_DIGIT_BITS;
102103
}
103104

104105
ASSERT(scalar == 0);
@@ -108,8 +109,6 @@ class ECCVMCircuitBuilder {
108109
return output;
109110
};
110111

111-
// a vector of MSMs = a vector of a vector of scalar muls
112-
// each mul
113112
size_t msm_count = 0;
114113
size_t active_mul_count = 0;
115114
std::vector<size_t> msm_opqueue_index;
@@ -118,6 +117,7 @@ class ECCVMCircuitBuilder {
118117

119118
const auto& raw_ops = op_queue->get_raw_ops();
120119
size_t op_idx = 0;
120+
// populate opqueue and mul indices
121121
for (const auto& op : raw_ops) {
122122
if (op.mul) {
123123
if (op.z1 != 0 || op.z2 != 0) {
@@ -142,39 +142,38 @@ class ECCVMCircuitBuilder {
142142
msm_sizes.push_back(active_mul_count);
143143
msm_count++;
144144
}
145-
std::vector<MSM> msms_test(msm_count);
145+
std::vector<MSM> result(msm_count);
146146
for (size_t i = 0; i < msm_count; ++i) {
147-
auto& msm = msms_test[i];
147+
auto& msm = result[i];
148148
msm.resize(msm_sizes[i]);
149149
}
150150

151151
run_loop_in_parallel(msm_opqueue_index.size(), [&](size_t start, size_t end) {
152152
for (size_t i = start; i < end; i++) {
153-
const size_t opqueue_index = msm_opqueue_index[i];
154-
const auto& op = raw_ops[opqueue_index];
153+
const auto& op = raw_ops[msm_opqueue_index[i]];
155154
auto [msm_index, mul_index] = msm_mul_index[i];
156155
if (op.z1 != 0) {
157-
ASSERT(msms_test.size() > msm_index);
158-
ASSERT(msms_test[msm_index].size() > mul_index);
159-
msms_test[msm_index][mul_index] = (ScalarMul{
156+
ASSERT(result.size() > msm_index);
157+
ASSERT(result[msm_index].size() > mul_index);
158+
result[msm_index][mul_index] = (ScalarMul{
160159
.pc = 0,
161160
.scalar = op.z1,
162161
.base_point = op.base_point,
163-
.wnaf_slices = compute_wnaf_slices(op.z1),
162+
.wnaf_digits = compute_wnaf_digits(op.z1),
164163
.wnaf_skew = (op.z1 & 1) == 0,
165164
.precomputed_table = compute_precomputed_table(op.base_point),
166165
});
167166
mul_index++;
168167
}
169168
if (op.z2 != 0) {
170-
ASSERT(msms_test.size() > msm_index);
171-
ASSERT(msms_test[msm_index].size() > mul_index);
169+
ASSERT(result.size() > msm_index);
170+
ASSERT(result[msm_index].size() > mul_index);
172171
auto endo_point = AffineElement{ op.base_point.x * FF::cube_root_of_unity(), -op.base_point.y };
173-
msms_test[msm_index][mul_index] = (ScalarMul{
172+
result[msm_index][mul_index] = (ScalarMul{
174173
.pc = 0,
175174
.scalar = op.z2,
176175
.base_point = endo_point,
177-
.wnaf_slices = compute_wnaf_slices(op.z2),
176+
.wnaf_digits = compute_wnaf_digits(op.z2),
178177
.wnaf_skew = (op.z2 & 1) == 0,
179178
.precomputed_table = compute_precomputed_table(endo_point),
180179
});
@@ -191,15 +190,15 @@ class ECCVMCircuitBuilder {
191190
// sumcheck relations that involve pc (if we did the other way around, starting at 1 and ending at num_muls,
192191
// we create a discontinuity in pc values between the last transcript row and the following empty row)
193192
uint32_t pc = num_muls;
194-
for (auto& msm : msms_test) {
193+
for (auto& msm : result) {
195194
for (auto& mul : msm) {
196195
mul.pc = pc;
197196
pc--;
198197
}
199198
}
200199

201200
ASSERT(pc == 0);
202-
return msms_test;
201+
return result;
203202
}
204203

205204
static std::vector<ScalarMul> get_flattened_scalar_muls(const std::vector<MSM>& msms)

0 commit comments

Comments
 (0)