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

R1cs nark pcd #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 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
33 changes: 18 additions & 15 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,34 @@ edition = "2018"
################################# Dependencies ################################

[dependencies]
ark-serialize = { git = "https://github.com/arkworks-rs/algebra", default-features = false, features = [ "derive" ] }
ark-ff = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-ec = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-poly = { git = "https://github.com/arkworks-rs/algebra", default-features = false }
ark-serialize = { version = "^0.2.0", default-features = false, features = [ "derive" ] }
ark-ff = { version = "^0.2.0", default-features = false }
ark-ec = { version = "^0.2.0", default-features = false }
ark-poly = { version = "^0.2.0", default-features = false }

ark-std = { git = "https://github.com/arkworks-rs/utils", default-features = false }
ark-std = { version = "^0.2.0", default-features = false }

ark-relations = { git = "https://github.com/arkworks-rs/snark", default-features = false }
ark-crypto-primitives = { git = "https://github.com/arkworks-rs/crypto-primitives", default-features = false, branch = "main", features = [ "r1cs" ] }
ark-relations = { version = "^0.2.0", default-features = false }
ark-crypto-primitives = { version = "^0.2.0", default-features = false, features = [ "r1cs" ] }

ark-r1cs-std = { git = "https://github.com/arkworks-rs/r1cs-std", default-features = false }
ark-r1cs-std = { version = "^0.2.0", default-features = false }

ark-nonnative-field = { git = "https://github.com/arkworks-rs/nonnative", default-features = false }
ark-snark = { git = "https://github.com/arkworks-rs/snark", default-features = false }
ark-snark = { version = "^0.2.0", default-features = false }

ark-ed-on-mnt4-298 = { git = "https://github.com/arkworks-rs/curves", default-features = false }
ark-ed-on-bls12-381 = { git = "https://github.com/arkworks-rs/curves", default-features = false }
ark-mnt4-298 = { git = "https://github.com/arkworks-rs/curves", default-features = false, features = [ "curve", "r1cs" ] }
ark-mnt6-298 = { git = "https://github.com/arkworks-rs/curves", default-features = false, features = [ "r1cs" ] }
ark-accumulation = { git = "https://github.com/arkworks-rs/accumulation/", branch = "main", default-features = false, features = [ "r1cs-nark-as", "r1cs" ] }
ark-sponge = { git = "https://github.com/arkworks-rs/sponge/", branch = "accumulation-experimental", default-features = false, features = [ "r1cs" ] }

ark-ed-on-mnt4-298 = { version = "^0.2.0", default-features = false }
ark-ed-on-bls12-381 = { version = "^0.2.0", default-features = false }
ark-mnt4-298 = { version = "^0.2.0", default-features = false, features = [ "curve", "r1cs" ] }
ark-mnt6-298 = { version = "^0.2.0", default-features = false, features = [ "r1cs" ] }

rand_chacha = { version = "0.2.1", default-features = false }
derivative = { version = "2.0", features = ["use_core"] }

ark-groth16 = { git = "https://github.com/arkworks-rs/groth16", features = [ "r1cs" ], default-features = false }
ark-gm17 = { git = "https://github.com/arkworks-rs/gm17", features = [ "r1cs" ], default-features = false }
ark-groth16 = { version = "^0.2.0", features = [ "r1cs" ], default-features = false }
ark-gm17 = { version = "^0.2.0", features = [ "r1cs" ], default-features = false }
ark-marlin = { git = "https://github.com/arkworks-rs/marlin", branch = "constraints", default-features = false }
ark-poly-commit = { git = "https://github.com/arkworks-rs/poly-commit", branch = "constraints", default-features = false, features = [ "r1cs" ] }

