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