Skip to content
Open
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
2 changes: 2 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ repository = "https://github.com/privacy-scaling-explorations/sonobe/"
rust-version = "1.85.1"

[workspace.dependencies]
itertools = { version = "0.14.0" }
num-bigint = { version = "0.4.3" }
num-integer = { version = "0.1" }
num-traits = { version = "0.2" }
Expand Down
1 change: 1 addition & 0 deletions crates/fs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ ark-r1cs-std = { workspace = true }
ark-relations = { workspace = true }
ark-std = { workspace = true, features = ["getrandom"] }
ark-serialize = { workspace = true }
itertools = { workspace = true }
num-bigint = { workspace = true, features = ["rand"] }
thiserror = { workspace = true }
rayon = { workspace = true }
Expand Down
10 changes: 6 additions & 4 deletions crates/fs/src/definitions/instances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ use super::utils::TaggedVec;

/// [`FoldingInstance`] defines the operations that a folding scheme's instance
/// should support.
pub trait FoldingInstance<CM: CommitmentDef>: Clone + Debug + PartialEq + Eq + Absorbable {
pub trait FoldingInstance<CM: CommitmentDef>:
Clone + Debug + PartialEq + Eq + Absorbable + for<'a> Dummy<&'a ArithConfig>
{
/// [`FoldingInstance::N_COMMITMENTS`] defines the number of commitments
/// contained in the instance.
const N_COMMITMENTS: usize;
Expand Down Expand Up @@ -44,9 +46,9 @@ pub trait FoldingInstance<CM: CommitmentDef>: Clone + Debug + PartialEq + Eq + A
/// `'u'` for it.
pub type PlainInstance<V> = TaggedVec<V, 'u'>;

impl<V: Default + Clone, A: ArithConfig> Dummy<&A> for PlainInstance<V> {
fn dummy(cfg: &A) -> Self {
vec![V::default(); cfg.n_public_inputs()].into()
impl<V: Default + Clone> Dummy<&ArithConfig> for PlainInstance<V> {
fn dummy(cfg: &ArithConfig) -> Self {
vec![V::default(); cfg.n_public_inputs].into()
}
}

Expand Down
9 changes: 3 additions & 6 deletions crates/fs/src/definitions/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,12 @@ pub trait DeciderKey: CanonicalSerialize + CanonicalDeserialize {
/// [`DeciderKey::VerifierKey`] is the type of the verifier key contained in
/// the decider key.
type VerifierKey;
/// [`DeciderKey::ArithConfig`] is the constraint system configuration
/// associated with the folding scheme.
type ArithConfig: ArithConfig;

/// [`DeciderKey::to_pk`] returns the reference to the prover key.
fn to_pk(&self) -> &Self::ProverKey;
/// [`DeciderKey::to_vk`] returns the reference to the verifier key.
fn to_vk(&self) -> &Self::VerifierKey;
/// [`DeciderKey::to_arith_config`] returns the reference to the constraint
/// system configuration.
fn to_arith_config(&self) -> &Self::ArithConfig;
/// [`DeciderKey::to_arith_config`] returns the constraint system
/// configuration.
fn to_arith_config(&self) -> ArithConfig;
}
15 changes: 7 additions & 8 deletions crates/fs/src/definitions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub mod witnesses;

use ark_r1cs_std::{GR1CSVar, alloc::AllocVar};
use sonobe_primitives::{
arithmetizations::Arith,
arithmetizations::{Arith, ArithConfig},
circuits::AssignmentsOwned,
commitments::{CommitmentDef, CommitmentDefGadget},
relations::{Relation, WitnessInstanceSampler},
Expand Down Expand Up @@ -54,19 +54,19 @@ pub trait FoldingSchemeDef {
/// scheme.
type CM: CommitmentDef<Scalar: SonobeField>;
/// [`FoldingSchemeDef::RW`] is the type of running witness.
type RW: FoldingWitness<Self::CM> + for<'a> Dummy<&'a <Self::Arith as Arith>::Config>;
type RW: FoldingWitness<Self::CM>;
/// [`FoldingSchemeDef::RU`] is the type of running instance.
type RU: FoldingInstance<Self::CM> + for<'a> Dummy<&'a <Self::Arith as Arith>::Config>;
type RU: FoldingInstance<Self::CM>;
/// [`FoldingSchemeDef::IW`] is the type of incoming witness.
type IW: FoldingWitness<Self::CM> + for<'a> Dummy<&'a <Self::Arith as Arith>::Config>;
type IW: FoldingWitness<Self::CM>;
/// [`FoldingSchemeDef::IU`] is the type of incoming instance.
type IU: FoldingInstance<Self::CM> + for<'a> Dummy<&'a <Self::Arith as Arith>::Config>;
type IU: FoldingInstance<Self::CM>;
/// [`FoldingSchemeDef::TranscriptField`] is the field type used in the
/// transcript of the folding scheme.
type TranscriptField: SonobeField;
/// [`FoldingSchemeDef::Arith`] is the constraint system supported by the
/// folding scheme.
type Arith: Arith<Config = <Self::DeciderKey as DeciderKey>::ArithConfig>;
type Arith: Arith;
/// [`FoldingSchemeDef::Config`] is the type of configuration required to
/// generate the public parameters of the folding scheme.
type Config;
Expand All @@ -92,8 +92,7 @@ pub trait FoldingSchemeDef {
type Challenge;
/// [`FoldingSchemeDef::Proof`] is the type of proof generated by the
/// folding prover.
type Proof<const M: usize, const N: usize>: Clone
+ for<'a> Dummy<&'a <Self::Arith as Arith>::Config>;
type Proof<const M: usize, const N: usize>: Clone + for<'a> Dummy<&'a ArithConfig>;
}

/// [`FoldingSchemeDefGadget`] specifies the in-circuit associated types for a
Expand Down
8 changes: 4 additions & 4 deletions crates/fs/src/definitions/witnesses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use super::utils::TaggedVec;

/// [`FoldingWitness`] defines the operations that a folding scheme's witness
/// should support.
pub trait FoldingWitness<CM: CommitmentDef>: Debug {
pub trait FoldingWitness<CM: CommitmentDef>: Debug + for<'a> Dummy<&'a ArithConfig> {
/// [`FoldingWitness::N_OPENINGS`] defines the number of openings contained
/// in the witness.
const N_OPENINGS: usize;
Expand All @@ -33,9 +33,9 @@ pub trait FoldingWitness<CM: CommitmentDef>: Debug {
/// `'w'` for it.
pub type PlainWitness<V> = TaggedVec<V, 'w'>;

impl<V: Default + Clone, A: ArithConfig> Dummy<&A> for PlainWitness<V> {
fn dummy(cfg: &A) -> Self {
vec![V::default(); cfg.n_witnesses()].into()
impl<V: Default + Clone> Dummy<&ArithConfig> for PlainWitness<V> {
fn dummy(cfg: &ArithConfig) -> Self {
vec![V::default(); cfg.n_witnesses].into()
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/fs/src/nova/algorithms/key_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

use ark_std::sync::Arc;
use sonobe_primitives::{
arithmetizations::{Arith, ArithConfig},
arithmetizations::Arith,
commitments::{CommitmentKey, GroupBasedCommitment},
traits::SonobeField,
};
Expand All @@ -16,7 +16,7 @@ impl<CM: GroupBasedCommitment, TF: SonobeField, const B: usize> FoldingSchemeKey
let ck = Arc::new(ck);
let r1cs = Arc::new(r1cs);
let cfg = r1cs.config();
if ck.max_scalars_len() < cfg.n_constraints().max(cfg.n_witnesses()) {
if ck.max_scalars_len() < cfg.n_constraints.max(cfg.n_witnesses) {
return Err(Error::InvalidPublicParameters(
"The commitment key is too short for the R1CS instance".into(),
));
Expand Down
35 changes: 23 additions & 12 deletions crates/fs/src/nova/algorithms/prover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

use ark_ff::{Field, One};
use ark_std::{borrow::Borrow, cfg_into_iter, cfg_iter, ops::Mul, rand::RngCore};
#[cfg(not(feature = "parallel"))]
use itertools::Itertools;
#[cfg(feature = "parallel")]
use rayon::prelude::*;
use sonobe_primitives::{
Expand Down Expand Up @@ -30,19 +32,19 @@ fn cross_term<'a, F: Field>(

// Compute the cross term `T` by following the optimized approach in
// [Mova](https://eprint.iacr.org/2024/1220.pdf)'s section 5.2.
let v = arith.evaluate_at(AssignmentsOwned::from((
let v = arith.evaluate_r1cs(AssignmentsOwned::from((
z1.constant + z2.constant,
cfg_iter!(z1.public)
.zip(z2.public)
.zip_eq(z2.public)
.map(|(a, b)| *a + b)
.collect(),
cfg_iter!(z1.private)
.zip(z2.private)
.zip_eq(z2.private)
.map(|(a, b)| *a + b)
.collect(),
)))?;
Ok(cfg_into_iter!(v)
.zip(e)
.zip_eq(e)
.map(|(a, b)| a - b.borrow())
.collect())
}
Expand Down Expand Up @@ -72,16 +74,25 @@ impl<CM: GroupBasedCommitment, TF: SonobeField, const B: usize> FoldingSchemePro
let rho = CM::Scalar::from_bits_le(&rho_bits);

let WW = Self::RW {
e: cfg_iter!(W.e).zip(&t).map(|(a, b)| rho * b + a).collect(),
e: cfg_iter!(W.e)
.zip_eq(&t)
.map(|(a, b)| rho * b + a)
.collect(),
r_e: W.r_e + r_t * rho,
w: cfg_iter!(W.w).zip(&w.w).map(|(a, b)| rho * b + a).collect(),
w: cfg_iter!(W.w)
.zip_eq(&w.w)
.map(|(a, b)| rho * b + a)
.collect(),
r_w: W.r_w + w.r_w * rho,
};
let UU = Self::RU {
cm_e: U.cm_e + cm_t.mul(rho),
u: U.u + rho,
cm_w: U.cm_w + u.cm_w.mul(rho),
x: cfg_iter!(U.x).zip(&u.x).map(|(a, b)| rho * b + a).collect(),
x: cfg_iter!(U.x)
.zip_eq(&u.x)
.map(|(a, b)| rho * b + a)
.collect(),
};
Ok((WW, UU, cm_t, rho_bits.try_into().unwrap()))
}
Expand All @@ -104,7 +115,7 @@ impl<CM: GroupBasedCommitment, TF: SonobeField, const B: usize> FoldingSchemePro
let (W2, U2) = (W2.borrow(), U2.borrow());

let (z1, z2) = ((U1.u, &U1.x[..], &W1.w[..]), (U2.u, &U2.x[..], &W2.w[..]));
let e = cfg_iter!(W1.e).zip(&W2.e).map(|(a, b)| *a + b);
let e = cfg_iter!(W1.e).zip_eq(&W2.e).map(|(a, b)| *a + b);
let t = cross_term(&pk.arith, z1, z2, e)?;

let (cm_t, r_t) = CM::commit(&pk.ck, &t, rng)?;
Expand All @@ -115,13 +126,13 @@ impl<CM: GroupBasedCommitment, TF: SonobeField, const B: usize> FoldingSchemePro

let WW = Self::RW {
e: cfg_iter!(W1.e)
.zip(&t)
.zip(&W2.e)
.zip_eq(&t)
.zip_eq(&W2.e)
.map(|((a, b), c)| rho_squared * c + rho * b + a)
.collect(),
r_e: W1.r_e + r_t * rho + W2.r_e * rho_squared,
w: cfg_iter!(W1.w)
.zip(&W2.w)
.zip_eq(&W2.w)
.map(|(a, b)| rho * b + a)
.collect(),
r_w: W1.r_w + W2.r_w * rho,
Expand All @@ -131,7 +142,7 @@ impl<CM: GroupBasedCommitment, TF: SonobeField, const B: usize> FoldingSchemePro
u: U1.u + rho * U2.u,
cm_w: U1.cm_w + U2.cm_w.mul(rho),
x: cfg_iter!(U1.x)
.zip(&U2.x)
.zip_eq(&U2.x)
.map(|(a, b)| rho * b + a)
.collect(),
};
Expand Down
9 changes: 7 additions & 2 deletions crates/fs/src/nova/algorithms/verifier.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! Proof verification for Nova.

use ark_std::{borrow::Borrow, cfg_iter, ops::Mul};
#[cfg(not(feature = "parallel"))]
use itertools::Itertools;
#[cfg(feature = "parallel")]
use rayon::prelude::*;
use sonobe_primitives::{
Expand Down Expand Up @@ -30,7 +32,10 @@ impl<CM: GroupBasedCommitment, TF: SonobeField, const B: usize> FoldingSchemeVer
cm_e: U.cm_e + cm_t.mul(rho),
u: U.u + rho,
cm_w: U.cm_w + u.cm_w.mul(rho),
x: cfg_iter!(U.x).zip(&u.x).map(|(a, b)| rho * b + a).collect(),
x: cfg_iter!(U.x)
.zip_eq(&u.x)
.map(|(a, b)| rho * b + a)
.collect(),
})
}
}
Expand All @@ -57,7 +62,7 @@ impl<CM: GroupBasedCommitment, TF: SonobeField, const B: usize> FoldingSchemeVer
u: U1.u + rho * U2.u,
cm_w: U1.cm_w + U2.cm_w.mul(rho),
x: cfg_iter!(U1.x)
.zip(&U2.x)
.zip_eq(&U2.x)
.map(|(a, b)| rho * b + a)
.collect(),
})
Expand Down
12 changes: 12 additions & 0 deletions crates/fs/src/nova/circuits/verifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ where
let rho_bits = transcript.add(&U)?.add(&u)?.add(proof)?.challenge_bits(B)?;
let rho = CM::ScalarVar::from_bits_le(&rho_bits)?;

if U.x.len() != u.x.len() {
return Err(SynthesisError::Unsatisfiable);
}

Ok((
Self::RU {
u: (U.u.clone() + &rho)
Expand Down Expand Up @@ -73,6 +77,10 @@ where
let rho_bits = transcript.add(&(U1, U2))?.add(proof)?.challenge_bits(B)?;
let rho = CM::ScalarVar::from_bits_le(&rho_bits)?;

if U1.x.len() != U2.x.len() {
return Err(SynthesisError::Unsatisfiable);
}

Ok((
Self::RU {
u: (U2.u.clone() * &rho + &U1.u)
Expand Down Expand Up @@ -123,6 +131,10 @@ where
let rho_bits = transcript.add(&U)?.add(&u)?.add(proof)?.challenge_bits(B)?;
let rho = CM::ScalarVar::from_bits_le(&rho_bits)?;

if U.x.len() != u.x.len() {
return Err(SynthesisError::Unsatisfiable);
}

Ok(Self::RU {
u: (U.u.clone() + &rho)
.try_into()
Expand Down
12 changes: 6 additions & 6 deletions crates/fs/src/nova/instances/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,13 @@ impl<CM: CommitmentDef> FoldingInstance<CM> for RunningInstance<CM> {
}
}

impl<CM: CommitmentDef, Cfg: ArithConfig> Dummy<&Cfg> for RunningInstance<CM> {
fn dummy(cfg: &Cfg) -> Self {
impl<CM: CommitmentDef> Dummy<&ArithConfig> for RunningInstance<CM> {
fn dummy(cfg: &ArithConfig) -> Self {
Self {
cm_e: Default::default(),
u: Default::default(),
cm_w: Default::default(),
x: vec![Default::default(); cfg.n_public_inputs()],
x: vec![Default::default(); cfg.n_public_inputs],
}
}
}
Expand Down Expand Up @@ -85,11 +85,11 @@ impl<CM: CommitmentDef> FoldingInstance<CM> for IncomingInstance<CM> {
}
}

impl<CM: CommitmentDef, Cfg: ArithConfig> Dummy<&Cfg> for IncomingInstance<CM> {
fn dummy(cfg: &Cfg) -> Self {
impl<CM: CommitmentDef> Dummy<&ArithConfig> for IncomingInstance<CM> {
fn dummy(cfg: &ArithConfig) -> Self {
Self {
cm_w: Default::default(),
x: vec![Default::default(); cfg.n_public_inputs()],
x: vec![Default::default(); cfg.n_public_inputs],
}
}
}
Expand Down
7 changes: 3 additions & 4 deletions crates/fs/src/nova/keys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ pub struct NovaKey<A: Arith, CM: CommitmentDef> {
impl<A: Arith, CM: CommitmentDef> DeciderKey for NovaKey<A, CM> {
type ProverKey = Self;
type VerifierKey = ();
type ArithConfig = A::Config;

fn to_pk(&self) -> &Self::ProverKey {
self
Expand All @@ -39,7 +38,7 @@ impl<A: Arith, CM: CommitmentDef> DeciderKey for NovaKey<A, CM> {
&()
}

fn to_arith_config(&self) -> &Self::ArithConfig {
fn to_arith_config(&self) -> ArithConfig {
self.arith.config()
}
}
Expand Down Expand Up @@ -131,10 +130,10 @@ where
let cfg = self.arith.config();

let u = CM::Scalar::rand(&mut rng);
let x = (0..cfg.n_public_inputs())
let x = (0..cfg.n_public_inputs)
.map(|_| CM::Scalar::rand(&mut rng))
.collect::<Vec<_>>();
let w = (0..cfg.n_witnesses())
let w = (0..cfg.n_witnesses)
.map(|_| CM::Scalar::rand(&mut rng))
.collect::<Vec<_>>();
let e = self.arith.eval_relation(
Expand Down
Loading
Loading