Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove duplicate shape object #8

Merged
merged 1 commit into from
Oct 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 11 additions & 51 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,9 @@ pub mod provider;
pub mod spartan;
pub mod traits;

use crate::bellpepper::{
r1cs::{SpartanShape, SpartanWitness},
shape_cs::ShapeCS,
solver::SatisfyingAssignment,
};
use bellpepper_core::{Circuit, ConstraintSystem};
use bellpepper_core::Circuit;
use core::marker::PhantomData;
use errors::SpartanError;
use r1cs::{R1CSShape, RelaxedR1CSInstance, RelaxedR1CSWitness};
use serde::{Deserialize, Serialize};
use traits::{
commitment::{CommitmentEngineTrait, CommitmentTrait},
Expand All @@ -47,8 +41,6 @@ where
G: Group,
S: RelaxedR1CSSNARKTrait<G>,
{
S: R1CSShape<G>,
ck: CommitmentKey<G>,
pk: S::ProverKey,
}

Expand All @@ -75,61 +67,34 @@ where
S: RelaxedR1CSSNARKTrait<G>,
C: Circuit<G::Scalar>,
{
comm_W: Commitment<G>, // commitment to the witness
io: Vec<G::Scalar>, // public IO
snark: S, // snark proving the witness is satisfying
_p: PhantomData<C>,
snark: S, // snark proving the witness is satisfying
_p: PhantomData<G>,
_p2: PhantomData<C>,
}

impl<G: Group, S: RelaxedR1CSSNARKTrait<G>, C: Circuit<G::Scalar>> SNARK<G, S, C> {
/// Produces prover and verifier keys for the direct SNARK
pub fn setup(circuit: C) -> Result<(ProverKey<G, S>, VerifierKey<G, S>), SpartanError> {
let mut cs: ShapeCS<G> = ShapeCS::new();
let _ = circuit.synthesize(&mut cs);
let (shape, ck) = cs.r1cs_shape();

let (pk, vk) = S::setup(&ck, &shape)?;
let pk = ProverKey { S: shape, ck, pk };
let vk = VerifierKey { vk };

Ok((pk, vk))
let (pk, vk) = S::setup(circuit)?;
Ok((ProverKey { pk }, VerifierKey { vk }))
}

/// Produces a proof of satisfiability of the provided circuit
pub fn prove(pk: &ProverKey<G, S>, circuit: C) -> Result<Self, SpartanError> {
let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new();
let _ = circuit.synthesize(&mut cs);

let (u, w) = cs
.r1cs_instance_and_witness(&pk.S, &pk.ck)
.map_err(|_e| SpartanError::UnSat)?;

// convert the instance and witness to relaxed form
let (u_relaxed, w_relaxed) = (
RelaxedR1CSInstance::from_r1cs_instance_unchecked(&u.comm_W, &u.X),
RelaxedR1CSWitness::from_r1cs_witness(&pk.S, &w),
);

// prove the instance using Spartan
let snark = S::prove(&pk.ck, &pk.pk, &u_relaxed, &w_relaxed)?;
let snark = S::prove(&pk.pk, circuit)?;

Ok(SNARK {
comm_W: u.comm_W,
io: u.X,
snark,
_p: Default::default(),
_p2: Default::default(),
})
}

/// Verifies a proof of satisfiability
pub fn verify(&self, vk: &VerifierKey<G, S>) -> Result<Vec<G::Scalar>, SpartanError> {
// construct an instance using the provided commitment to the witness and IO
let u_relaxed = RelaxedR1CSInstance::from_r1cs_instance_unchecked(&self.comm_W, &self.io);

pub fn verify(&self, vk: &VerifierKey<G, S>, io: &[G::Scalar]) -> Result<(), SpartanError> {
// verify the snark using the constructed instance
self.snark.verify(&vk.vk, &u_relaxed)?;

Ok(self.io.clone())
self.snark.verify(&vk.vk, io)
}
}

Expand Down Expand Up @@ -222,12 +187,7 @@ mod tests {
let snark = res.unwrap();

// verify the SNARK
let res = snark.verify(&vk);
let res = snark.verify(&vk, &[<G as Group>::Scalar::from(15u64)]);
assert!(res.is_ok());

let io = res.unwrap();

// sanity: check the claimed output with a direct computation of the same
assert_eq!(io, vec![<G as Group>::Scalar::from(15u64)]);
}
}
1 change: 1 addition & 0 deletions src/r1cs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ pub struct RelaxedR1CSInstance<G: Group> {
impl<G: Group> R1CS<G> {
/// Samples public parameters for the specified number of constraints and variables in an R1CS
pub fn commitment_key(S: &R1CSShape<G>) -> CommitmentKey<G> {
let S = S.pad(); // pad the shape before computing the commitment key
let num_cons = S.num_cons;
let num_vars = S.num_vars;
let total_nz = S.A.len() + S.B.len() + S.C.len();
Expand Down
71 changes: 48 additions & 23 deletions src/spartan/ppsnark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
//! The verifier in this preprocessing SNARK maintains a commitment to R1CS matrices. This is beneficial when using a
//! polynomial commitment scheme in which the verifier's costs is succinct.
use crate::{
bellpepper::{
r1cs::{SpartanShape, SpartanWitness},
shape_cs::ShapeCS,
solver::SatisfyingAssignment,
},
digest::{DigestComputer, SimpleDigestible},
errors::SpartanError,
r1cs::{R1CSShape, RelaxedR1CSInstance, RelaxedR1CSWitness},
Expand All @@ -25,10 +30,10 @@ use crate::{
},
Commitment, CommitmentKey, CompressedCommitment,
};
use bellpepper_core::{Circuit, ConstraintSystem};
use core::{cmp::max, marker::PhantomData};
use ff::{Field, PrimeField};
use once_cell::sync::OnceCell;

use rayon::prelude::*;
use serde::{Deserialize, Serialize};

Expand Down Expand Up @@ -656,6 +661,7 @@ impl<G: Group> SumcheckEngine<G> for InnerSumcheckInstance<G> {
#[derive(Clone, Serialize, Deserialize)]
#[serde(bound = "")]
pub struct ProverKey<G: Group, EE: EvaluationEngineTrait<G>> {
ck: CommitmentKey<G>,
pk_ee: EE::ProverKey,
S: R1CSShape<G>,
S_repr: R1CSShapeSparkRepr<G>,
Expand Down Expand Up @@ -683,6 +689,9 @@ impl<G: Group, EE: EvaluationEngineTrait<G>> SimpleDigestible for VerifierKey<G,
#[derive(Clone, Serialize, Deserialize)]
#[serde(bound = "")]
pub struct RelaxedR1CSSNARK<G: Group, EE: EvaluationEngineTrait<G>> {
// commitment to witness
comm_W: CompressedCommitment<G>,

// commitment to oracles
comm_Az: CompressedCommitment<G>,
comm_Bz: CompressedCommitment<G>,
Expand Down Expand Up @@ -876,21 +885,22 @@ impl<G: Group, EE: EvaluationEngineTrait<G>> RelaxedR1CSSNARKTrait<G> for Relaxe
type ProverKey = ProverKey<G, EE>;
type VerifierKey = VerifierKey<G, EE>;

fn setup(
ck: &CommitmentKey<G>,
S: &R1CSShape<G>,
fn setup<C: Circuit<G::Scalar>>(
circuit: C,
) -> Result<(Self::ProverKey, Self::VerifierKey), SpartanError> {
let (pk_ee, vk_ee) = EE::setup(ck);
let mut cs: ShapeCS<G> = ShapeCS::new();
let _ = circuit.synthesize(&mut cs);
let (S, ck) = cs.r1cs_shape();

// pad the R1CS matrices
let S = S.pad();
let (pk_ee, vk_ee) = EE::setup(&ck);

let S_repr = R1CSShapeSparkRepr::new(&S);
let S_comm = S_repr.commit(ck);
let S_comm = S_repr.commit(&ck);

let vk = VerifierKey::new(S.num_cons, S.num_vars, S_comm.clone(), vk_ee);

let pk = ProverKey {
ck,
pk_ee,
S,
S_repr,
Expand All @@ -902,12 +912,20 @@ impl<G: Group, EE: EvaluationEngineTrait<G>> RelaxedR1CSSNARKTrait<G> for Relaxe
}

/// produces a succinct proof of satisfiability of a `RelaxedR1CS` instance
fn prove(
ck: &CommitmentKey<G>,
pk: &Self::ProverKey,
U: &RelaxedR1CSInstance<G>,
W: &RelaxedR1CSWitness<G>,
) -> Result<Self, SpartanError> {
fn prove<C: Circuit<G::Scalar>>(pk: &Self::ProverKey, circuit: C) -> Result<Self, SpartanError> {
let mut cs: SatisfyingAssignment<G> = SatisfyingAssignment::new();
let _ = circuit.synthesize(&mut cs);

let (u, w) = cs
.r1cs_instance_and_witness(&pk.S, &pk.ck)
.map_err(|_e| SpartanError::UnSat)?;

// convert the instance and witness to relaxed form
let (U, W) = (
RelaxedR1CSInstance::from_r1cs_instance_unchecked(&u.comm_W, &u.X),
RelaxedR1CSWitness::from_r1cs_witness(&pk.S, &w),
);

let W = W.pad(&pk.S); // pad the witness
let mut transcript = G::TE::new(b"RelaxedR1CSSNARK");

Expand All @@ -919,7 +937,7 @@ impl<G: Group, EE: EvaluationEngineTrait<G>> RelaxedR1CSSNARKTrait<G> for Relaxe

// append the verifier key (which includes commitment to R1CS matrices) and the RelaxedR1CSInstance to the transcript
transcript.absorb(b"vk", &pk.vk_digest);
transcript.absorb(b"U", U);
transcript.absorb(b"U", &U);

// compute the full satisfying assignment by concatenating W.W, U.u, and U.X
let z = [W.W.clone(), vec![U.u], U.X.clone()].concat();
Expand All @@ -929,8 +947,8 @@ impl<G: Group, EE: EvaluationEngineTrait<G>> RelaxedR1CSSNARKTrait<G> for Relaxe

// commit to Az, Bz, Cz
let (comm_Az, (comm_Bz, comm_Cz)) = rayon::join(
|| G::CE::commit(ck, &Az),
|| rayon::join(|| G::CE::commit(ck, &Bz), || G::CE::commit(ck, &Cz)),
|| G::CE::commit(&pk.ck, &Az),
|| rayon::join(|| G::CE::commit(&pk.ck, &Bz), || G::CE::commit(&pk.ck, &Cz)),
);

transcript.absorb(b"c", &[comm_Az, comm_Bz, comm_Cz].as_slice());
Expand Down Expand Up @@ -969,8 +987,10 @@ impl<G: Group, EE: EvaluationEngineTrait<G>> RelaxedR1CSSNARKTrait<G> for Relaxe
// E_row(i) = eq(tau, row(i)) for all i
// E_col(i) = z(col(i)) for all i
let (mem_row, mem_col, E_row, E_col) = pk.S_repr.evaluation_oracles(&pk.S, &tau, &z);
let (comm_E_row, comm_E_col) =
rayon::join(|| G::CE::commit(ck, &E_row), || G::CE::commit(ck, &E_col));
let (comm_E_row, comm_E_col) = rayon::join(
|| G::CE::commit(&pk.ck, &E_row),
|| G::CE::commit(&pk.ck, &E_col),
);

// absorb the claimed evaluations into the transcript
transcript.absorb(
Expand Down Expand Up @@ -1090,7 +1110,7 @@ impl<G: Group, EE: EvaluationEngineTrait<G>> RelaxedR1CSSNARKTrait<G> for Relaxe
.collect::<Vec<G::Scalar>>();

let mut mem_sc_inst = ProductSumcheckInstance::new(
ck,
&pk.ck,
vec![
init_row, read_row, write_row, audit_row, init_col, read_col, write_col, audit_col,
],
Expand Down Expand Up @@ -1450,7 +1470,7 @@ impl<G: Group, EE: EvaluationEngineTrait<G>> RelaxedR1CSSNARKTrait<G> for Relaxe
.sum();

let eval_arg = EE::prove(
ck,
&pk.ck,
&pk.pk_ee,
&mut transcript,
&comm_joint,
Expand All @@ -1460,6 +1480,7 @@ impl<G: Group, EE: EvaluationEngineTrait<G>> RelaxedR1CSSNARKTrait<G> for Relaxe
)?;

Ok(RelaxedR1CSSNARK {
comm_W: U.comm_W.compress(),
comm_Az: comm_Az.compress(),
comm_Bz: comm_Bz.compress(),
comm_Cz: comm_Cz.compress(),
Expand Down Expand Up @@ -1512,13 +1533,17 @@ impl<G: Group, EE: EvaluationEngineTrait<G>> RelaxedR1CSSNARKTrait<G> for Relaxe
}

/// verifies a proof of satisfiability of a `RelaxedR1CS` instance
fn verify(&self, vk: &Self::VerifierKey, U: &RelaxedR1CSInstance<G>) -> Result<(), SpartanError> {
fn verify(&self, vk: &Self::VerifierKey, io: &[G::Scalar]) -> Result<(), SpartanError> {
// construct an instance using the provided commitment to the witness and IO
let comm_W = Commitment::<G>::decompress(&self.comm_W)?;
let U = RelaxedR1CSInstance::from_r1cs_instance_unchecked(&comm_W, io);

let mut transcript = G::TE::new(b"RelaxedR1CSSNARK");
let mut u_vec: Vec<PolyEvalInstance<G>> = Vec::new();

// append the verifier key (including commitment to R1CS matrices) and the RelaxedR1CSInstance to the transcript
transcript.absorb(b"vk", &vk.digest());
transcript.absorb(b"U", U);
transcript.absorb(b"U", &U);

let comm_Az = Commitment::<G>::decompress(&self.comm_Az)?;
let comm_Bz = Commitment::<G>::decompress(&self.comm_Bz)?;
Expand Down
Loading
Loading