1use std::sync::Arc;
2
3use itertools::Itertools;
4
5use crate::{
6 air_builders::debug::{debug_constraints_and_interactions, AirProofRawInput},
7 keygen::{
8 types::{MultiStarkProvingKey, MultiStarkVerifyingKey},
9 MultiStarkKeygenBuilder,
10 },
11 memory_metering::ProvingMemoryConfig,
12 proof::*,
13 prover::{
14 AirProvingContext, ColMajorMatrix, Coordinator, DeviceDataTransporter,
15 DeviceMultiStarkProvingKey, MultiRapProver, OpeningProver, Prover, ProverBackend,
16 ProverDevice, ProvingContext, StridedColMajorMatrixView,
17 },
18 verifier::{verify, VerifierError},
19 AirRef, FiatShamirTranscript, StarkProtocolConfig, SystemParams,
20};
21
22#[derive(Debug)]
24pub struct VerificationData<SC: StarkProtocolConfig> {
25 pub vk: MultiStarkVerifyingKey<SC>,
26 pub proof: Proof<SC>,
27}
28
29pub type ProverError<E> =
30 <<E as StarkEngine>::PD as ProverDevice<<E as StarkEngine>::PB, <E as StarkEngine>::TS>>::Error;
31
32pub type EngineDeviceCtx<E> = <<E as StarkEngine>::PD as ProverDevice<
34 <E as StarkEngine>::PB,
35 <E as StarkEngine>::TS,
36>>::DeviceCtx;
37
38pub trait StarkEngine
41where
42 <Self::PD as MultiRapProver<Self::PB, Self::TS>>::Artifacts:
43 Into<<Self::PD as OpeningProver<Self::PB, Self::TS>>::OpeningPoints>,
44 <Self::PD as MultiRapProver<Self::PB, Self::TS>>::PartialProof:
45 Into<(GkrProof<Self::SC>, BatchConstraintProof<Self::SC>)>,
46 <Self::PD as OpeningProver<Self::PB, Self::TS>>::OpeningProof:
47 Into<(StackingProof<Self::SC>, WhirProof<Self::SC>)>,
48{
49 type SC: StarkProtocolConfig;
50 type PB: ProverBackend<
51 Val = <Self::SC as StarkProtocolConfig>::F,
52 Challenge = <Self::SC as StarkProtocolConfig>::EF,
53 Commitment = <Self::SC as StarkProtocolConfig>::Digest,
54 >;
55 type PD: ProverDevice<Self::PB, Self::TS> + DeviceDataTransporter<Self::SC, Self::PB>;
56 type TS: FiatShamirTranscript<Self::SC>;
57
58 fn new(params: SystemParams) -> Self;
61
62 fn config(&self) -> &Self::SC;
63
64 fn params(&self) -> &SystemParams {
65 self.config().params()
66 }
67
68 fn proving_memory_config(&self) -> ProvingMemoryConfig {
69 ProvingMemoryConfig::from_protocol_config(self.config(), true)
70 }
71
72 fn device(&self) -> &Self::PD;
73
74 fn initial_transcript(&self) -> Self::TS;
76
77 fn prover_from_transcript(
78 &self,
79 transcript: Self::TS,
80 ) -> Coordinator<Self::SC, Self::PB, Self::PD, Self::TS>;
81
82 fn prover(&self) -> Coordinator<Self::SC, Self::PB, Self::PD, Self::TS> {
83 let transcript = self.initial_transcript();
84 self.prover_from_transcript(transcript)
85 }
86
87 fn keygen(
88 &self,
89 airs: &[AirRef<Self::SC>],
90 ) -> (
91 MultiStarkProvingKey<Self::SC>,
92 MultiStarkVerifyingKey<Self::SC>,
93 ) {
94 let mut keygen_builder = MultiStarkKeygenBuilder::new(self.config().clone());
95 for air in airs {
96 keygen_builder.add_air(air.clone());
97 }
98
99 let pk = keygen_builder.generate_pk().unwrap();
100 let vk = pk.get_vk();
101 (pk, vk)
102 }
103
104 fn prove(
105 &self,
106 pk: &DeviceMultiStarkProvingKey<Self::PB>,
107 ctx: ProvingContext<Self::PB>,
108 ) -> Result<Proof<Self::SC>, ProverError<Self>> {
109 let mut prover = self.prover();
110 prover.prove(pk, ctx)
111 }
112
113 fn verify(
115 &self,
116 vk: &MultiStarkVerifyingKey<Self::SC>,
117 proof: &Proof<Self::SC>,
118 ) -> Result<(), VerifierError<<Self::SC as StarkProtocolConfig>::EF>> {
119 let mut transcript = self.initial_transcript();
120 verify(self.config(), vk, proof, &mut transcript)
121 }
122
123 fn debug(&self, airs: &[AirRef<Self::SC>], ctx: &ProvingContext<Self::PB>) {
127 let mut keygen_builder = MultiStarkKeygenBuilder::new(self.config().clone());
128 for air in airs {
129 keygen_builder.add_air(air.clone());
130 }
131 let pk = keygen_builder.generate_pk().unwrap();
132
133 let transpose = |mat: ColMajorMatrix<<Self::SC as StarkProtocolConfig>::F>| {
134 let row_major = StridedColMajorMatrixView::from(mat.as_view()).to_row_major_matrix();
135 Arc::new(row_major)
136 };
137 let (inputs, used_airs, used_pks): (Vec<_>, Vec<_>, Vec<_>) = ctx
138 .per_trace
139 .iter()
140 .map(|(air_id, trace_ctx)| {
141 let common_main = self
142 .device()
143 .transport_matrix_from_device_to_host(&trace_ctx.common_main);
144 let cached_mains = trace_ctx
145 .cached_mains
146 .iter()
147 .map(|cd| {
148 transpose(
149 self.device()
150 .transport_matrix_from_device_to_host(&cd.trace),
151 )
152 })
153 .collect_vec();
154 let common_main = Some(transpose(common_main));
155 let public_values = trace_ctx.public_values.clone();
156 (
157 AirProofRawInput {
158 cached_mains,
159 common_main,
160 public_values,
161 },
162 airs[*air_id].clone(),
163 &pk.per_air[*air_id],
164 )
165 })
166 .multiunzip();
167
168 debug_constraints_and_interactions(&used_airs, &used_pks, &inputs);
169 }
170
171 fn run_test(
174 &self,
175 airs: Vec<AirRef<Self::SC>>,
176 ctxs: Vec<AirProvingContext<Self::PB>>,
177 ) -> RunTestResult<Self::SC, Self::PB, Self::PD, Self::TS> {
178 let (pk, vk) = self.keygen(&airs);
179 let device = self.prover().device;
180 let d_pk = device.transport_pk_to_device(&pk);
181 let ctx = ProvingContext::new(ctxs.into_iter().enumerate().collect());
182 let proof = self.prove(&d_pk, ctx).map_err(StarkTestError::Prover)?;
183 self.verify(&vk, &proof).map_err(StarkTestError::Verifier)?;
184 Ok(VerificationData { vk, proof })
185 }
186}
187
188type RunTestResult<SC, PB, PD, TS> = Result<
189 VerificationData<SC>,
190 StarkTestError<<PD as ProverDevice<PB, TS>>::Error, <SC as StarkProtocolConfig>::EF>,
191>;
192
193#[derive(Debug)]
195pub enum StarkTestError<
196 PE: std::error::Error,
197 EF: std::fmt::Debug + std::fmt::Display + PartialEq + Eq,
198> {
199 Prover(PE),
200 Verifier(VerifierError<EF>),
201}
202
203impl<PE: std::error::Error, EF: core::fmt::Debug + core::fmt::Display + PartialEq + Eq>
204 core::fmt::Display for StarkTestError<PE, EF>
205{
206 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
207 match self {
208 Self::Prover(e) => write!(f, "Prover error: {e:?}"),
209 Self::Verifier(e) => write!(f, "Verifier error: {e}"),
210 }
211 }
212}
213
214impl<PE: std::error::Error, EF: core::fmt::Debug + core::fmt::Display + PartialEq + Eq>
215 std::error::Error for StarkTestError<PE, EF>
216{
217}