Expand Down
16 changes: 11 additions & 5 deletions src/ec_cycle_pcd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use ark_r1cs_std::{
use ark_relations::r1cs::{
ConstraintSynthesizer, ConstraintSystem, ConstraintSystemRef, OptimizationGoal, SynthesisError,
};
use ark_sponge::Absorbable;
use ark_std::rand::{CryptoRng, Rng, RngCore};
use ark_std::{boxed::Box, marker::PhantomData, vec::Vec};

Expand Down Expand Up @@ -253,12 +254,15 @@ where
{
}

pub struct BoundTestingPredicate<F: PrimeField, BoundCircuit: ConstraintSynthesizer<F> + Clone> {
pub struct BoundTestingPredicate<
F: PrimeField + Absorbable<F>,
BoundCircuit: ConstraintSynthesizer<F> + Clone,
> {
pub bound_circuit: BoundCircuit,
pub field_phantom: PhantomData<F>,
}

impl<F: PrimeField, BoundCircuit: ConstraintSynthesizer<F> + Clone> Clone
impl<F: PrimeField + Absorbable<F>, BoundCircuit: ConstraintSynthesizer<F> + Clone> Clone
for BoundTestingPredicate<F, BoundCircuit>
{
fn clone(&self) -> Self {
Expand All @@ -269,7 +273,7 @@ impl<F: PrimeField, BoundCircuit: ConstraintSynthesizer<F> + Clone> Clone
}
}

impl<F: PrimeField, BoundCircuit: ConstraintSynthesizer<F> + Clone> PCDPredicate<F>
impl<F: PrimeField + Absorbable<F>, BoundCircuit: ConstraintSynthesizer<F> + Clone> PCDPredicate<F>
for BoundTestingPredicate<F, BoundCircuit>
{
type Message = F;
Expand Down Expand Up @@ -301,9 +305,11 @@ impl<F: PrimeField, BoundCircuit: ConstraintSynthesizer<F> + Clone> PCDPredicate
}
}

impl<MainField: PrimeField, HelpField: PrimeField, IC: ECCyclePCDConfig<MainField, HelpField>>
UniversalSetupPCD<MainField> for ECCyclePCD<MainField, HelpField, IC>
impl<MainField, HelpField, IC> UniversalSetupPCD<MainField> for ECCyclePCD<MainField, HelpField, IC>
where
MainField: PrimeField + Absorbable<MainField>,
HelpField: PrimeField + Absorbable<HelpField>,
IC: ECCyclePCDConfig<MainField, HelpField>,
IC::MainSNARK: UniversalSetupSNARK<MainField>,
IC::HelpSNARK: UniversalSetupSNARK<HelpField>,
IC::MainSNARKGadget: UniversalSetupSNARKGadget<MainField, HelpField, IC::MainSNARK>,
Expand Down
31 changes: 31 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
use ark_std::error::Error;

/// Common errors that PCD schemes may throw.
#[derive(Debug)]
pub enum PCDError {
/// The number of prior messages does not match the predicate.
InvalidPriorMessagesLength(usize, usize),

/// The number of prior proofs does not match the predicate.
InvalidPriorProofsLength(usize, usize),
}

impl core::fmt::Display for PCDError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let error_text = match self {
PCDError::InvalidPriorMessagesLength(expected, actual) => format!(
"Expected the number of prior messages to be `{}` but got `{}` instead",
expected, actual
),

PCDError::InvalidPriorProofsLength(expected, actual) => format!(
"Expected the number of prior proofs to be `{}` but got `{}` instead",
expected, actual
),
};

write!(f, "{}", error_text)
}
}

impl Error for PCDError {}
194 changes: 192 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ use ark_r1cs_std::alloc::AllocVar;
use ark_r1cs_std::bits::boolean::Boolean;
use ark_r1cs_std::ToBytesGadget;
use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
use ark_sponge::constraints::AbsorbableGadget;
use ark_sponge::Absorbable;
use ark_std::rand::{CryptoRng, RngCore};
use ark_std::{boxed::Box, fmt::Debug};

#[macro_use]
extern crate derivative;

pub type Error = Box<dyn ark_std::error::Error + 'static>;

pub trait PCDPredicate<F: PrimeField>: Clone {
type Message: ToBytes + Sized + Clone + Default;
type MessageVar: ToBytesGadget<F> + AllocVar<Self::Message, F>;
type Message: Absorbable<F> + ToBytes + Sized + Clone + Default;
type MessageVar: AbsorbableGadget<F> + ToBytesGadget<F> + AllocVar<Self::Message, F>;

type LocalWitness: Sized + Clone + Default;
type LocalWitnessVar: AllocVar<Self::LocalWitness, F>;
Expand Down Expand Up @@ -76,5 +81,190 @@ pub trait UniversalSetupPCD<F: PrimeField>: PCD<F> {
) -> Result<(<Self as PCD<F>>::ProvingKey, <Self as PCD<F>>::VerifyingKey), Error>;
}

/// Common errors that PCD schemes may throw.
pub mod error;

pub mod ec_cycle_pcd;
pub mod variable_length_crh;

/// A PCD that does not rely on SNARKs but instead builds on an R1CS NARK construction and its
/// accumulation scheme.
/// The implementation is based on the construction detailed in Section 5 of [\[BCLMS20\]][bclms20].
///
/// [bclms20]: https://eprint.iacr.org/2020/1618
pub mod r1cs_nark_pcd;

