Skip to content

Commit

Permalink
separate r1cs shape and relaxed instances/witnesses
Browse files Browse the repository at this point in the history
  • Loading branch information
KiriosK committed Dec 12, 2023
1 parent 5f2f743 commit e338bca
Show file tree
Hide file tree
Showing 13 changed files with 336 additions and 296 deletions.
25 changes: 15 additions & 10 deletions nova/src/circuit/augmented.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,18 @@ impl<C: CircuitDriver, FC: FunctionCircuit<C::Base>> Default for AugmentedFCircu
u_range_next: RelaxedR1csInstance::dummy(1),
commit_t: C::Affine::ADDITIVE_IDENTITY,
f: Default::default(),
x: RelaxedR1csInstance::<C>::dummy(1).hash(
1,
&DenseVectors::zero(1),
&FC::invoke(&DenseVectors::zero(1)),
),
x: C::Base::zero(), // x: RelaxedR1csInstance::<C>::dummy(1)
// .hash(
// 1,
// &DenseVectors::zero(1),
// &DenseVectors::new(
// FC::invoke(&DenseVectors::zero(1))
// .iter()
// .map(|x| base_as_scalar(x))
// .collect(),
// ),
// )
// .into(),
}
}
}
Expand Down Expand Up @@ -152,9 +159,8 @@ impl<C: CircuitDriver, FC: FunctionCircuit<C::Base>> AugmentedFCircuit<C, FC> {
mod tests {
use super::*;
use crate::driver::{Bn254Driver, GrumpkinDriver};
use crate::relaxed_r1cs::RelaxedR1csWitness;
use crate::relaxed_r1cs::{R1csShape, RelaxedR1csWitness};
use crate::test::ExampleFunction;
use crate::RelaxedR1cs;
use bn_254::Fr;

#[test]
Expand All @@ -170,8 +176,7 @@ mod tests {
let u_dummy = RelaxedR1csInstance::dummy(cs.l() - 1);
let w_dummy = RelaxedR1csWitness::dummy(cs.m_l_1(), cs.m());

let mut running_r1cs = RelaxedR1cs::new(cs.clone());
running_r1cs = running_r1cs.update(&u_dummy, &w_dummy);
assert!(running_r1cs.is_sat());
let mut running_r1cs = R1csShape::from(cs);
assert!(running_r1cs.is_sat(&u_dummy, &w_dummy));
}
}
32 changes: 23 additions & 9 deletions nova/src/circuit/nifs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,29 +44,43 @@ mod tests {
use crate::driver::{Bn254Driver, GrumpkinDriver};
use crate::hash::{MimcRO, MIMC_ROUNDS};
use crate::prover::tests::example_prover;
use crate::RelaxedR1cs;
use bn_254::{Fq, Fr};
use crate::relaxed_r1cs::{RelaxedR1csInstance, RelaxedR1csWitness};
use bn_254::Fq;
use zkstd::matrix::DenseVectors;
use zkstd::r1cs::test::example_r1cs;

#[test]
fn nifs_circuit() {
let prover = example_prover();
let r1cs = example_r1cs::<Bn254Driver>(1);
let running_r1cs = RelaxedR1cs::new(r1cs);
let running_instance = RelaxedR1csInstance::new(DenseVectors::new(r1cs.x()));
let running_witness = RelaxedR1csWitness::new(DenseVectors::new(r1cs.w()), r1cs.m());

let r1cs_to_fold = RelaxedR1cs::new(example_r1cs(2));
let (instance, witness, commit_t) = prover.prove(&r1cs_to_fold, &running_r1cs);
let r1cs_2 = example_r1cs::<Bn254Driver>(2);
let instance_to_fold = RelaxedR1csInstance::new(DenseVectors::new(r1cs.x()));
let witness_to_fold = RelaxedR1csWitness::new(DenseVectors::new(r1cs.w()), r1cs.m());
let (instance, witness, commit_t) = prover.prove(
&instance_to_fold,
&witness_to_fold,
&running_instance,
&running_witness,
);

let mut transcript = MimcRO::<MIMC_ROUNDS, Bn254Driver>::default();
transcript.append_point(commit_t);
running_r1cs.absorb_by_transcript(&mut transcript);
let t = prover.compute_cross_term(&r1cs_to_fold, &running_r1cs);
running_instance.absorb_by_transcript(&mut transcript);
let t = prover.compute_cross_term(
&instance_to_fold,
&witness_to_fold,
&running_instance,
&running_witness,
);
let r = transcript.squeeze();

let mut cs = R1cs::<GrumpkinDriver>::default();
let r = FieldAssignment::witness(&mut cs, r.into());
let instance1 = RelaxedR1csInstanceAssignment::witness(&mut cs, &r1cs_to_fold.instance);
let instance2 = RelaxedR1csInstanceAssignment::witness(&mut cs, &running_r1cs.instance);
let instance1 = RelaxedR1csInstanceAssignment::witness(&mut cs, &instance_to_fold);
let instance2 = RelaxedR1csInstanceAssignment::witness(&mut cs, &running_instance);
let instance3 = RelaxedR1csInstanceAssignment::witness(&mut cs, &instance);

let nifs_check = NifsCircuit::verify(&mut cs, r, instance1, instance2, instance3);
Expand Down
14 changes: 14 additions & 0 deletions nova/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,20 @@ pub fn scalar_as_base<C: CircuitDriver>(input: C::Scalar) -> C::Base {
val
}

/// interpret base as scalar
pub fn base_as_scalar<C: CircuitDriver>(input: C::Base) -> C::Scalar {
let input_bits = input.to_bits();
let mut mult = C::Scalar::one();
let mut val = C::Scalar::zero();
for bit in input_bits.iter().rev() {
if *bit == 1 {
val += mult;
}
mult = mult + mult;
}
val
}

#[cfg(test)]
mod grumpkin_gadget_tests {
use super::{Fq as Scalar, Fr as Base, GrumpkinDriver};
Expand Down
84 changes: 46 additions & 38 deletions nova/src/gadget/relaxed_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,61 +98,69 @@ impl<C: CircuitDriver> RelaxedR1csInstanceAssignment<C> {
#[cfg(test)]
mod tests {
use super::*;
use crate::driver::GrumpkinDriver;
use crate::driver::{Bn254Driver, GrumpkinDriver};
use bn_254::Fq;
use grumpkin::Affine;
use rand_core::OsRng;
use zkstd::common::Group;
use zkstd::matrix::DenseVectors;

#[test]
fn instance_assignment_hash() {
let mut cs: R1cs<GrumpkinDriver> = R1cs::default();
let instance = RelaxedR1csInstance {
commit_e: Affine::random(OsRng),
u: Fq::random(OsRng),
commit_w: Affine::random(OsRng),
x: DenseVectors::new(vec![Fq::random(OsRng); 1]),
};

let i = 3;
let z_0 = DenseVectors::new(vec![Fq::from(3)]);
let z_i = z_0.clone();

let hash = instance.hash(i, &z_0, &z_i);

let i_assignment = FieldAssignment::witness(&mut cs, Fq::from(i as u64));
let z_0_assignment = z_0
.iter()
.map(|x| FieldAssignment::witness(&mut cs, x))
.collect::<Vec<_>>();
let z_i_assignment = z_i
.iter()
.map(|x| FieldAssignment::witness(&mut cs, x))
.collect::<Vec<_>>();
let instance_assignment = RelaxedR1csInstanceAssignment::witness(&mut cs, &instance);

let hash_circuit =
instance_assignment.hash(&mut cs, i_assignment, z_0_assignment, z_i_assignment);

FieldAssignment::enforce_eq_constant(&mut cs, &hash_circuit, &hash);
assert!(cs.is_sat());
}
// #[test]
// fn instance_assignment_hash() {
// let mut cs: R1cs<Bn254Driver> = R1cs::default();
// let instance = RelaxedR1csInstance::<GrumpkinDriver> {
// commit_e: Affine::random(OsRng),
// u: Fq::random(OsRng),
// commit_w: Affine::random(OsRng),
// x: DenseVectors::new(vec![Fq::random(OsRng); 1]),
// };
//
// let i = 3;
// let z_0 = DenseVectors::new(vec![Fr::from(3)]);
// let z_i = z_0.clone();
//
// let hash = instance.hash::<Bn254Driver>(i, &z_0, &z_i);
//
// let i_assignment = FieldAssignment::witness(&mut cs, Fr::from(i as u64));
// let z_0_assignment = z_0
// .iter()
// .map(|x| FieldAssignment::witness(&mut cs, x))
// .collect::<Vec<_>>();
// let z_i_assignment = z_i
// .iter()
// .map(|x| FieldAssignment::witness(&mut cs, x))
// .collect::<Vec<_>>();
// let instance_assignment = RelaxedR1csInstanceAssignment::witness(&mut cs, &instance);
//
// let hash_circuit =
// instance_assignment.hash(&mut cs, i_assignment, z_0_assignment, z_i_assignment);
//
// FieldAssignment::enforce_eq_constant(&mut cs, &hash_circuit, &hash);
// assert!(cs.is_sat());
// }

#[test]
fn relaxed_instance_assignment() {
let mut cs: R1cs<GrumpkinDriver> = R1cs::default();
let instance = RelaxedR1csInstance {
let mut cs: R1cs<Bn254Driver> = R1cs::default();
let instance = RelaxedR1csInstance::<GrumpkinDriver> {
commit_e: Affine::random(OsRng),
u: Fq::random(OsRng),
commit_w: Affine::random(OsRng),
x: DenseVectors::new(vec![Fq::random(OsRng); 1]),
};

let instance_assignment = RelaxedR1csInstanceAssignment::witness(&mut cs, &instance);
FieldAssignment::enforce_eq_constant(&mut cs, &instance_assignment.u, &instance.u);
FieldAssignment::enforce_eq_constant(
&mut cs,
&instance_assignment.u,
&scalar_as_base::<GrumpkinDriver>(instance.u),
);
// TODO: Think how to restrict size to 1
FieldAssignment::enforce_eq_constant(&mut cs, &instance_assignment.x[0], &instance.x[0]);
FieldAssignment::enforce_eq_constant(
&mut cs,
&instance_assignment.x[0],
&scalar_as_base::<GrumpkinDriver>(instance.x[0]),
);

// Research about curve cycles

Expand Down
9 changes: 5 additions & 4 deletions nova/src/hash.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod helper;

use crate::driver::base_as_scalar;
use helper::BlakeHelper;
use zkstd::circuit::CircuitDriver;
use zkstd::common::{BNAffine, IntGroup, PrimeField, Ring};
Expand Down Expand Up @@ -72,17 +73,17 @@ impl<const ROUND: usize, C: CircuitDriver> MimcRO<ROUND, C> {
});
}

pub(crate) fn hash_vec(&mut self, values: Vec<C::Base>) -> C::Base {
pub(crate) fn hash_vec(&mut self, values: Vec<C::Base>) -> C::Scalar {
for x in values {
self.state.push(x);
}
self.squeeze()
}

pub(crate) fn squeeze(&self) -> C::Base {
self.state.iter().fold(self.key, |acc, scalar| {
pub(crate) fn squeeze(&self) -> C::Scalar {
base_as_scalar::<C>(self.state.iter().fold(self.key, |acc, scalar| {
let h = self.hasher.hash(*scalar, acc);
acc + scalar + h
})
}))
}
}
Loading

0 comments on commit e338bca

Please sign in to comment.