openvm_native_recursion/fri/
hints.rs

1use openvm_native_compiler::{
2    asm::AsmConfig,
3    ir::{Builder, Config, Usize, DIGEST_SIZE},
4};
5use openvm_stark_backend::p3_field::PrimeCharacteristicRing;
6
7use super::types::BatchOpeningVariable;
8use crate::{
9    digest::DigestVariable,
10    fri::types::{FriCommitPhaseProofStepVariable, FriProofVariable, FriQueryProofVariable},
11    hints::{
12        Hintable, InnerBatchOpening, InnerChallenge, InnerCommitPhaseStep, InnerDigest,
13        InnerFriProof, InnerQueryProof, InnerVal, VecAutoHintable,
14    },
15    types::InnerConfig,
16    vars::HintSlice,
17};
18
19type C = InnerConfig;
20
21impl Hintable<C> for InnerDigest {
22    type HintVariable = DigestVariable<C>;
23
24    fn read(builder: &mut Builder<AsmConfig<InnerVal, InnerChallenge>>) -> Self::HintVariable {
25        let digest = builder.hint_felts_fixed(DIGEST_SIZE);
26        DigestVariable::Felt(digest)
27    }
28
29    fn write(&self) -> Vec<Vec<InnerVal>> {
30        let h: [InnerVal; DIGEST_SIZE] = *self;
31        h.map(|x| vec![x]).to_vec()
32    }
33}
34
35impl VecAutoHintable for InnerDigest {}
36
37impl Hintable<C> for InnerCommitPhaseStep {
38    type HintVariable = FriCommitPhaseProofStepVariable<C>;
39
40    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
41        let sibling_value = builder.hint_ext();
42        let opening_proof = read_hint_slice(builder);
43        Self::HintVariable {
44            sibling_value,
45            opening_proof,
46        }
47    }
48
49    fn write(&self) -> Vec<Vec<<C as Config>::F>> {
50        let mut stream = Vec::new();
51
52        stream.extend(Hintable::<C>::write(&self.sibling_value));
53        stream.extend(write_opening_proof(&self.opening_proof));
54
55        stream
56    }
57}
58
59impl VecAutoHintable for InnerCommitPhaseStep {}
60
61impl Hintable<C> for InnerQueryProof {
62    type HintVariable = FriQueryProofVariable<C>;
63
64    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
65        let input_proof = Vec::<InnerBatchOpening>::read(builder);
66        let commit_phase_openings = Vec::<InnerCommitPhaseStep>::read(builder);
67        Self::HintVariable {
68            input_proof,
69            commit_phase_openings,
70        }
71    }
72
73    fn write(&self) -> Vec<Vec<<C as Config>::F>> {
74        let mut stream = Vec::new();
75
76        stream.extend(self.input_proof.write());
77        stream.extend(Vec::<InnerCommitPhaseStep>::write(
78            &self.commit_phase_openings,
79        ));
80
81        stream
82    }
83}
84
85impl VecAutoHintable for InnerQueryProof {}
86
87impl Hintable<C> for InnerFriProof {
88    type HintVariable = FriProofVariable<C>;
89
90    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
91        let commit_phase_commits = Vec::<InnerDigest>::read(builder);
92        let commit_pow_witnesses = Vec::<InnerVal>::read(builder);
93        let query_proofs = Vec::<InnerQueryProof>::read(builder);
94        let final_poly = builder.hint_exts();
95        let query_pow_witness = builder.hint_felt();
96        Self::HintVariable {
97            commit_phase_commits,
98            commit_pow_witnesses,
99            query_proofs,
100            final_poly,
101            query_pow_witness,
102        }
103    }
104
105    fn write(&self) -> Vec<Vec<<C as Config>::F>> {
106        let mut stream = Vec::new();
107
108        stream.extend(Vec::<InnerDigest>::write(
109            &self
110                .commit_phase_commits
111                .iter()
112                .map(|x| (*x).into())
113                .collect(),
114        ));
115        stream.extend(Vec::<InnerVal>::write(&self.commit_pow_witnesses));
116        stream.extend(Vec::<InnerQueryProof>::write(&self.query_proofs));
117        stream.extend(self.final_poly.write());
118        stream.push(vec![self.query_pow_witness]);
119
120        stream
121    }
122}
123
124impl Hintable<C> for InnerBatchOpening {
125    type HintVariable = BatchOpeningVariable<C>;
126
127    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
128        builder.cycle_tracker_start("HintOpenedValues");
129        let opened_values = read_hint_slice(builder);
130        builder.cycle_tracker_end("HintOpenedValues");
131        builder.cycle_tracker_start("HintOpeningProof");
132        let opening_proof = read_hint_slice(builder);
133        builder.cycle_tracker_end("HintOpeningProof");
134        Self::HintVariable {
135            opened_values,
136            opening_proof,
137        }
138    }
139
140    fn write(&self) -> Vec<Vec<<C as Config>::F>> {
141        let mut stream = Vec::new();
142        let flat_opened_values: Vec<_> = self.opened_values.iter().flatten().copied().collect();
143        stream.extend(vec![
144            vec![InnerVal::from_usize(flat_opened_values.len())],
145            flat_opened_values,
146        ]);
147        stream.extend(write_opening_proof(&self.opening_proof));
148        stream
149    }
150}
151
152impl VecAutoHintable for InnerBatchOpening {}
153impl VecAutoHintable for Vec<InnerBatchOpening> {}
154
155fn read_hint_slice(builder: &mut Builder<C>) -> HintSlice<C> {
156    let length = Usize::from(builder.hint_var());
157    let id = Usize::from(builder.hint_load());
158    HintSlice { length, id }
159}
160
161fn write_opening_proof(opening_proof: &[InnerDigest]) -> Vec<Vec<InnerVal>> {
162    vec![
163        vec![InnerVal::from_usize(opening_proof.len())],
164        opening_proof.iter().flatten().copied().collect(),
165    ]
166}