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}