openvm_stark_backend/prover/
types.rs

1use std::sync::Arc;
2
3use derivative::Derivative;
4use itertools::Itertools;
5use p3_field::Field;
6use p3_matrix::dense::RowMajorMatrix;
7use serde::{Deserialize, Serialize};
8
9use super::hal::ProverBackend;
10use crate::{
11    config::{Com, PcsProof, RapPhaseSeqPartialProof, StarkGenericConfig, Val},
12    keygen::types::{LinearConstraint, StarkVerifyingKey},
13    proof::{AirProofData, Commitments, OpeningProof, Proof},
14};
15
16/// A view of the proving key after it has been transferred to device. The view is filtered for only
17/// the proving keys corresponding to specific `air_ids`.
18pub struct DeviceMultiStarkProvingKeyView<'a, PB: ProverBackend> {
19    pub(super) air_ids: Vec<usize>,
20    pub per_air: Vec<&'a DeviceStarkProvingKey<PB>>,
21    /// Each [LinearConstraint] is indexed by AIR ID.
22    /// **Caution**: the linear constraints are **not** filtered for only the AIRs appearing in
23    /// `per_air`.
24    pub trace_height_constraints: &'a [LinearConstraint],
25    pub vk_pre_hash: &'a PB::Commitment,
26}
27
28/// The proving key for a circuit consisting of multiple AIRs, after prover-specific data has been
29/// transferred to device. The host data (e.g., vkey) is owned by this struct.
30#[derive(derive_new::new)]
31pub struct DeviceMultiStarkProvingKey<PB: ProverBackend> {
32    pub per_air: Vec<DeviceStarkProvingKey<PB>>,
33    /// Each [LinearConstraint] is indexed by AIR ID.
34    /// **Caution**: the linear constraints are **not** filtered for only the AIRs appearing in
35    /// `per_air`.
36    pub trace_height_constraints: Vec<LinearConstraint>,
37    pub vk_pre_hash: PB::Commitment,
38}
39
40impl<PB: ProverBackend> DeviceMultiStarkProvingKey<PB> {
41    pub fn view(&self, air_ids: Vec<usize>) -> DeviceMultiStarkProvingKeyView<'_, PB> {
42        let deduped: Vec<_> = air_ids.iter().dedup().collect();
43        assert_eq!(deduped.len(), air_ids.len(), "Duplicate AIR IDs found");
44        let per_air = air_ids.iter().map(|&id| &self.per_air[id]).collect();
45        DeviceMultiStarkProvingKeyView {
46            air_ids,
47            per_air,
48            trace_height_constraints: &self.trace_height_constraints,
49            vk_pre_hash: &self.vk_pre_hash,
50        }
51    }
52}
53
54/// The proving key after prover-specific data has been transferred to device. The host data (e.g.,
55/// vkey) is owned by this struct.
56pub struct DeviceStarkProvingKey<PB: ProverBackend> {
57    /// Type name of the AIR, for display purposes only
58    pub air_name: String,
59    pub vk: StarkVerifyingKey<PB::Val, PB::Commitment>,
60    /// Prover only data for preprocessed trace
61    pub preprocessed_data: Option<SingleCommitPreimage<PB::Matrix, PB::PcsData>>,
62    /// Additional configuration or preprocessed data for the RAP phases
63    pub rap_partial_pk: PB::RapPartialProvingKey,
64}
65
66/// A view of an already committed trace, together with a reference to the
67/// preimage of the commitment.
68///
69/// The PCS may commit to multiple matrices at once, so `matrix_idx` provides
70/// the index of this matrix within the commitment.
71#[derive(Clone)]
72pub struct SingleCommitPreimage<Matrix, PcsData> {
73    pub trace: Matrix,
74    pub data: PcsData,
75    pub matrix_idx: u32,
76}
77
78/// Commitment to a single trace matrix, together with the trace matrix and prover data.
79#[derive(Derivative)]
80#[derivative(Clone(bound = "PB::Matrix: Clone, PB::PcsData: Clone"))]
81pub struct CommittedTraceData<PB: ProverBackend> {
82    pub commitment: PB::Commitment,
83    pub trace: PB::Matrix,
84    pub data: PB::PcsData,
85}
86
87#[derive(derive_new::new)]
88pub struct ProvingContext<PB: ProverBackend> {
89    /// (AIR id, AIR input)
90    pub per_air: Vec<(usize, AirProvingContext<PB>)>,
91}
92
93impl<PB: ProverBackend> ProvingContext<PB> {
94    pub fn into_air_proving_ctx_vec(self) -> Vec<AirProvingContext<PB>> {
95        self.per_air.into_iter().map(|(_, x)| x).collect()
96    }
97
98    pub fn air_ids(&self) -> Vec<usize> {
99        self.per_air.iter().map(|(id, _)| *id).collect()
100    }
101}
102
103impl<PB: ProverBackend> IntoIterator for ProvingContext<PB> {
104    type Item = (usize, AirProvingContext<PB>);
105    type IntoIter = std::vec::IntoIter<Self::Item>;
106
107    fn into_iter(self) -> Self::IntoIter {
108        self.per_air.into_iter()
109    }
110}
111
112/// Necessary context for proving a single AIR.
113/// Consists of the trace and public values (witness and instance data) as well as
114/// cached prover data from cached traces (already committed traces).
115///
116/// Public values: for each AIR, a separate list of public values.
117/// The prover can support global public values that are shared among all AIRs,
118/// but we currently split public values per-AIR for modularity.
119#[derive(Derivative, derive_new::new)]
120#[derivative(Clone(bound = "PB::Matrix: Clone, PB::PcsData: Clone"))]
121pub struct AirProvingContext<PB: ProverBackend> {
122    /// Cached main trace matrices with commitments. One matrix per commitment.
123    // Note[jpw]: The cached data should have a lifetime since it may outlive a single proof
124    // invocation. But for now it's easier to assume `cached_mains` are owned, and any sharing
125    // is done via smart pointers.
126    pub cached_mains: Vec<CommittedTraceData<PB>>,
127    /// Common main trace matrix
128    pub common_main: Option<PB::Matrix>,
129    /// Public values
130    // [jpw] This is on host for now because it seems more convenient for the challenger to be on
131    // host.
132    pub public_values: Vec<PB::Val>,
133}
134
135/// A view of just the AIR, without any preprocessed or after challenge columns.
136/// The AIR's main trace is horizontally partitioned into multiple matrices,
137/// where each matrix can belong to a separate matrix commitment.
138///
139/// The generic `T` may be either just the trace matrix view or the LDE matrix view.
140pub struct AirView<T, Val> {
141    /// Main trace data, horizontally partitioned into multiple matrices
142    pub partitioned_main: Vec<T>,
143    /// Public values
144    pub public_values: Vec<Val>,
145}
146
147pub struct PairView<T, Val> {
148    /// Log_2 of the trace domain size (i.e., height of matrices)
149    pub log_trace_height: u8,
150    /// Preprocessed trace data, if any
151    pub preprocessed: Option<T>,
152    /// Main trace data, horizontally partitioned into multiple matrices
153    pub partitioned_main: Vec<T>,
154    /// Public values
155    pub public_values: Vec<Val>,
156}
157
158/// The full RAP trace consists of horizontal concatenation of multiple matrices of the same height:
159/// - preprocessed trace matrix
160/// - the main trace matrix is horizontally partitioned into multiple matrices, where each matrix
161///   can belong to a separate matrix commitment.
162/// - after each round of challenges, a trace matrix for trace allowed to use those challenges
163///
164/// Each of these matrices is allowed to be in a separate commitment.
165///
166/// Only the main trace matrix is allowed to be partitioned, so that different parts may belong to
167/// different commitments. We do not see any use cases where the `preprocessed` or `after_challenge`
168/// matrices need to be partitioned.
169///
170/// The generic `T` may be either just the trace matrix view or the LDE matrix view.
171pub struct RapView<T, Val, Challenge> {
172    /// Log_2 of the trace domain size (i.e., height of matrices)
173    pub log_trace_height: u8,
174    /// Preprocessed trace data, if any
175    pub preprocessed: Option<T>,
176    /// Main trace data, horizontally partitioned into multiple matrices
177    pub partitioned_main: Vec<T>,
178    /// Public values
179    pub public_values: Vec<Val>,
180    /// `per_phase[i]` is a view which is calculated after sampling challenges
181    /// which depend on observing commitments to `pair` and `per_phase[..i]`.
182    pub per_phase: Vec<RapSinglePhaseView<T, Challenge>>,
183}
184
185#[derive(Clone)]
186pub struct RapSinglePhaseView<T, Challenge> {
187    /// `None` if this RAP does not use this phase.
188    pub inner: Option<T>,
189    /// The challenges sampled in this phase
190    pub challenges: Vec<Challenge>,
191    /// These are extension field values exposed to the verifier after this phase.
192    /// They are like public values, except that they depend on randomness.
193    pub exposed_values: Vec<Challenge>,
194}
195
196impl<T, Challenge> Default for RapSinglePhaseView<T, Challenge> {
197    fn default() -> Self {
198        Self {
199            inner: None,
200            challenges: Vec::new(),
201            exposed_values: Vec::new(),
202        }
203    }
204}
205
206#[derive(derive_new::new)]
207pub struct ProverDataAfterRapPhases<PB: ProverBackend> {
208    /// For each challenge phase **after** the main phase,
209    /// the commitment and preimage (there should never be a reason to have more than one).
210    /// This may be empty if challenge phases do not require additional trace commitments.
211    pub committed_pcs_data_per_phase: Vec<(PB::Commitment, PB::PcsData)>,
212    /// For each challenge phase, for each RAP,
213    /// the challenge, and exposed values for the RAP.
214    /// The indexing is `rap_views_per_phase[phase_idx][rap_idx]`.
215    pub rap_views_per_phase: Vec<Vec<RapSinglePhaseView<usize, PB::Challenge>>>,
216}
217
218/// The full proof for multiple RAPs where trace matrices are committed into
219/// multiple commitments, where each commitment is multi-matrix.
220///
221/// Includes the quotient commitments and FRI opening proofs for the constraints as well.
222#[derive(Serialize, Deserialize, Derivative)]
223#[serde(bound = "")]
224#[derivative(Clone(bound = ""))]
225pub struct HalProof<PB: ProverBackend> {
226    /// The PCS commitments
227    pub commitments: Commitments<PB::Commitment>,
228    /// Opening proofs separated by partition, but this may change
229    pub opening: PB::OpeningProof,
230    /// Proof data for each AIR
231    pub per_air: Vec<AirProofData<PB::Val, PB::Challenge>>,
232    /// Partial proof for rap phase if it exists
233    pub rap_partial_proof: PB::RapPartialProof,
234}
235
236impl<PB, SC: StarkGenericConfig> From<HalProof<PB>> for Proof<SC>
237where
238    PB: ProverBackend<Val = Val<SC>, Challenge = SC::Challenge, Commitment = Com<SC>>,
239    PB::OpeningProof: Into<OpeningProof<PcsProof<SC>, SC::Challenge>>,
240    PB::RapPartialProof: Into<Option<RapPhaseSeqPartialProof<SC>>>,
241{
242    fn from(proof: HalProof<PB>) -> Self {
243        Proof {
244            commitments: proof.commitments,
245            opening: proof.opening.into(),
246            per_air: proof.per_air,
247            rap_phase_seq_proof: proof.rap_partial_proof.into(),
248        }
249    }
250}
251
252/// Raw input for proving a single AIR. For DEBUG use only.
253#[derive(Clone, Debug)]
254pub struct AirProofRawInput<F: Field> {
255    /// Cached main trace matrices
256    pub cached_mains: Vec<Arc<RowMajorMatrix<F>>>,
257    /// Common main trace matrix
258    pub common_main: Option<Arc<RowMajorMatrix<F>>>,
259    /// Public values
260    pub public_values: Vec<F>,
261}