rsnark_provers_core/
circuit_prover.rs

1use std::marker::PhantomData;
2
3use anyhow::Result;
4use rsnark_core::{CircuitPublicWitness, CircuitWitness, types};
5
6use crate::{Backend, Proof};
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<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
100        let proof = self
101            .backend
102            .prove(&self.constraint, proving_key, &witness)?;
103
104        Ok(proof)
105    }
106
107    /// Verifies a zero-knowledge proof against the given public witness.
108    ///
109    /// This method checks whether a proof is valid for the specified public inputs,
110    /// without requiring knowledge of the private witness components that were used
111    /// to generate the proof.
112    ///
113    /// # Arguments
114    ///
115    /// * `verifying_key` - The verifying key generated by [`CircuitProver::setup()`]
116    /// * `proof` - The proof to verify
117    /// * `public_witness` - The public inputs and outputs that should match the proof
118    ///
119    /// # Returns
120    ///
121    /// Returns `Ok(())` if the proof is valid, or an error if verification fails.
122    ///
123    /// # Errors
124    ///
125    /// This function may return an error if:
126    /// - The proof is invalid or malformed
127    /// - The public witness does not match the proof
128    /// - The verifying key is incompatible with the circuit
129    /// - Cryptographic verification operations fail
130    ///
131    /// # Type Constraints
132    ///
133    /// The public witness type must implement [`CircuitPublicWitness`] to ensure
134    /// it can be properly converted to the internal witness format.
135    ///
136    pub fn verify(
137        &self,
138        verifying_key: &B::VerifyingKey,
139        proof: &Proof,
140        public_witness: C::PublicWitness,
141    ) -> Result<()>
142    where
143        C::PublicWitness: CircuitPublicWitness,
144    {
145        let mut witness = types::PublicWitness::new();
146
147        public_witness.append_public_witness(witness.public_mut(), false);
148
149        self.backend.verify(verifying_key, proof, &witness)?;
150
151        Ok(())
152    }
153}