19 const Parameters& params)
23 const auto precompute_round = View(in.precompute_round);
24 const auto precompute_round2 = precompute_round + precompute_round;
25 const auto precompute_round4 = precompute_round2 + precompute_round2;
27 const auto& gamma = params.gamma;
28 const auto& beta = params.beta;
29 const auto& beta_sqr = params.beta_sqr;
30 const auto& beta_cube = params.beta_cube;
31 const auto& beta_quartic = params.beta_quartic;
32 const auto precompute_pc = View(in.precompute_pc);
33 const auto precompute_select = View(in.precompute_select);
35 const auto first_term_tag = beta_quartic * Base::FIRST_TERM_TAG;
36 const auto second_term_tag = beta_quartic * Base::SECOND_TERM_TAG;
37 const auto third_term_tag = beta_quartic * Base::THIRD_TERM_TAG;
39 const auto make_wnaf_input = [&](
const auto& hi,
const auto& lo,
const auto& round_offset) {
40 auto wnaf_slice = hi + hi;
41 wnaf_slice += wnaf_slice;
43 return wnaf_slice + gamma + precompute_pc * beta + (precompute_round4 + round_offset) * beta_sqr +
47 const auto wnaf_slice_input0 = make_wnaf_input(View(in.precompute_s1hi), View(in.precompute_s1lo),
FF(0));
48 const auto wnaf_slice_input1 = make_wnaf_input(View(in.precompute_s2hi), View(in.precompute_s2lo),
FF(1));
49 const auto wnaf_slice_input2 = make_wnaf_input(View(in.precompute_s3hi), View(in.precompute_s3lo),
FF(2));
50 const auto wnaf_slice_input3 = make_wnaf_input(View(in.precompute_s4hi), View(in.precompute_s4lo),
FF(3));
53 Accumulator(wnaf_slice_input0 * wnaf_slice_input1) * Accumulator(wnaf_slice_input2 * wnaf_slice_input3);
55 const auto skew = View(in.precompute_skew);
56 const auto precompute_point_transition = View(in.precompute_point_transition);
57 const auto skew_linear =
58 skew + gamma + precompute_pc * beta + (precompute_round4 +
FF(4)) * beta_sqr + first_term_tag;
59 const auto skew_input = precompute_point_transition * skew_linear + (-precompute_point_transition + 1);
60 numerator *= Accumulator(skew_input);
62 const auto& eccvm_set_permutation_delta = params.eccvm_set_permutation_delta;
63 const auto precompute_select_factor =
64 precompute_select * (-eccvm_set_permutation_delta + 1) + eccvm_set_permutation_delta;
65 numerator *= Accumulator(precompute_select_factor);
67 const auto table_x = View(in.precompute_tx);
68 const auto table_y = View(in.precompute_ty);
69 const auto precompute_skew = View(in.precompute_skew);
70 const auto negative_inverse_seven = []() {
72 static constexpr FF negative_inverse_seven =
FF(-7).
invert();
73 return negative_inverse_seven;
76 return negative_inverse_seven;
79 auto adjusted_skew = precompute_skew * negative_inverse_seven();
81 const auto wnaf_scalar_sum = View(in.precompute_scalar_sum);
82 const auto w0 = convert_to_wnaf<Accumulator>(View(in.precompute_s1hi), View(in.precompute_s1lo));
83 const auto w1 = convert_to_wnaf<Accumulator>(View(in.precompute_s2hi), View(in.precompute_s2lo));
84 const auto w2 = convert_to_wnaf<Accumulator>(View(in.precompute_s3hi), View(in.precompute_s3lo));
85 const auto w3 = convert_to_wnaf<Accumulator>(View(in.precompute_s4hi), View(in.precompute_s4lo));
88 row_slice += row_slice;
89 row_slice += row_slice;
90 row_slice += row_slice;
91 row_slice += row_slice;
93 row_slice += row_slice;
94 row_slice += row_slice;
95 row_slice += row_slice;
96 row_slice += row_slice;
98 row_slice += row_slice;
99 row_slice += row_slice;
100 row_slice += row_slice;
101 row_slice += row_slice;
104 auto scalar_sum_full = wnaf_scalar_sum *
FF(1ULL << 16);
105 scalar_sum_full += row_slice + adjusted_skew;
107 auto point_table_init_read_linear =
108 precompute_pc + table_x * beta + table_y * beta_sqr + scalar_sum_full * beta_cube + second_term_tag;
109 auto point_table_init_read =
110 precompute_point_transition * (point_table_init_read_linear + gamma) + (-precompute_point_transition + 1);
111 numerator *= Accumulator(point_table_init_read);
113 const auto lagrange_first = View(in.lagrange_first);
114 const auto partial_msm_transition_shift = View(in.msm_transition_shift);
115 const auto msm_transition_shift = (-lagrange_first + 1) * partial_msm_transition_shift;
116 const auto msm_pc_shift = View(in.msm_pc_shift);
117 const auto msm_x_shift = View(in.msm_accumulator_x_shift);
118 const auto msm_y_shift = View(in.msm_accumulator_y_shift);
119 const auto msm_size = View(in.msm_size_of_msm);
121 auto msm_result_write_linear =
122 msm_pc_shift + msm_x_shift * beta + msm_y_shift * beta_sqr + msm_size * beta_cube + third_term_tag;
123 auto msm_result_write = Accumulator(msm_transition_shift) * Accumulator(msm_result_write_linear + gamma) +
124 Accumulator(-msm_transition_shift + 1);
125 numerator *= msm_result_write;
133 const Parameters& params)
137 const auto& gamma = params.gamma;
138 const auto& beta = params.beta;
139 const auto& beta_sqr = params.beta_sqr;
140 const auto& beta_cube = params.beta_cube;
141 const auto& beta_quartic = params.beta_quartic;
142 const auto msm_pc = View(in.msm_pc);
143 const auto msm_count = View(in.msm_count);
144 const auto msm_round = View(in.msm_round);
146 const auto first_term_tag = beta_quartic * Base::FIRST_TERM_TAG;
147 const auto second_term_tag = beta_quartic * Base::SECOND_TERM_TAG;
148 const auto third_term_tag = beta_quartic * Base::THIRD_TERM_TAG;
150 const auto make_wnaf_output = [&](
const auto& add,
const auto&
slice,
const auto& count_offset) {
152 slice + gamma + (msm_pc - msm_count - count_offset) * beta + msm_round * beta_sqr + first_term_tag;
153 return add * input + (-add + 1);
156 const auto wnaf_slice_output1 = make_wnaf_output(View(in.msm_add1), View(in.msm_slice1),
FF(0));
157 const auto wnaf_slice_output2 = make_wnaf_output(View(in.msm_add2), View(in.msm_slice2),
FF(1));
158 const auto wnaf_slice_output3 = make_wnaf_output(View(in.msm_add3), View(in.msm_slice3),
FF(2));
159 const auto wnaf_slice_output4 = make_wnaf_output(View(in.msm_add4), View(in.msm_slice4),
FF(3));
161 auto denominator = Accumulator(wnaf_slice_output1) * Accumulator(wnaf_slice_output2);
162 denominator *= Accumulator(wnaf_slice_output3);
163 denominator *= Accumulator(wnaf_slice_output4);
165 const auto transcript_pc = View(in.transcript_pc);
166 const auto transcript_Px = View(in.transcript_Px);
167 const auto transcript_Py = View(in.transcript_Py);
168 const auto z1 = View(in.transcript_z1);
169 const auto z2 = View(in.transcript_z2);
170 const auto z1_zero = View(in.transcript_z1zero);
171 const auto z2_zero = View(in.transcript_z2zero);
172 const auto base_infinity = View(in.transcript_base_infinity);
173 const auto transcript_mul = View(in.transcript_mul);
175 const auto lookup_first = -z1_zero + 1;
176 const auto lookup_second = -z2_zero + 1;
179 auto transcript_input1_linear =
180 transcript_pc + transcript_Px * beta + transcript_Py * beta_sqr + z1 * beta_cube + second_term_tag;
181 auto transcript_input2_linear = (transcript_pc - lookup_first) + transcript_Px * cube_root_unity * beta -
182 transcript_Py * beta_sqr + z2 * beta_cube + second_term_tag;
184 auto transcript_input1 = (transcript_input1_linear + gamma) * lookup_first + (-lookup_first + 1);
185 auto transcript_input2 = (transcript_input2_linear + gamma) * lookup_second + (-lookup_second + 1);
187 auto transcript_product = Accumulator(transcript_input1) * Accumulator(transcript_input2);
188 transcript_product *= Accumulator(-base_infinity + 1);
189 transcript_product += Accumulator(base_infinity);
191 auto point_table_init_write = Accumulator(transcript_mul) * transcript_product + Accumulator(-transcript_mul + 1);
192 denominator *= point_table_init_write;
194 const auto transcript_pc_shift = View(in.transcript_pc_shift);
195 const auto transcript_msm_x = View(in.transcript_msm_x);
196 const auto transcript_msm_y = View(in.transcript_msm_y);
197 const auto transcript_msm_transition = View(in.transcript_msm_transition);
198 const auto transcript_msm_count = View(in.transcript_msm_count);
200 auto full_msm_count = Accumulator(transcript_msm_count);
201 full_msm_count += Accumulator(transcript_mul * (lookup_first + lookup_second)) * Accumulator(-base_infinity + 1);
203 auto msm_result_read =
204 Accumulator(transcript_pc_shift + transcript_msm_x * beta + transcript_msm_y * beta_sqr + third_term_tag);
205 msm_result_read += full_msm_count * beta_cube;
206 msm_result_read += gamma;
208 Accumulator(transcript_msm_transition) * msm_result_read + Accumulator(-transcript_msm_transition + 1);
209 denominator *= msm_result_read;
217 const AllEntities& in,
218 const Parameters& params,
219 const FF& scaling_factor)
224 GrandProductAccumulator numerator_evaluation = compute_grand_product_numerator<GrandProductAccumulator>(in, params);
225 GrandProductAccumulator denominator_evaluation =
226 compute_grand_product_denominator<GrandProductAccumulator>(in, params);
228 const auto z_perm = GrandProductView(in.z_perm);
229 const auto z_perm_shift = GrandProductView(in.z_perm_shift);
230 const auto lagrange_first = GrandProductView(in.lagrange_first);
231 const auto lagrange_last = GrandProductView(in.lagrange_last);
233 const auto z_perm_and_first_scaled = (z_perm + lagrange_first) * scaling_factor;
234 const auto z_perm_shift_and_last_scaled = (z_perm_shift + lagrange_last) * scaling_factor;
236 GrandProductAccumulator(z_perm_and_first_scaled) * numerator_evaluation -
237 GrandProductAccumulator(z_perm_shift_and_last_scaled) * denominator_evaluation;
241 const auto lagrange_last_short = LeftShiftableView(in.lagrange_last);
242 const auto z_perm_shift_short = LeftShiftableView(in.z_perm_shift);
244 LeftShiftableAccumulator((lagrange_last_short * z_perm_shift_short) * scaling_factor);
248 const auto lagrange_first_init = InitView(in.lagrange_first);
249 const auto z_perm_init = InitView(in.z_perm);