1use ark_ff::{fields::arithmetic::InvalidBigInt, BigInteger256, Field};
2use kimchi::proof::{PointEvaluations, ProofEvaluations};
3use mina_p2p_messages::{
4 bigint::BigInt, pseq::PaddedSeq,
5 v2::PicklesReducedMessagesForNextProofOverSameFieldWrapChallengesVectorStableV2A,
6};
7
8use crate::proofs::field::{field, Boolean, FieldWitness};
9
10use super::{
11 public_input::scalar_challenge::ScalarChallenge,
12 step::{Opt, OptFlag},
13 transaction::InnerCurve,
14 witness::Witness,
15};
16
17pub fn extract_polynomial_commitment<
18 'a,
19 F: FieldWitness,
20 I: IntoIterator<Item = &'a (BigInt, BigInt)>,
21>(
22 curves: I,
23) -> Result<Vec<InnerCurve<F>>, InvalidBigInt> {
24 curves
25 .into_iter()
26 .map(|curve| {
27 Ok(InnerCurve::from((
28 curve.0.to_field::<F>()?,
29 curve.1.to_field()?,
30 )))
31 })
32 .collect()
33}
34
35pub fn extract_bulletproof<
36 'a,
37 F: FieldWitness,
38 I: IntoIterator<
39 Item = &'a PaddedSeq<
40 PicklesReducedMessagesForNextProofOverSameFieldWrapChallengesVectorStableV2A,
41 N,
42 >,
43 >,
44 const N: usize,
45>(
46 v: I,
47) -> Vec<[F; N]> {
48 v.into_iter()
49 .map(|old| {
50 old.each_ref().map(|old| {
51 let prechallenge = old.prechallenge.inner.each_ref().map(|v| v.as_u64());
52 ScalarChallenge::limbs_to_field(&prechallenge)
53 })
54 })
55 .collect()
56}
57
58pub fn four_u64_to_field<F>(v: &[u64; 4]) -> Result<F, InvalidBigInt>
59where
60 F: Field + TryFrom<BigInteger256, Error = InvalidBigInt>,
61{
62 let mut bigint: [u64; 4] = [0; 4];
63 bigint[..4].copy_from_slice(v);
64
65 let bigint = BigInteger256::from_64x4(bigint);
66 F::try_from(bigint)
67}
68
69pub fn two_u64_to_field<F>(v: &[u64; 2]) -> F
70where
71 F: Field + TryFrom<BigInteger256, Error = InvalidBigInt>,
72{
73 let mut bigint: [u64; 4] = [0; 4];
74 bigint[..2].copy_from_slice(v);
75
76 let bigint = BigInteger256::from_64x4(bigint);
77 F::try_from(bigint).unwrap() }
79
80pub fn challenge_polynomial<F: FieldWitness>(chals: &[F]) -> impl Fn(F) -> F + '_ {
82 |pt: F| {
83 let k = chals.len();
84 let pow_two_pows = {
85 let mut res = vec![pt; k];
86 for i in 1..k {
87 let y = res[i - 1];
88 res[i] = y * y;
89 }
90 res
91 };
92 fn prod<F: FieldWitness>(k: usize, fun: impl Fn(usize) -> F) -> F {
93 let mut r = fun(0);
94 for i in 1..k {
95 r = fun(i) * r;
96 }
97 r
98 }
99 prod::<F>(k, |i| F::one() + (chals[i] * pow_two_pows[k - 1 - i]))
100 }
101}
102
103pub fn challenge_polynomial_checked<F: FieldWitness>(
105 chals: &[F],
106) -> impl Fn(F, &mut Witness<F>) -> F + '_ {
107 |pt: F, w: &mut Witness<F>| {
108 let k = chals.len();
109 let pow_two_pows = {
110 let mut res = vec![pt; k];
111 for i in 1..k {
112 let y = res[i - 1];
113 res[i] = field::mul(y, y, w);
114 }
115 res
116 };
117 fn prod<F: FieldWitness>(
118 k: usize,
119 fun: impl Fn(usize, &mut Witness<F>) -> F,
120 w: &mut Witness<F>,
121 ) -> F {
122 let mut r = fun(0, w);
123 for i in 1..k {
124 r = field::mul(fun(i, w), r, w);
125 }
126 r
127 }
128 prod(
129 k,
130 |i, w| F::one() + field::mul(chals[i], pow_two_pows[k - 1 - i], w),
131 w,
132 )
133 }
134}
135
136pub fn proof_evaluation_to_list<F: FieldWitness>(
140 e: &ProofEvaluations<PointEvaluations<Vec<F>>>,
141) -> Vec<&PointEvaluations<Vec<F>>> {
142 let ProofEvaluations::<PointEvaluations<Vec<F>>> {
143 public: _,
144 w,
145 z,
146 s,
147 coefficients,
148 generic_selector,
149 poseidon_selector,
150 complete_add_selector,
151 mul_selector,
152 emul_selector,
153 endomul_scalar_selector,
154 range_check0_selector,
155 range_check1_selector,
156 foreign_field_add_selector,
157 foreign_field_mul_selector,
158 xor_selector,
159 rot_selector,
160 lookup_aggregation,
161 lookup_table,
162 lookup_sorted,
163 runtime_lookup_table,
164 runtime_lookup_table_selector,
165 xor_lookup_selector,
166 lookup_gate_lookup_selector,
167 range_check_lookup_selector,
168 foreign_field_mul_lookup_selector,
169 } = e;
170
171 let mut list = vec![
172 z,
173 generic_selector,
174 poseidon_selector,
175 complete_add_selector,
176 mul_selector,
177 emul_selector,
178 endomul_scalar_selector,
179 ];
180
181 list.extend(w);
182 list.extend(coefficients);
183 list.extend(s);
184
185 let optional_gates = [
186 range_check0_selector,
187 range_check1_selector,
188 foreign_field_add_selector,
189 foreign_field_mul_selector,
190 xor_selector,
191 rot_selector,
192 ];
193
194 list.extend(optional_gates.iter().filter_map(|v| (*v).as_ref()));
195 list.extend(lookup_sorted.iter().filter_map(|v| v.as_ref()));
196 list.extend(
197 [
198 lookup_aggregation,
199 lookup_table,
200 runtime_lookup_table,
201 runtime_lookup_table_selector,
202 xor_lookup_selector,
203 lookup_gate_lookup_selector,
204 range_check_lookup_selector,
205 foreign_field_mul_lookup_selector,
206 ]
207 .iter()
208 .filter_map(|v| (*v).as_ref()),
209 );
210
211 list
212}
213
214pub fn proof_evaluation_to_absorption_sequence<F: FieldWitness>(
215 e: &ProofEvaluations<PointEvaluations<Vec<F>>>,
216) -> Vec<&PointEvaluations<Vec<F>>> {
217 let ProofEvaluations {
218 public: _,
219 w,
220 coefficients,
221 z,
222 s,
223 generic_selector,
224 poseidon_selector,
225 complete_add_selector,
226 mul_selector,
227 emul_selector,
228 endomul_scalar_selector,
229 range_check0_selector,
230 range_check1_selector,
231 foreign_field_add_selector,
232 foreign_field_mul_selector,
233 xor_selector,
234 rot_selector,
235 lookup_aggregation,
236 lookup_table,
237 lookup_sorted,
238 runtime_lookup_table,
239 runtime_lookup_table_selector,
240 xor_lookup_selector,
241 lookup_gate_lookup_selector,
242 range_check_lookup_selector,
243 foreign_field_mul_lookup_selector,
244 } = e;
245
246 let mut list = vec![
247 z,
248 generic_selector,
249 poseidon_selector,
250 complete_add_selector,
251 mul_selector,
252 emul_selector,
253 endomul_scalar_selector,
254 ];
255
256 list.extend(w.iter());
257 list.extend(coefficients.iter());
258 list.extend(s.iter());
259
260 list.extend(
261 [
262 range_check0_selector,
263 range_check1_selector,
264 foreign_field_add_selector,
265 foreign_field_mul_selector,
266 xor_selector,
267 rot_selector,
268 lookup_aggregation,
269 lookup_table,
270 ]
271 .into_iter()
272 .filter_map(|v| v.as_ref()),
273 );
274
275 list.extend(lookup_sorted.iter().filter_map(|v| v.as_ref()));
276
277 list.extend(
278 [
279 runtime_lookup_table,
280 runtime_lookup_table_selector,
281 xor_lookup_selector,
282 lookup_gate_lookup_selector,
283 range_check_lookup_selector,
284 foreign_field_mul_lookup_selector,
285 ]
286 .into_iter()
287 .filter_map(|v| v.as_ref()),
288 );
289
290 #[allow(clippy::iter_cloned_collect)]
291 list.iter().cloned().collect()
292}
293
294pub fn proof_evaluation_to_list_opt<F: FieldWitness>(
296 e: &ProofEvaluations<PointEvaluations<Vec<F>>>,
297 hack_feature_flags: OptFlag,
298) -> Vec<Opt<PointEvaluations<Vec<F>>>> {
299 let ProofEvaluations {
300 public: _,
301 w,
302 z,
303 s,
304 coefficients,
305 generic_selector,
306 poseidon_selector,
307 complete_add_selector,
308 mul_selector,
309 emul_selector,
310 endomul_scalar_selector,
311 range_check0_selector,
312 range_check1_selector,
313 foreign_field_add_selector,
314 foreign_field_mul_selector,
315 xor_selector,
316 rot_selector,
317 lookup_aggregation,
318 lookup_table,
319 lookup_sorted,
320 runtime_lookup_table,
321 runtime_lookup_table_selector,
322 xor_lookup_selector,
323 lookup_gate_lookup_selector,
324 range_check_lookup_selector,
325 foreign_field_mul_lookup_selector,
326 } = e;
327
328 let mut list = vec![
329 Opt::Some(z.clone()),
330 Opt::Some(generic_selector.clone()),
331 Opt::Some(poseidon_selector.clone()),
332 Opt::Some(complete_add_selector.clone()),
333 Opt::Some(mul_selector.clone()),
334 Opt::Some(emul_selector.clone()),
335 Opt::Some(endomul_scalar_selector.clone()),
336 ];
337
338 list.extend(w.iter().cloned().map(Opt::Some));
339 list.extend(coefficients.iter().cloned().map(Opt::Some));
340 list.extend(s.iter().cloned().map(Opt::Some));
341
342 let zero = || PointEvaluations {
343 zeta: vec![F::zero()],
344 zeta_omega: vec![F::zero()],
345 };
346 let to_opt = |v: &Option<PointEvaluations<Vec<F>>>| {
347 if let OptFlag::Maybe = hack_feature_flags {
348 match v {
349 Some(v) => Opt::Maybe(Boolean::True, v.clone()),
350 None => Opt::Maybe(Boolean::False, zero()),
351 }
352 } else {
353 match v {
354 Some(v) => Opt::Some(v.clone()),
355 None => Opt::No,
356 }
357 }
358 };
359
360 let optional_gates = [
361 range_check0_selector,
362 range_check1_selector,
363 foreign_field_add_selector,
364 foreign_field_mul_selector,
365 xor_selector,
366 rot_selector,
367 ];
368
369 list.extend(optional_gates.into_iter().map(to_opt));
370 list.extend(lookup_sorted.iter().map(to_opt));
371
372 list.extend(
373 [
374 lookup_aggregation,
375 lookup_table,
376 runtime_lookup_table,
377 runtime_lookup_table_selector,
378 xor_lookup_selector,
379 lookup_gate_lookup_selector,
380 range_check_lookup_selector,
381 foreign_field_mul_lookup_selector,
382 ]
383 .into_iter()
384 .map(to_opt),
385 );
386
387 list
388}
389
390pub fn to_absorption_sequence_opt<F: FieldWitness>(
392 evals: &ProofEvaluations<PointEvaluations<Vec<F>>>,
393 hack_feature_flags: OptFlag,
394) -> Vec<Opt<PointEvaluations<Vec<F>>>> {
395 let ProofEvaluations {
396 public: _,
397 w,
398 coefficients,
399 z,
400 s,
401 generic_selector,
402 poseidon_selector,
403 complete_add_selector,
404 mul_selector,
405 emul_selector,
406 endomul_scalar_selector,
407 range_check0_selector,
408 range_check1_selector,
409 foreign_field_add_selector,
410 foreign_field_mul_selector,
411 xor_selector,
412 rot_selector,
413 lookup_aggregation,
414 lookup_table,
415 lookup_sorted,
416 runtime_lookup_table,
417 runtime_lookup_table_selector,
418 xor_lookup_selector,
419 lookup_gate_lookup_selector,
420 range_check_lookup_selector,
421 foreign_field_mul_lookup_selector,
422 } = evals;
423
424 let mut list = vec![
425 Opt::Some(z.clone()),
426 Opt::Some(generic_selector.clone()),
427 Opt::Some(poseidon_selector.clone()),
428 Opt::Some(complete_add_selector.clone()),
429 Opt::Some(mul_selector.clone()),
430 Opt::Some(emul_selector.clone()),
431 Opt::Some(endomul_scalar_selector.clone()),
432 ];
433
434 list.extend(w.iter().cloned().map(Opt::Some));
435 list.extend(coefficients.iter().cloned().map(Opt::Some));
436 list.extend(s.iter().cloned().map(Opt::Some));
437
438 let zero = || PointEvaluations {
439 zeta: vec![F::zero()],
440 zeta_omega: vec![F::zero()],
441 };
442 let to_opt = |v: &Option<PointEvaluations<Vec<F>>>| {
443 if let OptFlag::Maybe = hack_feature_flags {
444 match v {
445 Some(v) => Opt::Maybe(Boolean::True, v.clone()),
446 None => Opt::Maybe(Boolean::False, zero()),
447 }
448 } else {
449 match v {
450 Some(v) => Opt::Some(v.clone()),
451 None => Opt::No,
452 }
453 }
454 };
455
456 list.extend(
457 [
458 range_check0_selector,
459 range_check1_selector,
460 foreign_field_add_selector,
461 foreign_field_mul_selector,
462 xor_selector,
463 rot_selector,
464 lookup_aggregation,
465 lookup_table,
466 ]
467 .iter()
468 .map(|e| to_opt(e)),
469 );
470
471 list.extend(lookup_sorted.iter().map(to_opt));
472
473 list.extend(
474 [
475 runtime_lookup_table,
476 runtime_lookup_table_selector,
477 xor_lookup_selector,
478 lookup_gate_lookup_selector,
479 range_check_lookup_selector,
480 foreign_field_mul_lookup_selector,
481 ]
482 .into_iter()
483 .map(to_opt),
484 );
485
486 list
487}
488
489pub fn sha256_sum(s: &[u8]) -> String {
490 use sha2::Digest;
491 let mut hasher = sha2::Sha256::new();
492 hasher.update(s);
493 hex::encode(hasher.finalize())
494}
495
496pub fn field_of_bits<F: FieldWitness, const N: usize>(bs: &[bool; N]) -> F {
497 bs.iter().rev().fold(F::zero(), |acc, b| {
498 let acc = acc + acc;
499 if *b {
500 acc + F::one()
501 } else {
502 acc
503 }
504 })
505}