64 const auto compute_precomputed_table =
93 const auto compute_wnaf_digits = [](
uint256_t scalar) -> std::array<int, NUM_WNAF_DIGITS_PER_SCALAR> {
94 std::array<int, NUM_WNAF_DIGITS_PER_SCALAR> output;
95 int previous_slice = 0;
98 uint64_t raw_slice =
static_cast<uint64_t
>(scalar) &
WNAF_MASK;
100 bool is_even = ((raw_slice & 1ULL) == 0ULL);
102 int wnaf_slice =
static_cast<int>(raw_slice);
104 if (i == 0 && is_even) {
107 }
else if (is_even) {
111 previous_slice -= borrow_constant;
116 const size_t idx = i - 1;
119 previous_slice = wnaf_slice;
127 output[0] = previous_slice;
137 size_t msm_count = 0;
138 size_t active_mul_count =
151 std::vector<size_t> msm_sizes;
153 const auto& eccvm_ops =
op_queue->get_eccvm_ops();
156 for (
const auto& op : eccvm_ops) {
157 if (op.op_code.mul) {
158 if ((op.z1 != 0 || op.z2 != 0) && !op.base_point.is_point_at_infinity()) {
159 msm_opqueue_index.push_back(op_idx);
160 msm_mul_index.emplace_back(msm_count, active_mul_count);
161 active_mul_count +=
static_cast<size_t>(op.z1 != 0) +
static_cast<size_t>(op.z2 != 0);
163 }
else if (active_mul_count > 0) {
164 msm_sizes.push_back(active_mul_count);
166 active_mul_count = 0;
171 if (!eccvm_ops.empty() && eccvm_ops.back().op_code.mul && active_mul_count > 0) {
172 msm_sizes.push_back(active_mul_count);
180 for (
size_t i = 0; i < msm_count; ++i) {
181 auto& msm = result[i];
182 msm.resize(msm_sizes[i]);
188 for (size_t i = start; i < end; i++) {
189 const auto& op = eccvm_ops[msm_opqueue_index[i]];
190 auto [msm_index, mul_index] = msm_mul_index[i];
191 if (op.z1 != 0 && !op.base_point.is_point_at_infinity()) {
192 BB_ASSERT_GT(result.size(), msm_index);
193 BB_ASSERT_GT(result[msm_index].size(), mul_index);
194 result[msm_index][mul_index] = (ScalarMul{
197 .base_point = op.base_point,
198 .wnaf_digits = compute_wnaf_digits(op.z1),
199 .wnaf_skew = (op.z1 & 1) == 0,
200 .precomputed_table = compute_precomputed_table(op.base_point),
204 if (op.z2 != 0 && !op.base_point.is_point_at_infinity()) {
205 BB_ASSERT_GT(result.size(), msm_index);
206 BB_ASSERT_GT(result[msm_index].size(), mul_index);
207 auto endo_point = AffineElement{ op.base_point.x * FF::cube_root_of_unity(), -op.base_point.y };
208 result[msm_index][mul_index] = (ScalarMul{
211 .base_point = endo_point,
212 .wnaf_digits = compute_wnaf_digits(op.z2),
213 .wnaf_skew = (op.z2 & 1) == 0,
214 .precomputed_table = compute_precomputed_table(endo_point),
230 uint32_t pc = num_muls;
231 for (
auto& msm : result) {
232 for (
auto& mul : msm) {