sp1_recursion_program/fri/
hints.rs

1use p3_field::{AbstractExtensionField, AbstractField};
2
3use sp1_recursion_compiler::{
4    asm::AsmConfig,
5    config::InnerConfig,
6    ir::{Array, Builder, Config},
7};
8use sp1_recursion_core::{air::Block, runtime::DIGEST_SIZE};
9use sp1_stark::{
10    InnerBatchOpening, InnerChallenge, InnerCommitPhaseStep, InnerDigest, InnerFriProof,
11    InnerPcsProof, InnerQueryProof, InnerVal,
12};
13
14use super::types::{BatchOpeningVariable, TwoAdicPcsProofVariable};
15use crate::{
16    fri::types::{
17        DigestVariable, FriCommitPhaseProofStepVariable, FriProofVariable, FriQueryProofVariable,
18    },
19    hints::Hintable,
20};
21
22type C = InnerConfig;
23
24impl Hintable<C> for InnerDigest {
25    type HintVariable = DigestVariable<C>;
26
27    fn read(builder: &mut Builder<AsmConfig<InnerVal, InnerChallenge>>) -> Self::HintVariable {
28        builder.hint_felts()
29    }
30
31    fn write(&self) -> Vec<Vec<Block<InnerVal>>> {
32        let h: [InnerVal; DIGEST_SIZE] = *self;
33        vec![h.iter().map(|x| Block::from(*x)).collect()]
34    }
35}
36
37impl Hintable<C> for Vec<InnerDigest> {
38    type HintVariable = Array<C, DigestVariable<C>>;
39
40    fn read(builder: &mut Builder<AsmConfig<InnerVal, InnerChallenge>>) -> Self::HintVariable {
41        let len = builder.hint_var();
42        let mut arr = builder.dyn_array(len);
43        builder.range(0, len).for_each(|i, builder| {
44            let hint = InnerDigest::read(builder);
45            builder.set(&mut arr, i, hint);
46        });
47        arr
48    }
49
50    fn write(&self) -> Vec<Vec<Block<InnerVal>>> {
51        let mut stream = Vec::new();
52
53        let len = InnerVal::from_canonical_usize(self.len());
54        stream.push(vec![len.into()]);
55
56        self.iter().for_each(|arr| {
57            let comm = InnerDigest::write(arr);
58            stream.extend(comm);
59        });
60
61        stream
62    }
63}
64
65impl Hintable<C> for InnerCommitPhaseStep {
66    type HintVariable = FriCommitPhaseProofStepVariable<C>;
67
68    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
69        let sibling_value = builder.hint_ext();
70        let opening_proof = Vec::<InnerDigest>::read(builder);
71        Self::HintVariable { sibling_value, opening_proof }
72    }
73
74    fn write(&self) -> Vec<Vec<Block<<C as Config>::F>>> {
75        let mut stream = Vec::new();
76
77        let sibling_value: &[InnerVal] = self.sibling_value.as_base_slice();
78        let sibling_value = Block::from(sibling_value);
79        stream.push(vec![sibling_value]);
80
81        stream.extend(Vec::<InnerDigest>::write(&self.opening_proof));
82
83        stream
84    }
85}
86
87impl Hintable<C> for Vec<InnerCommitPhaseStep> {
88    type HintVariable = Array<C, FriCommitPhaseProofStepVariable<C>>;
89
90    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
91        let len = builder.hint_var();
92        let mut arr = builder.dyn_array(len);
93        builder.range(0, len).for_each(|i, builder| {
94            let hint = InnerCommitPhaseStep::read(builder);
95            builder.set(&mut arr, i, hint);
96        });
97        arr
98    }
99
100    fn write(&self) -> Vec<Vec<Block<<C as Config>::F>>> {
101        let mut stream = Vec::new();
102
103        let len = InnerVal::from_canonical_usize(self.len());
104        stream.push(vec![len.into()]);
105
106        self.iter().for_each(|arr| {
107            let comm = InnerCommitPhaseStep::write(arr);
108            stream.extend(comm);
109        });
110
111        stream
112    }
113}
114
115impl Hintable<C> for InnerQueryProof {
116    type HintVariable = FriQueryProofVariable<C>;
117
118    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
119        let commit_phase_openings = Vec::<InnerCommitPhaseStep>::read(builder);
120        Self::HintVariable { commit_phase_openings }
121    }
122
123    fn write(&self) -> Vec<Vec<Block<<C as Config>::F>>> {
124        let mut stream = Vec::new();
125
126        stream.extend(Vec::<InnerCommitPhaseStep>::write(&self.commit_phase_openings));
127
128        stream
129    }
130}
131
132impl Hintable<C> for Vec<InnerQueryProof> {
133    type HintVariable = Array<C, FriQueryProofVariable<C>>;
134
135    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
136        let len = builder.hint_var();
137        let mut arr = builder.dyn_array(len);
138        builder.range(0, len).for_each(|i, builder| {
139            let hint = InnerQueryProof::read(builder);
140            builder.set(&mut arr, i, hint);
141        });
142        arr
143    }
144
145    fn write(&self) -> Vec<Vec<Block<<C as Config>::F>>> {
146        let mut stream = Vec::new();
147
148        let len = InnerVal::from_canonical_usize(self.len());
149        stream.push(vec![len.into()]);
150
151        self.iter().for_each(|arr| {
152            let comm = InnerQueryProof::write(arr);
153            stream.extend(comm);
154        });
155
156        stream
157    }
158}
159
160impl Hintable<C> for InnerFriProof {
161    type HintVariable = FriProofVariable<C>;
162
163    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
164        let commit_phase_commits = Vec::<InnerDigest>::read(builder);
165        let query_proofs = Vec::<InnerQueryProof>::read(builder);
166        let final_poly = builder.hint_ext();
167        let pow_witness = builder.hint_felt();
168        Self::HintVariable { commit_phase_commits, query_proofs, final_poly, pow_witness }
169    }
170
171    fn write(&self) -> Vec<Vec<Block<<C as Config>::F>>> {
172        let mut stream = Vec::new();
173
174        stream.extend(Vec::<InnerDigest>::write(
175            &self.commit_phase_commits.iter().map(|x| (*x).into()).collect(),
176        ));
177        stream.extend(Vec::<InnerQueryProof>::write(&self.query_proofs));
178        let final_poly: &[InnerVal] = self.final_poly.as_base_slice();
179        let final_poly = Block::from(final_poly);
180        stream.push(vec![final_poly]);
181        let pow_witness = Block::from(self.pow_witness);
182        stream.push(vec![pow_witness]);
183
184        stream
185    }
186}
187
188impl Hintable<C> for InnerBatchOpening {
189    type HintVariable = BatchOpeningVariable<C>;
190
191    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
192        let opened_values = Vec::<Vec<InnerChallenge>>::read(builder);
193        let opening_proof = Vec::<InnerDigest>::read(builder);
194        Self::HintVariable { opened_values, opening_proof }
195    }
196
197    fn write(&self) -> Vec<Vec<Block<<C as Config>::F>>> {
198        let mut stream = Vec::new();
199        stream.extend(Vec::<Vec<InnerChallenge>>::write(
200            &self
201                .opened_values
202                .iter()
203                .map(|v| v.iter().map(|x| InnerChallenge::from_base(*x)).collect())
204                .collect(),
205        ));
206        stream.extend(Vec::<InnerDigest>::write(&self.opening_proof));
207        stream
208    }
209}
210
211impl Hintable<C> for Vec<InnerBatchOpening> {
212    type HintVariable = Array<C, BatchOpeningVariable<C>>;
213
214    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
215        let len = builder.hint_var();
216        let mut arr = builder.dyn_array(len);
217        builder.range(0, len).for_each(|i, builder| {
218            let hint = InnerBatchOpening::read(builder);
219            builder.set(&mut arr, i, hint);
220        });
221        arr
222    }
223
224    fn write(&self) -> Vec<Vec<Block<<C as Config>::F>>> {
225        let mut stream = Vec::new();
226
227        let len = InnerVal::from_canonical_usize(self.len());
228        stream.push(vec![len.into()]);
229
230        self.iter().for_each(|arr| {
231            let comm = InnerBatchOpening::write(arr);
232            stream.extend(comm);
233        });
234
235        stream
236    }
237}
238
239impl Hintable<C> for Vec<Vec<InnerBatchOpening>> {
240    type HintVariable = Array<C, Array<C, BatchOpeningVariable<C>>>;
241
242    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
243        let len = builder.hint_var();
244        let mut arr = builder.dyn_array(len);
245        builder.range(0, len).for_each(|i, builder| {
246            let hint = Vec::<InnerBatchOpening>::read(builder);
247            builder.set(&mut arr, i, hint);
248        });
249        arr
250    }
251
252    fn write(&self) -> Vec<Vec<Block<<C as Config>::F>>> {
253        let mut stream = Vec::new();
254
255        let len = InnerVal::from_canonical_usize(self.len());
256        stream.push(vec![len.into()]);
257
258        self.iter().for_each(|arr| {
259            let comm = Vec::<InnerBatchOpening>::write(arr);
260            stream.extend(comm);
261        });
262
263        stream
264    }
265}
266
267impl Hintable<C> for InnerPcsProof {
268    type HintVariable = TwoAdicPcsProofVariable<C>;
269
270    fn read(builder: &mut Builder<C>) -> Self::HintVariable {
271        let fri_proof = InnerFriProof::read(builder);
272        let query_openings = Vec::<Vec<InnerBatchOpening>>::read(builder);
273        Self::HintVariable { fri_proof, query_openings }
274    }
275
276    fn write(&self) -> Vec<Vec<Block<<C as Config>::F>>> {
277        let mut stream = Vec::new();
278        stream.extend(self.fri_proof.write());
279        stream.extend(self.query_openings.write());
280        stream
281    }
282}