Skip to content

Commit

Permalink
Integrate folding
Browse files Browse the repository at this point in the history
  • Loading branch information
dannywillems committed May 29, 2024
1 parent aa0f95a commit 99ff70a
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 64 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions ivc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ edition = "2021"
ark-bn254.workspace = true
ark-ec.workspace = true
ark-ff.workspace = true
ark-poly.workspace = true
folding.workspace = true
kimchi.workspace = true
kimchi-msm.workspace = true
mina-poseidon.workspace = true
Expand All @@ -16,5 +18,6 @@ o1-utils.workspace = true
once_cell.workspace = true
poly-commitment.workspace = true
rand.workspace = true
rayon.workspace = true
strum.workspace = true
strum_macros.workspace = true
3 changes: 2 additions & 1 deletion ivc/src/test/columns.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use kimchi_msm::columns::{Column, ColumnIndexer};
use strum_macros::{EnumCount as EnumCountMacro, EnumIter};

#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, EnumIter, EnumCountMacro)]
pub enum AdditionColumn {
A,
B,
Expand Down
250 changes: 187 additions & 63 deletions ivc/src/test/mod.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
use ark_ec::{AffineCurve, ProjectiveCurve};
use ark_poly::Evaluations;
use folding::{
expressions::FoldingColumnTrait, instance_witness::Foldable, Alphas, FoldingConfig, FoldingEnv,
Instance, Side, Witness,
};
use kimchi::{circuits::gate::CurrOrNext, curve::KimchiCurve};
use kimchi_msm::witness::Witness as GenericWitness;
use mina_poseidon::{
constants::PlonkSpongeConstantsKimchi,
sponge::{DefaultFqSponge, DefaultFrSponge},
FqSponge,
};
use std::collections::BTreeMap;
use std::{array, ops::Index};
use strum::EnumCount;
use strum_macros::{EnumCount as EnumCountMacro, EnumIter};

use ark_ff::UniformRand;
use ark_poly::Radix2EvaluationDomain;
use kimchi::circuits::domains::EvaluationDomains;
use kimchi_msm::{
circuit_design::{ColWriteCap, ConstraintBuilderEnv, WitnessBuilderEnv},
columns::Column,
lookups::DummyLookupTable,
prover::prove,
verifier::verify,
witness::Witness,
};
use poly_commitment::srs::SRS;

use poly_commitment::pairing_proof::{PairingProof, PairingSRS};
use rand::{CryptoRng, RngCore};

Expand All @@ -22,9 +34,12 @@ mod columns;
mod interpreters;

pub type Fp = ark_bn254::Fr;
pub type BN254 = ark_ec::bn::Bn<ark_bn254::Parameters>;
pub type SpongeParams = PlonkSpongeConstantsKimchi;
pub type Curve = ark_bn254::G1Affine;

pub type BaseSponge = DefaultFqSponge<ark_bn254::g1::Parameters, SpongeParams>;
pub type SpongeParams = PlonkSpongeConstantsKimchi;

pub type BN254 = ark_ec::bn::Bn<ark_bn254::Parameters>;
pub type ScalarSponge = DefaultFrSponge<Fp, SpongeParams>;
pub type OpeningProof = PairingProof<BN254>;

Expand All @@ -47,7 +62,172 @@ pub fn test_simple_add() {
let domain_size: usize = 1 << 5;
let domain = EvaluationDomains::<Fp>::create(domain_size).unwrap();

let srs: PairingSRS<BN254> = get_bn254_srs(&mut rng, domain);
let mut fq_sponge: BaseSponge = FqSponge::new(Curve::other_curve_sponge_params());
let mut srs = SRS::<Curve>::create(domain_size);
srs.add_lagrange_basis(domain.d1);

// ---- Defining the folding configuration ----
// FoldingConfig
#[derive(Clone, Debug, Copy, Eq, PartialEq, Hash)]
pub struct Config;

impl FoldingColumnTrait for AdditionColumn {
fn is_witness(&self) -> bool {
true
}
}

// Folding Witness
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct PlonkishWitness {
pub witness: GenericWitness<3, Evaluations<Fp, Radix2EvaluationDomain<Fp>>>,
}

// Trait required for folding

impl Foldable<Fp> for PlonkishWitness {
fn combine(mut a: Self, b: Self, challenge: Fp) -> Self {
for (a, b) in (*a.witness.cols).iter_mut().zip(*(b.witness.cols)) {
for (a, b) in a.evals.iter_mut().zip(b.evals) {
*a += challenge * b;
}
}
a
}
}

impl Witness<Curve> for PlonkishWitness {}

impl Index<Column> for PlonkishWitness {
type Output = Evaluations<Fp, Radix2EvaluationDomain<Fp>>;

/// Map a column alias to the corresponding witness column.
fn index(&self, index: Column) -> &Self::Output {
match index {
Column::Relation(0) => &self.witness.cols[0],
Column::Relation(1) => &self.witness.cols[1],
Column::Relation(2) => &self.witness.cols[2],
_ => panic!("Invalid column index"),
}
}
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, EnumIter, EnumCountMacro)]
pub enum Challenge {
Beta,
Gamma,
JointCombiner,
}

#[derive(Clone, Debug)]
struct PlonkishInstance {
commitments: [Curve; AdditionColumn::COUNT],
challenges: [Fp; Challenge::COUNT],
alphas: Alphas<Fp>,
}

impl Foldable<Fp> for PlonkishInstance {
fn combine(a: Self, b: Self, challenge: Fp) -> Self {
Self {
commitments: array::from_fn(|i| {
a.commitments[i] + b.commitments[i].mul(challenge).into_affine()
}),
challenges: array::from_fn(|i| a.challenges[i] + challenge * b.challenges[i]),
alphas: Alphas::combine(a.alphas, b.alphas, challenge),
}
}
}

impl Instance<Curve> for PlonkishInstance {
fn to_absorb(&self) -> (Vec<Fp>, Vec<Curve>) {
// FIXME: check!!!!
let mut scalars = Vec::new();
let mut points = Vec::new();
points.extend(self.commitments);
scalars.extend(self.challenges);
scalars.extend(self.alphas.clone().powers());
(scalars, points)
}

fn get_alphas(&self) -> &Alphas<Fp> {
&self.alphas
}
}

pub struct PlonkishEnvironment {
/// Structure of the folded circuit
pub structure: (),
/// Commitments to the witness columns, for both sides
pub instances: [PlonkishInstance; 2],
/// Corresponds to the omega evaluations, for both sides
pub curr_witnesses: [PlonkishWitness; 2],
/// Corresponds to the zeta*omega evaluations, for both sides
/// This is curr_witness but left shifted by 1
pub next_witnesses: [PlonkishWitness; 2],
}

impl FoldingEnv<Fp, PlonkishInstance, PlonkishWitness, Column, Challenge, ()>
for PlonkishEnvironment
where
PlonkishWitness: Index<Column, Output = Evaluations<Fp, Radix2EvaluationDomain<Fp>>>,
{
type Structure = ();

fn new(
structure: &(),
instances: [&PlonkishInstance; 2],
witnesses: [&PlonkishWitness; 2],
) -> Self {
let curr_witnesses = [witnesses[0].clone(), witnesses[1].clone()];
let mut next_witnesses = curr_witnesses.clone();
for side in next_witnesses.iter_mut() {
for col in side.witness.cols.iter_mut() {
col.evals.rotate_left(1);
}
}
PlonkishEnvironment {
// FIXME: This is a clone, but it should be a reference
structure: (),
instances: [instances[0].clone(), instances[1].clone()],
curr_witnesses,
next_witnesses,
}
}

fn col(&self, col: Column, curr_or_next: CurrOrNext, side: Side) -> &Vec<Fp> {
let wit = match curr_or_next {
CurrOrNext::Curr => &self.curr_witnesses[side as usize],
CurrOrNext::Next => &self.next_witnesses[side as usize],
};
// The following is possible because Index is implemented for our
// circuit witnesses
&wit[col].evals
}

fn challenge(&self, challenge: Challenge, side: Side) -> Fp {
match challenge {
Challenge::Beta => self.instances[side as usize].challenges[0],
Challenge::Gamma => self.instances[side as usize].challenges[1],
Challenge::JointCombiner => self.instances[side as usize].challenges[2],
}
}

fn selector(&self, _s: &(), _side: Side) -> &Vec<Fp> {
unimplemented!("Selector not implemented for FoldingEnvironment. No selectors are supposed to be used when it is Plonkish relations.")
}
}

impl FoldingConfig for Config {
type Column = Column;
type Selector = ();
type Challenge = ();
type Curve = Curve;
type Srs = SRS<Curve>;
type Instance = PlonkishInstance;
type Witness = PlonkishWitness;
type Structure = ();
type Env = PlonkishEnvironment;
}

let constraints = {
let mut constraint_env = ConstraintBuilderEnv::<Fp, DummyLookupTable>::create();
Expand All @@ -62,8 +242,6 @@ pub fn test_simple_add() {
let mut witness_two: WitnessBuilderEnv<Fp, AdditionColumn, 3, 3, 0, 0, DummyLookupTable> =
WitnessBuilderEnv::create();

let empty_lookups = BTreeMap::new();

// Witness one
for _i in 0..domain_size {
let a: Fp = Fp::rand(&mut rng);
Expand All @@ -83,58 +261,4 @@ pub fn test_simple_add() {
interpreters::interpreter_simple_add(&mut witness_two);
witness_two.next_row();
}

// Verify individual witnesses before folding
{
let proof_inputs = witness_one.get_proof_inputs(domain, empty_lookups.clone());
// generate the proof
let proof =
prove::<_, OpeningProof, BaseSponge, ScalarSponge, _, 3, 3, 0, 0, DummyLookupTable>(
domain,
&srs,
&constraints,
proof_inputs,
&mut rng,
)
.unwrap();

// verify the proof
let verifies =
verify::<_, OpeningProof, BaseSponge, ScalarSponge, 3, 3, 0, 0, 0, DummyLookupTable>(
domain,
&srs,
&constraints,
&proof,
Witness::zero_vec(domain_size),
);

assert!(verifies);
}

// Verify individual witnesses before folding
{
let proof_inputs = witness_two.get_proof_inputs(domain, empty_lookups.clone());
// generate the proof
let proof =
prove::<_, OpeningProof, BaseSponge, ScalarSponge, _, 3, 3, 0, 0, DummyLookupTable>(
domain,
&srs,
&constraints,
proof_inputs,
&mut rng,
)
.unwrap();

// verify the proof
let verifies =
verify::<_, OpeningProof, BaseSponge, ScalarSponge, 3, 3, 0, 0, 0, DummyLookupTable>(
domain,
&srs,
&constraints,
&proof,
Witness::zero_vec(domain_size),
);

assert!(verifies);
}
}

0 comments on commit 99ff70a

Please sign in to comment.