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::FieldAlgebra;
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 query_proofs = Vec::<InnerQueryProof>::read(builder);
93        let final_poly = builder.hint_exts();
94        let pow_witness = builder.hint_felt();
95        Self::HintVariable {
96            commit_phase_commits,
97            query_proofs,
98            final_poly,
99            pow_witness,
100        }
101    }
102
103    fn write(&self) -> Vec<Vec<<C as Config>::F>> {
104        let mut stream = Vec::new();
105
106        stream.extend(Vec::<InnerDigest>::write(
107            &self
108                .commit_phase_commits
109                .iter()
110                .map(|x| (*x).into())
111                .collect(),
112        ));
113        stream.extend(Vec::<InnerQueryProof>::write(&self.query_proofs));
114        stream.extend(self.final_poly.write());
115        stream.push(vec![self.pow_witness]);
116
117        stream
118    }
119}
120
121impl Hintable<C> for InnerBatchOpening {
122    type HintVariable = BatchOpeningVariable<C>;
123
124    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
125        builder.cycle_tracker_start("HintOpenedValues");
126        let opened_values = read_hint_slice(builder);
127        builder.cycle_tracker_end("HintOpenedValues");
128        builder.cycle_tracker_start("HintOpeningProof");
129        let opening_proof = read_hint_slice(builder);
130        builder.cycle_tracker_end("HintOpeningProof");
131        Self::HintVariable {
132            opened_values,
133            opening_proof,
134        }
135    }
136
137    fn write(&self) -> Vec<Vec<<C as Config>::F>> {
138        let mut stream = Vec::new();
139        let flat_opened_values: Vec<_> = self.opened_values.iter().flatten().copied().collect();
140        stream.extend(vec![
141            vec![InnerVal::from_canonical_usize(flat_opened_values.len())],
142            flat_opened_values,
143        ]);
144        stream.extend(write_opening_proof(&self.opening_proof));
145        stream
146    }
147}
148
149impl VecAutoHintable for InnerBatchOpening {}
150impl VecAutoHintable for Vec<InnerBatchOpening> {}
151
152fn read_hint_slice(builder: &mut Builder<C>) -> HintSlice<C> {
153    let length = Usize::from(builder.hint_var());
154    let id = Usize::from(builder.hint_load());
155    HintSlice { length, id }
156}
157
158fn write_opening_proof(opening_proof: &[InnerDigest]) -> Vec<Vec<InnerVal>> {
159    vec![
160        vec![InnerVal::from_canonical_usize(opening_proof.len())],
161        opening_proof.iter().flatten().copied().collect(),
162    ]
163}