Skip to main content

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