rsnark_provers_core/
circuit_prover.rs

1use std::marker::PhantomData;
2
3use anyhow::Result;
4use rsnark_core::{CircuitPublicWitness, CircuitWitness, types};
5
6use crate::Backend;
7
8/// Circuit-specific prover for generating and verifying zero-knowledge proofs.
9///
10/// The `CircuitProver` is created by compiling a specific circuit with a [`crate::Prover`] and
11/// contains the compiled circuit constraints. It provides methods for performing trusted
12/// setup, generating proofs, and verifying proofs for the compiled circuit.
13///
14/// # Type Parameters
15///
16/// * `B` - The backend implementation that defines the underlying cryptographic operations
17/// * `C` - The circuit witness type that this prover was compiled for
18///
19/// # Workflow
20///
21/// 1. Create via [`crate::Prover::compile_circuit()`]
22/// 2. Perform trusted setup with [`CircuitProver::setup()`]
23/// 3. Generate proofs with [`CircuitProver::prove()`]
24/// 4. Verify proofs with [`CircuitProver::verify()`]
25///
26pub struct CircuitProver<B, C>
27where
28    B: Backend,
29{
30    pub(crate) backend: B,
31    pub(crate) constraint: B::CircuitConstraint,
32    pub(crate) marker: PhantomData<C>,
33}
34
35impl<B, C> CircuitProver<B, C>
36where
37    B: Backend,
38    C: CircuitWitness,
39{
40    /// Performs the trusted setup phase for this compiled circuit.
41    ///
42    /// This generates the proving and verifying keys that are specific to the compiled
43    /// circuit constraints. The setup must be performed before any proofs can be generated
44    /// or verified.
45    ///
46    /// # Returns
47    ///
48    /// Returns a tuple containing the proving key and verifying key on success.
49    /// The proving key is used for generating proofs, while the verifying key is used
50    /// for verifying proofs.
51    ///
52    /// # Errors
53    ///
54    /// This function may return an error if the backend's setup operation fails,
55    /// which could happen due to:
56    /// - Cryptographic errors during key generation
57    /// - Insufficient randomness for secure setup
58    /// - Backend-specific setup failures
59    ///
60    /// # Security Note
61    ///
62    /// The security of all subsequent proofs depends on this setup being performed
63    /// correctly and any setup randomness ("toxic waste") being properly discarded.
64    ///
65    pub fn setup(&self) -> Result<(B::ProvingKey, B::VerifyingKey)> {
66        Ok(self.backend.setup(&self.constraint)?)
67    }
68
69    /// Generates a zero-knowledge proof for the given circuit witness.
70    ///
71    /// This method creates a proof that demonstrates knowledge of a valid witness
72    /// satisfying the circuit constraints, without revealing the private components
73    /// of the witness.
74    ///
75    /// # Arguments
76    ///
77    /// * `proving_key` - The proving key generated by [`CircuitProver::setup()`]
78    /// * `circuit_witness` - The complete witness including both public and private values
79    ///
80    /// # Returns
81    ///
82    /// Returns the generated zero-knowledge proof on success.
83    ///
84    /// # Errors
85    ///
86    /// This function may return an error if:
87    /// - The circuit witness does not satisfy the circuit constraints
88    /// - The proving key is incompatible with the circuit
89    /// - Cryptographic operations fail during proof generation
90    /// - The witness values are malformed or invalid
91    ///
92    pub fn prove(&self, proving_key: &B::ProvingKey, circuit_witness: &C) -> Result<B::Proof> {
93        let mut public = Vec::new();
94        let mut private = Vec::new();
95
96        circuit_witness.append_witness(&mut public, &mut private, false);
97
98        let witness = types::Witness::from((public, private));
99        let proof = self
100            .backend
101            .prove(&self.constraint, proving_key, &witness)?;
102
103        Ok(proof)
104    }
105
106    /// Verifies a zero-knowledge proof against the given public witness.
107    ///
108    /// This method checks whether a proof is valid for the specified public inputs,
109    /// without requiring knowledge of the private witness components that were used
110    /// to generate the proof.
111    ///
112    /// # Arguments
113    ///
114    /// * `verifying_key` - The verifying key generated by [`CircuitProver::setup()`]
115    /// * `proof` - The proof to verify
116    /// * `public_witness` - The public inputs and outputs that should match the proof
117    ///
118    /// # Returns
119    ///
120    /// Returns `Ok(())` if the proof is valid, or an error if verification fails.
121    ///
122    /// # Errors
123    ///
124    /// This function may return an error if:
125    /// - The proof is invalid or malformed
126    /// - The public witness does not match the proof
127    /// - The verifying key is incompatible with the circuit
128    /// - Cryptographic verification operations fail
129    ///
130    /// # Type Constraints
131    ///
132    /// The public witness type must implement [`CircuitPublicWitness`] to ensure
133    /// it can be properly converted to the internal witness format.
134    ///
135    pub fn verify(
136        &self,
137        verifying_key: &B::VerifyingKey,
138        proof: &B::Proof,
139        public_witness: C::PublicWitness,
140    ) -> Result<()>
141    where
142        C::PublicWitness: CircuitPublicWitness,
143    {
144        let mut witness = types::PublicWitness::new();
145
146        public_witness.append_public_witness(witness.public_mut(), false);
147
148        self.backend.verify(verifying_key, proof, &witness)?;
149
150        Ok(())
151    }
152}