openvm_native_recursion/
helper.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
use itertools::Itertools;
use openvm_native_compiler::prelude::*;

use crate::vars::{MultiStarkVerificationAdviceVariable, StarkProofVariable};

impl<C: Config> StarkProofVariable<C> {
    pub fn get_air_ids(&self, builder: &mut Builder<C>) -> Array<C, Usize<C::N>> {
        if builder.flags.static_only {
            builder.vec(
                (0..self.per_air.len().value())
                    .map(Usize::from)
                    .collect_vec(),
            )
        } else {
            let air_ids = builder.array(self.per_air.len());
            builder.range(0, self.per_air.len()).for_each(|i, builder| {
                let air_proof_data = builder.get(&self.per_air, i);
                builder.set_value(&air_ids, i, air_proof_data.air_id);
            });
            air_ids
        }
    }
}

impl<C: Config> MultiStarkVerificationAdviceVariable<C> {
    /// Assumption: at most 1 phase is supported.
    pub fn num_challenges_to_sample(&self, builder: &mut Builder<C>) -> Array<C, Usize<C::N>> {
        if self.num_challenges_to_sample_mask.is_empty() {
            return builder.array(0);
        }
        // If all 0s, no phase 1.
        let num_phases: Usize<_> = builder.eval(self.num_challenges_to_sample_mask[0][0].clone());
        let ret = builder.array(num_phases.clone());
        // If phase 1 exists:
        builder
            .if_eq(num_phases.clone(), RVar::one())
            .then(|builder| {
                // Find the biggest index where the mask is 1.
                let num_challenges: Usize<_> = builder.eval(RVar::zero());
                for i in 1..self.num_challenges_to_sample_mask[0].len() {
                    builder
                        .if_eq(
                            self.num_challenges_to_sample_mask[0][i].clone(),
                            RVar::one(),
                        )
                        .then(|builder| {
                            builder.assign(&num_challenges, RVar::from(i));
                        });
                }
                builder.set(&ret, RVar::zero(), num_challenges + RVar::one());
            });
        ret
    }
}