From 945d86fe7db0855281ff2a161bc4d25c3ab79b48 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Mon, 20 Nov 2017 15:50:41 -0700 Subject: [PATCH] Make the namespacing not introduce too much indirection. --- src/groth16/generator.rs | 16 +++- src/groth16/prover.rs | 16 +++- src/groth16/verifier.rs | 32 +++++++- src/lib.rs | 163 ++++++++++++++++++++++++++++++++++----- 4 files changed, 203 insertions(+), 24 deletions(-) diff --git a/src/groth16/generator.rs b/src/groth16/generator.rs index 109bdfe..8f71fb5 100644 --- a/src/groth16/generator.rs +++ b/src/groth16/generator.rs @@ -7,8 +7,10 @@ use ::{ Circuit, Variable, ConstraintSystem, - PublicConstraintSystem + PublicConstraintSystem, + Namespace }; +use std::marker::PhantomData; use super::{VerifyingKey, Parameters}; use domain::{Scalar, EvaluationDomain}; use rand::Rng; @@ -91,6 +93,8 @@ pub fn generate_parameters( } impl ConstraintSystem for KeypairAssembly { + type Root = Self; + fn alloc( &mut self, _: N, @@ -140,6 +144,16 @@ pub fn generate_parameters( self.num_constraints += 1; } + + /// Begin a namespace for the constraint system + fn namespace<'a, NR, N>( + &'a mut self, + _: N + ) -> Namespace<'a, E, Self::Root> + where NR: Into, N: FnOnce() -> NR + { + Namespace(self, PhantomData) + } } let mut assembly = KeypairAssembly { diff --git a/src/groth16/prover.rs b/src/groth16/prover.rs index a86d679..93c26df 100644 --- a/src/groth16/prover.rs +++ b/src/groth16/prover.rs @@ -8,8 +8,10 @@ use ::{ Index, Error, Variable, - LinearCombination + LinearCombination, + Namespace }; +use std::marker::PhantomData; use multiexp::*; use super::{ParameterSource, Proof}; use rand::Rng; @@ -70,6 +72,8 @@ pub fn create_proof>( } impl ConstraintSystem for ProvingAssignment { + type Root = Self; + fn alloc( &mut self, _: N, @@ -96,6 +100,16 @@ pub fn create_proof>( self.b.push(Scalar(b.eval(Some(&mut self.b_input_density), Some(&mut self.b_aux_density), &self.input_assignment, &self.aux_assignment))); self.c.push(Scalar(c.eval(None, None, &self.input_assignment, &self.aux_assignment))); } + + /// Begin a namespace for the constraint system + fn namespace<'a, NR, N>( + &'a mut self, + _: N + ) -> Namespace<'a, E, Self::Root> + where NR: Into, N: FnOnce() -> NR + { + Namespace(self, PhantomData) + } } let mut prover = ProvingAssignment { diff --git a/src/groth16/verifier.rs b/src/groth16/verifier.rs index 246e925..668fdb4 100644 --- a/src/groth16/verifier.rs +++ b/src/groth16/verifier.rs @@ -6,9 +6,11 @@ use ::{ Index, Variable, ConstraintSystem, - PublicConstraintSystem + PublicConstraintSystem, + Namespace }; use super::{Proof, VerifyingKey, PreparedVerifyingKey}; +use std::marker::PhantomData; /// This is the constraint system synthesizer that is made available to /// callers of the verification function when they wish to perform @@ -21,7 +23,9 @@ pub struct VerifierInput<'a, E: Engine> { num_aux: usize } -impl<'a, E: Engine> ConstraintSystem for VerifierInput<'a, E> { +impl<'cs, E: Engine> ConstraintSystem for VerifierInput<'cs, E> { + type Root = Self; + fn alloc( &mut self, _: N, @@ -51,13 +55,25 @@ impl<'a, E: Engine> ConstraintSystem for VerifierInput<'a, E> { // Do nothing; we don't care about the constraint system // in this context. } + + /// Begin a namespace for the constraint system + fn namespace<'a, NR, N>( + &'a mut self, + _: N + ) -> Namespace<'a, E, Self::Root> + where NR: Into, N: FnOnce() -> NR + { + Namespace(self, PhantomData) + } } /// This is intended to be a wrapper around VerifierInput that is kept /// private and used for input allocation. struct InputAllocator(T); -impl<'a, 'b, E: Engine> ConstraintSystem for InputAllocator<&'a mut VerifierInput<'b, E>> { +impl<'cs, 'b, E: Engine> ConstraintSystem for InputAllocator<&'cs mut VerifierInput<'b, E>> { + type Root = Self; + fn alloc( &mut self, name_fn: N, @@ -79,6 +95,16 @@ impl<'a, 'b, E: Engine> ConstraintSystem for InputAllocator<&'a mut VerifierI // Do nothing; we don't care about the constraint system // in this context. } + + /// Begin a namespace for the constraint system + fn namespace<'a, NR, N>( + &'a mut self, + _: N + ) -> Namespace<'a, E, Self::Root> + where NR: Into, N: FnOnce() -> NR + { + Namespace(self, PhantomData) + } } impl<'a, 'b, E: Engine> PublicConstraintSystem for InputAllocator<&'a mut VerifierInput<'b, E>> { diff --git a/src/lib.rs b/src/lib.rs index 0b0de51..bf78edf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -190,7 +190,9 @@ pub trait PublicConstraintSystem: ConstraintSystem { where NR: Into, N: FnOnce() -> NR, F: FnOnce() -> Result; } -pub trait ConstraintSystem { +pub trait ConstraintSystem: Sized { + type Root: ConstraintSystem; + /// Return the "one" input variable fn one() -> Variable { Variable(Index::Input(0)) @@ -214,15 +216,129 @@ pub trait ConstraintSystem { c: LinearCombination ); - /// Begin a namespace for the constraint system - fn namespace( - &mut self, - _: N, - space_fn: F - ) -> Result - where NR: Into, N: FnOnce() -> NR, F: FnOnce(&mut Self) -> Result + fn push_namespace(&mut self, _: N) + where NR: Into, N: FnOnce() -> NR { - space_fn(self) + // Default is to do nothing. + } + + fn pop_namespace(&mut self) + { + // Default is to do nothing. + } + + /// Begin a namespace for the constraint system + fn namespace<'a, NR, N>( + &'a mut self, + name_fn: N + ) -> Namespace<'a, E, Self::Root> + where NR: Into, N: FnOnce() -> NR; +} + +impl<'cs, E: Engine, CS: ConstraintSystem> ConstraintSystem for &'cs mut CS { + type Root = CS::Root; + + /// Allocate a private variable in the constraint system. The provided function is used to + /// determine the assignment of the variable. + fn alloc( + &mut self, + name_fn: N, + f: F + ) -> Result + where NR: Into, N: FnOnce() -> NR, F: FnOnce() -> Result + { + (*self).alloc(name_fn, f) + } + + /// Enforce that `A` * `B` = `C`. + fn enforce, N: FnOnce() -> NR>( + &mut self, + name_fn: N, + a: LinearCombination, + b: LinearCombination, + c: LinearCombination + ) + { + (*self).enforce(name_fn, 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() + } + + /// Begin a namespace for the 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).namespace(name_fn) + } +} + +use std::marker::PhantomData; + +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; + + fn alloc( + &mut self, + name_fn: N, + f: F + ) -> Result + where NR: Into, N: FnOnce() -> NR, F: FnOnce() -> Result + { + self.0.alloc(name_fn, f) + } + + fn enforce, N: FnOnce() -> NR>( + &mut self, + name_fn: N, + a: LinearCombination, + b: LinearCombination, + c: LinearCombination + ) + { + self.0.enforce(name_fn, a, b, c) + } + + fn push_namespace(&mut self, name_fn: N) + where NR: Into, N: FnOnce() -> NR + { + self.0.push_namespace(name_fn); + } + + fn pop_namespace(&mut self) + { + self.0.pop_namespace(); + } + + /// Begin a namespace for the 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.0.push_namespace(name_fn); + + Namespace(self.0, PhantomData) + } +} + +impl<'a, E: Engine, CS: ConstraintSystem> Drop for Namespace<'a, E, CS> { + fn drop(&mut self) { + self.0.pop_namespace() } } @@ -353,6 +469,8 @@ impl PublicConstraintSystem for TestConstraintSystem { } impl ConstraintSystem for TestConstraintSystem { + type Root = Self; + fn alloc( &mut self, name_fn: N, @@ -386,24 +504,31 @@ impl ConstraintSystem for TestConstraintSystem { self.constraints.push((a, b, c, this_path)); } - fn namespace( - &mut self, - name_fn: N, - space_fn: F - ) -> Result - where NR: Into, N: FnOnce() -> NR, F: FnOnce(&mut Self) -> Result + fn push_namespace(&mut self, name_fn: N) + where NR: Into, N: FnOnce() -> NR { let name = name_fn().into(); - let this_path = compute_path(&self.current_namespace, name.clone()); + self.set_named_obj(this_path, NamedObject::Namespace); self.current_namespace.push(name); + } - let r = space_fn(self)?; - + fn pop_namespace(&mut self) + { self.current_namespace.pop(); + } - Ok(r) + /// Begin a namespace for the 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.push_namespace(name_fn); + + Namespace(self, PhantomData) } }