sp1_recursion_program/fri/
hints.rs1use 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}