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)
88//! - `cache` - Enable prepared point caching (~20-30% speedup, requires `parallel`)
89//! - `parallel` - Enable Rayon parallelization for MSMs and pairings
90
91/// Error types for Dory PCS operations
92pub mod error;
93pub mod evaluation_proof;
94pub mod messages;
95pub mod primitives;
96pub mod proof;
97pub mod reduce_and_fold;
98pub mod setup;
99
100#[cfg(feature = "arkworks")]
101pub mod backends;
102
103pub use error::DoryError;
104pub use evaluation_proof::create_evaluation_proof;
105pub use messages::{FirstReduceMessage, ScalarProductMessage, SecondReduceMessage, VMVMessage};
106use primitives::arithmetic::{DoryRoutines, Field, Group, PairingCurve};
107pub use primitives::poly::{MultilinearLagrange, Polynomial};
108use primitives::serialization::{DoryDeserialize, DorySerialize};
109pub use proof::DoryProof;
110pub use reduce_and_fold::{DoryProverState, DoryVerifierState};
111pub use setup::{ProverSetup, VerifierSetup};
112
113/// Generate or load prover and verifier setups from disk
114///
115/// Creates or loads the transparent setup parameters for Dory PCS.
116/// First attempts to load from disk; if not found, generates new setup and saves to disk.
117///
118/// Supports polynomials up to 2^max_log_n coefficients arranged as 2^ν × 2^σ matrices
119/// where ν + σ = max_log_n and ν ≤ σ (flexible matrix layouts including square and non-square).
120///
121/// Setup file location (OS-dependent):
122/// - Linux: `~/.cache/dory/dory_{max_log_n}.urs`
123/// - macOS: `~/Library/Caches/dory/dory_{max_log_n}.urs`
124/// - Windows: `{FOLDERID_LocalAppData}\dory\dory_{max_log_n}.urs`
125///
126/// # Parameters
127/// - `rng`: Random number generator for setup generation (used only if not found on disk)
128/// - `max_log_n`: Maximum log₂ of polynomial size
129///
130/// # Returns
131/// `(ProverSetup, VerifierSetup)` - Setup parameters for proving and verification
132///
133/// # Performance
134/// To enable prepared point caching (~20-30% speedup), use the `cache` feature and call
135/// `init_cache(&prover_setup.g1_vec, &prover_setup.g2_vec)` after setup.
136///
137/// # Panics
138/// Panics if the setup file exists on disk but is corrupted or cannot be deserialized.
139pub fn setup<E: PairingCurve, R: rand_core::RngCore>(
140    rng: &mut R,
141    max_log_n: usize,
142) -> (ProverSetup<E>, VerifierSetup<E>)
143where
144    ProverSetup<E>: DorySerialize + DoryDeserialize,
145    VerifierSetup<E>: DorySerialize + DoryDeserialize,
146{
147    #[cfg(feature = "disk-persistence")]
148    {
149        // Try to load from disk
150        match setup::load_setup::<E>(max_log_n) {
151            Ok(saved) => return saved,
152            Err(DoryError::InvalidURS(msg)) if msg.contains("not found") => {
153                // File doesn't exist, we'll generate new setup
154                tracing::debug!("Setup file not found, will generate new one");
155            }
156            Err(e) => {
157                // File exists but is corrupted - unrecoverable
158                panic!("Failed to load setup from disk: {}", e);
159            }
160        }
161
162        // Setup not found on disk - generate new setup
163        tracing::info!(
164            "Setup not found on disk, generating new setup for max_log_n={}",
165            max_log_n
166        );
167        let prover_setup = ProverSetup::new(rng, max_log_n);
168        let verifier_setup = prover_setup.to_verifier_setup();
169
170        // Save to disk
171        setup::save_setup(&prover_setup, &verifier_setup, max_log_n);
172
173        (prover_setup, verifier_setup)
174    }
175
176    #[cfg(not(feature = "disk-persistence"))]
177    {
178        tracing::info!("Generating new setup for max_log_n={}", max_log_n);
179
180        let prover_setup = ProverSetup::new(rng, max_log_n);
181        let verifier_setup = prover_setup.to_verifier_setup();
182
183        (prover_setup, verifier_setup)
184    }
185}
186
187/// Force generate new prover and verifier setups and save to disk
188///
189/// Always generates fresh setup parameters, ignoring any saved values on disk.
190/// Saves the newly generated setup to disk, overwriting any existing setup file
191/// for the given max_log_n.
192///
193/// Use this when you want to explicitly regenerate the setup (e.g., for testing
194/// or when you suspect the saved setup file is corrupted).
195///
196/// # Parameters
197/// - `rng`: Random number generator for setup generation
198/// - `max_log_n`: Maximum log₂ of polynomial size
199///
200/// # Returns
201/// `(ProverSetup, VerifierSetup)` - Newly generated setup parameters
202///
203/// # Availability
204/// This function is only available when the `disk-persistence` feature is enabled.
205#[cfg(feature = "disk-persistence")]
206pub fn generate_urs<E: PairingCurve, R: rand_core::RngCore>(
207    rng: &mut R,
208    max_log_n: usize,
209) -> (ProverSetup<E>, VerifierSetup<E>)
210where
211    ProverSetup<E>: DorySerialize + DoryDeserialize,
212    VerifierSetup<E>: DorySerialize + DoryDeserialize,
213{
214    tracing::info!("Force-generating new setup for max_log_n={}", max_log_n);
215
216    let prover_setup = ProverSetup::new(rng, max_log_n);
217    let verifier_setup = prover_setup.to_verifier_setup();
218
219    // Overwrites existing
220    setup::save_setup(&prover_setup, &verifier_setup, max_log_n);
221
222    (prover_setup, verifier_setup)
223}
224
225/// Evaluate a polynomial at a point and create proof
226///
227/// Creates an evaluation proof for a polynomial at a given point using precomputed
228/// tier-1 commitments (row commitments).
229///
230/// # Workflow
231/// 1. Call `polynomial.commit(nu, sigma, setup)` to get `(tier_2, row_commitments)`
232/// 2. Call this function with the `row_commitments` to create the proof
233/// 3. Use `tier_2` for verification via the `verify()` function
234///
235/// # Parameters
236/// - `polynomial`: Polynomial implementing MultilinearLagrange trait
237/// - `point`: Evaluation point (length must equal nu + sigma)
238/// - `row_commitments`: Tier-1 commitments (row commitments in G1) from `polynomial.commit()`
239/// - `nu`: Log₂ of number of rows (constraint: nu ≤ sigma for non-square matrices)
240/// - `sigma`: Log₂ of number of columns
241/// - `setup`: Prover setup
242/// - `transcript`: Fiat-Shamir transcript
243///
244/// # Returns
245/// The evaluation proof containing VMV message, reduce messages, and final message
246///
247/// # Homomorphic Properties
248/// Proofs can be created for homomorphically combined polynomials. If you have
249/// commitments Com(P₁), Com(P₂), ..., Com(Pₙ) and want to prove evaluation of
250/// r₁·P₁ + r₂·P₂ + ... + rₙ·Pₙ, you can:
251/// 1. Combine tier-2 commitments: r₁·Com(P₁) + r₂·Com(P₂) + ... + rₙ·Com(Pₙ)
252/// 2. Combine tier-1 commitments element-wise
253/// 3. Generate proof using this function with the combined polynomial
254///
255/// See `examples/homomorphic.rs` for a complete demonstration.
256///
257/// # Errors
258/// Returns `DoryError` if:
259/// - Point dimension doesn't match nu + sigma
260/// - Polynomial size doesn't match 2^(nu + sigma)
261/// - Number of row commitments doesn't match 2^nu
262#[allow(clippy::type_complexity)]
263#[tracing::instrument(skip_all, name = "prove")]
264pub fn prove<F, E, M1, M2, P, T>(
265    polynomial: &P,
266    point: &[F],
267    row_commitments: Vec<E::G1>,
268    nu: usize,
269    sigma: usize,
270    setup: &ProverSetup<E>,
271    transcript: &mut T,
272) -> Result<DoryProof<E::G1, E::G2, E::GT>, DoryError>
273where
274    F: Field,
275    E: PairingCurve,
276    E::G1: Group<Scalar = F>,
277    E::G2: Group<Scalar = F>,
278    E::GT: Group<Scalar = F>,
279    M1: DoryRoutines<E::G1>,
280    M2: DoryRoutines<E::G2>,
281    P: MultilinearLagrange<F>,
282    T: primitives::transcript::Transcript<Curve = E>,
283{
284    // Create evaluation proof using row_commitments
285    evaluation_proof::create_evaluation_proof::<F, E, M1, M2, T, P>(
286        polynomial,
287        point,
288        Some(row_commitments),
289        nu,
290        sigma,
291        setup,
292        transcript,
293    )
294}
295
296/// Verify an evaluation proof
297///
298/// Verifies that a committed polynomial evaluates to the claimed value at the given point.
299/// The matrix dimensions (nu, sigma) are extracted from the proof.
300///
301/// Works with both square and non-square matrix layouts (nu ≤ sigma), and can verify
302/// proofs for homomorphically combined polynomials.
303///
304/// # Parameters
305/// - `commitment`: Polynomial commitment (in GT) - can be a combined commitment for homomorphic proofs
306/// - `evaluation`: Claimed evaluation result
307/// - `point`: Evaluation point (length must equal proof.nu + proof.sigma)
308/// - `proof`: Evaluation proof to verify (contains nu and sigma)
309/// - `setup`: Verifier setup
310/// - `transcript`: Fiat-Shamir transcript
311///
312/// # Returns
313/// `Ok(())` if proof is valid, `Err(DoryError)` otherwise
314///
315/// # Errors
316/// Returns `DoryError::InvalidProof` if the proof is invalid, or other variants
317/// if the input parameters are incorrect (e.g., point dimension mismatch).
318#[tracing::instrument(skip_all, name = "verify")]
319pub fn verify<F, E, M1, M2, T>(
320    commitment: E::GT,
321    evaluation: F,
322    point: &[F],
323    proof: &DoryProof<E::G1, E::G2, E::GT>,
324    setup: VerifierSetup<E>,
325    transcript: &mut T,
326) -> Result<(), DoryError>
327where
328    F: Field,
329    E: PairingCurve + Clone,
330    E::G1: Group<Scalar = F>,
331    E::G2: Group<Scalar = F>,
332    E::GT: Group<Scalar = F>,
333    M1: DoryRoutines<E::G1>,
334    M2: DoryRoutines<E::G2>,
335    T: primitives::transcript::Transcript<Curve = E>,
336{
337    evaluation_proof::verify_evaluation_proof::<F, E, M1, M2, T>(
338        commitment, evaluation, point, proof, setup, transcript,
339    )
340}