141 const uint32_t total_number_of_muls)
143 const size_t num_vm_entries = vm_operations.size();
145 const size_t transcript_size = num_vm_entries + 2;
151 std::vector<FF> inverse_trace_x(num_vm_entries);
152 std::vector<FF> inverse_trace_y(num_vm_entries);
153 std::vector<FF> transcript_msm_x_inverse_trace(num_vm_entries);
154 std::vector<FF> add_lambda_denominator(num_vm_entries);
155 std::vector<FF> add_lambda_numerator(num_vm_entries);
156 std::vector<FF> msm_count_at_transition_inverse_trace(num_vm_entries);
166 .
pc = total_number_of_muls,
170 .is_accumulator_empty =
true,
190 hiding_row.
pc = state.pc;
193 accumulator_trace[0] = state.accumulator;
194 msm_accumulator_trace[0] = Element::infinity();
195 intermediate_accumulator_trace[0] = Element::infinity();
196 msm_count_at_transition_inverse_trace[0] = 0;
202 for (
size_t i = 1; i < num_vm_entries; i++) {
206 updated_state = state;
210 const bool z1_zero = is_mul ? entry.
z1 == 0 :
true;
211 const bool z2_zero = is_mul ? entry.
z2 == 0 :
true;
213 const bool base_point_infinity = entry.
base_point.is_point_at_infinity();
214 uint32_t num_muls = 0;
217 num_muls =
static_cast<uint32_t
>(!z1_zero) +
static_cast<uint32_t
>(!z2_zero);
218 if (base_point_infinity) {
222 updated_state.
pc = state.pc - num_muls;
232 const bool last_row = (i == (num_vm_entries - 1));
234 const bool next_not_msm = last_row || !vm_operations[i + 1].op_code.mul;
240 const bool msm_transition = is_mul && next_not_msm && (state.count + num_muls > 0);
243 const bool current_ongoing_msm = is_mul && !next_not_msm;
245 updated_state.
count = current_ongoing_msm ? state.count + num_muls : 0;
254 if (msm_transition) {
257 msm_accumulator_trace[i] = Element::infinity();
258 intermediate_accumulator_trace[i] = Element::infinity();
268 msm_count_at_transition_inverse_trace[i] = ((state.count + num_muls) == 0) ? 0 :
FF(state.count + num_muls);
272 accumulator_trace[i] = state.accumulator;
273 msm_accumulator_trace[i] = msm_transition ? updated_state.
msm_accumulator : Element::infinity();
274 intermediate_accumulator_trace[i] =
277 state = updated_state;
279 if (is_mul && next_not_msm) {
288 transcript_state, accumulator_trace, msm_accumulator_trace, intermediate_accumulator_trace);
292 for (
size_t i = 0; i < accumulator_trace.size(); ++i) {
299 if (msm_transition || is_add) {
303 intermediate_accumulator_trace[i],
304 transcript_msm_x_inverse_trace[i],
305 msm_accumulator_trace[i],
306 accumulator_trace[i],
313 intermediate_accumulator_trace[i],
314 accumulator_trace[i],
315 add_lambda_numerator[i],
316 add_lambda_denominator[i]);
320 add_lambda_numerator[i] = 0;
321 add_lambda_denominator[i] = 0;
322 inverse_trace_x[i] = 0;
323 inverse_trace_y[i] = 0;
332 FF::batch_invert(&msm_count_at_transition_inverse_trace[0], num_vm_entries);
335 for (
size_t i = 0; i < num_vm_entries; ++i) {
347 return transcript_state;
597 const Element& intermediate_accumulator,
599 FF& add_lambda_numerator,
600 FF& add_lambda_denominator)
604 const bool vm_infinity = vm_point.is_point_at_infinity();
605 const bool accumulator_infinity = accumulator.is_point_at_infinity();
608 const FF vm_x = vm_infinity ? 0 : vm_point.x;
609 const FF vm_y = vm_infinity ? 0 : vm_point.y;
612 const FF accumulator_x = accumulator_infinity ? 0 : accumulator.x;
613 const FF accumulator_y = accumulator_infinity ? 0 : accumulator.y;
619 if ((accumulator_x == vm_x) && (accumulator_y == vm_y) && !vm_infinity && !accumulator_infinity) {
621 add_lambda_denominator = vm_y + vm_y;
622 add_lambda_numerator = vm_x * vm_x * 3;
623 }
else if ((accumulator_x != vm_x) && !vm_infinity && !accumulator_infinity) {
625 add_lambda_denominator = accumulator_x - vm_x;
626 add_lambda_numerator = accumulator_y - vm_y;