Infrastructure for public input namespacing.

This commit is contained in:
Sean Bowe 2017-11-21 13:44:56 -07:00
parent b7f2f9e409
commit af91dcda33
1 changed files with 68 additions and 4 deletions

View File

@ -142,7 +142,12 @@ pub trait ConstraintSystem<E: Engine>: Sized {
}
}
pub trait PublicConstraintSystem<E: Engine>: ConstraintSystem<E> {
pub trait PublicConstraintSystem<E: Engine>: ConstraintSystem<E>
{
/// Represents the type of the "root" of this constraint system
/// so that nested namespaces can minimize indirection.
type PublicRoot: PublicConstraintSystem<E>;
/// 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>(
@ -151,6 +156,22 @@ pub trait PublicConstraintSystem<E: Engine>: ConstraintSystem<E> {
f: F
) -> Result<Self::Variable, SynthesisError>
where F: FnOnce() -> Result<E::Fr, SynthesisError>, A: FnOnce() -> AR, AR: Into<String>;
/// Gets the "root" constraint system, bypassing the namespacing.
/// Not intended for downstream use; use `namespace` instead.
fn get_public_root(&mut self) -> &mut Self::PublicRoot;
/// Begin a namespace for this constraint system.
fn public_namespace<'a, NR, N>(
&'a mut self,
name_fn: N
) -> Namespace<'a, E, Self::PublicRoot>
where NR: Into<String>, N: FnOnce() -> NR
{
self.get_root().push_namespace(name_fn);
Namespace(self.get_public_root(), PhantomData)
}
}
use std::marker::PhantomData;
@ -160,6 +181,8 @@ use std::marker::PhantomData;
pub struct Namespace<'a, E: Engine, CS: ConstraintSystem<E> + 'a>(&'a mut CS, PhantomData<E>);
impl<'cs, E: Engine, CS: PublicConstraintSystem<E>> PublicConstraintSystem<E> for Namespace<'cs, E, CS> {
type PublicRoot = CS::PublicRoot;
fn alloc_input<F, A, AR>(
&mut self,
annotation: A,
@ -169,6 +192,11 @@ impl<'cs, E: Engine, CS: PublicConstraintSystem<E>> PublicConstraintSystem<E> fo
{
self.0.alloc_input(annotation, f)
}
fn get_public_root(&mut self) -> &mut Self::PublicRoot
{
self.0.get_public_root()
}
}
impl<'cs, E: Engine, CS: ConstraintSystem<E>> ConstraintSystem<E> for Namespace<'cs, E, CS> {
@ -201,15 +229,19 @@ impl<'cs, E: Engine, CS: ConstraintSystem<E>> ConstraintSystem<E> for Namespace<
self.0.enforce(annotation, a, b, c)
}
fn push_namespace<NR, N>(&mut self, name_fn: N)
// 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
{
self.0.push_namespace(name_fn)
panic!("only the root's push_namespace should be called");
}
fn pop_namespace(&mut self)
{
self.0.pop_namespace()
panic!("only the root's pop_namespace should be called");
}
fn get_root(&mut self) -> &mut Self::Root
@ -227,6 +259,8 @@ impl<'a, E: Engine, CS: ConstraintSystem<E>> Drop for Namespace<'a, E, CS> {
/// Convenience implementation of PublicConstraintSystem<E> for mutable references to
/// public constraint systems.
impl<'cs, E: Engine, CS: PublicConstraintSystem<E>> PublicConstraintSystem<E> for &'cs mut CS {
type PublicRoot = CS::PublicRoot;
fn alloc_input<F, A, AR>(
&mut self,
annotation: A,
@ -236,6 +270,11 @@ impl<'cs, E: Engine, CS: PublicConstraintSystem<E>> PublicConstraintSystem<E> fo
{
(**self).alloc_input(annotation, f)
}
fn get_public_root(&mut self) -> &mut Self::PublicRoot
{
(**self).get_public_root()
}
}
/// Convenience implementation of ConstraintSystem<E> for mutable references to
@ -322,6 +361,8 @@ fn test_cs() {
}
impl<E: Engine> PublicConstraintSystem<E> for MySillyConstraintSystem<E> {
type PublicRoot = Self;
fn alloc_input<F, A, AR>(
&mut self,
annotation: A,
@ -335,6 +376,11 @@ fn test_cs() {
Ok(Var::Input(index))
}
fn get_public_root(&mut self) -> &mut Self::PublicRoot
{
self
}
}
impl<E: Engine> ConstraintSystem<E> for MySillyConstraintSystem<E> {
@ -390,6 +436,15 @@ fn test_cs() {
}
}
fn do_stuff_with_pcs<E: Engine, CS: PublicConstraintSystem<E>>(mut cs: CS, one_more: bool)
{
cs.alloc_input(|| "something", || Ok(E::Fr::zero())).unwrap();
if one_more {
do_stuff_with_pcs(cs.public_namespace(|| "cool namespace"), false);
}
}
let mut cs = MySillyConstraintSystem::<Bls12> {
inputs: vec![(Fr::one(), "ONE".into())],
aux: vec![],
@ -438,4 +493,13 @@ fn test_cs() {
assert!((cs.constraints[0].1).0 == vec![(Var::Input(0), Fr::one())]);
assert!((cs.constraints[0].2).0 == vec![(Var::Input(1), Fr::one())]);
assert!(cs.constraints[0].3 == "woohoo/hehe/great constraint");
do_stuff_with_pcs(cs.namespace(|| "namey"), true);
assert_eq!(cs.inputs, vec![
(Fr::one(), "ONE".into()),
(Fr::zero(), "woohoo/hehe/works lol".into()),
(Fr::zero(), "namey/something".into()),
(Fr::zero(), "namey/cool namespace/something".into()),
]);
}