#[cfg(test)]
pub mod tests {
use crate::{PCDPredicate, PCD};
use ark_ff::PrimeField;
use ark_r1cs_std::bits::boolean::Boolean;
use ark_r1cs_std::eq::EqGadget;
use ark_r1cs_std::fields::fp::FpVar;
use ark_relations::r1cs::{ConstraintSystemRef, SynthesisError};
use ark_sponge::Absorbable;
use ark_std::marker::PhantomData;

#[derive(Clone)]
pub struct TestIVCPredicate<F: PrimeField + Absorbable<F>> {
pub field_phantom: PhantomData<F>,
}

impl<F: PrimeField + Absorbable<F>> TestIVCPredicate<F> {
fn new() -> Self {
Self {
field_phantom: PhantomData,
}
}
}

impl<F: PrimeField + Absorbable<F>> PCDPredicate<F> for TestIVCPredicate<F> {
type Message = F;
type MessageVar = FpVar<F>;
type LocalWitness = F;
type LocalWitnessVar = FpVar<F>;

const PRIOR_MSG_LEN: usize = 1;

fn generate_constraints(
&self,
_cs: ConstraintSystemRef<F>,
msg: &Self::MessageVar,
witness: &Self::LocalWitnessVar,
prior_msgs: &[Self::MessageVar],
_base_case: &Boolean<F>,
) -> Result<(), SynthesisError> {
let msg_supposed = &prior_msgs[0] + witness;
msg_supposed.enforce_equal(&msg)?;

Ok(())
}
}

#[derive(Clone)]
pub struct TestPCDPredicate<F: PrimeField + Absorbable<F>> {
pub field_phantom: PhantomData<F>,
}

impl<F: PrimeField + Absorbable<F>> TestPCDPredicate<F> {
fn new() -> Self {
Self {
field_phantom: PhantomData,
}
}
}

impl<F: PrimeField + Absorbable<F>> PCDPredicate<F> for TestPCDPredicate<F> {
type Message = F;
type MessageVar = FpVar<F>;
type LocalWitness = F;
type LocalWitnessVar = FpVar<F>;

const PRIOR_MSG_LEN: usize = 2;

fn generate_constraints(
&self,
_cs: ConstraintSystemRef<F>,
msg: &Self::MessageVar,
witness: &Self::LocalWitnessVar,
prior_msgs: &[Self::MessageVar],
_base_case: &Boolean<F>,
) -> Result<(), SynthesisError> {
let msg_supposed = &prior_msgs[0] + &prior_msgs[1] + witness;
msg_supposed.enforce_equal(&msg)?;

Ok(())
}
}

pub fn test_ivc_base_case<F: PrimeField + Absorbable<F>, TestPCD: PCD<F>>() {
let mut rng = ark_std::test_rng();

let witness = F::one();
let msg_0 = F::one();

let circ = TestIVCPredicate::<F>::new();
let (pk, vk) = TestPCD::circuit_specific_setup(&circ, &mut rng).unwrap();

let proof_0 = TestPCD::prove(&pk, &circ, &msg_0, &witness, &[], &[], &mut rng).unwrap();
assert!(TestPCD::verify::<TestIVCPredicate<F>>(&vk, &msg_0, &proof_0).unwrap());
}

pub fn test_ivc<F: PrimeField + Absorbable<F>, TestPCD: PCD<F>>() {
let mut rng = ark_std::test_rng();

let witness = F::one();
let msg_0 = F::one();
let msg_1 = msg_0 + &witness;
let msg_2 = msg_1 + &witness;

let circ = TestIVCPredicate::<F>::new();
let (pk, vk) = TestPCD::circuit_specific_setup(&circ, &mut rng).unwrap();

let proof_0 = TestPCD::prove(&pk, &circ, &msg_0, &witness, &[], &[], &mut rng).unwrap();
assert!(TestPCD::verify::<TestIVCPredicate<F>>(&vk, &msg_0, &proof_0).unwrap());

let proof_1 = TestPCD::prove(
&pk,
&circ,
&msg_1,
&witness,
&[msg_0],
&vec![proof_0],
&mut rng,
)
.unwrap();
assert!(TestPCD::verify::<TestIVCPredicate<F>>(&vk, &msg_1, &proof_1).unwrap());

let proof_2 = TestPCD::prove(
&pk,
&circ,
&msg_2,
&witness,
&[msg_1],
&vec![proof_1],
&mut rng,
)
.unwrap();
assert!(TestPCD::verify::<TestIVCPredicate<F>>(&vk, &msg_2, &proof_2).unwrap());
}

pub fn test_pcd<F: PrimeField + Absorbable<F>, TestPCD: PCD<F>>() {
let mut rng = ark_std::test_rng();

let witness = F::one();
let msg_0 = F::one();
let msg_1 = msg_0 + &msg_0 + &witness;
let msg_2 = msg_1 + &msg_1 + &witness;

let circ = TestPCDPredicate::<F>::new();
let (pk, vk) = TestPCD::circuit_specific_setup(&circ, &mut rng).unwrap();

let proof_0 = TestPCD::prove(&pk, &circ, &msg_0, &witness, &[], &[], &mut rng).unwrap();
assert!(TestPCD::verify::<TestPCDPredicate<F>>(&vk, &msg_0, &proof_0).unwrap());

let proof_1 = TestPCD::prove(
&pk,
&circ,
&msg_1,
&witness,
&[msg_0, msg_0],
&vec![proof_0.clone(), proof_0],
&mut rng,
)
.unwrap();
assert!(TestPCD::verify::<TestPCDPredicate<F>>(&vk, &msg_1, &proof_1).unwrap());

let proof_2 = TestPCD::prove(
&pk,
&circ,
&msg_2,
&witness,
&[msg_1, msg_1],
&vec![proof_1.clone(), proof_1],
&mut rng,
)
.unwrap();
assert!(TestPCD::verify::<TestPCDPredicate<F>>(&vk, &msg_2, &proof_2).unwrap());
}
}
Loading