#![allow(unused_imports)] extern crate pairing; extern crate rand; extern crate num_cpus; extern crate futures; extern crate futures_cpupool; extern crate bit_vec; extern crate crossbeam; extern crate byteorder; extern crate ff; pub mod domain; pub mod groth16; pub mod gm17; pub mod sonic; mod group; mod source; #[cfg(not(feature = "singlecore"))] mod parallel_fft; mod multicore; mod parallel_multiexp; #[cfg(feature = "singlecore")] mod serial_fft; mod serial_multiexp; #[cfg(test)] mod tests; use pairing::{Engine}; use ff::Field; use std::ops::{Add, Sub}; use std::fmt; use std::error::Error; use std::io; use std::marker::PhantomData; pub mod multiexp { pub use source::*; #[cfg(not(feature = "singlecore"))] pub use parallel_multiexp::*; #[cfg(feature = "singlecore")] pub use serial_multiexp::*; } /// Computations are expressed in terms of arithmetic circuits, in particular /// rank-1 quadratic constraint systems. The `Circuit` trait represents a /// circuit that can be synthesized. The `synthesize` method is called during /// CRS generation and during proving. pub trait Circuit { /// Synthesize the circuit into a rank-1 quadratic constraint system fn synthesize>( self, cs: &mut CS ) -> Result<(), SynthesisError>; } /// Represents a variable in our constraint system. #[derive(Copy, Clone, Debug)] pub struct Variable(Index); impl Variable { /// This constructs a variable with an arbitrary index. /// Circuit implementations are not recommended to use this. pub fn new_unchecked(idx: Index) -> Variable { Variable(idx) } /// This returns the index underlying the variable. /// Circuit implementations are not recommended to use this. pub fn get_unchecked(&self) -> Index { self.0 } } /// Represents the index of either an input variable or /// auxillary variable. #[derive(Copy, Clone, PartialEq, Debug)] pub enum Index { Input(usize), Aux(usize) } /// This represents a linear combination of some variables, with coefficients /// in the scalar field of a pairing-friendly elliptic curve group. #[derive(Clone)] pub struct LinearCombination(Vec<(Variable, E::Fr)>); impl AsRef<[(Variable, E::Fr)]> for LinearCombination { fn as_ref(&self) -> &[(Variable, E::Fr)] { &self.0 } } impl LinearCombination { pub fn zero() -> LinearCombination { LinearCombination(vec![]) } } impl Add<(E::Fr, Variable)> for LinearCombination { type Output = LinearCombination; fn add(mut self, (coeff, var): (E::Fr, Variable)) -> LinearCombination { self.0.push((var, coeff)); self } } impl Sub<(E::Fr, Variable)> for LinearCombination { type Output = LinearCombination; fn sub(self, (mut coeff, var): (E::Fr, Variable)) -> LinearCombination { coeff.negate(); self + (coeff, var) } } impl Add for LinearCombination { type Output = LinearCombination; fn add(self, other: Variable) -> LinearCombination { self + (E::Fr::one(), other) } } impl Sub for LinearCombination { type Output = LinearCombination; fn sub(self, other: Variable) -> LinearCombination { self - (E::Fr::one(), other) } } impl<'a, E: Engine> Add<&'a LinearCombination> for LinearCombination { type Output = LinearCombination; fn add(mut self, other: &'a LinearCombination) -> LinearCombination { for s in &other.0 { self = self + (s.1, s.0); } self } } impl<'a, E: Engine> Sub<&'a LinearCombination> for LinearCombination { type Output = LinearCombination; fn sub(mut self, other: &'a LinearCombination) -> LinearCombination { for s in &other.0 { self = self - (s.1, s.0); } self } } impl<'a, E: Engine> Add<(E::Fr, &'a LinearCombination)> for LinearCombination { type Output = LinearCombination; fn add(mut self, (coeff, other): (E::Fr, &'a LinearCombination)) -> LinearCombination { for s in &other.0 { let mut tmp = s.1; tmp.mul_assign(&coeff); self = self + (tmp, s.0); } self } } impl<'a, E: Engine> Sub<(E::Fr, &'a LinearCombination)> for LinearCombination { type Output = LinearCombination; fn sub(mut self, (coeff, other): (E::Fr, &'a LinearCombination)) -> LinearCombination { for s in &other.0 { let mut tmp = s.1; tmp.mul_assign(&coeff); self = self - (tmp, s.0); } self } } /// This is an error that could occur during circuit synthesis contexts, /// such as CRS generation, proving or verification. #[derive(Debug)] pub enum SynthesisError { /// During synthesis, we lacked knowledge of a variable assignment. AssignmentMissing, /// During synthesis, we divided by zero. DivisionByZero, /// During synthesis, we constructed an unsatisfiable constraint system. Unsatisfiable, /// During synthesis, our polynomials ended up being too high of degree PolynomialDegreeTooLarge, /// During proof generation, we encountered an identity in the CRS UnexpectedIdentity, /// During proof generation, we encountered an I/O error with the CRS IoError(io::Error), /// During verification, our verifying key was malformed. MalformedVerifyingKey, /// During CRS generation, we observed an unconstrained auxillary variable UnconstrainedVariable } impl From for SynthesisError { fn from(e: io::Error) -> SynthesisError { SynthesisError::IoError(e) } } impl Error for SynthesisError { fn description(&self) -> &str { match *self { SynthesisError::AssignmentMissing => "an assignment for a variable could not be computed", SynthesisError::DivisionByZero => "division by zero", SynthesisError::Unsatisfiable => "unsatisfiable constraint system", SynthesisError::PolynomialDegreeTooLarge => "polynomial degree is too large", SynthesisError::UnexpectedIdentity => "encountered an identity element in the CRS", SynthesisError::IoError(_) => "encountered an I/O error", SynthesisError::MalformedVerifyingKey => "malformed verifying key", SynthesisError::UnconstrainedVariable => "auxillary variable was unconstrained" } } } impl fmt::Display for SynthesisError { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { if let &SynthesisError::IoError(ref e) = self { write!(f, "I/O error: ")?; e.fmt(f) } else { write!(f, "{}", self.description()) } } } /// Represents a constraint system which can have new variables /// allocated and constrains between them formed. pub trait ConstraintSystem: Sized { /// Represents the type of the "root" of this constraint system /// so that nested namespaces can minimize indirection. type Root: ConstraintSystem; /// Return the "one" input variable fn one() -> Variable { Variable::new_unchecked(Index::Input(0)) } /// Allocate a private variable in the constraint system. The provided function is used to /// determine the assignment of the variable. The given `annotation` function is invoked /// in testing contexts in order to derive a unique name for this variable in the current /// namespace. fn alloc( &mut self, annotation: A, f: F ) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into; /// Allocate a public variable in the constraint system. The provided function is used to /// determine the assignment of the variable. fn alloc_input( &mut self, annotation: A, f: F ) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into; /// Enforce that `A` * `B` = `C`. The `annotation` function is invoked in testing contexts /// in order to derive a unique name for the constraint in the current namespace. fn enforce( &mut self, annotation: A, a: LA, b: LB, c: LC ) where A: FnOnce() -> AR, AR: Into, LA: FnOnce(LinearCombination) -> LinearCombination, LB: FnOnce(LinearCombination) -> LinearCombination, LC: FnOnce(LinearCombination) -> LinearCombination; /// Create a new (sub)namespace and enter into it. Not intended /// for downstream use; use `namespace` instead. fn push_namespace(&mut self, name_fn: N) where NR: Into, N: FnOnce() -> NR; /// Exit out of the existing namespace. Not intended for /// downstream use; use `namespace` instead. fn pop_namespace(&mut self); /// Gets the "root" constraint system, bypassing the namespacing. /// Not intended for downstream use; use `namespace` instead. fn get_root(&mut self) -> &mut Self::Root; /// Begin a namespace for this constraint system. fn namespace<'a, NR, N>( &'a mut self, name_fn: N ) -> Namespace<'a, E, Self::Root> where NR: Into, N: FnOnce() -> NR { self.get_root().push_namespace(name_fn); Namespace(self.get_root(), PhantomData) } } /// This is a "namespaced" constraint system which borrows a constraint system (pushing /// a namespace context) and, when dropped, pops out of the namespace context. pub struct Namespace<'a, E: Engine, CS: ConstraintSystem + 'a>(&'a mut CS, PhantomData); impl<'cs, E: Engine, CS: ConstraintSystem> ConstraintSystem for Namespace<'cs, E, CS> { type Root = CS::Root; fn one() -> Variable { CS::one() } fn alloc( &mut self, annotation: A, f: F ) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into { self.0.alloc(annotation, f) } fn alloc_input( &mut self, annotation: A, f: F ) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into { self.0.alloc_input(annotation, f) } fn enforce( &mut self, annotation: A, a: LA, b: LB, c: LC ) where A: FnOnce() -> AR, AR: Into, LA: FnOnce(LinearCombination) -> LinearCombination, LB: FnOnce(LinearCombination) -> LinearCombination, LC: FnOnce(LinearCombination) -> LinearCombination { self.0.enforce(annotation, a, b, c) } // Downstream users who use `namespace` will never interact with these // functions and they will never be invoked because the namespace is // never a root constraint system. fn push_namespace(&mut self, _: N) where NR: Into, N: FnOnce() -> NR { panic!("only the root's push_namespace should be called"); } fn pop_namespace(&mut self) { panic!("only the root's pop_namespace should be called"); } fn get_root(&mut self) -> &mut Self::Root { self.0.get_root() } } impl<'a, E: Engine, CS: ConstraintSystem> Drop for Namespace<'a, E, CS> { fn drop(&mut self) { self.get_root().pop_namespace() } } /// Convenience implementation of ConstraintSystem for mutable references to /// constraint systems. impl<'cs, E: Engine, CS: ConstraintSystem> ConstraintSystem for &'cs mut CS { type Root = CS::Root; fn one() -> Variable { CS::one() } fn alloc( &mut self, annotation: A, f: F ) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into { (**self).alloc(annotation, f) } fn alloc_input( &mut self, annotation: A, f: F ) -> Result where F: FnOnce() -> Result, A: FnOnce() -> AR, AR: Into { (**self).alloc_input(annotation, f) } fn enforce( &mut self, annotation: A, a: LA, b: LB, c: LC ) where A: FnOnce() -> AR, AR: Into, LA: FnOnce(LinearCombination) -> LinearCombination, LB: FnOnce(LinearCombination) -> LinearCombination, LC: FnOnce(LinearCombination) -> LinearCombination { (**self).enforce(annotation, a, b, c) } fn push_namespace(&mut self, name_fn: N) where NR: Into, N: FnOnce() -> NR { (**self).push_namespace(name_fn) } fn pop_namespace(&mut self) { (**self).pop_namespace() } fn get_root(&mut self) -> &mut Self::Root { (**self).get_root() } } static mut VERBOSE_SWITCH: i8 = -1; use std::str::FromStr; use std::env; fn verbose_flag() -> bool { unsafe { if VERBOSE_SWITCH < 0 { VERBOSE_SWITCH = FromStr::from_str(&env::var("BELLMAN_VERBOSE").unwrap_or(String::new())).unwrap_or(1); } match VERBOSE_SWITCH { 1 => true, _ => false, } } }