p3_uni_stark/
preprocessed.rs

1use p3_air::Air;
2use p3_commit::Pcs;
3use p3_field::Field;
4use p3_matrix::Matrix;
5use tracing::debug_span;
6
7use crate::{ProverConstraintFolder, StarkGenericConfig, SymbolicAirBuilder, Val};
8
9/// Prover-side reusable data for preprocessed columns.
10///
11/// This allows committing to the preprocessed trace once per [`Air`]/degree and reusing
12/// the commitment and [`Pcs`] prover data across many proofs.
13pub struct PreprocessedProverData<SC: StarkGenericConfig> {
14    /// The width (number of columns) of the preprocessed trace.
15    pub width: usize,
16    /// The log2 of the degree of the domain over which the preprocessed trace is committed.
17    ///
18    /// In the current uni-stark implementation this matches `degree_bits` in [`Proof`](crate::Proof),
19    /// i.e. the (extended) trace degree.
20    pub degree_bits: usize,
21    /// [`Pcs`] commitment to the preprocessed trace.
22    pub commitment: <SC::Pcs as Pcs<SC::Challenge, SC::Challenger>>::Commitment,
23    /// [`Pcs`] prover data for the preprocessed trace.
24    pub prover_data: <SC::Pcs as Pcs<SC::Challenge, SC::Challenger>>::ProverData,
25}
26
27/// Verifier-side reusable data for preprocessed columns.
28///
29/// This allows committing to the preprocessed trace once per [`Air`]/degree and reusing
30/// the commitment across many verifications.
31#[derive(Clone)]
32pub struct PreprocessedVerifierKey<SC: StarkGenericConfig> {
33    /// The width (number of columns) of the preprocessed trace.
34    pub width: usize,
35    /// The log2 of the degree of the domain over which the preprocessed trace is committed.
36    ///
37    /// This should match `degree_bits` in [`Proof`](crate::Proof), i.e. the (extended) trace degree.
38    pub degree_bits: usize,
39    /// [`Pcs`] commitment to the preprocessed trace.
40    pub commitment: <SC::Pcs as Pcs<SC::Challenge, SC::Challenger>>::Commitment,
41}
42
43/// Set up and commit the preprocessed trace for a given [`Air`] and degree.
44///
45/// This can be called once per [`Air`]/degree configuration to obtain reusable
46/// prover data for preprocessed columns. Returns `None` if the [`Air`] does not
47/// define any preprocessed columns.
48pub fn setup_preprocessed<SC, A>(
49    config: &SC,
50    air: &A,
51    degree_bits: usize,
52) -> Option<(PreprocessedProverData<SC>, PreprocessedVerifierKey<SC>)>
53where
54    SC: StarkGenericConfig,
55    Val<SC>: Field,
56    A: Air<SymbolicAirBuilder<Val<SC>>> + for<'a> Air<ProverConstraintFolder<'a, SC>>,
57{
58    let pcs = config.pcs();
59    let is_zk = config.is_zk();
60
61    let init_degree = 1 << degree_bits;
62    let degree = 1 << (degree_bits + is_zk);
63
64    let preprocessed = air.preprocessed_trace()?;
65
66    let width = preprocessed.width();
67    if width == 0 {
68        return None;
69    }
70
71    assert_eq!(
72        preprocessed.height(),
73        init_degree,
74        "preprocessed trace height must equal trace degree"
75    );
76
77    let trace_domain = pcs.natural_domain_for_degree(degree);
78    let (commitment, prover_data) = debug_span!("commit to preprocessed trace")
79        .in_scope(|| pcs.commit_preprocessing([(trace_domain, preprocessed)]));
80
81    let degree_bits = degree_bits + is_zk;
82    let prover_data = PreprocessedProverData {
83        width,
84        degree_bits,
85        commitment: commitment.clone(),
86        prover_data,
87    };
88    let vk = PreprocessedVerifierKey {
89        width,
90        degree_bits,
91        commitment,
92    };
93    Some((prover_data, vk))
94}