start transitioning to versioning + more elegant re-exports
This commit is contained in:
parent
04454890b9
commit
810bb92cee
28
Cargo.toml
28
Cargo.toml
@ -6,7 +6,8 @@ homepage = "https://github.com/matterinc/bellman"
|
||||
license = "MIT/Apache-2.0"
|
||||
name = "bellman"
|
||||
repository = "https://github.com/matterinc/bellman"
|
||||
version = "0.1.3"
|
||||
version = "0.2.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib", "lib", "staticlib"]
|
||||
@ -15,20 +16,25 @@ crate-type = ["cdylib", "lib", "staticlib"]
|
||||
rand = "0.4"
|
||||
bit-vec = "0.4.4"
|
||||
futures = "0.1"
|
||||
futures-cpupool = "0.1"
|
||||
num_cpus = "1"
|
||||
crossbeam = "0.7.1"
|
||||
pairing = { git = 'https://github.com/matterinc/pairing' }
|
||||
byteorder = "1"
|
||||
ff = { git = 'https://github.com/matterinc/ff', features = ["derive"] }
|
||||
|
||||
tiny-keccak = "1.4.2"
|
||||
#pairing = { git = 'https://github.com/matterinc/pairing', tag = "0.16.2" }
|
||||
pairing = { path = "../pairing" }
|
||||
byteorder = "1"
|
||||
|
||||
futures-cpupool = {version = "0.1", optional = true}
|
||||
num_cpus = {version = "1", optional = true}
|
||||
crossbeam = {version = "0.7.1", optional = true}
|
||||
|
||||
tiny-keccak = {version = "1.4.2", optional = true}
|
||||
|
||||
[dependencies.blake2-rfc]
|
||||
git = "https://github.com/gtank/blake2-rfc"
|
||||
rev = "7a5b5fc99ae483a0043db7547fb79a6fa44b88a9"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
singlecore = []
|
||||
default = ["multicore", "gm17", "sonic"]
|
||||
#default = ["singlecore"]
|
||||
multicore = ["futures-cpupool", "num_cpus", "crossbeam"]
|
||||
sonic = ["tiny-keccak"]
|
||||
gm17 = []
|
||||
singlecore = ["futures-cpupool"]
|
||||
|
411
src/cs.rs
Normal file
411
src/cs.rs
Normal file
@ -0,0 +1,411 @@
|
||||
use pairing::{Engine};
|
||||
use pairing::ff::Field;
|
||||
|
||||
use std::ops::{Add, Sub};
|
||||
use std::fmt;
|
||||
use std::error::Error;
|
||||
use std::io;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
/// 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<E: Engine> {
|
||||
/// Synthesize the circuit into a rank-1 quadratic constraint system
|
||||
fn synthesize<CS: ConstraintSystem<E>>(
|
||||
self,
|
||||
cs: &mut CS
|
||||
) -> Result<(), SynthesisError>;
|
||||
}
|
||||
|
||||
/// Represents a variable in our constraint system.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Variable(pub(crate) 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<E: Engine>(pub(crate) Vec<(Variable, E::Fr)>);
|
||||
|
||||
impl<E: Engine> AsRef<[(Variable, E::Fr)]> for LinearCombination<E> {
|
||||
fn as_ref(&self) -> &[(Variable, E::Fr)] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> LinearCombination<E> {
|
||||
pub fn zero() -> LinearCombination<E> {
|
||||
LinearCombination(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> Add<(E::Fr, Variable)> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn add(mut self, (coeff, var): (E::Fr, Variable)) -> LinearCombination<E> {
|
||||
self.0.push((var, coeff));
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> Sub<(E::Fr, Variable)> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn sub(self, (mut coeff, var): (E::Fr, Variable)) -> LinearCombination<E> {
|
||||
coeff.negate();
|
||||
|
||||
self + (coeff, var)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> Add<Variable> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn add(self, other: Variable) -> LinearCombination<E> {
|
||||
self + (E::Fr::one(), other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> Sub<Variable> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn sub(self, other: Variable) -> LinearCombination<E> {
|
||||
self - (E::Fr::one(), other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Engine> Add<&'a LinearCombination<E>> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn add(mut self, other: &'a LinearCombination<E>) -> LinearCombination<E> {
|
||||
for s in &other.0 {
|
||||
self = self + (s.1, s.0);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Engine> Sub<&'a LinearCombination<E>> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn sub(mut self, other: &'a LinearCombination<E>) -> LinearCombination<E> {
|
||||
for s in &other.0 {
|
||||
self = self - (s.1, s.0);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Engine> Add<(E::Fr, &'a LinearCombination<E>)> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn add(mut self, (coeff, other): (E::Fr, &'a LinearCombination<E>)) -> LinearCombination<E> {
|
||||
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<E>)> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn sub(mut self, (coeff, other): (E::Fr, &'a LinearCombination<E>)) -> LinearCombination<E> {
|
||||
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<io::Error> 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<E: Engine>: Sized {
|
||||
/// Represents the type of the "root" of this constraint system
|
||||
/// so that nested namespaces can minimize indirection.
|
||||
type Root: ConstraintSystem<E>;
|
||||
|
||||
/// 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<F, A, AR>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
f: F
|
||||
) -> Result<Variable, SynthesisError>
|
||||
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>;
|
||||
|
||||
/// Allocate a public variable in the constraint system. The provided function is used to
|
||||
/// determine the assignment of the variable.
|
||||
fn alloc_input<F, A, AR>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
f: F
|
||||
) -> Result<Variable, SynthesisError>
|
||||
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>;
|
||||
|
||||
/// 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<A, AR, LA, LB, LC>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
a: LA,
|
||||
b: LB,
|
||||
c: LC
|
||||
)
|
||||
where A: FnOnce() -> AR, AR: Into<String>,
|
||||
LA: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
|
||||
LB: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
|
||||
LC: FnOnce(LinearCombination<E>) -> LinearCombination<E>;
|
||||
|
||||
/// Create a new (sub)namespace and enter into it. Not intended
|
||||
/// for downstream use; use `namespace` instead.
|
||||
fn push_namespace<NR, N>(&mut self, name_fn: N)
|
||||
where NR: Into<String>, 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<String>, 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<E> + 'a>(&'a mut CS, PhantomData<E>);
|
||||
|
||||
impl<'cs, E: Engine, CS: ConstraintSystem<E>> ConstraintSystem<E> for Namespace<'cs, E, CS> {
|
||||
type Root = CS::Root;
|
||||
|
||||
fn one() -> Variable {
|
||||
CS::one()
|
||||
}
|
||||
|
||||
fn alloc<F, A, AR>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
f: F
|
||||
) -> Result<Variable, SynthesisError>
|
||||
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>
|
||||
{
|
||||
self.0.alloc(annotation, f)
|
||||
}
|
||||
|
||||
fn alloc_input<F, A, AR>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
f: F
|
||||
) -> Result<Variable, SynthesisError>
|
||||
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>
|
||||
{
|
||||
self.0.alloc_input(annotation, f)
|
||||
}
|
||||
|
||||
fn enforce<A, AR, LA, LB, LC>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
a: LA,
|
||||
b: LB,
|
||||
c: LC
|
||||
)
|
||||
where A: FnOnce() -> AR, AR: Into<String>,
|
||||
LA: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
|
||||
LB: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
|
||||
LC: FnOnce(LinearCombination<E>) -> LinearCombination<E>
|
||||
{
|
||||
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<NR, N>(&mut self, _: N)
|
||||
where NR: Into<String>, 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<E>> Drop for Namespace<'a, E, CS> {
|
||||
fn drop(&mut self) {
|
||||
self.get_root().pop_namespace()
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience implementation of ConstraintSystem<E> for mutable references to
|
||||
/// constraint systems.
|
||||
impl<'cs, E: Engine, CS: ConstraintSystem<E>> ConstraintSystem<E> for &'cs mut CS {
|
||||
type Root = CS::Root;
|
||||
|
||||
fn one() -> Variable {
|
||||
CS::one()
|
||||
}
|
||||
|
||||
fn alloc<F, A, AR>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
f: F
|
||||
) -> Result<Variable, SynthesisError>
|
||||
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>
|
||||
{
|
||||
(**self).alloc(annotation, f)
|
||||
}
|
||||
|
||||
fn alloc_input<F, A, AR>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
f: F
|
||||
) -> Result<Variable, SynthesisError>
|
||||
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>
|
||||
{
|
||||
(**self).alloc_input(annotation, f)
|
||||
}
|
||||
|
||||
fn enforce<A, AR, LA, LB, LC>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
a: LA,
|
||||
b: LB,
|
||||
c: LC
|
||||
)
|
||||
where A: FnOnce() -> AR, AR: Into<String>,
|
||||
LA: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
|
||||
LB: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
|
||||
LC: FnOnce(LinearCombination<E>) -> LinearCombination<E>
|
||||
{
|
||||
(**self).enforce(annotation, a, b, c)
|
||||
}
|
||||
|
||||
fn push_namespace<NR, N>(&mut self, name_fn: N)
|
||||
where NR: Into<String>, 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()
|
||||
}
|
||||
}
|
127
src/domain.rs
127
src/domain.rs
@ -15,7 +15,7 @@ use pairing::{
|
||||
CurveProjective
|
||||
};
|
||||
|
||||
use ff::{
|
||||
use pairing::ff::{
|
||||
Field,
|
||||
PrimeField
|
||||
};
|
||||
@ -24,13 +24,9 @@ use super::{
|
||||
SynthesisError
|
||||
};
|
||||
|
||||
|
||||
use super::multicore::Worker;
|
||||
use super::worker::Worker;
|
||||
pub use super::group::*;
|
||||
|
||||
#[cfg(not(feature = "singlecore"))]
|
||||
use super::parallel_fft::*;
|
||||
|
||||
pub struct EvaluationDomain<E: Engine, G: Group<E>> {
|
||||
coeffs: Vec<G>,
|
||||
exp: u32,
|
||||
@ -55,7 +51,7 @@ impl<E: Engine, G: Group<E>> EvaluationDomain<E, G> {
|
||||
|
||||
pub fn from_coeffs(mut coeffs: Vec<G>) -> Result<EvaluationDomain<E, G>, SynthesisError>
|
||||
{
|
||||
use ff::PrimeField;
|
||||
use pairing::ff::PrimeField;
|
||||
// Compute the size of our evaluation domain
|
||||
|
||||
let coeffs_len = coeffs.len();
|
||||
@ -105,7 +101,7 @@ impl<E: Engine, G: Group<E>> EvaluationDomain<E, G> {
|
||||
// this one does expect coefficients to be smaller than `num_roots_of_unity/2` as we expect multiplication
|
||||
pub fn from_coeffs_into_sized(mut coeffs: Vec<G>, size: usize) -> Result<EvaluationDomain<E, G>, SynthesisError>
|
||||
{
|
||||
use ff::PrimeField;
|
||||
use pairing::ff::PrimeField;
|
||||
// Compute the size of our evaluation domain
|
||||
|
||||
assert!(size >= coeffs.len());
|
||||
@ -264,6 +260,121 @@ impl<E: Engine, G: Group<E>> EvaluationDomain<E, G> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn best_fft<E: Engine, T: Group<E>>(a: &mut [T], worker: &Worker, omega: &E::Fr, log_n: u32)
|
||||
{
|
||||
let log_cpus = worker.log_num_cpus();
|
||||
|
||||
if log_n <= log_cpus {
|
||||
serial_fft(a, omega, log_n);
|
||||
} else {
|
||||
parallel_fft(a, worker, omega, log_n, log_cpus);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn serial_fft<E: Engine, T: Group<E>>(a: &mut [T], omega: &E::Fr, log_n: u32)
|
||||
{
|
||||
fn bitreverse(mut n: u32, l: u32) -> u32 {
|
||||
let mut r = 0;
|
||||
for _ in 0..l {
|
||||
r = (r << 1) | (n & 1);
|
||||
n >>= 1;
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
let n = a.len() as u32;
|
||||
assert_eq!(n, 1 << log_n);
|
||||
|
||||
for k in 0..n {
|
||||
let rk = bitreverse(k, log_n);
|
||||
if k < rk {
|
||||
a.swap(rk as usize, k as usize);
|
||||
}
|
||||
}
|
||||
|
||||
let mut m = 1;
|
||||
for _ in 0..log_n {
|
||||
let w_m = omega.pow(&[(n / (2*m)) as u64]);
|
||||
|
||||
let mut k = 0;
|
||||
while k < n {
|
||||
let mut w = E::Fr::one();
|
||||
for j in 0..m {
|
||||
let mut t = a[(k+j+m) as usize];
|
||||
t.group_mul_assign(&w);
|
||||
let mut tmp = a[(k+j) as usize];
|
||||
tmp.group_sub_assign(&t);
|
||||
a[(k+j+m) as usize] = tmp;
|
||||
a[(k+j) as usize].group_add_assign(&t);
|
||||
w.mul_assign(&w_m);
|
||||
}
|
||||
|
||||
k += 2*m;
|
||||
}
|
||||
|
||||
m *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parallel_fft<E: Engine, T: Group<E>>(
|
||||
a: &mut [T],
|
||||
worker: &Worker,
|
||||
omega: &E::Fr,
|
||||
log_n: u32,
|
||||
log_cpus: u32
|
||||
)
|
||||
{
|
||||
assert!(log_n >= log_cpus);
|
||||
|
||||
let num_cpus = 1 << log_cpus;
|
||||
let log_new_n = log_n - log_cpus;
|
||||
let mut tmp = vec![vec![T::group_zero(); 1 << log_new_n]; num_cpus];
|
||||
let new_omega = omega.pow(&[num_cpus as u64]);
|
||||
|
||||
worker.scope(0, |scope, _| {
|
||||
let a = &*a;
|
||||
|
||||
for (j, tmp) in tmp.iter_mut().enumerate() {
|
||||
scope.spawn(move |_| {
|
||||
// Shuffle into a sub-FFT
|
||||
let omega_j = omega.pow(&[j as u64]);
|
||||
let omega_step = omega.pow(&[(j as u64) << log_new_n]);
|
||||
|
||||
let mut elt = E::Fr::one();
|
||||
for i in 0..(1 << log_new_n) {
|
||||
for s in 0..num_cpus {
|
||||
let idx = (i + (s << log_new_n)) % (1 << log_n);
|
||||
let mut t = a[idx];
|
||||
t.group_mul_assign(&elt);
|
||||
tmp[i].group_add_assign(&t);
|
||||
elt.mul_assign(&omega_step);
|
||||
}
|
||||
elt.mul_assign(&omega_j);
|
||||
}
|
||||
|
||||
// Perform sub-FFT
|
||||
serial_fft(tmp, &new_omega, log_new_n);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: does this hurt or help?
|
||||
worker.scope(a.len(), |scope, chunk| {
|
||||
let tmp = &tmp;
|
||||
|
||||
for (idx, a) in a.chunks_mut(chunk).enumerate() {
|
||||
scope.spawn(move |_| {
|
||||
let mut idx = idx * chunk;
|
||||
let mask = (1 << log_cpus) - 1;
|
||||
for a in a {
|
||||
*a = tmp[idx & mask][idx >> log_cpus];
|
||||
idx += 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Test multiplying various (low degree) polynomials together and
|
||||
// comparing with naive evaluations.
|
||||
#[test]
|
||||
|
@ -11,7 +11,7 @@ use pairing::{
|
||||
CurveAffine
|
||||
};
|
||||
|
||||
use ff::{
|
||||
use pairing::ff::{
|
||||
PrimeField,
|
||||
Field
|
||||
};
|
||||
@ -21,7 +21,7 @@ use super::{
|
||||
VerifyingKey
|
||||
};
|
||||
|
||||
use ::{
|
||||
use crate::{
|
||||
SynthesisError,
|
||||
Circuit,
|
||||
ConstraintSystem,
|
||||
@ -30,12 +30,12 @@ use ::{
|
||||
Index
|
||||
};
|
||||
|
||||
use ::domain::{
|
||||
use crate::domain::{
|
||||
EvaluationDomain,
|
||||
Scalar
|
||||
};
|
||||
|
||||
use ::multicore::{
|
||||
use crate::worker::{
|
||||
Worker
|
||||
};
|
||||
|
||||
|
@ -4,11 +4,11 @@ use pairing::{
|
||||
EncodedPoint
|
||||
};
|
||||
|
||||
use ::{
|
||||
use crate::{
|
||||
SynthesisError
|
||||
};
|
||||
|
||||
use multiexp::SourceBuilder;
|
||||
use crate::source::SourceBuilder;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::sync::Arc;
|
||||
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};
|
||||
@ -474,7 +474,7 @@ impl<E: Engine> PartialEq for Parameters<E> {
|
||||
// use {Circuit, SynthesisError, ConstraintSystem};
|
||||
|
||||
// use rand::{Rand, thread_rng};
|
||||
// use ff::{Field};
|
||||
// use pairing::ff::{Field};
|
||||
// use pairing::bls12_381::{Bls12, Fr};
|
||||
|
||||
// #[test]
|
||||
|
@ -2,7 +2,7 @@ use pairing::{
|
||||
Engine
|
||||
};
|
||||
|
||||
use ff:: {
|
||||
use pairing::ff:: {
|
||||
Field,
|
||||
PrimeField,
|
||||
};
|
||||
@ -12,7 +12,7 @@ use super::super::tests::XORDemo;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use ::{
|
||||
use crate::{
|
||||
Circuit,
|
||||
ConstraintSystem,
|
||||
SynthesisError
|
||||
|
@ -11,7 +11,7 @@ use pairing::{
|
||||
CurveAffine
|
||||
};
|
||||
|
||||
use ff::{
|
||||
use pairing::ff::{
|
||||
PrimeField,
|
||||
Field
|
||||
};
|
||||
@ -21,7 +21,7 @@ use super::{
|
||||
VerifyingKey
|
||||
};
|
||||
|
||||
use ::{
|
||||
use crate::{
|
||||
SynthesisError,
|
||||
Circuit,
|
||||
ConstraintSystem,
|
||||
@ -30,12 +30,12 @@ use ::{
|
||||
Index
|
||||
};
|
||||
|
||||
use ::domain::{
|
||||
use crate::domain::{
|
||||
EvaluationDomain,
|
||||
Scalar
|
||||
};
|
||||
|
||||
use ::multicore::{
|
||||
use crate::worker::{
|
||||
Worker
|
||||
};
|
||||
|
||||
|
@ -4,11 +4,11 @@ use pairing::{
|
||||
EncodedPoint
|
||||
};
|
||||
|
||||
use ::{
|
||||
use crate::{
|
||||
SynthesisError
|
||||
};
|
||||
|
||||
use multiexp::SourceBuilder;
|
||||
use crate::source::SourceBuilder;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::sync::Arc;
|
||||
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};
|
||||
@ -484,10 +484,10 @@ impl<'a, E: Engine> ParameterSource<E> for &'a Parameters<E> {
|
||||
#[cfg(test)]
|
||||
mod test_with_bls12_381 {
|
||||
use super::*;
|
||||
use {Circuit, SynthesisError, ConstraintSystem};
|
||||
use crate::{Circuit, SynthesisError, ConstraintSystem};
|
||||
|
||||
use rand::{Rand, thread_rng};
|
||||
use ff::{Field};
|
||||
use pairing::ff::{Field};
|
||||
use pairing::bls12_381::{Bls12, Fr};
|
||||
|
||||
#[test]
|
||||
|
@ -12,7 +12,7 @@ use pairing::{
|
||||
CurveAffine
|
||||
};
|
||||
|
||||
use ff::{
|
||||
use pairing::ff::{
|
||||
PrimeField,
|
||||
Field
|
||||
};
|
||||
@ -22,7 +22,7 @@ use super::{
|
||||
Proof
|
||||
};
|
||||
|
||||
use ::{
|
||||
use crate::{
|
||||
SynthesisError,
|
||||
Circuit,
|
||||
ConstraintSystem,
|
||||
@ -31,18 +31,19 @@ use ::{
|
||||
Index
|
||||
};
|
||||
|
||||
use ::domain::{
|
||||
use crate::domain::{
|
||||
EvaluationDomain,
|
||||
Scalar
|
||||
};
|
||||
|
||||
use ::multiexp::{
|
||||
use crate::source::{
|
||||
DensityTracker,
|
||||
FullDensity,
|
||||
multiexp
|
||||
FullDensity
|
||||
};
|
||||
|
||||
use ::multicore::{
|
||||
use crate::multiexp::*;
|
||||
|
||||
use crate::worker::{
|
||||
Worker
|
||||
};
|
||||
|
||||
|
@ -2,7 +2,7 @@ use pairing::{
|
||||
Engine
|
||||
};
|
||||
|
||||
use ff:: {
|
||||
use pairing::ff:: {
|
||||
Field,
|
||||
PrimeField,
|
||||
};
|
||||
@ -12,7 +12,7 @@ use super::super::tests::XORDemo;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use ::{
|
||||
use crate::{
|
||||
Circuit,
|
||||
ConstraintSystem,
|
||||
SynthesisError
|
||||
|
@ -4,7 +4,7 @@ use pairing::{
|
||||
CurveAffine
|
||||
};
|
||||
|
||||
use ff::{PrimeField};
|
||||
use pairing::ff::{PrimeField};
|
||||
|
||||
use super::{
|
||||
Proof,
|
||||
@ -12,7 +12,7 @@ use super::{
|
||||
PreparedVerifyingKey
|
||||
};
|
||||
|
||||
use ::{
|
||||
use crate::{
|
||||
SynthesisError
|
||||
};
|
||||
|
||||
|
@ -3,7 +3,7 @@ use pairing::{
|
||||
CurveProjective
|
||||
};
|
||||
|
||||
use ff::{
|
||||
use pairing::ff::{
|
||||
Field,
|
||||
PrimeField
|
||||
};
|
||||
|
447
src/lib.rs
447
src/lib.rs
@ -1,458 +1,45 @@
|
||||
#![allow(unused_imports)]
|
||||
|
||||
extern crate pairing;
|
||||
extern crate pairing as pairing_import;
|
||||
extern crate rand;
|
||||
extern crate bit_vec;
|
||||
extern crate byteorder;
|
||||
extern crate ff;
|
||||
|
||||
#[cfg(not(feature = "singlecore"))]
|
||||
extern crate num_cpus;
|
||||
extern crate futures;
|
||||
extern crate futures_cpupool;
|
||||
extern crate crossbeam;
|
||||
|
||||
pub mod domain;
|
||||
pub mod groth16;
|
||||
|
||||
#[cfg(feature = "gm17")]
|
||||
pub mod gm17;
|
||||
#[cfg(feature = "sonic")]
|
||||
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;
|
||||
mod multiexp;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use pairing::{Engine};
|
||||
use ff::Field;
|
||||
#[cfg(feature = "multicore")]
|
||||
mod multicore;
|
||||
|
||||
use std::ops::{Add, Sub};
|
||||
use std::fmt;
|
||||
use std::error::Error;
|
||||
use std::io;
|
||||
use std::marker::PhantomData;
|
||||
#[cfg(feature = "singlecore")]
|
||||
mod singlecore;
|
||||
|
||||
pub mod multiexp {
|
||||
pub use source::*;
|
||||
|
||||
#[cfg(not(feature = "singlecore"))]
|
||||
pub use parallel_multiexp::*;
|
||||
mod worker {
|
||||
#[cfg(feature = "multicore")]
|
||||
pub use crate::multicore::*;
|
||||
|
||||
#[cfg(feature = "singlecore")]
|
||||
pub use serial_multiexp::*;
|
||||
pub use crate::singlecore::*;
|
||||
}
|
||||
|
||||
/// 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<E: Engine> {
|
||||
/// Synthesize the circuit into a rank-1 quadratic constraint system
|
||||
fn synthesize<CS: ConstraintSystem<E>>(
|
||||
self,
|
||||
cs: &mut CS
|
||||
) -> Result<(), SynthesisError>;
|
||||
pub mod pairing {
|
||||
pub use pairing_import::*;
|
||||
}
|
||||
|
||||
/// 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<E: Engine>(Vec<(Variable, E::Fr)>);
|
||||
|
||||
impl<E: Engine> AsRef<[(Variable, E::Fr)]> for LinearCombination<E> {
|
||||
fn as_ref(&self) -> &[(Variable, E::Fr)] {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> LinearCombination<E> {
|
||||
pub fn zero() -> LinearCombination<E> {
|
||||
LinearCombination(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> Add<(E::Fr, Variable)> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn add(mut self, (coeff, var): (E::Fr, Variable)) -> LinearCombination<E> {
|
||||
self.0.push((var, coeff));
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> Sub<(E::Fr, Variable)> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn sub(self, (mut coeff, var): (E::Fr, Variable)) -> LinearCombination<E> {
|
||||
coeff.negate();
|
||||
|
||||
self + (coeff, var)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> Add<Variable> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn add(self, other: Variable) -> LinearCombination<E> {
|
||||
self + (E::Fr::one(), other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Engine> Sub<Variable> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn sub(self, other: Variable) -> LinearCombination<E> {
|
||||
self - (E::Fr::one(), other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Engine> Add<&'a LinearCombination<E>> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn add(mut self, other: &'a LinearCombination<E>) -> LinearCombination<E> {
|
||||
for s in &other.0 {
|
||||
self = self + (s.1, s.0);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Engine> Sub<&'a LinearCombination<E>> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn sub(mut self, other: &'a LinearCombination<E>) -> LinearCombination<E> {
|
||||
for s in &other.0 {
|
||||
self = self - (s.1, s.0);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Engine> Add<(E::Fr, &'a LinearCombination<E>)> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn add(mut self, (coeff, other): (E::Fr, &'a LinearCombination<E>)) -> LinearCombination<E> {
|
||||
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<E>)> for LinearCombination<E> {
|
||||
type Output = LinearCombination<E>;
|
||||
|
||||
fn sub(mut self, (coeff, other): (E::Fr, &'a LinearCombination<E>)) -> LinearCombination<E> {
|
||||
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<io::Error> 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<E: Engine>: Sized {
|
||||
/// Represents the type of the "root" of this constraint system
|
||||
/// so that nested namespaces can minimize indirection.
|
||||
type Root: ConstraintSystem<E>;
|
||||
|
||||
/// 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<F, A, AR>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
f: F
|
||||
) -> Result<Variable, SynthesisError>
|
||||
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>;
|
||||
|
||||
/// Allocate a public variable in the constraint system. The provided function is used to
|
||||
/// determine the assignment of the variable.
|
||||
fn alloc_input<F, A, AR>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
f: F
|
||||
) -> Result<Variable, SynthesisError>
|
||||
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>;
|
||||
|
||||
/// 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<A, AR, LA, LB, LC>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
a: LA,
|
||||
b: LB,
|
||||
c: LC
|
||||
)
|
||||
where A: FnOnce() -> AR, AR: Into<String>,
|
||||
LA: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
|
||||
LB: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
|
||||
LC: FnOnce(LinearCombination<E>) -> LinearCombination<E>;
|
||||
|
||||
/// Create a new (sub)namespace and enter into it. Not intended
|
||||
/// for downstream use; use `namespace` instead.
|
||||
fn push_namespace<NR, N>(&mut self, name_fn: N)
|
||||
where NR: Into<String>, 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<String>, 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<E> + 'a>(&'a mut CS, PhantomData<E>);
|
||||
|
||||
impl<'cs, E: Engine, CS: ConstraintSystem<E>> ConstraintSystem<E> for Namespace<'cs, E, CS> {
|
||||
type Root = CS::Root;
|
||||
|
||||
fn one() -> Variable {
|
||||
CS::one()
|
||||
}
|
||||
|
||||
fn alloc<F, A, AR>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
f: F
|
||||
) -> Result<Variable, SynthesisError>
|
||||
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>
|
||||
{
|
||||
self.0.alloc(annotation, f)
|
||||
}
|
||||
|
||||
fn alloc_input<F, A, AR>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
f: F
|
||||
) -> Result<Variable, SynthesisError>
|
||||
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>
|
||||
{
|
||||
self.0.alloc_input(annotation, f)
|
||||
}
|
||||
|
||||
fn enforce<A, AR, LA, LB, LC>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
a: LA,
|
||||
b: LB,
|
||||
c: LC
|
||||
)
|
||||
where A: FnOnce() -> AR, AR: Into<String>,
|
||||
LA: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
|
||||
LB: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
|
||||
LC: FnOnce(LinearCombination<E>) -> LinearCombination<E>
|
||||
{
|
||||
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<NR, N>(&mut self, _: N)
|
||||
where NR: Into<String>, 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<E>> Drop for Namespace<'a, E, CS> {
|
||||
fn drop(&mut self) {
|
||||
self.get_root().pop_namespace()
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience implementation of ConstraintSystem<E> for mutable references to
|
||||
/// constraint systems.
|
||||
impl<'cs, E: Engine, CS: ConstraintSystem<E>> ConstraintSystem<E> for &'cs mut CS {
|
||||
type Root = CS::Root;
|
||||
|
||||
fn one() -> Variable {
|
||||
CS::one()
|
||||
}
|
||||
|
||||
fn alloc<F, A, AR>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
f: F
|
||||
) -> Result<Variable, SynthesisError>
|
||||
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>
|
||||
{
|
||||
(**self).alloc(annotation, f)
|
||||
}
|
||||
|
||||
fn alloc_input<F, A, AR>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
f: F
|
||||
) -> Result<Variable, SynthesisError>
|
||||
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>
|
||||
{
|
||||
(**self).alloc_input(annotation, f)
|
||||
}
|
||||
|
||||
fn enforce<A, AR, LA, LB, LC>(
|
||||
&mut self,
|
||||
annotation: A,
|
||||
a: LA,
|
||||
b: LB,
|
||||
c: LC
|
||||
)
|
||||
where A: FnOnce() -> AR, AR: Into<String>,
|
||||
LA: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
|
||||
LB: FnOnce(LinearCombination<E>) -> LinearCombination<E>,
|
||||
LC: FnOnce(LinearCombination<E>) -> LinearCombination<E>
|
||||
{
|
||||
(**self).enforce(annotation, a, b, c)
|
||||
}
|
||||
|
||||
fn push_namespace<NR, N>(&mut self, name_fn: N)
|
||||
where NR: Into<String>, 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()
|
||||
}
|
||||
}
|
||||
mod cs;
|
||||
pub use self::cs::*;
|
||||
|
||||
static mut VERBOSE_SWITCH: i8 = -1;
|
||||
|
||||
|
@ -4,11 +4,14 @@
|
||||
//! crossbeam but may be extended in the future to
|
||||
//! allow for various parallelism strategies.
|
||||
|
||||
use num_cpus;
|
||||
use futures::{Future, IntoFuture, Poll};
|
||||
use futures_cpupool::{CpuPool, CpuFuture};
|
||||
use crossbeam::{self};
|
||||
use crossbeam::thread::{Scope};
|
||||
extern crate num_cpus;
|
||||
extern crate futures;
|
||||
extern crate futures_cpupool;
|
||||
extern crate crossbeam;
|
||||
|
||||
use self::futures::{Future, IntoFuture, Poll};
|
||||
use self::futures_cpupool::{CpuPool, CpuFuture};
|
||||
use self::crossbeam::thread::{Scope};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Worker {
|
||||
|
@ -4,7 +4,7 @@ use pairing::{
|
||||
Engine
|
||||
};
|
||||
|
||||
use ff::{
|
||||
use pairing::ff::{
|
||||
PrimeField,
|
||||
Field,
|
||||
PrimeFieldRepr,
|
||||
@ -13,7 +13,7 @@ use ff::{
|
||||
use std::sync::Arc;
|
||||
use super::source::*;
|
||||
use futures::{Future};
|
||||
use super::multicore::Worker;
|
||||
use super::worker::Worker;
|
||||
|
||||
use super::SynthesisError;
|
||||
|
||||
@ -212,19 +212,16 @@ fn dense_multiexp_inner<G: CurveAffine>(
|
||||
handle_trivial: bool
|
||||
) -> Result<<G as CurveAffine>::Projective, SynthesisError>
|
||||
{
|
||||
use crossbeam::channel::{unbounded, RecvError};
|
||||
// Perform this region of the multiexp. We use a different strategy - go over region in parallel,
|
||||
// then over another region, etc. No Arc required
|
||||
let this = {
|
||||
// let mask = (1u64 << c) - 1u64;
|
||||
let (s, r) = unbounded();
|
||||
// let this_region =
|
||||
let this_region =
|
||||
pool.scope(bases.len(), |scope, chunk| {
|
||||
// let mut handles = vec![];
|
||||
// let mut this_acc = <G as CurveAffine>::Projective::zero();
|
||||
let mut handles = vec![];
|
||||
let mut this_acc = <G as CurveAffine>::Projective::zero();
|
||||
for (base, exp) in bases.chunks(chunk).zip(exponents.chunks(chunk)) {
|
||||
let s = s.clone();
|
||||
// let handle =
|
||||
let handle =
|
||||
scope.spawn(move |_| {
|
||||
let mut buckets = vec![<G as CurveAffine>::Projective::zero(); (1 << c) - 1];
|
||||
// Accumulate the result
|
||||
@ -265,32 +262,32 @@ fn dense_multiexp_inner<G: CurveAffine>(
|
||||
}
|
||||
|
||||
// acc contains values over this region
|
||||
s.send(acc).expect("must send result");
|
||||
// s.send(acc).expect("must send result");
|
||||
|
||||
// acc
|
||||
acc
|
||||
});
|
||||
|
||||
// handles.push(handle);
|
||||
handles.push(handle);
|
||||
}
|
||||
|
||||
// // wait for all threads to finish
|
||||
// for r in handles.into_iter() {
|
||||
// let thread_result = r.join().unwrap();
|
||||
// this_acc.add_assign(&thread_result);
|
||||
// }
|
||||
// wait for all threads to finish
|
||||
for r in handles.into_iter() {
|
||||
let thread_result = r.join().unwrap();
|
||||
this_acc.add_assign(&thread_result);
|
||||
}
|
||||
|
||||
|
||||
// this_acc
|
||||
this_acc
|
||||
});
|
||||
|
||||
let mut this_region = <G as CurveAffine>::Projective::zero();
|
||||
loop {
|
||||
if r.is_empty() {
|
||||
break;
|
||||
}
|
||||
let value = r.recv().expect("must have value");
|
||||
this_region.add_assign(&value);
|
||||
}
|
||||
// let mut this_region = <G as CurveAffine>::Projective::zero();
|
||||
// loop {
|
||||
// if r.is_empty() {
|
||||
// break;
|
||||
// }
|
||||
// let value = r.recv().expect("must have value");
|
||||
// this_region.add_assign(&value);
|
||||
// }
|
||||
|
||||
this_region
|
||||
};
|
@ -1,143 +0,0 @@
|
||||
//! This module contains an `EvaluationDomain` abstraction for
|
||||
//! performing various kinds of polynomial arithmetic on top of
|
||||
//! the scalar field.
|
||||
//!
|
||||
//! In pairing-based SNARKs like Groth16, we need to calculate
|
||||
//! a quotient polynomial over a target polynomial with roots
|
||||
//! at distinct points associated with each constraint of the
|
||||
//! constraint system. In order to be efficient, we choose these
|
||||
//! roots to be the powers of a 2^n root of unity in the field.
|
||||
//! This allows us to perform polynomial operations in O(n)
|
||||
//! by performing an O(n log n) FFT over such a domain.
|
||||
|
||||
use pairing::{
|
||||
Engine,
|
||||
CurveProjective
|
||||
};
|
||||
|
||||
use ff::{
|
||||
Field,
|
||||
PrimeField
|
||||
};
|
||||
|
||||
use super::{
|
||||
SynthesisError
|
||||
};
|
||||
|
||||
use super::multicore::Worker;
|
||||
use super::group::*;
|
||||
|
||||
pub(crate) fn best_fft<E: Engine, T: Group<E>>(a: &mut [T], worker: &Worker, omega: &E::Fr, log_n: u32)
|
||||
{
|
||||
let log_cpus = worker.log_num_cpus();
|
||||
|
||||
if log_n <= log_cpus {
|
||||
serial_fft(a, omega, log_n);
|
||||
} else {
|
||||
parallel_fft(a, worker, omega, log_n, log_cpus);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn serial_fft<E: Engine, T: Group<E>>(a: &mut [T], omega: &E::Fr, log_n: u32)
|
||||
{
|
||||
fn bitreverse(mut n: u32, l: u32) -> u32 {
|
||||
let mut r = 0;
|
||||
for _ in 0..l {
|
||||
r = (r << 1) | (n & 1);
|
||||
n >>= 1;
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
let n = a.len() as u32;
|
||||
assert_eq!(n, 1 << log_n);
|
||||
|
||||
for k in 0..n {
|
||||
let rk = bitreverse(k, log_n);
|
||||
if k < rk {
|
||||
a.swap(rk as usize, k as usize);
|
||||
}
|
||||
}
|
||||
|
||||
let mut m = 1;
|
||||
for _ in 0..log_n {
|
||||
let w_m = omega.pow(&[(n / (2*m)) as u64]);
|
||||
|
||||
let mut k = 0;
|
||||
while k < n {
|
||||
let mut w = E::Fr::one();
|
||||
for j in 0..m {
|
||||
let mut t = a[(k+j+m) as usize];
|
||||
t.group_mul_assign(&w);
|
||||
let mut tmp = a[(k+j) as usize];
|
||||
tmp.group_sub_assign(&t);
|
||||
a[(k+j+m) as usize] = tmp;
|
||||
a[(k+j) as usize].group_add_assign(&t);
|
||||
w.mul_assign(&w_m);
|
||||
}
|
||||
|
||||
k += 2*m;
|
||||
}
|
||||
|
||||
m *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn parallel_fft<E: Engine, T: Group<E>>(
|
||||
a: &mut [T],
|
||||
worker: &Worker,
|
||||
omega: &E::Fr,
|
||||
log_n: u32,
|
||||
log_cpus: u32
|
||||
)
|
||||
{
|
||||
assert!(log_n >= log_cpus);
|
||||
|
||||
let num_cpus = 1 << log_cpus;
|
||||
let log_new_n = log_n - log_cpus;
|
||||
let mut tmp = vec![vec![T::group_zero(); 1 << log_new_n]; num_cpus];
|
||||
let new_omega = omega.pow(&[num_cpus as u64]);
|
||||
|
||||
worker.scope(0, |scope, _| {
|
||||
let a = &*a;
|
||||
|
||||
for (j, tmp) in tmp.iter_mut().enumerate() {
|
||||
scope.spawn(move |_| {
|
||||
// Shuffle into a sub-FFT
|
||||
let omega_j = omega.pow(&[j as u64]);
|
||||
let omega_step = omega.pow(&[(j as u64) << log_new_n]);
|
||||
|
||||
let mut elt = E::Fr::one();
|
||||
for i in 0..(1 << log_new_n) {
|
||||
for s in 0..num_cpus {
|
||||
let idx = (i + (s << log_new_n)) % (1 << log_n);
|
||||
let mut t = a[idx];
|
||||
t.group_mul_assign(&elt);
|
||||
tmp[i].group_add_assign(&t);
|
||||
elt.mul_assign(&omega_step);
|
||||
}
|
||||
elt.mul_assign(&omega_j);
|
||||
}
|
||||
|
||||
// Perform sub-FFT
|
||||
serial_fft(tmp, &new_omega, log_new_n);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: does this hurt or help?
|
||||
worker.scope(a.len(), |scope, chunk| {
|
||||
let tmp = &tmp;
|
||||
|
||||
for (idx, a) in a.chunks_mut(chunk).enumerate() {
|
||||
scope.spawn(move |_| {
|
||||
let mut idx = idx * chunk;
|
||||
let mask = (1 << log_cpus) - 1;
|
||||
for a in a {
|
||||
*a = tmp[idx & mask][idx >> log_cpus];
|
||||
idx += 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
94
src/singlecore.rs
Normal file
94
src/singlecore.rs
Normal file
@ -0,0 +1,94 @@
|
||||
//! This is a dummy interface to substitute multicore worker
|
||||
//! in environments like WASM
|
||||
extern crate futures;
|
||||
extern crate futures_cpupool;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use self::futures::{Future, IntoFuture, Poll};
|
||||
use self::futures_cpupool::{CpuFuture, CpuPool};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Worker {
|
||||
cpus: usize,
|
||||
pool: CpuPool
|
||||
}
|
||||
|
||||
impl Worker {
|
||||
// We don't expose this outside the library so that
|
||||
// all `Worker` instances have the same number of
|
||||
// CPUs configured.
|
||||
pub(crate) fn new_with_cpus(cpus: usize) -> Worker {
|
||||
Worker {
|
||||
cpus: 1,
|
||||
pool: CpuPool::new(1)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new() -> Worker {
|
||||
Self::new_with_cpus(1)
|
||||
}
|
||||
|
||||
pub fn log_num_cpus(&self) -> u32 {
|
||||
0u32
|
||||
}
|
||||
|
||||
pub fn compute<F, R>(
|
||||
&self, f: F
|
||||
) -> WorkerFuture<R::Item, R::Error>
|
||||
where F: FnOnce() -> R + Send + 'static,
|
||||
R: IntoFuture + 'static,
|
||||
R::Future: Send + 'static,
|
||||
R::Item: Send + 'static,
|
||||
R::Error: Send + 'static
|
||||
{
|
||||
WorkerFuture {
|
||||
future: self.pool.spawn_fn(f)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn scope<'a, F, R>(
|
||||
&self,
|
||||
elements: usize,
|
||||
f: F
|
||||
) -> R
|
||||
where F: FnOnce(&Scope<'a>, usize) -> R
|
||||
{
|
||||
let chunk_size = elements;
|
||||
|
||||
let scope = Scope{
|
||||
_marker: PhantomData
|
||||
};
|
||||
|
||||
f(&scope, chunk_size)
|
||||
}
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub struct Scope<'a> {
|
||||
_marker: PhantomData<& 'a usize>
|
||||
}
|
||||
|
||||
impl<'a> Scope<'a> {
|
||||
pub fn spawn<F, R>(
|
||||
&self,
|
||||
f: F
|
||||
) -> R
|
||||
where F: FnOnce(&Scope<'a>) -> R
|
||||
{
|
||||
f(&self)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WorkerFuture<T, E> {
|
||||
future: CpuFuture<T, E>
|
||||
}
|
||||
|
||||
impl<T: Send + 'static, E: Send + 'static> Future for WorkerFuture<T, E> {
|
||||
type Item = T;
|
||||
type Error = E;
|
||||
|
||||
fn poll(&mut self) -> Poll<Self::Item, Self::Error>
|
||||
{
|
||||
self.future.poll()
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use ff::{Field};
|
||||
use pairing::ff::{Field};
|
||||
use pairing::{Engine};
|
||||
use std::ops::{Add, Sub, Neg};
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
extern crate ff;
|
||||
extern crate pairing;
|
||||
|
||||
use ff::{Field};
|
||||
use pairing::ff::{Field};
|
||||
use pairing::{Engine};
|
||||
|
||||
use crate::{SynthesisError};
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ff::{Field};
|
||||
use pairing::ff::{Field};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ff::{Field};
|
||||
use pairing::ff::{Field};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@ -97,7 +97,7 @@ pub fn create_proof_on_srs<E: Engine, C: Circuit<E> + Clone>(
|
||||
|
||||
// #[test]
|
||||
// fn my_fun_circuit_test() {
|
||||
// use ff::PrimeField;
|
||||
// use pairing::ff::PrimeField;
|
||||
// use pairing::bls12_381::{Bls12, Fr};
|
||||
// use super::*;
|
||||
// use crate::sonic::cs::{Basic, ConstraintSystem, LinearCombination};
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ff::{Field};
|
||||
use pairing::ff::{Field};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@ -53,7 +53,7 @@ pub fn verify_aggregate<E: Engine, C: Circuit<E> + Clone, R: Rng>(
|
||||
|
||||
// #[test]
|
||||
// fn my_fun_circuit_test() {
|
||||
// use ff::PrimeField;
|
||||
// use pairing::ff::PrimeField;
|
||||
// use pairing::bls12_381::{Bls12, Fr};
|
||||
// use super::*;
|
||||
// use crate::sonic::cs::{Basic, ConstraintSystem, LinearCombination};
|
||||
|
@ -8,7 +8,7 @@
|
||||
//! This submodule contains the `Batch` abstraction for creating a
|
||||
//! context for batch verification.
|
||||
|
||||
use ff::{Field};
|
||||
use pairing::ff::{Field};
|
||||
use pairing::{Engine, CurveAffine, CurveProjective};
|
||||
|
||||
use crate::SynthesisError;
|
||||
|
@ -9,7 +9,7 @@ use pairing::{
|
||||
CurveAffine
|
||||
};
|
||||
|
||||
use ff::{
|
||||
use pairing::ff::{
|
||||
PrimeField,
|
||||
Field
|
||||
};
|
||||
@ -19,7 +19,7 @@ use super::{
|
||||
VerifyingKey
|
||||
};
|
||||
|
||||
use ::{
|
||||
use crate::{
|
||||
SynthesisError,
|
||||
Circuit,
|
||||
ConstraintSystem,
|
||||
@ -32,7 +32,7 @@ use crate::domain::{
|
||||
Scalar
|
||||
};
|
||||
|
||||
use ::multicore::{
|
||||
use crate::multicore::{
|
||||
Worker
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ff::{Field};
|
||||
use pairing::ff::{Field};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
extern crate ff;
|
||||
extern crate pairing;
|
||||
|
||||
use ff::{Field};
|
||||
use pairing::ff::{Field};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ff::{
|
||||
use pairing::ff::{
|
||||
Field,
|
||||
PrimeField,
|
||||
PrimeFieldRepr
|
||||
@ -10,11 +10,11 @@ use pairing::{
|
||||
EncodedPoint
|
||||
};
|
||||
|
||||
use ::{
|
||||
use crate::{
|
||||
SynthesisError
|
||||
};
|
||||
|
||||
use multiexp::SourceBuilder;
|
||||
use crate::source::SourceBuilder;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::sync::Arc;
|
||||
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};
|
||||
@ -64,7 +64,7 @@ impl<E: Engine> Proof<E> {
|
||||
mut writer: W
|
||||
) -> io::Result<()>
|
||||
{
|
||||
use ff::{PrimeField, PrimeFieldRepr};
|
||||
use pairing::ff::{PrimeField, PrimeFieldRepr};
|
||||
writer.write_all(self.r.into_compressed().as_ref())?;
|
||||
writer.write_all(self.t.into_compressed().as_ref())?;
|
||||
let mut buffer = vec![];
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ff::{Field};
|
||||
use pairing::ff::{Field};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ff::{Field};
|
||||
use pairing::ff::{Field};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
@ -397,7 +397,7 @@ pub fn create_proof_on_srs<E: Engine, C: Circuit<E>, S: SynthesisDriver>(
|
||||
|
||||
#[test]
|
||||
fn my_fun_circuit_test() {
|
||||
use ff::PrimeField;
|
||||
use pairing::ff::PrimeField;
|
||||
use pairing::bls12_381::{Bls12, Fr};
|
||||
use super::*;
|
||||
use crate::sonic::cs::{Basic, ConstraintSystem, LinearCombination};
|
||||
@ -449,8 +449,8 @@ fn my_fun_circuit_test() {
|
||||
|
||||
#[test]
|
||||
fn polynomial_commitment_test() {
|
||||
use ff::PrimeField;
|
||||
use ff::PrimeFieldRepr;
|
||||
use pairing::ff::PrimeField;
|
||||
use pairing::ff::PrimeFieldRepr;
|
||||
use pairing::bls12_381::{Bls12, Fr};
|
||||
use super::*;
|
||||
use crate::sonic::cs::{Basic, ConstraintSystem, LinearCombination};
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ff::{Field};
|
||||
use pairing::ff::{Field};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
use std::marker::PhantomData;
|
||||
use rand::{Rand, Rng};
|
||||
|
@ -1,4 +1,3 @@
|
||||
extern crate ff;
|
||||
extern crate pairing;
|
||||
|
||||
pub use crate::{SynthesisError};
|
||||
|
@ -1,8 +1,7 @@
|
||||
extern crate ff;
|
||||
extern crate pairing;
|
||||
extern crate rand;
|
||||
|
||||
use ff::{Field, PrimeField};
|
||||
use pairing::ff::{Field, PrimeField};
|
||||
use pairing::{Engine, CurveProjective};
|
||||
|
||||
// this one is for all external interfaces
|
||||
|
@ -1,4 +1,3 @@
|
||||
extern crate ff;
|
||||
extern crate pairing;
|
||||
|
||||
mod adaptor;
|
||||
|
@ -1,4 +1,3 @@
|
||||
extern crate ff;
|
||||
extern crate pairing;
|
||||
|
||||
mod srs;
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ff::{Field, PrimeField};
|
||||
use pairing::ff::{Field, PrimeField};
|
||||
use pairing::{CurveAffine, CurveProjective, Engine, Wnaf};
|
||||
|
||||
use std::io::{self, Read, Write};
|
||||
|
@ -1,7 +1,6 @@
|
||||
extern crate ff;
|
||||
extern crate pairing;
|
||||
|
||||
use ff::{Field, PrimeField, PrimeFieldRepr};
|
||||
use pairing::ff::{Field, PrimeField, PrimeFieldRepr};
|
||||
use pairing::{CurveAffine, CurveProjective, Engine};
|
||||
use std::io;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
/// in those two polynomials are equal (part of the permutation argument) with additional assumption that
|
||||
/// those coefficients are never equal to zero
|
||||
|
||||
use ff::{Field, PrimeField, PrimeFieldRepr};
|
||||
use pairing::ff::{Field, PrimeField, PrimeFieldRepr};
|
||||
use pairing::{Engine, CurveProjective, CurveAffine};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
/// actually a commitment to a vector of values that are equal to `(s^{perm})_i * y^{perm(i)}`
|
||||
/// for some fixed permutation `perm`
|
||||
|
||||
use ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine};
|
||||
use pairing::ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine};
|
||||
use pairing::{Engine, CurveProjective, CurveAffine};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
use ff::{Field, PrimeField, PrimeFieldRepr};
|
||||
use pairing::ff::{Field, PrimeField, PrimeFieldRepr};
|
||||
use pairing::{Engine, CurveProjective, CurveAffine};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/// Wellformedness argument allows to verify that some committment was to multivariate polynomial of degree n,
|
||||
/// with no constant term and negative powers
|
||||
|
||||
use ff::{Field, PrimeField, PrimeFieldRepr};
|
||||
use pairing::ff::{Field, PrimeField, PrimeFieldRepr};
|
||||
use pairing::{Engine, CurveProjective, CurveAffine};
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::SynthesisError;
|
||||
use ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine};
|
||||
use pairing::ff::{Field, PrimeField, PrimeFieldRepr, ScalarEngine};
|
||||
use pairing::{CurveAffine, CurveProjective, Engine};
|
||||
use super::srs::SRS;
|
||||
|
||||
@ -437,7 +437,7 @@ pub fn check_polynomial_commitment<E: Engine>(
|
||||
|
||||
#[test]
|
||||
fn laurent_division() {
|
||||
use ff::PrimeField;
|
||||
use pairing::ff::PrimeField;
|
||||
use pairing::bls12_381::{Fr};
|
||||
|
||||
let mut poly = vec![
|
||||
|
@ -4,7 +4,7 @@ use pairing::{
|
||||
Engine
|
||||
};
|
||||
|
||||
use ff::{
|
||||
use pairing::ff::{
|
||||
PrimeField,
|
||||
Field,
|
||||
PrimeFieldRepr,
|
||||
|
@ -6,7 +6,7 @@ use pairing::{
|
||||
EncodedPoint
|
||||
};
|
||||
|
||||
use ff::{
|
||||
use pairing::ff::{
|
||||
PrimeField,
|
||||
PrimeFieldRepr,
|
||||
Field,
|
||||
|
@ -2,7 +2,7 @@ use pairing::{
|
||||
Engine
|
||||
};
|
||||
|
||||
use ff:: {
|
||||
use pairing::ff:: {
|
||||
Field,
|
||||
PrimeField,
|
||||
};
|
||||
@ -12,7 +12,7 @@ use self::dummy_engine::*;
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use ::{
|
||||
use crate::{
|
||||
Circuit,
|
||||
ConstraintSystem,
|
||||
SynthesisError
|
||||
|
@ -1,7 +1,6 @@
|
||||
extern crate bellman;
|
||||
extern crate pairing;
|
||||
extern crate rand;
|
||||
extern crate ff;
|
||||
|
||||
// For randomness (during paramgen and proof generation)
|
||||
use rand::{thread_rng, Rng};
|
||||
@ -14,7 +13,7 @@ use pairing::{
|
||||
Engine
|
||||
};
|
||||
|
||||
use ff::{
|
||||
use pairing::ff::{
|
||||
Field,
|
||||
};
|
||||
|
||||
@ -442,7 +441,7 @@ impl<'a, E: Engine> Circuit<E> for MiMCDemoNoInputs<'a, E> {
|
||||
|
||||
#[test]
|
||||
fn test_sonic_mimc() {
|
||||
use ff::{Field, PrimeField};
|
||||
use pairing::ff::{Field, PrimeField};
|
||||
use pairing::{Engine, CurveAffine, CurveProjective};
|
||||
use pairing::bls12_381::{Bls12, Fr};
|
||||
use std::time::{Instant};
|
||||
@ -546,7 +545,7 @@ fn test_sonic_mimc() {
|
||||
|
||||
#[test]
|
||||
fn test_inputs_into_sonic_mimc() {
|
||||
use ff::{Field, PrimeField};
|
||||
use pairing::ff::{Field, PrimeField};
|
||||
use pairing::{Engine, CurveAffine, CurveProjective};
|
||||
use pairing::bn256::{Bn256, Fr};
|
||||
// use pairing::bls12_381::{Bls12, Fr};
|
||||
|
Loading…
Reference in New Issue
Block a user