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