sp1_stark/
types.rs

1#![allow(missing_docs)]
2
3use std::fmt::Debug;
4
5use hashbrown::HashMap;
6use itertools::Itertools;
7use p3_matrix::{dense::RowMajorMatrixView, stack::VerticalPair};
8use serde::{de::DeserializeOwned, Deserialize, Serialize};
9use strum::{EnumDiscriminants, EnumTryAs};
10
11use super::{Challenge, Com, OpeningProof, StarkGenericConfig, Val};
12use crate::{
13    baby_bear_poseidon2::BabyBearPoseidon2, septic_digest::SepticDigest, shape::OrderedShape, Dom,
14    StarkVerifyingKey,
15};
16
17pub type QuotientOpenedValues<T> = Vec<T>;
18
19pub struct ShardMainData<SC: StarkGenericConfig, M, P> {
20    pub traces: Vec<M>,
21    pub main_commit: Com<SC>,
22    pub main_data: P,
23    pub chip_ordering: HashMap<String, usize>,
24    pub public_values: Vec<SC::Val>,
25}
26
27impl<SC: StarkGenericConfig, M, P> ShardMainData<SC, M, P> {
28    pub const fn new(
29        traces: Vec<M>,
30        main_commit: Com<SC>,
31        main_data: P,
32        chip_ordering: HashMap<String, usize>,
33        public_values: Vec<Val<SC>>,
34    ) -> Self {
35        Self { traces, main_commit, main_data, chip_ordering, public_values }
36    }
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
40pub struct ShardCommitment<C> {
41    pub main_commit: C,
42    pub permutation_commit: C,
43    pub quotient_commit: C,
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
47#[serde(bound(serialize = "T: Serialize"))]
48#[serde(bound(deserialize = "T: Deserialize<'de>"))]
49pub struct AirOpenedValues<T> {
50    pub local: Vec<T>,
51    pub next: Vec<T>,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
55#[serde(bound(serialize = "F: Serialize, EF: Serialize"))]
56#[serde(bound(deserialize = "F: Deserialize<'de>, EF: Deserialize<'de>"))]
57pub struct ChipOpenedValues<F, EF> {
58    pub preprocessed: AirOpenedValues<EF>,
59    pub main: AirOpenedValues<EF>,
60    pub permutation: AirOpenedValues<EF>,
61    pub quotient: Vec<Vec<EF>>,
62    pub global_cumulative_sum: SepticDigest<F>,
63    pub local_cumulative_sum: EF,
64    pub log_degree: usize,
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct ShardOpenedValues<F, EF> {
69    pub chips: Vec<ChipOpenedValues<F, EF>>,
70}
71
72/// The maximum number of elements that can be stored in the public values vec.  Both SP1 and
73/// recursive proofs need to pad their public values vec to this length.  This is required since the
74/// recursion verification program expects the public values vec to be fixed length.
75pub const PROOF_MAX_NUM_PVS: usize = 231;
76
77#[derive(Serialize, Deserialize, Clone)]
78#[serde(bound = "")]
79pub struct ShardProof<SC: StarkGenericConfig> {
80    pub commitment: ShardCommitment<Com<SC>>,
81    pub opened_values: ShardOpenedValues<Val<SC>, Challenge<SC>>,
82    pub opening_proof: OpeningProof<SC>,
83    pub chip_ordering: HashMap<String, usize>,
84    pub public_values: Vec<Val<SC>>,
85}
86
87impl<SC: StarkGenericConfig> Debug for ShardProof<SC> {
88    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89        f.debug_struct("ShardProof").finish()
90    }
91}
92
93impl<T: Send + Sync + Clone> AirOpenedValues<T> {
94    #[must_use]
95    pub fn view(&self) -> VerticalPair<RowMajorMatrixView<'_, T>, RowMajorMatrixView<'_, T>> {
96        let a = RowMajorMatrixView::new_row(&self.local);
97        let b = RowMajorMatrixView::new_row(&self.next);
98        VerticalPair::new(a, b)
99    }
100}
101
102impl<SC: StarkGenericConfig> ShardProof<SC> {
103    pub fn local_cumulative_sum(&self) -> Challenge<SC> {
104        self.opened_values.chips.iter().map(|c| c.local_cumulative_sum).sum()
105    }
106
107    pub fn global_cumulative_sum(&self) -> SepticDigest<Val<SC>> {
108        self.opened_values.chips.iter().map(|c| c.global_cumulative_sum).sum()
109    }
110
111    pub fn log_degree_cpu(&self) -> usize {
112        let idx = self.chip_ordering.get("Cpu").expect("Cpu chip not found");
113        self.opened_values.chips[*idx].log_degree
114    }
115
116    pub fn contains_cpu(&self) -> bool {
117        self.chip_ordering.contains_key("Cpu")
118    }
119
120    pub fn contains_global_memory_init(&self) -> bool {
121        self.chip_ordering.contains_key("MemoryGlobalInit")
122    }
123
124    pub fn contains_global_memory_finalize(&self) -> bool {
125        self.chip_ordering.contains_key("MemoryGlobalFinalize")
126    }
127}
128
129#[derive(Serialize, Deserialize, Clone)]
130#[serde(bound = "")]
131pub struct MachineProof<SC: StarkGenericConfig> {
132    pub shard_proofs: Vec<ShardProof<SC>>,
133}
134
135impl<SC: StarkGenericConfig> Debug for MachineProof<SC> {
136    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
137        f.debug_struct("Proof").field("shard_proofs", &self.shard_proofs.len()).finish()
138    }
139}
140
141/// The configuration for the core prover.
142pub type CoreSC = BabyBearPoseidon2;
143
144/// The configuration for the inner prover.
145pub type InnerSC = BabyBearPoseidon2;
146
147/// A proof generated by the SP1 RISC-V zkVM.
148#[derive(Debug, Clone, Serialize, Deserialize, EnumDiscriminants, EnumTryAs)]
149#[strum_discriminants(derive(Default, Hash, PartialOrd, Ord))]
150#[strum_discriminants(name(SP1ProofMode))]
151pub enum SP1Proof {
152    /// A proof generated by the core proof mode.
153    ///
154    /// The proof size scales linearly with the number of cycles.
155    #[strum_discriminants(default)]
156    Core(Vec<ShardProof<CoreSC>>),
157    /// A proof generated by the compress proof mode.
158    ///
159    /// The proof size is constant, regardless of the number of cycles.
160    Compressed(Box<SP1ReduceProof<InnerSC>>),
161    /// A proof generated by the Plonk proof mode.
162    Plonk(PlonkBn254Proof),
163    /// A proof generated by the Groth16 proof mode.
164    Groth16(Groth16Bn254Proof),
165}
166
167impl core::fmt::Display for SP1Proof {
168    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
169        match self {
170            SP1Proof::Core(_) => write!(f, "Core"),
171            SP1Proof::Compressed(_) => write!(f, "Compressed"),
172            SP1Proof::Plonk(_) => write!(f, "Plonk"),
173            SP1Proof::Groth16(_) => write!(f, "Groth16"),
174        }
175    }
176}
177
178#[derive(Debug, Clone, Serialize, Deserialize, Default)]
179pub struct PlonkBn254Proof {
180    pub public_inputs: [String; 2],
181    pub encoded_proof: String,
182    pub raw_proof: String,
183    pub plonk_vkey_hash: [u8; 32],
184}
185
186#[derive(Debug, Clone, Serialize, Deserialize, Default)]
187pub struct Groth16Bn254Proof {
188    pub public_inputs: [String; 2],
189    pub encoded_proof: String,
190    pub raw_proof: String,
191    pub groth16_vkey_hash: [u8; 32],
192}
193
194/// An intermediate proof which proves the execution.
195#[derive(Serialize, Deserialize, Clone)]
196#[serde(bound(serialize = "ShardProof<SC>: Serialize, Dom<SC>: Serialize"))]
197#[serde(bound(deserialize = "ShardProof<SC>: Deserialize<'de>, Dom<SC>: DeserializeOwned"))]
198pub struct SP1ReduceProof<SC: StarkGenericConfig> {
199    /// The compress verifying key associated with the proof.
200    pub vk: StarkVerifyingKey<SC>,
201    /// The shard proof representing the compressed proof.
202    pub proof: ShardProof<SC>,
203}
204
205impl<SC: StarkGenericConfig> std::fmt::Debug for SP1ReduceProof<SC> {
206    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
207        let mut debug_struct = f.debug_struct("SP1ReduceProof");
208        debug_struct.field("vk", &self.vk);
209        debug_struct.field("proof", &self.proof);
210        debug_struct.finish()
211    }
212}
213
214/// The hash of all the public values that a zkvm program has committed to.
215pub struct PublicValuesDigest(pub [u8; 32]);
216
217impl From<[u32; 8]> for PublicValuesDigest {
218    fn from(arr: [u32; 8]) -> Self {
219        let mut bytes = [0u8; 32];
220        for (i, word) in arr.iter().enumerate() {
221            bytes[i * 4..(i + 1) * 4].copy_from_slice(&word.to_le_bytes());
222        }
223        PublicValuesDigest(bytes)
224    }
225}
226
227/// The hash of all the deferred proofs that have been witnessed in the VM.
228pub struct DeferredDigest(pub [u8; 32]);
229
230impl From<[u32; 8]> for DeferredDigest {
231    fn from(arr: [u32; 8]) -> Self {
232        let mut bytes = [0u8; 32];
233        for (i, word) in arr.iter().enumerate() {
234            bytes[i * 4..(i + 1) * 4].copy_from_slice(&word.to_le_bytes());
235        }
236        DeferredDigest(bytes)
237    }
238}
239
240impl<SC: StarkGenericConfig> ShardProof<SC> {
241    pub fn shape(&self) -> OrderedShape {
242        OrderedShape {
243            inner: self
244                .chip_ordering
245                .iter()
246                .sorted_by_key(|(_, idx)| *idx)
247                .zip(self.opened_values.chips.iter())
248                .map(|((name, _), values)| (name.to_owned(), values.log_degree))
249                .collect(),
250        }
251    }
252}