1use core::borrow::Borrow;
2
3use openvm_native_compiler::ir::{
4 Array, Builder, Config, Ext, Felt, MemVariable, Usize, Var, Witness,
5};
6use openvm_stark_backend::{
7 config::{Com, PcsProof},
8 p3_util::log2_strict_usize,
9 proof::{AdjacentOpenedValues, AirProofData, Commitments, OpenedValues, OpeningProof, Proof},
10};
11use openvm_stark_sdk::{
12 config::baby_bear_poseidon2_root::BabyBearPoseidon2RootConfig, p3_baby_bear::BabyBear,
13 p3_bn254_fr::Bn254Fr,
14};
15use p3_symmetric::Hash;
16
17use crate::{
18 config::outer::{OuterChallenge, OuterConfig, OuterVal},
19 digest::{DigestVal, DigestVariable},
20 hints::{InnerChallenge, InnerVal},
21 vars::{
22 AdjacentOpenedValuesVariable, AirProofDataVariable, CommitmentsVariable,
23 OpenedValuesVariable, OpeningProofVariable, StarkProofVariable,
24 },
25};
26
27pub trait Witnessable<C: Config> {
28 type WitnessVariable: MemVariable<C>;
29
30 fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable;
31
32 fn write(&self, witness: &mut Witness<C>);
33}
34
35type C = OuterConfig;
36type OuterCom = Hash<BabyBear, Bn254Fr, 1>;
37
38impl Witnessable<C> for Bn254Fr {
39 type WitnessVariable = Var<Bn254Fr>;
40
41 fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
42 builder.witness_var()
43 }
44
45 fn write(&self, witness: &mut Witness<C>) {
46 witness.vars.push(*self);
47 }
48}
49
50impl Witnessable<C> for OuterVal {
51 type WitnessVariable = Felt<OuterVal>;
52
53 fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
54 builder.witness_felt()
55 }
56
57 fn write(&self, witness: &mut Witness<C>) {
58 witness.felts.push(*self);
59 }
60}
61
62impl Witnessable<C> for OuterChallenge {
63 type WitnessVariable = Ext<OuterVal, OuterChallenge>;
64
65 fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
66 builder.witness_ext()
67 }
68
69 fn write(&self, witness: &mut Witness<C>) {
70 witness.exts.push(*self);
71 }
72}
73
74impl Witnessable<C> for OuterCom {
75 type WitnessVariable = DigestVariable<C>;
76
77 fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
78 let bv: &[Bn254Fr; 1] = self.borrow();
79 let v = vec![bv[0].read(builder)];
80 DigestVariable::Var(builder.vec(v))
81 }
82
83 fn write(&self, witness: &mut Witness<C>) {
84 let bv: &[Bn254Fr; 1] = self.borrow();
85 witness.vars.push(bv[0]);
86 }
87}
88
89impl Witnessable<C> for usize {
91 type WitnessVariable = Usize<<C as Config>::N>;
92
93 fn read(&self, _builder: &mut Builder<C>) -> Self::WitnessVariable {
94 Usize::from(*self)
95 }
96
97 fn write(&self, _witness: &mut Witness<C>) {
98 }
100}
101
102pub trait VectorWitnessable<C: Config>: Witnessable<C> {}
103impl VectorWitnessable<C> for Bn254Fr {}
104impl VectorWitnessable<C> for OuterVal {}
105impl VectorWitnessable<C> for OuterChallenge {}
106impl VectorWitnessable<C> for OuterCom {}
107impl VectorWitnessable<C> for usize {}
108impl VectorWitnessable<C> for Vec<OuterChallenge> {}
109impl VectorWitnessable<C> for Vec<Vec<OuterChallenge>> {}
110impl VectorWitnessable<C> for Vec<OuterVal> {}
111impl VectorWitnessable<C> for Vec<Vec<OuterVal>> {}
112
113impl<I: VectorWitnessable<C>> Witnessable<C> for Vec<I> {
114 type WitnessVariable = Array<C, I::WitnessVariable>;
115
116 fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
117 let raw_vec: Vec<I::WitnessVariable> = self.iter().map(|x| x.read(builder)).collect();
118 builder.vec(raw_vec)
119 }
120
121 fn write(&self, witness: &mut Witness<C>) {
122 self.iter().for_each(|x| x.write(witness));
123 }
124}
125
126impl Witnessable<C> for DigestVal<C> {
127 type WitnessVariable = DigestVariable<C>;
128
129 fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
130 let result = vec![builder.witness_var()];
131 DigestVariable::Var(builder.vec(result))
132 }
133
134 fn write(&self, witness: &mut Witness<C>) {
135 if let DigestVal::N(v) = self {
136 assert_eq!(v.len(), 1);
137 witness.vars.push(v[0]);
138 } else {
139 panic!("DigestVal should use N in static mode")
140 }
141 }
142}
143impl VectorWitnessable<C> for DigestVal<C> {}
144
145impl VectorWitnessable<C> for AirProofData<InnerVal, InnerChallenge> {}
146
147impl Witnessable<C> for Proof<BabyBearPoseidon2RootConfig> {
148 type WitnessVariable = StarkProofVariable<C>;
149
150 fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
151 if builder.flags.static_only {
152 assert!(
154 self.per_air.windows(2).all(|w| w[0].degree >= w[1].degree),
155 "Static verifier requires trace heights to be sorted descending"
156 );
157 }
158 let commitments = self.commitments.read(builder);
159 let opening = self.opening.read(builder);
160 let per_air = self.per_air.read(builder);
161 let air_perm_by_height = builder.array(0);
163 let log_up_pow_witness = self
164 .rap_phase_seq_proof
165 .as_ref()
166 .map(|proof| proof.logup_pow_witness)
167 .unwrap_or_default()
168 .read(builder);
169
170 StarkProofVariable {
171 commitments,
172 opening,
173 per_air,
174 air_perm_by_height,
175 log_up_pow_witness,
176 }
177 }
178
179 fn write(&self, witness: &mut Witness<C>) {
180 self.commitments.write(witness);
181 self.opening.write(witness);
182 self.per_air.write(witness);
183 let logup_pow_witness = self
185 .rap_phase_seq_proof
186 .as_ref()
187 .map(|p| p.logup_pow_witness)
188 .unwrap_or_default();
189 logup_pow_witness.write(witness);
190 }
191}
192
193impl Witnessable<C> for AirProofData<OuterVal, OuterChallenge> {
194 type WitnessVariable = AirProofDataVariable<C>;
195 fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
196 let air_id = Usize::from(0);
198 let log_degree = Usize::from(log2_strict_usize(self.degree));
200 let exposed_values_after_challenge = self.exposed_values_after_challenge.read(builder);
201 let public_values = self.public_values.read(builder);
202 Self::WitnessVariable {
203 air_id,
204 log_degree,
205 exposed_values_after_challenge,
206 public_values,
207 }
208 }
209 fn write(&self, witness: &mut Witness<C>) {
210 <_ as Witnessable<_>>::write(&self.exposed_values_after_challenge, witness);
213 <_ as Witnessable<_>>::write(&self.public_values, witness);
214 }
215}
216
217impl Witnessable<OuterConfig> for Commitments<Com<BabyBearPoseidon2RootConfig>> {
218 type WitnessVariable = CommitmentsVariable<OuterConfig>;
219
220 fn read(&self, builder: &mut Builder<OuterConfig>) -> Self::WitnessVariable {
221 let after_challenge = self.after_challenge.read(builder);
222 let main_trace = self.main_trace.read(builder);
223 let quotient = self.quotient.read(builder);
224 Self::WitnessVariable {
225 after_challenge,
226 main_trace,
227 quotient,
228 }
229 }
230
231 fn write(&self, witness: &mut Witness<OuterConfig>) {
232 self.after_challenge.write(witness);
233 self.main_trace.write(witness);
234 self.quotient.write(witness);
235 }
236}
237
238impl Witnessable<C> for OpeningProof<PcsProof<BabyBearPoseidon2RootConfig>, OuterChallenge> {
239 type WitnessVariable = OpeningProofVariable<C>;
240
241 fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
242 let proof = self.proof.read(builder);
243 let values = self.values.read(builder);
244 OpeningProofVariable { proof, values }
245 }
246
247 fn write(&self, witness: &mut Witness<C>) {
248 self.proof.write(witness);
249 <_ as Witnessable<C>>::write(&self.values, witness);
250 }
251}
252
253impl Witnessable<C> for OpenedValues<OuterChallenge> {
254 type WitnessVariable = OpenedValuesVariable<C>;
255
256 fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
257 let preprocessed = self.preprocessed.read(builder);
258 let main = self.main.read(builder);
259 let quotient = self.quotient.read(builder);
260 let after_challenge = self.after_challenge.read(builder);
261
262 OpenedValuesVariable {
263 preprocessed,
264 main,
265 quotient,
266 after_challenge,
267 }
268 }
269
270 fn write(&self, witness: &mut Witness<C>) {
271 <Vec<_> as Witnessable<C>>::write(&self.preprocessed, witness);
272 <Vec<_> as Witnessable<C>>::write(&self.main, witness);
273 <Vec<_> as Witnessable<C>>::write(&self.quotient, witness);
274 <Vec<_> as Witnessable<C>>::write(&self.after_challenge, witness);
275 }
276}
277
278impl Witnessable<C> for AdjacentOpenedValues<OuterChallenge> {
279 type WitnessVariable = AdjacentOpenedValuesVariable<C>;
280
281 fn read(&self, builder: &mut Builder<C>) -> Self::WitnessVariable {
282 let local = self.local.read(builder);
283 let next = self.next.read(builder);
284 AdjacentOpenedValuesVariable { local, next }
285 }
286
287 fn write(&self, witness: &mut Witness<C>) {
288 <Vec<_> as Witnessable<C>>::write(&self.local, witness);
289 <Vec<_> as Witnessable<C>>::write(&self.next, witness);
290 }
291}
292impl VectorWitnessable<C> for AdjacentOpenedValues<OuterChallenge> {}
293impl VectorWitnessable<C> for Vec<AdjacentOpenedValues<OuterChallenge>> {}