56 for (
const auto&
event : events) {
61 bool x_match = p.
x() == q.
x();
62 bool y_match = p.
y() == q.
y();
64 bool double_predicate = (x_match && y_match);
65 bool add_predicate = (!x_match && !y_match);
67 bool infinity_predicate = (x_match && !y_match);
76 assert(result_is_infinity == result.
is_infinity() &&
"Inconsistent infinity result assumption");
78 FF lambda = compute_lambda(double_predicate, add_predicate, result_is_infinity, p, q);
84 { C::ecc_p_x, p.
x() },
85 { C::ecc_p_y, p.
y() },
88 { C::ecc_q_x, q.
x() },
89 { C::ecc_q_y, q.
y() },
92 { C::ecc_r_x, result.
x() },
93 { C::ecc_r_y, result.
y() },
97 { C::ecc_use_computed_result, use_computed_result },
100 { C::ecc_x_match, x_match },
101 { C::ecc_inv_x_diff, q.
x() - p.
x() },
102 { C::ecc_y_match, y_match },
103 { C::ecc_inv_y_diff, q.
y() - p.
y() },
106 { C::ecc_double_op, double_predicate },
108 !result_is_infinity && double_predicate ? (p.
y() * 2)
112 { C::ecc_add_op, add_predicate },
115 { C::ecc_result_infinity, result_is_infinity },
117 { C::ecc_lambda, lambda },
124 trace.invert_columns({ { C::ecc_inv_x_diff, C::ecc_inv_y_diff, C::ecc_inv_2_p_y } });
133 for (
const auto&
event : events) {
134 size_t num_intermediate_states =
event.intermediate_states.size();
137 for (
size_t i = 0; i < num_intermediate_states; ++i) {
139 size_t intermediate_state_idx = num_intermediate_states - i - 1;
142 bool is_start = i == 0;
144 bool is_end = intermediate_state_idx == 0;
153 bool bit = state.
bit;
156 { { { C::scalar_mul_sel, 1 },
157 { C::scalar_mul_scalar,
event.scalar },
158 { C::scalar_mul_point_x, point.
x() },
159 { C::scalar_mul_point_y, point.
y() },
161 { C::scalar_mul_res_x, res.
x() },
162 { C::scalar_mul_res_y, res.
y() },
164 { C::scalar_mul_start, is_start },
165 { C::scalar_mul_end, is_end },
166 { C::scalar_mul_not_end, !is_end },
167 { C::scalar_mul_bit, bit },
168 { C::scalar_mul_bit_idx, intermediate_state_idx },
169 { C::scalar_mul_temp_x, temp.
x() },
170 { C::scalar_mul_temp_y, temp.
y() },
173 C::scalar_mul_should_add,
176 { C::scalar_mul_bit_radix, 2 } } });
189 for (
const auto&
event : events) {
190 uint64_t
dst_addr =
static_cast<uint64_t
>(
event.dst_address);
198 bool p_is_on_curve =
event.p.on_curve();
199 FF p_is_on_curve_eqn = compute_curve_eqn_diff(
event.p);
200 FF p_is_on_curve_eqn_inv = p_is_on_curve ?
FF::zero() : p_is_on_curve_eqn.invert();
202 bool q_is_on_curve =
event.q.on_curve();
203 FF q_is_on_curve_eqn = compute_curve_eqn_diff(
event.q);
204 FF q_is_on_curve_eqn_inv = q_is_on_curve ?
FF::zero() : q_is_on_curve_eqn.invert();
206 bool error = dst_out_of_range_err || !p_is_on_curve || !q_is_on_curve;
210 { C::ecc_add_mem_sel, 1 },
211 { C::ecc_add_mem_execution_clk,
event.execution_clk },
212 { C::ecc_add_mem_space_id,
event.space_id },
215 { C::ecc_add_mem_sel_dst_out_of_range_err, dst_out_of_range_err ? 1 : 0 },
217 { C::ecc_add_mem_sel_p_not_on_curve_err, !p_is_on_curve ? 1 : 0 },
218 { C::ecc_add_mem_p_is_on_curve_eqn, p_is_on_curve_eqn },
219 { C::ecc_add_mem_p_is_on_curve_eqn_inv, p_is_on_curve_eqn_inv },
221 { C::ecc_add_mem_sel_q_not_on_curve_err, !q_is_on_curve ? 1 : 0 },
222 { C::ecc_add_mem_q_is_on_curve_eqn, q_is_on_curve_eqn },
223 { C::ecc_add_mem_q_is_on_curve_eqn_inv, q_is_on_curve_eqn_inv },
225 { C::ecc_add_mem_err, error ? 1 : 0 },
227 { C::ecc_add_mem_dst_addr_0_,
dst_addr },
228 { C::ecc_add_mem_dst_addr_1_,
dst_addr + 1 },
229 { C::ecc_add_mem_dst_addr_2_,
dst_addr + 2 },
231 { C::ecc_add_mem_p_x,
event.p.x() },
232 { C::ecc_add_mem_p_y,
event.p.y() },
233 { C::ecc_add_mem_p_is_inf,
event.p.is_infinity() ? 1 : 0 },
235 { C::ecc_add_mem_q_x,
event.q.x() },
236 { C::ecc_add_mem_q_y,
event.q.y() },
237 { C::ecc_add_mem_q_is_inf,
event.q.is_infinity() ? 1 : 0 },
239 { C::ecc_add_mem_sel_should_exec, error ? 0 : 1 },
240 { C::ecc_add_mem_res_x,
event.result.x() },
241 { C::ecc_add_mem_res_y,
event.result.y() },
242 { C::ecc_add_mem_res_is_inf,
event.result.is_infinity() },