mina_tree/proofs/
util.rs

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() // Never fail with 2 limbs
79}
80
81/// <https://github.com/MinaProtocol/mina/blob/bfd1009abdbee78979ff0343cc73a3480e862f58/src/lib/pickles/wrap_verifier.ml#L16>
82pub 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
104/// <https://github.com/MinaProtocol/mina/blob/bfd1009abdbee78979ff0343cc73a3480e862f58/src/lib/pickles/wrap_verifier.ml#L16>
105pub 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
137/// Note: Outdated URL
138/// Note: Different than `to_absorption_sequence`
139/// <https://github.com/MinaProtocol/mina/blob/4af0c229548bc96d76678f11b6842999de5d3b0b/src/lib/pickles_types/plonk_types.ml#L611>
140pub 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
295/// <https://github.com/MinaProtocol/mina/blob/4af0c229548bc96d76678f11b6842999de5d3b0b/src/lib/pickles_types/plonk_types.ml#L611>
296pub 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
391/// <https://github.com/MinaProtocol/mina/blob/4af0c229548bc96d76678f11b6842999de5d3b0b/src/lib/pickles_types/plonk_types.ml#L674>
392pub 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}