1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use ark_ff::PrimeField;
use ark_relations::{
	lc,
	r1cs::{ConstraintSynthesizer, ConstraintSystemRef, SynthesisError},
};

#[derive(Copy)]
struct DummyCircuit<F: PrimeField> {
	pub a: Option<F>,
	pub b: Option<F>,
	pub num_variables: usize,
	pub num_constraints: usize,
}

impl<F: PrimeField> Clone for DummyCircuit<F> {
	fn clone(&self) -> Self {
		DummyCircuit {
			a: self.a,
			b: self.b,
			num_variables: self.num_variables,
			num_constraints: self.num_constraints,
		}
	}
}

impl<F: PrimeField> ConstraintSynthesizer<F> for DummyCircuit<F> {
	fn generate_constraints(self, cs: ConstraintSystemRef<F>) -> Result<(), SynthesisError> {
		let a = cs.new_witness_variable(|| self.a.ok_or(SynthesisError::AssignmentMissing))?;
		let b = cs.new_witness_variable(|| self.b.ok_or(SynthesisError::AssignmentMissing))?;
		let c = cs.new_input_variable(|| {
			let a = self.a.ok_or(SynthesisError::AssignmentMissing)?;
			let b = self.b.ok_or(SynthesisError::AssignmentMissing)?;

			Ok(a * b)
		})?;

		for _ in 0..self.num_constraints {
			cs.enforce_constraint(lc!() + a, lc!() + b, lc!() + c)?;
		}

		Ok(())
	}
}

#[cfg(test)]
mod test {
	use super::*;
	use ark_bls12_381::{Bls12_381, Fr as BlsFr};
	use ark_ed_on_bn254::{EdwardsAffine, Fr as BabyJubJub};
	use ark_groth16::Groth16;
	use ark_marlin::Marlin;
	use ark_poly::univariate::DensePolynomial;
	use ark_poly_commit::{ipa_pc::InnerProductArgPC, marlin_pc::MarlinKZG10};
	use ark_snark::SNARK;
	use ark_std::{ops::*, UniformRand};
	use blake2::Blake2s;

	#[test]
	fn should_verify_basic_circuit() {
		let rng = &mut ark_std::test_rng();

		let nc = 3;
		let nv = 3;
		let c = DummyCircuit::<BlsFr> {
			a: Some(BlsFr::rand(rng)),
			b: Some(BlsFr::rand(rng)),
			num_variables: nv,
			num_constraints: nc,
		};

		type KZG10 = MarlinKZG10<Bls12_381, DensePolynomial<BlsFr>>;
		type MarlinSetup = Marlin<BlsFr, KZG10, Blake2s>;

		let srs = MarlinSetup::universal_setup(nc, nv, nv, rng).unwrap();
		let (pk, vk) = MarlinSetup::index(&srs, c).unwrap();
		let proof = MarlinSetup::prove(&pk, c.clone(), rng).unwrap();

		let v = c.a.unwrap().mul(c.b.unwrap());

		let res = MarlinSetup::verify(&vk, &vec![v], &proof, rng).unwrap();
		assert!(res);
	}

	#[test]
	fn should_verify_basic_ipa_circuit() {
		let rng = &mut ark_std::test_rng();

		let nc = 3;
		let nv = 3;
		let c = DummyCircuit::<BabyJubJub> {
			a: Some(BabyJubJub::rand(rng)),
			b: Some(BabyJubJub::rand(rng)),
			num_variables: nv,
			num_constraints: nc,
		};

		type UniPoly = DensePolynomial<BabyJubJub>;
		type IPA = InnerProductArgPC<EdwardsAffine, Blake2s, UniPoly>;
		type MarlinSetup = Marlin<BabyJubJub, IPA, Blake2s>;

		let srs = MarlinSetup::universal_setup(nc, nc, nc, rng).unwrap();
		let (pk, vk) = MarlinSetup::index(&srs, c).unwrap();
		let proof = MarlinSetup::prove(&pk, c, rng).unwrap();

		let v = c.a.unwrap().mul(c.b.unwrap());

		let res = MarlinSetup::verify(&vk, &vec![v], &proof, rng).unwrap();
		assert!(res);
	}

	#[test]
	fn should_verify_basic_circuit_groth16() {
		let rng = &mut ark_std::test_rng();
		let c = DummyCircuit::<BlsFr> {
			a: Some(BlsFr::rand(rng)),
			b: Some(BlsFr::rand(rng)),
			num_variables: 0,
			num_constraints: 3,
		};

		let (pk, vk) = Groth16::<Bls12_381>::circuit_specific_setup(c, rng).unwrap();
		let proof = Groth16::<Bls12_381>::prove(&pk, c.clone(), rng).unwrap();

		let v = c.a.unwrap().mul(c.b.unwrap());

		let res = Groth16::<Bls12_381>::verify(&vk, &vec![v], &proof).unwrap();
		assert!(res);
	}
}