openvm_stark_backend/prover/hal.rs
1use std::sync::Arc;
2
3use serde::{de::DeserializeOwned, Serialize};
4
5use crate::{
6 keygen::types::MultiStarkProvingKey,
7 prover::{
8 stacked_pcs::StackedPcsData, AirProvingContext, ColMajorMatrix, CommittedTraceData,
9 CpuColMajorBackend, DeviceMultiStarkProvingKey, ProvingContext,
10 },
11 StarkProtocolConfig,
12};
13
14pub trait MatrixDimensions {
15 fn height(&self) -> usize;
16 fn width(&self) -> usize;
17}
18
19/// Associated types needed by the prover, in the form of buffers and views,
20/// specific to a specific hardware backend.
21///
22/// Memory allocation and copying is not handled by this trait.
23pub trait ProverBackend {
24 /// Extension field degree for the challenge field `Self::Challenge` over base field
25 /// `Self::Val`.
26 const CHALLENGE_EXT_DEGREE: u8;
27 // ==== Host Types ====
28 /// Base field type, on host.
29 type Val: Copy + Send + Sync + Serialize + DeserializeOwned;
30 /// Challenge field (extension field of base field), on host.
31 type Challenge: Copy + Send + Sync + Serialize + DeserializeOwned;
32 /// Single commitment on host.
33 // Commitments are small in size and need to be transferred back to host to be included in
34 // proof.
35 type Commitment: Clone + Send + Sync + Serialize + DeserializeOwned;
36
37 // ==== Device Types ====
38 /// Single matrix buffer on device together with dimension metadata. Owning this means nothing
39 /// else has a shared reference to the buffer.
40 type Matrix: MatrixDimensions + Send + Sync;
41 /// Backend specific type for any pre-computed data associated with a single AIR. For example,
42 /// it may contain prover-specific precomputations based on the AIR constraints (but
43 /// independent from any trace data).
44 type OtherAirData: Send + Sync;
45 /// Owned buffer for the preimage of a PCS commitment on device, together with any metadata
46 /// necessary for computing opening proofs.
47 ///
48 /// For example, multiple buffers for LDE matrices, their trace domain sizes, and pointer to
49 /// mixed merkle tree.
50 type PcsData: Send + Sync;
51}
52
53pub trait ProverDevice<PB: ProverBackend, TS>:
54 TraceCommitter<PB> + MultiRapProver<PB, TS> + OpeningProver<PB, TS>
55{
56 type Error: 'static
57 + std::error::Error
58 + Send
59 + Sync
60 + From<<Self as TraceCommitter<PB>>::Error>
61 + From<<Self as MultiRapProver<PB, TS>>::Error>
62 + From<<Self as OpeningProver<PB, TS>>::Error>;
63
64 /// Device-specific context (e.g., CUDA stream). Unit `()` for CPU devices.
65 type DeviceCtx: Clone + Send + Sync;
66
67 fn device_ctx(&self) -> &Self::DeviceCtx;
68}
69
70/// Provides functionality for committing to a batch of trace matrices, possibly of different
71/// heights.
72pub trait TraceCommitter<PB: ProverBackend> {
73 type Error: std::fmt::Debug;
74 fn commit(&self, traces: &[&PB::Matrix]) -> Result<(PB::Commitment, PB::PcsData), Self::Error>;
75}
76
77/// This trait is responsible for the proving steps that reduce AIR zerocheck constraints and
78/// interaction consistency claims to polynomial opening claims.
79///
80/// This trait is _not_ responsible for committing to trace matrices or for checking polynomial
81/// openings against PCS commitments.
82pub trait MultiRapProver<PB: ProverBackend, TS> {
83 /// The partial proof is the proof that the trace matrices satisfy all constraints assuming that
84 /// certain polynomial opening claims are validated. In other words, it is a proof that reduces
85 /// the constraint satisfaction claim to certain polynomial opening claims.
86 type PartialProof: Clone + Send + Sync + Serialize + DeserializeOwned;
87 /// Other artifacts of the proof (e.g., sampled randomness) that may be passed to later stages
88 /// of the protocol.
89 type Artifacts;
90
91 type Error: std::fmt::Debug;
92
93 fn prove_rap_constraints(
94 &self,
95 transcript: &mut TS,
96 mpk: &DeviceMultiStarkProvingKey<PB>,
97 ctx: &ProvingContext<PB>,
98 common_main_pcs_data: &PB::PcsData,
99 ) -> Result<(Self::PartialProof, Self::Artifacts), Self::Error>;
100}
101
102/// This trait is responsible for proving the evaluation claims of a collection of polynomials at a
103/// collection of points. The opening point may be the same across polynomials. The polynomials may
104/// be defined over different domains and are hence of "mixed" nature. The polynomials are already
105/// committed and provided in their committed form.
106pub trait OpeningProver<PB: ProverBackend, TS> {
107 /// PCS opening proof on host. This should not be a reference.
108 type OpeningProof: Clone + Send + Sync + Serialize + DeserializeOwned;
109 type OpeningPoints;
110
111 /// Computes the opening proof.
112 /// The `common_main_pcs_data` is the `PcsData` for the collection of common main trace
113 /// matrices. It is owned by the function and may be mutated.
114 /// The `pre_cached_pcs_data_per_commit` is the `PcsData` for the preprocessed and cached trace
115 /// matrices. These are specified by their `PcsData` per commitment.
116 type Error: std::fmt::Debug;
117
118 fn prove_openings(
119 &self,
120 transcript: &mut TS,
121 mpk: &DeviceMultiStarkProvingKey<PB>,
122 ctx: ProvingContext<PB>,
123 common_main_pcs_data: PB::PcsData,
124 points: Self::OpeningPoints,
125 ) -> Result<Self::OpeningProof, Self::Error>;
126}
127
128/// Trait to manage data transport of prover types from host to device.
129pub trait DeviceDataTransporter<SC, PB>
130where
131 SC: StarkProtocolConfig,
132 PB: ProverBackend<Val = SC::F, Challenge = SC::EF, Commitment = SC::Digest>,
133{
134 /// Transport the proving key to the device, filtering for only the provided `air_ids`.
135 fn transport_pk_to_device(
136 &self,
137 mpk: &MultiStarkProvingKey<SC>,
138 ) -> DeviceMultiStarkProvingKey<PB>;
139
140 fn transport_matrix_to_device(&self, matrix: &ColMajorMatrix<SC::F>) -> PB::Matrix;
141
142 /// The `commitment` and `prover_data` are assumed to have been previously computed from the
143 /// `trace`.
144 fn transport_pcs_data_to_device(
145 &self,
146 pcs_data: &StackedPcsData<SC::F, SC::Digest>,
147 ) -> PB::PcsData;
148
149 fn transport_committed_trace_data_to_device(
150 &self,
151 committed_trace: &CommittedTraceData<CpuColMajorBackend<SC>>,
152 ) -> CommittedTraceData<PB> {
153 let trace = self.transport_matrix_to_device(&committed_trace.trace);
154 let data = self.transport_pcs_data_to_device(committed_trace.data.as_ref());
155
156 CommittedTraceData {
157 commitment: committed_trace.commitment,
158 trace,
159 data: Arc::new(data),
160 }
161 }
162
163 fn transport_proving_ctx_to_device(
164 &self,
165 ctx: &ProvingContext<CpuColMajorBackend<SC>>,
166 ) -> ProvingContext<PB> {
167 let per_trace = ctx
168 .per_trace
169 .iter()
170 .map(|(air_idx, trace_ctx)| {
171 let common_main = self.transport_matrix_to_device(&trace_ctx.common_main);
172 let cached_mains = trace_ctx
173 .cached_mains
174 .iter()
175 .map(|cd| self.transport_committed_trace_data_to_device(cd))
176 .collect();
177 let trace_ctx_gpu = AirProvingContext::new(
178 cached_mains,
179 common_main,
180 trace_ctx.public_values.clone(),
181 );
182 (*air_idx, trace_ctx_gpu)
183 })
184 .collect();
185 ProvingContext::new(per_trace)
186 }
187
188 // ==================================================================================
189 // Device-to-Host methods below should only be used for testing / debugging purposes.
190 // ==================================================================================
191
192 /// Transport a device matrix to host. This should only be used for testing / debugging
193 /// purposes.
194 fn transport_matrix_from_device_to_host(&self, matrix: &PB::Matrix) -> ColMajorMatrix<SC::F>;
195}