use group::{CurveAffine, EncodedPoint}; use pairing::{ Engine, PairingCurveAffine, }; use ::{ SynthesisError }; use multiexp::SourceBuilder; use std::io::{self, Read, Write}; use std::sync::Arc; use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt}; #[cfg(test)] mod tests; mod generator; mod prover; mod verifier; pub use self::generator::*; pub use self::prover::*; pub use self::verifier::*; #[derive(Clone)] pub struct Proof { pub a: E::G1Affine, pub b: E::G2Affine, pub c: E::G1Affine } impl PartialEq for Proof { fn eq(&self, other: &Self) -> bool { self.a == other.a && self.b == other.b && self.c == other.c } } impl Proof { pub fn write( &self, mut writer: W ) -> io::Result<()> { writer.write_all(self.a.into_compressed().as_ref())?; writer.write_all(self.b.into_compressed().as_ref())?; writer.write_all(self.c.into_compressed().as_ref())?; Ok(()) } pub fn read( mut reader: R ) -> io::Result { let mut g1_repr = ::Compressed::empty(); let mut g2_repr = ::Compressed::empty(); reader.read_exact(g1_repr.as_mut())?; let a = g1_repr .into_affine() .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) .and_then(|e| if e.is_zero() { Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity")) } else { Ok(e) })?; reader.read_exact(g2_repr.as_mut())?; let b = g2_repr .into_affine() .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) .and_then(|e| if e.is_zero() { Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity")) } else { Ok(e) })?; reader.read_exact(g1_repr.as_mut())?; let c = g1_repr .into_affine() .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) .and_then(|e| if e.is_zero() { Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity")) } else { Ok(e) })?; Ok(Proof { a: a, b: b, c: c }) } } #[derive(Clone)] pub struct VerifyingKey { // alpha in g1 for verifying and for creating A/C elements of // proof. Never the point at infinity. pub alpha_g1: E::G1Affine, // beta in g1 and g2 for verifying and for creating B/C elements // of proof. Never the point at infinity. pub beta_g1: E::G1Affine, pub beta_g2: E::G2Affine, // gamma in g2 for verifying. Never the point at infinity. pub gamma_g2: E::G2Affine, // delta in g1/g2 for verifying and proving, essentially the magic // trapdoor that forces the prover to evaluate the C element of the // proof with only components from the CRS. Never the point at // infinity. pub delta_g1: E::G1Affine, pub delta_g2: E::G2Affine, // Elements of the form (beta * u_i(tau) + alpha v_i(tau) + w_i(tau)) / gamma // for all public inputs. Because all public inputs have a dummy constraint, // this is the same size as the number of inputs, and never contains points // at infinity. pub ic: Vec } impl PartialEq for VerifyingKey { fn eq(&self, other: &Self) -> bool { self.alpha_g1 == other.alpha_g1 && self.beta_g1 == other.beta_g1 && self.beta_g2 == other.beta_g2 && self.gamma_g2 == other.gamma_g2 && self.delta_g1 == other.delta_g1 && self.delta_g2 == other.delta_g2 && self.ic == other.ic } } impl VerifyingKey { pub fn write( &self, mut writer: W ) -> io::Result<()> { writer.write_all(self.alpha_g1.into_uncompressed().as_ref())?; writer.write_all(self.beta_g1.into_uncompressed().as_ref())?; writer.write_all(self.beta_g2.into_uncompressed().as_ref())?; writer.write_all(self.gamma_g2.into_uncompressed().as_ref())?; writer.write_all(self.delta_g1.into_uncompressed().as_ref())?; writer.write_all(self.delta_g2.into_uncompressed().as_ref())?; writer.write_u32::(self.ic.len() as u32)?; for ic in &self.ic { writer.write_all(ic.into_uncompressed().as_ref())?; } Ok(()) } pub fn read( mut reader: R ) -> io::Result { let mut g1_repr = ::Uncompressed::empty(); let mut g2_repr = ::Uncompressed::empty(); reader.read_exact(g1_repr.as_mut())?; let alpha_g1 = g1_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; reader.read_exact(g1_repr.as_mut())?; let beta_g1 = g1_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; reader.read_exact(g2_repr.as_mut())?; let beta_g2 = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; reader.read_exact(g2_repr.as_mut())?; let gamma_g2 = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; reader.read_exact(g1_repr.as_mut())?; let delta_g1 = g1_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; reader.read_exact(g2_repr.as_mut())?; let delta_g2 = g2_repr.into_affine().map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?; let ic_len = reader.read_u32::()? as usize; let mut ic = vec![]; for _ in 0..ic_len { reader.read_exact(g1_repr.as_mut())?; let g1 = g1_repr .into_affine() .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) .and_then(|e| if e.is_zero() { Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity")) } else { Ok(e) })?; ic.push(g1); } Ok(VerifyingKey { alpha_g1: alpha_g1, beta_g1: beta_g1, beta_g2: beta_g2, gamma_g2: gamma_g2, delta_g1: delta_g1, delta_g2: delta_g2, ic: ic }) } } #[derive(Clone)] pub struct Parameters { pub vk: VerifyingKey, // Elements of the form ((tau^i * t(tau)) / delta) for i between 0 and // m-2 inclusive. Never contains points at infinity. pub h: Arc>, // Elements of the form (beta * u_i(tau) + alpha v_i(tau) + w_i(tau)) / delta // for all auxiliary inputs. Variables can never be unconstrained, so this // never contains points at infinity. pub l: Arc>, // QAP "A" polynomials evaluated at tau in the Lagrange basis. Never contains // points at infinity: polynomials that evaluate to zero are omitted from // the CRS and the prover can deterministically skip their evaluation. pub a: Arc>, // QAP "B" polynomials evaluated at tau in the Lagrange basis. Needed in // G1 and G2 for C/B queries, respectively. Never contains points at // infinity for the same reason as the "A" polynomials. pub b_g1: Arc>, pub b_g2: Arc> } impl PartialEq for Parameters { fn eq(&self, other: &Self) -> bool { self.vk == other.vk && self.h == other.h && self.l == other.l && self.a == other.a && self.b_g1 == other.b_g1 && self.b_g2 == other.b_g2 } } impl Parameters { pub fn write( &self, mut writer: W ) -> io::Result<()> { self.vk.write(&mut writer)?; writer.write_u32::(self.h.len() as u32)?; for g in &self.h[..] { writer.write_all(g.into_uncompressed().as_ref())?; } writer.write_u32::(self.l.len() as u32)?; for g in &self.l[..] { writer.write_all(g.into_uncompressed().as_ref())?; } writer.write_u32::(self.a.len() as u32)?; for g in &self.a[..] { writer.write_all(g.into_uncompressed().as_ref())?; } writer.write_u32::(self.b_g1.len() as u32)?; for g in &self.b_g1[..] { writer.write_all(g.into_uncompressed().as_ref())?; } writer.write_u32::(self.b_g2.len() as u32)?; for g in &self.b_g2[..] { writer.write_all(g.into_uncompressed().as_ref())?; } Ok(()) } pub fn read( mut reader: R, checked: bool ) -> io::Result { let read_g1 = |reader: &mut R| -> io::Result { let mut repr = ::Uncompressed::empty(); reader.read_exact(repr.as_mut())?; if checked { repr .into_affine() } else { repr .into_affine_unchecked() } .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) .and_then(|e| if e.is_zero() { Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity")) } else { Ok(e) }) }; let read_g2 = |reader: &mut R| -> io::Result { let mut repr = ::Uncompressed::empty(); reader.read_exact(repr.as_mut())?; if checked { repr .into_affine() } else { repr .into_affine_unchecked() } .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e)) .and_then(|e| if e.is_zero() { Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity")) } else { Ok(e) }) }; let vk = VerifyingKey::::read(&mut reader)?; let mut h = vec![]; let mut l = vec![]; let mut a = vec![]; let mut b_g1 = vec![]; let mut b_g2 = vec![]; { let len = reader.read_u32::()? as usize; for _ in 0..len { h.push(read_g1(&mut reader)?); } } { let len = reader.read_u32::()? as usize; for _ in 0..len { l.push(read_g1(&mut reader)?); } } { let len = reader.read_u32::()? as usize; for _ in 0..len { a.push(read_g1(&mut reader)?); } } { let len = reader.read_u32::()? as usize; for _ in 0..len { b_g1.push(read_g1(&mut reader)?); } } { let len = reader.read_u32::()? as usize; for _ in 0..len { b_g2.push(read_g2(&mut reader)?); } } Ok(Parameters { vk: vk, h: Arc::new(h), l: Arc::new(l), a: Arc::new(a), b_g1: Arc::new(b_g1), b_g2: Arc::new(b_g2) }) } } pub struct PreparedVerifyingKey { /// Pairing result of alpha*beta alpha_g1_beta_g2: E::Fqk, /// -gamma in G2 neg_gamma_g2: ::Prepared, /// -delta in G2 neg_delta_g2: ::Prepared, /// Copy of IC from `VerifiyingKey`. ic: Vec } pub trait ParameterSource { type G1Builder: SourceBuilder; type G2Builder: SourceBuilder; fn get_vk( &mut self, num_ic: usize ) -> Result, SynthesisError>; fn get_h( &mut self, num_h: usize ) -> Result; fn get_l( &mut self, num_l: usize ) -> Result; fn get_a( &mut self, num_inputs: usize, num_aux: usize ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError>; fn get_b_g1( &mut self, num_inputs: usize, num_aux: usize ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError>; fn get_b_g2( &mut self, num_inputs: usize, num_aux: usize ) -> Result<(Self::G2Builder, Self::G2Builder), SynthesisError>; } impl<'a, E: Engine> ParameterSource for &'a Parameters { type G1Builder = (Arc>, usize); type G2Builder = (Arc>, usize); fn get_vk( &mut self, _: usize ) -> Result, SynthesisError> { Ok(self.vk.clone()) } fn get_h( &mut self, _: usize ) -> Result { Ok((self.h.clone(), 0)) } fn get_l( &mut self, _: usize ) -> Result { Ok((self.l.clone(), 0)) } fn get_a( &mut self, num_inputs: usize, _: usize ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError> { Ok(((self.a.clone(), 0), (self.a.clone(), num_inputs))) } fn get_b_g1( &mut self, num_inputs: usize, _: usize ) -> Result<(Self::G1Builder, Self::G1Builder), SynthesisError> { Ok(((self.b_g1.clone(), 0), (self.b_g1.clone(), num_inputs))) } fn get_b_g2( &mut self, num_inputs: usize, _: usize ) -> Result<(Self::G2Builder, Self::G2Builder), SynthesisError> { Ok(((self.b_g2.clone(), 0), (self.b_g2.clone(), num_inputs))) } } #[cfg(test)] mod test_with_bls12_381 { use super::*; use {Circuit, SynthesisError, ConstraintSystem}; use ff::Field; use rand::{Rand, thread_rng}; use pairing::bls12_381::{Bls12, Fr}; #[test] fn serialization() { struct MySillyCircuit { a: Option, b: Option } impl Circuit for MySillyCircuit { fn synthesize>( self, cs: &mut CS ) -> Result<(), SynthesisError> { let a = cs.alloc(|| "a", || self.a.ok_or(SynthesisError::AssignmentMissing))?; let b = cs.alloc(|| "b", || self.b.ok_or(SynthesisError::AssignmentMissing))?; let c = cs.alloc_input(|| "c", || { let mut a = self.a.ok_or(SynthesisError::AssignmentMissing)?; let b = self.b.ok_or(SynthesisError::AssignmentMissing)?; a.mul_assign(&b); Ok(a) })?; cs.enforce( || "a*b=c", |lc| lc + a, |lc| lc + b, |lc| lc + c ); Ok(()) } } let rng = &mut thread_rng(); let params = generate_random_parameters::( MySillyCircuit { a: None, b: None }, rng ).unwrap(); { let mut v = vec![]; params.write(&mut v).unwrap(); assert_eq!(v.len(), 2136); let de_params = Parameters::read(&v[..], true).unwrap(); assert!(params == de_params); let de_params = Parameters::read(&v[..], false).unwrap(); assert!(params == de_params); } let pvk = prepare_verifying_key::(¶ms.vk); for _ in 0..100 { let a = Fr::rand(rng); let b = Fr::rand(rng); let mut c = a; c.mul_assign(&b); let proof = create_random_proof( MySillyCircuit { a: Some(a), b: Some(b) }, ¶ms, rng ).unwrap(); let mut v = vec![]; proof.write(&mut v).unwrap(); assert_eq!(v.len(), 192); let de_proof = Proof::read(&v[..]).unwrap(); assert!(proof == de_proof); assert!(verify_proof(&pvk, &proof, &[c]).unwrap()); assert!(!verify_proof(&pvk, &proof, &[a]).unwrap()); } } }