Skip to main content

provekit_common/
noir_proof_scheme.rs

1use {
2    crate::{
3        whir_r1cs::{WhirR1CSProof, WhirR1CSScheme},
4        witness::{NoirWitnessGenerator, SplitWitnessBuilders},
5        NoirElement, PublicInputs, R1CS,
6    },
7    acir::circuit::Program,
8    anyhow::{Context, Result},
9    base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _},
10    serde::{Deserialize, Serialize},
11};
12
13/// A scheme for proving a Noir program.
14#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct NoirProofScheme {
16    pub program:                Program<NoirElement>,
17    pub r1cs:                   R1CS,
18    pub split_witness_builders: SplitWitnessBuilders,
19    pub witness_generator:      NoirWitnessGenerator,
20    pub whir_for_witness:       WhirR1CSScheme,
21}
22
23#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
24pub struct NoirProof {
25    pub public_inputs:   PublicInputs,
26    pub whir_r1cs_proof: WhirR1CSProof,
27}
28
29impl NoirProofScheme {
30    #[must_use]
31    pub const fn size(&self) -> (usize, usize) {
32        (self.r1cs.num_constraints(), self.r1cs.num_witnesses())
33    }
34}
35
36impl NoirProof {
37    /// Encode to a portable text form: CBOR, wrapped in base64url (no padding).
38    pub fn encode(&self) -> Result<String> {
39        let mut cbor = Vec::new();
40        ciborium::into_writer(self, &mut cbor).context("CBOR encode NoirProof")?;
41        Ok(URL_SAFE_NO_PAD.encode(cbor))
42    }
43
44    /// Inverse of [`encode`](Self::encode).
45    pub fn decode(s: &str) -> Result<Self> {
46        let cbor = URL_SAFE_NO_PAD
47            .decode(s.as_bytes())
48            .context("base64url decode NoirProof")?;
49        ciborium::from_reader(cbor.as_slice()).context("CBOR decode NoirProof")
50    }
51}