openvm_stark_backend/keygen/
types.rs1use std::sync::Arc;
7
8use derivative::Derivative;
9use serde::{Deserialize, Serialize};
10use thiserror::Error;
11
12use crate::{
13 air_builders::symbolic::{symbolic_variable::SymbolicVariable, SymbolicConstraintsDag},
14 prover::stacked_pcs::StackedPcsData,
15 StarkProtocolConfig, SystemParams,
16};
17
18#[derive(Clone, Debug, Serialize, Deserialize)]
20pub struct TraceWidth {
21 pub preprocessed: Option<usize>,
22 pub cached_mains: Vec<usize>,
23 pub common_main: usize,
24}
25
26impl TraceWidth {
27 pub fn main_widths(&self) -> Vec<usize> {
29 let mut ret = self.cached_mains.clone();
30 if self.common_main != 0 {
31 ret.push(self.common_main);
32 }
33 ret
34 }
35
36 pub fn main_width(&self) -> usize {
39 self.cached_mains.iter().sum::<usize>() + self.common_main
40 }
41
42 pub fn total_width(&self) -> usize {
44 self.preprocessed.unwrap_or(0) + self.main_width()
45 }
46}
47
48#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
49pub struct LinearConstraint {
50 pub coefficients: Vec<u32>,
51 pub threshold: u32,
52}
53
54impl LinearConstraint {
55 pub fn is_implied_by(&self, other: &LinearConstraint) -> bool {
58 self.threshold >= other.threshold
59 && self
60 .coefficients
61 .iter()
62 .zip(&other.coefficients)
63 .all(|(a, b)| a <= b)
64 }
65}
66
67#[derive(Error, Debug)]
68pub enum KeygenError {
69 #[error("AIR {name} has zero main trace width")]
70 AirWidthZero { name: String },
71 #[error("AIR {name} must have at least one constraint or interaction")]
72 AirNoConstraintsOrInteractions { name: String },
73 #[error("AIR {name} interaction {interaction_index} has a zero-length message")]
74 InteractionMessageEmpty {
75 name: String,
76 interaction_index: usize,
77 },
78 #[error("Max constraint degree exceeded for AIR {name}: {degree} > {max_degree}")]
79 MaxConstraintDegreeExceeded {
80 name: String,
81 degree: usize,
82 max_degree: usize,
83 },
84}
85
86#[derive(Clone, Debug, Serialize, Deserialize)]
87#[repr(C)]
88pub struct StarkVerifyingParams {
89 pub width: TraceWidth,
91 pub num_public_values: usize,
93 pub need_rot: bool,
97}
98
99#[derive(Clone, Debug, Serialize, Deserialize)]
103pub struct VerifierSinglePreprocessedData<Digest> {
104 pub commit: Digest,
106 pub hypercube_dim: isize,
109 pub stacking_width: usize,
111}
112
113#[derive(Clone, Debug, Serialize, Deserialize)]
115#[repr(C)]
116pub struct StarkVerifyingKey<F, Digest> {
117 pub preprocessed_data: Option<VerifierSinglePreprocessedData<Digest>>,
119 pub params: StarkVerifyingParams,
121 pub symbolic_constraints: SymbolicConstraintsDag<F>,
124 pub max_constraint_degree: u8,
126 pub is_required: bool,
128 pub unused_variables: Vec<SymbolicVariable<F>>,
130}
131
132#[derive(Derivative, Serialize, Deserialize)]
137#[derivative(Clone(bound = ""), Debug(bound = ""))]
138#[serde(bound = "")]
139pub struct MultiStarkVerifyingKey<SC: StarkProtocolConfig> {
140 pub inner: MultiStarkVerifyingKey0<SC>,
143 pub pre_hash: SC::Digest,
146}
147
148#[derive(Derivative, Serialize, Deserialize)]
151#[derivative(Clone(bound = ""), Debug(bound = ""))]
152#[serde(bound = "")]
153pub struct MultiStarkVerifyingKey0<SC: StarkProtocolConfig> {
154 pub params: SystemParams,
155 pub per_air: Vec<StarkVerifyingKey<SC::F, SC::Digest>>,
156 pub trace_height_constraints: Vec<LinearConstraint>,
157}
158
159#[derive(Derivative, Serialize, Deserialize)]
161#[derivative(Clone(bound = ""))]
162#[serde(bound = "")]
163pub struct StarkProvingKey<SC: StarkProtocolConfig> {
164 pub air_name: String,
166 pub vk: StarkVerifyingKey<SC::F, SC::Digest>,
168 pub preprocessed_data: Option<Arc<StackedPcsData<SC::F, SC::Digest>>>,
170}
171
172#[derive(Derivative, Serialize, Deserialize)]
177#[derivative(Clone(bound = ""))]
178#[serde(bound = "")]
179pub struct MultiStarkProvingKey<SC: StarkProtocolConfig> {
180 pub per_air: Vec<StarkProvingKey<SC>>,
181 pub trace_height_constraints: Vec<LinearConstraint>,
182 pub max_constraint_degree: usize,
184 pub params: SystemParams,
185 pub vk_pre_hash: SC::Digest,
187}
188
189impl<Val, Com> StarkVerifyingKey<Val, Com> {
190 pub fn num_cached_mains(&self) -> usize {
191 self.params.width.cached_mains.len()
192 }
193
194 pub fn num_parts(&self) -> usize {
195 1 + self.num_cached_mains() + (self.preprocessed_data.is_some() as usize)
196 }
197
198 pub fn has_interaction(&self) -> bool {
199 !self.symbolic_constraints.interactions.is_empty()
200 }
201
202 pub fn num_interactions(&self) -> usize {
203 self.symbolic_constraints.interactions.len()
204 }
205
206 pub fn dag_main_part_index_to_commit_index(&self, index: usize) -> usize {
209 if index == self.num_cached_mains() {
211 0
212 } else {
213 index + 1 + self.preprocessed_data.is_some() as usize
214 }
215 }
216}
217
218impl<SC: StarkProtocolConfig> MultiStarkProvingKey<SC> {
219 pub fn get_vk(&self) -> MultiStarkVerifyingKey<SC> {
220 MultiStarkVerifyingKey {
221 inner: self.get_vk0(),
222 pre_hash: self.vk_pre_hash,
223 }
224 }
225
226 fn get_vk0(&self) -> MultiStarkVerifyingKey0<SC> {
227 MultiStarkVerifyingKey0 {
228 params: self.params.clone(),
229 per_air: self.per_air.iter().map(|pk| pk.vk.clone()).collect(),
230 trace_height_constraints: self.trace_height_constraints.clone(),
231 }
232 }
233}
234
235impl<SC: StarkProtocolConfig> MultiStarkVerifyingKey<SC> {
236 pub fn max_constraint_degree(&self) -> usize {
238 self.inner.max_constraint_degree()
239 }
240}
241
242impl<SC: StarkProtocolConfig> MultiStarkVerifyingKey0<SC> {
243 pub fn max_constraint_degree(&self) -> usize {
244 self.params.max_constraint_degree
245 }
246}