dory_pcs/lib.rs
1//! # dory
2//!
3//! A high performance and modular implementation of the Dory polynomial commitment scheme.
4//!
5//! Dory is a transparent polynomial commitment scheme with excellent asymptotic
6//! performance, based on the work of Jonathan Lee
7//! ([eprint 2020/1274](https://eprint.iacr.org/2020/1274)).
8//!
9//! ## Key Features
10//!
11//! - **Transparent setup** with automatic disk persistence
12//! - **Logarithmic proof size**: O(log n) group elements
13//! - **Logarithmic verification**: O(log n) GT exps and 5 pairings
14//! - **Performance optimizations**: Optional prepared point caching (~20-30% speedup) and parallelization
15//! - **Flexible matrix layouts**: Supports both square and non-square matrices (nu ≤ sigma)
16//! - **Homomorphic properties**: Com(r₁·P₁ + r₂·P₂ + ... + rₙ·Pₙ) = r₁·Com(P₁) + r₂·Com(P₂) + ... + rₙ·Com(Pₙ)
17//!
18//! ## Structure
19//!
20//! ### Core Modules
21//! - [`primitives`] - Core traits and abstractions
22//! - [`primitives::arithmetic`] - Field, group, and pairing curve traits
23//! - [`primitives::poly`] - Multilinear polynomial traits and operations
24//! - [`primitives::transcript`] - Fiat-Shamir transcript trait
25//! - [`primitives::serialization`] - Serialization abstractions
26//! - [`mod@setup`] - Transparent setup generation for prover and verifier
27//! - [`evaluation_proof`] - Evaluation proof creation and verification
28//! - [`reduce_and_fold`] - Inner product protocol state machines (prover/verifier)
29//! - [`messages`] - Protocol message structures (VMV, reduce rounds, scalar product)
30//! - [`proof`] - Complete proof data structure
31//! - [`error`] - Error types
32//!
33//! ### Backend Implementations
34//! - `backends` - Concrete backend implementations (available with feature flags)
35//! - `backends::arkworks` - Arkworks backend with BN254 curve (requires `arkworks` feature)
36//!
37//! ## Usage
38//!
39//! ### Basic Example
40//!
41//! ```ignore
42//! use dory_pcs::{setup, prove, verify};
43//! use dory_pcs::backends::arkworks::{BN254, G1Routines, G2Routines, Blake2bTranscript};
44//!
45//! // 1. Generate setup (automatically loads from/saves to disk)
46//! let (prover_setup, verifier_setup) = setup::<BN254, _>(&mut rng, max_log_n);
47//!
48//! // 2. Commit to polynomial
49//! let (tier_2_commitment, tier_1_commitments) = polynomial
50//! .commit::<BN254, G1Routines>(nu, sigma, &prover_setup)?;
51//!
52//! // 3. Generate evaluation proof
53//! let mut prover_transcript = Blake2bTranscript::new(b"domain-separation");
54//! let proof = prove::<_, BN254, G1Routines, G2Routines, _, _>(
55//! &polynomial, &point, tier_1_commitments, nu, sigma,
56//! &prover_setup, &mut prover_transcript
57//! )?;
58//!
59//! // 4. Verify
60//! let mut verifier_transcript = Blake2bTranscript::new(b"domain-separation");
61//! verify::<_, BN254, G1Routines, G2Routines, _>(
62//! tier_2_commitment, evaluation, &point, &proof,
63//! verifier_setup, &mut verifier_transcript
64//! )?;
65//! ```
66//!
67//! ### Performance Optimization
68//!
69//! Enable prepared point caching for ~20-30% pairing speedup (requires `cache` feature):
70//! ```ignore
71//! use dory_pcs::backends::arkworks::init_cache;
72//!
73//! let (prover_setup, verifier_setup) = setup::<BN254, _>(&mut rng, max_log_n);
74//! init_cache(&prover_setup.g1_vec, &prover_setup.g2_vec);
75//! // Subsequent operations will automatically use cached prepared points
76//! ```
77//!
78//! ### Examples
79//!
80//! See the `examples/` directory for complete demonstrations:
81//! - `basic_e2e.rs` - Standard square matrix workflow
82//! - `homomorphic.rs` - Homomorphic combination of multiple polynomials
83//! - `non_square.rs` - Non-square matrix layout (nu < sigma)
84//!
85//! ## Feature Flags
86//!
87//! - `backends` - Enable concrete backends (currently Arkworks BN254, includes `disk-persistence`)
88//! - `cache` - Enable prepared point caching (~20-30% speedup, requires `parallel`)
89//! - `parallel` - Enable Rayon parallelization for MSMs and pairings
90//! - `disk-persistence` - Enable automatic setup caching to disk
91
92/// Error types for Dory PCS operations
93pub mod error;
94pub mod evaluation_proof;
95pub mod messages;
96pub mod primitives;
97pub mod proof;
98pub mod reduce_and_fold;
99pub mod setup;
100
101#[cfg(feature = "arkworks")]
102pub mod backends;
103
104pub use error::DoryError;
105pub use evaluation_proof::create_evaluation_proof;
106pub use messages::{FirstReduceMessage, ScalarProductMessage, SecondReduceMessage, VMVMessage};
107use primitives::arithmetic::{DoryRoutines, Field, Group, PairingCurve};
108pub use primitives::poly::{MultilinearLagrange, Polynomial};
109use primitives::serialization::{DoryDeserialize, DorySerialize};
110pub use proof::DoryProof;
111pub use reduce_and_fold::{DoryProverState, DoryVerifierState};
112pub use setup::{ProverSetup, VerifierSetup};
113
114/// Generate or load prover and verifier setups from disk
115///
116/// Creates or loads the transparent setup parameters for Dory PCS.
117/// First attempts to load from disk; if not found, generates new setup and saves to disk.
118///
119/// Supports polynomials up to 2^max_log_n coefficients arranged as 2^ν × 2^σ matrices
120/// where ν + σ = max_log_n and ν ≤ σ (flexible matrix layouts including square and non-square).
121///
122/// Setup file location (OS-dependent):
123/// - Linux: `~/.cache/dory/dory_{max_log_n}.urs`
124/// - macOS: `~/Library/Caches/dory/dory_{max_log_n}.urs`
125/// - Windows: `{FOLDERID_LocalAppData}\dory\dory_{max_log_n}.urs`
126///
127/// # Parameters
128/// - `rng`: Random number generator for setup generation (used only if not found on disk)
129/// - `max_log_n`: Maximum log₂ of polynomial size
130///
131/// # Returns
132/// `(ProverSetup, VerifierSetup)` - Setup parameters for proving and verification
133///
134/// # Performance
135/// To enable prepared point caching (~20-30% speedup), use the `cache` feature and call
136/// `init_cache(&prover_setup.g1_vec, &prover_setup.g2_vec)` after setup.
137///
138/// # Panics
139/// Panics if the setup file exists on disk but is corrupted or cannot be deserialized.
140pub fn setup<E: PairingCurve, R: rand_core::RngCore>(
141 rng: &mut R,
142 max_log_n: usize,
143) -> (ProverSetup<E>, VerifierSetup<E>)
144where
145 ProverSetup<E>: DorySerialize + DoryDeserialize,
146 VerifierSetup<E>: DorySerialize + DoryDeserialize,
147{
148 #[cfg(feature = "disk-persistence")]
149 {
150 // Try to load from disk
151 match setup::load_setup::<E>(max_log_n) {
152 Ok(saved) => return saved,
153 Err(DoryError::InvalidURS(msg)) if msg.contains("not found") => {
154 // File doesn't exist, we'll generate new setup
155 tracing::debug!("Setup file not found, will generate new one");
156 }
157 Err(e) => {
158 // File exists but is corrupted - unrecoverable
159 panic!("Failed to load setup from disk: {e}");
160 }
161 }
162
163 // Setup not found on disk - generate new setup
164 tracing::info!(
165 "Setup not found on disk, generating new setup for max_log_n={}",
166 max_log_n
167 );
168 let prover_setup = ProverSetup::new(rng, max_log_n);
169 let verifier_setup = prover_setup.to_verifier_setup();
170
171 // Save to disk
172 setup::save_setup(&prover_setup, &verifier_setup, max_log_n);
173
174 (prover_setup, verifier_setup)
175 }
176
177 #[cfg(not(feature = "disk-persistence"))]
178 {
179 tracing::info!("Generating new setup for max_log_n={}", max_log_n);
180
181 let prover_setup = ProverSetup::new(rng, max_log_n);
182 let verifier_setup = prover_setup.to_verifier_setup();
183
184 (prover_setup, verifier_setup)
185 }
186}
187
188/// Force generate new prover and verifier setups and save to disk
189///
190/// Always generates fresh setup parameters, ignoring any saved values on disk.
191/// Saves the newly generated setup to disk, overwriting any existing setup file
192/// for the given max_log_n.
193///
194/// Use this when you want to explicitly regenerate the setup (e.g., for testing
195/// or when you suspect the saved setup file is corrupted).
196///
197/// # Parameters
198/// - `rng`: Random number generator for setup generation
199/// - `max_log_n`: Maximum log₂ of polynomial size
200///
201/// # Returns
202/// `(ProverSetup, VerifierSetup)` - Newly generated setup parameters
203///
204/// # Availability
205/// This function is only available when the `disk-persistence` feature is enabled.
206#[cfg(feature = "disk-persistence")]
207pub fn generate_urs<E: PairingCurve, R: rand_core::RngCore>(
208 rng: &mut R,
209 max_log_n: usize,
210) -> (ProverSetup<E>, VerifierSetup<E>)
211where
212 ProverSetup<E>: DorySerialize + DoryDeserialize,
213 VerifierSetup<E>: DorySerialize + DoryDeserialize,
214{
215 tracing::info!("Force-generating new setup for max_log_n={}", max_log_n);
216
217 let prover_setup = ProverSetup::new(rng, max_log_n);
218 let verifier_setup = prover_setup.to_verifier_setup();
219
220 // Overwrites existing
221 setup::save_setup(&prover_setup, &verifier_setup, max_log_n);
222
223 (prover_setup, verifier_setup)
224}
225
226/// Evaluate a polynomial at a point and create proof
227///
228/// Creates an evaluation proof for a polynomial at a given point using precomputed
229/// tier-1 commitments (row commitments).
230///
231/// # Workflow
232/// 1. Call `polynomial.commit(nu, sigma, setup)` to get `(tier_2, row_commitments)`
233/// 2. Call this function with the `row_commitments` to create the proof
234/// 3. Use `tier_2` for verification via the `verify()` function
235///
236/// # Parameters
237/// - `polynomial`: Polynomial implementing MultilinearLagrange trait
238/// - `point`: Evaluation point (length must equal nu + sigma)
239/// - `row_commitments`: Tier-1 commitments (row commitments in G1) from `polynomial.commit()`
240/// - `nu`: Log₂ of number of rows (constraint: nu ≤ sigma for non-square matrices)
241/// - `sigma`: Log₂ of number of columns
242/// - `setup`: Prover setup
243/// - `transcript`: Fiat-Shamir transcript
244///
245/// # Returns
246/// The evaluation proof containing VMV message, reduce messages, and final message
247///
248/// # Homomorphic Properties
249/// Proofs can be created for homomorphically combined polynomials. If you have
250/// commitments Com(P₁), Com(P₂), ..., Com(Pₙ) and want to prove evaluation of
251/// r₁·P₁ + r₂·P₂ + ... + rₙ·Pₙ, you can:
252/// 1. Combine tier-2 commitments: r₁·Com(P₁) + r₂·Com(P₂) + ... + rₙ·Com(Pₙ)
253/// 2. Combine tier-1 commitments element-wise
254/// 3. Generate proof using this function with the combined polynomial
255///
256/// See `examples/homomorphic.rs` for a complete demonstration.
257///
258/// # Errors
259/// Returns `DoryError` if:
260/// - Point dimension doesn't match nu + sigma
261/// - Polynomial size doesn't match 2^(nu + sigma)
262/// - Number of row commitments doesn't match 2^nu
263#[allow(clippy::type_complexity)]
264#[tracing::instrument(skip_all, name = "prove")]
265pub fn prove<F, E, M1, M2, P, T>(
266 polynomial: &P,
267 point: &[F],
268 row_commitments: Vec<E::G1>,
269 nu: usize,
270 sigma: usize,
271 setup: &ProverSetup<E>,
272 transcript: &mut T,
273) -> Result<DoryProof<E::G1, E::G2, E::GT>, DoryError>
274where
275 F: Field,
276 E: PairingCurve,
277 E::G1: Group<Scalar = F>,
278 E::G2: Group<Scalar = F>,
279 E::GT: Group<Scalar = F>,
280 M1: DoryRoutines<E::G1>,
281 M2: DoryRoutines<E::G2>,
282 P: MultilinearLagrange<F>,
283 T: primitives::transcript::Transcript<Curve = E>,
284{
285 // Create evaluation proof using row_commitments
286 evaluation_proof::create_evaluation_proof::<F, E, M1, M2, T, P>(
287 polynomial,
288 point,
289 Some(row_commitments),
290 nu,
291 sigma,
292 setup,
293 transcript,
294 )
295}
296
297/// Verify an evaluation proof
298///
299/// Verifies that a committed polynomial evaluates to the claimed value at the given point.
300/// The matrix dimensions (nu, sigma) are extracted from the proof.
301///
302/// Works with both square and non-square matrix layouts (nu ≤ sigma), and can verify
303/// proofs for homomorphically combined polynomials.
304///
305/// # Parameters
306/// - `commitment`: Polynomial commitment (in GT) - can be a combined commitment for homomorphic proofs
307/// - `evaluation`: Claimed evaluation result
308/// - `point`: Evaluation point (length must equal proof.nu + proof.sigma)
309/// - `proof`: Evaluation proof to verify (contains nu and sigma)
310/// - `setup`: Verifier setup
311/// - `transcript`: Fiat-Shamir transcript
312///
313/// # Returns
314/// `Ok(())` if proof is valid, `Err(DoryError)` otherwise
315///
316/// # Errors
317/// Returns `DoryError::InvalidProof` if the proof is invalid, or other variants
318/// if the input parameters are incorrect (e.g., point dimension mismatch).
319#[tracing::instrument(skip_all, name = "verify")]
320pub fn verify<F, E, M1, M2, T>(
321 commitment: E::GT,
322 evaluation: F,
323 point: &[F],
324 proof: &DoryProof<E::G1, E::G2, E::GT>,
325 setup: VerifierSetup<E>,
326 transcript: &mut T,
327) -> Result<(), DoryError>
328where
329 F: Field,
330 E: PairingCurve + Clone,
331 E::G1: Group<Scalar = F>,
332 E::G2: Group<Scalar = F>,
333 E::GT: Group<Scalar = F>,
334 M1: DoryRoutines<E::G1>,
335 M2: DoryRoutines<E::G2>,
336 T: primitives::transcript::Transcript<Curve = E>,
337{
338 evaluation_proof::verify_evaluation_proof::<F, E, M1, M2, T>(
339 commitment, evaluation, point, proof, setup, transcript,
340 )
341}