Browse Source

Cleanup (#27)

* VerificationCircuit --> NIFSVerifierCircuit, for clarity

* InnerCircuit --> StepCircuit

* Rename

* cleanup imports

* additional cleanup in the test

* small cleanup
main
Srinath Setty 2 years ago
committed by GitHub
parent
commit
c20da2f58c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 95 additions and 82 deletions
  1. +1
    -0
      rustfmt.toml
  2. +1
    -2
      src/bellperson/r1cs.rs
  3. +4
    -2
      src/bellperson/shape_cs.rs
  4. +55
    -52
      src/circuit.rs
  5. +8
    -4
      src/commitments.rs
  6. +2
    -5
      src/gadgets/ecc.rs
  7. +7
    -5
      src/pasta.rs
  8. +3
    -3
      src/poseidon.rs
  9. +5
    -3
      src/r1cs.rs
  10. +9
    -6
      src/traits.rs

+ 1
- 0
rustfmt.toml

@ -2,3 +2,4 @@ edition = "2018"
tab_spaces = 2
newline_style = "Unix"
use_try_shorthand = true
imports_granularity = "crate"

+ 1
- 2
src/bellperson/r1cs.rs

@ -2,8 +2,7 @@
#![allow(non_snake_case)]
use super::shape_cs::ShapeCS;
use super::solver::SatisfyingAssignment;
use super::{shape_cs::ShapeCS, solver::SatisfyingAssignment};
use bellperson::{Index, LinearCombination};
use ff::PrimeField;

+ 4
- 2
src/bellperson/shape_cs.rs

@ -1,7 +1,9 @@
//! Support for generating R1CS shape using bellperson.
use std::cmp::Ordering;
use std::collections::{BTreeMap, HashMap};
use std::{
cmp::Ordering,
collections::{BTreeMap, HashMap},
};
use crate::traits::{Group, PrimeField as PF};
use ff::{Field, PrimeField};

+ 55
- 52
src/circuit.rs

@ -10,18 +10,19 @@
//! otherwise
//! h1 = H(u2, i) and h2 = H(params = H(shape, gens), u1, i, z0, zi)
use super::commitments::Commitment;
use super::gadgets::{
ecc::AllocatedPoint,
utils::{
alloc_bignat_constant, alloc_num_equals, alloc_one, alloc_zero, conditionally_select,
conditionally_select_bignat, le_bits_to_num,
use super::{
commitments::Commitment,
gadgets::{
ecc::AllocatedPoint,
utils::{
alloc_bignat_constant, alloc_num_equals, alloc_one, alloc_zero, conditionally_select,
conditionally_select_bignat, le_bits_to_num,
},
},
poseidon::{NovaPoseidonConstants, PoseidonROGadget},
r1cs::RelaxedR1CSInstance,
traits::{Group, PrimeField, StepCircuit},
};
use super::poseidon::NovaPoseidonConstants;
use super::poseidon::PoseidonROGadget;
use super::r1cs::RelaxedR1CSInstance;
use super::traits::{Group, InnerCircuit, PrimeField};
use bellperson::{
gadgets::{boolean::Boolean, num::AllocatedNum, Assignment},
Circuit, ConstraintSystem, SynthesisError,
@ -33,12 +34,12 @@ use bellperson_nonnative::{
use ff::PrimeFieldBits;
#[derive(Debug, Clone)]
pub struct VerificationCircuitParams {
pub struct NIFSVerifierCircuitParams {
limb_width: usize,
n_limbs: usize,
}
impl VerificationCircuitParams {
impl NIFSVerifierCircuitParams {
#[allow(dead_code)]
pub fn new(limb_width: usize, n_limbs: usize) -> Self {
Self {
@ -48,7 +49,7 @@ impl VerificationCircuitParams {
}
}
pub struct VerificationCircuitInputs<G>
pub struct NIFSVerifierCircuitInputs<G>
where
G: Group,
{
@ -63,7 +64,7 @@ where
w: Commitment<G>, // The commitment to the witness of the fresh r1cs instance
}
impl<G> VerificationCircuitInputs<G>
impl<G> NIFSVerifierCircuitInputs<G>
where
G: Group,
{
@ -95,30 +96,30 @@ where
}
/// Circuit that encodes only the folding verifier
pub struct VerificationCircuit<G, IC>
pub struct NIFSVerifierCircuit<G, SC>
where
G: Group,
<G as Group>::Base: ff::PrimeField,
IC: InnerCircuit<G::Base>,
SC: StepCircuit<G::Base>,
{
params: VerificationCircuitParams,
inputs: Option<VerificationCircuitInputs<G>>,
inner_circuit: Option<IC>, // The function that is applied for each step. may be None.
params: NIFSVerifierCircuitParams,
inputs: Option<NIFSVerifierCircuitInputs<G>>,
step_circuit: Option<SC>, // The function that is applied for each step. may be None.
poseidon_constants: NovaPoseidonConstants<G::Base>,
}
impl<G, IC> VerificationCircuit<G, IC>
impl<G, SC> NIFSVerifierCircuit<G, SC>
where
G: Group,
<G as Group>::Base: ff::PrimeField,
IC: InnerCircuit<G::Base>,
SC: StepCircuit<G::Base>,
{
/// Create a new verification circuit for the input relaxed r1cs instances
#[allow(dead_code)]
pub fn new(
params: VerificationCircuitParams,
inputs: Option<VerificationCircuitInputs<G>>,
inner_circuit: Option<IC>,
params: NIFSVerifierCircuitParams,
inputs: Option<NIFSVerifierCircuitInputs<G>>,
step_circuit: Option<SC>,
poseidon_constants: NovaPoseidonConstants<G::Base>,
) -> Self
where
@ -127,18 +128,18 @@ where
Self {
params,
inputs,
inner_circuit,
step_circuit,
poseidon_constants,
}
}
}
impl<G, IC> Circuit<<G as Group>::Base> for VerificationCircuit<G, IC>
impl<G, SC> Circuit<<G as Group>::Base> for NIFSVerifierCircuit<G, SC>
where
G: Group,
<G as Group>::Base: ff::PrimeField + PrimeField + PrimeFieldBits,
<G as Group>::Scalar: PrimeFieldBits,
IC: InnerCircuit<G::Base>,
SC: StepCircuit<G::Base>,
{
fn synthesize<CS: ConstraintSystem<<G as Group>::Base>>(
self,
@ -304,7 +305,7 @@ where
// Allocate W
/***********************************************************************/
// T = (x, y, infinity)
// W = (x, y, infinity)
let W_x = AllocatedNum::alloc(cs.namespace(|| "W.x"), || {
Ok(self.inputs.get()?.w.comm.to_coordinates().0)
})?;
@ -336,7 +337,7 @@ where
// Compute default values of U2':
let zero_commitment = AllocatedPoint::new(zero.clone(), zero.clone(), one);
//W_default and E_default are a commitment to zero
// W_default and E_default are a commitment to zero
let W_default = zero_commitment.clone();
let E_default = zero_commitment;
@ -501,7 +502,7 @@ where
.collect::<Result<Vec<AllocatedNum<G::Base>>, _>>()?;
/***********************************************************************/
//Compute i + 1
// Compute i + 1
/***********************************************************************/
let next_i = AllocatedNum::alloc(cs.namespace(|| "i + 1"), || {
@ -515,7 +516,7 @@ where
|lc| lc + next_i.get_variable() - CS::one() - i.get_variable(),
);
if self.inner_circuit.is_some() {
if self.step_circuit.is_some() {
/***********************************************************************/
//Allocate z0
/***********************************************************************/
@ -590,7 +591,7 @@ where
/***********************************************************************/
let z_next = self
.inner_circuit
.step_circuit
.unwrap()
.synthesize(&mut cs.namespace(|| "F"), z_i)?;
@ -641,12 +642,12 @@ where
h1_hash.absorb(u_r);
h1_hash.absorb(i.clone());
//absorb each of the limbs of X_r[0]
// absorb each of the limbs of X_r[0]
for limb in Xr0_bn.into_iter() {
h1_hash.absorb(limb);
}
//absorb each of the limbs of X_r[1]
// absorb each of the limbs of X_r[1]
for limb in Xr1_bn.into_iter() {
h1_hash.absorb(limb);
}
@ -698,12 +699,13 @@ where
#[cfg(test)]
mod tests {
use super::*;
use crate::bellperson::shape_cs::ShapeCS;
use crate::bellperson::solver::SatisfyingAssignment;
use crate::bellperson::{shape_cs::ShapeCS, solver::SatisfyingAssignment};
type G1 = pasta_curves::pallas::Point;
type G2 = pasta_curves::vesta::Point;
use crate::bellperson::r1cs::{NovaShape, NovaWitness};
use crate::commitments::CommitTrait;
use crate::{
bellperson::r1cs::{NovaShape, NovaWitness},
commitments::CommitTrait,
};
use std::marker::PhantomData;
struct TestCircuit<F>
@ -713,7 +715,7 @@ mod tests {
_p: PhantomData<F>,
}
impl<F> InnerCircuit<F> for TestCircuit<F>
impl<F> StepCircuit<F> for TestCircuit<F>
where
F: PrimeField + ff::PrimeField,
{
@ -729,12 +731,12 @@ mod tests {
#[test]
fn test_verification_circuit() {
// We experiment with 8 limbs of 32 bits each
let params = VerificationCircuitParams::new(32, 8);
let params = NIFSVerifierCircuitParams::new(32, 8);
// The first circuit that verifies G2
let poseidon_constants1: NovaPoseidonConstants<<G2 as Group>::Base> =
NovaPoseidonConstants::new();
let circuit1: VerificationCircuit<G2, TestCircuit<<G2 as Group>::Base>> =
VerificationCircuit::new(
let circuit1: NIFSVerifierCircuit<G2, TestCircuit<<G2 as Group>::Base>> =
NIFSVerifierCircuit::new(
params.clone(),
None,
Some(TestCircuit {
@ -745,8 +747,7 @@ mod tests {
// First create the shape
let mut cs: ShapeCS<G1> = ShapeCS::new();
let _ = circuit1.synthesize(&mut cs);
let shape1 = cs.r1cs_shape();
let gens1 = cs.r1cs_gens();
let (shape1, gens1) = (cs.r1cs_shape(), cs.r1cs_gens());
println!(
"Circuit1 -> Number of constraints: {}",
cs.num_constraints()
@ -755,28 +756,29 @@ mod tests {
// The second circuit that verifies G1
let poseidon_constants2: NovaPoseidonConstants<<G1 as Group>::Base> =
NovaPoseidonConstants::new();
let circuit2: VerificationCircuit<G1, TestCircuit<<G1 as Group>::Base>> =
VerificationCircuit::new(params.clone(), None, None, poseidon_constants2);
let circuit2: NIFSVerifierCircuit<G1, TestCircuit<<G1 as Group>::Base>> =
NIFSVerifierCircuit::new(params.clone(), None, None, poseidon_constants2);
// First create the shape
let mut cs: ShapeCS<G2> = ShapeCS::new();
let _ = circuit2.synthesize(&mut cs);
let shape2 = cs.r1cs_shape();
let gens2 = cs.r1cs_gens();
let (shape2, gens2) = (cs.r1cs_shape(), cs.r1cs_gens());
println!(
"Circuit2 -> Number of constraints: {}",
cs.num_constraints()
);
//TODO: We need to hardwire default hash or give it as input
// TODO: We need to hardwire default hash or give it as input
let default_hash = <<G2 as Group>::Base as ff::PrimeField>::from_str_vartime(
"332553638888022689042501686561503049809",
)
.unwrap();
let T = vec![<G2 as Group>::Scalar::zero()].commit(&gens2.gens_E);
let w = vec![<G2 as Group>::Scalar::zero()].commit(&gens2.gens_E);
// Now get an assignment
let mut cs: SatisfyingAssignment<G1> = SatisfyingAssignment::new();
let inputs: VerificationCircuitInputs<G2> = VerificationCircuitInputs::new(
let inputs: NIFSVerifierCircuitInputs<G2> = NIFSVerifierCircuitInputs::new(
default_hash,
RelaxedR1CSInstance::default(&gens2, &shape2),
<<G2 as Group>::Base as PrimeField>::zero(), // TODO: provide real inputs
@ -787,8 +789,9 @@ mod tests {
T, // TODO: provide real inputs
w,
);
let circuit: VerificationCircuit<G2, TestCircuit<<G2 as Group>::Base>> =
VerificationCircuit::new(
let circuit: NIFSVerifierCircuit<G2, TestCircuit<<G2 as Group>::Base>> =
NIFSVerifierCircuit::new(
params,
Some(inputs),
Some(TestCircuit {

+ 8
- 4
src/commitments.rs

@ -1,7 +1,11 @@
use super::errors::NovaError;
use super::traits::{CompressedGroup, Group};
use core::fmt::Debug;
use core::ops::{Add, AddAssign, Mul, MulAssign};
use super::{
errors::NovaError,
traits::{CompressedGroup, Group},
};
use core::{
fmt::Debug,
ops::{Add, AddAssign, Mul, MulAssign},
};
use digest::{ExtendableOutput, Input};
use merlin::Transcript;
use sha3::Shake256;

+ 2
- 5
src/gadgets/ecc.rs

@ -619,12 +619,9 @@ mod tests {
assert_eq!(e_pasta, e_pasta_2);
}
use crate::bellperson::shape_cs::ShapeCS;
use crate::bellperson::solver::SatisfyingAssignment;
use crate::bellperson::{shape_cs::ShapeCS, solver::SatisfyingAssignment};
use ff::{Field, PrimeFieldBits};
use pasta_curves::arithmetic::CurveAffine;
use pasta_curves::group::Curve;
use pasta_curves::EpAffine;
use pasta_curves::{arithmetic::CurveAffine, group::Curve, EpAffine};
use std::ops::Mul;
type G = pasta_curves::pallas::Point;
type Fp = pasta_curves::pallas::Scalar;

+ 7
- 5
src/pasta.rs

@ -1,13 +1,15 @@
//! This module implements the Nova traits for pallas::Point, pallas::Scalar, vesta::Point, vesta::Scalar.
use crate::traits::{ChallengeTrait, CompressedGroup, Group, PrimeField};
use merlin::Transcript;
use pasta_curves::arithmetic::{CurveAffine, CurveExt, FieldExt, Group as Grp};
use pasta_curves::group::{Curve, GroupEncoding};
use pasta_curves::{self, pallas, vesta, Ep, Eq, Fp, Fq};
use pasta_curves::{
self,
arithmetic::{CurveAffine, CurveExt, FieldExt, Group as Grp},
group::{Curve, GroupEncoding},
pallas, vesta, Ep, Eq, Fp, Fq,
};
use rand::{CryptoRng, RngCore};
use rug::Integer;
use std::borrow::Borrow;
use std::ops::Mul;
use std::{borrow::Borrow, ops::Mul};
//////////////////////////////////////Pallas///////////////////////////////////////////////

+ 3
- 3
src/poseidon.rs

@ -189,9 +189,9 @@ mod tests {
use super::*;
type S = pasta_curves::pallas::Scalar;
type G = pasta_curves::pallas::Point;
use crate::bellperson::solver::SatisfyingAssignment;
use crate::gadgets::utils::le_bits_to_num;
use crate::traits::PrimeField;
use crate::{
bellperson::solver::SatisfyingAssignment, gadgets::utils::le_bits_to_num, traits::PrimeField,
};
use rand::rngs::OsRng;
#[test]

+ 5
- 3
src/r1cs.rs

@ -1,8 +1,10 @@
//! This module defines R1CS related types and a folding scheme for Relaxed R1CS
#![allow(clippy::type_complexity)]
use super::commitments::{CommitGens, CommitTrait, Commitment, CompressedCommitment};
use super::errors::NovaError;
use super::traits::{Group, PrimeField};
use super::{
commitments::{CommitGens, CommitTrait, Commitment, CompressedCommitment},
errors::NovaError,
traits::{Group, PrimeField},
};
use itertools::concat;
use rayon::prelude::*;

+ 9
- 6
src/traits.rs

@ -1,8 +1,10 @@
//! This module defines various traits required by the users of the library to implement.
use bellperson::{gadgets::num::AllocatedNum, ConstraintSystem, SynthesisError};
use core::borrow::Borrow;
use core::fmt::Debug;
use core::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};
use core::{
borrow::Borrow,
fmt::Debug,
ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign},
};
use merlin::Transcript;
use rand::{CryptoRng, RngCore};
use rug::Integer;
@ -131,9 +133,10 @@ impl ScalarMul for T where T: Mul
pub trait ScalarMulOwned<Rhs, Output = Self>: for<'r> ScalarMul<&'r Rhs, Output> {}
impl<T, Rhs, Output> ScalarMulOwned<Rhs, Output> for T where T: for<'r> ScalarMul<&'r Rhs, Output> {}
///A helper trait for the inner circuit F
pub trait InnerCircuit<F: PrimeField + ff::PrimeField> {
///Sythesize the circuit for a computation step and return variable that corresponds to z_{i+1}
/// A helper trait for a step of the incremental computation (i.e., circuit for F)
pub trait StepCircuit<F: PrimeField + ff::PrimeField> {
/// Sythesize the circuit for a computation step and return variable
/// that corresponds to the output of the step z_{i+1}
fn synthesize<CS: ConstraintSystem<F>>(
&self,
cs: &mut CS,

Loading…
Cancel
Save